[llvm] [SandboxIR] Implement CallBase and CallInst (PR #100218)
Alina Sbirlea via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 26 10:14:42 PDT 2024
================
@@ -836,3 +836,203 @@ define i8 @foo(i8 %val) {
sandboxir::ReturnInst::create(Val, /*InsertAtEnd=*/BB, Ctx));
EXPECT_EQ(NewRet4->getReturnValue(), Val);
}
+
+TEST_F(SandboxIRTest, CallBase) {
+ parseIR(C, R"IR(
+declare void @bar1(i8)
+declare void @bar2()
+declare void @bar3()
+declare void @variadic(ptr, ...)
+
+define i8 @foo(i8 %arg0, i32 %arg1, ptr %indirectFoo) {
+ %call = call i8 @foo(i8 %arg0, i32 %arg1)
+ call void @bar1(i8 %arg0)
+ call void @bar2()
+ call void %indirectFoo()
+ call void @bar2() noreturn
+ tail call fastcc void @bar2()
+ call void (ptr, ...) @variadic(ptr %indirectFoo, i32 1)
+ ret i8 %call
+}
+)IR");
+ llvm::Function &LLVMF = *M->getFunction("foo");
+ unsigned ArgIdx = 0;
+ llvm::Argument *LLVMArg0 = LLVMF.getArg(ArgIdx++);
+ llvm::Argument *LLVMArg1 = LLVMF.getArg(ArgIdx++);
+ llvm::BasicBlock *LLVMBB = &*LLVMF.begin();
+ SmallVector<llvm::CallBase *, 8> LLVMCalls;
+ auto LLVMIt = LLVMBB->begin();
+ while (isa<llvm::CallBase>(&*LLVMIt))
+ LLVMCalls.push_back(cast<llvm::CallBase>(&*LLVMIt++));
+
+ sandboxir::Context Ctx(C);
+ sandboxir::Function &F = *Ctx.createFunction(&LLVMF);
+
+ for (llvm::CallBase *LLVMCall : LLVMCalls) {
+ // Check classof(Instruction *).
+ auto *Call = cast<sandboxir::CallBase>(Ctx.getValue(LLVMCall));
+ // Check classof(Value *).
+ EXPECT_TRUE(isa<sandboxir::CallBase>((sandboxir::Value *)Call));
+ // Check getFunctionType().
+ EXPECT_EQ(Call->getFunctionType(), LLVMCall->getFunctionType());
+ // Check data_ops().
+ EXPECT_EQ(range_size(Call->data_ops()), range_size(LLVMCall->data_ops()));
+ auto DataOpIt = Call->data_operands_begin();
+ for (llvm::Use &LLVMUse : LLVMCall->data_ops()) {
+ Value *LLVMOp = LLVMUse.get();
+ sandboxir::Use Use = *DataOpIt++;
+ EXPECT_EQ(Ctx.getValue(LLVMOp), Use.get());
+ // Check isDataOperand().
+ EXPECT_EQ(Call->isDataOperand(Use), LLVMCall->isDataOperand(&LLVMUse));
+ // Check getDataOperandNo().
+ EXPECT_EQ(Call->getDataOperandNo(Use),
+ LLVMCall->getDataOperandNo(&LLVMUse));
+ // Check isArgOperand().
+ EXPECT_EQ(Call->isArgOperand(Use), LLVMCall->isArgOperand(&LLVMUse));
+ // Check isCallee().
+ EXPECT_EQ(Call->isCallee(Use), LLVMCall->isCallee(&LLVMUse));
+ }
+ // Check data_operands_empty().
+ EXPECT_EQ(Call->data_operands_empty(), LLVMCall->data_operands_empty());
+ // Check data_operands_size().
+ EXPECT_EQ(Call->data_operands_size(), LLVMCall->data_operands_size());
+ // Check getNumTotalBundleOperands().
+ EXPECT_EQ(Call->getNumTotalBundleOperands(),
+ LLVMCall->getNumTotalBundleOperands());
+ // Check args().
+ EXPECT_EQ(range_size(Call->args()), range_size(LLVMCall->args()));
+ auto ArgIt = Call->arg_begin();
+ for (llvm::Use &LLVMUse : LLVMCall->args()) {
+ Value *LLVMArg = LLVMUse.get();
+ sandboxir::Use Use = *ArgIt++;
+ EXPECT_EQ(Ctx.getValue(LLVMArg), Use.get());
+ }
+ // Check arg_empty().
+ EXPECT_EQ(Call->arg_empty(), LLVMCall->arg_empty());
+ // Check arg_size().
+ EXPECT_EQ(Call->arg_size(), LLVMCall->arg_size());
+ for (unsigned ArgIdx = 0, E = Call->arg_size(); ArgIdx != E; ++ArgIdx) {
+ // Check getArgOperand().
+ EXPECT_EQ(Call->getArgOperand(ArgIdx),
+ Ctx.getValue(LLVMCall->getArgOperand(ArgIdx)));
+ // Check getArgOperandUse().
+ sandboxir::Use Use = Call->getArgOperandUse(ArgIdx);
+ llvm::Use &LLVMUse = LLVMCall->getArgOperandUse(ArgIdx);
+ EXPECT_EQ(Use.get(), Ctx.getValue(LLVMUse.get()));
+ // Check getArgOperandNo().
+ EXPECT_EQ(Call->getArgOperandNo(Use),
+ LLVMCall->getArgOperandNo(&LLVMUse));
+ }
+ // Check hasArgument().
+ SmallVector<llvm::Value *> TestArgs(
+ {LLVMArg0, LLVMArg1, &LLVMF, LLVMBB, LLVMCall});
+ for (llvm::Value *LLVMV : TestArgs) {
+ sandboxir::Value *V = Ctx.getValue(LLVMV);
+ EXPECT_EQ(Call->hasArgument(V), LLVMCall->hasArgument(LLVMV));
+ }
+ // Check getCalledOperand().
+ EXPECT_EQ(Call->getCalledOperand(),
+ Ctx.getValue(LLVMCall->getCalledOperand()));
+ // Check getCalledOperandUse().
+ EXPECT_EQ(Call->getCalledOperandUse().get(),
+ Ctx.getValue(LLVMCall->getCalledOperandUse()));
+ // Check getCalledFunction().
+ if (LLVMCall->getCalledFunction() == nullptr)
+ EXPECT_EQ(Call->getCalledFunction(), nullptr);
+ else {
+ auto *LLVMCF = cast<llvm::Function>(LLVMCall->getCalledFunction());
+ (void)LLVMCF;
+ EXPECT_EQ(Call->getCalledFunction(),
+ cast<sandboxir::Function>(
+ Ctx.getValue(LLVMCall->getCalledFunction())));
+ }
+ // Check isIndirectCall().
+ EXPECT_EQ(Call->isIndirectCall(), LLVMCall->isIndirectCall());
+ // Check getCaller().
+ EXPECT_EQ(Call->getCaller(), Ctx.getValue(LLVMCall->getCaller()));
+ // Check isMustTailCall().
+ EXPECT_EQ(Call->isMustTailCall(), LLVMCall->isMustTailCall());
+ // Check isTailCall().
+ EXPECT_EQ(Call->isTailCall(), LLVMCall->isTailCall());
+ // Check getIntrinsicID().
+ EXPECT_EQ(Call->getIntrinsicID(), LLVMCall->getIntrinsicID());
+ // Check getCallingConv().
+ EXPECT_EQ(Call->getCallingConv(), LLVMCall->getCallingConv());
+ // Check isInlineAsm().
+ EXPECT_EQ(Call->isInlineAsm(), LLVMCall->isInlineAsm());
+ }
+
+ auto *Arg0 = F.getArg(0);
+ auto *Arg1 = F.getArg(1);
+ auto *BB = &*F.begin();
+ auto It = BB->begin();
+ auto *Call0 = cast<sandboxir::CallBase>(&*It++);
+ [[maybe_unused]] auto *Call1 = cast<sandboxir::CallBase>(&*It++);
+ auto *Call2 = cast<sandboxir::CallBase>(&*It++);
+ // Check setArgOperand
+ Call0->setArgOperand(0, Arg1);
+ EXPECT_EQ(Call0->getArgOperand(0), Arg1);
+ Call0->setArgOperand(0, Arg0);
+ EXPECT_EQ(Call0->getArgOperand(0), Arg0);
+
+ auto *Bar3F = Ctx.createFunction(M->getFunction("bar3"));
+
+ // Check setCalledOperand
+ auto *SvOp = Call0->getCalledOperand();
+ Call0->setCalledOperand(Bar3F);
+ EXPECT_EQ(Call0->getCalledOperand(), Bar3F);
+ Call0->setCalledOperand(SvOp);
+ // Check setCalledFunction
+ Call2->setCalledFunction(Bar3F);
+ EXPECT_EQ(Call2->getCalledFunction(), Bar3F);
+}
+
+TEST_F(SandboxIRTest, CallInst) {
+ parseIR(C, R"IR(
+define i8 @foo(i8 %arg) {
+ %call = call i8 @foo(i8 %arg)
+ ret i8 %call
+}
+)IR");
+ Function &LLVMF = *M->getFunction("foo");
+ sandboxir::Context Ctx(C);
+ auto &F = *Ctx.createFunction(&LLVMF);
+ unsigned ArgIdx = 0;
+ auto *Arg0 = F.getArg(ArgIdx++);
+ auto *BB = &*F.begin();
+ auto It = BB->begin();
+ auto *Call = cast<sandboxir::CallInst>(&*It++);
+ auto *Ret = cast<sandboxir::ReturnInst>(&*It++);
+ EXPECT_EQ(Call->getNumOperands(), 2u);
+ EXPECT_EQ(Ret->getOpcode(), sandboxir::Instruction::Opcode::Ret);
+ FunctionType *FTy = F.getFunctionType();
+ SmallVector<sandboxir::Value *, 1> Args;
+ Args.push_back(Arg0);
+ {
+ // Check create() WhereIt.
+ auto *Call = cast<sandboxir::CallInst>(sandboxir::CallInst::create(
+ FTy, &F, Args, /*WhereIt=*/Ret->getIterator(), BB, Ctx));
+ EXPECT_EQ(Call->getNextNode(), Ret);
+ EXPECT_EQ(Call->getCalledFunction(), &F);
+ EXPECT_EQ(range_size(Call->args()), 1u);
+ EXPECT_EQ(Call->getArgOperand(0), Arg0);
+ }
+ {
+ // Check create() InsertBefore.
+ auto *Call = cast<sandboxir::CallInst>(
+ sandboxir::CallInst::create(FTy, &F, Args, /*InsertBefore=*/Ret, Ctx));
+ EXPECT_EQ(Call->getNextNode(), Ret);
+ EXPECT_EQ(Call->getCalledFunction(), &F);
+ EXPECT_EQ(range_size(Call->args()), 1u);
+ EXPECT_EQ(Call->getArgOperand(0), Arg0);
+ }
+ {
+ // Check create() InsertAtEnd.
+ auto *Call = cast<sandboxir::CallInst>(
+ sandboxir::CallInst::create(FTy, &F, Args, /*InsertAtEnd=*/BB, Ctx));
+ EXPECT_EQ(Call->getPrevNode(), Ret);
+ EXPECT_EQ(Call->getCalledFunction(), &F);
+ EXPECT_EQ(range_size(Call->args()), 1u);
+ EXPECT_EQ(Call->getArgOperand(0), Arg0);
+ }
----------------
alinas wrote:
Optional: add a test for dump()?
https://github.com/llvm/llvm-project/pull/100218
More information about the llvm-commits
mailing list