blob: 6ad2df85169d31400c162f4b3d8d19edd1994e89 [file] [log] [blame]
Johannes Doerfert18251842019-01-19 05:19:06 +00001//===-- 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
23using namespace llvm;
24
25#define DEBUG_TYPE "abstract-call-sites"
26
27STATISTIC(NumCallbackCallSites, "Number of callback call sites created");
28STATISTIC(NumDirectAbstractCallSites,
29 "Number of direct abstract call sites created");
30STATISTIC(NumInvalidAbstractCallSitesUnknownUse,
31 "Number of invalid abstract call sites created (unknown use)");
32STATISTIC(NumInvalidAbstractCallSitesUnknownCallee,
33 "Number of invalid abstract call sites created (unknown callee)");
34STATISTIC(NumInvalidAbstractCallSitesNoCallback,
35 "Number of invalid abstract call sites created (no callback)");
36
37/// Create an abstract call site from a use.
38AbstractCallSite::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}