clang  9.0.0svn
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 
44 void TypeLocBuilder::grow(size_t NewCapacity) {
45  assert(NewCapacity > Capacity);
46 
47  // Allocate the new buffer and copy the old data into it.
48  char *NewBuffer = new char[NewCapacity];
49  unsigned NewIndex = Index + NewCapacity - Capacity;
50  memcpy(&NewBuffer[NewIndex],
51  &Buffer[Index],
52  Capacity - Index);
53 
54  if (Buffer != InlineBuffer.buffer)
55  delete[] Buffer;
56 
57  Buffer = NewBuffer;
58  Capacity = NewCapacity;
59  Index = NewIndex;
60 }
61 
62 TypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) {
63 #ifndef NDEBUG
64  QualType TLast = TypeLoc(T, nullptr).getNextTypeLoc().getType();
65  assert(TLast == LastTy &&
66  "mismatch between last type and new type's inner type");
67  LastTy = T;
68 #endif
69 
70  assert(LocalAlignment <= BufferMaxAlignment && "Unexpected alignment");
71 
72  // If we need to grow, grow by a factor of 2.
73  if (LocalSize > Index) {
74  size_t RequiredCapacity = Capacity + (LocalSize - Index);
75  size_t NewCapacity = Capacity * 2;
76  while (RequiredCapacity > NewCapacity)
77  NewCapacity *= 2;
78  grow(NewCapacity);
79  }
80 
81  // Because we're adding elements to the TypeLoc backwards, we have to
82  // do some extra work to keep everything aligned appropriately.
83  // FIXME: This algorithm is a absolute mess because every TypeLoc returned
84  // needs to be valid. Partial TypeLocs are a terrible idea.
85  // FIXME: 4 and 8 are sufficient at the moment, but it's pretty ugly to
86  // hardcode them.
87  if (LocalAlignment == 4) {
88  if (NumBytesAtAlign8 == 0) {
89  NumBytesAtAlign4 += LocalSize;
90  } else {
91  unsigned Padding = NumBytesAtAlign4 % 8;
92  if (Padding == 0) {
93  if (LocalSize % 8 == 0) {
94  // Everything is set: there's no padding and we don't need to add
95  // any.
96  } else {
97  assert(LocalSize % 8 == 4);
98  // No existing padding; add in 4 bytes padding
99  memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
100  Index -= 4;
101  }
102  } else {
103  assert(Padding == 4);
104  if (LocalSize % 8 == 0) {
105  // Everything is set: there's 4 bytes padding and we don't need
106  // to add any.
107  } else {
108  assert(LocalSize % 8 == 4);
109  // There are 4 bytes padding, but we don't need any; remove it.
110  memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);
111  Index += 4;
112  }
113  }
114  NumBytesAtAlign4 += LocalSize;
115  }
116  } else if (LocalAlignment == 8) {
117  if (NumBytesAtAlign8 == 0) {
118  // We have not seen any 8-byte aligned element yet. We insert a padding
119  // only if the new Index is not 8-byte-aligned.
120  if ((Index - LocalSize) % 8 != 0) {
121  memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
122  Index -= 4;
123  }
124  } else {
125  unsigned Padding = NumBytesAtAlign4 % 8;
126  if (Padding == 0) {
127  if (LocalSize % 8 == 0) {
128  // Everything is set: there's no padding and we don't need to add
129  // any.
130  } else {
131  assert(LocalSize % 8 == 4);
132  // No existing padding; add in 4 bytes padding
133  memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
134  Index -= 4;
135  }
136  } else {
137  assert(Padding == 4);
138  if (LocalSize % 8 == 0) {
139  // Everything is set: there's 4 bytes padding and we don't need
140  // to add any.
141  } else {
142  assert(LocalSize % 8 == 4);
143  // There are 4 bytes padding, but we don't need any; remove it.
144  memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);
145  Index += 4;
146  }
147  }
148  }
149 
150  // Forget about any padding.
151  NumBytesAtAlign4 = 0;
152  NumBytesAtAlign8 += LocalSize;
153  } else {
154  assert(LocalSize == 0);
155  }
156 
157  Index -= LocalSize;
158 
159  assert(Capacity - Index == TypeLoc::getFullDataSizeForType(T) &&
160  "incorrect data size provided to CreateTypeSourceInfo!");
161 
162  return getTemporaryTypeLoc(T);
163 }
static unsigned getFullDataSizeForType(QualType Ty)
Returns the size of type source info data block for the given type.
Definition: TypeLoc.cpp:91
A (possibly-)qualified type.
Definition: Type.h:639
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:167
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:56
void reserve(size_t Requested)
Ensures that this buffer has at least as much capacity as described.
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
unsigned getFullDataSize() const
Returns the size of the type source info data block.
Definition: TypeLoc.h:161
Dataflow Directional Tag Classes.
QualType getType() const
Get the type for which this source info wrapper provides information.
Definition: TypeLoc.h:130
TypeLocClass getTypeLocClass() const
Definition: TypeLoc.h:113
void pushFullCopy(TypeLoc L)
Pushes a copy of the given TypeLoc onto this builder.