AbstractCallSite.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. //===-- AbstractCallSite.cpp - Implementation of abstract call sites ------===//
  2. //
  3. // 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
  6. //
  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. #include "llvm/ADT/Statistic.h"
  17. #include "llvm/ADT/StringSwitch.h"
  18. #include "llvm/IR/CallSite.h"
  19. #include "llvm/Support/Debug.h"
  20. using namespace llvm;
  21. #define DEBUG_TYPE "abstract-call-sites"
  22. STATISTIC(NumCallbackCallSites, "Number of callback call sites created");
  23. STATISTIC(NumDirectAbstractCallSites,
  24. "Number of direct abstract call sites created");
  25. STATISTIC(NumInvalidAbstractCallSitesUnknownUse,
  26. "Number of invalid abstract call sites created (unknown use)");
  27. STATISTIC(NumInvalidAbstractCallSitesUnknownCallee,
  28. "Number of invalid abstract call sites created (unknown callee)");
  29. STATISTIC(NumInvalidAbstractCallSitesNoCallback,
  30. "Number of invalid abstract call sites created (no callback)");
  31. /// Create an abstract call site from a use.
  32. AbstractCallSite::AbstractCallSite(const Use *U) : CS(U->getUser()) {
  33. // First handle unknown users.
  34. if (!CS) {
  35. // If the use is actually in a constant cast expression which itself
  36. // has only one use, we look through the constant cast expression.
  37. // This happens by updating the use @p U to the use of the constant
  38. // cast expression and afterwards re-initializing CS accordingly.
  39. if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U->getUser()))
  40. if (CE->getNumUses() == 1 && CE->isCast()) {
  41. U = &*CE->use_begin();
  42. CS = CallSite(U->getUser());
  43. }
  44. if (!CS) {
  45. NumInvalidAbstractCallSitesUnknownUse++;
  46. return;
  47. }
  48. }
  49. // Then handle direct or indirect calls. Thus, if U is the callee of the
  50. // call site CS it is not a callback and we are done.
  51. if (CS.isCallee(U)) {
  52. NumDirectAbstractCallSites++;
  53. return;
  54. }
  55. // If we cannot identify the broker function we cannot create a callback and
  56. // invalidate the abstract call site.
  57. Function *Callee = CS.getCalledFunction();
  58. if (!Callee) {
  59. NumInvalidAbstractCallSitesUnknownCallee++;
  60. CS = CallSite();
  61. return;
  62. }
  63. MDNode *CallbackMD = Callee->getMetadata(LLVMContext::MD_callback);
  64. if (!CallbackMD) {
  65. NumInvalidAbstractCallSitesNoCallback++;
  66. CS = CallSite();
  67. return;
  68. }
  69. unsigned UseIdx = CS.getArgumentNo(U);
  70. MDNode *CallbackEncMD = nullptr;
  71. for (const MDOperand &Op : CallbackMD->operands()) {
  72. MDNode *OpMD = cast<MDNode>(Op.get());
  73. auto *CBCalleeIdxAsCM = cast<ConstantAsMetadata>(OpMD->getOperand(0));
  74. uint64_t CBCalleeIdx =
  75. cast<ConstantInt>(CBCalleeIdxAsCM->getValue())->getZExtValue();
  76. if (CBCalleeIdx != UseIdx)
  77. continue;
  78. CallbackEncMD = OpMD;
  79. break;
  80. }
  81. if (!CallbackEncMD) {
  82. NumInvalidAbstractCallSitesNoCallback++;
  83. CS = CallSite();
  84. return;
  85. }
  86. NumCallbackCallSites++;
  87. assert(CallbackEncMD->getNumOperands() >= 2 && "Incomplete !callback metadata");
  88. unsigned NumCallOperands = CS.getNumArgOperands();
  89. // Skip the var-arg flag at the end when reading the metadata.
  90. for (unsigned u = 0, e = CallbackEncMD->getNumOperands() - 1; u < e; u++) {
  91. Metadata *OpAsM = CallbackEncMD->getOperand(u).get();
  92. auto *OpAsCM = cast<ConstantAsMetadata>(OpAsM);
  93. assert(OpAsCM->getType()->isIntegerTy(64) &&
  94. "Malformed !callback metadata");
  95. int64_t Idx = cast<ConstantInt>(OpAsCM->getValue())->getSExtValue();
  96. assert(-1 <= Idx && Idx <= NumCallOperands &&
  97. "Out-of-bounds !callback metadata index");
  98. CI.ParameterEncoding.push_back(Idx);
  99. }
  100. if (!Callee->isVarArg())
  101. return;
  102. Metadata *VarArgFlagAsM =
  103. CallbackEncMD->getOperand(CallbackEncMD->getNumOperands() - 1).get();
  104. auto *VarArgFlagAsCM = cast<ConstantAsMetadata>(VarArgFlagAsM);
  105. assert(VarArgFlagAsCM->getType()->isIntegerTy(1) &&
  106. "Malformed !callback metadata var-arg flag");
  107. if (VarArgFlagAsCM->getValue()->isNullValue())
  108. return;
  109. // Add all variadic arguments at the end.
  110. for (unsigned u = Callee->arg_size(); u < NumCallOperands; u++)
  111. CI.ParameterEncoding.push_back(u);
  112. }