Home | History | Annotate | Line # | Download | only in Sema
      1 //===--- TypeLocBuilder.cpp - Type Source Info collector ------------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 //  This files defines TypeLocBuilder, a class for building TypeLocs
     10 //  bottom-up.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "TypeLocBuilder.h"
     15 
     16 using namespace clang;
     17 
     18 void TypeLocBuilder::pushFullCopy(TypeLoc L) {
     19   size_t Size = L.getFullDataSize();
     20   reserve(Size);
     21 
     22   SmallVector<TypeLoc, 4> TypeLocs;
     23   TypeLoc CurTL = L;
     24   while (CurTL) {
     25     TypeLocs.push_back(CurTL);
     26     CurTL = CurTL.getNextTypeLoc();
     27   }
     28 
     29   for (unsigned i = 0, e = TypeLocs.size(); i < e; ++i) {
     30     TypeLoc CurTL = TypeLocs[e-i-1];
     31     switch (CurTL.getTypeLocClass()) {
     32 #define ABSTRACT_TYPELOC(CLASS, PARENT)
     33 #define TYPELOC(CLASS, PARENT) \
     34     case TypeLoc::CLASS: { \
     35       CLASS##TypeLoc NewTL = push<class CLASS##TypeLoc>(CurTL.getType()); \
     36       memcpy(NewTL.getOpaqueData(), CurTL.getOpaqueData(), NewTL.getLocalDataSize()); \
     37       break; \
     38     }
     39 #include "clang/AST/TypeLocNodes.def"
     40     }
     41   }
     42 }
     43 
     44 void TypeLocBuilder::grow(size_t NewCapacity) {
     45   assert(NewCapacity > Capacity);
     46 
     47   // Allocate the new buffer and copy the old data into it.
     48   char *NewBuffer = new char[NewCapacity];
     49   unsigned NewIndex = Index + NewCapacity - Capacity;
     50   memcpy(&NewBuffer[NewIndex],
     51          &Buffer[Index],
     52          Capacity - Index);
     53 
     54   if (Buffer != InlineBuffer)
     55     delete[] Buffer;
     56 
     57   Buffer = NewBuffer;
     58   Capacity = NewCapacity;
     59   Index = NewIndex;
     60 }
     61 
     62 TypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) {
     63 #ifndef NDEBUG
     64   QualType TLast = TypeLoc(T, nullptr).getNextTypeLoc().getType();
     65   assert(TLast == LastTy &&
     66          "mismatch between last type and new type's inner type");
     67   LastTy = T;
     68 #endif
     69 
     70   assert(LocalAlignment <= BufferMaxAlignment && "Unexpected alignment");
     71 
     72   // If we need to grow, grow by a factor of 2.
     73   if (LocalSize > Index) {
     74     size_t RequiredCapacity = Capacity + (LocalSize - Index);
     75     size_t NewCapacity = Capacity * 2;
     76     while (RequiredCapacity > NewCapacity)
     77       NewCapacity *= 2;
     78     grow(NewCapacity);
     79   }
     80 
     81   // Because we're adding elements to the TypeLoc backwards, we have to
     82   // do some extra work to keep everything aligned appropriately.
     83   // FIXME: This algorithm is a absolute mess because every TypeLoc returned
     84   // needs to be valid.  Partial TypeLocs are a terrible idea.
     85   // FIXME: 4 and 8 are sufficient at the moment, but it's pretty ugly to
     86   // hardcode them.
     87   if (LocalAlignment == 4) {
     88     if (NumBytesAtAlign8 == 0) {
     89       NumBytesAtAlign4 += LocalSize;
     90     } else {
     91       unsigned Padding = NumBytesAtAlign4 % 8;
     92       if (Padding == 0) {
     93         if (LocalSize % 8 == 0) {
     94           // Everything is set: there's no padding and we don't need to add
     95           // any.
     96         } else {
     97           assert(LocalSize % 8 == 4);
     98           // No existing padding; add in 4 bytes padding
     99           memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
    100           Index -= 4;
    101         }
    102       } else {
    103         assert(Padding == 4);
    104         if (LocalSize % 8 == 0) {
    105           // Everything is set: there's 4 bytes padding and we don't need
    106           // to add any.
    107         } else {
    108           assert(LocalSize % 8 == 4);
    109           // There are 4 bytes padding, but we don't need any; remove it.
    110           memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);
    111           Index += 4;
    112         }
    113       }
    114       NumBytesAtAlign4 += LocalSize;
    115     }
    116   } else if (LocalAlignment == 8) {
    117     if (NumBytesAtAlign8 == 0) {
    118       // We have not seen any 8-byte aligned element yet. We insert a padding
    119       // only if the new Index is not 8-byte-aligned.
    120       if ((Index - LocalSize) % 8 != 0) {
    121         memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
    122         Index -= 4;
    123       }
    124     } else {
    125       unsigned Padding = NumBytesAtAlign4 % 8;
    126       if (Padding == 0) {
    127         if (LocalSize % 8 == 0) {
    128           // Everything is set: there's no padding and we don't need to add
    129           // any.
    130         } else {
    131           assert(LocalSize % 8 == 4);
    132           // No existing padding; add in 4 bytes padding
    133           memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
    134           Index -= 4;
    135         }
    136       } else {
    137         assert(Padding == 4);
    138         if (LocalSize % 8 == 0) {
    139           // Everything is set: there's 4 bytes padding and we don't need
    140           // to add any.
    141         } else {
    142           assert(LocalSize % 8 == 4);
    143           // There are 4 bytes padding, but we don't need any; remove it.
    144           memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);
    145           Index += 4;
    146         }
    147       }
    148     }
    149 
    150     // Forget about any padding.
    151     NumBytesAtAlign4 = 0;
    152     NumBytesAtAlign8 += LocalSize;
    153   } else {
    154     assert(LocalSize == 0);
    155   }
    156 
    157   Index -= LocalSize;
    158 
    159   assert(Capacity - Index == TypeLoc::getFullDataSizeForType(T) &&
    160          "incorrect data size provided to CreateTypeSourceInfo!");
    161 
    162   return getTemporaryTypeLoc(T);
    163 }
    164