1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
//===--- TypeLocBuilder.cpp - Type Source Info collector ------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// 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)
delete[] Buffer;
Buffer = NewBuffer;
Capacity = NewCapacity;
Index = NewIndex;
}
TypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) {
#ifndef NDEBUG
QualType TLast = TypeLoc(T, nullptr).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 == 0) {
// We have not seen any 8-byte aligned element yet. We insert a padding
// only if the new Index is not 8-byte-aligned.
if ((Index - LocalSize) % 8 != 0) {
memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
Index -= 4;
}
} 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;
}
}
}
// 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);
}
|