118251842SJohannes Doerfert //===-- AbstractCallSite.cpp - Implementation of abstract call sites ------===// 218251842SJohannes Doerfert // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 618251842SJohannes Doerfert // 718251842SJohannes Doerfert //===----------------------------------------------------------------------===// 818251842SJohannes Doerfert // 918251842SJohannes Doerfert // This file implements abstract call sites which unify the interface for 1018251842SJohannes Doerfert // direct, indirect, and callback call sites. 1118251842SJohannes Doerfert // 1218251842SJohannes Doerfert // For more information see: 1318251842SJohannes Doerfert // https://llvm.org/devmtg/2018-10/talk-abstracts.html#talk20 1418251842SJohannes Doerfert // 1518251842SJohannes Doerfert //===----------------------------------------------------------------------===// 1618251842SJohannes Doerfert 1718251842SJohannes Doerfert #include "llvm/ADT/Statistic.h" 1818251842SJohannes Doerfert #include "llvm/ADT/StringSwitch.h" 1918251842SJohannes Doerfert #include "llvm/IR/CallSite.h" 2018251842SJohannes Doerfert #include "llvm/Support/Debug.h" 2118251842SJohannes Doerfert 2218251842SJohannes Doerfert using namespace llvm; 2318251842SJohannes Doerfert 2418251842SJohannes Doerfert #define DEBUG_TYPE "abstract-call-sites" 2518251842SJohannes Doerfert 2618251842SJohannes Doerfert STATISTIC(NumCallbackCallSites, "Number of callback call sites created"); 2718251842SJohannes Doerfert STATISTIC(NumDirectAbstractCallSites, 2818251842SJohannes Doerfert "Number of direct abstract call sites created"); 2918251842SJohannes Doerfert STATISTIC(NumInvalidAbstractCallSitesUnknownUse, 3018251842SJohannes Doerfert "Number of invalid abstract call sites created (unknown use)"); 3118251842SJohannes Doerfert STATISTIC(NumInvalidAbstractCallSitesUnknownCallee, 3218251842SJohannes Doerfert "Number of invalid abstract call sites created (unknown callee)"); 3318251842SJohannes Doerfert STATISTIC(NumInvalidAbstractCallSitesNoCallback, 3418251842SJohannes Doerfert "Number of invalid abstract call sites created (no callback)"); 3518251842SJohannes Doerfert 36*cd28a473SCraig Topper void AbstractCallSite::getCallbackUses( 37*cd28a473SCraig Topper const CallBase &CB, SmallVectorImpl<const Use *> &CallbackUses) { 38798b262cSCraig Topper const Function *Callee = CB.getCalledFunction(); 39b1b441d2SJohannes Doerfert if (!Callee) 40b1b441d2SJohannes Doerfert return; 41b1b441d2SJohannes Doerfert 42b1b441d2SJohannes Doerfert MDNode *CallbackMD = Callee->getMetadata(LLVMContext::MD_callback); 43b1b441d2SJohannes Doerfert if (!CallbackMD) 44b1b441d2SJohannes Doerfert return; 45b1b441d2SJohannes Doerfert 46b1b441d2SJohannes Doerfert for (const MDOperand &Op : CallbackMD->operands()) { 47b1b441d2SJohannes Doerfert MDNode *OpMD = cast<MDNode>(Op.get()); 48b1b441d2SJohannes Doerfert auto *CBCalleeIdxAsCM = cast<ConstantAsMetadata>(OpMD->getOperand(0)); 49b1b441d2SJohannes Doerfert uint64_t CBCalleeIdx = 50b1b441d2SJohannes Doerfert cast<ConstantInt>(CBCalleeIdxAsCM->getValue())->getZExtValue(); 51798b262cSCraig Topper if (CBCalleeIdx < CB.arg_size()) 52798b262cSCraig Topper CallbackUses.push_back(CB.arg_begin() + CBCalleeIdx); 53b1b441d2SJohannes Doerfert } 54b1b441d2SJohannes Doerfert } 55b1b441d2SJohannes Doerfert 5618251842SJohannes Doerfert /// Create an abstract call site from a use. 57798b262cSCraig Topper AbstractCallSite::AbstractCallSite(const Use *U) 58798b262cSCraig Topper : CB(dyn_cast<CallBase>(U->getUser())) { 5918251842SJohannes Doerfert 6018251842SJohannes Doerfert // First handle unknown users. 61798b262cSCraig Topper if (!CB) { 6218251842SJohannes Doerfert 6318251842SJohannes Doerfert // If the use is actually in a constant cast expression which itself 6418251842SJohannes Doerfert // has only one use, we look through the constant cast expression. 6518251842SJohannes Doerfert // This happens by updating the use @p U to the use of the constant 66798b262cSCraig Topper // cast expression and afterwards re-initializing CB accordingly. 6718251842SJohannes Doerfert if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U->getUser())) 6818251842SJohannes Doerfert if (CE->getNumUses() == 1 && CE->isCast()) { 6918251842SJohannes Doerfert U = &*CE->use_begin(); 70798b262cSCraig Topper CB = dyn_cast<CallBase>(U->getUser()); 7118251842SJohannes Doerfert } 7218251842SJohannes Doerfert 73798b262cSCraig Topper if (!CB) { 7418251842SJohannes Doerfert NumInvalidAbstractCallSitesUnknownUse++; 7518251842SJohannes Doerfert return; 7618251842SJohannes Doerfert } 7718251842SJohannes Doerfert } 7818251842SJohannes Doerfert 7918251842SJohannes Doerfert // Then handle direct or indirect calls. Thus, if U is the callee of the 80798b262cSCraig Topper // call site CB it is not a callback and we are done. 81798b262cSCraig Topper if (CB->isCallee(U)) { 8218251842SJohannes Doerfert NumDirectAbstractCallSites++; 8318251842SJohannes Doerfert return; 8418251842SJohannes Doerfert } 8518251842SJohannes Doerfert 8618251842SJohannes Doerfert // If we cannot identify the broker function we cannot create a callback and 8718251842SJohannes Doerfert // invalidate the abstract call site. 88798b262cSCraig Topper Function *Callee = CB->getCalledFunction(); 8918251842SJohannes Doerfert if (!Callee) { 9018251842SJohannes Doerfert NumInvalidAbstractCallSitesUnknownCallee++; 91798b262cSCraig Topper CB = nullptr; 9218251842SJohannes Doerfert return; 9318251842SJohannes Doerfert } 9418251842SJohannes Doerfert 9518251842SJohannes Doerfert MDNode *CallbackMD = Callee->getMetadata(LLVMContext::MD_callback); 9618251842SJohannes Doerfert if (!CallbackMD) { 9718251842SJohannes Doerfert NumInvalidAbstractCallSitesNoCallback++; 98798b262cSCraig Topper CB = nullptr; 9918251842SJohannes Doerfert return; 10018251842SJohannes Doerfert } 10118251842SJohannes Doerfert 102798b262cSCraig Topper unsigned UseIdx = CB->getArgOperandNo(U); 10318251842SJohannes Doerfert MDNode *CallbackEncMD = nullptr; 10418251842SJohannes Doerfert for (const MDOperand &Op : CallbackMD->operands()) { 10518251842SJohannes Doerfert MDNode *OpMD = cast<MDNode>(Op.get()); 10618251842SJohannes Doerfert auto *CBCalleeIdxAsCM = cast<ConstantAsMetadata>(OpMD->getOperand(0)); 10718251842SJohannes Doerfert uint64_t CBCalleeIdx = 10818251842SJohannes Doerfert cast<ConstantInt>(CBCalleeIdxAsCM->getValue())->getZExtValue(); 10918251842SJohannes Doerfert if (CBCalleeIdx != UseIdx) 11018251842SJohannes Doerfert continue; 11118251842SJohannes Doerfert CallbackEncMD = OpMD; 11218251842SJohannes Doerfert break; 11318251842SJohannes Doerfert } 11418251842SJohannes Doerfert 11518251842SJohannes Doerfert if (!CallbackEncMD) { 11618251842SJohannes Doerfert NumInvalidAbstractCallSitesNoCallback++; 117798b262cSCraig Topper CB = nullptr; 11818251842SJohannes Doerfert return; 11918251842SJohannes Doerfert } 12018251842SJohannes Doerfert 12118251842SJohannes Doerfert NumCallbackCallSites++; 12218251842SJohannes Doerfert 12318251842SJohannes Doerfert assert(CallbackEncMD->getNumOperands() >= 2 && "Incomplete !callback metadata"); 12418251842SJohannes Doerfert 125798b262cSCraig Topper unsigned NumCallOperands = CB->getNumArgOperands(); 12618251842SJohannes Doerfert // Skip the var-arg flag at the end when reading the metadata. 12718251842SJohannes Doerfert for (unsigned u = 0, e = CallbackEncMD->getNumOperands() - 1; u < e; u++) { 12818251842SJohannes Doerfert Metadata *OpAsM = CallbackEncMD->getOperand(u).get(); 12918251842SJohannes Doerfert auto *OpAsCM = cast<ConstantAsMetadata>(OpAsM); 13018251842SJohannes Doerfert assert(OpAsCM->getType()->isIntegerTy(64) && 13118251842SJohannes Doerfert "Malformed !callback metadata"); 13218251842SJohannes Doerfert 13318251842SJohannes Doerfert int64_t Idx = cast<ConstantInt>(OpAsCM->getValue())->getSExtValue(); 13418251842SJohannes Doerfert assert(-1 <= Idx && Idx <= NumCallOperands && 13518251842SJohannes Doerfert "Out-of-bounds !callback metadata index"); 13618251842SJohannes Doerfert 13718251842SJohannes Doerfert CI.ParameterEncoding.push_back(Idx); 13818251842SJohannes Doerfert } 13918251842SJohannes Doerfert 14018251842SJohannes Doerfert if (!Callee->isVarArg()) 14118251842SJohannes Doerfert return; 14218251842SJohannes Doerfert 14318251842SJohannes Doerfert Metadata *VarArgFlagAsM = 14418251842SJohannes Doerfert CallbackEncMD->getOperand(CallbackEncMD->getNumOperands() - 1).get(); 14518251842SJohannes Doerfert auto *VarArgFlagAsCM = cast<ConstantAsMetadata>(VarArgFlagAsM); 14618251842SJohannes Doerfert assert(VarArgFlagAsCM->getType()->isIntegerTy(1) && 14718251842SJohannes Doerfert "Malformed !callback metadata var-arg flag"); 14818251842SJohannes Doerfert 14918251842SJohannes Doerfert if (VarArgFlagAsCM->getValue()->isNullValue()) 15018251842SJohannes Doerfert return; 15118251842SJohannes Doerfert 15218251842SJohannes Doerfert // Add all variadic arguments at the end. 15318251842SJohannes Doerfert for (unsigned u = Callee->arg_size(); u < NumCallOperands; u++) 15418251842SJohannes Doerfert CI.ParameterEncoding.push_back(u); 15518251842SJohannes Doerfert } 156