LLVM  9.0.0svn
WebAssemblyAddMissingPrototypes.cpp
Go to the documentation of this file.
1 //===-- WebAssemblyAddMissingPrototypes.cpp - Fix prototypeless functions -===//
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 /// \file
10 /// Add prototypes to prototypes-less functions.
11 ///
12 /// WebAssembly has strict function prototype checking so we need functions
13 /// declarations to match the call sites. Clang treats prototype-less functions
14 /// as varargs (foo(...)) which happens to work on existing platforms but
15 /// doesn't under WebAssembly. This pass will find all the call sites of each
16 /// prototype-less function, ensure they agree, and then set the signature
17 /// on the function declaration accordingly.
18 ///
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/Pass.h"
27 #include "llvm/Support/Debug.h"
30 using namespace llvm;
31 
32 #define DEBUG_TYPE "wasm-add-missing-prototypes"
33 
34 namespace {
35 class WebAssemblyAddMissingPrototypes final : public ModulePass {
36  StringRef getPassName() const override {
37  return "Add prototypes to prototypes-less functions";
38  }
39 
40  void getAnalysisUsage(AnalysisUsage &AU) const override {
41  AU.setPreservesCFG();
43  }
44 
45  bool runOnModule(Module &M) override;
46 
47 public:
48  static char ID;
49  WebAssemblyAddMissingPrototypes() : ModulePass(ID) {}
50 };
51 } // End anonymous namespace
52 
54 INITIALIZE_PASS(WebAssemblyAddMissingPrototypes, DEBUG_TYPE,
55  "Add prototypes to prototypes-less functions", false, false)
56 
58  return new WebAssemblyAddMissingPrototypes();
59 }
60 
61 bool WebAssemblyAddMissingPrototypes::runOnModule(Module &M) {
62  LLVM_DEBUG(dbgs() << "********** Add Missing Prototypes **********\n");
63 
64  std::vector<std::pair<Function *, Function *>> Replacements;
65 
66  // Find all the prototype-less function declarations
67  for (Function &F : M) {
68  if (!F.isDeclaration() || !F.hasFnAttribute("no-prototype"))
69  continue;
70 
71  LLVM_DEBUG(dbgs() << "Found no-prototype function: " << F.getName()
72  << "\n");
73 
74  // When clang emits prototype-less C functions it uses (...), i.e. varargs
75  // function that take no arguments (have no sentinel). When we see a
76  // no-prototype attribute we expect the function have these properties.
77  if (!F.isVarArg())
79  "Functions with 'no-prototype' attribute must take varargs: " +
80  F.getName());
81  if (F.getFunctionType()->getNumParams() != 0)
83  "Functions with 'no-prototype' attribute should not have params: " +
84  F.getName());
85 
86  // Create a function prototype based on the first call site (first bitcast)
87  // that we find.
88  FunctionType *NewType = nullptr;
89  Function *NewF = nullptr;
90  for (Use &U : F.uses()) {
91  LLVM_DEBUG(dbgs() << "prototype-less use: " << F.getName() << "\n");
92  if (auto *BC = dyn_cast<BitCastOperator>(U.getUser())) {
93  if (auto *DestType = dyn_cast<FunctionType>(
94  BC->getDestTy()->getPointerElementType())) {
95  if (!NewType) {
96  // Create a new function with the correct type
97  NewType = DestType;
98  NewF = Function::Create(NewType, F.getLinkage(), F.getName() + ".fixed_sig");
99  NewF->setAttributes(F.getAttributes());
100  NewF->removeFnAttr("no-prototype");
101  Replacements.emplace_back(&F, NewF);
102  } else {
103  if (NewType != DestType) {
104  report_fatal_error("Prototypeless function used with "
105  "conflicting signatures: " +
106  F.getName());
107  }
108  }
109  }
110  }
111  }
112 
113  if (!NewType) {
114  LLVM_DEBUG(
115  dbgs() << "could not derive a function prototype from usage: " +
116  F.getName() + "\n");
117  continue;
118  }
119  }
120 
121  for (auto &Pair : Replacements) {
122  Function *OldF = Pair.first;
123  Function *NewF = Pair.second;
124  std::string Name = OldF->getName();
125  M.getFunctionList().push_back(NewF);
126  OldF->replaceAllUsesWith(
128  OldF->eraseFromParent();
129  NewF->setName(Name);
130  }
131 
132  return !Replacements.empty();
133 }
static Constant * getPointerBitCastOrAddrSpaceCast(Constant *C, Type *Ty)
Create a BitCast or AddrSpaceCast for a pointer type depending on the address space.
Definition: Constants.cpp:1601
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:139
This class represents lattice values for constants.
Definition: AllocatorList.h:23
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:64
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
F(f)
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:74
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
A Use represents the edge between a Value definition and its users.
Definition: Use.h:55
void setName(const Twine &Name)
Change the name of the value.
Definition: Value.cpp:285
Class to represent function types.
Definition: DerivedTypes.h:102
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:91
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:429
ModulePass * createWebAssemblyAddMissingPrototypes()
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition: Function.h:135
INITIALIZE_PASS(WebAssemblyAddMissingPrototypes, DEBUG_TYPE, "Add prototypes to prototypes-less functions", false, false) ModulePass *llvm
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Represent the analysis usage information of a pass.
Module.h This file contains the declarations for the Module class.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:285
void setAttributes(AttributeList Attrs)
Set the attribute list for this Function.
Definition: Function.h:226
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
StringRef getName() const
Return a constant reference to the value&#39;s name.
Definition: Value.cpp:214
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:224
void eraseFromParent()
eraseFromParent - This method unlinks &#39;this&#39; from the containing module and deletes it...
Definition: Function.cpp:213
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
Definition: Function.h:245
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
#define LLVM_DEBUG(X)
Definition: Debug.h:122
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:273