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, 0).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