187 lines · cpp
1//===--- TypeLocBuilder.cpp - Type Source Info collector ------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This files defines TypeLocBuilder, a class for building TypeLocs10// bottom-up.11//12//===----------------------------------------------------------------------===//13 14#include "TypeLocBuilder.h"15 16using namespace clang;17 18void TypeLocBuilder::pushFullCopy(TypeLoc L) {19 size_t Size = L.getFullDataSize();20 reserve(Size);21 22 SmallVector<TypeLoc, 4> TypeLocs;23 TypeLoc CurTL = L;24 while (CurTL) {25 TypeLocs.push_back(CurTL);26 CurTL = CurTL.getNextTypeLoc();27 }28 29 for (unsigned i = 0, e = TypeLocs.size(); i < e; ++i) {30 TypeLoc CurTL = TypeLocs[e-i-1];31 switch (CurTL.getTypeLocClass()) {32#define ABSTRACT_TYPELOC(CLASS, PARENT)33#define TYPELOC(CLASS, PARENT) \34 case TypeLoc::CLASS: { \35 CLASS##TypeLoc NewTL = push<class CLASS##TypeLoc>(CurTL.getType()); \36 memcpy(NewTL.getOpaqueData(), CurTL.getOpaqueData(), NewTL.getLocalDataSize()); \37 break; \38 }39#include "clang/AST/TypeLocNodes.def"40 }41 }42}43 44void TypeLocBuilder::pushTrivial(ASTContext &Context, QualType T,45 SourceLocation Loc) {46 auto L = TypeLoc(T, nullptr);47 reserve(L.getFullDataSize());48 49 SmallVector<TypeLoc, 4> TypeLocs;50 for (auto CurTL = L; CurTL; CurTL = CurTL.getNextTypeLoc())51 TypeLocs.push_back(CurTL);52 53 for (const auto &CurTL : llvm::reverse(TypeLocs)) {54 switch (CurTL.getTypeLocClass()) {55#define ABSTRACT_TYPELOC(CLASS, PARENT)56#define TYPELOC(CLASS, PARENT) \57 case TypeLoc::CLASS: { \58 auto NewTL = push<class CLASS##TypeLoc>(CurTL.getType()); \59 NewTL.initializeLocal(Context, Loc); \60 break; \61 }62#include "clang/AST/TypeLocNodes.def"63 }64 }65}66 67void TypeLocBuilder::grow(size_t NewCapacity) {68 assert(NewCapacity > Capacity);69 70 // Allocate the new buffer and copy the old data into it.71 char *NewBuffer = new char[NewCapacity];72 unsigned NewIndex = Index + NewCapacity - Capacity;73 memcpy(&NewBuffer[NewIndex],74 &Buffer[Index],75 Capacity - Index);76 77 if (Buffer != InlineBuffer)78 delete[] Buffer;79 80 Buffer = NewBuffer;81 Capacity = NewCapacity;82 Index = NewIndex;83}84 85TypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) {86#ifndef NDEBUG87 QualType TLast = TypeLoc(T, nullptr).getNextTypeLoc().getType();88 assert(TLast == LastTy &&89 "mismatch between last type and new type's inner type");90 LastTy = T;91#endif92 93 assert(LocalAlignment <= BufferMaxAlignment && "Unexpected alignment");94 95 // If we need to grow, grow by a factor of 2.96 if (LocalSize > Index) {97 size_t RequiredCapacity = Capacity + (LocalSize - Index);98 size_t NewCapacity = Capacity * 2;99 while (RequiredCapacity > NewCapacity)100 NewCapacity *= 2;101 grow(NewCapacity);102 }103 104 // Because we're adding elements to the TypeLoc backwards, we have to105 // do some extra work to keep everything aligned appropriately.106 // FIXME: This algorithm is a absolute mess because every TypeLoc returned107 // needs to be valid. Partial TypeLocs are a terrible idea.108 // FIXME: 4 and 8 are sufficient at the moment, but it's pretty ugly to109 // hardcode them.110 if (LocalAlignment == 4) {111 if (!AtAlign8) {112 NumBytesAtAlign4 += LocalSize;113 } else {114 unsigned Padding = NumBytesAtAlign4 % 8;115 if (Padding == 0) {116 if (LocalSize % 8 == 0) {117 // Everything is set: there's no padding and we don't need to add118 // any.119 } else {120 assert(LocalSize % 8 == 4);121 // No existing padding; add in 4 bytes padding122 memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);123 Index -= 4;124 }125 } else {126 assert(Padding == 4);127 if (LocalSize % 8 == 0) {128 // Everything is set: there's 4 bytes padding and we don't need129 // to add any.130 } else {131 assert(LocalSize % 8 == 4);132 // There are 4 bytes padding, but we don't need any; remove it.133 memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);134 Index += 4;135 }136 }137 NumBytesAtAlign4 += LocalSize;138 }139 } else if (LocalAlignment == 8) {140 if (!AtAlign8) {141 // We have not seen any 8-byte aligned element yet. We insert a padding142 // only if the new Index is not 8-byte-aligned.143 if ((Index - LocalSize) % 8 != 0) {144 memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);145 Index -= 4;146 }147 } else {148 unsigned Padding = NumBytesAtAlign4 % 8;149 if (Padding == 0) {150 if (LocalSize % 8 == 0) {151 // Everything is set: there's no padding and we don't need to add152 // any.153 } else {154 assert(LocalSize % 8 == 4);155 // No existing padding; add in 4 bytes padding156 memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);157 Index -= 4;158 }159 } else {160 assert(Padding == 4);161 if (LocalSize % 8 == 0) {162 // Everything is set: there's 4 bytes padding and we don't need163 // to add any.164 } else {165 assert(LocalSize % 8 == 4);166 // There are 4 bytes padding, but we don't need any; remove it.167 memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);168 Index += 4;169 }170 }171 }172 173 // Forget about any padding.174 NumBytesAtAlign4 = 0;175 AtAlign8 = true;176 } else {177 assert(LocalSize == 0);178 }179 180 Index -= LocalSize;181 182 assert(Capacity - Index == TypeLoc::getFullDataSizeForType(T) &&183 "incorrect data size provided to CreateTypeSourceInfo!");184 185 return getTemporaryTypeLoc(T);186}187