aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/IR
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/unittests/IR')
-rw-r--r--llvm/unittests/IR/AbstractCallSiteTest.cpp94
1 files changed, 93 insertions, 1 deletions
diff --git a/llvm/unittests/IR/AbstractCallSiteTest.cpp b/llvm/unittests/IR/AbstractCallSiteTest.cpp
index ddb1091..623d1b3 100644
--- a/llvm/unittests/IR/AbstractCallSiteTest.cpp
+++ b/llvm/unittests/IR/AbstractCallSiteTest.cpp
@@ -6,8 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/AbstractCallSite.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Argument.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/SourceMgr.h"
@@ -51,5 +52,96 @@ TEST(AbstractCallSite, CallbackCall) {
EXPECT_TRUE(ACS);
EXPECT_TRUE(ACS.isCallbackCall());
EXPECT_TRUE(ACS.isCallee(CallbackUse));
+ EXPECT_EQ(ACS.getCalleeUseForCallback(), *CallbackUse);
EXPECT_EQ(ACS.getCalledFunction(), Callback);
+
+ // The callback metadata {CallbackNo, Arg0No, ..., isVarArg} = {1, -1, true}
+ EXPECT_EQ(ACS.getCallArgOperandNoForCallee(), 1);
+ // Though the callback metadata only specifies ONE unfixed argument No, the
+ // callback callee is vararg, hence the third arg is also considered as
+ // another arg for the callback.
+ EXPECT_EQ(ACS.getNumArgOperands(), 2u);
+ Argument *Param0 = Callback->getArg(0), *Param1 = Callback->getArg(1);
+ ASSERT_TRUE(Param0 && Param1);
+ EXPECT_EQ(ACS.getCallArgOperandNo(*Param0), -1);
+ EXPECT_EQ(ACS.getCallArgOperandNo(*Param1), 2);
+}
+
+TEST(AbstractCallSite, DirectCall) {
+ LLVMContext C;
+
+ const char *IR = "declare void @bar(i32 %x, i32 %y)\n"
+ "define void @foo() {\n"
+ " call void @bar(i32 1, i32 2)\n"
+ " ret void\n"
+ "}\n";
+
+ std::unique_ptr<Module> M = parseIR(C, IR);
+ ASSERT_TRUE(M);
+
+ Function *Callee = M->getFunction("bar");
+ ASSERT_NE(Callee, nullptr);
+
+ const Use *DirectCallUse = Callee->getSingleUndroppableUse();
+ ASSERT_NE(DirectCallUse, nullptr);
+
+ AbstractCallSite ACS(DirectCallUse);
+ EXPECT_TRUE(ACS);
+ EXPECT_TRUE(ACS.isDirectCall());
+ EXPECT_TRUE(ACS.isCallee(DirectCallUse));
+ EXPECT_EQ(ACS.getCalledFunction(), Callee);
+ EXPECT_EQ(ACS.getNumArgOperands(), 2u);
+ Argument *ArgX = Callee->getArg(0);
+ ASSERT_NE(ArgX, nullptr);
+ Value *CAO1 = ACS.getCallArgOperand(*ArgX);
+ Value *CAO2 = ACS.getCallArgOperand(0);
+ ASSERT_NE(CAO2, nullptr);
+ // The two call arg operands should be the same object, since they are both
+ // the first argument of the call.
+ EXPECT_EQ(CAO2, CAO1);
+
+ ConstantInt *FirstArgInt = dyn_cast<ConstantInt>(CAO2);
+ ASSERT_NE(FirstArgInt, nullptr);
+ EXPECT_EQ(FirstArgInt->getZExtValue(), 1ull);
+
+ EXPECT_EQ(ACS.getCallArgOperandNo(*ArgX), 0);
+ EXPECT_EQ(ACS.getCallArgOperandNo(0), 0);
+ EXPECT_EQ(ACS.getCallArgOperandNo(1), 1);
+}
+
+TEST(AbstractCallSite, IndirectCall) {
+ LLVMContext C;
+
+ const char *IR = "define void @foo(ptr %0) {\n"
+ " call void %0(i32 1, i32 2)\n"
+ " ret void\n"
+ "}\n";
+
+ std::unique_ptr<Module> M = parseIR(C, IR);
+ ASSERT_TRUE(M);
+
+ Function *Fun = M->getFunction("foo");
+ ASSERT_NE(Fun, nullptr);
+
+ Argument *ArgAsCallee = Fun->getArg(0);
+ ASSERT_NE(ArgAsCallee, nullptr);
+
+ const Use *IndCallUse = ArgAsCallee->getSingleUndroppableUse();
+ ASSERT_NE(IndCallUse, nullptr);
+
+ AbstractCallSite ACS(IndCallUse);
+ EXPECT_TRUE(ACS);
+ EXPECT_TRUE(ACS.isIndirectCall());
+ EXPECT_TRUE(ACS.isCallee(IndCallUse));
+ EXPECT_EQ(ACS.getCalledFunction(), nullptr);
+ EXPECT_EQ(ACS.getCalledOperand(), ArgAsCallee);
+ EXPECT_EQ(ACS.getNumArgOperands(), 2u);
+ Value *CalledOperand = ACS.getCallArgOperand(0);
+ ASSERT_NE(CalledOperand, nullptr);
+ ConstantInt *FirstArgInt = dyn_cast<ConstantInt>(CalledOperand);
+ ASSERT_NE(FirstArgInt, nullptr);
+ EXPECT_EQ(FirstArgInt->getZExtValue(), 1ull);
+
+ EXPECT_EQ(ACS.getCallArgOperandNo(0), 0);
+ EXPECT_EQ(ACS.getCallArgOperandNo(1), 1);
}