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