clang  6.0.0svn
TypeLocBuilder.cpp
Go to the documentation of this file.
1 //===--- TypeLocBuilder.cpp - Type Source Info collector ------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This files defines TypeLocBuilder, a class for building TypeLocs
11 // bottom-up.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "TypeLocBuilder.h"
16 
17 using namespace clang;
18 
20  size_t Size = L.getFullDataSize();
21  reserve(Size);
22 
23  SmallVector<TypeLoc, 4> TypeLocs;
24  TypeLoc CurTL = L;
25  while (CurTL) {
26  TypeLocs.push_back(CurTL);
27  CurTL = CurTL.getNextTypeLoc();
28  }
29 
30  for (unsigned i = 0, e = TypeLocs.size(); i < e; ++i) {
31  TypeLoc CurTL = TypeLocs[e-i-1];
32  switch (CurTL.getTypeLocClass()) {
33 #define ABSTRACT_TYPELOC(CLASS, PARENT)
34 #define TYPELOC(CLASS, PARENT) \
35  case TypeLoc::CLASS: { \
36  CLASS##TypeLoc NewTL = push<class CLASS##TypeLoc>(CurTL.getType()); \
37  memcpy(NewTL.getOpaqueData(), CurTL.getOpaqueData(), NewTL.getLocalDataSize()); \
38  break; \
39  }
40 #include "clang/AST/TypeLocNodes.def"
41  }
42  }
43 }
44 
45 void TypeLocBuilder::grow(size_t NewCapacity) {
46  assert(NewCapacity > Capacity);
47 
48  // Allocate the new buffer and copy the old data into it.
49  char *NewBuffer = new char[NewCapacity];
50  unsigned NewIndex = Index + NewCapacity - Capacity;
51  memcpy(&NewBuffer[NewIndex],
52  &Buffer[Index],
53  Capacity - Index);
54 
55  if (Buffer != InlineBuffer.buffer)
56  delete[] Buffer;
57 
58  Buffer = NewBuffer;
59  Capacity = NewCapacity;
60  Index = NewIndex;
61 }
62 
63 TypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) {
64 #ifndef NDEBUG
65  QualType TLast = TypeLoc(T, nullptr).getNextTypeLoc().getType();
66  assert(TLast == LastTy &&
67  "mismatch between last type and new type's inner type");
68  LastTy = T;
69 #endif
70 
71  assert(LocalAlignment <= BufferMaxAlignment && "Unexpected alignment");
72 
73  // If we need to grow, grow by a factor of 2.
74  if (LocalSize > Index) {
75  size_t RequiredCapacity = Capacity + (LocalSize - Index);
76  size_t NewCapacity = Capacity * 2;
77  while (RequiredCapacity > NewCapacity)
78  NewCapacity *= 2;
79  grow(NewCapacity);
80  }
81 
82  // Because we're adding elements to the TypeLoc backwards, we have to
83  // do some extra work to keep everything aligned appropriately.
84  // FIXME: This algorithm is a absolute mess because every TypeLoc returned
85  // needs to be valid. Partial TypeLocs are a terrible idea.
86  // FIXME: 4 and 8 are sufficient at the moment, but it's pretty ugly to
87  // hardcode them.
88  if (LocalAlignment == 4) {
89  if (NumBytesAtAlign8 == 0) {
90  NumBytesAtAlign4 += LocalSize;
91  } else {
92  unsigned Padding = NumBytesAtAlign4 % 8;
93  if (Padding == 0) {
94  if (LocalSize % 8 == 0) {
95  // Everything is set: there's no padding and we don't need to add
96  // any.
97  } else {
98  assert(LocalSize % 8 == 4);
99  // No existing padding; add in 4 bytes padding
100  memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
101  Index -= 4;
102  }
103  } else {
104  assert(Padding == 4);
105  if (LocalSize % 8 == 0) {
106  // Everything is set: there's 4 bytes padding and we don't need
107  // to add any.
108  } else {
109  assert(LocalSize % 8 == 4);
110  // There are 4 bytes padding, but we don't need any; remove it.
111  memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);
112  Index += 4;
113  }
114  }
115  NumBytesAtAlign4 += LocalSize;
116  }
117  } else if (LocalAlignment == 8) {
118  if (NumBytesAtAlign8 == 0) {
119  // We have not seen any 8-byte aligned element yet. We insert a padding
120  // only if the new Index is not 8-byte-aligned.
121  if ((Index - LocalSize) % 8 != 0) {
122  memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
123  Index -= 4;
124  }
125  } else {
126  unsigned Padding = NumBytesAtAlign4 % 8;
127  if (Padding == 0) {
128  if (LocalSize % 8 == 0) {
129  // Everything is set: there's no padding and we don't need to add
130  // any.
131  } else {
132  assert(LocalSize % 8 == 4);
133  // No existing padding; add in 4 bytes padding
134  memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
135  Index -= 4;
136  }
137  } else {
138  assert(Padding == 4);
139  if (LocalSize % 8 == 0) {
140  // Everything is set: there's 4 bytes padding and we don't need
141  // to add any.
142  } else {
143  assert(LocalSize % 8 == 4);
144  // There are 4 bytes padding, but we don't need any; remove it.
145  memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);
146  Index += 4;
147  }
148  }
149  }
150 
151  // Forget about any padding.
152  NumBytesAtAlign4 = 0;
153  NumBytesAtAlign8 += LocalSize;
154  } else {
155  assert(LocalSize == 0);
156  }
157 
158  Index -= LocalSize;
159 
160  assert(Capacity - Index == TypeLoc::getFullDataSizeForType(T) &&
161  "incorrect data size provided to CreateTypeSourceInfo!");
162 
163  return getTemporaryTypeLoc(T);
164 }
static unsigned getFullDataSizeForType(QualType Ty)
Returns the size of type source info data block for the given type.
Definition: TypeLoc.cpp:75
A (possibly-)qualified type.
Definition: Type.h:614
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:152
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:40
const FunctionProtoType * T
void reserve(size_t Requested)
Ensures that this buffer has at least as much capacity as described.
unsigned getFullDataSize() const
Returns the size of the type source info data block.
Definition: TypeLoc.h:146
Dataflow Directional Tag Classes.
QualType getType() const
Get the type for which this source info wrapper provides information.
Definition: TypeLoc.h:114
TypeLocClass getTypeLocClass() const
Definition: TypeLoc.h:97
void pushFullCopy(TypeLoc L)
Pushes a copy of the given TypeLoc onto this builder.