blob: ab5551a8ea39c13dc7e0db2804f8a7ce90e360df [file] [log] [blame]
Johannes Doerfert18251842019-01-19 05:19:06 +00001//===-- AbstractCallSite.cpp - Implementation of abstract call sites ------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Johannes Doerfert18251842019-01-19 05:19:06 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file implements abstract call sites which unify the interface for
10// direct, indirect, and callback call sites.
11//
12// For more information see:
13// https://llvm.org/devmtg/2018-10/talk-abstracts.html#talk20
14//
15//===----------------------------------------------------------------------===//
16
17#include "llvm/ADT/Statistic.h"
18#include "llvm/ADT/StringSwitch.h"
19#include "llvm/IR/CallSite.h"
20#include "llvm/Support/Debug.h"
21
22using namespace llvm;
23
24#define DEBUG_TYPE "abstract-call-sites"
25
26STATISTIC(NumCallbackCallSites, "Number of callback call sites created");
27STATISTIC(NumDirectAbstractCallSites,
28 "Number of direct abstract call sites created");
29STATISTIC(NumInvalidAbstractCallSitesUnknownUse,
30 "Number of invalid abstract call sites created (unknown use)");
31STATISTIC(NumInvalidAbstractCallSitesUnknownCallee,
32 "Number of invalid abstract call sites created (unknown callee)");
33STATISTIC(NumInvalidAbstractCallSitesNoCallback,
34 "Number of invalid abstract call sites created (no callback)");
35
Craig Toppercd28a472020-04-17 17:07:19 -070036void AbstractCallSite::getCallbackUses(
37 const CallBase &CB, SmallVectorImpl<const Use *> &CallbackUses) {
Craig Topper798b2622020-04-16 16:23:03 -070038 const Function *Callee = CB.getCalledFunction();
Johannes Doerfertb1b441d2019-10-10 01:19:57 -050039 if (!Callee)
40 return;
41
42 MDNode *CallbackMD = Callee->getMetadata(LLVMContext::MD_callback);
43 if (!CallbackMD)
44 return;
45
46 for (const MDOperand &Op : CallbackMD->operands()) {
47 MDNode *OpMD = cast<MDNode>(Op.get());
48 auto *CBCalleeIdxAsCM = cast<ConstantAsMetadata>(OpMD->getOperand(0));
49 uint64_t CBCalleeIdx =
50 cast<ConstantInt>(CBCalleeIdxAsCM->getValue())->getZExtValue();
Craig Topper798b2622020-04-16 16:23:03 -070051 if (CBCalleeIdx < CB.arg_size())
52 CallbackUses.push_back(CB.arg_begin() + CBCalleeIdx);
Johannes Doerfertb1b441d2019-10-10 01:19:57 -050053 }
54}
55
Johannes Doerfert18251842019-01-19 05:19:06 +000056/// Create an abstract call site from a use.
Craig Topper798b2622020-04-16 16:23:03 -070057AbstractCallSite::AbstractCallSite(const Use *U)
58 : CB(dyn_cast<CallBase>(U->getUser())) {
Johannes Doerfert18251842019-01-19 05:19:06 +000059
60 // First handle unknown users.
Craig Topper798b2622020-04-16 16:23:03 -070061 if (!CB) {
Johannes Doerfert18251842019-01-19 05:19:06 +000062
63 // If the use is actually in a constant cast expression which itself
64 // has only one use, we look through the constant cast expression.
65 // This happens by updating the use @p U to the use of the constant
Craig Topper798b2622020-04-16 16:23:03 -070066 // cast expression and afterwards re-initializing CB accordingly.
Johannes Doerfert18251842019-01-19 05:19:06 +000067 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U->getUser()))
68 if (CE->getNumUses() == 1 && CE->isCast()) {
69 U = &*CE->use_begin();
Craig Topper798b2622020-04-16 16:23:03 -070070 CB = dyn_cast<CallBase>(U->getUser());
Johannes Doerfert18251842019-01-19 05:19:06 +000071 }
72
Craig Topper798b2622020-04-16 16:23:03 -070073 if (!CB) {
Johannes Doerfert18251842019-01-19 05:19:06 +000074 NumInvalidAbstractCallSitesUnknownUse++;
75 return;
76 }
77 }
78
79 // Then handle direct or indirect calls. Thus, if U is the callee of the
Craig Topper798b2622020-04-16 16:23:03 -070080 // call site CB it is not a callback and we are done.
81 if (CB->isCallee(U)) {
Johannes Doerfert18251842019-01-19 05:19:06 +000082 NumDirectAbstractCallSites++;
83 return;
84 }
85
86 // If we cannot identify the broker function we cannot create a callback and
87 // invalidate the abstract call site.
Craig Topper798b2622020-04-16 16:23:03 -070088 Function *Callee = CB->getCalledFunction();
Johannes Doerfert18251842019-01-19 05:19:06 +000089 if (!Callee) {
90 NumInvalidAbstractCallSitesUnknownCallee++;
Craig Topper798b2622020-04-16 16:23:03 -070091 CB = nullptr;
Johannes Doerfert18251842019-01-19 05:19:06 +000092 return;
93 }
94
95 MDNode *CallbackMD = Callee->getMetadata(LLVMContext::MD_callback);
96 if (!CallbackMD) {
97 NumInvalidAbstractCallSitesNoCallback++;
Craig Topper798b2622020-04-16 16:23:03 -070098 CB = nullptr;
Johannes Doerfert18251842019-01-19 05:19:06 +000099 return;
100 }
101
Craig Topper798b2622020-04-16 16:23:03 -0700102 unsigned UseIdx = CB->getArgOperandNo(U);
Johannes Doerfert18251842019-01-19 05:19:06 +0000103 MDNode *CallbackEncMD = nullptr;
104 for (const MDOperand &Op : CallbackMD->operands()) {
105 MDNode *OpMD = cast<MDNode>(Op.get());
106 auto *CBCalleeIdxAsCM = cast<ConstantAsMetadata>(OpMD->getOperand(0));
107 uint64_t CBCalleeIdx =
108 cast<ConstantInt>(CBCalleeIdxAsCM->getValue())->getZExtValue();
109 if (CBCalleeIdx != UseIdx)
110 continue;
111 CallbackEncMD = OpMD;
112 break;
113 }
114
115 if (!CallbackEncMD) {
116 NumInvalidAbstractCallSitesNoCallback++;
Craig Topper798b2622020-04-16 16:23:03 -0700117 CB = nullptr;
Johannes Doerfert18251842019-01-19 05:19:06 +0000118 return;
119 }
120
121 NumCallbackCallSites++;
122
123 assert(CallbackEncMD->getNumOperands() >= 2 && "Incomplete !callback metadata");
124
Craig Topper798b2622020-04-16 16:23:03 -0700125 unsigned NumCallOperands = CB->getNumArgOperands();
Johannes Doerfert18251842019-01-19 05:19:06 +0000126 // Skip the var-arg flag at the end when reading the metadata.
127 for (unsigned u = 0, e = CallbackEncMD->getNumOperands() - 1; u < e; u++) {
128 Metadata *OpAsM = CallbackEncMD->getOperand(u).get();
129 auto *OpAsCM = cast<ConstantAsMetadata>(OpAsM);
130 assert(OpAsCM->getType()->isIntegerTy(64) &&
131 "Malformed !callback metadata");
132
133 int64_t Idx = cast<ConstantInt>(OpAsCM->getValue())->getSExtValue();
134 assert(-1 <= Idx && Idx <= NumCallOperands &&
135 "Out-of-bounds !callback metadata index");
136
137 CI.ParameterEncoding.push_back(Idx);
138 }
139
140 if (!Callee->isVarArg())
141 return;
142
143 Metadata *VarArgFlagAsM =
144 CallbackEncMD->getOperand(CallbackEncMD->getNumOperands() - 1).get();
145 auto *VarArgFlagAsCM = cast<ConstantAsMetadata>(VarArgFlagAsM);
146 assert(VarArgFlagAsCM->getType()->isIntegerTy(1) &&
147 "Malformed !callback metadata var-arg flag");
148
149 if (VarArgFlagAsCM->getValue()->isNullValue())
150 return;
151
152 // Add all variadic arguments at the end.
153 for (unsigned u = Callee->arg_size(); u < NumCallOperands; u++)
154 CI.ParameterEncoding.push_back(u);
155}