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