Skip to content

Commit

Permalink
[SandboxIR] Implement GlobalValue (llvm#108317)
Browse files Browse the repository at this point in the history
This patch implements sandboxir::GlobalValue mirroring
llvm::GlobalValue. Please note that the implementation is incomplete as
it's missing several member functions.
  • Loading branch information
vporpo authored Sep 12, 2024
1 parent 6292ea6 commit 6d859c1
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 2 deletions.
81 changes: 79 additions & 2 deletions llvm/include/llvm/SandboxIR/SandboxIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ class ConstantPointerNull;
class PoisonValue;
class BlockAddress;
class ConstantTokenNone;
class GlobalValue;
class Context;
class Function;
class Instruction;
Expand Down Expand Up @@ -326,6 +327,7 @@ class Value {
friend class UndefValue; // For `Val`.
friend class PoisonValue; // For `Val`.
friend class BlockAddress; // For `Val`.
friend class GlobalValue; // For `Val`.

/// All values point to the context.
Context &Ctx;
Expand Down Expand Up @@ -1115,6 +1117,80 @@ class PoisonValue final : public UndefValue {
#endif
};

class GlobalValue : public Constant {
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()) {
case ClassID::Function:
case ClassID::GlobalVariable:
case ClassID::GlobalAlias:
case ClassID::GlobalIFunc:
return true;
default:
return false;
}
}

unsigned getAddressSpace() const {
return cast<llvm::GlobalValue>(Val)->getAddressSpace();
}
bool hasGlobalUnnamedAddr() const {
return cast<llvm::GlobalValue>(Val)->hasGlobalUnnamedAddr();
}

/// Returns true if this value's address is not significant in this module.
/// This attribute is intended to be used only by the code generator and LTO
/// to allow the linker to decide whether the global needs to be in the symbol
/// table. It should probably not be used in optimizations, as the value may
/// have uses outside the module; use hasGlobalUnnamedAddr() instead.
bool hasAtLeastLocalUnnamedAddr() const {
return cast<llvm::GlobalValue>(Val)->hasAtLeastLocalUnnamedAddr();
}

using UnnamedAddr = llvm::GlobalValue::UnnamedAddr;

UnnamedAddr getUnnamedAddr() const {
return cast<llvm::GlobalValue>(Val)->getUnnamedAddr();
}
void setUnnamedAddr(UnnamedAddr V);

static UnnamedAddr getMinUnnamedAddr(UnnamedAddr A, UnnamedAddr B) {
return llvm::GlobalValue::getMinUnnamedAddr(A, B);
}

bool hasComdat() const { return cast<llvm::GlobalValue>(Val)->hasComdat(); }

// TODO: We need a SandboxIR Comdat if we want to implement getComdat().
using VisibilityTypes = llvm::GlobalValue::VisibilityTypes;
VisibilityTypes getVisibility() const {
return cast<llvm::GlobalValue>(Val)->getVisibility();
}
bool hasDefaultVisibility() const {
return cast<llvm::GlobalValue>(Val)->hasDefaultVisibility();
}
bool hasHiddenVisibility() const {
return cast<llvm::GlobalValue>(Val)->hasHiddenVisibility();
}
bool hasProtectedVisibility() const {
return cast<llvm::GlobalValue>(Val)->hasProtectedVisibility();
}
void setVisibility(VisibilityTypes V);

// TODO: Add missing functions.
};

class BlockAddress final : public Constant {
BlockAddress(llvm::BlockAddress *C, Context &Ctx)
: Constant(ClassID::BlockAddress, C, Ctx) {}
Expand Down Expand Up @@ -3845,8 +3921,9 @@ class Context {
friend class PointerType; // For LLVMCtx.
friend class CmpInst; // For LLVMCtx. TODO: cleanup when sandboxir::VectorType
// is complete
friend class IntegerType; // For LLVMCtx.
friend class StructType; // For LLVMCtx.
friend class IntegerType; // For LLVMCtx.
friend class StructType; // For LLVMCtx.
friend class TargetExtType; // For LLVMCtx.
Tracker IRTracker;

/// Maps LLVM Value to the corresponding sandboxir::Value. Owns all
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/SandboxIR/SandboxIRValues.def
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ DEF_CONST(ConstantAggregateZero, ConstantAggregateZero)
DEF_CONST(ConstantPointerNull, ConstantPointerNull)
DEF_CONST(UndefValue, UndefValue)
DEF_CONST(PoisonValue, PoisonValue)
DEF_CONST(GlobalVariable, GlobalVariable)
DEF_CONST(GlobalIFunc, GlobalIFunc)
DEF_CONST(GlobalAlias, GlobalAlias)
DEF_CONST(BlockAddress, BlockAddress)
DEF_CONST(ConstantTokenNone, ConstantTokenNone)

Expand Down
14 changes: 14 additions & 0 deletions llvm/lib/SandboxIR/SandboxIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2495,6 +2495,20 @@ PoisonValue *PoisonValue::getElementValue(unsigned Idx) const {
cast<llvm::PoisonValue>(Val)->getElementValue(Idx)));
}

void GlobalValue::setUnnamedAddr(UnnamedAddr V) {
Ctx.getTracker()
.emplaceIfTracking<GenericSetter<&GlobalValue::getUnnamedAddr,
&GlobalValue::setUnnamedAddr>>(this);
cast<llvm::GlobalValue>(Val)->setUnnamedAddr(V);
}

void GlobalValue::setVisibility(VisibilityTypes V) {
Ctx.getTracker()
.emplaceIfTracking<GenericSetter<&GlobalValue::getVisibility,
&GlobalValue::setVisibility>>(this);
cast<llvm::GlobalValue>(Val)->setVisibility(V);
}

BlockAddress *BlockAddress::get(Function *F, BasicBlock *BB) {
auto *LLVMC = llvm::BlockAddress::get(cast<llvm::Function>(F->Val),
cast<llvm::BasicBlock>(BB->Val));
Expand Down
66 changes: 66 additions & 0 deletions llvm/unittests/SandboxIR/SandboxIRTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,72 @@ define void @foo() {
EXPECT_EQ(UndefStruct->getNumElements(), 2u);
}

TEST_F(SandboxIRTest, GlobalValue) {
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 *LLVMGV = cast<llvm::GlobalValue>(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++);
[[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++);

// Check classof(), creation, getFunction(), getBasicBlock().
auto *GV = cast<sandboxir::GlobalValue>(Call->getCalledOperand());
// Check getAddressSpace().
EXPECT_EQ(GV->getAddressSpace(), LLVMGV->getAddressSpace());
// Check hasGlobalUnnamedAddr().
EXPECT_EQ(GV->hasGlobalUnnamedAddr(), LLVMGV->hasGlobalUnnamedAddr());
// Check hasAtLeastLocalUnnamedAddr().
EXPECT_EQ(GV->hasAtLeastLocalUnnamedAddr(),
LLVMGV->hasAtLeastLocalUnnamedAddr());
// Check getUnnamedAddr().
EXPECT_EQ(GV->getUnnamedAddr(), LLVMGV->getUnnamedAddr());
// Check setUnnamedAddr().
auto OrigUnnamedAddr = GV->getUnnamedAddr();
auto NewUnnamedAddr = sandboxir::GlobalValue::UnnamedAddr::Global;
EXPECT_NE(NewUnnamedAddr, OrigUnnamedAddr);
GV->setUnnamedAddr(NewUnnamedAddr);
EXPECT_EQ(GV->getUnnamedAddr(), NewUnnamedAddr);
GV->setUnnamedAddr(OrigUnnamedAddr);
EXPECT_EQ(GV->getUnnamedAddr(), OrigUnnamedAddr);
// Check getMinUnnamedAddr().
EXPECT_EQ(
sandboxir::GlobalValue::getMinUnnamedAddr(OrigUnnamedAddr,
NewUnnamedAddr),
llvm::GlobalValue::getMinUnnamedAddr(OrigUnnamedAddr, NewUnnamedAddr));
// Check hasComdat().
EXPECT_EQ(GV->hasComdat(), LLVMGV->hasComdat());
// Check getVisibility().
EXPECT_EQ(GV->getVisibility(), LLVMGV->getVisibility());
// Check hasDefaultVisibility().
EXPECT_EQ(GV->hasDefaultVisibility(), LLVMGV->hasDefaultVisibility());
// Check hasHiddenVisibility().
EXPECT_EQ(GV->hasHiddenVisibility(), LLVMGV->hasHiddenVisibility());
// Check hasProtectedVisibility().
EXPECT_EQ(GV->hasProtectedVisibility(), LLVMGV->hasProtectedVisibility());
// Check setVisibility().
auto OrigVisibility = GV->getVisibility();
auto NewVisibility =
sandboxir::GlobalValue::VisibilityTypes::ProtectedVisibility;
EXPECT_NE(NewVisibility, OrigVisibility);
GV->setVisibility(NewVisibility);
EXPECT_EQ(GV->getVisibility(), NewVisibility);
GV->setVisibility(OrigVisibility);
EXPECT_EQ(GV->getVisibility(), OrigVisibility);
}

TEST_F(SandboxIRTest, BlockAddress) {
parseIR(C, R"IR(
define void @foo(ptr %ptr) {
Expand Down
37 changes: 37 additions & 0 deletions llvm/unittests/SandboxIR/TrackerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1521,6 +1521,43 @@ define void @foo(i64 %i0, i64 %i1, float %f0, float %f1) {
checkCmpInst(Ctx, ICmp);
}

TEST_F(TrackerTest, GlobalValueSetters) {
parseIR(C, R"IR(
define void @foo() {
call void @foo()
ret void
}
)IR");
Function &LLVMF = *M->getFunction("foo");
sandboxir::Context Ctx(C);

auto &F = *Ctx.createFunction(&LLVMF);
auto *BB = &*F.begin();
auto *Call = cast<sandboxir::CallInst>(&*BB->begin());

auto *GV = cast<sandboxir::GlobalValue>(Call->getCalledOperand());
// Check setUnnamedAddr().
auto OrigUnnamedAddr = GV->getUnnamedAddr();
auto NewUnnamedAddr = sandboxir::GlobalValue::UnnamedAddr::Global;
EXPECT_NE(NewUnnamedAddr, OrigUnnamedAddr);
Ctx.save();
GV->setUnnamedAddr(NewUnnamedAddr);
EXPECT_EQ(GV->getUnnamedAddr(), NewUnnamedAddr);
Ctx.revert();
EXPECT_EQ(GV->getUnnamedAddr(), OrigUnnamedAddr);

// Check setVisibility().
auto OrigVisibility = GV->getVisibility();
auto NewVisibility =
sandboxir::GlobalValue::VisibilityTypes::ProtectedVisibility;
EXPECT_NE(NewVisibility, OrigVisibility);
Ctx.save();
GV->setVisibility(NewVisibility);
EXPECT_EQ(GV->getVisibility(), NewVisibility);
Ctx.revert();
EXPECT_EQ(GV->getVisibility(), OrigVisibility);
}

TEST_F(TrackerTest, SetVolatile) {
parseIR(C, R"IR(
define void @foo(ptr %arg0, i8 %val) {
Expand Down

0 comments on commit 6d859c1

Please sign in to comment.