[llvm] b9bf831 - [SandboxIR] Implement GlobalVariable (#108642)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 17 10:26:38 PDT 2024
Author: vporpo
Date: 2024-09-17T10:26:34-07:00
New Revision: b9bf831e8db38efcd930397516cbc4ca2c53d098
URL: https://github.com/llvm/llvm-project/commit/b9bf831e8db38efcd930397516cbc4ca2c53d098
DIFF: https://github.com/llvm/llvm-project/commit/b9bf831e8db38efcd930397516cbc4ca2c53d098.diff
LOG: [SandboxIR] Implement GlobalVariable (#108642)
This patch implements sandboxir::GlobalVariable mirroring
llvm::GlobalVariable.
Added:
Modified:
llvm/include/llvm/SandboxIR/SandboxIR.h
llvm/lib/SandboxIR/SandboxIR.cpp
llvm/unittests/SandboxIR/SandboxIRTest.cpp
llvm/unittests/SandboxIR/TrackerTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h
index 0cc0f3a4c87035..22b46bd8d7da14 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIR.h
+++ b/llvm/include/llvm/SandboxIR/SandboxIR.h
@@ -129,6 +129,7 @@ class ConstantTokenNone;
class GlobalValue;
class GlobalObject;
class GlobalIFunc;
+class GlobalVariable;
class Context;
class Function;
class Instruction;
@@ -334,6 +335,7 @@ class Value {
friend class DSOLocalEquivalent; // For `Val`.
friend class GlobalObject; // For `Val`.
friend class GlobalIFunc; // For `Val`.
+ friend class GlobalVariable; // For `Val`.
/// All values point to the context.
Context &Ctx;
@@ -1370,6 +1372,162 @@ class GlobalIFunc final
#endif
};
+class GlobalVariable final
+ : public GlobalWithNodeAPI<GlobalVariable, llvm::GlobalVariable,
+ GlobalObject, llvm::GlobalObject> {
+ GlobalVariable(llvm::GlobalObject *C, Context &Ctx)
+ : GlobalWithNodeAPI(ClassID::GlobalVariable, C, Ctx) {}
+ friend class Context; // For constructor.
+
+ /// Helper for mapped_iterator.
+ struct LLVMGVToGV {
+ Context &Ctx;
+ LLVMGVToGV(Context &Ctx) : Ctx(Ctx) {}
+ GlobalVariable &operator()(llvm::GlobalVariable &LLVMGV) const;
+ };
+
+public:
+ /// For isa/dyn_cast.
+ static bool classof(const sandboxir::Value *From) {
+ return From->getSubclassID() == ClassID::GlobalVariable;
+ }
+
+ /// Definitions have initializers, declarations don't.
+ ///
+ inline bool hasInitializer() const {
+ return cast<llvm::GlobalVariable>(Val)->hasInitializer();
+ }
+
+ /// hasDefinitiveInitializer - Whether the global variable has an initializer,
+ /// and any other instances of the global (this can happen due to weak
+ /// linkage) are guaranteed to have the same initializer.
+ ///
+ /// Note that if you want to transform a global, you must use
+ /// hasUniqueInitializer() instead, because of the *_odr linkage type.
+ ///
+ /// Example:
+ ///
+ /// @a = global SomeType* null - Initializer is both definitive and unique.
+ ///
+ /// @b = global weak SomeType* null - Initializer is neither definitive nor
+ /// unique.
+ ///
+ /// @c = global weak_odr SomeType* null - Initializer is definitive, but not
+ /// unique.
+ inline bool hasDefinitiveInitializer() const {
+ return cast<llvm::GlobalVariable>(Val)->hasDefinitiveInitializer();
+ }
+
+ /// hasUniqueInitializer - Whether the global variable has an initializer, and
+ /// any changes made to the initializer will turn up in the final executable.
+ inline bool hasUniqueInitializer() const {
+ return cast<llvm::GlobalVariable>(Val)->hasUniqueInitializer();
+ }
+
+ /// getInitializer - Return the initializer for this global variable. It is
+ /// illegal to call this method if the global is external, because we cannot
+ /// tell what the value is initialized to!
+ ///
+ Constant *getInitializer() const;
+ /// setInitializer - Sets the initializer for this global variable, removing
+ /// any existing initializer if InitVal==NULL. The initializer must have the
+ /// type getValueType().
+ void setInitializer(Constant *InitVal);
+
+ // TODO: Add missing replaceInitializer(). Requires special tracker
+
+ /// If the value is a global constant, its value is immutable throughout the
+ /// runtime execution of the program. Assigning a value into the constant
+ /// leads to undefined behavior.
+ ///
+ bool isConstant() const {
+ return cast<llvm::GlobalVariable>(Val)->isConstant();
+ }
+ void setConstant(bool V);
+
+ bool isExternallyInitialized() const {
+ return cast<llvm::GlobalVariable>(Val)->isExternallyInitialized();
+ }
+ void setExternallyInitialized(bool Val);
+
+ // TODO: Missing copyAttributesFrom()
+
+ // TODO: Missing removeFromParent(), eraseFromParent(), dropAllReferences()
+
+ // TODO: Missing addDebugInfo(), getDebugInfo()
+
+ // TODO: Missing attribute setter functions: addAttribute(), setAttributes().
+ // There seems to be no removeAttribute() so we can't undo them.
+
+ /// Return true if the attribute exists.
+ bool hasAttribute(Attribute::AttrKind Kind) const {
+ return cast<llvm::GlobalVariable>(Val)->hasAttribute(Kind);
+ }
+
+ /// Return true if the attribute exists.
+ bool hasAttribute(StringRef Kind) const {
+ return cast<llvm::GlobalVariable>(Val)->hasAttribute(Kind);
+ }
+
+ /// Return true if any attributes exist.
+ bool hasAttributes() const {
+ return cast<llvm::GlobalVariable>(Val)->hasAttributes();
+ }
+
+ /// Return the attribute object.
+ Attribute getAttribute(Attribute::AttrKind Kind) const {
+ return cast<llvm::GlobalVariable>(Val)->getAttribute(Kind);
+ }
+
+ /// Return the attribute object.
+ Attribute getAttribute(StringRef Kind) const {
+ return cast<llvm::GlobalVariable>(Val)->getAttribute(Kind);
+ }
+
+ /// Return the attribute set for this global
+ AttributeSet getAttributes() const {
+ return cast<llvm::GlobalVariable>(Val)->getAttributes();
+ }
+
+ /// Return attribute set as list with index.
+ /// FIXME: This may not be required once ValueEnumerators
+ /// in bitcode-writer can enumerate attribute-set.
+ AttributeList getAttributesAsList(unsigned Index) const {
+ return cast<llvm::GlobalVariable>(Val)->getAttributesAsList(Index);
+ }
+
+ /// Check if section name is present
+ bool hasImplicitSection() const {
+ return cast<llvm::GlobalVariable>(Val)->hasImplicitSection();
+ }
+
+ /// Get the custom code model raw value of this global.
+ ///
+ unsigned getCodeModelRaw() const {
+ return cast<llvm::GlobalVariable>(Val)->getCodeModelRaw();
+ }
+
+ /// Get the custom code model of this global if it has one.
+ ///
+ /// If this global does not have a custom code model, the empty instance
+ /// will be returned.
+ std::optional<CodeModel::Model> getCodeModel() const {
+ return cast<llvm::GlobalVariable>(Val)->getCodeModel();
+ }
+
+ // TODO: Missing setCodeModel(). Requires custom tracker.
+
+#ifndef NDEBUG
+ void verify() const override {
+ assert(isa<llvm::GlobalVariable>(Val) && "Expected a GlobalVariable!");
+ }
+ void dumpOS(raw_ostream &OS) const override {
+ dumpCommonPrefix(OS);
+ dumpCommonSuffix(OS);
+ }
+#endif
+};
+
class BlockAddress final : public Constant {
BlockAddress(llvm::BlockAddress *C, Context &Ctx)
: Constant(ClassID::BlockAddress, C, Ctx) {}
diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index 03d3e9e607f01a..c26ba1983db91e 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -2532,6 +2532,8 @@ template class GlobalWithNodeAPI<GlobalIFunc, llvm::GlobalIFunc, GlobalObject,
llvm::GlobalObject>;
template class GlobalWithNodeAPI<Function, llvm::Function, GlobalObject,
llvm::GlobalObject>;
+template class GlobalWithNodeAPI<GlobalVariable, llvm::GlobalVariable,
+ GlobalObject, llvm::GlobalObject>;
} // namespace llvm::sandboxir
void GlobalIFunc::setResolver(Constant *Resolver) {
@@ -2552,6 +2554,39 @@ Function *GlobalIFunc::getResolverFunction() {
cast<llvm::GlobalIFunc>(Val)->getResolverFunction()));
}
+GlobalVariable &
+GlobalVariable::LLVMGVToGV::operator()(llvm::GlobalVariable &LLVMGV) const {
+ return cast<GlobalVariable>(*Ctx.getValue(&LLVMGV));
+}
+
+Constant *GlobalVariable::getInitializer() const {
+ return Ctx.getOrCreateConstant(
+ cast<llvm::GlobalVariable>(Val)->getInitializer());
+}
+
+void GlobalVariable::setInitializer(Constant *InitVal) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&GlobalVariable::getInitializer,
+ &GlobalVariable::setInitializer>>(this);
+ cast<llvm::GlobalVariable>(Val)->setInitializer(
+ cast<llvm::Constant>(InitVal->Val));
+}
+
+void GlobalVariable::setConstant(bool V) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&GlobalVariable::isConstant,
+ &GlobalVariable::setConstant>>(this);
+ cast<llvm::GlobalVariable>(Val)->setConstant(V);
+}
+
+void GlobalVariable::setExternallyInitialized(bool V) {
+ Ctx.getTracker()
+ .emplaceIfTracking<
+ GenericSetter<&GlobalVariable::isExternallyInitialized,
+ &GlobalVariable::setExternallyInitialized>>(this);
+ cast<llvm::GlobalVariable>(Val)->setExternallyInitialized(V);
+}
+
void GlobalValue::setUnnamedAddr(UnnamedAddr V) {
Ctx.getTracker()
.emplaceIfTracking<GenericSetter<&GlobalValue::getUnnamedAddr,
@@ -2764,6 +2799,10 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
It->second = std::unique_ptr<GlobalIFunc>(
new GlobalIFunc(cast<llvm::GlobalIFunc>(C), *this));
break;
+ case llvm::Value::GlobalVariableVal:
+ It->second = std::unique_ptr<GlobalVariable>(
+ new GlobalVariable(cast<llvm::GlobalVariable>(C), *this));
+ break;
default:
It->second = std::unique_ptr<Constant>(new Constant(C, *this));
break;
diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
index 92118bfb4cfd98..5ded063ef6f735 100644
--- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp
+++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
@@ -937,6 +937,120 @@ define void @foo() {
}
}
+TEST_F(SandboxIRTest, GlobalVariable) {
+ parseIR(C, R"IR(
+ at glob0 = global i32 42
+ at glob1 = global i32 43
+define void @foo() {
+ %ld0 = load i32, ptr @glob0
+ %ld1 = load i32, ptr @glob1
+ ret void
+}
+)IR");
+ Function &LLVMF = *M->getFunction("foo");
+ auto *LLVMBB = &*LLVMF.begin();
+ auto LLVMIt = LLVMBB->begin();
+ auto *LLVMLd0 = cast<llvm::LoadInst>(&*LLVMIt++);
+ auto *LLVMGV0 = cast<llvm::GlobalVariable>(LLVMLd0->getPointerOperand());
+ sandboxir::Context Ctx(C);
+
+ auto &F = *Ctx.createFunction(&LLVMF);
+ auto *BB = &*F.begin();
+ auto It = BB->begin();
+ auto *Ld0 = cast<sandboxir::LoadInst>(&*It++);
+ auto *Ld1 = cast<sandboxir::LoadInst>(&*It++);
+ // Check classof(), creation.
+ auto *GV0 = cast<sandboxir::GlobalVariable>(Ld0->getPointerOperand());
+ auto *GV1 = cast<sandboxir::GlobalVariable>(Ld1->getPointerOperand());
+ // Check getIterator().
+ {
+ auto It0 = GV0->getIterator();
+ auto It1 = GV1->getIterator();
+ EXPECT_EQ(&*It0, GV0);
+ EXPECT_EQ(&*It1, GV1);
+ EXPECT_EQ(std::next(It0), It1);
+ EXPECT_EQ(std::prev(It1), It0);
+ EXPECT_EQ(&*std::next(It0), GV1);
+ EXPECT_EQ(&*std::prev(It1), GV0);
+ }
+ // Check getReverseIterator().
+ {
+ auto RevIt0 = GV0->getReverseIterator();
+ auto RevIt1 = GV1->getReverseIterator();
+ EXPECT_EQ(&*RevIt0, GV0);
+ EXPECT_EQ(&*RevIt1, GV1);
+ EXPECT_EQ(std::prev(RevIt0), RevIt1);
+ EXPECT_EQ(std::next(RevIt1), RevIt0);
+ EXPECT_EQ(&*std::prev(RevIt0), GV1);
+ EXPECT_EQ(&*std::next(RevIt1), GV0);
+ }
+ // Check hasInitializer().
+ EXPECT_EQ(GV0->hasInitializer(), LLVMGV0->hasInitializer());
+ // Check hasDefinitiveInitializer().
+ EXPECT_EQ(GV0->hasDefinitiveInitializer(),
+ LLVMGV0->hasDefinitiveInitializer());
+ // Check hasUniqueInitializer().
+ EXPECT_EQ(GV0->hasUniqueInitializer(), LLVMGV0->hasUniqueInitializer());
+ // Check getInitializer().
+ EXPECT_EQ(GV0->getInitializer(), Ctx.getValue(LLVMGV0->getInitializer()));
+ // Check setInitializer().
+ auto *OrigInitializer = GV0->getInitializer();
+ auto *NewInitializer = GV1->getInitializer();
+ EXPECT_NE(NewInitializer, OrigInitializer);
+ GV0->setInitializer(NewInitializer);
+ EXPECT_EQ(GV0->getInitializer(), NewInitializer);
+ GV0->setInitializer(OrigInitializer);
+ EXPECT_EQ(GV0->getInitializer(), OrigInitializer);
+ // Check isConstant().
+ EXPECT_EQ(GV0->isConstant(), LLVMGV0->isConstant());
+ // Check setConstant().
+ bool OrigIsConstant = GV0->isConstant();
+ bool NewIsConstant = !OrigIsConstant;
+ GV0->setConstant(NewIsConstant);
+ EXPECT_EQ(GV0->isConstant(), NewIsConstant);
+ GV0->setConstant(OrigIsConstant);
+ EXPECT_EQ(GV0->isConstant(), OrigIsConstant);
+ // Check isExternallyInitialized().
+ EXPECT_EQ(GV0->isExternallyInitialized(), LLVMGV0->isExternallyInitialized());
+ // Check setExternallyInitialized().
+ bool OrigIsExtInit = GV0->isExternallyInitialized();
+ bool NewIsExtInit = !OrigIsExtInit;
+ GV0->setExternallyInitialized(NewIsExtInit);
+ EXPECT_EQ(GV0->isExternallyInitialized(), NewIsExtInit);
+ GV0->setExternallyInitialized(OrigIsExtInit);
+ EXPECT_EQ(GV0->isExternallyInitialized(), OrigIsExtInit);
+ for (auto KindIdx : seq<int>(0, Attribute::AttrKind::EndAttrKinds)) {
+ // Check hasAttribute(AttrKind).
+ auto Kind = static_cast<Attribute::AttrKind>(KindIdx);
+ EXPECT_EQ(GV0->hasAttribute(Kind), LLVMGV0->hasAttribute(Kind));
+ // Check hasAttribute(StringRef).
+ StringRef KindStr = Attribute::getNameFromAttrKind(Kind);
+ EXPECT_EQ(GV0->hasAttribute(KindStr), LLVMGV0->hasAttribute(KindStr));
+ }
+ // Check hasAttributes().
+ EXPECT_EQ(GV0->hasAttributes(), LLVMGV0->hasAttributes());
+
+ for (auto KindIdx : seq<int>(0, Attribute::AttrKind::EndAttrKinds)) {
+ // Check getAttribute(AttrKind).
+ auto Kind = static_cast<Attribute::AttrKind>(KindIdx);
+ EXPECT_EQ(GV0->getAttribute(Kind), LLVMGV0->getAttribute(Kind));
+ // Check getAttribute(StringRef).
+ StringRef KindStr = Attribute::getNameFromAttrKind(Kind);
+ EXPECT_EQ(GV0->getAttribute(KindStr), LLVMGV0->getAttribute(KindStr));
+ }
+ // Check getAttributes().
+ EXPECT_EQ(GV0->getAttributes(), LLVMGV0->getAttributes());
+ // Check getAttributesAsList().
+ EXPECT_THAT(GV0->getAttributesAsList(0u),
+ testing::ContainerEq(LLVMGV0->getAttributesAsList(0u)));
+ // Check hasImplicitSection().
+ EXPECT_EQ(GV0->hasImplicitSection(), LLVMGV0->hasImplicitSection());
+ // Check getCodeModelRaw().
+ EXPECT_EQ(GV0->getCodeModelRaw(), LLVMGV0->getCodeModelRaw());
+ // Check getCodeModel().
+ EXPECT_EQ(GV0->getCodeModel(), LLVMGV0->getCodeModel());
+}
+
TEST_F(SandboxIRTest, BlockAddress) {
parseIR(C, R"IR(
define void @foo(ptr %ptr) {
diff --git a/llvm/unittests/SandboxIR/TrackerTest.cpp b/llvm/unittests/SandboxIR/TrackerTest.cpp
index d4ff4fd6464e5c..f46e16e626baf0 100644
--- a/llvm/unittests/SandboxIR/TrackerTest.cpp
+++ b/llvm/unittests/SandboxIR/TrackerTest.cpp
@@ -1590,6 +1590,54 @@ define void @foo() {
EXPECT_EQ(IFunc->getResolver(), OrigResolver);
}
+TEST_F(TrackerTest, GlobalVariableSetters) {
+ parseIR(C, R"IR(
+ at glob0 = global i32 42
+ at glob1 = global i32 43
+define void @foo() {
+ %ld0 = load i32, ptr @glob0
+ %ld1 = load i32, ptr @glob1
+ ret void
+}
+)IR");
+ Function &LLVMF = *M->getFunction("foo");
+ sandboxir::Context Ctx(C);
+
+ auto &F = *Ctx.createFunction(&LLVMF);
+ auto *BB = &*F.begin();
+ auto It = BB->begin();
+ auto *Ld0 = cast<sandboxir::LoadInst>(&*It++);
+ auto *Ld1 = cast<sandboxir::LoadInst>(&*It++);
+ // Check classof(), creation.
+ auto *GV0 = cast<sandboxir::GlobalVariable>(Ld0->getPointerOperand());
+ auto *GV1 = cast<sandboxir::GlobalVariable>(Ld1->getPointerOperand());
+ // Check setInitializer().
+ auto *OrigInitializer = GV0->getInitializer();
+ auto *NewInitializer = GV1->getInitializer();
+ EXPECT_NE(NewInitializer, OrigInitializer);
+ Ctx.save();
+ GV0->setInitializer(NewInitializer);
+ EXPECT_EQ(GV0->getInitializer(), NewInitializer);
+ Ctx.revert();
+ EXPECT_EQ(GV0->getInitializer(), OrigInitializer);
+ // Check setConstant().
+ bool OrigIsConstant = GV0->isConstant();
+ bool NewIsConstant = !OrigIsConstant;
+ Ctx.save();
+ GV0->setConstant(NewIsConstant);
+ EXPECT_EQ(GV0->isConstant(), NewIsConstant);
+ Ctx.revert();
+ EXPECT_EQ(GV0->isConstant(), OrigIsConstant);
+ // Check setExternallyInitialized().
+ bool OrigIsExtInit = GV0->isExternallyInitialized();
+ bool NewIsExtInit = !OrigIsExtInit;
+ Ctx.save();
+ GV0->setExternallyInitialized(NewIsExtInit);
+ EXPECT_EQ(GV0->isExternallyInitialized(), NewIsExtInit);
+ Ctx.revert();
+ EXPECT_EQ(GV0->isExternallyInitialized(), OrigIsExtInit);
+}
+
TEST_F(TrackerTest, SetVolatile) {
parseIR(C, R"IR(
define void @foo(ptr %arg0, i8 %val) {
More information about the llvm-commits
mailing list