Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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