/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/CodeGen/ConstantInitBuilder.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- ConstantInitBuilder.h - Builder for LLVM IR constants ----*- C++ -*-===// |
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 class provides a convenient interface for building complex |
10 | | // global initializers of the sort that are frequently required for |
11 | | // language ABIs. |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #ifndef LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H |
16 | | #define LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H |
17 | | |
18 | | #include "llvm/ADT/ArrayRef.h" |
19 | | #include "llvm/ADT/SmallVector.h" |
20 | | #include "llvm/IR/Constants.h" |
21 | | #include "llvm/IR/GlobalValue.h" |
22 | | #include "clang/AST/CharUnits.h" |
23 | | #include "clang/CodeGen/ConstantInitFuture.h" |
24 | | |
25 | | #include <vector> |
26 | | |
27 | | namespace clang { |
28 | | namespace CodeGen { |
29 | | |
30 | | class CodeGenModule; |
31 | | |
32 | | /// A convenience builder class for complex constant initializers, |
33 | | /// especially for anonymous global structures used by various language |
34 | | /// runtimes. |
35 | | /// |
36 | | /// The basic usage pattern is expected to be something like: |
37 | | /// ConstantInitBuilder builder(CGM); |
38 | | /// auto toplevel = builder.beginStruct(); |
39 | | /// toplevel.addInt(CGM.SizeTy, widgets.size()); |
40 | | /// auto widgetArray = builder.beginArray(); |
41 | | /// for (auto &widget : widgets) { |
42 | | /// auto widgetDesc = widgetArray.beginStruct(); |
43 | | /// widgetDesc.addInt(CGM.SizeTy, widget.getPower()); |
44 | | /// widgetDesc.add(CGM.GetAddrOfConstantString(widget.getName())); |
45 | | /// widgetDesc.add(CGM.GetAddrOfGlobal(widget.getInitializerDecl())); |
46 | | /// widgetDesc.finishAndAddTo(widgetArray); |
47 | | /// } |
48 | | /// widgetArray.finishAndAddTo(toplevel); |
49 | | /// auto global = toplevel.finishAndCreateGlobal("WIDGET_LIST", Align, |
50 | | /// /*constant*/ true); |
51 | | class ConstantInitBuilderBase { |
52 | | struct SelfReference { |
53 | | llvm::GlobalVariable *Dummy; |
54 | | llvm::SmallVector<llvm::Constant*, 4> Indices; |
55 | | |
56 | 166 | SelfReference(llvm::GlobalVariable *dummy) : Dummy(dummy) {} |
57 | | }; |
58 | | CodeGenModule &CGM; |
59 | | llvm::SmallVector<llvm::Constant*, 16> Buffer; |
60 | | std::vector<SelfReference> SelfReferences; |
61 | | bool Frozen = false; |
62 | | |
63 | | friend class ConstantInitFuture; |
64 | | friend class ConstantAggregateBuilderBase; |
65 | | template <class, class> |
66 | | friend class ConstantAggregateBuilderTemplateBase; |
67 | | |
68 | | protected: |
69 | 18.8k | explicit ConstantInitBuilderBase(CodeGenModule &CGM) : CGM(CGM) {} |
70 | | |
71 | 18.8k | ~ConstantInitBuilderBase() { |
72 | 18.8k | assert(Buffer.empty() && "didn't claim all values out of buffer"); |
73 | 0 | assert(SelfReferences.empty() && "didn't apply all self-references"); |
74 | 18.8k | } |
75 | | |
76 | | private: |
77 | | llvm::GlobalVariable *createGlobal(llvm::Constant *initializer, |
78 | | const llvm::Twine &name, |
79 | | CharUnits alignment, |
80 | | bool constant = false, |
81 | | llvm::GlobalValue::LinkageTypes linkage |
82 | | = llvm::GlobalValue::InternalLinkage, |
83 | | unsigned addressSpace = 0); |
84 | | |
85 | | ConstantInitFuture createFuture(llvm::Constant *initializer); |
86 | | |
87 | | void setGlobalInitializer(llvm::GlobalVariable *GV, |
88 | | llvm::Constant *initializer); |
89 | | |
90 | | void resolveSelfReferences(llvm::GlobalVariable *GV); |
91 | | |
92 | | void abandon(size_t newEnd); |
93 | | }; |
94 | | |
95 | | /// A concrete base class for struct and array aggregate |
96 | | /// initializer builders. |
97 | | class ConstantAggregateBuilderBase { |
98 | | protected: |
99 | | ConstantInitBuilderBase &Builder; |
100 | | ConstantAggregateBuilderBase *Parent; |
101 | | size_t Begin; |
102 | | mutable size_t CachedOffsetEnd = 0; |
103 | | bool Finished = false; |
104 | | bool Frozen = false; |
105 | | bool Packed = false; |
106 | | mutable CharUnits CachedOffsetFromGlobal; |
107 | | |
108 | 33.2k | llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() { |
109 | 33.2k | return Builder.Buffer; |
110 | 33.2k | } |
111 | | |
112 | 3.61k | const llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() const { |
113 | 3.61k | return Builder.Buffer; |
114 | 3.61k | } |
115 | | |
116 | | ConstantAggregateBuilderBase(ConstantInitBuilderBase &builder, |
117 | | ConstantAggregateBuilderBase *parent) |
118 | 34.1k | : Builder(builder), Parent(parent), Begin(builder.Buffer.size()) { |
119 | 34.1k | if (parent) { |
120 | 15.1k | assert(!parent->Frozen && "parent already has child builder active"); |
121 | 0 | parent->Frozen = true; |
122 | 18.9k | } else { |
123 | 18.9k | assert(!builder.Frozen && "builder already has child builder active"); |
124 | 0 | builder.Frozen = true; |
125 | 18.9k | } |
126 | 34.1k | } |
127 | | |
128 | 34.1k | ~ConstantAggregateBuilderBase() { |
129 | 34.1k | assert(Finished && "didn't finish aggregate builder"); |
130 | 34.1k | } |
131 | | |
132 | 34.1k | void markFinished() { |
133 | 34.1k | assert(!Frozen && "child builder still active"); |
134 | 0 | assert(!Finished && "builder already finished"); |
135 | 0 | Finished = true; |
136 | 34.1k | if (Parent) { |
137 | 15.1k | assert(Parent->Frozen && |
138 | 15.1k | "parent not frozen while child builder active"); |
139 | 0 | Parent->Frozen = false; |
140 | 18.9k | } else { |
141 | 18.9k | assert(Builder.Frozen && |
142 | 18.9k | "builder not frozen while child builder active"); |
143 | 0 | Builder.Frozen = false; |
144 | 18.9k | } |
145 | 34.1k | } |
146 | | |
147 | | public: |
148 | | // Not copyable. |
149 | | ConstantAggregateBuilderBase(const ConstantAggregateBuilderBase &) = delete; |
150 | | ConstantAggregateBuilderBase &operator=(const ConstantAggregateBuilderBase &) |
151 | | = delete; |
152 | | |
153 | | // Movable, mostly to allow returning. But we have to write this out |
154 | | // properly to satisfy the assert in the destructor. |
155 | | ConstantAggregateBuilderBase(ConstantAggregateBuilderBase &&other) |
156 | | : Builder(other.Builder), Parent(other.Parent), Begin(other.Begin), |
157 | | CachedOffsetEnd(other.CachedOffsetEnd), |
158 | | Finished(other.Finished), Frozen(other.Frozen), Packed(other.Packed), |
159 | 0 | CachedOffsetFromGlobal(other.CachedOffsetFromGlobal) { |
160 | 0 | other.Finished = true; |
161 | 0 | } |
162 | | ConstantAggregateBuilderBase &operator=(ConstantAggregateBuilderBase &&other) |
163 | | = delete; |
164 | | |
165 | | /// Return the number of elements that have been added to |
166 | | /// this struct or array. |
167 | 1.80k | size_t size() const { |
168 | 1.80k | assert(!this->Finished && "cannot query after finishing builder"); |
169 | 0 | assert(!this->Frozen && "cannot query while sub-builder is active"); |
170 | 0 | assert(this->Begin <= this->getBuffer().size()); |
171 | 0 | return this->getBuffer().size() - this->Begin; |
172 | 1.80k | } |
173 | | |
174 | | /// Return true if no elements have yet been added to this struct or array. |
175 | 970 | bool empty() const { |
176 | 970 | return size() == 0; |
177 | 970 | } |
178 | | |
179 | | /// Abandon this builder completely. |
180 | 862 | void abandon() { |
181 | 862 | markFinished(); |
182 | 862 | Builder.abandon(Begin); |
183 | 862 | } |
184 | | |
185 | | /// Add a new value to this initializer. |
186 | 119k | void add(llvm::Constant *value) { |
187 | 119k | assert(value && "adding null value to constant initializer"); |
188 | 0 | assert(!Finished && "cannot add more values after finishing builder"); |
189 | 0 | assert(!Frozen && "cannot add values while subbuilder is active"); |
190 | 0 | Builder.Buffer.push_back(value); |
191 | 119k | } |
192 | | |
193 | | /// Add an integer value of type size_t. |
194 | | void addSize(CharUnits size); |
195 | | |
196 | | /// Add an integer value of a specific type. |
197 | | void addInt(llvm::IntegerType *intTy, uint64_t value, |
198 | 28.6k | bool isSigned = false) { |
199 | 28.6k | add(llvm::ConstantInt::get(intTy, value, isSigned)); |
200 | 28.6k | } |
201 | | |
202 | | /// Add a null pointer of a specific type. |
203 | 7.42k | void addNullPointer(llvm::PointerType *ptrTy) { |
204 | 7.42k | add(llvm::ConstantPointerNull::get(ptrTy)); |
205 | 7.42k | } |
206 | | |
207 | | /// Add a bitcast of a value to a specific type. |
208 | 5.84k | void addBitCast(llvm::Constant *value, llvm::Type *type) { |
209 | 5.84k | add(llvm::ConstantExpr::getBitCast(value, type)); |
210 | 5.84k | } |
211 | | |
212 | | /// Add a bunch of new values to this initializer. |
213 | 103 | void addAll(llvm::ArrayRef<llvm::Constant *> values) { |
214 | 103 | assert(!Finished && "cannot add more values after finishing builder"); |
215 | 0 | assert(!Frozen && "cannot add values while subbuilder is active"); |
216 | 0 | Builder.Buffer.append(values.begin(), values.end()); |
217 | 103 | } |
218 | | |
219 | | /// Add a relative offset to the given target address, i.e. the |
220 | | /// static difference between the target address and the address |
221 | | /// of the relative offset. The target must be known to be defined |
222 | | /// in the current linkage unit. The offset will have the given |
223 | | /// integer type, which must be no wider than intptr_t. Some |
224 | | /// targets may not fully support this operation. |
225 | 0 | void addRelativeOffset(llvm::IntegerType *type, llvm::Constant *target) { |
226 | 0 | add(getRelativeOffset(type, target)); |
227 | 0 | } |
228 | | |
229 | | /// Same as addRelativeOffset(), but instead relative to an element in this |
230 | | /// aggregate, identified by its index. |
231 | | void addRelativeOffsetToPosition(llvm::IntegerType *type, |
232 | 166 | llvm::Constant *target, size_t position) { |
233 | 166 | add(getRelativeOffsetToPosition(type, target, position)); |
234 | 166 | } |
235 | | |
236 | | /// Add a relative offset to the target address, plus a small |
237 | | /// constant offset. This is primarily useful when the relative |
238 | | /// offset is known to be a multiple of (say) four and therefore |
239 | | /// the tag can be used to express an extra two bits of information. |
240 | | void addTaggedRelativeOffset(llvm::IntegerType *type, |
241 | | llvm::Constant *address, |
242 | 0 | unsigned tag) { |
243 | 0 | llvm::Constant *offset = getRelativeOffset(type, address); |
244 | 0 | if (tag) { |
245 | 0 | offset = llvm::ConstantExpr::getAdd(offset, |
246 | 0 | llvm::ConstantInt::get(type, tag)); |
247 | 0 | } |
248 | 0 | add(offset); |
249 | 0 | } |
250 | | |
251 | | /// Return the offset from the start of the initializer to the |
252 | | /// next position, assuming no padding is required prior to it. |
253 | | /// |
254 | | /// This operation will not succeed if any unsized placeholders are |
255 | | /// currently in place in the initializer. |
256 | 0 | CharUnits getNextOffsetFromGlobal() const { |
257 | 0 | assert(!Finished && "cannot add more values after finishing builder"); |
258 | 0 | assert(!Frozen && "cannot add values while subbuilder is active"); |
259 | 0 | return getOffsetFromGlobalTo(Builder.Buffer.size()); |
260 | 0 | } |
261 | | |
262 | | /// An opaque class to hold the abstract position of a placeholder. |
263 | | class PlaceholderPosition { |
264 | | size_t Index; |
265 | | friend class ConstantAggregateBuilderBase; |
266 | 1.15k | PlaceholderPosition(size_t index) : Index(index) {} |
267 | | }; |
268 | | |
269 | | /// Add a placeholder value to the structure. The returned position |
270 | | /// can be used to set the value later; it will not be invalidated by |
271 | | /// any intermediate operations except (1) filling the same position or |
272 | | /// (2) finishing the entire builder. |
273 | | /// |
274 | | /// This is useful for emitting certain kinds of structure which |
275 | | /// contain some sort of summary field, generally a count, before any |
276 | | /// of the data. By emitting a placeholder first, the structure can |
277 | | /// be emitted eagerly. |
278 | 1.15k | PlaceholderPosition addPlaceholder() { |
279 | 1.15k | assert(!Finished && "cannot add more values after finishing builder"); |
280 | 0 | assert(!Frozen && "cannot add values while subbuilder is active"); |
281 | 0 | Builder.Buffer.push_back(nullptr); |
282 | 1.15k | return Builder.Buffer.size() - 1; |
283 | 1.15k | } |
284 | | |
285 | | /// Add a placeholder, giving the expected type that will be filled in. |
286 | | PlaceholderPosition addPlaceholderWithSize(llvm::Type *expectedType); |
287 | | |
288 | | /// Fill a previously-added placeholder. |
289 | | void fillPlaceholderWithInt(PlaceholderPosition position, |
290 | | llvm::IntegerType *type, uint64_t value, |
291 | 734 | bool isSigned = false) { |
292 | 734 | fillPlaceholder(position, llvm::ConstantInt::get(type, value, isSigned)); |
293 | 734 | } |
294 | | |
295 | | /// Fill a previously-added placeholder. |
296 | 734 | void fillPlaceholder(PlaceholderPosition position, llvm::Constant *value) { |
297 | 734 | assert(!Finished && "cannot change values after finishing builder"); |
298 | 0 | assert(!Frozen && "cannot add values while subbuilder is active"); |
299 | 0 | llvm::Constant *&slot = Builder.Buffer[position.Index]; |
300 | 734 | assert(slot == nullptr && "placeholder already filled"); |
301 | 0 | slot = value; |
302 | 734 | } |
303 | | |
304 | | /// Produce an address which will eventually point to the next |
305 | | /// position to be filled. This is computed with an indexed |
306 | | /// getelementptr rather than by computing offsets. |
307 | | /// |
308 | | /// The returned pointer will have type T*, where T is the given type. This |
309 | | /// type can differ from the type of the actual element. |
310 | | llvm::Constant *getAddrOfCurrentPosition(llvm::Type *type); |
311 | | |
312 | | /// Produce an address which points to a position in the aggregate being |
313 | | /// constructed. This is computed with an indexed getelementptr rather than by |
314 | | /// computing offsets. |
315 | | /// |
316 | | /// The returned pointer will have type T*, where T is the given type. This |
317 | | /// type can differ from the type of the actual element. |
318 | | llvm::Constant *getAddrOfPosition(llvm::Type *type, size_t position); |
319 | | |
320 | | llvm::ArrayRef<llvm::Constant*> getGEPIndicesToCurrentPosition( |
321 | 0 | llvm::SmallVectorImpl<llvm::Constant*> &indices) { |
322 | 0 | getGEPIndicesTo(indices, Builder.Buffer.size()); |
323 | 0 | return indices; |
324 | 0 | } |
325 | | |
326 | | protected: |
327 | | llvm::Constant *finishArray(llvm::Type *eltTy); |
328 | | llvm::Constant *finishStruct(llvm::StructType *structTy); |
329 | | |
330 | | private: |
331 | | void getGEPIndicesTo(llvm::SmallVectorImpl<llvm::Constant*> &indices, |
332 | | size_t position) const; |
333 | | |
334 | | llvm::Constant *getRelativeOffset(llvm::IntegerType *offsetType, |
335 | | llvm::Constant *target); |
336 | | |
337 | | llvm::Constant *getRelativeOffsetToPosition(llvm::IntegerType *offsetType, |
338 | | llvm::Constant *target, |
339 | | size_t position); |
340 | | |
341 | | CharUnits getOffsetFromGlobalTo(size_t index) const; |
342 | | }; |
343 | | |
344 | | template <class Impl, class Traits> |
345 | | class ConstantAggregateBuilderTemplateBase |
346 | | : public Traits::AggregateBuilderBase { |
347 | | using super = typename Traits::AggregateBuilderBase; |
348 | | public: |
349 | | using InitBuilder = typename Traits::InitBuilder; |
350 | | using ArrayBuilder = typename Traits::ArrayBuilder; |
351 | | using StructBuilder = typename Traits::StructBuilder; |
352 | | using AggregateBuilderBase = typename Traits::AggregateBuilderBase; |
353 | | |
354 | | protected: |
355 | | ConstantAggregateBuilderTemplateBase(InitBuilder &builder, |
356 | | AggregateBuilderBase *parent) |
357 | 34.1k | : super(builder, parent) {} clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantArrayBuilder, clang::CodeGen::ConstantInitBuilderTraits>::ConstantAggregateBuilderTemplateBase(clang::CodeGen::ConstantInitBuilder&, clang::CodeGen::ConstantAggregateBuilderBase*) Line | Count | Source | 357 | 9.61k | : super(builder, parent) {} |
clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::ConstantAggregateBuilderTemplateBase(clang::CodeGen::ConstantInitBuilder&, clang::CodeGen::ConstantAggregateBuilderBase*) Line | Count | Source | 357 | 24.5k | : super(builder, parent) {} |
|
358 | | |
359 | 33.2k | Impl &asImpl() { return *static_cast<Impl*>(this); } clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::asImpl() Line | Count | Source | 359 | 24.0k | Impl &asImpl() { return *static_cast<Impl*>(this); } |
clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantArrayBuilder, clang::CodeGen::ConstantInitBuilderTraits>::asImpl() Line | Count | Source | 359 | 9.19k | Impl &asImpl() { return *static_cast<Impl*>(this); } |
|
360 | | |
361 | | public: |
362 | 6.26k | ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) { |
363 | 6.26k | return ArrayBuilder(static_cast<InitBuilder&>(this->Builder), this, eltTy); |
364 | 6.26k | } |
365 | | |
366 | 8.93k | StructBuilder beginStruct(llvm::StructType *ty = nullptr) { |
367 | 8.93k | return StructBuilder(static_cast<InitBuilder&>(this->Builder), this, ty); |
368 | 8.93k | } |
369 | | |
370 | | /// Given that this builder was created by beginning an array or struct |
371 | | /// component on the given parent builder, finish the array/struct |
372 | | /// component and add it to the parent. |
373 | | /// |
374 | | /// It is an intentional choice that the parent is passed in explicitly |
375 | | /// despite it being redundant with information already kept in the |
376 | | /// builder. This aids in readability by making it easier to find the |
377 | | /// places that add components to a builder, as well as "bookending" |
378 | | /// the sub-builder more explicitly. |
379 | 14.7k | void finishAndAddTo(AggregateBuilderBase &parent) { |
380 | 14.7k | assert(this->Parent == &parent && "adding to non-parent builder"); |
381 | 0 | parent.add(asImpl().finishImpl()); |
382 | 14.7k | } clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantArrayBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndAddTo(clang::CodeGen::ConstantAggregateBuilderBase&) Line | Count | Source | 379 | 5.84k | void finishAndAddTo(AggregateBuilderBase &parent) { | 380 | 5.84k | assert(this->Parent == &parent && "adding to non-parent builder"); | 381 | 0 | parent.add(asImpl().finishImpl()); | 382 | 5.84k | } |
clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndAddTo(clang::CodeGen::ConstantAggregateBuilderBase&) Line | Count | Source | 379 | 8.93k | void finishAndAddTo(AggregateBuilderBase &parent) { | 380 | 8.93k | assert(this->Parent == &parent && "adding to non-parent builder"); | 381 | 0 | parent.add(asImpl().finishImpl()); | 382 | 8.93k | } |
|
383 | | |
384 | | /// Given that this builder was created by beginning an array or struct |
385 | | /// directly on a ConstantInitBuilder, finish the array/struct and |
386 | | /// create a global variable with it as the initializer. |
387 | | template <class... As> |
388 | 13.7k | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { |
389 | 13.7k | assert(!this->Parent && "finishing non-root builder"); |
390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), |
391 | 13.7k | std::forward<As>(args)...); |
392 | 13.7k | } llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, clang::CharUnits, bool, llvm::GlobalValue::LinkageTypes&, unsigned int&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, clang::CharUnits&&, bool&&, llvm::GlobalValue::LinkageTypes&, unsigned int&) Line | Count | Source | 388 | 910 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 910 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 910 | std::forward<As>(args)...); | 392 | 910 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<char const (&) [23], clang::CharUnits const&, bool, llvm::GlobalValue::LinkageTypes, unsigned int&>(char const (&) [23], clang::CharUnits const&, bool&&, llvm::GlobalValue::LinkageTypes&&, unsigned int&) Line | Count | Source | 388 | 412 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 412 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 412 | std::forward<As>(args)...); | 392 | 412 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, clang::CharUnits, bool>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, clang::CharUnits&&, bool&&) Line | Count | Source | 388 | 51 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 51 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 51 | std::forward<As>(args)...); | 392 | 51 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<char const (&) [18], clang::CharUnits>(char const (&) [18], clang::CharUnits&&) Line | Count | Source | 388 | 41 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 41 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 41 | std::forward<As>(args)...); | 392 | 41 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<char const (&) [20], clang::CharUnits>(char const (&) [20], clang::CharUnits&&) Line | Count | Source | 388 | 95 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 95 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 95 | std::forward<As>(args)...); | 392 | 95 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<char const (&) [1], clang::CharUnits>(char const (&) [1], clang::CharUnits&&) Line | Count | Source | 388 | 150 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 150 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 150 | std::forward<As>(args)...); | 392 | 150 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<char const (&) [14], clang::CharUnits>(char const (&) [14], clang::CharUnits&&) Line | Count | Source | 388 | 3 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 3 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 3 | std::forward<As>(args)...); | 392 | 3 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantArrayBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<char const (&) [18], clang::CharUnits>(char const (&) [18], clang::CharUnits&&) Line | Count | Source | 388 | 3 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 3 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 3 | std::forward<As>(args)...); | 392 | 3 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantArrayBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<char const (&) [20], clang::CharUnits>(char const (&) [20], clang::CharUnits&&) Line | Count | Source | 388 | 50 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 50 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 50 | std::forward<As>(args)...); | 392 | 50 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<char const (&) [10], clang::CharUnits&>(char const (&) [10], clang::CharUnits&) Line | Count | Source | 388 | 7 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 7 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 7 | std::forward<As>(args)...); | 392 | 7 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantArrayBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<char const (&) [14], clang::CharUnits>(char const (&) [14], clang::CharUnits&&) Line | Count | Source | 388 | 24 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 24 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 24 | std::forward<As>(args)...); | 392 | 24 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, clang::CharUnits, bool, llvm::GlobalValue::LinkageTypes>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, clang::CharUnits&&, bool&&, llvm::GlobalValue::LinkageTypes&&) Line | Count | Source | 388 | 209 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 209 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 209 | std::forward<As>(args)...); | 392 | 209 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<char const (&) [15], clang::CharUnits>(char const (&) [15], clang::CharUnits&&) Line | Count | Source | 388 | 5 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 5 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 5 | std::forward<As>(args)...); | 392 | 5 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<char const (&) [16], clang::CharUnits>(char const (&) [16], clang::CharUnits&&) Line | Count | Source | 388 | 13 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 13 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 13 | std::forward<As>(args)...); | 392 | 13 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, clang::CharUnits>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, clang::CharUnits&&) Line | Count | Source | 388 | 18 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 18 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 18 | std::forward<As>(args)...); | 392 | 18 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<char const (&) [11], clang::CharUnits, bool, llvm::GlobalValue::LinkageTypes>(char const (&) [11], clang::CharUnits&&, bool&&, llvm::GlobalValue::LinkageTypes&&) Line | Count | Source | 388 | 13 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 13 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 13 | std::forward<As>(args)...); | 392 | 13 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<llvm::StringRef&, clang::CharUnits, bool, llvm::GlobalValue::LinkageTypes>(llvm::StringRef&, clang::CharUnits&&, bool&&, llvm::GlobalValue::LinkageTypes&&) Line | Count | Source | 388 | 71 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 71 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 71 | std::forward<As>(args)...); | 392 | 71 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, clang::CharUnits, bool, llvm::GlobalValue::LinkageTypes>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, clang::CharUnits&&, bool&&, llvm::GlobalValue::LinkageTypes&&) Line | Count | Source | 388 | 12 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 12 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 12 | std::forward<As>(args)...); | 392 | 12 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<llvm::StringRef, clang::CharUnits&, bool, llvm::GlobalValue::LinkageTypes>(llvm::StringRef&&, clang::CharUnits&, bool&&, llvm::GlobalValue::LinkageTypes&&) Line | Count | Source | 388 | 2 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 2 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 2 | std::forward<As>(args)...); | 392 | 2 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<char const (&) [16], clang::CharUnits, bool, llvm::GlobalValue::LinkageTypes>(char const (&) [16], clang::CharUnits&&, bool&&, llvm::GlobalValue::LinkageTypes&&) Line | Count | Source | 388 | 4 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 4 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 4 | std::forward<As>(args)...); | 392 | 4 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<char const (&) [20], clang::CharUnits, bool, llvm::GlobalValue::LinkageTypes>(char const (&) [20], clang::CharUnits&&, bool&&, llvm::GlobalValue::LinkageTypes&&) Line | Count | Source | 388 | 8 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 8 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 8 | std::forward<As>(args)...); | 392 | 8 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<char const (&) [27], clang::CharUnits>(char const (&) [27], clang::CharUnits&&) Line | Count | Source | 388 | 20 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 20 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 20 | std::forward<As>(args)...); | 392 | 20 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<llvm::Twine&, clang::CharUnits&, bool, llvm::GlobalValue::LinkageTypes&>(llvm::Twine&, clang::CharUnits&, bool&&, llvm::GlobalValue::LinkageTypes&) Line | Count | Source | 388 | 884 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 884 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 884 | std::forward<As>(args)...); | 392 | 884 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<llvm::Twine, clang::CharUnits, bool, llvm::GlobalValue::LinkageTypes>(llvm::Twine&&, clang::CharUnits&&, bool&&, llvm::GlobalValue::LinkageTypes&&) Line | Count | Source | 388 | 15 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 15 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 15 | std::forward<As>(args)...); | 392 | 15 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<llvm::Twine, clang::CharUnits, bool, llvm::GlobalValue::LinkageTypes&>(llvm::Twine&&, clang::CharUnits&&, bool&&, llvm::GlobalValue::LinkageTypes&) Line | Count | Source | 388 | 57 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 57 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 57 | std::forward<As>(args)...); | 392 | 57 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<llvm::Twine const&, clang::CharUnits, bool, llvm::GlobalValue::LinkageTypes>(llvm::Twine const&, clang::CharUnits&&, bool&&, llvm::GlobalValue::LinkageTypes&&) Line | Count | Source | 388 | 3.85k | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 3.85k | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 3.85k | std::forward<As>(args)...); | 392 | 3.85k | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<llvm::SmallString<64u>&, clang::CharUnits, bool, llvm::GlobalValue::LinkageTypes>(llvm::SmallString<64u>&, clang::CharUnits&&, bool&&, llvm::GlobalValue::LinkageTypes&&) Line | Count | Source | 388 | 60 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 60 | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 60 | std::forward<As>(args)...); | 392 | 60 | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantArrayBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<char const*&, clang::CharUnits, bool, llvm::GlobalValue::LinkageTypes>(char const*&, clang::CharUnits&&, bool&&, llvm::GlobalValue::LinkageTypes&&) Line | Count | Source | 388 | 3.26k | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 3.26k | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 3.26k | std::forward<As>(args)...); | 392 | 3.26k | } |
llvm::GlobalVariable* clang::CodeGen::ConstantAggregateBuilderTemplateBase<clang::CodeGen::ConstantStructBuilder, clang::CodeGen::ConstantInitBuilderTraits>::finishAndCreateGlobal<char const (&) [19], clang::CharUnits&, bool, llvm::GlobalValue::LinkageTypes>(char const (&) [19], clang::CharUnits&, bool&&, llvm::GlobalValue::LinkageTypes&&) Line | Count | Source | 388 | 3.51k | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 389 | 3.51k | assert(!this->Parent && "finishing non-root builder"); | 390 | 0 | return this->Builder.createGlobal(asImpl().finishImpl(), | 391 | 3.51k | std::forward<As>(args)...); | 392 | 3.51k | } |
|
393 | | |
394 | | /// Given that this builder was created by beginning an array or struct |
395 | | /// directly on a ConstantInitBuilder, finish the array/struct and |
396 | | /// set it as the initializer of the given global variable. |
397 | 4.71k | void finishAndSetAsInitializer(llvm::GlobalVariable *global) { |
398 | 4.71k | assert(!this->Parent && "finishing non-root builder"); |
399 | 0 | return this->Builder.setGlobalInitializer(global, asImpl().finishImpl()); |
400 | 4.71k | } |
401 | | |
402 | | /// Given that this builder was created by beginning an array or struct |
403 | | /// directly on a ConstantInitBuilder, finish the array/struct and |
404 | | /// return a future which can be used to install the initializer in |
405 | | /// a global later. |
406 | | /// |
407 | | /// This is useful for allowing a finished initializer to passed to |
408 | | /// an API which will build the global. However, the "future" preserves |
409 | | /// a dependency on the original builder; it is an error to pass it aside. |
410 | | ConstantInitFuture finishAndCreateFuture() { |
411 | | assert(!this->Parent && "finishing non-root builder"); |
412 | | return this->Builder.createFuture(asImpl().finishImpl()); |
413 | | } |
414 | | }; |
415 | | |
416 | | template <class Traits> |
417 | | class ConstantArrayBuilderTemplateBase |
418 | | : public ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder, |
419 | | Traits> { |
420 | | using super = |
421 | | ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder, Traits>; |
422 | | |
423 | | public: |
424 | | using InitBuilder = typename Traits::InitBuilder; |
425 | | using AggregateBuilderBase = typename Traits::AggregateBuilderBase; |
426 | | |
427 | | private: |
428 | | llvm::Type *EltTy; |
429 | | |
430 | | template <class, class> |
431 | | friend class ConstantAggregateBuilderTemplateBase; |
432 | | |
433 | | protected: |
434 | | ConstantArrayBuilderTemplateBase(InitBuilder &builder, |
435 | | AggregateBuilderBase *parent, |
436 | | llvm::Type *eltTy) |
437 | 9.61k | : super(builder, parent), EltTy(eltTy) {} |
438 | | |
439 | | private: |
440 | | /// Form an array constant from the values that have been added to this |
441 | | /// builder. |
442 | 9.19k | llvm::Constant *finishImpl() { |
443 | 9.19k | return AggregateBuilderBase::finishArray(EltTy); |
444 | 9.19k | } |
445 | | }; |
446 | | |
447 | | /// A template class designed to allow other frontends to |
448 | | /// easily customize the builder classes used by ConstantInitBuilder, |
449 | | /// and thus to extend the API to work with the abstractions they |
450 | | /// prefer. This would probably not be necessary if C++ just |
451 | | /// supported extension methods. |
452 | | template <class Traits> |
453 | | class ConstantStructBuilderTemplateBase |
454 | | : public ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder, |
455 | | Traits> { |
456 | | using super = |
457 | | ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder,Traits>; |
458 | | |
459 | | public: |
460 | | using InitBuilder = typename Traits::InitBuilder; |
461 | | using AggregateBuilderBase = typename Traits::AggregateBuilderBase; |
462 | | |
463 | | private: |
464 | | llvm::StructType *StructTy; |
465 | | |
466 | | template <class, class> |
467 | | friend class ConstantAggregateBuilderTemplateBase; |
468 | | |
469 | | protected: |
470 | | ConstantStructBuilderTemplateBase(InitBuilder &builder, |
471 | | AggregateBuilderBase *parent, |
472 | | llvm::StructType *structTy) |
473 | 24.5k | : super(builder, parent), StructTy(structTy) { |
474 | 24.5k | if (structTy) this->Packed = structTy->isPacked()17.2k ; |
475 | 24.5k | } |
476 | | |
477 | | public: |
478 | | void setPacked(bool packed) { |
479 | | this->Packed = packed; |
480 | | } |
481 | | |
482 | | /// Use the given type for the struct if its element count is correct. |
483 | | /// Don't add more elements after calling this. |
484 | | void suggestType(llvm::StructType *structTy) { |
485 | | if (this->size() == structTy->getNumElements()) { |
486 | | StructTy = structTy; |
487 | | } |
488 | | } |
489 | | |
490 | | private: |
491 | | /// Form an array constant from the values that have been added to this |
492 | | /// builder. |
493 | 24.0k | llvm::Constant *finishImpl() { |
494 | 24.0k | return AggregateBuilderBase::finishStruct(StructTy); |
495 | 24.0k | } |
496 | | }; |
497 | | |
498 | | /// A template class designed to allow other frontends to |
499 | | /// easily customize the builder classes used by ConstantInitBuilder, |
500 | | /// and thus to extend the API to work with the abstractions they |
501 | | /// prefer. This would probably not be necessary if C++ just |
502 | | /// supported extension methods. |
503 | | template <class Traits> |
504 | | class ConstantInitBuilderTemplateBase : public ConstantInitBuilderBase { |
505 | | protected: |
506 | | ConstantInitBuilderTemplateBase(CodeGenModule &CGM) |
507 | 18.8k | : ConstantInitBuilderBase(CGM) {} |
508 | | |
509 | | public: |
510 | | using InitBuilder = typename Traits::InitBuilder; |
511 | | using ArrayBuilder = typename Traits::ArrayBuilder; |
512 | | using StructBuilder = typename Traits::StructBuilder; |
513 | | |
514 | 3.34k | ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) { |
515 | 3.34k | return ArrayBuilder(static_cast<InitBuilder&>(*this), nullptr, eltTy); |
516 | 3.34k | } |
517 | | |
518 | 15.5k | StructBuilder beginStruct(llvm::StructType *structTy = nullptr) { |
519 | 15.5k | return StructBuilder(static_cast<InitBuilder&>(*this), nullptr, structTy); |
520 | 15.5k | } |
521 | | }; |
522 | | |
523 | | class ConstantInitBuilder; |
524 | | class ConstantStructBuilder; |
525 | | class ConstantArrayBuilder; |
526 | | |
527 | | struct ConstantInitBuilderTraits { |
528 | | using InitBuilder = ConstantInitBuilder; |
529 | | using AggregateBuilderBase = ConstantAggregateBuilderBase; |
530 | | using ArrayBuilder = ConstantArrayBuilder; |
531 | | using StructBuilder = ConstantStructBuilder; |
532 | | }; |
533 | | |
534 | | /// The standard implementation of ConstantInitBuilder used in Clang. |
535 | | class ConstantInitBuilder |
536 | | : public ConstantInitBuilderTemplateBase<ConstantInitBuilderTraits> { |
537 | | public: |
538 | | explicit ConstantInitBuilder(CodeGenModule &CGM) : |
539 | 18.8k | ConstantInitBuilderTemplateBase(CGM) {} |
540 | | }; |
541 | | |
542 | | /// A helper class of ConstantInitBuilder, used for building constant |
543 | | /// array initializers. |
544 | | class ConstantArrayBuilder |
545 | | : public ConstantArrayBuilderTemplateBase<ConstantInitBuilderTraits> { |
546 | | template <class Traits> |
547 | | friend class ConstantInitBuilderTemplateBase; |
548 | | |
549 | | // The use of explicit qualification is a GCC workaround. |
550 | | template <class Impl, class Traits> |
551 | | friend class CodeGen::ConstantAggregateBuilderTemplateBase; |
552 | | |
553 | | ConstantArrayBuilder(ConstantInitBuilder &builder, |
554 | | ConstantAggregateBuilderBase *parent, |
555 | | llvm::Type *eltTy) |
556 | 9.61k | : ConstantArrayBuilderTemplateBase(builder, parent, eltTy) {} |
557 | | }; |
558 | | |
559 | | /// A helper class of ConstantInitBuilder, used for building constant |
560 | | /// struct initializers. |
561 | | class ConstantStructBuilder |
562 | | : public ConstantStructBuilderTemplateBase<ConstantInitBuilderTraits> { |
563 | | template <class Traits> |
564 | | friend class ConstantInitBuilderTemplateBase; |
565 | | |
566 | | // The use of explicit qualification is a GCC workaround. |
567 | | template <class Impl, class Traits> |
568 | | friend class CodeGen::ConstantAggregateBuilderTemplateBase; |
569 | | |
570 | | ConstantStructBuilder(ConstantInitBuilder &builder, |
571 | | ConstantAggregateBuilderBase *parent, |
572 | | llvm::StructType *structTy) |
573 | 24.5k | : ConstantStructBuilderTemplateBase(builder, parent, structTy) {} |
574 | | }; |
575 | | |
576 | | } // end namespace CodeGen |
577 | | } // end namespace clang |
578 | | |
579 | | #endif |