LLVM  8.0.1
WebAssemblyAddMissingPrototypes.cpp
Go to the documentation of this file.
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 
22 #include "WebAssembly.h"
23 #include "llvm/IR/Constants.h"
24 #include "llvm/IR/IRBuilder.h"
25 #include "llvm/IR/Module.h"
26 #include "llvm/IR/Operator.h"
27 #include "llvm/Pass.h"
28 #include "llvm/Support/Debug.h"
31 using namespace llvm;
32 
33 #define DEBUG_TYPE "wasm-add-missing-prototypes"
34 
35 namespace {
36 class WebAssemblyAddMissingPrototypes final : public ModulePass {
37  StringRef getPassName() const override {
38  return "Add prototypes to prototypes-less functions";
39  }
40 
41  void getAnalysisUsage(AnalysisUsage &AU) const override {
42  AU.setPreservesCFG();
44  }
45 
46  bool runOnModule(Module &M) override;
47 
48 public:
49  static char ID;
50  WebAssemblyAddMissingPrototypes() : ModulePass(ID) {}
51 };
52 } // End anonymous namespace
53 
55 INITIALIZE_PASS(WebAssemblyAddMissingPrototypes, DEBUG_TYPE,
56  "Add prototypes to prototypes-less functions", false, false)
57 
59  return new WebAssemblyAddMissingPrototypes();
60 }
61 
62 bool WebAssemblyAddMissingPrototypes::runOnModule(Module &M) {
63  LLVM_DEBUG(dbgs() << "********** Add Missing Prototypes **********\n");
64 
65  std::vector<std::pair<Function *, Function *>> Replacements;
66 
67  // Find all the prototype-less function declarations
68  for (Function &F : M) {
69  if (!F.isDeclaration() || !F.hasFnAttribute("no-prototype"))
70  continue;
71 
72  LLVM_DEBUG(dbgs() << "Found no-prototype function: " << F.getName()
73  << "\n");
74 
75  // When clang emits prototype-less C functions it uses (...), i.e. varargs
76  // function that take no arguments (have no sentinel). When we see a
77  // no-prototype attribute we expect the function have these properties.
78  if (!F.isVarArg())
80  "Functions with 'no-prototype' attribute must take varargs: " +
81  F.getName());
82  if (F.getFunctionType()->getNumParams() != 0)
84  "Functions with 'no-prototype' attribute should not have params: " +
85  F.getName());
86 
87  // Create a function prototype based on the first call site (first bitcast)
88  // that we find.
89  FunctionType *NewType = nullptr;
90  Function *NewF = nullptr;
91  for (Use &U : F.uses()) {
92  LLVM_DEBUG(dbgs() << "prototype-less use: " << F.getName() << "\n");
93  if (auto *BC = dyn_cast<BitCastOperator>(U.getUser())) {
94  if (auto *DestType = dyn_cast<FunctionType>(
95  BC->getDestTy()->getPointerElementType())) {
96  if (!NewType) {
97  // Create a new function with the correct type
98  NewType = DestType;
99  NewF = Function::Create(NewType, F.getLinkage(), F.getName());
100  NewF->setAttributes(F.getAttributes());
101  NewF->removeFnAttr("no-prototype");
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 
121 
122  for (Use &US : F.uses()) {
123  User *U = US.getUser();
124  if (auto *BC = dyn_cast<BitCastOperator>(U)) {
125  if (auto *Inst = dyn_cast<BitCastInst>(U)) {
126  // Replace with a new bitcast
127  IRBuilder<> Builder(Inst);
128  Value *NewCast = Builder.CreatePointerCast(NewF, BC->getDestTy());
129  Inst->replaceAllUsesWith(NewCast);
130  DeadInsts.push_back(Inst);
131  } else if (auto *Const = dyn_cast<ConstantExpr>(U)) {
132  Constant *NewConst =
133  ConstantExpr::getPointerCast(NewF, BC->getDestTy());
134  Const->replaceAllUsesWith(NewConst);
135  } else {
136  dbgs() << *U->getType() << "\n";
137 #ifndef NDEBUG
138  U->dump();
139 #endif
140  report_fatal_error("unexpected use of prototypeless function: " +
141  F.getName() + "\n");
142  }
143  }
144  }
145 
146  for (auto I : DeadInsts)
147  I->eraseFromParent();
148  Replacements.emplace_back(&F, NewF);
149  }
150 
151 
152  // Finally replace the old function declarations with the new ones
153  for (auto &Pair : Replacements) {
154  Function *Old = Pair.first;
155  Function *New = Pair.second;
156  Old->eraseFromParent();
157  M.getFunctionList().push_back(New);
158  }
159 
160  return !Replacements.empty();
161 }
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:140
This class represents lattice values for constants.
Definition: AllocatorList.h:24
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
F(f)
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:75
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
void dump() const
Support for debugging, callable in GDB: V->dump()
Definition: AsmWriter.cpp:4298
A Use represents the edge between a Value definition and its users.
Definition: Use.h:56
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:743
Class to represent function types.
Definition: DerivedTypes.h:103
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:92
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:245
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:136
INITIALIZE_PASS(WebAssemblyAddMissingPrototypes, DEBUG_TYPE, "Add prototypes to prototypes-less functions", false, false) ModulePass *llvm
This is an important base class in LLVM.
Definition: Constant.h:42
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Represent the analysis usage information of a pass.
static Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
Definition: Constants.cpp:1587
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
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:286
void setAttributes(AttributeList Attrs)
Set the attribute list for this Function.
Definition: Function.h:227
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:1778
#define I(x, y, z)
Definition: MD5.cpp:58
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:225
void eraseFromParent()
eraseFromParent - This method unlinks &#39;this&#39; from the containing module and deletes it...
Definition: Function.cpp:214
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
Definition: Function.h:246
LLVM Value Representation.
Definition: Value.h:73
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
#define LLVM_DEBUG(X)
Definition: Debug.h:123