summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2016-12-01 05:33:30 +0000
committerJohn McCall <rjmccall@apple.com>2016-12-01 05:33:30 +0000
commite5f23fb9ea2242576c899d80ff4e6247aa8d9c36 (patch)
treeaed8fa67c592c8bd43f360f2a17ed0af37b48e3b
parent812476b49584c9084c5a7269ea838a185e4d8cfe (diff)
downloadbcm5719-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.h40
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();
+ }
}
};
OpenPOWER on IntegriCloud