clang API Documentation
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 }