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 && NumBytesAtAlign4 % 8 != 0) {
119 // No existing padding and misaligned members; add in 4 bytes padding
120 memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
121 Index -= 4;
122 }
123 // Forget about any padding.
124 NumBytesAtAlign4 = 0;
125 NumBytesAtAlign8 += LocalSize;
126 } else {
127 assert(LocalSize == 0);
128 }
129
130 Index -= LocalSize;
131
132 assert(Capacity - Index == TypeLoc::getFullDataSizeForType(T) &&
133 "incorrect data size provided to CreateTypeSourceInfo!");
134
135 return getTemporaryTypeLoc(T);
136 }
137