diff options
Diffstat (limited to 'include/clang/CodeGen')
-rw-r--r-- | include/clang/CodeGen/BackendUtil.h | 5 | ||||
-rw-r--r-- | include/clang/CodeGen/CodeGenABITypes.h | 2 | ||||
-rw-r--r-- | include/clang/CodeGen/CodeGenAction.h | 35 | ||||
-rw-r--r-- | include/clang/CodeGen/ConstantInitBuilder.h | 561 | ||||
-rw-r--r-- | include/clang/CodeGen/ConstantInitFuture.h | 111 | ||||
-rw-r--r-- | include/clang/CodeGen/ModuleBuilder.h | 4 |
6 files changed, 707 insertions, 11 deletions
diff --git a/include/clang/CodeGen/BackendUtil.h b/include/clang/CodeGen/BackendUtil.h index c6abc6e3f574..bb105cb533a4 100644 --- a/include/clang/CodeGen/BackendUtil.h +++ b/include/clang/CodeGen/BackendUtil.h @@ -15,6 +15,8 @@ #include <memory> namespace llvm { + class BitcodeModule; + template <typename T> class Expected; class Module; class MemoryBufferRef; } @@ -44,6 +46,9 @@ namespace clang { void EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts, llvm::MemoryBufferRef Buf); + + llvm::Expected<llvm::BitcodeModule> + FindThinLTOModule(llvm::MemoryBufferRef MBRef); } #endif diff --git a/include/clang/CodeGen/CodeGenABITypes.h b/include/clang/CodeGen/CodeGenABITypes.h index e7b7435968fb..8ba769dfc3af 100644 --- a/include/clang/CodeGen/CodeGenABITypes.h +++ b/include/clang/CodeGen/CodeGenABITypes.h @@ -16,7 +16,7 @@ // // It allows other clients, like LLDB, to determine the LLVM types that are // actually used in function calls, which makes it possible to then determine -// the acutal ABI locations (e.g. registers, stack locations, etc.) that +// the actual ABI locations (e.g. registers, stack locations, etc.) that // these parameters are stored in. // //===----------------------------------------------------------------------===// diff --git a/include/clang/CodeGen/CodeGenAction.h b/include/clang/CodeGen/CodeGenAction.h index cc38e243420b..5a18a9de030b 100644 --- a/include/clang/CodeGen/CodeGenAction.h +++ b/include/clang/CodeGen/CodeGenAction.h @@ -23,14 +23,36 @@ class BackendConsumer; class CodeGenAction : public ASTFrontendAction { private: + // Let BackendConsumer access LinkModule. + friend class BackendConsumer; + + /// Info about module to link into a module we're generating. + struct LinkModule { + /// The module to link in. + std::unique_ptr<llvm::Module> Module; + + /// If true, we set attributes on Module's functions according to our + /// CodeGenOptions and LangOptions, as though we were generating the + /// function ourselves. + bool PropagateAttrs; + + /// If true, we use LLVM module internalizer. + bool Internalize; + + /// Bitwise combination of llvm::LinkerFlags used when we link the module. + unsigned LinkFlags; + }; + unsigned Act; std::unique_ptr<llvm::Module> TheModule; - // Vector of {Linker::Flags, Module*} pairs to specify bitcode - // modules to link in using corresponding linker flags. - SmallVector<std::pair<unsigned, llvm::Module *>, 4> LinkModules; + + /// Bitcode modules to link in to our module. + SmallVector<LinkModule, 4> LinkModules; llvm::LLVMContext *VMContext; bool OwnsVMContext; + std::unique_ptr<llvm::Module> loadModule(llvm::MemoryBufferRef MBRef); + protected: /// Create a new code generation action. If the optional \p _VMContext /// parameter is supplied, the action uses it without taking ownership, @@ -49,13 +71,6 @@ protected: public: ~CodeGenAction() override; - /// setLinkModule - Set the link module to be used by this action. If a link - /// module is not provided, and CodeGenOptions::LinkBitcodeFile is non-empty, - /// the action will load it from the specified file. - void addLinkModule(llvm::Module *Mod, unsigned LinkFlags) { - LinkModules.push_back(std::make_pair(LinkFlags, Mod)); - } - /// Take the generated LLVM module, for use after the action has been run. /// The result may be null on failure. std::unique_ptr<llvm::Module> takeModule(); diff --git a/include/clang/CodeGen/ConstantInitBuilder.h b/include/clang/CodeGen/ConstantInitBuilder.h new file mode 100644 index 000000000000..113d86d82c10 --- /dev/null +++ b/include/clang/CodeGen/ConstantInitBuilder.h @@ -0,0 +1,561 @@ +//===- ConstantInitBuilder.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 of the sort that are frequently required for +// language ABIs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H +#define LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/GlobalValue.h" +#include "clang/AST/CharUnits.h" +#include "clang/CodeGen/ConstantInitFuture.h" + +#include <vector> + +namespace clang { +namespace CodeGen { + +class CodeGenModule; + +/// 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())); +/// widgetDesc.finishAndAddTo(widgetArray); +/// } +/// widgetArray.finishAndAddTo(toplevel); +/// auto global = toplevel.finishAndCreateGlobal("WIDGET_LIST", Align, +/// /*constant*/ true); +class ConstantInitBuilderBase { + 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; + + friend class ConstantInitFuture; + friend class ConstantAggregateBuilderBase; + template <class, class> + friend class ConstantAggregateBuilderTemplateBase; + +protected: + explicit ConstantInitBuilderBase(CodeGenModule &CGM) : CGM(CGM) {} + + ~ConstantInitBuilderBase() { + assert(Buffer.empty() && "didn't claim all values out of buffer"); + assert(SelfReferences.empty() && "didn't apply all self-references"); + } + +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); + + ConstantInitFuture createFuture(llvm::Constant *initializer); + + void setGlobalInitializer(llvm::GlobalVariable *GV, + llvm::Constant *initializer); + + void resolveSelfReferences(llvm::GlobalVariable *GV); + + void abandon(size_t newEnd); +}; + +/// A concrete base class for struct and array aggregate +/// initializer builders. +class ConstantAggregateBuilderBase { +protected: + ConstantInitBuilderBase &Builder; + ConstantAggregateBuilderBase *Parent; + size_t Begin; + mutable size_t CachedOffsetEnd = 0; + bool Finished = false; + bool Frozen = false; + bool Packed = false; + mutable CharUnits CachedOffsetFromGlobal; + + llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() { + return Builder.Buffer; + } + + const llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() const { + return Builder.Buffer; + } + + ConstantAggregateBuilderBase(ConstantInitBuilderBase &builder, + ConstantAggregateBuilderBase *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; + } + } + + ~ConstantAggregateBuilderBase() { + 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. + ConstantAggregateBuilderBase(const ConstantAggregateBuilderBase &) = delete; + ConstantAggregateBuilderBase &operator=(const ConstantAggregateBuilderBase &) + = delete; + + // Movable, mostly to allow returning. But we have to write this out + // properly to satisfy the assert in the destructor. + ConstantAggregateBuilderBase(ConstantAggregateBuilderBase &&other) + : Builder(other.Builder), Parent(other.Parent), Begin(other.Begin), + CachedOffsetEnd(other.CachedOffsetEnd), + Finished(other.Finished), Frozen(other.Frozen), Packed(other.Packed), + CachedOffsetFromGlobal(other.CachedOffsetFromGlobal) { + other.Finished = true; + } + ConstantAggregateBuilderBase &operator=(ConstantAggregateBuilderBase &&other) + = delete; + + /// Return the number of elements that have been added to + /// this struct or array. + size_t size() const { + assert(!this->Finished && "cannot query after finishing builder"); + assert(!this->Frozen && "cannot query while sub-builder is active"); + assert(this->Begin <= this->getBuffer().size()); + return this->getBuffer().size() - this->Begin; + } + + /// Return true if no elements have yet been added to this struct or array. + bool empty() const { + return size() == 0; + } + + /// Abandon this builder completely. + void abandon() { + markFinished(); + Builder.abandon(Begin); + } + + /// 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 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(llvm::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()); + } + + /// Add a relative offset to the given target address, i.e. the + /// static difference between the target address and the address + /// of the relative offset. The target must be known to be defined + /// in the current linkage unit. The offset will have the given + /// integer type, which must be no wider than intptr_t. Some + /// targets may not fully support this operation. + void addRelativeOffset(llvm::IntegerType *type, llvm::Constant *target) { + add(getRelativeOffset(type, target)); + } + + /// Add a relative offset to the target address, plus a small + /// constant offset. This is primarily useful when the relative + /// offset is known to be a multiple of (say) four and therefore + /// the tag can be used to express an extra two bits of information. + void addTaggedRelativeOffset(llvm::IntegerType *type, + llvm::Constant *address, + unsigned tag) { + llvm::Constant *offset = getRelativeOffset(type, address); + if (tag) { + offset = llvm::ConstantExpr::getAdd(offset, + llvm::ConstantInt::get(type, tag)); + } + add(offset); + } + + /// Return the offset from the start of the initializer to the + /// next position, assuming no padding is required prior to it. + /// + /// This operation will not succeed if any unsized placeholders are + /// currently in place in the initializer. + CharUnits getNextOffsetFromGlobal() const { + assert(!Finished && "cannot add more values after finishing builder"); + assert(!Frozen && "cannot add values while subbuilder is active"); + return getOffsetFromGlobalTo(Builder.Buffer.size()); + } + + /// An opaque class to hold the abstract position of a placeholder. + class PlaceholderPosition { + size_t Index; + friend class ConstantAggregateBuilderBase; + 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; + } + + /// Add a placeholder, giving the expected type that will be filled in. + PlaceholderPosition addPlaceholderWithSize(llvm::Type *expectedType); + + /// 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); + + llvm::ArrayRef<llvm::Constant*> getGEPIndicesToCurrentPosition( + llvm::SmallVectorImpl<llvm::Constant*> &indices) { + getGEPIndicesTo(indices, Builder.Buffer.size()); + return indices; + } + +protected: + llvm::Constant *finishArray(llvm::Type *eltTy); + llvm::Constant *finishStruct(llvm::StructType *structTy); + +private: + void getGEPIndicesTo(llvm::SmallVectorImpl<llvm::Constant*> &indices, + size_t position) const; + + llvm::Constant *getRelativeOffset(llvm::IntegerType *offsetType, + llvm::Constant *target); + + CharUnits getOffsetFromGlobalTo(size_t index) const; +}; + +template <class Impl, class Traits> +class ConstantAggregateBuilderTemplateBase + : public Traits::AggregateBuilderBase { + using super = typename Traits::AggregateBuilderBase; +public: + using InitBuilder = typename Traits::InitBuilder; + using ArrayBuilder = typename Traits::ArrayBuilder; + using StructBuilder = typename Traits::StructBuilder; + using AggregateBuilderBase = typename Traits::AggregateBuilderBase; + +protected: + ConstantAggregateBuilderTemplateBase(InitBuilder &builder, + AggregateBuilderBase *parent) + : super(builder, parent) {} + + Impl &asImpl() { return *static_cast<Impl*>(this); } + +public: + ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) { + return ArrayBuilder(static_cast<InitBuilder&>(this->Builder), this, eltTy); + } + + StructBuilder beginStruct(llvm::StructType *ty = nullptr) { + return StructBuilder(static_cast<InitBuilder&>(this->Builder), this, ty); + } + + /// 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(this->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(!this->Parent && "finishing non-root builder"); + return this->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(!this->Parent && "finishing non-root builder"); + return this->Builder.setGlobalInitializer(global, asImpl().finishImpl()); + } + + /// Given that this builder was created by beginning an array or struct + /// directly on a ConstantInitBuilder, finish the array/struct and + /// return a future which can be used to install the initializer in + /// a global later. + /// + /// This is useful for allowing a finished initializer to passed to + /// an API which will build the global. However, the "future" preserves + /// a dependency on the original builder; it is an error to pass it aside. + ConstantInitFuture finishAndCreateFuture() { + assert(!this->Parent && "finishing non-root builder"); + return this->Builder.createFuture(asImpl().finishImpl()); + } +}; + +template <class Traits> +class ConstantArrayBuilderTemplateBase + : public ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder, + Traits> { + using super = + ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder, Traits>; + +public: + using InitBuilder = typename Traits::InitBuilder; + using AggregateBuilderBase = typename Traits::AggregateBuilderBase; + +private: + llvm::Type *EltTy; + + template <class, class> + friend class ConstantAggregateBuilderTemplateBase; + +protected: + ConstantArrayBuilderTemplateBase(InitBuilder &builder, + AggregateBuilderBase *parent, + llvm::Type *eltTy) + : super(builder, parent), EltTy(eltTy) {} + +private: + /// Form an array constant from the values that have been added to this + /// builder. + llvm::Constant *finishImpl() { + return AggregateBuilderBase::finishArray(EltTy); + } +}; + +/// A template class designed to allow other frontends to +/// easily customize the builder classes used by ConstantInitBuilder, +/// and thus to extend the API to work with the abstractions they +/// prefer. This would probably not be necessary if C++ just +/// supported extension methods. +template <class Traits> +class ConstantStructBuilderTemplateBase + : public ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder, + Traits> { + using super = + ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder,Traits>; + +public: + using InitBuilder = typename Traits::InitBuilder; + using AggregateBuilderBase = typename Traits::AggregateBuilderBase; + +private: + llvm::StructType *StructTy; + + template <class, class> + friend class ConstantAggregateBuilderTemplateBase; + +protected: + ConstantStructBuilderTemplateBase(InitBuilder &builder, + AggregateBuilderBase *parent, + llvm::StructType *structTy) + : super(builder, parent), StructTy(structTy) { + if (structTy) this->Packed = structTy->isPacked(); + } + +public: + void setPacked(bool packed) { + this->Packed = packed; + } + + /// Use the given type for the struct if its element count is correct. + /// Don't add more elements after calling this. + void suggestType(llvm::StructType *structTy) { + if (this->size() == structTy->getNumElements()) { + StructTy = structTy; + } + } + +private: + /// Form an array constant from the values that have been added to this + /// builder. + llvm::Constant *finishImpl() { + return AggregateBuilderBase::finishStruct(StructTy); + } +}; + +/// A template class designed to allow other frontends to +/// easily customize the builder classes used by ConstantInitBuilder, +/// and thus to extend the API to work with the abstractions they +/// prefer. This would probably not be necessary if C++ just +/// supported extension methods. +template <class Traits> +class ConstantInitBuilderTemplateBase : public ConstantInitBuilderBase { +protected: + ConstantInitBuilderTemplateBase(CodeGenModule &CGM) + : ConstantInitBuilderBase(CGM) {} + +public: + using InitBuilder = typename Traits::InitBuilder; + using ArrayBuilder = typename Traits::ArrayBuilder; + using StructBuilder = typename Traits::StructBuilder; + + ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) { + return ArrayBuilder(static_cast<InitBuilder&>(*this), nullptr, eltTy); + } + + StructBuilder beginStruct(llvm::StructType *structTy = nullptr) { + return StructBuilder(static_cast<InitBuilder&>(*this), nullptr, structTy); + } +}; + +class ConstantInitBuilder; +class ConstantStructBuilder; +class ConstantArrayBuilder; + +struct ConstantInitBuilderTraits { + using InitBuilder = ConstantInitBuilder; + using AggregateBuilderBase = ConstantAggregateBuilderBase; + using ArrayBuilder = ConstantArrayBuilder; + using StructBuilder = ConstantStructBuilder; +}; + +/// The standard implementation of ConstantInitBuilder used in Clang. +class ConstantInitBuilder + : public ConstantInitBuilderTemplateBase<ConstantInitBuilderTraits> { +public: + explicit ConstantInitBuilder(CodeGenModule &CGM) : + ConstantInitBuilderTemplateBase(CGM) {} +}; + +/// A helper class of ConstantInitBuilder, used for building constant +/// array initializers. +class ConstantArrayBuilder + : public ConstantArrayBuilderTemplateBase<ConstantInitBuilderTraits> { + template <class Traits> + friend class ConstantInitBuilderTemplateBase; + + // The use of explicit qualification is a GCC workaround. + template <class Impl, class Traits> + friend class CodeGen::ConstantAggregateBuilderTemplateBase; + + ConstantArrayBuilder(ConstantInitBuilder &builder, + ConstantAggregateBuilderBase *parent, + llvm::Type *eltTy) + : ConstantArrayBuilderTemplateBase(builder, parent, eltTy) {} +}; + +/// A helper class of ConstantInitBuilder, used for building constant +/// struct initializers. +class ConstantStructBuilder + : public ConstantStructBuilderTemplateBase<ConstantInitBuilderTraits> { + template <class Traits> + friend class ConstantInitBuilderTemplateBase; + + // The use of explicit qualification is a GCC workaround. + template <class Impl, class Traits> + friend class CodeGen::ConstantAggregateBuilderTemplateBase; + + ConstantStructBuilder(ConstantInitBuilder &builder, + ConstantAggregateBuilderBase *parent, + llvm::StructType *structTy) + : ConstantStructBuilderTemplateBase(builder, parent, structTy) {} +}; + +} // end namespace CodeGen +} // end namespace clang + +#endif diff --git a/include/clang/CodeGen/ConstantInitFuture.h b/include/clang/CodeGen/ConstantInitFuture.h new file mode 100644 index 000000000000..ef1a5d2f49af --- /dev/null +++ b/include/clang/CodeGen/ConstantInitFuture.h @@ -0,0 +1,111 @@ +//===- ConstantInitFuture.h - "Future" constant initializers ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class defines the ConstantInitFuture class. This is split out +// from ConstantInitBuilder.h in order to allow APIs to work with it +// without having to include that entire header. This is particularly +// important because it is often useful to be able to default-construct +// a future in, say, a default argument. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_CONSTANTINITFUTURE_H +#define LLVM_CLANG_CODEGEN_CONSTANTINITFUTURE_H + +#include "llvm/ADT/PointerUnion.h" +#include "llvm/IR/Constant.h" + +// Forward-declare ConstantInitBuilderBase and give it a +// PointerLikeTypeTraits specialization so that we can safely use it +// in a PointerUnion below. +namespace clang { +namespace CodeGen { +class ConstantInitBuilderBase; +} +} +namespace llvm { +template <> +class PointerLikeTypeTraits< ::clang::CodeGen::ConstantInitBuilderBase*> { +public: + using T = ::clang::CodeGen::ConstantInitBuilderBase*; + + static inline void *getAsVoidPointer(T p) { return p; } + static inline T getFromVoidPointer(void *p) {return static_cast<T>(p);} + enum { NumLowBitsAvailable = 2 }; +}; +} + +namespace clang { +namespace CodeGen { + +/// A "future" for a completed constant initializer, which can be passed +/// around independently of any sub-builders (but not the original parent). +class ConstantInitFuture { + using PairTy = llvm::PointerUnion<ConstantInitBuilderBase*, llvm::Constant*>; + + PairTy Data; + + friend class ConstantInitBuilderBase; + explicit ConstantInitFuture(ConstantInitBuilderBase *builder); + +public: + ConstantInitFuture() {} + + /// A future can be explicitly created from a fixed initializer. + explicit ConstantInitFuture(llvm::Constant *initializer) : Data(initializer) { + assert(initializer && "creating null future"); + } + + /// Is this future non-null? + explicit operator bool() const { return bool(Data); } + + /// Return the type of the initializer. + llvm::Type *getType() const; + + /// Abandon this initializer. + void abandon(); + + /// Install the initializer into a global variable. This cannot + /// be called multiple times. + void installInGlobal(llvm::GlobalVariable *global); + + void *getOpaqueValue() const { return Data.getOpaqueValue(); } + static ConstantInitFuture getFromOpaqueValue(void *value) { + ConstantInitFuture result; + result.Data = PairTy::getFromOpaqueValue(value); + return result; + } + enum { + NumLowBitsAvailable = + llvm::PointerLikeTypeTraits<PairTy>::NumLowBitsAvailable + }; +}; + +} // end namespace CodeGen +} // end namespace clang + +namespace llvm { + +template <> +class PointerLikeTypeTraits< ::clang::CodeGen::ConstantInitFuture> { +public: + using T = ::clang::CodeGen::ConstantInitFuture; + + static inline void *getAsVoidPointer(T future) { + return future.getOpaqueValue(); + } + static inline T getFromVoidPointer(void *p) { + return T::getFromOpaqueValue(p); + } + enum { NumLowBitsAvailable = T::NumLowBitsAvailable }; +}; + +} // end namespace llvm + +#endif diff --git a/include/clang/CodeGen/ModuleBuilder.h b/include/clang/CodeGen/ModuleBuilder.h index 58638348653f..6f81ea9d6370 100644 --- a/include/clang/CodeGen/ModuleBuilder.h +++ b/include/clang/CodeGen/ModuleBuilder.h @@ -35,6 +35,7 @@ namespace clang { namespace CodeGen { class CodeGenModule; + class CGDebugInfo; } /// The primary public interface to the Clang code generator. @@ -65,6 +66,9 @@ public: /// CodeGenerator after releasing its module. llvm::Module *ReleaseModule(); + /// Return debug info code generator. + CodeGen::CGDebugInfo *getCGDebugInfo(); + /// Given a mangled name, return a declaration which mangles that way /// which has been added to this code generator via a Handle method. /// |