/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Sema/TypeLocBuilder.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
18 | 493k | void TypeLocBuilder::pushFullCopy(TypeLoc L) { |
19 | 493k | size_t Size = L.getFullDataSize(); |
20 | 493k | reserve(Size); |
21 | | |
22 | 493k | SmallVector<TypeLoc, 4> TypeLocs; |
23 | 493k | TypeLoc CurTL = L; |
24 | 1.01M | while (CurTL) { |
25 | 517k | TypeLocs.push_back(CurTL); |
26 | 517k | CurTL = CurTL.getNextTypeLoc(); |
27 | 517k | } |
28 | | |
29 | 1.01M | for (unsigned i = 0, e = TypeLocs.size(); i < e; ++i517k ) { |
30 | 517k | TypeLoc CurTL = TypeLocs[e-i-1]; |
31 | 517k | switch (CurTL.getTypeLocClass()) { |
32 | 0 | #define ABSTRACT_TYPELOC(CLASS, PARENT) |
33 | 0 | #define TYPELOC(CLASS, PARENT) \ |
34 | 517k | case TypeLoc::CLASS: { \ |
35 | 517k | CLASS##TypeLoc NewTL = push<class CLASS##TypeLoc>(CurTL.getType()); \ |
36 | 517k | memcpy(NewTL.getOpaqueData(), CurTL.getOpaqueData(), NewTL.getLocalDataSize()); \ |
37 | 517k | break; \ |
38 | 517k | } |
39 | 517k | #include "clang/AST/TypeLocNodes.def"0 |
40 | 517k | } |
41 | 517k | } |
42 | 493k | } |
43 | | |
44 | 1.84M | void TypeLocBuilder::grow(size_t NewCapacity) { |
45 | 1.84M | assert(NewCapacity > Capacity); |
46 | | |
47 | | // Allocate the new buffer and copy the old data into it. |
48 | 0 | char *NewBuffer = new char[NewCapacity]; |
49 | 1.84M | unsigned NewIndex = Index + NewCapacity - Capacity; |
50 | 1.84M | memcpy(&NewBuffer[NewIndex], |
51 | 1.84M | &Buffer[Index], |
52 | 1.84M | Capacity - Index); |
53 | | |
54 | 1.84M | if (Buffer != InlineBuffer) |
55 | 14.5k | delete[] Buffer; |
56 | | |
57 | 1.84M | Buffer = NewBuffer; |
58 | 1.84M | Capacity = NewCapacity; |
59 | 1.84M | Index = NewIndex; |
60 | 1.84M | } |
61 | | |
62 | 25.4M | TypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) { |
63 | 25.4M | #ifndef NDEBUG |
64 | 25.4M | QualType TLast = TypeLoc(T, nullptr).getNextTypeLoc().getType(); |
65 | 25.4M | assert(TLast == LastTy && |
66 | 25.4M | "mismatch between last type and new type's inner type"); |
67 | 0 | LastTy = T; |
68 | 25.4M | #endif |
69 | | |
70 | 25.4M | assert(LocalAlignment <= BufferMaxAlignment && "Unexpected alignment"); |
71 | | |
72 | | // If we need to grow, grow by a factor of 2. |
73 | 25.4M | if (LocalSize > Index) { |
74 | 782k | size_t RequiredCapacity = Capacity + (LocalSize - Index); |
75 | 782k | size_t NewCapacity = Capacity * 2; |
76 | 785k | while (RequiredCapacity > NewCapacity) |
77 | 2.96k | NewCapacity *= 2; |
78 | 782k | grow(NewCapacity); |
79 | 782k | } |
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 | 25.4M | if (LocalAlignment == 4) { |
88 | 14.0M | if (NumBytesAtAlign8 == 0) { |
89 | 13.5M | NumBytesAtAlign4 += LocalSize; |
90 | 13.5M | } else { |
91 | 457k | unsigned Padding = NumBytesAtAlign4 % 8; |
92 | 457k | if (Padding == 0) { |
93 | 455k | if (LocalSize % 8 == 0) { |
94 | | // Everything is set: there's no padding and we don't need to add |
95 | | // any. |
96 | 447k | } else { |
97 | 447k | assert(LocalSize % 8 == 4); |
98 | | // No existing padding; add in 4 bytes padding |
99 | 0 | memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4); |
100 | 447k | Index -= 4; |
101 | 447k | } |
102 | 455k | } else { |
103 | 1.50k | assert(Padding == 4); |
104 | 1.50k | if (LocalSize % 8 == 0) { |
105 | | // Everything is set: there's 4 bytes padding and we don't need |
106 | | // to add any. |
107 | 1.50k | } else { |
108 | 1.50k | assert(LocalSize % 8 == 4); |
109 | | // There are 4 bytes padding, but we don't need any; remove it. |
110 | 0 | memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4); |
111 | 1.50k | Index += 4; |
112 | 1.50k | } |
113 | 1.50k | } |
114 | 0 | NumBytesAtAlign4 += LocalSize; |
115 | 457k | } |
116 | 14.0M | } else if (11.3M LocalAlignment == 811.3M ) { |
117 | 11.3M | 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 | 11.1M | if ((Index - LocalSize) % 8 != 0) { |
121 | 1.48M | memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4); |
122 | 1.48M | Index -= 4; |
123 | 1.48M | } |
124 | 11.1M | } else { |
125 | 244k | unsigned Padding = NumBytesAtAlign4 % 8; |
126 | 244k | if (Padding == 0) { |
127 | 226k | if (LocalSize % 8 == 0) { |
128 | | // Everything is set: there's no padding and we don't need to add |
129 | | // any. |
130 | 226k | } else { |
131 | 0 | assert(LocalSize % 8 == 4); |
132 | | // No existing padding; add in 4 bytes padding |
133 | 0 | memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4); |
134 | 0 | Index -= 4; |
135 | 0 | } |
136 | 226k | } else { |
137 | 18.2k | assert(Padding == 4); |
138 | 18.2k | if (LocalSize % 8 == 0) { |
139 | | // Everything is set: there's 4 bytes padding and we don't need |
140 | | // to add any. |
141 | 18.2k | } else { |
142 | 0 | assert(LocalSize % 8 == 4); |
143 | | // There are 4 bytes padding, but we don't need any; remove it. |
144 | 0 | memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4); |
145 | 0 | Index += 4; |
146 | 0 | } |
147 | 18.2k | } |
148 | 244k | } |
149 | | |
150 | | // Forget about any padding. |
151 | 0 | NumBytesAtAlign4 = 0; |
152 | 11.3M | NumBytesAtAlign8 += LocalSize; |
153 | 11.3M | } else { |
154 | 1.20k | assert(LocalSize == 0); |
155 | 1.20k | } |
156 | | |
157 | 0 | Index -= LocalSize; |
158 | | |
159 | 25.4M | assert(Capacity - Index == TypeLoc::getFullDataSizeForType(T) && |
160 | 25.4M | "incorrect data size provided to CreateTypeSourceInfo!"); |
161 | | |
162 | 0 | return getTemporaryTypeLoc(T); |
163 | 25.4M | } |