r183466 - Perform dynamic alignment computations so that the data in TypeLocs is
Manuel Klimek
klimek at google.com
Fri Jun 7 01:46:09 PDT 2013
FYI: this test leads to invalid type source locations in some cases. I
don't have a good enough repro yet (internal refactoring tests found this),
but the general idea is this:
Given a TypeLoc for a templated type A<B> of a function parameter (like
void f(const A<B>&), trying to getAs<clang::TemplateSpecializationTypeLoc>
would previously return a valid type loc, and now returns an invalid type
loc... Is that intentional?
Thanks,
/Manuel
On Fri, Jun 7, 2013 at 2:04 AM, Eli Friedman <eli.friedman at gmail.com> wrote:
> Author: efriedma
> Date: Thu Jun 6 19:04:31 2013
> New Revision: 183466
>
> URL: http://llvm.org/viewvc/llvm-project?rev=183466&view=rev
> Log:
> Perform dynamic alignment computations so that the data in TypeLocs is
> correctly aligned. Not performing such computations led to misaligned
> loads,
> which crash on some platforms and are generally bad on other platforms.
>
> The implementation of TypeLocBuilder::pushImpl is rather messy; code using
> TypeLocBuilder accidentally assumes that partial TypeLocs are
> laid out like a complete TypeLoc. As a followup, I intend to work on
> fixing the TypeLocBuilder API to avoid exposing partial TypeLocs; this
> should
> substantially simplify the implemementation.
>
> Fixes PR16144.
>
>
> Added:
> cfe/trunk/lib/Sema/TypeLocBuilder.cpp
> Modified:
> cfe/trunk/include/clang/AST/TypeLoc.h
> cfe/trunk/lib/AST/TypeLoc.cpp
> cfe/trunk/lib/Sema/CMakeLists.txt
> cfe/trunk/lib/Sema/SemaLambda.cpp
> cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
> cfe/trunk/lib/Sema/TreeTransform.h
> cfe/trunk/lib/Sema/TypeLocBuilder.h
>
> Modified: cfe/trunk/include/clang/AST/TypeLoc.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=183466&r1=183465&r2=183466&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/TypeLoc.h (original)
> +++ cfe/trunk/include/clang/AST/TypeLoc.h Thu Jun 6 19:04:31 2013
> @@ -95,6 +95,10 @@ public:
> /// \brief Returns the size of type source info data block for the
> given type.
> static unsigned getFullDataSizeForType(QualType Ty);
>
> + /// \brief Returns the alignment of type source info data block for
> + /// the given type.
> + static unsigned getLocalAlignmentForType(QualType Ty);
> +
> /// \brief Get the type for which this source info wrapper provides
> /// information.
> QualType getType() const {
> @@ -229,7 +233,11 @@ public:
> }
>
> UnqualTypeLoc getUnqualifiedLoc() const {
> - return UnqualTypeLoc(getTypePtr(), Data);
> + unsigned align =
> + TypeLoc::getLocalAlignmentForType(QualType(getTypePtr(), 0));
> + uintptr_t dataInt = reinterpret_cast<uintptr_t>(Data);
> + dataInt = llvm::RoundUpToAlignment(dataInt, align);
> + return UnqualTypeLoc(getTypePtr(), reinterpret_cast<void*>(dataInt));
> }
>
> /// Initializes the local data of this type source info block to
> @@ -250,10 +258,11 @@ public:
> return 0;
> }
>
> - /// \brief Returns the size of the type source info data block.
> - unsigned getFullDataSize() const {
> - return getLocalDataSize() +
> - getFullDataSizeForType(getType().getLocalUnqualifiedType());
> + /// \brief Returns the alignment of the type source info data block
> that is
> + /// specific to this type.
> + unsigned getLocalDataAlignment() const {
> + // We don't preserve any location information.
> + return 1;
> }
>
> private:
> @@ -280,9 +289,6 @@ inline UnqualTypeLoc TypeLoc::getUnquali
> /// \tparam LocalData the structure type of local location data for
> /// this type
> ///
> -/// sizeof(LocalData) needs to be a multiple of sizeof(void*) or
> -/// else the world will end.
> -///
> /// TypeLocs with non-constant amounts of local data should override
> /// getExtraLocalDataSize(); getExtraLocalData() will then point to
> /// this extra memory.
> @@ -317,12 +323,16 @@ class ConcreteTypeLoc : public Base {
> }
>
> public:
> - unsigned getLocalDataSize() const {
> - return sizeof(LocalData) + asDerived()->getExtraLocalDataSize();
> + unsigned getLocalDataAlignment() const {
> + return std::max(llvm::alignOf<LocalData>(),
> + asDerived()->getExtraLocalDataAlignment());
> }
> - // Give a default implementation that's useful for leaf types.
> - unsigned getFullDataSize() const {
> - return asDerived()->getLocalDataSize() + getInnerTypeSize();
> + unsigned getLocalDataSize() const {
> + unsigned size = sizeof(LocalData);
> + unsigned extraAlign = asDerived()->getExtraLocalDataAlignment();
> + size = llvm::RoundUpToAlignment(size, extraAlign);
> + size += asDerived()->getExtraLocalDataSize();
> + return size;
> }
>
> TypeLoc getNextTypeLoc() const {
> @@ -338,6 +348,10 @@ protected:
> return 0;
> }
>
> + unsigned getExtraLocalDataAlignment() const {
> + return 1;
> + }
> +
> LocalData *getLocalData() const {
> return static_cast<LocalData*>(Base::Data);
> }
> @@ -346,11 +360,17 @@ protected:
> /// local data that can't be captured in the Info (e.g. because it's
> /// of variable size).
> void *getExtraLocalData() const {
> - return getLocalData() + 1;
> + unsigned size = sizeof(LocalData);
> + unsigned extraAlign = asDerived()->getExtraLocalDataAlignment();
> + size = llvm::RoundUpToAlignment(size, extraAlign);
> + return reinterpret_cast<char*>(Base::Data) + size;
> }
>
> void *getNonLocalData() const {
> - return static_cast<char*>(Base::Data) +
> asDerived()->getLocalDataSize();
> + uintptr_t data = reinterpret_cast<uintptr_t>(Base::Data);
> + data += asDerived()->getLocalDataSize();
> + data = llvm::RoundUpToAlignment(data, getNextTypeAlign());
> + return reinterpret_cast<void*>(data);
> }
>
> struct HasNoInnerType {};
> @@ -373,6 +393,18 @@ private:
> return getInnerTypeLoc().getFullDataSize();
> }
>
> + unsigned getNextTypeAlign() const {
> + return getNextTypeAlign(asDerived()->getInnerType());
> + }
> +
> + unsigned getNextTypeAlign(HasNoInnerType _) const {
> + return 1;
> + }
> +
> + unsigned getNextTypeAlign(QualType T) const {
> + return TypeLoc::getLocalAlignmentForType(T);
> + }
> +
> TypeLoc getNextTypeLoc(HasNoInnerType _) const {
> return TypeLoc();
> }
> @@ -417,7 +449,8 @@ class TypeSpecTypeLoc : public ConcreteT
> Type,
> TypeSpecLocInfo> {
> public:
> - enum { LocalDataSize = sizeof(TypeSpecLocInfo) };
> + enum { LocalDataSize = sizeof(TypeSpecLocInfo),
> + LocalDataAlignment = llvm::AlignOf<TypeSpecLocInfo>::Alignment };
>
> SourceLocation getNameLoc() const {
> return this->getLocalData()->NameLoc;
> @@ -448,8 +481,6 @@ class BuiltinTypeLoc : public ConcreteTy
> BuiltinType,
> BuiltinLocInfo> {
> public:
> - enum { LocalDataSize = sizeof(BuiltinLocInfo) };
> -
> SourceLocation getBuiltinLoc() const {
> return getLocalData()->BuiltinLoc;
> }
> @@ -478,6 +509,10 @@ public:
> return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0;
> }
>
> + unsigned getExtraLocalDataAlignment() const {
> + return needsExtraLocalData() ? llvm::alignOf<WrittenBuiltinSpecs>() :
> 1;
> + }
> +
> SourceRange getLocalSourceRange() const {
> return SourceRange(getBuiltinLoc(), getBuiltinLoc());
> }
> @@ -840,6 +875,10 @@ public:
> return this->getNumProtocols() * sizeof(SourceLocation);
> }
>
> + unsigned getExtraLocalDataAlignment() const {
> + return llvm::alignOf<SourceLocation>();
> + }
> +
> QualType getInnerType() const {
> return getTypePtr()->getBaseType();
> }
> @@ -1166,6 +1205,10 @@ public:
> return getNumArgs() * sizeof(ParmVarDecl*);
> }
>
> + unsigned getExtraLocalDataAlignment() const {
> + return llvm::alignOf<ParmVarDecl*>();
> + }
> +
> QualType getInnerType() const { return getTypePtr()->getResultType(); }
> };
>
> @@ -1357,6 +1400,10 @@ public:
> return getNumArgs() * sizeof(TemplateArgumentLocInfo);
> }
>
> + unsigned getExtraLocalDataAlignment() const {
> + return llvm::alignOf<TemplateArgumentLocInfo>();
> + }
> +
> private:
> TemplateArgumentLocInfo *getArgInfos() const {
> return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
> @@ -1761,6 +1808,10 @@ public:
> return getNumArgs() * sizeof(TemplateArgumentLocInfo);
> }
>
> + unsigned getExtraLocalDataAlignment() const {
> + return llvm::alignOf<TemplateArgumentLocInfo>();
> + }
> +
> private:
> TemplateArgumentLocInfo *getArgInfos() const {
> return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
>
> Modified: cfe/trunk/lib/AST/TypeLoc.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeLoc.cpp?rev=183466&r1=183465&r2=183466&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/TypeLoc.cpp (original)
> +++ cfe/trunk/lib/AST/TypeLoc.cpp Thu Jun 6 19:04:31 2013
> @@ -41,12 +41,30 @@ SourceRange TypeLoc::getLocalSourceRange
> }
>
> namespace {
> + class TypeAligner : public TypeLocVisitor<TypeAligner, unsigned> {
> + public:
> +#define ABSTRACT_TYPELOC(CLASS, PARENT)
> +#define TYPELOC(CLASS, PARENT) \
> + unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
> + return TyLoc.getLocalDataAlignment(); \
> + }
> +#include "clang/AST/TypeLocNodes.def"
> + };
> +}
> +
> +/// \brief Returns the alignment of the type source info data block.
> +unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) {
> + if (Ty.isNull()) return 1;
> + return TypeAligner().Visit(TypeLoc(Ty, 0));
> +}
> +
> +namespace {
> class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
> public:
> #define ABSTRACT_TYPELOC(CLASS, PARENT)
> #define TYPELOC(CLASS, PARENT) \
> unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
> - return TyLoc.getFullDataSize(); \
> + return TyLoc.getLocalDataSize(); \
> }
> #include "clang/AST/TypeLocNodes.def"
> };
> @@ -54,8 +72,18 @@ namespace {
>
> /// \brief Returns the size of the type source info data block.
> unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
> - if (Ty.isNull()) return 0;
> - return TypeSizer().Visit(TypeLoc(Ty, 0));
> + unsigned Total = 0;
> + TypeLoc TyLoc(Ty, 0);
> + unsigned MaxAlign = 1;
> + while (!TyLoc.isNull()) {
> + unsigned Align = getLocalAlignmentForType(TyLoc.getType());
> + MaxAlign = std::max(Align, MaxAlign);
> + Total = llvm::RoundUpToAlignment(Total, Align);
> + Total += TypeSizer().Visit(TyLoc);
> + TyLoc = TyLoc.getNextTypeLoc();
> + }
> + Total = llvm::RoundUpToAlignment(Total, MaxAlign);
> + return Total;
> }
>
> namespace {
>
> Modified: cfe/trunk/lib/Sema/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=183466&r1=183465&r2=183466&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/CMakeLists.txt (original)
> +++ cfe/trunk/lib/Sema/CMakeLists.txt Thu Jun 6 19:04:31 2013
> @@ -51,6 +51,7 @@ add_clang_library(clangSema
> SemaTemplateVariadic.cpp
> SemaType.cpp
> TargetAttributesSema.cpp
> + TypeLocBuilder.cpp
> )
>
> add_dependencies(clangSema
>
> Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=183466&r1=183465&r2=183466&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaLambda.cpp Thu Jun 6 19:04:31 2013
> @@ -445,6 +445,7 @@ FieldDecl *Sema::checkInitCapture(Source
> assert(!DeductType.isNull() && "can't build reference to auto");
> TLB.push<ReferenceTypeLoc>(DeductType).setSigilLoc(Loc);
> }
> + TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType);
>
> InitializationKind InitKind = InitializationKind::CreateDefault(Loc);
> Expr *Init = InitExpr;
> @@ -476,8 +477,7 @@ FieldDecl *Sema::checkInitCapture(Source
> else
> InitKind = InitializationKind::CreateCopy(Loc, Loc);
> QualType DeducedType;
> - if (DeduceAutoType(TLB.getTemporaryTypeLoc(DeductType),
> - Init, DeducedType) == DAR_Failed) {
> + if (DeduceAutoType(TSI, Init, DeducedType) == DAR_Failed) {
> if (isa<InitListExpr>(Init))
> Diag(Loc, diag::err_init_capture_deduction_failure_from_init_list)
> << Id << Init->getSourceRange();
> @@ -492,7 +492,7 @@ FieldDecl *Sema::checkInitCapture(Source
> // the closure type. This member is not a bit-field and not mutable.
> // Core issue: the member is (probably...) public.
> FieldDecl *NewFD = CheckFieldDecl(
> - Id, DeducedType, TLB.getTypeSourceInfo(Context, DeductType),
> LSI->Lambda,
> + Id, DeducedType, TSI, LSI->Lambda,
> Loc, /*Mutable*/ false, /*BitWidth*/ 0, ICIS_NoInit,
> Loc, AS_public, /*PrevDecl*/ 0, /*Declarator*/ 0);
> LSI->Lambda->addDecl(NewFD);
>
> Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=183466&r1=183465&r2=183466&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Thu Jun 6 19:04:31 2013
> @@ -18,6 +18,7 @@
> #include "clang/Sema/ScopeInfo.h"
> #include "clang/Sema/SemaInternal.h"
> #include "clang/Sema/Template.h"
> +#include "TypeLocBuilder.h"
>
> using namespace clang;
>
> @@ -463,17 +464,13 @@ Sema::CheckPackExpansion(TypeSourceInfo
> EllipsisLoc, NumExpansions);
> if (Result.isNull())
> return 0;
> -
> - TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result);
> - PackExpansionTypeLoc TL =
> - TSResult->getTypeLoc().castAs<PackExpansionTypeLoc>();
> +
> + TypeLocBuilder TLB;
> + TLB.pushFullCopy(Pattern->getTypeLoc());
> + PackExpansionTypeLoc TL = TLB.push<PackExpansionTypeLoc>(Result);
> TL.setEllipsisLoc(EllipsisLoc);
> -
> - // Copy over the source-location information from the type.
> - memcpy(TL.getNextTypeLoc().getOpaqueData(),
> - Pattern->getTypeLoc().getOpaqueData(),
> - Pattern->getTypeLoc().getFullDataSize());
> - return TSResult;
> +
> + return TLB.getTypeSourceInfo(Context, Result);
> }
>
> QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange
> PatternRange,
>
> Modified: cfe/trunk/lib/Sema/TreeTransform.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=183466&r1=183465&r2=183466&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
> +++ cfe/trunk/lib/Sema/TreeTransform.h Thu Jun 6 19:04:31 2013
> @@ -3427,7 +3427,7 @@ TreeTransform<Derived>::TransformQualifi
> } else {
> // Otherwise, complain about the addition of a qualifier to an
> // already-qualified type.
> - SourceRange R = TLB.getTemporaryTypeLoc(Result).getSourceRange();
> + SourceRange R = T.getUnqualifiedLoc().getSourceRange();
> SemaRef.Diag(R.getBegin(),
> diag::err_attr_objc_ownership_redundant)
> << Result << R;
>
>
> Added: cfe/trunk/lib/Sema/TypeLocBuilder.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TypeLocBuilder.cpp?rev=183466&view=auto
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/TypeLocBuilder.cpp (added)
> +++ cfe/trunk/lib/Sema/TypeLocBuilder.cpp Thu Jun 6 19:04:31 2013
> @@ -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);
> +}
>
> Modified: cfe/trunk/lib/Sema/TypeLocBuilder.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TypeLocBuilder.h?rev=183466&r1=183465&r2=183466&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/TypeLocBuilder.h (original)
> +++ cfe/trunk/lib/Sema/TypeLocBuilder.h Thu Jun 6 19:04:31 2013
> @@ -39,14 +39,19 @@ class TypeLocBuilder {
> #endif
>
> /// The inline buffer.
> - char InlineBuffer[InlineCapacity];
> + enum { BufferMaxAlignment = llvm::AlignOf<void*>::Alignment };
> + llvm::AlignedCharArray<BufferMaxAlignment, InlineCapacity> InlineBuffer;
> + unsigned NumBytesAtAlign4, NumBytesAtAlign8;
>
> public:
> TypeLocBuilder()
> - : Buffer(InlineBuffer), Capacity(InlineCapacity),
> Index(InlineCapacity) {}
> + : Buffer(InlineBuffer.buffer), Capacity(InlineCapacity),
> + Index(InlineCapacity), NumBytesAtAlign4(0), NumBytesAtAlign8(0)
> + {
> + }
>
> ~TypeLocBuilder() {
> - if (Buffer != InlineBuffer)
> + if (Buffer != InlineBuffer.buffer)
> delete[] Buffer;
> }
>
> @@ -59,23 +64,14 @@ class TypeLocBuilder {
>
> /// Pushes a copy of the given TypeLoc onto this builder. The builder
> /// must be empty for this to work.
> - void pushFullCopy(TypeLoc L) {
> - size_t Size = L.getFullDataSize();
> - TypeLoc Copy = pushFullUninitializedImpl(L.getType(), Size);
> - memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size);
> - }
> -
> - /// Pushes uninitialized space for the given type. The builder must
> - /// be empty.
> - TypeLoc pushFullUninitialized(QualType T) {
> - return pushFullUninitializedImpl(T,
> TypeLoc::getFullDataSizeForType(T));
> - }
> + void pushFullCopy(TypeLoc L);
>
> /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs
> /// previously retrieved from this builder.
> TypeSpecTypeLoc pushTypeSpec(QualType T) {
> size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
> - return pushImpl(T, LocalSize).castAs<TypeSpecTypeLoc>();
> + unsigned LocalAlign = TypeSpecTypeLoc::LocalDataAlignment;
> + return pushImpl(T, LocalSize, LocalAlign).castAs<TypeSpecTypeLoc>();
> }
>
> /// Resets this builder to the newly-initialized state.
> @@ -84,6 +80,7 @@ class TypeLocBuilder {
> LastTy = QualType();
> #endif
> Index = Capacity;
> + NumBytesAtAlign4 = NumBytesAtAlign8 = 0;
> }
>
> /// \brief Tell the TypeLocBuilder that the type it is storing has been
> @@ -97,8 +94,10 @@ class TypeLocBuilder {
> /// Pushes space for a new TypeLoc of the given type. Invalidates
> /// any TypeLocs previously retrieved from this builder.
> template <class TyLocType> TyLocType push(QualType T) {
> - size_t LocalSize = TypeLoc(T,
> 0).castAs<TyLocType>().getLocalDataSize();
> - return pushImpl(T, LocalSize).castAs<TyLocType>();
> + TyLocType Loc = TypeLoc(T, 0).castAs<TyLocType>();
> + size_t LocalSize = Loc.getLocalDataSize();
> + unsigned LocalAlign = Loc.getLocalDataAlignment();
> + return pushImpl(T, LocalSize, LocalAlign).castAs<TyLocType>();
> }
>
> /// Creates a TypeSourceInfo for the given type.
> @@ -127,61 +126,12 @@ class TypeLocBuilder {
> }
>
> private:
> - TypeLoc pushImpl(QualType T, size_t LocalSize) {
> -#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
> -
> - // 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);
> - }
>
> - Index -= LocalSize;
> -
> - return getTemporaryTypeLoc(T);
> - }
> + TypeLoc pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment);
>
> /// Grow to the given capacity.
> - void 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)
> - delete[] Buffer;
> -
> - Buffer = NewBuffer;
> - Capacity = NewCapacity;
> - Index = NewIndex;
> - }
> -
> - TypeLoc pushFullUninitializedImpl(QualType T, size_t Size) {
> -#ifndef NDEBUG
> - assert(LastTy.isNull() && "pushing full on non-empty TypeLocBuilder");
> - LastTy = T;
> -#endif
> - assert(Index == Capacity && "pushing full on non-empty
> TypeLocBuilder");
> -
> - reserve(Size);
> - Index -= Size;
> -
> - return getTemporaryTypeLoc(T);
> - }
> + void grow(size_t NewCapacity);
>
> -public:
> /// \brief Retrieve a temporary TypeLoc that refers into this \c
> TypeLocBuilder
> /// object.
> ///
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130607/e6a523e6/attachment.html>
More information about the cfe-commits
mailing list