Skip to content

Commit 6311451

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

File tree

4 files changed

+258
-4
lines changed

4 files changed

+258
-4
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 70 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,66 @@ 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+
1061+
static bool classof(const Value *From) {
1062+
return From->getSubclassID() == ClassID::Invoke;
1063+
}
1064+
unsigned getUseOperandNo(const Use &Use) const final {
1065+
return getUseOperandNoDefault(Use);
1066+
}
1067+
unsigned getNumOfIRInstrs() const final { return 1u; }
1068+
BasicBlock *getNormalDest() const;
1069+
BasicBlock *getUnwindDest() const;
1070+
void setNormalDest(BasicBlock *BB);
1071+
void setUnwindDest(BasicBlock *BB);
1072+
// TODO: Return a `LandingPadInst` once implemented.
1073+
Instruction *getLandingPadInst() const;
1074+
BasicBlock *getSuccessor(unsigned SuccIdx) const;
1075+
void setSuccessor(unsigned SuccIdx, BasicBlock *NewSucc) {
1076+
assert(SuccIdx < 2 && "Successor # out of range for invoke!");
1077+
if (SuccIdx == 0)
1078+
setNormalDest(NewSucc);
1079+
else
1080+
setUnwindDest(NewSucc);
1081+
}
1082+
unsigned getNumSuccessors() const {
1083+
return cast<llvm::InvokeInst>(Val)->getNumSuccessors();
1084+
}
1085+
#ifndef NDEBUG
1086+
void verify() const final {}
1087+
friend raw_ostream &operator<<(raw_ostream &OS, const InvokeInst &I) {
1088+
I.dump(OS);
1089+
return OS;
1090+
}
1091+
void dump(raw_ostream &OS) const override;
1092+
LLVM_DUMP_METHOD void dump() const override;
1093+
#endif
1094+
};
1095+
10321096
/// An LLLVM Instruction that has no SandboxIR equivalent class gets mapped to
10331097
/// an OpaqueInstr.
10341098
class OpaqueInst : public sandboxir::Instruction {
@@ -1179,6 +1243,8 @@ class Context {
11791243
friend ReturnInst; // For createReturnInst()
11801244
CallInst *createCallInst(llvm::CallInst *I);
11811245
friend CallInst; // For createCallInst()
1246+
InvokeInst *createInvokeInst(llvm::InvokeInst *I);
1247+
friend InvokeInst; // For createInvokeInst()
11821248

11831249
public:
11841250
Context(LLVMContext &LLVMCtx)

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,72 @@ 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+
BasicBlock *InvokeInst::getNormalDest() const {
844+
return cast<BasicBlock>(
845+
Ctx.getValue(cast<llvm::InvokeInst>(Val)->getNormalDest()));
846+
}
847+
BasicBlock *InvokeInst::getUnwindDest() const {
848+
return cast<BasicBlock>(
849+
Ctx.getValue(cast<llvm::InvokeInst>(Val)->getUnwindDest()));
850+
}
851+
void InvokeInst::setNormalDest(BasicBlock *BB) {
852+
setOperand(1, BB);
853+
assert(getNormalDest() == BB && "LLVM IR uses a different operan index!");
854+
}
855+
void InvokeInst::setUnwindDest(BasicBlock *BB) {
856+
setOperand(2, BB);
857+
assert(getUnwindDest() == BB && "LLVM IR uses a different operan index!");
858+
}
859+
Instruction *InvokeInst::getLandingPadInst() const {
860+
return cast<Instruction>(
861+
Ctx.getValue(cast<llvm::InvokeInst>(Val)->getLandingPadInst()));
862+
;
863+
}
864+
BasicBlock *InvokeInst::getSuccessor(unsigned SuccIdx) const {
865+
return cast<BasicBlock>(
866+
Ctx.getValue(cast<llvm::InvokeInst>(Val)->getSuccessor(SuccIdx)));
867+
}
868+
869+
#ifndef NDEBUG
870+
void InvokeInst::dump(raw_ostream &OS) const {
871+
dumpCommonPrefix(OS);
872+
dumpCommonSuffix(OS);
873+
}
874+
void InvokeInst::dump() const {
875+
dump(dbgs());
876+
dbgs() << "\n";
877+
}
812878

813879
void OpaqueInst::dump(raw_ostream &OS) const {
814880
dumpCommonPrefix(OS);
@@ -968,6 +1034,11 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
9681034
It->second = std::unique_ptr<CallInst>(new CallInst(LLVMCall, *this));
9691035
return It->second.get();
9701036
}
1037+
case llvm::Instruction::Invoke: {
1038+
auto *LLVMInvoke = cast<llvm::InvokeInst>(LLVMV);
1039+
It->second = std::unique_ptr<InvokeInst>(new InvokeInst(LLVMInvoke, *this));
1040+
return It->second.get();
1041+
}
9711042
default:
9721043
break;
9731044
}
@@ -1016,6 +1087,11 @@ CallInst *Context::createCallInst(llvm::CallInst *I) {
10161087
return cast<CallInst>(registerValue(std::move(NewPtr)));
10171088
}
10181089

1090+
InvokeInst *Context::createInvokeInst(llvm::InvokeInst *I) {
1091+
auto NewPtr = std::unique_ptr<InvokeInst>(new InvokeInst(I, *this));
1092+
return cast<InvokeInst>(registerValue(std::move(NewPtr)));
1093+
}
1094+
10191095
Value *Context::getValue(llvm::Value *V) const {
10201096
auto It = LLVMValueToValueMap.find(V);
10211097
if (It != LLVMValueToValueMap.end())

llvm/unittests/SandboxIR/SandboxIRTest.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,3 +1036,59 @@ 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+
[[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);
1059+
auto *BB0 = cast<sandboxir::BasicBlock>(
1060+
Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));
1061+
auto *NormalBB = cast<sandboxir::BasicBlock>(
1062+
Ctx.getValue(getBasicBlockByName(LLVMF, "normal_bb")));
1063+
auto *ExceptionBB = cast<sandboxir::BasicBlock>(
1064+
Ctx.getValue(getBasicBlockByName(LLVMF, "exception_bb")));
1065+
auto *LandingPad = &*ExceptionBB->begin();
1066+
auto *OtherBB = cast<sandboxir::BasicBlock>(
1067+
Ctx.getValue(getBasicBlockByName(LLVMF, "other_bb")));
1068+
auto It = BB0->begin();
1069+
// Check classof(Instruction *).
1070+
auto *Invoke = cast<sandboxir::InvokeInst>(&*It++);
1071+
1072+
// Check getNormalDest().
1073+
EXPECT_EQ(Invoke->getNormalDest(), NormalBB);
1074+
// Check getUnwindDest().
1075+
EXPECT_EQ(Invoke->getUnwindDest(), ExceptionBB);
1076+
// Check getSuccessor().
1077+
EXPECT_EQ(Invoke->getSuccessor(0), NormalBB);
1078+
EXPECT_EQ(Invoke->getSuccessor(1), ExceptionBB);
1079+
// Check setNormalDest().
1080+
Invoke->setNormalDest(OtherBB);
1081+
EXPECT_EQ(Invoke->getNormalDest(), OtherBB);
1082+
EXPECT_EQ(Invoke->getUnwindDest(), ExceptionBB);
1083+
// Check setUnwindDest().
1084+
Invoke->setUnwindDest(OtherBB);
1085+
EXPECT_EQ(Invoke->getNormalDest(), OtherBB);
1086+
EXPECT_EQ(Invoke->getUnwindDest(), OtherBB);
1087+
// Check setSuccessor().
1088+
Invoke->setSuccessor(0, NormalBB);
1089+
EXPECT_EQ(Invoke->getNormalDest(), NormalBB);
1090+
Invoke->setSuccessor(1, ExceptionBB);
1091+
EXPECT_EQ(Invoke->getUnwindDest(), ExceptionBB);
1092+
// Check getLandingPadInst().
1093+
EXPECT_EQ(Invoke->getLandingPadInst(), LandingPad);
1094+
}

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)