Skip to content

Commit d14a600

Browse files
authored
[SandboxIR] Implement BlockAddress (#107940)
This patch implements sandboxir::BlockAddress mirroring llvm:BlockAddress.
1 parent 6007ad7 commit d14a600

File tree

4 files changed

+109
-1
lines changed

4 files changed

+109
-1
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ class ConstantFP;
123123
class ConstantAggregateZero;
124124
class ConstantPointerNull;
125125
class PoisonValue;
126+
class BlockAddress;
126127
class Context;
127128
class Function;
128129
class Instruction;
@@ -323,6 +324,7 @@ class Value {
323324
friend class ConstantPointerNull; // For `Val`.
324325
friend class UndefValue; // For `Val`.
325326
friend class PoisonValue; // For `Val`.
327+
friend class BlockAddress; // For `Val`.
326328

327329
/// All values point to the context.
328330
Context &Ctx;
@@ -1112,6 +1114,33 @@ class PoisonValue final : public UndefValue {
11121114
#endif
11131115
};
11141116

1117+
class BlockAddress final : public Constant {
1118+
BlockAddress(llvm::BlockAddress *C, Context &Ctx)
1119+
: Constant(ClassID::BlockAddress, C, Ctx) {}
1120+
friend class Context; // For constructor.
1121+
1122+
public:
1123+
/// Return a BlockAddress for the specified function and basic block.
1124+
static BlockAddress *get(Function *F, BasicBlock *BB);
1125+
1126+
/// Return a BlockAddress for the specified basic block. The basic
1127+
/// block must be embedded into a function.
1128+
static BlockAddress *get(BasicBlock *BB);
1129+
1130+
/// Lookup an existing \c BlockAddress constant for the given BasicBlock.
1131+
///
1132+
/// \returns 0 if \c !BB->hasAddressTaken(), otherwise the \c BlockAddress.
1133+
static BlockAddress *lookup(const BasicBlock *BB);
1134+
1135+
Function *getFunction() const;
1136+
BasicBlock *getBasicBlock() const;
1137+
1138+
/// For isa/dyn_cast.
1139+
static bool classof(const sandboxir::Value *From) {
1140+
return From->getSubclassID() == ClassID::BlockAddress;
1141+
}
1142+
};
1143+
11151144
/// Iterator for `Instruction`s in a `BasicBlock.
11161145
/// \Returns an sandboxir::Instruction & when derereferenced.
11171146
class BBIterator {

llvm/include/llvm/SandboxIR/SandboxIRValues.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ DEF_CONST(ConstantAggregateZero, ConstantAggregateZero)
3434
DEF_CONST(ConstantPointerNull, ConstantPointerNull)
3535
DEF_CONST(UndefValue, UndefValue)
3636
DEF_CONST(PoisonValue, PoisonValue)
37+
DEF_CONST(BlockAddress, BlockAddress)
3738

3839
#ifndef DEF_INSTR
3940
#define DEF_INSTR(ID, OPCODE, CLASS)

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2489,6 +2489,32 @@ PoisonValue *PoisonValue::getElementValue(unsigned Idx) const {
24892489
cast<llvm::PoisonValue>(Val)->getElementValue(Idx)));
24902490
}
24912491

2492+
BlockAddress *BlockAddress::get(Function *F, BasicBlock *BB) {
2493+
auto *LLVMC = llvm::BlockAddress::get(cast<llvm::Function>(F->Val),
2494+
cast<llvm::BasicBlock>(BB->Val));
2495+
return cast<BlockAddress>(F->getContext().getOrCreateConstant(LLVMC));
2496+
}
2497+
2498+
BlockAddress *BlockAddress::get(BasicBlock *BB) {
2499+
auto *LLVMC = llvm::BlockAddress::get(cast<llvm::BasicBlock>(BB->Val));
2500+
return cast<BlockAddress>(BB->getContext().getOrCreateConstant(LLVMC));
2501+
}
2502+
2503+
BlockAddress *BlockAddress::lookup(const BasicBlock *BB) {
2504+
auto *LLVMC = llvm::BlockAddress::lookup(cast<llvm::BasicBlock>(BB->Val));
2505+
return cast_or_null<BlockAddress>(BB->getContext().getValue(LLVMC));
2506+
}
2507+
2508+
Function *BlockAddress::getFunction() const {
2509+
return cast<Function>(
2510+
Ctx.getValue(cast<llvm::BlockAddress>(Val)->getFunction()));
2511+
}
2512+
2513+
BasicBlock *BlockAddress::getBasicBlock() const {
2514+
return cast<BasicBlock>(
2515+
Ctx.getValue(cast<llvm::BlockAddress>(Val)->getBasicBlock()));
2516+
}
2517+
24922518
FunctionType *Function::getFunctionType() const {
24932519
return cast<FunctionType>(
24942520
Ctx.getType(cast<llvm::Function>(Val)->getFunctionType()));
@@ -2585,6 +2611,10 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
25852611
It->second = std::unique_ptr<ConstantFP>(
25862612
new ConstantFP(cast<llvm::ConstantFP>(C), *this));
25872613
return It->second.get();
2614+
case llvm::Value::BlockAddressVal:
2615+
It->second = std::unique_ptr<BlockAddress>(
2616+
new BlockAddress(cast<llvm::BlockAddress>(C), *this));
2617+
return It->second.get();
25882618
case llvm::Value::ConstantAggregateZeroVal: {
25892619
auto *CAZ = cast<llvm::ConstantAggregateZero>(C);
25902620
It->second = std::unique_ptr<ConstantAggregateZero>(
@@ -2640,7 +2670,7 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
26402670
return It->second.get();
26412671
}
26422672
if (auto *BB = dyn_cast<llvm::BasicBlock>(LLVMV)) {
2643-
assert(isa<BlockAddress>(U) &&
2673+
assert(isa<llvm::BlockAddress>(U) &&
26442674
"This won't create a SBBB, don't call this function directly!");
26452675
if (auto *SBBB = getValue(BB))
26462676
return SBBB;

llvm/unittests/SandboxIR/SandboxIRTest.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,54 @@ define void @foo() {
729729
EXPECT_EQ(UndefStruct->getNumElements(), 2u);
730730
}
731731

732+
TEST_F(SandboxIRTest, BlockAddress) {
733+
parseIR(C, R"IR(
734+
define void @foo(ptr %ptr) {
735+
bb0:
736+
store ptr blockaddress(@foo, %bb0), ptr %ptr
737+
ret void
738+
bb1:
739+
ret void
740+
bb2:
741+
ret void
742+
}
743+
)IR");
744+
Function &LLVMF = *M->getFunction("foo");
745+
sandboxir::Context Ctx(C);
746+
747+
auto &F = *Ctx.createFunction(&LLVMF);
748+
auto *BB0 = cast<sandboxir::BasicBlock>(
749+
Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));
750+
auto *BB1 = cast<sandboxir::BasicBlock>(
751+
Ctx.getValue(getBasicBlockByName(LLVMF, "bb1")));
752+
auto *BB2 = cast<sandboxir::BasicBlock>(
753+
Ctx.getValue(getBasicBlockByName(LLVMF, "bb2")));
754+
auto It = BB0->begin();
755+
auto *SI = cast<sandboxir::StoreInst>(&*It++);
756+
[[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++);
757+
758+
// Check classof(), creation, getFunction(), getBasicBlock().
759+
auto *BB0Addr = cast<sandboxir::BlockAddress>(SI->getValueOperand());
760+
EXPECT_EQ(BB0Addr->getBasicBlock(), BB0);
761+
EXPECT_EQ(BB0Addr->getFunction(), &F);
762+
// Check get(F, BB).
763+
auto *NewBB0Addr = sandboxir::BlockAddress::get(&F, BB0);
764+
EXPECT_EQ(NewBB0Addr, BB0Addr);
765+
// Check get(BB).
766+
auto *NewBB0Addr2 = sandboxir::BlockAddress::get(BB0);
767+
EXPECT_EQ(NewBB0Addr2, BB0Addr);
768+
auto *BB1Addr = sandboxir::BlockAddress::get(BB1);
769+
EXPECT_EQ(BB1Addr->getBasicBlock(), BB1);
770+
EXPECT_NE(BB1Addr, BB0Addr);
771+
// Check lookup().
772+
auto *LookupBB0Addr = sandboxir::BlockAddress::lookup(BB0);
773+
EXPECT_EQ(LookupBB0Addr, BB0Addr);
774+
auto *LookupBB1Addr = sandboxir::BlockAddress::lookup(BB1);
775+
EXPECT_EQ(LookupBB1Addr, BB1Addr);
776+
auto *LookupBB2Addr = sandboxir::BlockAddress::lookup(BB2);
777+
EXPECT_EQ(LookupBB2Addr, nullptr);
778+
}
779+
732780
TEST_F(SandboxIRTest, Use) {
733781
parseIR(C, R"IR(
734782
define i32 @foo(i32 %v0, i32 %v1) {

0 commit comments

Comments
 (0)