1259701Sdim//===--- TypeLocBuilder.cpp - Type Source Info collector ------------------===// 2259701Sdim// 3259701Sdim// The LLVM Compiler Infrastructure 4259701Sdim// 5259701Sdim// This file is distributed under the University of Illinois Open Source 6259701Sdim// License. See LICENSE.TXT for details. 7259701Sdim// 8259701Sdim//===----------------------------------------------------------------------===// 9259701Sdim// 10259701Sdim// This files defines TypeLocBuilder, a class for building TypeLocs 11259701Sdim// bottom-up. 12259701Sdim// 13259701Sdim//===----------------------------------------------------------------------===// 14259701Sdim 15259701Sdim#include "TypeLocBuilder.h" 16259701Sdim 17259701Sdimusing namespace clang; 18259701Sdim 19259701Sdimvoid TypeLocBuilder::pushFullCopy(TypeLoc L) { 20259701Sdim size_t Size = L.getFullDataSize(); 21259701Sdim reserve(Size); 22259701Sdim 23259701Sdim SmallVector<TypeLoc, 4> TypeLocs; 24259701Sdim TypeLoc CurTL = L; 25259701Sdim while (CurTL) { 26259701Sdim TypeLocs.push_back(CurTL); 27259701Sdim CurTL = CurTL.getNextTypeLoc(); 28259701Sdim } 29259701Sdim 30259701Sdim for (unsigned i = 0, e = TypeLocs.size(); i < e; ++i) { 31259701Sdim TypeLoc CurTL = TypeLocs[e-i-1]; 32259701Sdim switch (CurTL.getTypeLocClass()) { 33259701Sdim#define ABSTRACT_TYPELOC(CLASS, PARENT) 34259701Sdim#define TYPELOC(CLASS, PARENT) \ 35259701Sdim case TypeLoc::CLASS: { \ 36259701Sdim CLASS##TypeLoc NewTL = push<class CLASS##TypeLoc>(CurTL.getType()); \ 37259701Sdim memcpy(NewTL.getOpaqueData(), CurTL.getOpaqueData(), NewTL.getLocalDataSize()); \ 38259701Sdim break; \ 39259701Sdim } 40259701Sdim#include "clang/AST/TypeLocNodes.def" 41259701Sdim } 42259701Sdim } 43259701Sdim} 44259701Sdim 45259701Sdimvoid TypeLocBuilder::grow(size_t NewCapacity) { 46259701Sdim assert(NewCapacity > Capacity); 47259701Sdim 48259701Sdim // Allocate the new buffer and copy the old data into it. 49259701Sdim char *NewBuffer = new char[NewCapacity]; 50259701Sdim unsigned NewIndex = Index + NewCapacity - Capacity; 51259701Sdim memcpy(&NewBuffer[NewIndex], 52259701Sdim &Buffer[Index], 53259701Sdim Capacity - Index); 54259701Sdim 55259701Sdim if (Buffer != InlineBuffer.buffer) 56259701Sdim delete[] Buffer; 57259701Sdim 58259701Sdim Buffer = NewBuffer; 59259701Sdim Capacity = NewCapacity; 60259701Sdim Index = NewIndex; 61259701Sdim} 62259701Sdim 63259701SdimTypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) { 64259701Sdim#ifndef NDEBUG 65259701Sdim QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType(); 66259701Sdim assert(TLast == LastTy && 67259701Sdim "mismatch between last type and new type's inner type"); 68259701Sdim LastTy = T; 69259701Sdim#endif 70259701Sdim 71259701Sdim assert(LocalAlignment <= BufferMaxAlignment && "Unexpected alignment"); 72259701Sdim 73259701Sdim // If we need to grow, grow by a factor of 2. 74259701Sdim if (LocalSize > Index) { 75259701Sdim size_t RequiredCapacity = Capacity + (LocalSize - Index); 76259701Sdim size_t NewCapacity = Capacity * 2; 77259701Sdim while (RequiredCapacity > NewCapacity) 78259701Sdim NewCapacity *= 2; 79259701Sdim grow(NewCapacity); 80259701Sdim } 81259701Sdim 82259701Sdim // Because we're adding elements to the TypeLoc backwards, we have to 83259701Sdim // do some extra work to keep everything aligned appropriately. 84259701Sdim // FIXME: This algorithm is a absolute mess because every TypeLoc returned 85259701Sdim // needs to be valid. Partial TypeLocs are a terrible idea. 86259701Sdim // FIXME: 4 and 8 are sufficient at the moment, but it's pretty ugly to 87259701Sdim // hardcode them. 88259701Sdim if (LocalAlignment == 4) { 89259701Sdim if (NumBytesAtAlign8 == 0) { 90259701Sdim NumBytesAtAlign4 += LocalSize; 91259701Sdim } else { 92259701Sdim unsigned Padding = NumBytesAtAlign4 % 8; 93259701Sdim if (Padding == 0) { 94259701Sdim if (LocalSize % 8 == 0) { 95259701Sdim // Everything is set: there's no padding and we don't need to add 96259701Sdim // any. 97259701Sdim } else { 98259701Sdim assert(LocalSize % 8 == 4); 99259701Sdim // No existing padding; add in 4 bytes padding 100259701Sdim memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4); 101259701Sdim Index -= 4; 102259701Sdim } 103259701Sdim } else { 104259701Sdim assert(Padding == 4); 105259701Sdim if (LocalSize % 8 == 0) { 106259701Sdim // Everything is set: there's 4 bytes padding and we don't need 107259701Sdim // to add any. 108259701Sdim } else { 109259701Sdim assert(LocalSize % 8 == 4); 110259701Sdim // There are 4 bytes padding, but we don't need any; remove it. 111259701Sdim memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4); 112259701Sdim Index += 4; 113259701Sdim } 114259701Sdim } 115259701Sdim NumBytesAtAlign4 += LocalSize; 116259701Sdim } 117259701Sdim } else if (LocalAlignment == 8) { 118259701Sdim if (!NumBytesAtAlign8 && NumBytesAtAlign4 % 8 != 0) { 119259701Sdim // No existing padding and misaligned members; add in 4 bytes padding 120259701Sdim memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4); 121259701Sdim Index -= 4; 122259701Sdim } 123259701Sdim // Forget about any padding. 124259701Sdim NumBytesAtAlign4 = 0; 125259701Sdim NumBytesAtAlign8 += LocalSize; 126259701Sdim } else { 127259701Sdim assert(LocalSize == 0); 128259701Sdim } 129259701Sdim 130259701Sdim Index -= LocalSize; 131259701Sdim 132259701Sdim assert(Capacity - Index == TypeLoc::getFullDataSizeForType(T) && 133259701Sdim "incorrect data size provided to CreateTypeSourceInfo!"); 134259701Sdim 135259701Sdim return getTemporaryTypeLoc(T); 136259701Sdim} 137