From decbe09056e0b4a646b3413abbfa8c282ed4397f Mon Sep 17 00:00:00 2001 From: Vasileios Porpodas Date: Fri, 23 Aug 2024 09:00:53 -0700 Subject: [PATCH] [SandboxIR] Implement GlobalObject This patch implements sandboxir::GlobalObject mirroring llvm::GlobalObject. --- llvm/include/llvm/SandboxIR/SandboxIR.h | 108 +++++++++++++++++++-- llvm/lib/SandboxIR/SandboxIR.cpp | 24 +++++ 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 d21b8a85161e4..24c34466b4415 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 @@ class Value { 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 @@ class GlobalValue : public Constant { 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 @@ class GlobalValue : public Constant { // 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(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(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(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(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(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(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(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(Val)->canIncreaseAlignment(); + } +}; + class BlockAddress final : public Constant { BlockAddress(llvm::BlockAddress *C, Context &Ctx) : Constant(ClassID::BlockAddress, C, Ctx) {} @@ -4127,7 +4219,7 @@ class Context { 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 04243564809db..2f20fd3ff1dcc 100644 --- a/llvm/lib/SandboxIR/SandboxIR.cpp +++ b/llvm/lib/SandboxIR/SandboxIR.cpp @@ -2495,6 +2495,30 @@ PoisonValue *PoisonValue::getElementValue(unsigned Idx) const { cast(Val)->getElementValue(Idx))); } +void GlobalObject::setAlignment(MaybeAlign Align) { + Ctx.getTracker() + .emplaceIfTracking< + GenericSetter<&GlobalObject::getAlign, &GlobalObject::setAlignment>>( + this); + cast(Val)->setAlignment(Align); +} + +void GlobalObject::setGlobalObjectSubClassData(unsigned V) { + Ctx.getTracker() + .emplaceIfTracking< + GenericSetter<&GlobalObject::getGlobalObjectSubClassData, + &GlobalObject::setGlobalObjectSubClassData>>(this); + cast(Val)->setGlobalObjectSubClassData(V); +} + +void GlobalObject::setSection(StringRef S) { + Ctx.getTracker() + .emplaceIfTracking< + GenericSetter<&GlobalObject::getSection, &GlobalObject::setSection>>( + this); + cast(Val)->setSection(S); +} + void GlobalValue::setUnnamedAddr(UnnamedAddr V) { Ctx.getTracker() .emplaceIfTrackinggetVisibility(), 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(&*LLVMIt++); + auto *LLVMGO = cast(LLVMCall->getCalledOperand()); + sandboxir::Context Ctx(C); + + auto &F = *Ctx.createFunction(&LLVMF); + auto *BB = &*F.begin(); + auto It = BB->begin(); + auto *Call = cast(&*It++); + // Check classof(), creation. + auto *GO = cast(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) {