[llvm] [SandboxIR] Implement LandingPadInst (PR #106116)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 26 11:37:44 PDT 2024
https://github.com/vporpo created https://github.com/llvm/llvm-project/pull/106116
This patch implements sandboxir::LandingPadInst mirroring llvm::LandingPadInst.
>From 3e0a40c0c0fc2507419685da1f94400dd30ec834 Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Thu, 15 Aug 2024 15:29:04 -0700
Subject: [PATCH] [SandboxIR] Implement LandingPadInst
This patch implements sandboxir::LandingPadInst mirroring llvm::LandingPadInst.
---
llvm/include/llvm/SandboxIR/SandboxIR.h | 52 +++++++++++++++-
.../llvm/SandboxIR/SandboxIRValues.def | 1 +
llvm/lib/SandboxIR/SandboxIR.cpp | 39 +++++++++++-
llvm/unittests/SandboxIR/SandboxIRTest.cpp | 61 +++++++++++++++++++
llvm/unittests/SandboxIR/TrackerTest.cpp | 35 +++++++++++
5 files changed, 184 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h
index 32e23ddfcafeed..06f05f88c9c082 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIR.h
+++ b/llvm/include/llvm/SandboxIR/SandboxIR.h
@@ -128,6 +128,7 @@ class CallBase;
class CallInst;
class InvokeInst;
class CallBrInst;
+class LandingPadInst;
class FuncletPadInst;
class CatchPadInst;
class CleanupPadInst;
@@ -263,6 +264,7 @@ class Value {
friend class CallInst; // For getting `Val`.
friend class InvokeInst; // For getting `Val`.
friend class CallBrInst; // For getting `Val`.
+ friend class LandingPadInst; // For getting `Val`.
friend class FuncletPadInst; // For getting `Val`.
friend class CatchPadInst; // For getting `Val`.
friend class CleanupPadInst; // For getting `Val`.
@@ -692,6 +694,7 @@ class Instruction : public sandboxir::User {
friend class CallInst; // For getTopmostLLVMInstruction().
friend class InvokeInst; // For getTopmostLLVMInstruction().
friend class CallBrInst; // For getTopmostLLVMInstruction().
+ friend class LandingPadInst; // For getTopmostLLVMInstruction().
friend class CatchPadInst; // For getTopmostLLVMInstruction().
friend class CleanupPadInst; // For getTopmostLLVMInstruction().
friend class CatchReturnInst; // For getTopmostLLVMInstruction().
@@ -1829,8 +1832,7 @@ class InvokeInst final : public CallBase {
BasicBlock *getUnwindDest() const;
void setNormalDest(BasicBlock *BB);
void setUnwindDest(BasicBlock *BB);
- // TODO: Return a `LandingPadInst` once implemented.
- Instruction *getLandingPadInst() const;
+ LandingPadInst *getLandingPadInst() const;
BasicBlock *getSuccessor(unsigned SuccIdx) const;
void setSuccessor(unsigned SuccIdx, BasicBlock *NewSucc) {
assert(SuccIdx < 2 && "Successor # out of range for invoke!");
@@ -1888,6 +1890,50 @@ class CallBrInst final : public CallBase {
}
};
+class LandingPadInst : public SingleLLVMInstructionImpl<llvm::LandingPadInst> {
+ LandingPadInst(llvm::LandingPadInst *LP, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::LandingPad, Opcode::LandingPad, LP,
+ Ctx) {}
+ friend class Context; // For constructor.
+
+public:
+ static LandingPadInst *create(Type *RetTy, unsigned NumReservedClauses,
+ BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx, const Twine &Name = "");
+ /// Return 'true' if this landingpad instruction is a
+ /// cleanup. I.e., it should be run when unwinding even if its landing pad
+ /// doesn't catch the exception.
+ bool isCleanup() const {
+ return cast<llvm::LandingPadInst>(Val)->isCleanup();
+ }
+ /// Indicate that this landingpad instruction is a cleanup.
+ void setCleanup(bool V);
+
+ // TODO: We are not implementing addClause() because we have no way to revert
+ // it for now.
+
+ /// Get the value of the clause at index Idx. Use isCatch/isFilter to
+ /// determine what type of clause this is.
+ Constant *getClause(unsigned Idx) const;
+
+ /// Return 'true' if the clause and index Idx is a catch clause.
+ bool isCatch(unsigned Idx) const {
+ return cast<llvm::LandingPadInst>(Val)->isCatch(Idx);
+ }
+ /// Return 'true' if the clause and index Idx is a filter clause.
+ bool isFilter(unsigned Idx) const {
+ return cast<llvm::LandingPadInst>(Val)->isFilter(Idx);
+ }
+ /// Get the number of clauses for this landing pad.
+ unsigned getNumClauses() const {
+ return cast<llvm::LandingPadInst>(Val)->getNumOperands();
+ }
+ // TODO: We are not implementing reserveClauses() because we can't revert it.
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::LandingPad;
+ }
+};
+
class FuncletPadInst : public SingleLLVMInstructionImpl<llvm::FuncletPadInst> {
FuncletPadInst(ClassID SubclassID, Opcode Opc, llvm::Instruction *I,
Context &Ctx)
@@ -2908,6 +2954,8 @@ class Context {
friend InvokeInst; // For createInvokeInst()
CallBrInst *createCallBrInst(llvm::CallBrInst *I);
friend CallBrInst; // For createCallBrInst()
+ LandingPadInst *createLandingPadInst(llvm::LandingPadInst *I);
+ friend LandingPadInst; // For createLandingPadInst()
CatchPadInst *createCatchPadInst(llvm::CatchPadInst *I);
friend CatchPadInst; // For createCatchPadInst()
CleanupPadInst *createCleanupPadInst(llvm::CleanupPadInst *I);
diff --git a/llvm/include/llvm/SandboxIR/SandboxIRValues.def b/llvm/include/llvm/SandboxIR/SandboxIRValues.def
index 7bac00fb2918a4..a74e7adfeab139 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIRValues.def
+++ b/llvm/include/llvm/SandboxIR/SandboxIRValues.def
@@ -47,6 +47,7 @@ DEF_INSTR(Ret, OP(Ret), ReturnInst)
DEF_INSTR(Call, OP(Call), CallInst)
DEF_INSTR(Invoke, OP(Invoke), InvokeInst)
DEF_INSTR(CallBr, OP(CallBr), CallBrInst)
+DEF_INSTR(LandingPad, OP(LandingPad), LandingPadInst)
DEF_INSTR(CatchPad, OP(CatchPad), CatchPadInst)
DEF_INSTR(CleanupPad, OP(CleanupPad), CleanupPadInst)
DEF_INSTR(CatchRet, OP(CatchRet), CatchReturnInst)
diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index 559fb4d10fff52..31992b043e9fc6 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -972,8 +972,8 @@ void InvokeInst::setUnwindDest(BasicBlock *BB) {
setOperand(2, BB);
assert(getUnwindDest() == BB && "LLVM IR uses a different operan index!");
}
-Instruction *InvokeInst::getLandingPadInst() const {
- return cast<Instruction>(
+LandingPadInst *InvokeInst::getLandingPadInst() const {
+ return cast<LandingPadInst>(
Ctx.getValue(cast<llvm::InvokeInst>(Val)->getLandingPadInst()));
;
}
@@ -1070,6 +1070,31 @@ BasicBlock *CallBrInst::getSuccessor(unsigned Idx) const {
Ctx.getValue(cast<llvm::CallBrInst>(Val)->getSuccessor(Idx)));
}
+LandingPadInst *LandingPadInst::create(Type *RetTy, unsigned NumReservedClauses,
+ BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx, const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ llvm::LandingPadInst *LLVMI =
+ Builder.CreateLandingPad(RetTy, NumReservedClauses, Name);
+ return Ctx.createLandingPadInst(LLVMI);
+}
+
+void LandingPadInst::setCleanup(bool V) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&LandingPadInst::isCleanup,
+ &LandingPadInst::setCleanup>>(this);
+ cast<llvm::LandingPadInst>(Val)->setCleanup(V);
+}
+
+Constant *LandingPadInst::getClause(unsigned Idx) const {
+ return cast<Constant>(
+ Ctx.getValue(cast<llvm::LandingPadInst>(Val)->getClause(Idx)));
+}
+
Value *FuncletPadInst::getParentPad() const {
return Ctx.getValue(cast<llvm::FuncletPadInst>(Val)->getParentPad());
}
@@ -2247,6 +2272,12 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
It->second = std::unique_ptr<CallBrInst>(new CallBrInst(LLVMCallBr, *this));
return It->second.get();
}
+ case llvm::Instruction::LandingPad: {
+ auto *LLVMLPad = cast<llvm::LandingPadInst>(LLVMV);
+ It->second =
+ std::unique_ptr<LandingPadInst>(new LandingPadInst(LLVMLPad, *this));
+ return It->second.get();
+ }
case llvm::Instruction::CatchPad: {
auto *LLVMCPI = cast<llvm::CatchPadInst>(LLVMV);
It->second =
@@ -2452,6 +2483,10 @@ UnreachableInst *Context::createUnreachableInst(llvm::UnreachableInst *UI) {
std::unique_ptr<UnreachableInst>(new UnreachableInst(UI, *this));
return cast<UnreachableInst>(registerValue(std::move(NewPtr)));
}
+LandingPadInst *Context::createLandingPadInst(llvm::LandingPadInst *I) {
+ auto NewPtr = std::unique_ptr<LandingPadInst>(new LandingPadInst(I, *this));
+ return cast<LandingPadInst>(registerValue(std::move(NewPtr)));
+}
CatchPadInst *Context::createCatchPadInst(llvm::CatchPadInst *I) {
auto NewPtr = std::unique_ptr<CatchPadInst>(new CatchPadInst(I, *this));
return cast<CatchPadInst>(registerValue(std::move(NewPtr)));
diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
index a7192ac98af41a..eb405b11be351c 100644
--- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp
+++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
@@ -1913,6 +1913,67 @@ define void @foo(i8 %arg) {
}
}
+TEST_F(SandboxIRTest, LandingPadInst) {
+ parseIR(C, R"IR(
+define void @foo() {
+entry:
+ invoke void @foo()
+ to label %bb unwind label %unwind
+unwind:
+ %lpad = landingpad { ptr, i32 }
+ catch ptr null
+ ret void
+bb:
+ ret void
+}
+)IR");
+ Function &LLVMF = *M->getFunction("foo");
+ auto *LLVMUnwind = getBasicBlockByName(LLVMF, "unwind");
+ auto *LLVMLPad = cast<llvm::LandingPadInst>(&*LLVMUnwind->begin());
+
+ sandboxir::Context Ctx(C);
+ [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);
+ auto *Unwind = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMUnwind));
+ auto *BB = cast<sandboxir::BasicBlock>(
+ Ctx.getValue(getBasicBlockByName(LLVMF, "bb")));
+ auto It = Unwind->begin();
+ auto *LPad = cast<sandboxir::LandingPadInst>(&*It++);
+ [[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++);
+
+ // Check isCleanup().
+ EXPECT_EQ(LPad->isCleanup(), LLVMLPad->isCleanup());
+ // Check setCleanup().
+ auto OrigIsCleanup = LPad->isCleanup();
+ auto NewIsCleanup = true;
+ EXPECT_NE(NewIsCleanup, OrigIsCleanup);
+ LPad->setCleanup(NewIsCleanup);
+ EXPECT_EQ(LPad->isCleanup(), NewIsCleanup);
+ LPad->setCleanup(OrigIsCleanup);
+ EXPECT_EQ(LPad->isCleanup(), OrigIsCleanup);
+ // Check getNumClauses().
+ EXPECT_EQ(LPad->getNumClauses(), LLVMLPad->getNumClauses());
+ // Check getClause().
+ for (auto Idx : seq<unsigned>(0, LPad->getNumClauses()))
+ EXPECT_EQ(LPad->getClause(Idx), Ctx.getValue(LLVMLPad->getClause(Idx)));
+ // Check isCatch().
+ for (auto Idx : seq<unsigned>(0, LPad->getNumClauses()))
+ EXPECT_EQ(LPad->isCatch(Idx), LLVMLPad->isCatch(Idx));
+ // Check isFilter().
+ for (auto Idx : seq<unsigned>(0, LPad->getNumClauses()))
+ EXPECT_EQ(LPad->isFilter(Idx), LLVMLPad->isFilter(Idx));
+ // Check create().
+ auto *BBRet = &*BB->begin();
+ auto *NewLPad =
+ cast<sandboxir::LandingPadInst>(sandboxir::LandingPadInst::create(
+ Type::getInt8Ty(C), 0, BBRet->getIterator(), BBRet->getParent(), Ctx,
+ "NewLPad"));
+ EXPECT_EQ(NewLPad->getNextNode(), BBRet);
+ EXPECT_FALSE(NewLPad->isCleanup());
+#ifndef NDEBUG
+ EXPECT_EQ(NewLPad->getName(), "NewLPad");
+#endif // NDEBUG
+}
+
TEST_F(SandboxIRTest, FuncletPadInst_CatchPadInst_CleanupPadInst) {
parseIR(C, R"IR(
define void @foo() {
diff --git a/llvm/unittests/SandboxIR/TrackerTest.cpp b/llvm/unittests/SandboxIR/TrackerTest.cpp
index 5f04cbd5840ba5..a1059d6fa64274 100644
--- a/llvm/unittests/SandboxIR/TrackerTest.cpp
+++ b/llvm/unittests/SandboxIR/TrackerTest.cpp
@@ -747,6 +747,41 @@ define void @foo(i32 %cond0, i32 %cond1) {
EXPECT_EQ(*HIt++, Handler1);
}
+TEST_F(TrackerTest, LandingPadInstSetters) {
+ parseIR(C, R"IR(
+define void @foo() {
+entry:
+ invoke void @foo()
+ to label %bb unwind label %unwind
+unwind:
+ %lpad = landingpad { ptr, i32 }
+ catch ptr null
+ ret void
+bb:
+ ret void
+}
+)IR");
+ Function &LLVMF = *M->getFunction("foo");
+ auto *LLVMUnwind = getBasicBlockByName(LLVMF, "unwind");
+
+ sandboxir::Context Ctx(C);
+ [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);
+ auto *Unwind = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMUnwind));
+ auto It = Unwind->begin();
+ auto *LPad = cast<sandboxir::LandingPadInst>(&*It++);
+ [[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++);
+
+ // Check setCleanup().
+ auto OrigIsCleanup = LPad->isCleanup();
+ auto NewIsCleanup = true;
+ EXPECT_NE(NewIsCleanup, OrigIsCleanup);
+ Ctx.save();
+ LPad->setCleanup(NewIsCleanup);
+ EXPECT_EQ(LPad->isCleanup(), NewIsCleanup);
+ Ctx.revert();
+ EXPECT_EQ(LPad->isCleanup(), OrigIsCleanup);
+}
+
TEST_F(TrackerTest, CatchReturnInstSetters) {
parseIR(C, R"IR(
define void @foo() {
More information about the llvm-commits
mailing list