Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SandboxIR] Implement GlobalObject #108604

Merged
merged 1 commit into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading