clang API Documentation

TypeLocBuilder.cpp
Go to the documentation of this file.
00001 //===--- TypeLocBuilder.cpp - Type Source Info collector ------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This files defines TypeLocBuilder, a class for building TypeLocs
00011 //  bottom-up.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "TypeLocBuilder.h"
00016 
00017 using namespace clang;
00018 
00019 void TypeLocBuilder::pushFullCopy(TypeLoc L) {
00020   size_t Size = L.getFullDataSize();
00021   reserve(Size);
00022 
00023   SmallVector<TypeLoc, 4> TypeLocs;
00024   TypeLoc CurTL = L;
00025   while (CurTL) {
00026     TypeLocs.push_back(CurTL);
00027     CurTL = CurTL.getNextTypeLoc();
00028   }
00029 
00030   for (unsigned i = 0, e = TypeLocs.size(); i < e; ++i) {
00031     TypeLoc CurTL = TypeLocs[e-i-1];
00032     switch (CurTL.getTypeLocClass()) {
00033 #define ABSTRACT_TYPELOC(CLASS, PARENT)
00034 #define TYPELOC(CLASS, PARENT) \
00035     case TypeLoc::CLASS: { \
00036       CLASS##TypeLoc NewTL = push<class CLASS##TypeLoc>(CurTL.getType()); \
00037       memcpy(NewTL.getOpaqueData(), CurTL.getOpaqueData(), NewTL.getLocalDataSize()); \
00038       break; \
00039     }
00040 #include "clang/AST/TypeLocNodes.def"
00041     }
00042   }
00043 }
00044 
00045 void TypeLocBuilder::grow(size_t NewCapacity) {
00046   assert(NewCapacity > Capacity);
00047 
00048   // Allocate the new buffer and copy the old data into it.
00049   char *NewBuffer = new char[NewCapacity];
00050   unsigned NewIndex = Index + NewCapacity - Capacity;
00051   memcpy(&NewBuffer[NewIndex],
00052          &Buffer[Index],
00053          Capacity - Index);
00054 
00055   if (Buffer != InlineBuffer.buffer)
00056     delete[] Buffer;
00057 
00058   Buffer = NewBuffer;
00059   Capacity = NewCapacity;
00060   Index = NewIndex;
00061 }
00062 
00063 TypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) {
00064 #ifndef NDEBUG
00065   QualType TLast = TypeLoc(T, nullptr).getNextTypeLoc().getType();
00066   assert(TLast == LastTy &&
00067          "mismatch between last type and new type's inner type");
00068   LastTy = T;
00069 #endif
00070 
00071   assert(LocalAlignment <= BufferMaxAlignment && "Unexpected alignment");
00072 
00073   // If we need to grow, grow by a factor of 2.
00074   if (LocalSize > Index) {
00075     size_t RequiredCapacity = Capacity + (LocalSize - Index);
00076     size_t NewCapacity = Capacity * 2;
00077     while (RequiredCapacity > NewCapacity)
00078       NewCapacity *= 2;
00079     grow(NewCapacity);
00080   }
00081 
00082   // Because we're adding elements to the TypeLoc backwards, we have to
00083   // do some extra work to keep everything aligned appropriately.
00084   // FIXME: This algorithm is a absolute mess because every TypeLoc returned
00085   // needs to be valid.  Partial TypeLocs are a terrible idea.
00086   // FIXME: 4 and 8 are sufficient at the moment, but it's pretty ugly to
00087   // hardcode them.
00088   if (LocalAlignment == 4) {
00089     if (NumBytesAtAlign8 == 0) {
00090       NumBytesAtAlign4 += LocalSize;
00091     } else {
00092       unsigned Padding = NumBytesAtAlign4 % 8;
00093       if (Padding == 0) {
00094         if (LocalSize % 8 == 0) {
00095           // Everything is set: there's no padding and we don't need to add
00096           // any.
00097         } else {
00098           assert(LocalSize % 8 == 4);
00099           // No existing padding; add in 4 bytes padding
00100           memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
00101           Index -= 4;
00102         }
00103       } else {
00104         assert(Padding == 4);
00105         if (LocalSize % 8 == 0) {
00106           // Everything is set: there's 4 bytes padding and we don't need
00107           // to add any.
00108         } else {
00109           assert(LocalSize % 8 == 4);
00110           // There are 4 bytes padding, but we don't need any; remove it.
00111           memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);
00112           Index += 4;
00113         }
00114       }
00115       NumBytesAtAlign4 += LocalSize;
00116     }
00117   } else if (LocalAlignment == 8) {
00118     if (!NumBytesAtAlign8 && NumBytesAtAlign4 % 8 != 0) {
00119       // No existing padding and misaligned members; add in 4 bytes padding
00120       memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
00121       Index -= 4;
00122     }
00123     // Forget about any padding.
00124     NumBytesAtAlign4 = 0;
00125     NumBytesAtAlign8 += LocalSize;
00126   } else {
00127     assert(LocalSize == 0);
00128   }
00129 
00130   Index -= LocalSize;
00131 
00132   assert(Capacity - Index == TypeLoc::getFullDataSizeForType(T) &&
00133          "incorrect data size provided to CreateTypeSourceInfo!");
00134 
00135   return getTemporaryTypeLoc(T);
00136 }