WebAssemblyAddMissingPrototypes.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. //===-- WebAssemblyAddMissingPrototypes.cpp - Fix prototypeless functions -===//
  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. /// \file
  11. /// Add prototypes to prototypes-less functions.
  12. ///
  13. /// WebAssembly has strict function prototype checking so we need functions
  14. /// declarations to match the call sites. Clang treats prototype-less functions
  15. /// as varargs (foo(...)) which happens to work on existing platforms but
  16. /// doesn't under WebAssembly. This pass will find all the call sites of each
  17. /// prototype-less function, ensure they agree, and then set the signature
  18. /// on the function declaration accordingly.
  19. ///
  20. //===----------------------------------------------------------------------===//
  21. #include "WebAssembly.h"
  22. #include "llvm/IR/Constants.h"
  23. #include "llvm/IR/IRBuilder.h"
  24. #include "llvm/IR/Module.h"
  25. #include "llvm/IR/Operator.h"
  26. #include "llvm/Transforms/Utils/ModuleUtils.h"
  27. #include "llvm/Transforms/Utils/Local.h"
  28. #include "llvm/Pass.h"
  29. #include "llvm/Support/Debug.h"
  30. using namespace llvm;
  31. #define DEBUG_TYPE "wasm-add-missing-prototypes"
  32. namespace {
  33. class WebAssemblyAddMissingPrototypes final : public ModulePass {
  34. StringRef getPassName() const override {
  35. return "Add prototypes to prototypes-less functions";
  36. }
  37. void getAnalysisUsage(AnalysisUsage &AU) const override {
  38. AU.setPreservesCFG();
  39. ModulePass::getAnalysisUsage(AU);
  40. }
  41. bool runOnModule(Module &M) override;
  42. public:
  43. static char ID;
  44. WebAssemblyAddMissingPrototypes() : ModulePass(ID) {}
  45. };
  46. } // End anonymous namespace
  47. char WebAssemblyAddMissingPrototypes::ID = 0;
  48. INITIALIZE_PASS(WebAssemblyAddMissingPrototypes, DEBUG_TYPE,
  49. "Add prototypes to prototypes-less functions", false, false)
  50. ModulePass *llvm::createWebAssemblyAddMissingPrototypes() {
  51. return new WebAssemblyAddMissingPrototypes();
  52. }
  53. bool WebAssemblyAddMissingPrototypes::runOnModule(Module &M) {
  54. LLVM_DEBUG(dbgs() << "runnning AddMissingPrototypes\n");
  55. std::vector<std::pair<Function*, Function*>> Replacements;
  56. // Find all the prototype-less function declarations
  57. for (Function &F : M) {
  58. if (!F.isDeclaration() || !F.hasFnAttribute("no-prototype"))
  59. continue;
  60. LLVM_DEBUG(dbgs() << "Found no-prototype function: " << F.getName() << "\n");
  61. // When clang emits prototype-less C functions it uses (...), i.e. varargs
  62. // function that take no arguments (have no sentinel). When we see a
  63. // no-prototype attribute we expect the function have these properties.
  64. if (!F.isVarArg())
  65. report_fatal_error(
  66. "Functions with 'no-prototype' attribute must take varargs: " +
  67. F.getName());
  68. if (F.getFunctionType()->getNumParams() != 0)
  69. report_fatal_error(
  70. "Functions with 'no-prototype' attribute should not have params: " +
  71. F.getName());
  72. // Create a function prototype based on the first call site (first bitcast)
  73. // that we find.
  74. FunctionType *NewType = nullptr;
  75. Function* NewF = nullptr;
  76. for (Use &U : F.uses()) {
  77. LLVM_DEBUG(dbgs() << "prototype-less use: " << F.getName() << "\n");
  78. if (BitCastOperator *BC = dyn_cast<BitCastOperator>(U.getUser())) {
  79. FunctionType *DestType =
  80. cast<FunctionType>(BC->getDestTy()->getPointerElementType());
  81. // Create a new function with the correct type
  82. NewType = DestType;
  83. NewF = Function::Create(NewType, F.getLinkage(), F.getName());
  84. NewF->setAttributes(F.getAttributes());
  85. NewF->removeFnAttr("no-prototype");
  86. break;
  87. }
  88. }
  89. if (!NewType) {
  90. LLVM_DEBUG(
  91. dbgs() << "could not derive a function prototype from usage: " +
  92. F.getName() + "\n");
  93. continue;
  94. }
  95. for (Use &U : F.uses()) {
  96. if (BitCastOperator *BC = dyn_cast<BitCastOperator>(U.getUser())) {
  97. FunctionType *DestType =
  98. cast<FunctionType>(BC->getDestTy()->getPointerElementType());
  99. if (NewType != DestType) {
  100. report_fatal_error(
  101. "Prototypeless function used with conflicting signatures: " +
  102. F.getName());
  103. }
  104. BC->replaceAllUsesWith(NewF);
  105. Replacements.emplace_back(&F, NewF);
  106. } else {
  107. dbgs() << *U.getUser()->getType() << "\n";
  108. #ifndef NDEBUG
  109. U.getUser()->dump();
  110. #endif
  111. report_fatal_error(
  112. "unexpected use of prototypeless function: " + F.getName() + "\n");
  113. }
  114. }
  115. }
  116. // Finally replace the old function declarations with the new ones
  117. for (auto &Pair : Replacements) {
  118. Function* Old = Pair.first;
  119. Function* New = Pair.second;
  120. Old->eraseFromParent();
  121. M.getFunctionList().push_back(New);
  122. }
  123. return !Replacements.empty();
  124. }