Skip to content

Commit eb71849

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

File tree

4 files changed

+274
-26
lines changed

4 files changed

+274
-26
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 100 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ class CallBase;
126126
class CallInst;
127127
class InvokeInst;
128128
class CallBrInst;
129+
class FuncletPadInst;
130+
class CatchPadInst;
131+
class CleanupPadInst;
129132
class GetElementPtrInst;
130133
class CastInst;
131134
class PtrToIntInst;
@@ -240,31 +243,34 @@ class Value {
240243
/// order.
241244
llvm::Value *Val = nullptr;
242245

243-
friend class Context; // For getting `Val`.
244-
friend class User; // For getting `Val`.
245-
friend class Use; // For getting `Val`.
246-
friend class SelectInst; // For getting `Val`.
247-
friend class ExtractElementInst; // For getting `Val`.
248-
friend class InsertElementInst; // For getting `Val`.
249-
friend class BranchInst; // For getting `Val`.
250-
friend class LoadInst; // For getting `Val`.
251-
friend class StoreInst; // For getting `Val`.
252-
friend class ReturnInst; // For getting `Val`.
253-
friend class CallBase; // For getting `Val`.
254-
friend class CallInst; // For getting `Val`.
255-
friend class InvokeInst; // For getting `Val`.
256-
friend class CallBrInst; // For getting `Val`.
257-
friend class GetElementPtrInst; // For getting `Val`.
258-
friend class CatchSwitchInst; // For getting `Val`.
259-
friend class SwitchInst; // For getting `Val`.
260-
friend class UnaryOperator; // For getting `Val`.
261-
friend class BinaryOperator; // For getting `Val`.
262-
friend class AtomicRMWInst; // For getting `Val`.
263-
friend class AtomicCmpXchgInst; // For getting `Val`.
264-
friend class AllocaInst; // For getting `Val`.
265-
friend class CastInst; // For getting `Val`.
266-
friend class PHINode; // For getting `Val`.
267-
friend class UnreachableInst; // For getting `Val`.
246+
friend class Context; // For getting `Val`.
247+
friend class User; // For getting `Val`.
248+
friend class Use; // For getting `Val`.
249+
friend class SelectInst; // For getting `Val`.
250+
friend class ExtractElementInst; // For getting `Val`.
251+
friend class InsertElementInst; // For getting `Val`.
252+
friend class BranchInst; // For getting `Val`.
253+
friend class LoadInst; // For getting `Val`.
254+
friend class StoreInst; // For getting `Val`.
255+
friend class ReturnInst; // For getting `Val`.
256+
friend class CallBase; // For getting `Val`.
257+
friend class CallInst; // For getting `Val`.
258+
friend class InvokeInst; // For getting `Val`.
259+
friend class CallBrInst; // For getting `Val`.
260+
friend class FuncletPadInst; // For getting `Val`.
261+
friend class CatchPadInst; // For getting `Val`.
262+
friend class CleanupPadInst; // For getting `Val`.
263+
friend class GetElementPtrInst; // For getting `Val`.
264+
friend class CatchSwitchInst; // For getting `Val`.
265+
friend class SwitchInst; // For getting `Val`.
266+
friend class UnaryOperator; // For getting `Val`.
267+
friend class BinaryOperator; // For getting `Val`.
268+
friend class AtomicRMWInst; // For getting `Val`.
269+
friend class AtomicCmpXchgInst; // For getting `Val`.
270+
friend class AllocaInst; // For getting `Val`.
271+
friend class CastInst; // For getting `Val`.
272+
friend class PHINode; // For getting `Val`.
273+
friend class UnreachableInst; // For getting `Val`.
268274
friend class CatchSwitchAddHandler; // For `Val`.
269275

270276
/// All values point to the context.
@@ -676,6 +682,8 @@ class Instruction : public sandboxir::User {
676682
friend class CallInst; // For getTopmostLLVMInstruction().
677683
friend class InvokeInst; // For getTopmostLLVMInstruction().
678684
friend class CallBrInst; // For getTopmostLLVMInstruction().
685+
friend class CatchPadInst; // For getTopmostLLVMInstruction().
686+
friend class CleanupPadInst; // For getTopmostLLVMInstruction().
679687
friend class GetElementPtrInst; // For getTopmostLLVMInstruction().
680688
friend class CatchSwitchInst; // For getTopmostLLVMInstruction().
681689
friend class SwitchInst; // For getTopmostLLVMInstruction().
@@ -842,6 +850,7 @@ template <typename LLVMT> class SingleLLVMInstructionImpl : public Instruction {
842850
#include "llvm/SandboxIR/SandboxIRValues.def"
843851
friend class UnaryInstruction;
844852
friend class CallBase;
853+
friend class FuncletPadInst;
845854

846855
Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
847856
return getOperandUseDefault(OpIdx, Verify);
@@ -1394,6 +1403,68 @@ class CallBrInst final : public CallBase {
13941403
}
13951404
};
13961405

1406+
class FuncletPadInst : public SingleLLVMInstructionImpl<llvm::FuncletPadInst> {
1407+
FuncletPadInst(ClassID SubclassID, Opcode Opc, llvm::Instruction *I,
1408+
Context &Ctx)
1409+
: SingleLLVMInstructionImpl(SubclassID, Opc, I, Ctx) {}
1410+
friend class CatchPadInst; // For constructor.
1411+
friend class CleanupPadInst; // For constructor.
1412+
1413+
public:
1414+
/// Return the number of funcletpad arguments.
1415+
unsigned arg_size() const {
1416+
return cast<llvm::FuncletPadInst>(Val)->arg_size();
1417+
}
1418+
/// Return the outer EH-pad this funclet is nested within.
1419+
///
1420+
/// Note: This returns the associated CatchSwitchInst if this FuncletPadInst
1421+
/// is a CatchPadInst.
1422+
Value *getParentPad() const;
1423+
void setParentPad(Value *ParentPad);
1424+
/// Return the Idx-th funcletpad argument.
1425+
Value *getArgOperand(unsigned Idx) const;
1426+
/// Set the Idx-th funcletpad argument.
1427+
void setArgOperand(unsigned Idx, Value *V);
1428+
1429+
// TODO: Implement missing functions: arg_operands().
1430+
static bool classof(const Value *From) {
1431+
return From->getSubclassID() == ClassID::CatchPad ||
1432+
From->getSubclassID() == ClassID::CleanupPad;
1433+
}
1434+
};
1435+
1436+
class CatchPadInst : public FuncletPadInst {
1437+
CatchPadInst(llvm::CatchPadInst *CPI, Context &Ctx)
1438+
: FuncletPadInst(ClassID::CatchPad, Opcode::CatchPad, CPI, Ctx) {}
1439+
friend class Context; // For constructor.
1440+
1441+
public:
1442+
CatchSwitchInst *getCatchSwitch() const;
1443+
// TODO: We have not implemented setCatchSwitch() because we can't revert it
1444+
// for now, as there is no CatchPadInst member function that can undo it.
1445+
1446+
static CatchPadInst *create(Value *ParentPad, ArrayRef<Value *> Args,
1447+
BBIterator WhereIt, BasicBlock *WhereBB,
1448+
Context &Ctx, const Twine &Name = "");
1449+
static bool classof(const Value *From) {
1450+
return From->getSubclassID() == ClassID::CatchPad;
1451+
}
1452+
};
1453+
1454+
class CleanupPadInst : public FuncletPadInst {
1455+
CleanupPadInst(llvm::CleanupPadInst *CPI, Context &Ctx)
1456+
: FuncletPadInst(ClassID::CleanupPad, Opcode::CleanupPad, CPI, Ctx) {}
1457+
friend class Context; // For constructor.
1458+
1459+
public:
1460+
static CleanupPadInst *create(Value *ParentPad, ArrayRef<Value *> Args,
1461+
BBIterator WhereIt, BasicBlock *WhereBB,
1462+
Context &Ctx, const Twine &Name = "");
1463+
static bool classof(const Value *From) {
1464+
return From->getSubclassID() == ClassID::CleanupPad;
1465+
}
1466+
};
1467+
13971468
class GetElementPtrInst final
13981469
: public SingleLLVMInstructionImpl<llvm::GetElementPtrInst> {
13991470
/// Use Context::createGetElementPtrInst(). Don't call
@@ -2294,6 +2365,10 @@ class Context {
22942365
friend InvokeInst; // For createInvokeInst()
22952366
CallBrInst *createCallBrInst(llvm::CallBrInst *I);
22962367
friend CallBrInst; // For createCallBrInst()
2368+
CatchPadInst *createCatchPadInst(llvm::CatchPadInst *I);
2369+
friend CatchPadInst; // For createCatchPadInst()
2370+
CleanupPadInst *createCleanupPadInst(llvm::CleanupPadInst *I);
2371+
friend CleanupPadInst; // For createCleanupPadInst()
22972372
GetElementPtrInst *createGetElementPtrInst(llvm::GetElementPtrInst *I);
22982373
friend GetElementPtrInst; // For createGetElementPtrInst()
22992374
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
@@ -45,6 +45,8 @@ DEF_INSTR(Ret, OP(Ret), ReturnInst)
4545
DEF_INSTR(Call, OP(Call), CallInst)
4646
DEF_INSTR(Invoke, OP(Invoke), InvokeInst)
4747
DEF_INSTR(CallBr, OP(CallBr), CallBrInst)
48+
DEF_INSTR(CatchPad, OP(CatchPad), CatchPadInst)
49+
DEF_INSTR(CleanupPad, OP(CleanupPad), CleanupPadInst)
4850
DEF_INSTR(GetElementPtr, OP(GetElementPtr), GetElementPtrInst)
4951
DEF_INSTR(CatchSwitch, OP(CatchSwitch), CatchSwitchInst)
5052
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,
@@ -1992,6 +2054,18 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
19922054
It->second = std::unique_ptr<CallBrInst>(new CallBrInst(LLVMCallBr, *this));
19932055
return It->second.get();
19942056
}
2057+
case llvm::Instruction::CatchPad: {
2058+
auto *LLVMCPI = cast<llvm::CatchPadInst>(LLVMV);
2059+
It->second =
2060+
std::unique_ptr<CatchPadInst>(new CatchPadInst(LLVMCPI, *this));
2061+
return It->second.get();
2062+
}
2063+
case llvm::Instruction::CleanupPad: {
2064+
auto *LLVMCPI = cast<llvm::CleanupPadInst>(LLVMV);
2065+
It->second =
2066+
std::unique_ptr<CleanupPadInst>(new CleanupPadInst(LLVMCPI, *this));
2067+
return It->second.get();
2068+
}
19952069
case llvm::Instruction::GetElementPtr: {
19962070
auto *LLVMGEP = cast<llvm::GetElementPtrInst>(LLVMV);
19972071
It->second = std::unique_ptr<GetElementPtrInst>(
@@ -2161,7 +2235,14 @@ UnreachableInst *Context::createUnreachableInst(llvm::UnreachableInst *UI) {
21612235
std::unique_ptr<UnreachableInst>(new UnreachableInst(UI, *this));
21622236
return cast<UnreachableInst>(registerValue(std::move(NewPtr)));
21632237
}
2164-
2238+
CatchPadInst *Context::createCatchPadInst(llvm::CatchPadInst *I) {
2239+
auto NewPtr = std::unique_ptr<CatchPadInst>(new CatchPadInst(I, *this));
2240+
return cast<CatchPadInst>(registerValue(std::move(NewPtr)));
2241+
}
2242+
CleanupPadInst *Context::createCleanupPadInst(llvm::CleanupPadInst *I) {
2243+
auto NewPtr = std::unique_ptr<CleanupPadInst>(new CleanupPadInst(I, *this));
2244+
return cast<CleanupPadInst>(registerValue(std::move(NewPtr)));
2245+
}
21652246
GetElementPtrInst *
21662247
Context::createGetElementPtrInst(llvm::GetElementPtrInst *I) {
21672248
auto NewPtr =

llvm/unittests/SandboxIR/SandboxIRTest.cpp

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,6 +1453,96 @@ define void @foo(i8 %arg) {
14531453
}
14541454
}
14551455

1456+
TEST_F(SandboxIRTest, FuncletPadInst_CatchPadInst_CleanupPadInst) {
1457+
parseIR(C, R"IR(
1458+
define void @foo() {
1459+
dispatch:
1460+
%cs = catchswitch within none [label %handler0] unwind to caller
1461+
handler0:
1462+
%catchpad = catchpad within %cs [ptr @foo]
1463+
ret void
1464+
handler1:
1465+
%cleanuppad = cleanuppad within %cs [ptr @foo]
1466+
ret void
1467+
bb:
1468+
ret void
1469+
}
1470+
)IR");
1471+
Function &LLVMF = *M->getFunction("foo");
1472+
BasicBlock *LLVMDispatch = getBasicBlockByName(LLVMF, "dispatch");
1473+
BasicBlock *LLVMHandler0 = getBasicBlockByName(LLVMF, "handler0");
1474+
BasicBlock *LLVMHandler1 = getBasicBlockByName(LLVMF, "handler1");
1475+
auto *LLVMCP = cast<llvm::CatchPadInst>(&*LLVMHandler0->begin());
1476+
auto *LLVMCLP = cast<llvm::CleanupPadInst>(&*LLVMHandler1->begin());
1477+
1478+
sandboxir::Context Ctx(C);
1479+
[[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);
1480+
auto *Dispatch = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMDispatch));
1481+
auto *Handler0 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMHandler0));
1482+
auto *Handler1 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMHandler1));
1483+
auto *BB = cast<sandboxir::BasicBlock>(
1484+
Ctx.getValue(getBasicBlockByName(LLVMF, "bb")));
1485+
auto *BBRet = cast<sandboxir::ReturnInst>(&*BB->begin());
1486+
auto *CS = cast<sandboxir::CatchSwitchInst>(&*Dispatch->begin());
1487+
[[maybe_unused]] auto *CP =
1488+
cast<sandboxir::CatchPadInst>(&*Handler0->begin());
1489+
[[maybe_unused]] auto *CLP =
1490+
cast<sandboxir::CleanupPadInst>(&*Handler1->begin());
1491+
1492+
// Check getCatchSwitch().
1493+
EXPECT_EQ(CP->getCatchSwitch(), CS);
1494+
EXPECT_EQ(CP->getCatchSwitch(), Ctx.getValue(LLVMCP->getCatchSwitch()));
1495+
1496+
for (llvm::FuncletPadInst *LLVMFPI :
1497+
{static_cast<llvm::FuncletPadInst *>(LLVMCP),
1498+
static_cast<llvm::FuncletPadInst *>(LLVMCLP)}) {
1499+
auto *FPI = cast<sandboxir::FuncletPadInst>(Ctx.getValue(LLVMFPI));
1500+
// Check arg_size().
1501+
EXPECT_EQ(FPI->arg_size(), LLVMFPI->arg_size());
1502+
// Check getParentPad().
1503+
EXPECT_EQ(FPI->getParentPad(), Ctx.getValue(LLVMFPI->getParentPad()));
1504+
// Check setParentPad().
1505+
auto *OrigParentPad = FPI->getParentPad();
1506+
auto *NewParentPad = Dispatch;
1507+
EXPECT_NE(NewParentPad, OrigParentPad);
1508+
FPI->setParentPad(NewParentPad);
1509+
EXPECT_EQ(FPI->getParentPad(), NewParentPad);
1510+
FPI->setParentPad(OrigParentPad);
1511+
EXPECT_EQ(FPI->getParentPad(), OrigParentPad);
1512+
// Check getArgOperand().
1513+
for (auto Idx : seq<unsigned>(0, FPI->arg_size()))
1514+
EXPECT_EQ(FPI->getArgOperand(Idx),
1515+
Ctx.getValue(LLVMFPI->getArgOperand(Idx)));
1516+
// Check setArgOperand().
1517+
auto *OrigArgOperand = FPI->getArgOperand(0);
1518+
auto *NewArgOperand = Dispatch;
1519+
EXPECT_NE(NewArgOperand, OrigArgOperand);
1520+
FPI->setArgOperand(0, NewArgOperand);
1521+
EXPECT_EQ(FPI->getArgOperand(0), NewArgOperand);
1522+
FPI->setArgOperand(0, OrigArgOperand);
1523+
EXPECT_EQ(FPI->getArgOperand(0), OrigArgOperand);
1524+
}
1525+
// Check CatchPadInst::create().
1526+
auto *NewCPI = cast<sandboxir::CatchPadInst>(sandboxir::CatchPadInst::create(
1527+
CS, {}, BBRet->getIterator(), BB, Ctx, "NewCPI"));
1528+
EXPECT_EQ(NewCPI->getCatchSwitch(), CS);
1529+
EXPECT_EQ(NewCPI->arg_size(), 0u);
1530+
EXPECT_EQ(NewCPI->getNextNode(), BBRet);
1531+
#ifndef NDEBUG
1532+
EXPECT_EQ(NewCPI->getName(), "NewCPI");
1533+
#endif // NDEBUG
1534+
// Check CleanupPadInst::create().
1535+
auto *NewCLPI =
1536+
cast<sandboxir::CleanupPadInst>(sandboxir::CleanupPadInst::create(
1537+
CS, {}, BBRet->getIterator(), BB, Ctx, "NewCLPI"));
1538+
EXPECT_EQ(NewCLPI->getParentPad(), CS);
1539+
EXPECT_EQ(NewCLPI->arg_size(), 0u);
1540+
EXPECT_EQ(NewCLPI->getNextNode(), BBRet);
1541+
#ifndef NDEBUG
1542+
EXPECT_EQ(NewCLPI->getName(), "NewCLPI");
1543+
#endif // NDEBUG
1544+
}
1545+
14561546
TEST_F(SandboxIRTest, GetElementPtrInstruction) {
14571547
parseIR(C, R"IR(
14581548
define void @foo(ptr %ptr, <2 x ptr> %ptrs) {

0 commit comments

Comments
 (0)