diff options
Diffstat (limited to 'lib/Sema/TypeLocBuilder.cpp')
-rw-r--r-- | lib/Sema/TypeLocBuilder.cpp | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/lib/Sema/TypeLocBuilder.cpp b/lib/Sema/TypeLocBuilder.cpp new file mode 100644 index 0000000..c7d43b7 --- /dev/null +++ b/lib/Sema/TypeLocBuilder.cpp @@ -0,0 +1,136 @@ +//===--- TypeLocBuilder.cpp - Type Source Info collector ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This files defines TypeLocBuilder, a class for building TypeLocs +// bottom-up. +// +//===----------------------------------------------------------------------===// + +#include "TypeLocBuilder.h" + +using namespace clang; + +void TypeLocBuilder::pushFullCopy(TypeLoc L) { + size_t Size = L.getFullDataSize(); + reserve(Size); + + SmallVector<TypeLoc, 4> TypeLocs; + TypeLoc CurTL = L; + while (CurTL) { + TypeLocs.push_back(CurTL); + CurTL = CurTL.getNextTypeLoc(); + } + + for (unsigned i = 0, e = TypeLocs.size(); i < e; ++i) { + TypeLoc CurTL = TypeLocs[e-i-1]; + switch (CurTL.getTypeLocClass()) { +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ + case TypeLoc::CLASS: { \ + CLASS##TypeLoc NewTL = push<class CLASS##TypeLoc>(CurTL.getType()); \ + memcpy(NewTL.getOpaqueData(), CurTL.getOpaqueData(), NewTL.getLocalDataSize()); \ + break; \ + } +#include "clang/AST/TypeLocNodes.def" + } + } +} + +void TypeLocBuilder::grow(size_t NewCapacity) { + assert(NewCapacity > Capacity); + + // Allocate the new buffer and copy the old data into it. + char *NewBuffer = new char[NewCapacity]; + unsigned NewIndex = Index + NewCapacity - Capacity; + memcpy(&NewBuffer[NewIndex], + &Buffer[Index], + Capacity - Index); + + if (Buffer != InlineBuffer.buffer) + delete[] Buffer; + + Buffer = NewBuffer; + Capacity = NewCapacity; + Index = NewIndex; +} + +TypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) { +#ifndef NDEBUG + QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType(); + assert(TLast == LastTy && + "mismatch between last type and new type's inner type"); + LastTy = T; +#endif + + assert(LocalAlignment <= BufferMaxAlignment && "Unexpected alignment"); + + // If we need to grow, grow by a factor of 2. + if (LocalSize > Index) { + size_t RequiredCapacity = Capacity + (LocalSize - Index); + size_t NewCapacity = Capacity * 2; + while (RequiredCapacity > NewCapacity) + NewCapacity *= 2; + grow(NewCapacity); + } + + // Because we're adding elements to the TypeLoc backwards, we have to + // do some extra work to keep everything aligned appropriately. + // FIXME: This algorithm is a absolute mess because every TypeLoc returned + // needs to be valid. Partial TypeLocs are a terrible idea. + // FIXME: 4 and 8 are sufficient at the moment, but it's pretty ugly to + // hardcode them. + if (LocalAlignment == 4) { + if (NumBytesAtAlign8 == 0) { + NumBytesAtAlign4 += LocalSize; + } else { + unsigned Padding = NumBytesAtAlign4 % 8; + if (Padding == 0) { + if (LocalSize % 8 == 0) { + // Everything is set: there's no padding and we don't need to add + // any. + } else { + assert(LocalSize % 8 == 4); + // No existing padding; add in 4 bytes padding + memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4); + Index -= 4; + } + } else { + assert(Padding == 4); + if (LocalSize % 8 == 0) { + // Everything is set: there's 4 bytes padding and we don't need + // to add any. + } else { + assert(LocalSize % 8 == 4); + // There are 4 bytes padding, but we don't need any; remove it. + memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4); + Index += 4; + } + } + NumBytesAtAlign4 += LocalSize; + } + } else if (LocalAlignment == 8) { + if (!NumBytesAtAlign8 && NumBytesAtAlign4 % 8 != 0) { + // No existing padding and misaligned members; add in 4 bytes padding + memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4); + Index -= 4; + } + // Forget about any padding. + NumBytesAtAlign4 = 0; + NumBytesAtAlign8 += LocalSize; + } else { + assert(LocalSize == 0); + } + + Index -= LocalSize; + + assert(Capacity - Index == TypeLoc::getFullDataSizeForType(T) && + "incorrect data size provided to CreateTypeSourceInfo!"); + + return getTemporaryTypeLoc(T); +} |