Skip to content

Commit e8b93ce

Browse files
authored
[SandboxIR] Implement LandingPadInst (#106116)
This patch implements sandboxir::LandingPadInst mirroring llvm::LandingPadInst.
1 parent f05145c commit e8b93ce

File tree

5 files changed

+184
-4
lines changed

5 files changed

+184
-4
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class CallBase;
128128
class CallInst;
129129
class InvokeInst;
130130
class CallBrInst;
131+
class LandingPadInst;
131132
class FuncletPadInst;
132133
class CatchPadInst;
133134
class CleanupPadInst;
@@ -263,6 +264,7 @@ class Value {
263264
friend class CallInst; // For getting `Val`.
264265
friend class InvokeInst; // For getting `Val`.
265266
friend class CallBrInst; // For getting `Val`.
267+
friend class LandingPadInst; // For getting `Val`.
266268
friend class FuncletPadInst; // For getting `Val`.
267269
friend class CatchPadInst; // For getting `Val`.
268270
friend class CleanupPadInst; // For getting `Val`.
@@ -692,6 +694,7 @@ class Instruction : public sandboxir::User {
692694
friend class CallInst; // For getTopmostLLVMInstruction().
693695
friend class InvokeInst; // For getTopmostLLVMInstruction().
694696
friend class CallBrInst; // For getTopmostLLVMInstruction().
697+
friend class LandingPadInst; // For getTopmostLLVMInstruction().
695698
friend class CatchPadInst; // For getTopmostLLVMInstruction().
696699
friend class CleanupPadInst; // For getTopmostLLVMInstruction().
697700
friend class CatchReturnInst; // For getTopmostLLVMInstruction().
@@ -1829,8 +1832,7 @@ class InvokeInst final : public CallBase {
18291832
BasicBlock *getUnwindDest() const;
18301833
void setNormalDest(BasicBlock *BB);
18311834
void setUnwindDest(BasicBlock *BB);
1832-
// TODO: Return a `LandingPadInst` once implemented.
1833-
Instruction *getLandingPadInst() const;
1835+
LandingPadInst *getLandingPadInst() const;
18341836
BasicBlock *getSuccessor(unsigned SuccIdx) const;
18351837
void setSuccessor(unsigned SuccIdx, BasicBlock *NewSucc) {
18361838
assert(SuccIdx < 2 && "Successor # out of range for invoke!");
@@ -1888,6 +1890,50 @@ class CallBrInst final : public CallBase {
18881890
}
18891891
};
18901892

1893+
class LandingPadInst : public SingleLLVMInstructionImpl<llvm::LandingPadInst> {
1894+
LandingPadInst(llvm::LandingPadInst *LP, Context &Ctx)
1895+
: SingleLLVMInstructionImpl(ClassID::LandingPad, Opcode::LandingPad, LP,
1896+
Ctx) {}
1897+
friend class Context; // For constructor.
1898+
1899+
public:
1900+
static LandingPadInst *create(Type *RetTy, unsigned NumReservedClauses,
1901+
BBIterator WhereIt, BasicBlock *WhereBB,
1902+
Context &Ctx, const Twine &Name = "");
1903+
/// Return 'true' if this landingpad instruction is a
1904+
/// cleanup. I.e., it should be run when unwinding even if its landing pad
1905+
/// doesn't catch the exception.
1906+
bool isCleanup() const {
1907+
return cast<llvm::LandingPadInst>(Val)->isCleanup();
1908+
}
1909+
/// Indicate that this landingpad instruction is a cleanup.
1910+
void setCleanup(bool V);
1911+
1912+
// TODO: We are not implementing addClause() because we have no way to revert
1913+
// it for now.
1914+
1915+
/// Get the value of the clause at index Idx. Use isCatch/isFilter to
1916+
/// determine what type of clause this is.
1917+
Constant *getClause(unsigned Idx) const;
1918+
1919+
/// Return 'true' if the clause and index Idx is a catch clause.
1920+
bool isCatch(unsigned Idx) const {
1921+
return cast<llvm::LandingPadInst>(Val)->isCatch(Idx);
1922+
}
1923+
/// Return 'true' if the clause and index Idx is a filter clause.
1924+
bool isFilter(unsigned Idx) const {
1925+
return cast<llvm::LandingPadInst>(Val)->isFilter(Idx);
1926+
}
1927+
/// Get the number of clauses for this landing pad.
1928+
unsigned getNumClauses() const {
1929+
return cast<llvm::LandingPadInst>(Val)->getNumOperands();
1930+
}
1931+
// TODO: We are not implementing reserveClauses() because we can't revert it.
1932+
static bool classof(const Value *From) {
1933+
return From->getSubclassID() == ClassID::LandingPad;
1934+
}
1935+
};
1936+
18911937
class FuncletPadInst : public SingleLLVMInstructionImpl<llvm::FuncletPadInst> {
18921938
FuncletPadInst(ClassID SubclassID, Opcode Opc, llvm::Instruction *I,
18931939
Context &Ctx)
@@ -2908,6 +2954,8 @@ class Context {
29082954
friend InvokeInst; // For createInvokeInst()
29092955
CallBrInst *createCallBrInst(llvm::CallBrInst *I);
29102956
friend CallBrInst; // For createCallBrInst()
2957+
LandingPadInst *createLandingPadInst(llvm::LandingPadInst *I);
2958+
friend LandingPadInst; // For createLandingPadInst()
29112959
CatchPadInst *createCatchPadInst(llvm::CatchPadInst *I);
29122960
friend CatchPadInst; // For createCatchPadInst()
29132961
CleanupPadInst *createCleanupPadInst(llvm::CleanupPadInst *I);

llvm/include/llvm/SandboxIR/SandboxIRValues.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ DEF_INSTR(Ret, OP(Ret), ReturnInst)
4747
DEF_INSTR(Call, OP(Call), CallInst)
4848
DEF_INSTR(Invoke, OP(Invoke), InvokeInst)
4949
DEF_INSTR(CallBr, OP(CallBr), CallBrInst)
50+
DEF_INSTR(LandingPad, OP(LandingPad), LandingPadInst)
5051
DEF_INSTR(CatchPad, OP(CatchPad), CatchPadInst)
5152
DEF_INSTR(CleanupPad, OP(CleanupPad), CleanupPadInst)
5253
DEF_INSTR(CatchRet, OP(CatchRet), CatchReturnInst)

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -972,8 +972,8 @@ void InvokeInst::setUnwindDest(BasicBlock *BB) {
972972
setOperand(2, BB);
973973
assert(getUnwindDest() == BB && "LLVM IR uses a different operan index!");
974974
}
975-
Instruction *InvokeInst::getLandingPadInst() const {
976-
return cast<Instruction>(
975+
LandingPadInst *InvokeInst::getLandingPadInst() const {
976+
return cast<LandingPadInst>(
977977
Ctx.getValue(cast<llvm::InvokeInst>(Val)->getLandingPadInst()));
978978
;
979979
}
@@ -1070,6 +1070,31 @@ BasicBlock *CallBrInst::getSuccessor(unsigned Idx) const {
10701070
Ctx.getValue(cast<llvm::CallBrInst>(Val)->getSuccessor(Idx)));
10711071
}
10721072

1073+
LandingPadInst *LandingPadInst::create(Type *RetTy, unsigned NumReservedClauses,
1074+
BBIterator WhereIt, BasicBlock *WhereBB,
1075+
Context &Ctx, const Twine &Name) {
1076+
auto &Builder = Ctx.getLLVMIRBuilder();
1077+
if (WhereIt != WhereBB->end())
1078+
Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
1079+
else
1080+
Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
1081+
llvm::LandingPadInst *LLVMI =
1082+
Builder.CreateLandingPad(RetTy, NumReservedClauses, Name);
1083+
return Ctx.createLandingPadInst(LLVMI);
1084+
}
1085+
1086+
void LandingPadInst::setCleanup(bool V) {
1087+
Ctx.getTracker()
1088+
.emplaceIfTracking<GenericSetter<&LandingPadInst::isCleanup,
1089+
&LandingPadInst::setCleanup>>(this);
1090+
cast<llvm::LandingPadInst>(Val)->setCleanup(V);
1091+
}
1092+
1093+
Constant *LandingPadInst::getClause(unsigned Idx) const {
1094+
return cast<Constant>(
1095+
Ctx.getValue(cast<llvm::LandingPadInst>(Val)->getClause(Idx)));
1096+
}
1097+
10731098
Value *FuncletPadInst::getParentPad() const {
10741099
return Ctx.getValue(cast<llvm::FuncletPadInst>(Val)->getParentPad());
10751100
}
@@ -2247,6 +2272,12 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
22472272
It->second = std::unique_ptr<CallBrInst>(new CallBrInst(LLVMCallBr, *this));
22482273
return It->second.get();
22492274
}
2275+
case llvm::Instruction::LandingPad: {
2276+
auto *LLVMLPad = cast<llvm::LandingPadInst>(LLVMV);
2277+
It->second =
2278+
std::unique_ptr<LandingPadInst>(new LandingPadInst(LLVMLPad, *this));
2279+
return It->second.get();
2280+
}
22502281
case llvm::Instruction::CatchPad: {
22512282
auto *LLVMCPI = cast<llvm::CatchPadInst>(LLVMV);
22522283
It->second =
@@ -2452,6 +2483,10 @@ UnreachableInst *Context::createUnreachableInst(llvm::UnreachableInst *UI) {
24522483
std::unique_ptr<UnreachableInst>(new UnreachableInst(UI, *this));
24532484
return cast<UnreachableInst>(registerValue(std::move(NewPtr)));
24542485
}
2486+
LandingPadInst *Context::createLandingPadInst(llvm::LandingPadInst *I) {
2487+
auto NewPtr = std::unique_ptr<LandingPadInst>(new LandingPadInst(I, *this));
2488+
return cast<LandingPadInst>(registerValue(std::move(NewPtr)));
2489+
}
24552490
CatchPadInst *Context::createCatchPadInst(llvm::CatchPadInst *I) {
24562491
auto NewPtr = std::unique_ptr<CatchPadInst>(new CatchPadInst(I, *this));
24572492
return cast<CatchPadInst>(registerValue(std::move(NewPtr)));

llvm/unittests/SandboxIR/SandboxIRTest.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1913,6 +1913,67 @@ define void @foo(i8 %arg) {
19131913
}
19141914
}
19151915

1916+
TEST_F(SandboxIRTest, LandingPadInst) {
1917+
parseIR(C, R"IR(
1918+
define void @foo() {
1919+
entry:
1920+
invoke void @foo()
1921+
to label %bb unwind label %unwind
1922+
unwind:
1923+
%lpad = landingpad { ptr, i32 }
1924+
catch ptr null
1925+
ret void
1926+
bb:
1927+
ret void
1928+
}
1929+
)IR");
1930+
Function &LLVMF = *M->getFunction("foo");
1931+
auto *LLVMUnwind = getBasicBlockByName(LLVMF, "unwind");
1932+
auto *LLVMLPad = cast<llvm::LandingPadInst>(&*LLVMUnwind->begin());
1933+
1934+
sandboxir::Context Ctx(C);
1935+
[[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);
1936+
auto *Unwind = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMUnwind));
1937+
auto *BB = cast<sandboxir::BasicBlock>(
1938+
Ctx.getValue(getBasicBlockByName(LLVMF, "bb")));
1939+
auto It = Unwind->begin();
1940+
auto *LPad = cast<sandboxir::LandingPadInst>(&*It++);
1941+
[[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++);
1942+
1943+
// Check isCleanup().
1944+
EXPECT_EQ(LPad->isCleanup(), LLVMLPad->isCleanup());
1945+
// Check setCleanup().
1946+
auto OrigIsCleanup = LPad->isCleanup();
1947+
auto NewIsCleanup = true;
1948+
EXPECT_NE(NewIsCleanup, OrigIsCleanup);
1949+
LPad->setCleanup(NewIsCleanup);
1950+
EXPECT_EQ(LPad->isCleanup(), NewIsCleanup);
1951+
LPad->setCleanup(OrigIsCleanup);
1952+
EXPECT_EQ(LPad->isCleanup(), OrigIsCleanup);
1953+
// Check getNumClauses().
1954+
EXPECT_EQ(LPad->getNumClauses(), LLVMLPad->getNumClauses());
1955+
// Check getClause().
1956+
for (auto Idx : seq<unsigned>(0, LPad->getNumClauses()))
1957+
EXPECT_EQ(LPad->getClause(Idx), Ctx.getValue(LLVMLPad->getClause(Idx)));
1958+
// Check isCatch().
1959+
for (auto Idx : seq<unsigned>(0, LPad->getNumClauses()))
1960+
EXPECT_EQ(LPad->isCatch(Idx), LLVMLPad->isCatch(Idx));
1961+
// Check isFilter().
1962+
for (auto Idx : seq<unsigned>(0, LPad->getNumClauses()))
1963+
EXPECT_EQ(LPad->isFilter(Idx), LLVMLPad->isFilter(Idx));
1964+
// Check create().
1965+
auto *BBRet = &*BB->begin();
1966+
auto *NewLPad =
1967+
cast<sandboxir::LandingPadInst>(sandboxir::LandingPadInst::create(
1968+
Type::getInt8Ty(C), 0, BBRet->getIterator(), BBRet->getParent(), Ctx,
1969+
"NewLPad"));
1970+
EXPECT_EQ(NewLPad->getNextNode(), BBRet);
1971+
EXPECT_FALSE(NewLPad->isCleanup());
1972+
#ifndef NDEBUG
1973+
EXPECT_EQ(NewLPad->getName(), "NewLPad");
1974+
#endif // NDEBUG
1975+
}
1976+
19161977
TEST_F(SandboxIRTest, FuncletPadInst_CatchPadInst_CleanupPadInst) {
19171978
parseIR(C, R"IR(
19181979
define void @foo() {

llvm/unittests/SandboxIR/TrackerTest.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,41 @@ define void @foo(i32 %cond0, i32 %cond1) {
747747
EXPECT_EQ(*HIt++, Handler1);
748748
}
749749

750+
TEST_F(TrackerTest, LandingPadInstSetters) {
751+
parseIR(C, R"IR(
752+
define void @foo() {
753+
entry:
754+
invoke void @foo()
755+
to label %bb unwind label %unwind
756+
unwind:
757+
%lpad = landingpad { ptr, i32 }
758+
catch ptr null
759+
ret void
760+
bb:
761+
ret void
762+
}
763+
)IR");
764+
Function &LLVMF = *M->getFunction("foo");
765+
auto *LLVMUnwind = getBasicBlockByName(LLVMF, "unwind");
766+
767+
sandboxir::Context Ctx(C);
768+
[[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);
769+
auto *Unwind = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMUnwind));
770+
auto It = Unwind->begin();
771+
auto *LPad = cast<sandboxir::LandingPadInst>(&*It++);
772+
[[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++);
773+
774+
// Check setCleanup().
775+
auto OrigIsCleanup = LPad->isCleanup();
776+
auto NewIsCleanup = true;
777+
EXPECT_NE(NewIsCleanup, OrigIsCleanup);
778+
Ctx.save();
779+
LPad->setCleanup(NewIsCleanup);
780+
EXPECT_EQ(LPad->isCleanup(), NewIsCleanup);
781+
Ctx.revert();
782+
EXPECT_EQ(LPad->isCleanup(), OrigIsCleanup);
783+
}
784+
750785
TEST_F(TrackerTest, CatchReturnInstSetters) {
751786
parseIR(C, R"IR(
752787
define void @foo() {

0 commit comments

Comments
 (0)