1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
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 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | class ConstantInitBuilderBase { |
52 | struct SelfReference { |
53 | llvm::GlobalVariable *Dummy; |
54 | llvm::SmallVector<llvm::Constant*, 4> Indices; |
55 | |
56 | 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 | explicit ConstantInitBuilderBase(CodeGenModule &CGM) : CGM(CGM) {} |
70 | |
71 | ~ConstantInitBuilderBase() { |
72 | (0) . __assert_fail ("Buffer.empty() && \"didn't claim all values out of buffer\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 72, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Buffer.empty() && "didn't claim all values out of buffer"); |
73 | (0) . __assert_fail ("SelfReferences.empty() && \"didn't apply all self-references\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 73, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(SelfReferences.empty() && "didn't apply all self-references"); |
74 | } |
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 | |
96 | |
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 | llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() { |
109 | return Builder.Buffer; |
110 | } |
111 | |
112 | const llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() const { |
113 | return Builder.Buffer; |
114 | } |
115 | |
116 | ConstantAggregateBuilderBase(ConstantInitBuilderBase &builder, |
117 | ConstantAggregateBuilderBase *parent) |
118 | : Builder(builder), Parent(parent), Begin(builder.Buffer.size()) { |
119 | if (parent) { |
120 | (0) . __assert_fail ("!parent->Frozen && \"parent already has child builder active\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 120, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!parent->Frozen && "parent already has child builder active"); |
121 | parent->Frozen = true; |
122 | } else { |
123 | (0) . __assert_fail ("!builder.Frozen && \"builder already has child builder active\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 123, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!builder.Frozen && "builder already has child builder active"); |
124 | builder.Frozen = true; |
125 | } |
126 | } |
127 | |
128 | ~ConstantAggregateBuilderBase() { |
129 | (0) . __assert_fail ("Finished && \"didn't finish aggregate builder\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 129, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Finished && "didn't finish aggregate builder"); |
130 | } |
131 | |
132 | void markFinished() { |
133 | (0) . __assert_fail ("!Frozen && \"child builder still active\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 133, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!Frozen && "child builder still active"); |
134 | (0) . __assert_fail ("!Finished && \"builder already finished\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 134, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!Finished && "builder already finished"); |
135 | Finished = true; |
136 | if (Parent) { |
137 | (0) . __assert_fail ("Parent->Frozen && \"parent not frozen while child builder active\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 138, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Parent->Frozen && |
138 | (0) . __assert_fail ("Parent->Frozen && \"parent not frozen while child builder active\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 138, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "parent not frozen while child builder active"); |
139 | Parent->Frozen = false; |
140 | } else { |
141 | (0) . __assert_fail ("Builder.Frozen && \"builder not frozen while child builder active\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 142, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Builder.Frozen && |
142 | (0) . __assert_fail ("Builder.Frozen && \"builder not frozen while child builder active\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 142, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "builder not frozen while child builder active"); |
143 | Builder.Frozen = false; |
144 | } |
145 | } |
146 | |
147 | public: |
148 | |
149 | ConstantAggregateBuilderBase(const ConstantAggregateBuilderBase &) = delete; |
150 | ConstantAggregateBuilderBase &operator=(const ConstantAggregateBuilderBase &) |
151 | = delete; |
152 | |
153 | |
154 | |
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 | CachedOffsetFromGlobal(other.CachedOffsetFromGlobal) { |
160 | other.Finished = true; |
161 | } |
162 | ConstantAggregateBuilderBase &operator=(ConstantAggregateBuilderBase &&other) |
163 | = delete; |
164 | |
165 | |
166 | |
167 | size_t size() const { |
168 | (0) . __assert_fail ("!this->Finished && \"cannot query after finishing builder\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 168, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!this->Finished && "cannot query after finishing builder"); |
169 | (0) . __assert_fail ("!this->Frozen && \"cannot query while sub-builder is active\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 169, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!this->Frozen && "cannot query while sub-builder is active"); |
170 | Begin <= this->getBuffer().size()", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 170, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(this->Begin <= this->getBuffer().size()); |
171 | return this->getBuffer().size() - this->Begin; |
172 | } |
173 | |
174 | |
175 | bool empty() const { |
176 | return size() == 0; |
177 | } |
178 | |
179 | |
180 | void abandon() { |
181 | markFinished(); |
182 | Builder.abandon(Begin); |
183 | } |
184 | |
185 | |
186 | void add(llvm::Constant *value) { |
187 | (0) . __assert_fail ("value && \"adding null value to constant initializer\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 187, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(value && "adding null value to constant initializer"); |
188 | (0) . __assert_fail ("!Finished && \"cannot add more values after finishing builder\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 188, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!Finished && "cannot add more values after finishing builder"); |
189 | (0) . __assert_fail ("!Frozen && \"cannot add values while subbuilder is active\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 189, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!Frozen && "cannot add values while subbuilder is active"); |
190 | Builder.Buffer.push_back(value); |
191 | } |
192 | |
193 | |
194 | void addSize(CharUnits size); |
195 | |
196 | |
197 | void addInt(llvm::IntegerType *intTy, uint64_t value, |
198 | bool isSigned = false) { |
199 | add(llvm::ConstantInt::get(intTy, value, isSigned)); |
200 | } |
201 | |
202 | |
203 | void addNullPointer(llvm::PointerType *ptrTy) { |
204 | add(llvm::ConstantPointerNull::get(ptrTy)); |
205 | } |
206 | |
207 | |
208 | void addBitCast(llvm::Constant *value, llvm::Type *type) { |
209 | add(llvm::ConstantExpr::getBitCast(value, type)); |
210 | } |
211 | |
212 | |
213 | void addAll(llvm::ArrayRef<llvm::Constant *> values) { |
214 | (0) . __assert_fail ("!Finished && \"cannot add more values after finishing builder\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 214, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!Finished && "cannot add more values after finishing builder"); |
215 | (0) . __assert_fail ("!Frozen && \"cannot add values while subbuilder is active\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 215, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!Frozen && "cannot add values while subbuilder is active"); |
216 | Builder.Buffer.append(values.begin(), values.end()); |
217 | } |
218 | |
219 | |
220 | |
221 | |
222 | |
223 | |
224 | |
225 | void addRelativeOffset(llvm::IntegerType *type, llvm::Constant *target) { |
226 | add(getRelativeOffset(type, target)); |
227 | } |
228 | |
229 | |
230 | |
231 | |
232 | |
233 | void addTaggedRelativeOffset(llvm::IntegerType *type, |
234 | llvm::Constant *address, |
235 | unsigned tag) { |
236 | llvm::Constant *offset = getRelativeOffset(type, address); |
237 | if (tag) { |
238 | offset = llvm::ConstantExpr::getAdd(offset, |
239 | llvm::ConstantInt::get(type, tag)); |
240 | } |
241 | add(offset); |
242 | } |
243 | |
244 | |
245 | |
246 | |
247 | |
248 | |
249 | CharUnits getNextOffsetFromGlobal() const { |
250 | (0) . __assert_fail ("!Finished && \"cannot add more values after finishing builder\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 250, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!Finished && "cannot add more values after finishing builder"); |
251 | (0) . __assert_fail ("!Frozen && \"cannot add values while subbuilder is active\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 251, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!Frozen && "cannot add values while subbuilder is active"); |
252 | return getOffsetFromGlobalTo(Builder.Buffer.size()); |
253 | } |
254 | |
255 | |
256 | class PlaceholderPosition { |
257 | size_t Index; |
258 | friend class ConstantAggregateBuilderBase; |
259 | PlaceholderPosition(size_t index) : Index(index) {} |
260 | }; |
261 | |
262 | |
263 | |
264 | |
265 | |
266 | |
267 | |
268 | |
269 | |
270 | |
271 | PlaceholderPosition addPlaceholder() { |
272 | (0) . __assert_fail ("!Finished && \"cannot add more values after finishing builder\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 272, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!Finished && "cannot add more values after finishing builder"); |
273 | (0) . __assert_fail ("!Frozen && \"cannot add values while subbuilder is active\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 273, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!Frozen && "cannot add values while subbuilder is active"); |
274 | Builder.Buffer.push_back(nullptr); |
275 | return Builder.Buffer.size() - 1; |
276 | } |
277 | |
278 | |
279 | PlaceholderPosition addPlaceholderWithSize(llvm::Type *expectedType); |
280 | |
281 | |
282 | void fillPlaceholderWithInt(PlaceholderPosition position, |
283 | llvm::IntegerType *type, uint64_t value, |
284 | bool isSigned = false) { |
285 | fillPlaceholder(position, llvm::ConstantInt::get(type, value, isSigned)); |
286 | } |
287 | |
288 | |
289 | void fillPlaceholder(PlaceholderPosition position, llvm::Constant *value) { |
290 | (0) . __assert_fail ("!Finished && \"cannot change values after finishing builder\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 290, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!Finished && "cannot change values after finishing builder"); |
291 | (0) . __assert_fail ("!Frozen && \"cannot add values while subbuilder is active\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 291, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!Frozen && "cannot add values while subbuilder is active"); |
292 | llvm::Constant *&slot = Builder.Buffer[position.Index]; |
293 | (0) . __assert_fail ("slot == nullptr && \"placeholder already filled\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 293, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(slot == nullptr && "placeholder already filled"); |
294 | slot = value; |
295 | } |
296 | |
297 | |
298 | |
299 | |
300 | |
301 | |
302 | |
303 | llvm::Constant *getAddrOfCurrentPosition(llvm::Type *type); |
304 | |
305 | llvm::ArrayRef<llvm::Constant*> getGEPIndicesToCurrentPosition( |
306 | llvm::SmallVectorImpl<llvm::Constant*> &indices) { |
307 | getGEPIndicesTo(indices, Builder.Buffer.size()); |
308 | return indices; |
309 | } |
310 | |
311 | protected: |
312 | llvm::Constant *finishArray(llvm::Type *eltTy); |
313 | llvm::Constant *finishStruct(llvm::StructType *structTy); |
314 | |
315 | private: |
316 | void getGEPIndicesTo(llvm::SmallVectorImpl<llvm::Constant*> &indices, |
317 | size_t position) const; |
318 | |
319 | llvm::Constant *getRelativeOffset(llvm::IntegerType *offsetType, |
320 | llvm::Constant *target); |
321 | |
322 | CharUnits getOffsetFromGlobalTo(size_t index) const; |
323 | }; |
324 | |
325 | template <class Impl, class Traits> |
326 | class ConstantAggregateBuilderTemplateBase |
327 | : public Traits::AggregateBuilderBase { |
328 | using super = typename Traits::AggregateBuilderBase; |
329 | public: |
330 | using InitBuilder = typename Traits::InitBuilder; |
331 | using ArrayBuilder = typename Traits::ArrayBuilder; |
332 | using StructBuilder = typename Traits::StructBuilder; |
333 | using AggregateBuilderBase = typename Traits::AggregateBuilderBase; |
334 | |
335 | protected: |
336 | ConstantAggregateBuilderTemplateBase(InitBuilder &builder, |
337 | AggregateBuilderBase *parent) |
338 | : super(builder, parent) {} |
339 | |
340 | Impl &asImpl() { return *static_cast<Impl*>(this); } |
341 | |
342 | public: |
343 | ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) { |
344 | return ArrayBuilder(static_cast<InitBuilder&>(this->Builder), this, eltTy); |
345 | } |
346 | |
347 | StructBuilder beginStruct(llvm::StructType *ty = nullptr) { |
348 | return StructBuilder(static_cast<InitBuilder&>(this->Builder), this, ty); |
349 | } |
350 | |
351 | |
352 | |
353 | |
354 | |
355 | |
356 | |
357 | |
358 | |
359 | |
360 | void finishAndAddTo(AggregateBuilderBase &parent) { |
361 | (0) . __assert_fail ("this->Parent == &parent && \"adding to non-parent builder\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 361, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(this->Parent == &parent && "adding to non-parent builder"); |
362 | parent.add(asImpl().finishImpl()); |
363 | } |
364 | |
365 | |
366 | |
367 | |
368 | template <class... As> |
369 | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { |
370 | (0) . __assert_fail ("!this->Parent && \"finishing non-root builder\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 370, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!this->Parent && "finishing non-root builder"); |
371 | return this->Builder.createGlobal(asImpl().finishImpl(), |
372 | std::forward<As>(args)...); |
373 | } |
374 | |
375 | |
376 | |
377 | |
378 | void finishAndSetAsInitializer(llvm::GlobalVariable *global) { |
379 | (0) . __assert_fail ("!this->Parent && \"finishing non-root builder\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 379, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!this->Parent && "finishing non-root builder"); |
380 | return this->Builder.setGlobalInitializer(global, asImpl().finishImpl()); |
381 | } |
382 | |
383 | |
384 | |
385 | |
386 | |
387 | |
388 | |
389 | |
390 | |
391 | ConstantInitFuture finishAndCreateFuture() { |
392 | (0) . __assert_fail ("!this->Parent && \"finishing non-root builder\"", "/home/seafit/code_projects/clang_source/clang/include/clang/CodeGen/ConstantInitBuilder.h", 392, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!this->Parent && "finishing non-root builder"); |
393 | return this->Builder.createFuture(asImpl().finishImpl()); |
394 | } |
395 | }; |
396 | |
397 | template <class Traits> |
398 | class ConstantArrayBuilderTemplateBase |
399 | : public ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder, |
400 | Traits> { |
401 | using super = |
402 | ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder, Traits>; |
403 | |
404 | public: |
405 | using InitBuilder = typename Traits::InitBuilder; |
406 | using AggregateBuilderBase = typename Traits::AggregateBuilderBase; |
407 | |
408 | private: |
409 | llvm::Type *EltTy; |
410 | |
411 | template <class, class> |
412 | friend class ConstantAggregateBuilderTemplateBase; |
413 | |
414 | protected: |
415 | ConstantArrayBuilderTemplateBase(InitBuilder &builder, |
416 | AggregateBuilderBase *parent, |
417 | llvm::Type *eltTy) |
418 | : super(builder, parent), EltTy(eltTy) {} |
419 | |
420 | private: |
421 | |
422 | |
423 | llvm::Constant *finishImpl() { |
424 | return AggregateBuilderBase::finishArray(EltTy); |
425 | } |
426 | }; |
427 | |
428 | |
429 | |
430 | |
431 | |
432 | |
433 | template <class Traits> |
434 | class ConstantStructBuilderTemplateBase |
435 | : public ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder, |
436 | Traits> { |
437 | using super = |
438 | ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder,Traits>; |
439 | |
440 | public: |
441 | using InitBuilder = typename Traits::InitBuilder; |
442 | using AggregateBuilderBase = typename Traits::AggregateBuilderBase; |
443 | |
444 | private: |
445 | llvm::StructType *StructTy; |
446 | |
447 | template <class, class> |
448 | friend class ConstantAggregateBuilderTemplateBase; |
449 | |
450 | protected: |
451 | ConstantStructBuilderTemplateBase(InitBuilder &builder, |
452 | AggregateBuilderBase *parent, |
453 | llvm::StructType *structTy) |
454 | : super(builder, parent), StructTy(structTy) { |
455 | if (structTy) this->Packed = structTy->isPacked(); |
456 | } |
457 | |
458 | public: |
459 | void setPacked(bool packed) { |
460 | this->Packed = packed; |
461 | } |
462 | |
463 | |
464 | |
465 | void suggestType(llvm::StructType *structTy) { |
466 | if (this->size() == structTy->getNumElements()) { |
467 | StructTy = structTy; |
468 | } |
469 | } |
470 | |
471 | private: |
472 | |
473 | |
474 | llvm::Constant *finishImpl() { |
475 | return AggregateBuilderBase::finishStruct(StructTy); |
476 | } |
477 | }; |
478 | |
479 | |
480 | |
481 | |
482 | |
483 | |
484 | template <class Traits> |
485 | class ConstantInitBuilderTemplateBase : public ConstantInitBuilderBase { |
486 | protected: |
487 | ConstantInitBuilderTemplateBase(CodeGenModule &CGM) |
488 | : ConstantInitBuilderBase(CGM) {} |
489 | |
490 | public: |
491 | using InitBuilder = typename Traits::InitBuilder; |
492 | using ArrayBuilder = typename Traits::ArrayBuilder; |
493 | using StructBuilder = typename Traits::StructBuilder; |
494 | |
495 | ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) { |
496 | return ArrayBuilder(static_cast<InitBuilder&>(*this), nullptr, eltTy); |
497 | } |
498 | |
499 | StructBuilder beginStruct(llvm::StructType *structTy = nullptr) { |
500 | return StructBuilder(static_cast<InitBuilder&>(*this), nullptr, structTy); |
501 | } |
502 | }; |
503 | |
504 | class ConstantInitBuilder; |
505 | class ConstantStructBuilder; |
506 | class ConstantArrayBuilder; |
507 | |
508 | struct ConstantInitBuilderTraits { |
509 | using InitBuilder = ConstantInitBuilder; |
510 | using AggregateBuilderBase = ConstantAggregateBuilderBase; |
511 | using ArrayBuilder = ConstantArrayBuilder; |
512 | using StructBuilder = ConstantStructBuilder; |
513 | }; |
514 | |
515 | |
516 | class ConstantInitBuilder |
517 | : public ConstantInitBuilderTemplateBase<ConstantInitBuilderTraits> { |
518 | public: |
519 | explicit ConstantInitBuilder(CodeGenModule &CGM) : |
520 | ConstantInitBuilderTemplateBase(CGM) {} |
521 | }; |
522 | |
523 | |
524 | |
525 | class ConstantArrayBuilder |
526 | : public ConstantArrayBuilderTemplateBase<ConstantInitBuilderTraits> { |
527 | template <class Traits> |
528 | friend class ConstantInitBuilderTemplateBase; |
529 | |
530 | |
531 | template <class Impl, class Traits> |
532 | friend class CodeGen::ConstantAggregateBuilderTemplateBase; |
533 | |
534 | ConstantArrayBuilder(ConstantInitBuilder &builder, |
535 | ConstantAggregateBuilderBase *parent, |
536 | llvm::Type *eltTy) |
537 | : ConstantArrayBuilderTemplateBase(builder, parent, eltTy) {} |
538 | }; |
539 | |
540 | |
541 | |
542 | class ConstantStructBuilder |
543 | : public ConstantStructBuilderTemplateBase<ConstantInitBuilderTraits> { |
544 | template <class Traits> |
545 | friend class ConstantInitBuilderTemplateBase; |
546 | |
547 | |
548 | template <class Impl, class Traits> |
549 | friend class CodeGen::ConstantAggregateBuilderTemplateBase; |
550 | |
551 | ConstantStructBuilder(ConstantInitBuilder &builder, |
552 | ConstantAggregateBuilderBase *parent, |
553 | llvm::StructType *structTy) |
554 | : ConstantStructBuilderTemplateBase(builder, parent, structTy) {} |
555 | }; |
556 | |
557 | } |
558 | } |
559 | |
560 | #endif |
561 | |