| 
6 | 6 | //  | 
7 | 7 | //===----------------------------------------------------------------------===//  | 
8 | 8 | 
 
  | 
9 |  | -#include "llvm/AsmParser/Parser.h"  | 
10 | 9 | #include "llvm/IR/AbstractCallSite.h"  | 
 | 10 | +#include "llvm/AsmParser/Parser.h"  | 
 | 11 | +#include "llvm/IR/Argument.h"  | 
11 | 12 | #include "llvm/IR/Function.h"  | 
12 | 13 | #include "llvm/IR/Module.h"  | 
13 | 14 | #include "llvm/Support/SourceMgr.h"  | 
@@ -51,5 +52,96 @@ TEST(AbstractCallSite, CallbackCall) {  | 
51 | 52 |   EXPECT_TRUE(ACS);  | 
52 | 53 |   EXPECT_TRUE(ACS.isCallbackCall());  | 
53 | 54 |   EXPECT_TRUE(ACS.isCallee(CallbackUse));  | 
 | 55 | +  EXPECT_EQ(ACS.getCalleeUseForCallback(), *CallbackUse);  | 
54 | 56 |   EXPECT_EQ(ACS.getCalledFunction(), Callback);  | 
 | 57 | + | 
 | 58 | +  // The callback metadata {CallbackNo, Arg0No, ..., isVarArg} = {1, -1, true}  | 
 | 59 | +  EXPECT_EQ(ACS.getCallArgOperandNoForCallee(), 1);  | 
 | 60 | +  // Though the callback metadata only specifies ONE unfixed argument No, the  | 
 | 61 | +  // callback callee is vararg, hence the third arg is also considered as  | 
 | 62 | +  // another arg for the callback.  | 
 | 63 | +  EXPECT_EQ(ACS.getNumArgOperands(), 2u);  | 
 | 64 | +  Argument *Param0 = Callback->getArg(0), *Param1 = Callback->getArg(1);  | 
 | 65 | +  ASSERT_TRUE(Param0 && Param1);  | 
 | 66 | +  EXPECT_EQ(ACS.getCallArgOperandNo(*Param0), -1);  | 
 | 67 | +  EXPECT_EQ(ACS.getCallArgOperandNo(*Param1), 2);  | 
 | 68 | +}  | 
 | 69 | + | 
 | 70 | +TEST(AbstractCallSite, DirectCall) {  | 
 | 71 | +  LLVMContext C;  | 
 | 72 | + | 
 | 73 | +  const char *IR = "declare void @bar(i32 %x, i32 %y)\n"  | 
 | 74 | +                   "define void @foo() {\n"  | 
 | 75 | +                   "  call void @bar(i32 1, i32 2)\n"  | 
 | 76 | +                   "  ret void\n"  | 
 | 77 | +                   "}\n";  | 
 | 78 | + | 
 | 79 | +  std::unique_ptr<Module> M = parseIR(C, IR);  | 
 | 80 | +  ASSERT_TRUE(M);  | 
 | 81 | + | 
 | 82 | +  Function *Callee = M->getFunction("bar");  | 
 | 83 | +  ASSERT_NE(Callee, nullptr);  | 
 | 84 | + | 
 | 85 | +  const Use *DirectCallUse = Callee->getSingleUndroppableUse();  | 
 | 86 | +  ASSERT_NE(DirectCallUse, nullptr);  | 
 | 87 | + | 
 | 88 | +  AbstractCallSite ACS(DirectCallUse);  | 
 | 89 | +  EXPECT_TRUE(ACS);  | 
 | 90 | +  EXPECT_TRUE(ACS.isDirectCall());  | 
 | 91 | +  EXPECT_TRUE(ACS.isCallee(DirectCallUse));  | 
 | 92 | +  EXPECT_EQ(ACS.getCalledFunction(), Callee);  | 
 | 93 | +  EXPECT_EQ(ACS.getNumArgOperands(), 2u);  | 
 | 94 | +  Argument *ArgX = Callee->getArg(0);  | 
 | 95 | +  ASSERT_NE(ArgX, nullptr);  | 
 | 96 | +  Value *CAO1 = ACS.getCallArgOperand(*ArgX);  | 
 | 97 | +  Value *CAO2 = ACS.getCallArgOperand(0);  | 
 | 98 | +  ASSERT_NE(CAO2, nullptr);  | 
 | 99 | +  // The two call arg operands should be the same object, since they are both  | 
 | 100 | +  // the first argument of the call.  | 
 | 101 | +  EXPECT_EQ(CAO2, CAO1);  | 
 | 102 | + | 
 | 103 | +  ConstantInt *FirstArgInt = dyn_cast<ConstantInt>(CAO2);  | 
 | 104 | +  ASSERT_NE(FirstArgInt, nullptr);  | 
 | 105 | +  EXPECT_EQ(FirstArgInt->getZExtValue(), 1ull);  | 
 | 106 | + | 
 | 107 | +  EXPECT_EQ(ACS.getCallArgOperandNo(*ArgX), 0);  | 
 | 108 | +  EXPECT_EQ(ACS.getCallArgOperandNo(0), 0);  | 
 | 109 | +  EXPECT_EQ(ACS.getCallArgOperandNo(1), 1);  | 
 | 110 | +}  | 
 | 111 | + | 
 | 112 | +TEST(AbstractCallSite, IndirectCall) {  | 
 | 113 | +  LLVMContext C;  | 
 | 114 | + | 
 | 115 | +  const char *IR = "define void @foo(ptr %0) {\n"  | 
 | 116 | +                   "  call void %0(i32 1, i32 2)\n"  | 
 | 117 | +                   "  ret void\n"  | 
 | 118 | +                   "}\n";  | 
 | 119 | + | 
 | 120 | +  std::unique_ptr<Module> M = parseIR(C, IR);  | 
 | 121 | +  ASSERT_TRUE(M);  | 
 | 122 | + | 
 | 123 | +  Function *Fun = M->getFunction("foo");  | 
 | 124 | +  ASSERT_NE(Fun, nullptr);  | 
 | 125 | + | 
 | 126 | +  Argument *ArgAsCallee = Fun->getArg(0);  | 
 | 127 | +  ASSERT_NE(ArgAsCallee, nullptr);  | 
 | 128 | + | 
 | 129 | +  const Use *IndCallUse = ArgAsCallee->getSingleUndroppableUse();  | 
 | 130 | +  ASSERT_NE(IndCallUse, nullptr);  | 
 | 131 | + | 
 | 132 | +  AbstractCallSite ACS(IndCallUse);  | 
 | 133 | +  EXPECT_TRUE(ACS);  | 
 | 134 | +  EXPECT_TRUE(ACS.isIndirectCall());  | 
 | 135 | +  EXPECT_TRUE(ACS.isCallee(IndCallUse));  | 
 | 136 | +  EXPECT_EQ(ACS.getCalledFunction(), nullptr);  | 
 | 137 | +  EXPECT_EQ(ACS.getCalledOperand(), ArgAsCallee);  | 
 | 138 | +  EXPECT_EQ(ACS.getNumArgOperands(), 2u);  | 
 | 139 | +  Value *CalledOperand = ACS.getCallArgOperand(0);  | 
 | 140 | +  ASSERT_NE(CalledOperand, nullptr);  | 
 | 141 | +  ConstantInt *FirstArgInt = dyn_cast<ConstantInt>(CalledOperand);  | 
 | 142 | +  ASSERT_NE(FirstArgInt, nullptr);  | 
 | 143 | +  EXPECT_EQ(FirstArgInt->getZExtValue(), 1ull);  | 
 | 144 | + | 
 | 145 | +  EXPECT_EQ(ACS.getCallArgOperandNo(0), 0);  | 
 | 146 | +  EXPECT_EQ(ACS.getCallArgOperandNo(1), 1);  | 
55 | 147 | }  | 
0 commit comments