Skip to content

Commit 7854b16

Browse files
authored
[SandboxIR] Implement FuncletPadInst, CatchPadInst and CleanupInst (llvm#105294)
This patch implements sandboxir::FuncletPadInst,CatchInst,CleanupInst mirroring their llvm:: counterparts.
1 parent 8e0b9c8 commit 7854b16

File tree

5 files changed

+300
-1
lines changed

5 files changed

+300
-1
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ class CallBase;
127127
class CallInst;
128128
class InvokeInst;
129129
class CallBrInst;
130+
class FuncletPadInst;
131+
class CatchPadInst;
132+
class CleanupPadInst;
130133
class GetElementPtrInst;
131134
class CastInst;
132135
class PtrToIntInst;
@@ -256,6 +259,9 @@ class Value {
256259
friend class CallInst; // For getting `Val`.
257260
friend class InvokeInst; // For getting `Val`.
258261
friend class CallBrInst; // For getting `Val`.
262+
friend class FuncletPadInst; // For getting `Val`.
263+
friend class CatchPadInst; // For getting `Val`.
264+
friend class CleanupPadInst; // For getting `Val`.
259265
friend class GetElementPtrInst; // For getting `Val`.
260266
friend class CatchSwitchInst; // For getting `Val`.
261267
friend class SwitchInst; // For getting `Val`.
@@ -679,6 +685,8 @@ class Instruction : public sandboxir::User {
679685
friend class CallInst; // For getTopmostLLVMInstruction().
680686
friend class InvokeInst; // For getTopmostLLVMInstruction().
681687
friend class CallBrInst; // For getTopmostLLVMInstruction().
688+
friend class CatchPadInst; // For getTopmostLLVMInstruction().
689+
friend class CleanupPadInst; // For getTopmostLLVMInstruction().
682690
friend class GetElementPtrInst; // For getTopmostLLVMInstruction().
683691
friend class CatchSwitchInst; // For getTopmostLLVMInstruction().
684692
friend class SwitchInst; // For getTopmostLLVMInstruction().
@@ -845,6 +853,7 @@ template <typename LLVMT> class SingleLLVMInstructionImpl : public Instruction {
845853
#include "llvm/SandboxIR/SandboxIRValues.def"
846854
friend class UnaryInstruction;
847855
friend class CallBase;
856+
friend class FuncletPadInst;
848857

849858
Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
850859
return getOperandUseDefault(OpIdx, Verify);
@@ -1843,6 +1852,68 @@ class CallBrInst final : public CallBase {
18431852
}
18441853
};
18451854

1855+
class FuncletPadInst : public SingleLLVMInstructionImpl<llvm::FuncletPadInst> {
1856+
FuncletPadInst(ClassID SubclassID, Opcode Opc, llvm::Instruction *I,
1857+
Context &Ctx)
1858+
: SingleLLVMInstructionImpl(SubclassID, Opc, I, Ctx) {}
1859+
friend class CatchPadInst; // For constructor.
1860+
friend class CleanupPadInst; // For constructor.
1861+
1862+
public:
1863+
/// Return the number of funcletpad arguments.
1864+
unsigned arg_size() const {
1865+
return cast<llvm::FuncletPadInst>(Val)->arg_size();
1866+
}
1867+
/// Return the outer EH-pad this funclet is nested within.
1868+
///
1869+
/// Note: This returns the associated CatchSwitchInst if this FuncletPadInst
1870+
/// is a CatchPadInst.
1871+
Value *getParentPad() const;
1872+
void setParentPad(Value *ParentPad);
1873+
/// Return the Idx-th funcletpad argument.
1874+
Value *getArgOperand(unsigned Idx) const;
1875+
/// Set the Idx-th funcletpad argument.
1876+
void setArgOperand(unsigned Idx, Value *V);
1877+
1878+
// TODO: Implement missing functions: arg_operands().
1879+
static bool classof(const Value *From) {
1880+
return From->getSubclassID() == ClassID::CatchPad ||
1881+
From->getSubclassID() == ClassID::CleanupPad;
1882+
}
1883+
};
1884+
1885+
class CatchPadInst : public FuncletPadInst {
1886+
CatchPadInst(llvm::CatchPadInst *CPI, Context &Ctx)
1887+
: FuncletPadInst(ClassID::CatchPad, Opcode::CatchPad, CPI, Ctx) {}
1888+
friend class Context; // For constructor.
1889+
1890+
public:
1891+
CatchSwitchInst *getCatchSwitch() const;
1892+
// TODO: We have not implemented setCatchSwitch() because we can't revert it
1893+
// for now, as there is no CatchPadInst member function that can undo it.
1894+
1895+
static CatchPadInst *create(Value *ParentPad, ArrayRef<Value *> Args,
1896+
BBIterator WhereIt, BasicBlock *WhereBB,
1897+
Context &Ctx, const Twine &Name = "");
1898+
static bool classof(const Value *From) {
1899+
return From->getSubclassID() == ClassID::CatchPad;
1900+
}
1901+
};
1902+
1903+
class CleanupPadInst : public FuncletPadInst {
1904+
CleanupPadInst(llvm::CleanupPadInst *CPI, Context &Ctx)
1905+
: FuncletPadInst(ClassID::CleanupPad, Opcode::CleanupPad, CPI, Ctx) {}
1906+
friend class Context; // For constructor.
1907+
1908+
public:
1909+
static CleanupPadInst *create(Value *ParentPad, ArrayRef<Value *> Args,
1910+
BBIterator WhereIt, BasicBlock *WhereBB,
1911+
Context &Ctx, const Twine &Name = "");
1912+
static bool classof(const Value *From) {
1913+
return From->getSubclassID() == ClassID::CleanupPad;
1914+
}
1915+
};
1916+
18461917
class GetElementPtrInst final
18471918
: public SingleLLVMInstructionImpl<llvm::GetElementPtrInst> {
18481919
/// Use Context::createGetElementPtrInst(). Don't call
@@ -2745,6 +2816,10 @@ class Context {
27452816
friend InvokeInst; // For createInvokeInst()
27462817
CallBrInst *createCallBrInst(llvm::CallBrInst *I);
27472818
friend CallBrInst; // For createCallBrInst()
2819+
CatchPadInst *createCatchPadInst(llvm::CatchPadInst *I);
2820+
friend CatchPadInst; // For createCatchPadInst()
2821+
CleanupPadInst *createCleanupPadInst(llvm::CleanupPadInst *I);
2822+
friend CleanupPadInst; // For createCleanupPadInst()
27482823
GetElementPtrInst *createGetElementPtrInst(llvm::GetElementPtrInst *I);
27492824
friend GetElementPtrInst; // For createGetElementPtrInst()
27502825
CatchSwitchInst *createCatchSwitchInst(llvm::CatchSwitchInst *I);

llvm/include/llvm/SandboxIR/SandboxIRValues.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ DEF_INSTR(Ret, OP(Ret), ReturnInst)
4646
DEF_INSTR(Call, OP(Call), CallInst)
4747
DEF_INSTR(Invoke, OP(Invoke), InvokeInst)
4848
DEF_INSTR(CallBr, OP(CallBr), CallBrInst)
49+
DEF_INSTR(CatchPad, OP(CatchPad), CatchPadInst)
50+
DEF_INSTR(CleanupPad, OP(CleanupPad), CleanupPadInst)
4951
DEF_INSTR(GetElementPtr, OP(GetElementPtr), GetElementPtrInst)
5052
DEF_INSTR(CatchSwitch, OP(CatchSwitch), CatchSwitchInst)
5153
DEF_INSTR(Switch, OP(Switch), SwitchInst)

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,68 @@ BasicBlock *CallBrInst::getSuccessor(unsigned Idx) const {
10431043
Ctx.getValue(cast<llvm::CallBrInst>(Val)->getSuccessor(Idx)));
10441044
}
10451045

1046+
Value *FuncletPadInst::getParentPad() const {
1047+
return Ctx.getValue(cast<llvm::FuncletPadInst>(Val)->getParentPad());
1048+
}
1049+
1050+
void FuncletPadInst::setParentPad(Value *ParentPad) {
1051+
Ctx.getTracker()
1052+
.emplaceIfTracking<GenericSetter<&FuncletPadInst::getParentPad,
1053+
&FuncletPadInst::setParentPad>>(this);
1054+
cast<llvm::FuncletPadInst>(Val)->setParentPad(ParentPad->Val);
1055+
}
1056+
1057+
Value *FuncletPadInst::getArgOperand(unsigned Idx) const {
1058+
return Ctx.getValue(cast<llvm::FuncletPadInst>(Val)->getArgOperand(Idx));
1059+
}
1060+
1061+
void FuncletPadInst::setArgOperand(unsigned Idx, Value *V) {
1062+
Ctx.getTracker()
1063+
.emplaceIfTracking<GenericSetterWithIdx<&FuncletPadInst::getArgOperand,
1064+
&FuncletPadInst::setArgOperand>>(
1065+
this, Idx);
1066+
cast<llvm::FuncletPadInst>(Val)->setArgOperand(Idx, V->Val);
1067+
}
1068+
1069+
CatchSwitchInst *CatchPadInst::getCatchSwitch() const {
1070+
return cast<CatchSwitchInst>(
1071+
Ctx.getValue(cast<llvm::CatchPadInst>(Val)->getCatchSwitch()));
1072+
}
1073+
1074+
CatchPadInst *CatchPadInst::create(Value *ParentPad, ArrayRef<Value *> Args,
1075+
BBIterator WhereIt, BasicBlock *WhereBB,
1076+
Context &Ctx, const Twine &Name) {
1077+
auto &Builder = Ctx.getLLVMIRBuilder();
1078+
if (WhereIt != WhereBB->end())
1079+
Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
1080+
else
1081+
Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
1082+
SmallVector<llvm::Value *> LLVMArgs;
1083+
LLVMArgs.reserve(Args.size());
1084+
for (auto *Arg : Args)
1085+
LLVMArgs.push_back(Arg->Val);
1086+
llvm::CatchPadInst *LLVMI =
1087+
Builder.CreateCatchPad(ParentPad->Val, LLVMArgs, Name);
1088+
return Ctx.createCatchPadInst(LLVMI);
1089+
}
1090+
1091+
CleanupPadInst *CleanupPadInst::create(Value *ParentPad, ArrayRef<Value *> Args,
1092+
BBIterator WhereIt, BasicBlock *WhereBB,
1093+
Context &Ctx, const Twine &Name) {
1094+
auto &Builder = Ctx.getLLVMIRBuilder();
1095+
if (WhereIt != WhereBB->end())
1096+
Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
1097+
else
1098+
Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
1099+
SmallVector<llvm::Value *> LLVMArgs;
1100+
LLVMArgs.reserve(Args.size());
1101+
for (auto *Arg : Args)
1102+
LLVMArgs.push_back(Arg->Val);
1103+
llvm::CleanupPadInst *LLVMI =
1104+
Builder.CreateCleanupPad(ParentPad->Val, LLVMArgs, Name);
1105+
return Ctx.createCleanupPadInst(LLVMI);
1106+
}
1107+
10461108
Value *GetElementPtrInst::create(Type *Ty, Value *Ptr,
10471109
ArrayRef<Value *> IdxList,
10481110
BasicBlock::iterator WhereIt,
@@ -2064,6 +2126,18 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
20642126
It->second = std::unique_ptr<CallBrInst>(new CallBrInst(LLVMCallBr, *this));
20652127
return It->second.get();
20662128
}
2129+
case llvm::Instruction::CatchPad: {
2130+
auto *LLVMCPI = cast<llvm::CatchPadInst>(LLVMV);
2131+
It->second =
2132+
std::unique_ptr<CatchPadInst>(new CatchPadInst(LLVMCPI, *this));
2133+
return It->second.get();
2134+
}
2135+
case llvm::Instruction::CleanupPad: {
2136+
auto *LLVMCPI = cast<llvm::CleanupPadInst>(LLVMV);
2137+
It->second =
2138+
std::unique_ptr<CleanupPadInst>(new CleanupPadInst(LLVMCPI, *this));
2139+
return It->second.get();
2140+
}
20672141
case llvm::Instruction::GetElementPtr: {
20682142
auto *LLVMGEP = cast<llvm::GetElementPtrInst>(LLVMV);
20692143
It->second = std::unique_ptr<GetElementPtrInst>(
@@ -2240,7 +2314,14 @@ UnreachableInst *Context::createUnreachableInst(llvm::UnreachableInst *UI) {
22402314
std::unique_ptr<UnreachableInst>(new UnreachableInst(UI, *this));
22412315
return cast<UnreachableInst>(registerValue(std::move(NewPtr)));
22422316
}
2243-
2317+
CatchPadInst *Context::createCatchPadInst(llvm::CatchPadInst *I) {
2318+
auto NewPtr = std::unique_ptr<CatchPadInst>(new CatchPadInst(I, *this));
2319+
return cast<CatchPadInst>(registerValue(std::move(NewPtr)));
2320+
}
2321+
CleanupPadInst *Context::createCleanupPadInst(llvm::CleanupPadInst *I) {
2322+
auto NewPtr = std::unique_ptr<CleanupPadInst>(new CleanupPadInst(I, *this));
2323+
return cast<CleanupPadInst>(registerValue(std::move(NewPtr)));
2324+
}
22442325
GetElementPtrInst *
22452326
Context::createGetElementPtrInst(llvm::GetElementPtrInst *I) {
22462327
auto NewPtr =

llvm/unittests/SandboxIR/SandboxIRTest.cpp

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1867,6 +1867,96 @@ define void @foo(i8 %arg) {
18671867
}
18681868
}
18691869

1870+
TEST_F(SandboxIRTest, FuncletPadInst_CatchPadInst_CleanupPadInst) {
1871+
parseIR(C, R"IR(
1872+
define void @foo() {
1873+
dispatch:
1874+
%cs = catchswitch within none [label %handler0] unwind to caller
1875+
handler0:
1876+
%catchpad = catchpad within %cs [ptr @foo]
1877+
ret void
1878+
handler1:
1879+
%cleanuppad = cleanuppad within %cs [ptr @foo]
1880+
ret void
1881+
bb:
1882+
ret void
1883+
}
1884+
)IR");
1885+
Function &LLVMF = *M->getFunction("foo");
1886+
BasicBlock *LLVMDispatch = getBasicBlockByName(LLVMF, "dispatch");
1887+
BasicBlock *LLVMHandler0 = getBasicBlockByName(LLVMF, "handler0");
1888+
BasicBlock *LLVMHandler1 = getBasicBlockByName(LLVMF, "handler1");
1889+
auto *LLVMCP = cast<llvm::CatchPadInst>(&*LLVMHandler0->begin());
1890+
auto *LLVMCLP = cast<llvm::CleanupPadInst>(&*LLVMHandler1->begin());
1891+
1892+
sandboxir::Context Ctx(C);
1893+
[[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);
1894+
auto *Dispatch = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMDispatch));
1895+
auto *Handler0 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMHandler0));
1896+
auto *Handler1 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMHandler1));
1897+
auto *BB = cast<sandboxir::BasicBlock>(
1898+
Ctx.getValue(getBasicBlockByName(LLVMF, "bb")));
1899+
auto *BBRet = cast<sandboxir::ReturnInst>(&*BB->begin());
1900+
auto *CS = cast<sandboxir::CatchSwitchInst>(&*Dispatch->begin());
1901+
[[maybe_unused]] auto *CP =
1902+
cast<sandboxir::CatchPadInst>(&*Handler0->begin());
1903+
[[maybe_unused]] auto *CLP =
1904+
cast<sandboxir::CleanupPadInst>(&*Handler1->begin());
1905+
1906+
// Check getCatchSwitch().
1907+
EXPECT_EQ(CP->getCatchSwitch(), CS);
1908+
EXPECT_EQ(CP->getCatchSwitch(), Ctx.getValue(LLVMCP->getCatchSwitch()));
1909+
1910+
for (llvm::FuncletPadInst *LLVMFPI :
1911+
{static_cast<llvm::FuncletPadInst *>(LLVMCP),
1912+
static_cast<llvm::FuncletPadInst *>(LLVMCLP)}) {
1913+
auto *FPI = cast<sandboxir::FuncletPadInst>(Ctx.getValue(LLVMFPI));
1914+
// Check arg_size().
1915+
EXPECT_EQ(FPI->arg_size(), LLVMFPI->arg_size());
1916+
// Check getParentPad().
1917+
EXPECT_EQ(FPI->getParentPad(), Ctx.getValue(LLVMFPI->getParentPad()));
1918+
// Check setParentPad().
1919+
auto *OrigParentPad = FPI->getParentPad();
1920+
auto *NewParentPad = Dispatch;
1921+
EXPECT_NE(NewParentPad, OrigParentPad);
1922+
FPI->setParentPad(NewParentPad);
1923+
EXPECT_EQ(FPI->getParentPad(), NewParentPad);
1924+
FPI->setParentPad(OrigParentPad);
1925+
EXPECT_EQ(FPI->getParentPad(), OrigParentPad);
1926+
// Check getArgOperand().
1927+
for (auto Idx : seq<unsigned>(0, FPI->arg_size()))
1928+
EXPECT_EQ(FPI->getArgOperand(Idx),
1929+
Ctx.getValue(LLVMFPI->getArgOperand(Idx)));
1930+
// Check setArgOperand().
1931+
auto *OrigArgOperand = FPI->getArgOperand(0);
1932+
auto *NewArgOperand = Dispatch;
1933+
EXPECT_NE(NewArgOperand, OrigArgOperand);
1934+
FPI->setArgOperand(0, NewArgOperand);
1935+
EXPECT_EQ(FPI->getArgOperand(0), NewArgOperand);
1936+
FPI->setArgOperand(0, OrigArgOperand);
1937+
EXPECT_EQ(FPI->getArgOperand(0), OrigArgOperand);
1938+
}
1939+
// Check CatchPadInst::create().
1940+
auto *NewCPI = cast<sandboxir::CatchPadInst>(sandboxir::CatchPadInst::create(
1941+
CS, {}, BBRet->getIterator(), BB, Ctx, "NewCPI"));
1942+
EXPECT_EQ(NewCPI->getCatchSwitch(), CS);
1943+
EXPECT_EQ(NewCPI->arg_size(), 0u);
1944+
EXPECT_EQ(NewCPI->getNextNode(), BBRet);
1945+
#ifndef NDEBUG
1946+
EXPECT_EQ(NewCPI->getName(), "NewCPI");
1947+
#endif // NDEBUG
1948+
// Check CleanupPadInst::create().
1949+
auto *NewCLPI =
1950+
cast<sandboxir::CleanupPadInst>(sandboxir::CleanupPadInst::create(
1951+
CS, {}, BBRet->getIterator(), BB, Ctx, "NewCLPI"));
1952+
EXPECT_EQ(NewCLPI->getParentPad(), CS);
1953+
EXPECT_EQ(NewCLPI->arg_size(), 0u);
1954+
EXPECT_EQ(NewCLPI->getNextNode(), BBRet);
1955+
#ifndef NDEBUG
1956+
EXPECT_EQ(NewCLPI->getName(), "NewCLPI");
1957+
#endif // NDEBUG
1958+
}
1959+
18701960
TEST_F(SandboxIRTest, GetElementPtrInstruction) {
18711961
parseIR(C, R"IR(
18721962
define void @foo(ptr %ptr, <2 x ptr> %ptrs) {

llvm/unittests/SandboxIR/TrackerTest.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,57 @@ define void @foo(i8 %arg) {
10331033
EXPECT_EQ(CallBr->getIndirectDest(0), OrigIndirectDest);
10341034
}
10351035

1036+
TEST_F(TrackerTest, FuncletPadInstSetters) {
1037+
parseIR(C, R"IR(
1038+
define void @foo() {
1039+
dispatch:
1040+
%cs = catchswitch within none [label %handler0] unwind to caller
1041+
handler0:
1042+
%catchpad = catchpad within %cs [ptr @foo]
1043+
ret void
1044+
handler1:
1045+
%cleanuppad = cleanuppad within %cs [ptr @foo]
1046+
ret void
1047+
bb:
1048+
ret void
1049+
}
1050+
)IR");
1051+
Function &LLVMF = *M->getFunction("foo");
1052+
sandboxir::Context Ctx(C);
1053+
[[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);
1054+
auto *Dispatch = cast<sandboxir::BasicBlock>(
1055+
Ctx.getValue(getBasicBlockByName(LLVMF, "dispatch")));
1056+
auto *Handler0 = cast<sandboxir::BasicBlock>(
1057+
Ctx.getValue(getBasicBlockByName(LLVMF, "handler0")));
1058+
auto *Handler1 = cast<sandboxir::BasicBlock>(
1059+
Ctx.getValue(getBasicBlockByName(LLVMF, "handler1")));
1060+
auto *CP = cast<sandboxir::CatchPadInst>(&*Handler0->begin());
1061+
auto *CLP = cast<sandboxir::CleanupPadInst>(&*Handler1->begin());
1062+
1063+
for (auto *FPI : {static_cast<sandboxir::FuncletPadInst *>(CP),
1064+
static_cast<sandboxir::FuncletPadInst *>(CLP)}) {
1065+
// Check setParentPad().
1066+
auto *OrigParentPad = FPI->getParentPad();
1067+
auto *NewParentPad = Dispatch;
1068+
EXPECT_NE(NewParentPad, OrigParentPad);
1069+
Ctx.save();
1070+
FPI->setParentPad(NewParentPad);
1071+
EXPECT_EQ(FPI->getParentPad(), NewParentPad);
1072+
Ctx.revert();
1073+
EXPECT_EQ(FPI->getParentPad(), OrigParentPad);
1074+
1075+
// Check setArgOperand().
1076+
auto *OrigArgOperand = FPI->getArgOperand(0);
1077+
auto *NewArgOperand = Dispatch;
1078+
EXPECT_NE(NewArgOperand, OrigArgOperand);
1079+
Ctx.save();
1080+
FPI->setArgOperand(0, NewArgOperand);
1081+
EXPECT_EQ(FPI->getArgOperand(0), NewArgOperand);
1082+
Ctx.revert();
1083+
EXPECT_EQ(FPI->getArgOperand(0), OrigArgOperand);
1084+
}
1085+
}
1086+
10361087
TEST_F(TrackerTest, PHINodeSetters) {
10371088
parseIR(C, R"IR(
10381089
define void @foo(i8 %arg0, i8 %arg1, i8 %arg2) {

0 commit comments

Comments
 (0)