Skip to content

Commit

Permalink
[SandboxIR] Implement GlobalObject (llvm#108604)
Browse files Browse the repository at this point in the history
This patch implements sandboxir::GlobalObject mirroring
llvm::GlobalObject.
  • Loading branch information
vporpo authored Sep 13, 2024
1 parent d588e49 commit 9f738c8
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 8 deletions.
108 changes: 100 additions & 8 deletions llvm/include/llvm/SandboxIR/SandboxIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class BlockAddress;
class DSOLocalEquivalent;
class ConstantTokenNone;
class GlobalValue;
class GlobalObject;
class Context;
class Function;
class Instruction;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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<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) {}
Expand Down Expand Up @@ -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;
Expand All @@ -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:
Expand Down
24 changes: 24 additions & 0 deletions llvm/lib/SandboxIR/SandboxIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
64 changes: 64 additions & 0 deletions llvm/unittests/SandboxIR/SandboxIRTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit 9f738c8

Please sign in to comment.