Skip to content

Commit c80d0dc

Browse files
committed
[SandboxIR] Implement InvokeInst
This patch implements sandboxir::InvokeInst which mirrors llvm::InvokeInst.
1 parent 372a6be commit c80d0dc

File tree

4 files changed

+306
-4
lines changed

4 files changed

+306
-4
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@
3030
// |
3131
// +- CastInst
3232
// |
33-
// +- CallBase ----- CallInst
34-
// |
35-
// +- CmpInst
33+
// +- CallBase ------+- CallInst
34+
// | |
35+
// +- CmpInst +- InvokeInst
3636
// |
3737
// +- ExtractElementInst
3838
// |
@@ -90,6 +90,7 @@ class User;
9090
class Value;
9191
class CallBase;
9292
class CallInst;
93+
class InvokeInst;
9394

9495
/// Iterator for the `Use` edges of a User's operands.
9596
/// \Returns the operand `Use` when dereferenced.
@@ -203,6 +204,7 @@ class Value {
203204
friend class ReturnInst; // For getting `Val`.
204205
friend class CallBase; // For getting `Val`.
205206
friend class CallInst; // For getting `Val`.
207+
friend class InvokeInst; // For getting `Val`.
206208

207209
/// All values point to the context.
208210
Context &Ctx;
@@ -541,6 +543,7 @@ class Instruction : public sandboxir::User {
541543
friend class StoreInst; // For getTopmostLLVMInstruction().
542544
friend class ReturnInst; // For getTopmostLLVMInstruction().
543545
friend class CallInst; // For getTopmostLLVMInstruction().
546+
friend class InvokeInst; // For getTopmostLLVMInstruction().
544547

545548
/// \Returns the LLVM IR Instructions that this SandboxIR maps to in program
546549
/// order.
@@ -861,7 +864,8 @@ class ReturnInst final : public Instruction {
861864
class CallBase : public Instruction {
862865
CallBase(ClassID ID, Opcode Opc, llvm::Instruction *I, Context &Ctx)
863866
: Instruction(ID, Opc, I, Ctx) {}
864-
friend class CallInst; // For constructor.
867+
friend class CallInst; // For constructor.
868+
friend class InvokeInst; // For constructor.
865869

866870
public:
867871
static bool classof(const Value *From) {
@@ -1029,6 +1033,70 @@ class CallInst final : public CallBase {
10291033
#endif
10301034
};
10311035

1036+
class InvokeInst final : public CallBase {
1037+
/// Use Context::createInvokeInst(). Don't call the
1038+
/// constructor directly.
1039+
InvokeInst(llvm::Instruction *I, Context &Ctx)
1040+
: CallBase(ClassID::Invoke, Opcode::Invoke, I, Ctx) {}
1041+
friend class Context; // For accessing the constructor in
1042+
// create*()
1043+
Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
1044+
return getOperandUseDefault(OpIdx, Verify);
1045+
}
1046+
SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
1047+
return {cast<llvm::Instruction>(Val)};
1048+
}
1049+
1050+
public:
1051+
static InvokeInst *create(FunctionType *FTy, Value *Func,
1052+
BasicBlock *IfNormal, BasicBlock *IfException,
1053+
ArrayRef<Value *> Args, BBIterator WhereIt,
1054+
BasicBlock *WhereBB, Context &Ctx,
1055+
const Twine &NameStr = "");
1056+
static InvokeInst *create(FunctionType *FTy, Value *Func,
1057+
BasicBlock *IfNormal, BasicBlock *IfException,
1058+
ArrayRef<Value *> Args, Instruction *InsertBefore,
1059+
Context &Ctx, const Twine &NameStr = "");
1060+
static InvokeInst *create(FunctionType *FTy, Value *Func,
1061+
BasicBlock *IfNormal, BasicBlock *IfException,
1062+
ArrayRef<Value *> Args, BasicBlock *InsertAtEnd,
1063+
Context &Ctx, const Twine &NameStr = "");
1064+
1065+
static bool classof(const Value *From) {
1066+
return From->getSubclassID() == ClassID::Invoke;
1067+
}
1068+
unsigned getUseOperandNo(const Use &Use) const final {
1069+
return getUseOperandNoDefault(Use);
1070+
}
1071+
unsigned getNumOfIRInstrs() const final { return 1u; }
1072+
BasicBlock *getNormalDest() const;
1073+
BasicBlock *getUnwindDest() const;
1074+
void setNormalDest(BasicBlock *BB);
1075+
void setUnwindDest(BasicBlock *BB);
1076+
// TODO: Return a `LandingPadInst` once implemented.
1077+
Instruction *getLandingPadInst() const;
1078+
BasicBlock *getSuccessor(unsigned SuccIdx) const;
1079+
void setSuccessor(unsigned SuccIdx, BasicBlock *NewSucc) {
1080+
assert(SuccIdx < 2 && "Successor # out of range for invoke!");
1081+
if (SuccIdx == 0)
1082+
setNormalDest(NewSucc);
1083+
else
1084+
setUnwindDest(NewSucc);
1085+
}
1086+
unsigned getNumSuccessors() const {
1087+
return cast<llvm::InvokeInst>(Val)->getNumSuccessors();
1088+
}
1089+
#ifndef NDEBUG
1090+
void verify() const final {}
1091+
friend raw_ostream &operator<<(raw_ostream &OS, const InvokeInst &I) {
1092+
I.dump(OS);
1093+
return OS;
1094+
}
1095+
void dump(raw_ostream &OS) const override;
1096+
LLVM_DUMP_METHOD void dump() const override;
1097+
#endif
1098+
};
1099+
10321100
/// An LLLVM Instruction that has no SandboxIR equivalent class gets mapped to
10331101
/// an OpaqueInstr.
10341102
class OpaqueInst : public sandboxir::Instruction {
@@ -1179,6 +1247,8 @@ class Context {
11791247
friend ReturnInst; // For createReturnInst()
11801248
CallInst *createCallInst(llvm::CallInst *I);
11811249
friend CallInst; // For createCallInst()
1250+
InvokeInst *createInvokeInst(llvm::InvokeInst *I);
1251+
friend InvokeInst; // For createInvokeInst()
11821252

11831253
public:
11841254
Context(LLVMContext &LLVMCtx)

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,81 @@ void CallInst::dump() const {
809809
dump(dbgs());
810810
dbgs() << "\n";
811811
}
812+
#endif // NDEBUG
813+
814+
InvokeInst *InvokeInst::create(FunctionType *FTy, Value *Func,
815+
BasicBlock *IfNormal, BasicBlock *IfException,
816+
ArrayRef<Value *> Args, BBIterator WhereIt,
817+
BasicBlock *WhereBB, Context &Ctx,
818+
const Twine &NameStr) {
819+
auto &Builder = Ctx.getLLVMIRBuilder();
820+
if (WhereIt != WhereBB->end())
821+
Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
822+
else
823+
Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
824+
SmallVector<llvm::Value *> LLVMArgs;
825+
LLVMArgs.reserve(Args.size());
826+
for (Value *Arg : Args)
827+
LLVMArgs.push_back(Arg->Val);
828+
llvm::InvokeInst *Invoke = Builder.CreateInvoke(
829+
FTy, Func->Val, cast<llvm::BasicBlock>(IfNormal->Val),
830+
cast<llvm::BasicBlock>(IfException->Val), LLVMArgs, NameStr);
831+
return Ctx.createInvokeInst(Invoke);
832+
}
833+
834+
InvokeInst *InvokeInst::create(FunctionType *FTy, Value *Func,
835+
BasicBlock *IfNormal, BasicBlock *IfException,
836+
ArrayRef<Value *> Args,
837+
Instruction *InsertBefore, Context &Ctx,
838+
const Twine &NameStr) {
839+
return create(FTy, Func, IfNormal, IfException, Args,
840+
InsertBefore->getIterator(), InsertBefore->getParent(), Ctx,
841+
NameStr);
842+
}
843+
844+
InvokeInst *InvokeInst::create(FunctionType *FTy, Value *Func,
845+
BasicBlock *IfNormal, BasicBlock *IfException,
846+
ArrayRef<Value *> Args, BasicBlock *InsertAtEnd,
847+
Context &Ctx, const Twine &NameStr) {
848+
return create(FTy, Func, IfNormal, IfException, Args, InsertAtEnd->end(),
849+
InsertAtEnd, Ctx, NameStr);
850+
}
851+
852+
BasicBlock *InvokeInst::getNormalDest() const {
853+
return cast<BasicBlock>(
854+
Ctx.getValue(cast<llvm::InvokeInst>(Val)->getNormalDest()));
855+
}
856+
BasicBlock *InvokeInst::getUnwindDest() const {
857+
return cast<BasicBlock>(
858+
Ctx.getValue(cast<llvm::InvokeInst>(Val)->getUnwindDest()));
859+
}
860+
void InvokeInst::setNormalDest(BasicBlock *BB) {
861+
setOperand(1, BB);
862+
assert(getNormalDest() == BB && "LLVM IR uses a different operan index!");
863+
}
864+
void InvokeInst::setUnwindDest(BasicBlock *BB) {
865+
setOperand(2, BB);
866+
assert(getUnwindDest() == BB && "LLVM IR uses a different operan index!");
867+
}
868+
Instruction *InvokeInst::getLandingPadInst() const {
869+
return cast<Instruction>(
870+
Ctx.getValue(cast<llvm::InvokeInst>(Val)->getLandingPadInst()));
871+
;
872+
}
873+
BasicBlock *InvokeInst::getSuccessor(unsigned SuccIdx) const {
874+
return cast<BasicBlock>(
875+
Ctx.getValue(cast<llvm::InvokeInst>(Val)->getSuccessor(SuccIdx)));
876+
}
877+
878+
#ifndef NDEBUG
879+
void InvokeInst::dump(raw_ostream &OS) const {
880+
dumpCommonPrefix(OS);
881+
dumpCommonSuffix(OS);
882+
}
883+
void InvokeInst::dump() const {
884+
dump(dbgs());
885+
dbgs() << "\n";
886+
}
812887

813888
void OpaqueInst::dump(raw_ostream &OS) const {
814889
dumpCommonPrefix(OS);
@@ -968,6 +1043,11 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
9681043
It->second = std::unique_ptr<CallInst>(new CallInst(LLVMCall, *this));
9691044
return It->second.get();
9701045
}
1046+
case llvm::Instruction::Invoke: {
1047+
auto *LLVMInvoke = cast<llvm::InvokeInst>(LLVMV);
1048+
It->second = std::unique_ptr<InvokeInst>(new InvokeInst(LLVMInvoke, *this));
1049+
return It->second.get();
1050+
}
9711051
default:
9721052
break;
9731053
}
@@ -1016,6 +1096,11 @@ CallInst *Context::createCallInst(llvm::CallInst *I) {
10161096
return cast<CallInst>(registerValue(std::move(NewPtr)));
10171097
}
10181098

1099+
InvokeInst *Context::createInvokeInst(llvm::InvokeInst *I) {
1100+
auto NewPtr = std::unique_ptr<InvokeInst>(new InvokeInst(I, *this));
1101+
return cast<InvokeInst>(registerValue(std::move(NewPtr)));
1102+
}
1103+
10191104
Value *Context::getValue(llvm::Value *V) const {
10201105
auto It = LLVMValueToValueMap.find(V);
10211106
if (It != LLVMValueToValueMap.end())

llvm/unittests/SandboxIR/SandboxIRTest.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,3 +1036,94 @@ define i8 @foo(i8 %arg) {
10361036
EXPECT_EQ(Call->getArgOperand(0), Arg0);
10371037
}
10381038
}
1039+
1040+
TEST_F(SandboxIRTest, InvokeInst) {
1041+
parseIR(C, R"IR(
1042+
define void @foo(i8 %arg) {
1043+
bb0:
1044+
invoke i8 @foo(i8 %arg) to label %normal_bb
1045+
unwind label %exception_bb
1046+
normal_bb:
1047+
ret void
1048+
exception_bb:
1049+
%lpad = landingpad { ptr, i32}
1050+
cleanup
1051+
ret void
1052+
other_bb:
1053+
ret void
1054+
}
1055+
)IR");
1056+
Function &LLVMF = *M->getFunction("foo");
1057+
sandboxir::Context Ctx(C);
1058+
auto &F = *Ctx.createFunction(&LLVMF);
1059+
auto *Arg = F.getArg(0);
1060+
auto *BB0 = cast<sandboxir::BasicBlock>(
1061+
Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));
1062+
auto *NormalBB = cast<sandboxir::BasicBlock>(
1063+
Ctx.getValue(getBasicBlockByName(LLVMF, "normal_bb")));
1064+
auto *ExceptionBB = cast<sandboxir::BasicBlock>(
1065+
Ctx.getValue(getBasicBlockByName(LLVMF, "exception_bb")));
1066+
auto *LandingPad = &*ExceptionBB->begin();
1067+
auto *OtherBB = cast<sandboxir::BasicBlock>(
1068+
Ctx.getValue(getBasicBlockByName(LLVMF, "other_bb")));
1069+
auto It = BB0->begin();
1070+
// Check classof(Instruction *).
1071+
auto *Invoke = cast<sandboxir::InvokeInst>(&*It++);
1072+
1073+
// Check getNormalDest().
1074+
EXPECT_EQ(Invoke->getNormalDest(), NormalBB);
1075+
// Check getUnwindDest().
1076+
EXPECT_EQ(Invoke->getUnwindDest(), ExceptionBB);
1077+
// Check getSuccessor().
1078+
EXPECT_EQ(Invoke->getSuccessor(0), NormalBB);
1079+
EXPECT_EQ(Invoke->getSuccessor(1), ExceptionBB);
1080+
// Check setNormalDest().
1081+
Invoke->setNormalDest(OtherBB);
1082+
EXPECT_EQ(Invoke->getNormalDest(), OtherBB);
1083+
EXPECT_EQ(Invoke->getUnwindDest(), ExceptionBB);
1084+
// Check setUnwindDest().
1085+
Invoke->setUnwindDest(OtherBB);
1086+
EXPECT_EQ(Invoke->getNormalDest(), OtherBB);
1087+
EXPECT_EQ(Invoke->getUnwindDest(), OtherBB);
1088+
// Check setSuccessor().
1089+
Invoke->setSuccessor(0, NormalBB);
1090+
EXPECT_EQ(Invoke->getNormalDest(), NormalBB);
1091+
Invoke->setSuccessor(1, ExceptionBB);
1092+
EXPECT_EQ(Invoke->getUnwindDest(), ExceptionBB);
1093+
// Check getLandingPadInst().
1094+
EXPECT_EQ(Invoke->getLandingPadInst(), LandingPad);
1095+
1096+
{
1097+
// Check create() WhereIt, WhereBB.
1098+
SmallVector<sandboxir::Value *> Args({Arg});
1099+
auto *InsertBefore = &*BB0->begin();
1100+
auto *NewInvoke = cast<sandboxir::InvokeInst>(sandboxir::InvokeInst::create(
1101+
F.getFunctionType(), &F, NormalBB, ExceptionBB, Args,
1102+
/*WhereIt=*/InsertBefore->getIterator(), /*WhereBB=*/BB0, Ctx));
1103+
EXPECT_EQ(NewInvoke->getNormalDest(), NormalBB);
1104+
EXPECT_EQ(NewInvoke->getUnwindDest(), ExceptionBB);
1105+
EXPECT_EQ(NewInvoke->getNextNode(), InsertBefore);
1106+
}
1107+
{
1108+
// Check create() InsertBefore.
1109+
SmallVector<sandboxir::Value *> Args({Arg});
1110+
auto *InsertBefore = &*BB0->begin();
1111+
auto *NewInvoke = cast<sandboxir::InvokeInst>(
1112+
sandboxir::InvokeInst::create(F.getFunctionType(), &F, NormalBB,
1113+
ExceptionBB, Args, InsertBefore, Ctx));
1114+
EXPECT_EQ(NewInvoke->getNormalDest(), NormalBB);
1115+
EXPECT_EQ(NewInvoke->getUnwindDest(), ExceptionBB);
1116+
EXPECT_EQ(NewInvoke->getNextNode(), InsertBefore);
1117+
}
1118+
{
1119+
// Check create() InsertAtEnd.
1120+
SmallVector<sandboxir::Value *> Args({Arg});
1121+
auto *NewInvoke = cast<sandboxir::InvokeInst>(sandboxir::InvokeInst::create(
1122+
F.getFunctionType(), &F, NormalBB, ExceptionBB, Args,
1123+
/*InsertAtEnd=*/BB0, Ctx));
1124+
EXPECT_EQ(NewInvoke->getNormalDest(), NormalBB);
1125+
EXPECT_EQ(NewInvoke->getUnwindDest(), ExceptionBB);
1126+
EXPECT_EQ(NewInvoke->getParent(), BB0);
1127+
EXPECT_EQ(NewInvoke->getNextNode(), nullptr);
1128+
}
1129+
}

llvm/unittests/SandboxIR/TrackerTest.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,3 +488,59 @@ define void @foo(i8 %arg0, i8 %arg1) {
488488
Ctx.revert();
489489
EXPECT_EQ(Call->getCalledFunction(), Bar1F);
490490
}
491+
492+
TEST_F(TrackerTest, InvokeSetters) {
493+
parseIR(C, R"IR(
494+
define void @foo(i8 %arg) {
495+
bb0:
496+
invoke i8 @foo(i8 %arg) to label %normal_bb
497+
unwind label %exception_bb
498+
normal_bb:
499+
ret void
500+
exception_bb:
501+
ret void
502+
other_bb:
503+
ret void
504+
}
505+
)IR");
506+
Function &LLVMF = *M->getFunction("foo");
507+
sandboxir::Context Ctx(C);
508+
[[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);
509+
auto *BB0 = cast<sandboxir::BasicBlock>(
510+
Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));
511+
auto *NormalBB = cast<sandboxir::BasicBlock>(
512+
Ctx.getValue(getBasicBlockByName(LLVMF, "normal_bb")));
513+
auto *ExceptionBB = cast<sandboxir::BasicBlock>(
514+
Ctx.getValue(getBasicBlockByName(LLVMF, "exception_bb")));
515+
auto *OtherBB = cast<sandboxir::BasicBlock>(
516+
Ctx.getValue(getBasicBlockByName(LLVMF, "other_bb")));
517+
auto It = BB0->begin();
518+
auto *Invoke = cast<sandboxir::InvokeInst>(&*It++);
519+
520+
// Check setNormalDest().
521+
Ctx.save();
522+
Invoke->setNormalDest(OtherBB);
523+
EXPECT_EQ(Invoke->getNormalDest(), OtherBB);
524+
Ctx.revert();
525+
EXPECT_EQ(Invoke->getNormalDest(), NormalBB);
526+
527+
// Check setUnwindDest().
528+
Ctx.save();
529+
Invoke->setUnwindDest(OtherBB);
530+
EXPECT_EQ(Invoke->getUnwindDest(), OtherBB);
531+
Ctx.revert();
532+
EXPECT_EQ(Invoke->getUnwindDest(), ExceptionBB);
533+
534+
// Check setSuccessor().
535+
Ctx.save();
536+
Invoke->setSuccessor(0, OtherBB);
537+
EXPECT_EQ(Invoke->getSuccessor(0), OtherBB);
538+
Ctx.revert();
539+
EXPECT_EQ(Invoke->getSuccessor(0), NormalBB);
540+
541+
Ctx.save();
542+
Invoke->setSuccessor(1, OtherBB);
543+
EXPECT_EQ(Invoke->getSuccessor(1), OtherBB);
544+
Ctx.revert();
545+
EXPECT_EQ(Invoke->getSuccessor(1), ExceptionBB);
546+
}

0 commit comments

Comments
 (0)