xref: /llvm-project/llvm/lib/IR/AbstractCallSite.cpp (revision 18251842c6781ddcd74d785da1235593ad7613dc)
1 //===-- AbstractCallSite.cpp - Implementation of abstract call sites ------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements abstract call sites which unify the interface for
11 // direct, indirect, and callback call sites.
12 //
13 // For more information see:
14 // https://llvm.org/devmtg/2018-10/talk-abstracts.html#talk20
15 //
16 //===----------------------------------------------------------------------===//
17 
18 #include "llvm/ADT/Statistic.h"
19 #include "llvm/ADT/StringSwitch.h"
20 #include "llvm/IR/CallSite.h"
21 #include "llvm/Support/Debug.h"
22 
23 using namespace llvm;
24 
25 #define DEBUG_TYPE "abstract-call-sites"
26 
27 STATISTIC(NumCallbackCallSites, "Number of callback call sites created");
28 STATISTIC(NumDirectAbstractCallSites,
29           "Number of direct abstract call sites created");
30 STATISTIC(NumInvalidAbstractCallSitesUnknownUse,
31           "Number of invalid abstract call sites created (unknown use)");
32 STATISTIC(NumInvalidAbstractCallSitesUnknownCallee,
33           "Number of invalid abstract call sites created (unknown callee)");
34 STATISTIC(NumInvalidAbstractCallSitesNoCallback,
35           "Number of invalid abstract call sites created (no callback)");
36 
37 /// Create an abstract call site from a use.
38 AbstractCallSite::AbstractCallSite(const Use *U) : CS(U->getUser()) {
39 
40   // First handle unknown users.
41   if (!CS) {
42 
43     // If the use is actually in a constant cast expression which itself
44     // has only one use, we look through the constant cast expression.
45     // This happens by updating the use @p U to the use of the constant
46     // cast expression and afterwards re-initializing CS accordingly.
47     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U->getUser()))
48       if (CE->getNumUses() == 1 && CE->isCast()) {
49         U = &*CE->use_begin();
50         CS = CallSite(U->getUser());
51       }
52 
53     if (!CS) {
54       NumInvalidAbstractCallSitesUnknownUse++;
55       return;
56     }
57   }
58 
59   // Then handle direct or indirect calls. Thus, if U is the callee of the
60   // call site CS it is not a callback and we are done.
61   if (CS.isCallee(U)) {
62     NumDirectAbstractCallSites++;
63     return;
64   }
65 
66   // If we cannot identify the broker function we cannot create a callback and
67   // invalidate the abstract call site.
68   Function *Callee = CS.getCalledFunction();
69   if (!Callee) {
70     NumInvalidAbstractCallSitesUnknownCallee++;
71     CS = CallSite();
72     return;
73   }
74 
75   MDNode *CallbackMD = Callee->getMetadata(LLVMContext::MD_callback);
76   if (!CallbackMD) {
77     NumInvalidAbstractCallSitesNoCallback++;
78     CS = CallSite();
79     return;
80   }
81 
82   unsigned UseIdx = CS.getArgumentNo(U);
83   MDNode *CallbackEncMD = nullptr;
84   for (const MDOperand &Op : CallbackMD->operands()) {
85     MDNode *OpMD = cast<MDNode>(Op.get());
86     auto *CBCalleeIdxAsCM = cast<ConstantAsMetadata>(OpMD->getOperand(0));
87     uint64_t CBCalleeIdx =
88         cast<ConstantInt>(CBCalleeIdxAsCM->getValue())->getZExtValue();
89     if (CBCalleeIdx != UseIdx)
90       continue;
91     CallbackEncMD = OpMD;
92     break;
93   }
94 
95   if (!CallbackEncMD) {
96     NumInvalidAbstractCallSitesNoCallback++;
97     CS = CallSite();
98     return;
99   }
100 
101   NumCallbackCallSites++;
102 
103   assert(CallbackEncMD->getNumOperands() >= 2 && "Incomplete !callback metadata");
104 
105   unsigned NumCallOperands = CS.getNumArgOperands();
106   // Skip the var-arg flag at the end when reading the metadata.
107   for (unsigned u = 0, e = CallbackEncMD->getNumOperands() - 1; u < e; u++) {
108     Metadata *OpAsM = CallbackEncMD->getOperand(u).get();
109     auto *OpAsCM = cast<ConstantAsMetadata>(OpAsM);
110     assert(OpAsCM->getType()->isIntegerTy(64) &&
111            "Malformed !callback metadata");
112 
113     int64_t Idx = cast<ConstantInt>(OpAsCM->getValue())->getSExtValue();
114     assert(-1 <= Idx && Idx <= NumCallOperands &&
115            "Out-of-bounds !callback metadata index");
116 
117     CI.ParameterEncoding.push_back(Idx);
118   }
119 
120   if (!Callee->isVarArg())
121     return;
122 
123   Metadata *VarArgFlagAsM =
124       CallbackEncMD->getOperand(CallbackEncMD->getNumOperands() - 1).get();
125   auto *VarArgFlagAsCM = cast<ConstantAsMetadata>(VarArgFlagAsM);
126   assert(VarArgFlagAsCM->getType()->isIntegerTy(1) &&
127          "Malformed !callback metadata var-arg flag");
128 
129   if (VarArgFlagAsCM->getValue()->isNullValue())
130     return;
131 
132   // Add all variadic arguments at the end.
133   for (unsigned u = Callee->arg_size(); u < NumCallOperands; u++)
134     CI.ParameterEncoding.push_back(u);
135 }
136