• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
pushFullCopy(TypeLoc L)19 void TypeLocBuilder::pushFullCopy(TypeLoc L) {
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 
grow(size_t NewCapacity)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 
pushImpl(QualType T,size_t LocalSize,unsigned LocalAlignment)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 }
165