Skip to content

Commit f147972

Browse files
committed
[SandboxIR] Implement FuncletPadInst, CatchPadInst and CleanupInst
This patch implements sandboxir::FuncletPadInst,CatchInst,CleanupInst mirroring their llvm:: counterparts.
1 parent 716594d commit f147972

File tree

4 files changed

+249
-1
lines changed

4 files changed

+249
-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);
@@ -1845,6 +1854,68 @@ class CallBrInst final : public CallBase {
18451854
}
18461855
};
18471856

1857+
class FuncletPadInst : public SingleLLVMInstructionImpl<llvm::FuncletPadInst> {
1858+
FuncletPadInst(ClassID SubclassID, Opcode Opc, llvm::Instruction *I,
1859+
Context &Ctx)
1860+
: SingleLLVMInstructionImpl(SubclassID, Opc, I, Ctx) {}
1861+
friend class CatchPadInst; // For constructor.
1862+
friend class CleanupPadInst; // For constructor.
1863+
1864+
public:
1865+
/// Return the number of funcletpad arguments.
1866+
unsigned arg_size() const {
1867+
return cast<llvm::FuncletPadInst>(Val)->arg_size();
1868+
}
1869+
/// Return the outer EH-pad this funclet is nested within.
1870+
///
1871+
/// Note: This returns the associated CatchSwitchInst if this FuncletPadInst
1872+
/// is a CatchPadInst.
1873+
Value *getParentPad() const;
1874+
void setParentPad(Value *ParentPad);
1875+
/// Return the Idx-th funcletpad argument.
1876+
Value *getArgOperand(unsigned Idx) const;
1877+
/// Set the Idx-th funcletpad argument.
1878+
void setArgOperand(unsigned Idx, Value *V);
1879+
1880+
// TODO: Implement missing functions: arg_operands().
1881+
static bool classof(const Value *From) {
1882+
return From->getSubclassID() == ClassID::CatchPad ||
1883+
From->getSubclassID() == ClassID::CleanupPad;
1884+
}
1885+
};
1886+
1887+
class CatchPadInst : public FuncletPadInst {
1888+
CatchPadInst(llvm::CatchPadInst *CPI, Context &Ctx)
1889+
: FuncletPadInst(ClassID::CatchPad, Opcode::CatchPad, CPI, Ctx) {}
1890+
friend class Context; // For constructor.
1891+
1892+
public:
1893+
CatchSwitchInst *getCatchSwitch() const;
1894+
// TODO: We have not implemented setCatchSwitch() because we can't revert it
1895+
// for now, as there is no CatchPadInst member function that can undo it.
1896+
1897+
static CatchPadInst *create(Value *ParentPad, ArrayRef<Value *> Args,
1898+
BBIterator WhereIt, BasicBlock *WhereBB,
1899+
Context &Ctx, const Twine &Name = "");
1900+
static bool classof(const Value *From) {
1901+
return From->getSubclassID() == ClassID::CatchPad;
1902+
}
1903+
};
1904+
1905+
class CleanupPadInst : public FuncletPadInst {
1906+
CleanupPadInst(llvm::CleanupPadInst *CPI, Context &Ctx)
1907+
: FuncletPadInst(ClassID::CleanupPad, Opcode::CleanupPad, CPI, Ctx) {}
1908+
friend class Context; // For constructor.
1909+
1910+
public:
1911+
static CleanupPadInst *create(Value *ParentPad, ArrayRef<Value *> Args,
1912+
BBIterator WhereIt, BasicBlock *WhereBB,
1913+
Context &Ctx, const Twine &Name = "");
1914+
static bool classof(const Value *From) {
1915+
return From->getSubclassID() == ClassID::CleanupPad;
1916+
}
1917+
};
1918+
18481919
class GetElementPtrInst final
18491920
: public SingleLLVMInstructionImpl<llvm::GetElementPtrInst> {
18501921
/// Use Context::createGetElementPtrInst(). Don't call
@@ -2747,6 +2818,10 @@ class Context {
27472818
friend InvokeInst; // For createInvokeInst()
27482819
CallBrInst *createCallBrInst(llvm::CallBrInst *I);
27492820
friend CallBrInst; // For createCallBrInst()
2821+
CatchPadInst *createCatchPadInst(llvm::CatchPadInst *I);
2822+
friend CatchPadInst; // For createCatchPadInst()
2823+
CleanupPadInst *createCleanupPadInst(llvm::CleanupPadInst *I);
2824+
friend CleanupPadInst; // For createCleanupPadInst()
27502825
GetElementPtrInst *createGetElementPtrInst(llvm::GetElementPtrInst *I);
27512826
friend GetElementPtrInst; // For createGetElementPtrInst()
27522827
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,
@@ -2059,6 +2121,18 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
20592121
It->second = std::unique_ptr<CallBrInst>(new CallBrInst(LLVMCallBr, *this));
20602122
return It->second.get();
20612123
}
2124+
case llvm::Instruction::CatchPad: {
2125+
auto *LLVMCPI = cast<llvm::CatchPadInst>(LLVMV);
2126+
It->second =
2127+
std::unique_ptr<CatchPadInst>(new CatchPadInst(LLVMCPI, *this));
2128+
return It->second.get();
2129+
}
2130+
case llvm::Instruction::CleanupPad: {
2131+
auto *LLVMCPI = cast<llvm::CleanupPadInst>(LLVMV);
2132+
It->second =
2133+
std::unique_ptr<CleanupPadInst>(new CleanupPadInst(LLVMCPI, *this));
2134+
return It->second.get();
2135+
}
20622136
case llvm::Instruction::GetElementPtr: {
20632137
auto *LLVMGEP = cast<llvm::GetElementPtrInst>(LLVMV);
20642138
It->second = std::unique_ptr<GetElementPtrInst>(
@@ -2235,7 +2309,14 @@ UnreachableInst *Context::createUnreachableInst(llvm::UnreachableInst *UI) {
22352309
std::unique_ptr<UnreachableInst>(new UnreachableInst(UI, *this));
22362310
return cast<UnreachableInst>(registerValue(std::move(NewPtr)));
22372311
}
2238-
2312+
CatchPadInst *Context::createCatchPadInst(llvm::CatchPadInst *I) {
2313+
auto NewPtr = std::unique_ptr<CatchPadInst>(new CatchPadInst(I, *this));
2314+
return cast<CatchPadInst>(registerValue(std::move(NewPtr)));
2315+
}
2316+
CleanupPadInst *Context::createCleanupPadInst(llvm::CleanupPadInst *I) {
2317+
auto NewPtr = std::unique_ptr<CleanupPadInst>(new CleanupPadInst(I, *this));
2318+
return cast<CleanupPadInst>(registerValue(std::move(NewPtr)));
2319+
}
22392320
GetElementPtrInst *
22402321
Context::createGetElementPtrInst(llvm::GetElementPtrInst *I) {
22412322
auto NewPtr =

llvm/unittests/SandboxIR/SandboxIRTest.cpp

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,6 +1870,96 @@ define void @foo(i8 %arg) {
18701870
}
18711871
}
18721872

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

0 commit comments

Comments
 (0)