|  | //===----- ConstantBuilder.h - Builder for LLVM IR constants ----*- C++ -*-===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This class provides a convenient interface for building complex | 
|  | // global initializers. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef LLVM_CLANG_LIB_CODEGEN_CONSTANTBUILDER_H | 
|  | #define LLVM_CLANG_LIB_CODEGEN_CONSTANTBUILDER_H | 
|  |  | 
|  | #include "llvm/ADT/ArrayRef.h" | 
|  | #include "llvm/ADT/SmallVector.h" | 
|  | #include "llvm/IR/Constants.h" | 
|  |  | 
|  | #include "CodeGenModule.h" | 
|  |  | 
|  | #include <vector> | 
|  |  | 
|  | namespace clang { | 
|  | namespace CodeGen { | 
|  |  | 
|  | class ConstantStructBuilder; | 
|  | class ConstantArrayBuilder; | 
|  |  | 
|  | /// A convenience builder class for complex constant initializers, | 
|  | /// especially for anonymous global structures used by various language | 
|  | /// runtimes. | 
|  | /// | 
|  | /// The basic usage pattern is expected to be something like: | 
|  | ///    ConstantInitBuilder builder(CGM); | 
|  | ///    auto toplevel = builder.beginStruct(); | 
|  | ///    toplevel.addInt(CGM.SizeTy, widgets.size()); | 
|  | ///    auto widgetArray = builder.beginArray(); | 
|  | ///    for (auto &widget : widgets) { | 
|  | ///      auto widgetDesc = widgetArray.beginStruct(); | 
|  | ///      widgetDesc.addInt(CGM.SizeTy, widget.getPower()); | 
|  | ///      widgetDesc.add(CGM.GetAddrOfConstantString(widget.getName())); | 
|  | ///      widgetDesc.add(CGM.GetAddrOfGlobal(widget.getInitializerDecl())); | 
|  | ///      widgetArray.add(widgetDesc.finish()); | 
|  | ///    } | 
|  | ///    toplevel.add(widgetArray.finish()); | 
|  | ///    auto global = toplevel.finishAndCreateGlobal("WIDGET_LIST", Align, | 
|  | ///                                                 /*constant*/ true); | 
|  | class ConstantInitBuilder { | 
|  | struct SelfReference { | 
|  | llvm::GlobalVariable *Dummy; | 
|  | llvm::SmallVector<llvm::Constant*, 4> Indices; | 
|  |  | 
|  | SelfReference(llvm::GlobalVariable *dummy) : Dummy(dummy) {} | 
|  | }; | 
|  | CodeGenModule &CGM; | 
|  | llvm::SmallVector<llvm::Constant*, 16> Buffer; | 
|  | std::vector<SelfReference> SelfReferences; | 
|  | bool Frozen = false; | 
|  |  | 
|  | public: | 
|  | explicit ConstantInitBuilder(CodeGenModule &CGM) : CGM(CGM) {} | 
|  |  | 
|  | ~ConstantInitBuilder() { | 
|  | assert(Buffer.empty() && "didn't claim all values out of buffer"); | 
|  | } | 
|  |  | 
|  | class AggregateBuilderBase { | 
|  | protected: | 
|  | ConstantInitBuilder &Builder; | 
|  | AggregateBuilderBase *Parent; | 
|  | size_t Begin; | 
|  | bool Finished = false; | 
|  | bool Frozen = false; | 
|  |  | 
|  | llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() { | 
|  | return Builder.Buffer; | 
|  | } | 
|  |  | 
|  | const llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() const { | 
|  | return Builder.Buffer; | 
|  | } | 
|  |  | 
|  | AggregateBuilderBase(ConstantInitBuilder &builder, | 
|  | AggregateBuilderBase *parent) | 
|  | : Builder(builder), Parent(parent), Begin(builder.Buffer.size()) { | 
|  | if (parent) { | 
|  | assert(!parent->Frozen && "parent already has child builder active"); | 
|  | parent->Frozen = true; | 
|  | } else { | 
|  | assert(!builder.Frozen && "builder already has child builder active"); | 
|  | builder.Frozen = true; | 
|  | } | 
|  | } | 
|  |  | 
|  | ~AggregateBuilderBase() { | 
|  | assert(Finished && "didn't finish aggregate builder"); | 
|  | } | 
|  |  | 
|  | void markFinished() { | 
|  | assert(!Frozen && "child builder still active"); | 
|  | assert(!Finished && "builder already finished"); | 
|  | Finished = true; | 
|  | if (Parent) { | 
|  | assert(Parent->Frozen && | 
|  | "parent not frozen while child builder active"); | 
|  | Parent->Frozen = false; | 
|  | } else { | 
|  | assert(Builder.Frozen && | 
|  | "builder not frozen while child builder active"); | 
|  | Builder.Frozen = false; | 
|  | } | 
|  | } | 
|  |  | 
|  | public: | 
|  | // Not copyable. | 
|  | AggregateBuilderBase(const AggregateBuilderBase &) = delete; | 
|  | AggregateBuilderBase &operator=(const AggregateBuilderBase &) = delete; | 
|  |  | 
|  | // Movable, mostly to allow returning.  But we have to write this out | 
|  | // properly to satisfy the assert in the destructor. | 
|  | AggregateBuilderBase(AggregateBuilderBase &&other) | 
|  | : Builder(other.Builder), Parent(other.Parent), Begin(other.Begin), | 
|  | Finished(other.Finished), Frozen(other.Frozen) { | 
|  | other.Finished = false; | 
|  | } | 
|  | AggregateBuilderBase &operator=(AggregateBuilderBase &&other) = delete; | 
|  |  | 
|  | /// Abandon this builder completely. | 
|  | void abandon() { | 
|  | markFinished(); | 
|  | auto &buffer = Builder.Buffer; | 
|  | buffer.erase(buffer.begin() + Begin, buffer.end()); | 
|  | } | 
|  |  | 
|  | /// Add a new value to this initializer. | 
|  | void add(llvm::Constant *value) { | 
|  | assert(value && "adding null value to constant initializer"); | 
|  | assert(!Finished && "cannot add more values after finishing builder"); | 
|  | assert(!Frozen && "cannot add values while subbuilder is active"); | 
|  | Builder.Buffer.push_back(value); | 
|  | } | 
|  |  | 
|  | /// Add an integer value of type size_t. | 
|  | void addSize(CharUnits size) { | 
|  | add(Builder.CGM.getSize(size)); | 
|  | } | 
|  |  | 
|  | /// Add an integer value of a specific type. | 
|  | void addInt(llvm::IntegerType *intTy, uint64_t value, | 
|  | bool isSigned = false) { | 
|  | add(llvm::ConstantInt::get(intTy, value, isSigned)); | 
|  | } | 
|  |  | 
|  | /// Add a null pointer of a specific type. | 
|  | void addNullPointer(llvm::PointerType *ptrTy) { | 
|  | add(llvm::ConstantPointerNull::get(ptrTy)); | 
|  | } | 
|  |  | 
|  | /// Add a bitcast of a value to a specific type. | 
|  | void addBitCast(llvm::Constant *value, llvm::Type *type) { | 
|  | add(llvm::ConstantExpr::getBitCast(value, type)); | 
|  | } | 
|  |  | 
|  | /// Add a bunch of new values to this initializer. | 
|  | void addAll(ArrayRef<llvm::Constant *> values) { | 
|  | assert(!Finished && "cannot add more values after finishing builder"); | 
|  | assert(!Frozen && "cannot add values while subbuilder is active"); | 
|  | Builder.Buffer.append(values.begin(), values.end()); | 
|  | } | 
|  |  | 
|  | /// An opaque class to hold the abstract position of a placeholder. | 
|  | class PlaceholderPosition { | 
|  | size_t Index; | 
|  | friend class AggregateBuilderBase; | 
|  | PlaceholderPosition(size_t index) : Index(index) {} | 
|  | }; | 
|  |  | 
|  | /// Add a placeholder value to the structure.  The returned position | 
|  | /// can be used to set the value later; it will not be invalidated by | 
|  | /// any intermediate operations except (1) filling the same position or | 
|  | /// (2) finishing the entire builder. | 
|  | /// | 
|  | /// This is useful for emitting certain kinds of structure which | 
|  | /// contain some sort of summary field, generaly a count, before any | 
|  | /// of the data.  By emitting a placeholder first, the structure can | 
|  | /// be emitted eagerly. | 
|  | PlaceholderPosition addPlaceholder() { | 
|  | assert(!Finished && "cannot add more values after finishing builder"); | 
|  | assert(!Frozen && "cannot add values while subbuilder is active"); | 
|  | Builder.Buffer.push_back(nullptr); | 
|  | return Builder.Buffer.size() - 1; | 
|  | } | 
|  |  | 
|  | /// Fill a previously-added placeholder. | 
|  | void fillPlaceholderWithInt(PlaceholderPosition position, | 
|  | llvm::IntegerType *type, uint64_t value, | 
|  | bool isSigned = false) { | 
|  | fillPlaceholder(position, llvm::ConstantInt::get(type, value, isSigned)); | 
|  | } | 
|  |  | 
|  | /// Fill a previously-added placeholder. | 
|  | void fillPlaceholder(PlaceholderPosition position, llvm::Constant *value) { | 
|  | assert(!Finished && "cannot change values after finishing builder"); | 
|  | assert(!Frozen && "cannot add values while subbuilder is active"); | 
|  | llvm::Constant *&slot = Builder.Buffer[position.Index]; | 
|  | assert(slot == nullptr && "placeholder already filled"); | 
|  | slot = value; | 
|  | } | 
|  |  | 
|  | /// Produce an address which will eventually point to the the next | 
|  | /// position to be filled.  This is computed with an indexed | 
|  | /// getelementptr rather than by computing offsets. | 
|  | /// | 
|  | /// The returned pointer will have type T*, where T is the given | 
|  | /// position. | 
|  | llvm::Constant *getAddrOfCurrentPosition(llvm::Type *type) { | 
|  | // Make a global variable.  We will replace this with a GEP to this | 
|  | // position after installing the initializer. | 
|  | auto dummy = | 
|  | new llvm::GlobalVariable(Builder.CGM.getModule(), type, true, | 
|  | llvm::GlobalVariable::PrivateLinkage, | 
|  | nullptr, ""); | 
|  | Builder.SelfReferences.emplace_back(dummy); | 
|  | auto &entry = Builder.SelfReferences.back(); | 
|  | (void) getGEPIndicesToCurrentPosition(entry.Indices); | 
|  | return dummy; | 
|  | } | 
|  |  | 
|  | ArrayRef<llvm::Constant*> getGEPIndicesToCurrentPosition( | 
|  | llvm::SmallVectorImpl<llvm::Constant*> &indices) { | 
|  | getGEPIndicesTo(indices, Builder.Buffer.size()); | 
|  | return indices; | 
|  | } | 
|  |  | 
|  | ConstantArrayBuilder beginArray(llvm::Type *eltTy = nullptr); | 
|  | ConstantStructBuilder beginStruct(llvm::StructType *structTy = nullptr); | 
|  |  | 
|  | private: | 
|  | void getGEPIndicesTo(llvm::SmallVectorImpl<llvm::Constant*> &indices, | 
|  | size_t position) const { | 
|  | // Recurse on the parent builder if present. | 
|  | if (Parent) { | 
|  | Parent->getGEPIndicesTo(indices, Begin); | 
|  |  | 
|  | // Otherwise, add an index to drill into the first level of pointer. | 
|  | } else { | 
|  | assert(indices.empty()); | 
|  | indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty, 0)); | 
|  | } | 
|  |  | 
|  | assert(position >= Begin); | 
|  | // We have to use i32 here because struct GEPs demand i32 indices. | 
|  | // It's rather unlikely to matter in practice. | 
|  | indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty, | 
|  | position - Begin)); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <class Impl> | 
|  | class AggregateBuilder : public AggregateBuilderBase { | 
|  | protected: | 
|  | AggregateBuilder(ConstantInitBuilder &builder, | 
|  | AggregateBuilderBase *parent) | 
|  | : AggregateBuilderBase(builder, parent) {} | 
|  |  | 
|  | Impl &asImpl() { return *static_cast<Impl*>(this); } | 
|  |  | 
|  | public: | 
|  | /// Given that this builder was created by beginning an array or struct | 
|  | /// component on the given parent builder, finish the array/struct | 
|  | /// component and add it to the parent. | 
|  | /// | 
|  | /// It is an intentional choice that the parent is passed in explicitly | 
|  | /// despite it being redundant with information already kept in the | 
|  | /// builder.  This aids in readability by making it easier to find the | 
|  | /// places that add components to a builder, as well as "bookending" | 
|  | /// the sub-builder more explicitly. | 
|  | void finishAndAddTo(AggregateBuilderBase &parent) { | 
|  | assert(Parent == &parent && "adding to non-parent builder"); | 
|  | parent.add(asImpl().finishImpl()); | 
|  | } | 
|  |  | 
|  | /// Given that this builder was created by beginning an array or struct | 
|  | /// directly on a ConstantInitBuilder, finish the array/struct and | 
|  | /// create a global variable with it as the initializer. | 
|  | template <class... As> | 
|  | llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) { | 
|  | assert(!Parent && "finishing non-root builder"); | 
|  | return Builder.createGlobal(asImpl().finishImpl(), | 
|  | std::forward<As>(args)...); | 
|  | } | 
|  |  | 
|  | /// Given that this builder was created by beginning an array or struct | 
|  | /// directly on a ConstantInitBuilder, finish the array/struct and | 
|  | /// set it as the initializer of the given global variable. | 
|  | void finishAndSetAsInitializer(llvm::GlobalVariable *global) { | 
|  | assert(!Parent && "finishing non-root builder"); | 
|  | return Builder.setGlobalInitializer(global, asImpl().finishImpl()); | 
|  | } | 
|  | }; | 
|  |  | 
|  | ConstantArrayBuilder beginArray(llvm::Type *eltTy = nullptr); | 
|  |  | 
|  | ConstantStructBuilder beginStruct(llvm::StructType *structTy = nullptr); | 
|  |  | 
|  | private: | 
|  | llvm::GlobalVariable *createGlobal(llvm::Constant *initializer, | 
|  | const llvm::Twine &name, | 
|  | CharUnits alignment, | 
|  | bool constant = false, | 
|  | llvm::GlobalValue::LinkageTypes linkage | 
|  | = llvm::GlobalValue::InternalLinkage, | 
|  | unsigned addressSpace = 0) { | 
|  | auto GV = new llvm::GlobalVariable(CGM.getModule(), | 
|  | initializer->getType(), | 
|  | constant, | 
|  | linkage, | 
|  | initializer, | 
|  | name, | 
|  | /*insert before*/ nullptr, | 
|  | llvm::GlobalValue::NotThreadLocal, | 
|  | addressSpace); | 
|  | GV->setAlignment(alignment.getQuantity()); | 
|  | resolveSelfReferences(GV); | 
|  | return GV; | 
|  | } | 
|  |  | 
|  | void setGlobalInitializer(llvm::GlobalVariable *GV, | 
|  | llvm::Constant *initializer) { | 
|  | GV->setInitializer(initializer); | 
|  | resolveSelfReferences(GV); | 
|  | } | 
|  |  | 
|  | void resolveSelfReferences(llvm::GlobalVariable *GV) { | 
|  | for (auto &entry : SelfReferences) { | 
|  | llvm::Constant *resolvedReference = | 
|  | llvm::ConstantExpr::getInBoundsGetElementPtr( | 
|  | GV->getValueType(), GV, entry.Indices); | 
|  | entry.Dummy->replaceAllUsesWith(resolvedReference); | 
|  | entry.Dummy->eraseFromParent(); | 
|  | } | 
|  | } | 
|  | }; | 
|  |  | 
|  | /// A helper class of ConstantInitBuilder, used for building constant | 
|  | /// array initializers. | 
|  | class ConstantArrayBuilder | 
|  | : public ConstantInitBuilder::AggregateBuilder<ConstantArrayBuilder> { | 
|  | llvm::Type *EltTy; | 
|  | friend class ConstantInitBuilder; | 
|  | template <class Impl> friend class ConstantInitBuilder::AggregateBuilder; | 
|  | ConstantArrayBuilder(ConstantInitBuilder &builder, | 
|  | AggregateBuilderBase *parent, llvm::Type *eltTy) | 
|  | : AggregateBuilder(builder, parent), EltTy(eltTy) {} | 
|  | public: | 
|  | size_t size() const { | 
|  | assert(!Finished); | 
|  | assert(!Frozen); | 
|  | assert(Begin <= getBuffer().size()); | 
|  | return getBuffer().size() - Begin; | 
|  | } | 
|  |  | 
|  | bool empty() const { | 
|  | return size() == 0; | 
|  | } | 
|  |  | 
|  | private: | 
|  | /// Form an array constant from the values that have been added to this | 
|  | /// builder. | 
|  | llvm::Constant *finishImpl() { | 
|  | markFinished(); | 
|  |  | 
|  | auto &buffer = getBuffer(); | 
|  | assert((Begin < buffer.size() || | 
|  | (Begin == buffer.size() && EltTy)) | 
|  | && "didn't add any array elements without element type"); | 
|  | auto elts = llvm::makeArrayRef(buffer).slice(Begin); | 
|  | auto eltTy = EltTy ? EltTy : elts[0]->getType(); | 
|  | auto type = llvm::ArrayType::get(eltTy, elts.size()); | 
|  | auto constant = llvm::ConstantArray::get(type, elts); | 
|  | buffer.erase(buffer.begin() + Begin, buffer.end()); | 
|  | return constant; | 
|  | } | 
|  | }; | 
|  |  | 
|  | inline ConstantArrayBuilder | 
|  | ConstantInitBuilder::beginArray(llvm::Type *eltTy) { | 
|  | return ConstantArrayBuilder(*this, nullptr, eltTy); | 
|  | } | 
|  |  | 
|  | inline ConstantArrayBuilder | 
|  | ConstantInitBuilder::AggregateBuilderBase::beginArray(llvm::Type *eltTy) { | 
|  | return ConstantArrayBuilder(Builder, this, eltTy); | 
|  | } | 
|  |  | 
|  | /// A helper class of ConstantInitBuilder, used for building constant | 
|  | /// struct initializers. | 
|  | class ConstantStructBuilder | 
|  | : public ConstantInitBuilder::AggregateBuilder<ConstantStructBuilder> { | 
|  | llvm::StructType *Ty; | 
|  | friend class ConstantInitBuilder; | 
|  | template <class Impl> friend class ConstantInitBuilder::AggregateBuilder; | 
|  | ConstantStructBuilder(ConstantInitBuilder &builder, | 
|  | AggregateBuilderBase *parent, llvm::StructType *ty) | 
|  | : AggregateBuilder(builder, parent), Ty(ty) {} | 
|  |  | 
|  | /// Finish the struct. | 
|  | llvm::Constant *finishImpl() { | 
|  | markFinished(); | 
|  |  | 
|  | auto &buffer = getBuffer(); | 
|  | assert(Begin < buffer.size() && "didn't add any struct elements?"); | 
|  | auto elts = llvm::makeArrayRef(buffer).slice(Begin); | 
|  |  | 
|  | llvm::Constant *constant; | 
|  | if (Ty) { | 
|  | constant = llvm::ConstantStruct::get(Ty, elts); | 
|  | } else { | 
|  | constant = llvm::ConstantStruct::getAnon(elts, /*packed*/ false); | 
|  | } | 
|  |  | 
|  | buffer.erase(buffer.begin() + Begin, buffer.end()); | 
|  | return constant; | 
|  | } | 
|  | }; | 
|  |  | 
|  | inline ConstantStructBuilder | 
|  | ConstantInitBuilder::beginStruct(llvm::StructType *structTy) { | 
|  | return ConstantStructBuilder(*this, nullptr, structTy); | 
|  | } | 
|  |  | 
|  | inline ConstantStructBuilder | 
|  | ConstantInitBuilder::AggregateBuilderBase::beginStruct( | 
|  | llvm::StructType *structTy) { | 
|  | return ConstantStructBuilder(Builder, this, structTy); | 
|  | } | 
|  |  | 
|  | }  // end namespace CodeGen | 
|  | }  // end namespace clang | 
|  |  | 
|  | #endif |