diff options
author | John McCall <rjmccall@apple.com> | 2016-12-01 05:33:30 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2016-12-01 05:33:30 +0000 |
commit | e5f23fb9ea2242576c899d80ff4e6247aa8d9c36 (patch) | |
tree | aed8fa67c592c8bd43f360f2a17ed0af37b48e3b | |
parent | 812476b49584c9084c5a7269ea838a185e4d8cfe (diff) | |
download | bcm5719-llvm-e5f23fb9ea2242576c899d80ff4e6247aa8d9c36.tar.gz bcm5719-llvm-e5f23fb9ea2242576c899d80ff4e6247aa8d9c36.zip |
Teach ConstantBuilder how to emit a reference to the current position
that will be filled in when the initializer is set.
llvm-svn: 288313
-rw-r--r-- | clang/lib/CodeGen/ConstantBuilder.h | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/ConstantBuilder.h b/clang/lib/CodeGen/ConstantBuilder.h index bedab3e2013..6c5a5e515d1 100644 --- a/clang/lib/CodeGen/ConstantBuilder.h +++ b/clang/lib/CodeGen/ConstantBuilder.h @@ -21,6 +21,8 @@ #include "CodeGenModule.h" +#include <vector> + namespace clang { namespace CodeGen { @@ -47,8 +49,15 @@ class ConstantArrayBuilder; /// 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: @@ -201,6 +210,25 @@ public: 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()); @@ -294,12 +322,24 @@ private: 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(); + } } }; |