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