Home | History | Annotate | Download | only in CodeGen
      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 
     57     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:
     70   explicit ConstantInitBuilderBase(CodeGenModule &CGM) : CGM(CGM) {}
     71 
     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 
    109   llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() {
    110     return Builder.Buffer;
    111   }
    112 
    113   const llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() const {
    114     return Builder.Buffer;
    115   }
    116 
    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 
    129   ~ConstantAggregateBuilderBase() {
    130     assert(Finished && "didn't finish aggregate builder");
    131   }
    132 
    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.
    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.
    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.
    176   bool empty() const {
    177     return size() == 0;
    178   }
    179 
    180   /// Abandon this builder completely.
    181   void abandon() {
    182     markFinished();
    183     Builder.abandon(Begin);
    184   }
    185 
    186   /// Add a new value to this initializer.
    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.
    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.
    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.
    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.
    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.
    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.
    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;
    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, generaly a count, before any
    270   /// of the data.  By emitting a placeholder first, the structure can
    271   /// be emitted eagerly.
    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.
    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 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 
    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:
    337   ConstantAggregateBuilderTemplateBase(InitBuilder &builder,
    338                                        AggregateBuilderBase *parent)
    339     : super(builder, parent) {}
    340 
    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.
    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>
    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.
    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.
    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:
    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.
    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:
    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:
    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.
    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.
    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:
    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:
    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 
    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 
    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