clang 17.0.0git
TypeLocBuilder.cpp
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This files defines TypeLocBuilder, a class for building TypeLocs
10// bottom-up.
11//
12//===----------------------------------------------------------------------===//
13
14#include "TypeLocBuilder.h"
15
16using namespace clang;
17
19 size_t Size = L.getFullDataSize();
20 reserve(Size);
21
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
45 SourceLocation Loc) {
46 auto L = TypeLoc(T, nullptr);
47 reserve(L.getFullDataSize());
48
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 NDEBUG
87 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#endif
92
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 to
105 // do some extra work to keep everything aligned appropriately.
106 // FIXME: This algorithm is a absolute mess because every TypeLoc returned
107 // 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 to
109 // 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 add
118 // any.
119 } else {
120 assert(LocalSize % 8 == 4);
121 // No existing padding; add in 4 bytes padding
122 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 need
129 // 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 padding
142 // 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 add
152 // any.
153 } else {
154 assert(LocalSize % 8 == 4);
155 // No existing padding; add in 4 bytes padding
156 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 need
163 // 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}
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:182
A (possibly-)qualified type.
Definition: Type.h:736
Encodes a location in the source.
void pushFullCopy(TypeLoc L)
Pushes a copy of the given TypeLoc onto this builder.
void reserve(size_t Requested)
Ensures that this buffer has at least as much capacity as described.
void pushTrivial(ASTContext &Context, QualType T, SourceLocation Loc)
Pushes 'T' with all locations pointing to 'Loc'.
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:58
QualType getType() const
Get the type for which this source info wrapper provides information.
Definition: TypeLoc.h:132
TypeLoc getNextTypeLoc() const
Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the TypeLoc is a PointerLoc and next Typ...
Definition: TypeLoc.h:169
unsigned getFullDataSize() const
Returns the size of the type source info data block.
Definition: TypeLoc.h:163
TypeLocClass getTypeLocClass() const
Definition: TypeLoc.h:115
static unsigned getFullDataSizeForType(QualType Ty)
Returns the size of type source info data block for the given type.
Definition: TypeLoc.cpp:93