clang  19.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 
16 using namespace clang;
17 
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 
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 
67 void 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 
85 TypeLoc 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 }
SourceLocation Loc
Definition: SemaObjC.cpp:755
__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:185
A (possibly-)qualified type.
Definition: Type.h:940
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:59
QualType getType() const
Get the type for which this source info wrapper provides information.
Definition: TypeLoc.h:133
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:170
unsigned getFullDataSize() const
Returns the size of the type source info data block.
Definition: TypeLoc.h:164
TypeLocClass getTypeLocClass() const
Definition: TypeLoc.h:116
static unsigned getFullDataSizeForType(QualType Ty)
Returns the size of type source info data block for the given type.
Definition: TypeLoc.cpp:94
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T