Skip to content

[SandboxIR] Implement LandingPadInst #106116

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

Merged
merged 1 commit into from
Aug 26, 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
52 changes: 50 additions & 2 deletions llvm/include/llvm/SandboxIR/SandboxIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ class CallBase;
class CallInst;
class InvokeInst;
class CallBrInst;
class LandingPadInst;
class FuncletPadInst;
class CatchPadInst;
class CleanupPadInst;
Expand Down Expand Up @@ -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`.
Expand Down Expand Up @@ -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().
Expand Down Expand Up @@ -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!");
Expand Down Expand Up @@ -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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems fine for now as the vectorizer will never have to add/remove catch and filters?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this could be added later on, if someone really needs it. It would require some changes in LLVM IR because currently there is no API that would allow us to revert it.


/// 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)
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/SandboxIR/SandboxIRValues.def
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
39 changes: 37 additions & 2 deletions llvm/lib/SandboxIR/SandboxIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
;
}
Expand Down Expand Up @@ -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());
}
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -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)));
Expand Down
61 changes: 61 additions & 0 deletions llvm/unittests/SandboxIR/SandboxIRTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
35 changes: 35 additions & 0 deletions llvm/unittests/SandboxIR/TrackerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
Loading