diff options
author | vporpo <vporpodas@google.com> | 2024-09-13 11:18:42 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-13 11:18:42 -0700 |
commit | 9f738c84f05ff965b81e0be5cc725af3fa13cbf0 (patch) | |
tree | eb3a823ae251175b3698696b74d52e32c95789f7 | |
parent | d588e49a324b3d6039c19f3108d722a8b9fcd96e (diff) | |
download | llvm-9f738c84f05ff965b81e0be5cc725af3fa13cbf0.zip llvm-9f738c84f05ff965b81e0be5cc725af3fa13cbf0.tar.gz llvm-9f738c84f05ff965b81e0be5cc725af3fa13cbf0.tar.bz2 |
[SandboxIR] Implement GlobalObject (#108604)
This patch implements sandboxir::GlobalObject mirroring
llvm::GlobalObject.
-rw-r--r-- | llvm/include/llvm/SandboxIR/SandboxIR.h | 108 | ||||
-rw-r--r-- | llvm/lib/SandboxIR/SandboxIR.cpp | 24 | ||||
-rw-r--r-- | llvm/unittests/SandboxIR/SandboxIRTest.cpp | 64 |
3 files changed, 188 insertions, 8 deletions
diff --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h index d21b8a8..24c3446 100644 --- a/llvm/include/llvm/SandboxIR/SandboxIR.h +++ b/llvm/include/llvm/SandboxIR/SandboxIR.h @@ -127,6 +127,7 @@ class BlockAddress; class DSOLocalEquivalent; class ConstantTokenNone; class GlobalValue; +class GlobalObject; class Context; class Function; class Instruction; @@ -330,6 +331,7 @@ protected: friend class BlockAddress; // For `Val`. friend class GlobalValue; // For `Val`. friend class DSOLocalEquivalent; // For `Val`. + friend class GlobalObject; // For `Val`. /// All values point to the context. Context &Ctx; @@ -1124,14 +1126,8 @@ protected: GlobalValue(ClassID ID, llvm::GlobalValue *C, Context &Ctx) : Constant(ID, C, Ctx) {} friend class Context; // For constructor. - Use getOperandUseInternal(unsigned OpIdx, bool Verify) const override { - return getOperandUseDefault(OpIdx, Verify); - } public: - unsigned getUseOperandNo(const Use &Use) const override { - return getUseOperandNoDefault(Use); - } /// For isa/dyn_cast. static bool classof(const sandboxir::Value *From) { switch (From->getSubclassID()) { @@ -1193,6 +1189,102 @@ public: // TODO: Add missing functions. }; +class GlobalObject : public GlobalValue { +protected: + GlobalObject(ClassID ID, llvm::GlobalObject *C, Context &Ctx) + : GlobalValue(ID, C, Ctx) {} + friend class Context; // For constructor. + Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final { + return getOperandUseDefault(OpIdx, Verify); + } + +public: + unsigned getUseOperandNo(const Use &Use) const final { + return getUseOperandNoDefault(Use); + } + /// For isa/dyn_cast. + static bool classof(const sandboxir::Value *From) { + switch (From->getSubclassID()) { + case ClassID::Function: + case ClassID::GlobalVariable: + case ClassID::GlobalIFunc: + return true; + default: + return false; + } + } + + /// FIXME: Remove this function once transition to Align is over. + uint64_t getAlignment() const { + return cast<llvm::GlobalObject>(Val)->getAlignment(); + } + + /// Returns the alignment of the given variable or function. + /// + /// Note that for functions this is the alignment of the code, not the + /// alignment of a function pointer. + MaybeAlign getAlign() const { + return cast<llvm::GlobalObject>(Val)->getAlign(); + } + + // TODO: Add missing: setAlignment(Align) + + /// Sets the alignment attribute of the GlobalObject. + /// This method will be deprecated as the alignment property should always be + /// defined. + void setAlignment(MaybeAlign Align); + + unsigned getGlobalObjectSubClassData() const { + return cast<llvm::GlobalObject>(Val)->getGlobalObjectSubClassData(); + } + + void setGlobalObjectSubClassData(unsigned V); + + /// Check if this global has a custom object file section. + /// + /// This is more efficient than calling getSection() and checking for an empty + /// string. + bool hasSection() const { + return cast<llvm::GlobalObject>(Val)->hasSection(); + } + + /// Get the custom section of this global if it has one. + /// + /// If this global does not have a custom section, this will be empty and the + /// default object file section (.text, .data, etc) will be used. + StringRef getSection() const { + return cast<llvm::GlobalObject>(Val)->getSection(); + } + + /// Change the section for this global. + /// + /// Setting the section to the empty string tells LLVM to choose an + /// appropriate default object file section. + void setSection(StringRef S); + + bool hasComdat() const { return cast<llvm::GlobalObject>(Val)->hasComdat(); } + + // TODO: implement get/setComdat(), etc. once we have a sandboxir::Comdat. + + // TODO: We currently don't support Metadata in sandboxir so all + // Metadata-related functions are missing. + + using VCallVisibility = llvm::GlobalObject::VCallVisibility; + + VCallVisibility getVCallVisibility() const { + return cast<llvm::GlobalObject>(Val)->getVCallVisibility(); + } + + /// Returns true if the alignment of the value can be unilaterally + /// increased. + /// + /// Note that for functions this is the alignment of the code, not the + /// alignment of a function pointer. + bool canIncreaseAlignment() const { + return cast<llvm::GlobalObject>(Val)->canIncreaseAlignment(); + } +}; + class BlockAddress final : public Constant { BlockAddress(llvm::BlockAddress *C, Context &Ctx) : Constant(ClassID::BlockAddress, C, Ctx) {} @@ -4127,7 +4219,7 @@ public: size_t getNumValues() const { return LLVMValueToValueMap.size(); } }; -class Function : public Constant { +class Function : public GlobalObject { /// Helper for mapped_iterator. struct LLVMBBToBB { Context &Ctx; @@ -4138,7 +4230,7 @@ class Function : public Constant { }; /// Use Context::createFunction() instead. Function(llvm::Function *F, sandboxir::Context &Ctx) - : Constant(ClassID::Function, F, Ctx) {} + : GlobalObject(ClassID::Function, F, Ctx) {} friend class Context; // For constructor. public: diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp index 0424356..2f20fd3f 100644 --- a/llvm/lib/SandboxIR/SandboxIR.cpp +++ b/llvm/lib/SandboxIR/SandboxIR.cpp @@ -2495,6 +2495,30 @@ PoisonValue *PoisonValue::getElementValue(unsigned Idx) const { cast<llvm::PoisonValue>(Val)->getElementValue(Idx))); } +void GlobalObject::setAlignment(MaybeAlign Align) { + Ctx.getTracker() + .emplaceIfTracking< + GenericSetter<&GlobalObject::getAlign, &GlobalObject::setAlignment>>( + this); + cast<llvm::GlobalObject>(Val)->setAlignment(Align); +} + +void GlobalObject::setGlobalObjectSubClassData(unsigned V) { + Ctx.getTracker() + .emplaceIfTracking< + GenericSetter<&GlobalObject::getGlobalObjectSubClassData, + &GlobalObject::setGlobalObjectSubClassData>>(this); + cast<llvm::GlobalObject>(Val)->setGlobalObjectSubClassData(V); +} + +void GlobalObject::setSection(StringRef S) { + Ctx.getTracker() + .emplaceIfTracking< + GenericSetter<&GlobalObject::getSection, &GlobalObject::setSection>>( + this); + cast<llvm::GlobalObject>(Val)->setSection(S); +} + void GlobalValue::setUnnamedAddr(UnnamedAddr V) { Ctx.getTracker() .emplaceIfTracking<GenericSetter<&GlobalValue::getUnnamedAddr, diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp index d883c18..b1f3a6c0 100644 --- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp +++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp @@ -795,6 +795,70 @@ define void @foo() { EXPECT_EQ(GV->getVisibility(), OrigVisibility); } +TEST_F(SandboxIRTest, GlobalObject) { + parseIR(C, R"IR( +declare external void @bar() +define void @foo() { + call void @bar() + ret void +} +)IR"); + Function &LLVMF = *M->getFunction("foo"); + auto *LLVMBB = &*LLVMF.begin(); + auto LLVMIt = LLVMBB->begin(); + auto *LLVMCall = cast<llvm::CallInst>(&*LLVMIt++); + auto *LLVMGO = cast<llvm::GlobalObject>(LLVMCall->getCalledOperand()); + sandboxir::Context Ctx(C); + + auto &F = *Ctx.createFunction(&LLVMF); + auto *BB = &*F.begin(); + auto It = BB->begin(); + auto *Call = cast<sandboxir::CallInst>(&*It++); + // Check classof(), creation. + auto *GO = cast<sandboxir::GlobalObject>(Call->getCalledOperand()); + // Check getAlignment(). + EXPECT_EQ(GO->getAlignment(), LLVMGO->getAlignment()); + // Check getAlign(). + EXPECT_EQ(GO->getAlign(), LLVMGO->getAlign()); + // Check setAlignment(). + auto OrigMaybeAlign = GO->getAlign(); + auto NewMaybeAlign = MaybeAlign(128); + EXPECT_NE(NewMaybeAlign, OrigMaybeAlign); + GO->setAlignment(NewMaybeAlign); + EXPECT_EQ(GO->getAlign(), NewMaybeAlign); + GO->setAlignment(OrigMaybeAlign); + EXPECT_EQ(GO->getAlign(), OrigMaybeAlign); + // Check getGlobalObjectSubClassData(). + EXPECT_EQ(GO->getGlobalObjectSubClassData(), + LLVMGO->getGlobalObjectSubClassData()); + // Check setGlobalObjectSubClassData(). + auto OrigGOSCD = GO->getGlobalObjectSubClassData(); + auto NewGOSCD = 1u; + EXPECT_NE(NewGOSCD, OrigGOSCD); + GO->setGlobalObjectSubClassData(NewGOSCD); + EXPECT_EQ(GO->getGlobalObjectSubClassData(), NewGOSCD); + GO->setGlobalObjectSubClassData(OrigGOSCD); + EXPECT_EQ(GO->getGlobalObjectSubClassData(), OrigGOSCD); + // Check hasSection(). + EXPECT_EQ(GO->hasSection(), LLVMGO->hasSection()); + // Check getSection(). + EXPECT_EQ(GO->getSection(), LLVMGO->getSection()); + // Check setSection(). + auto OrigSection = GO->getSection(); + auto NewSection = ".some_section"; + EXPECT_NE(NewSection, OrigSection); + GO->setSection(NewSection); + EXPECT_EQ(GO->getSection(), NewSection); + GO->setSection(OrigSection); + EXPECT_EQ(GO->getSection(), OrigSection); + // Check hasComdat(). + EXPECT_EQ(GO->hasComdat(), LLVMGO->hasComdat()); + // Check getVCallVisibility(). + EXPECT_EQ(GO->getVCallVisibility(), LLVMGO->getVCallVisibility()); + // Check canIncreaseAlignment(). + EXPECT_EQ(GO->canIncreaseAlignment(), LLVMGO->canIncreaseAlignment()); +} + TEST_F(SandboxIRTest, BlockAddress) { parseIR(C, R"IR( define void @foo(ptr %ptr) { |