1//===-- WebAssemblyFixFunctionBitcasts.cpp - Fix function bitcasts --------===//
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
7//===----------------------------------------------------------------------===//
10/// Fix bitcasted functions.
12/// WebAssembly requires caller and callee signatures to match, however in LLVM,
13/// some amount of slop is vaguely permitted. Detect mismatch by looking for
14/// bitcasts of functions and rewrite them to use wrapper functions instead.
16/// This doesn't catch all cases, such as when a function's address is taken in
17/// one place and casted in another, but it works for many common cases.
19/// Note that LLVM already optimizes away function bitcasts in common cases by
20/// dropping arguments as needed, so this pass only ends up getting used in less
23//===----------------------------------------------------------------------===//
36 #define DEBUG_TYPE "wasm-fix-function-bitcasts"
39class FixFunctionBitcasts final :
public ModulePass {
41 return "WebAssembly Fix Function Bitcasts";
49 bool runOnModule(
Module &M)
override;
55}
// End anonymous namespace
57char FixFunctionBitcasts::ID = 0;
59 "Fix mismatching bitcasts for WebAssembly",
false,
false)
62 return new FixFunctionBitcasts();
65// Recursively descend the def-use lists from V to find non-bitcast users of
75 Value *Callee = CB->getCalledOperand();
77 // Skip calls where the function isn't the callee
79 if (CB->getFunctionType() ==
F.getValueType())
80 // Skip uses that are immediately called
82 Uses.push_back(std::make_pair(CB, &
F));
87// Create a wrapper function with type Ty that calls F (which may have a
88// different type). Attempt to support common bitcasted function idioms:
89// - Call with more arguments than needed: arguments are dropped
90// - Call with fewer arguments than needed: arguments are filled in with poison
91// - Return value is not needed: drop it
92// - Return value needed but not present: supply a poison value
94// If the all the argument types of trivially castable to one another (i.e.
95// I32 vs pointer type) then we don't create a wrapper at all (return nullptr
98// If there is a type mismatch that we know would result in an invalid wasm
99// module then generate wrapper that contains unreachable (i.e. abort at
100// runtime). Such programs are deep into undefined behaviour territory,
101// but we choose to fail at runtime rather than generate and invalid module
102// or fail at compiler time. The reason we delay the error is that we want
103// to support the CMake which expects to be able to compile and link programs
104// that refer to functions with entirely incorrect signatures (this is how
105// CMake detects the existence of a function in a toolchain).
107// For bitcasts that involve struct types we don't know at this stage if they
108// would be equivalent at the wasm level and so we can't know if we need to
109// generate a wrapper.
114 F->getName() +
"_bitcast", M);
115 Wrapper->setAttributes(
F->getAttributes());
120 // Determine what arguments to pass.
126 bool TypeMismatch =
false;
127 bool WrapperNeeded =
false;
129 Type *ExpectedRtnType =
F->getFunctionType()->getReturnType();
130 Type *RtnType = Ty->getReturnType();
132 if ((
F->getFunctionType()->getNumParams() != Ty->getNumParams()) ||
133 (
F->getFunctionType()->isVarArg() != Ty->isVarArg()) ||
134 (ExpectedRtnType != RtnType))
135 WrapperNeeded =
true;
137 for (; AI != AE && PI != PE; ++AI, ++PI) {
139 Type *ParamType = *PI;
141 if (ArgType == ParamType) {
142 Args.push_back(&*AI);
145 Args.push_back(Builder.CreateBitOrPointerCast(AI, ParamType,
"cast"));
147 LLVM_DEBUG(
dbgs() <<
"createWrapper: struct param type in bitcast: "
148 <<
F->getName() <<
"\n");
149 WrapperNeeded =
false;
152 <<
F->getName() <<
"\n");
154 << *ParamType <<
" Got: " << *ArgType <<
"\n");
161 if (WrapperNeeded && !TypeMismatch) {
162 for (; PI != PE; ++PI)
165 for (; AI != AE; ++AI)
166 Args.push_back(&*AI);
170 // Determine what value to return.
172 Builder.CreateRetVoid();
173 }
else if (ExpectedRtnType->
isVoidTy()) {
174 LLVM_DEBUG(
dbgs() <<
"Creating dummy return: " << *RtnType <<
"\n");
176 }
else if (RtnType == ExpectedRtnType) {
177 Builder.CreateRet(
Call);
180 Builder.CreateRet(Builder.CreateBitOrPointerCast(
Call, RtnType,
"cast"));
182 LLVM_DEBUG(
dbgs() <<
"createWrapper: struct return type in bitcast: "
183 <<
F->getName() <<
"\n");
184 WrapperNeeded =
false;
186 LLVM_DEBUG(
dbgs() <<
"createWrapper: return type mismatch calling: "
187 <<
F->getName() <<
"\n");
189 <<
" Got: " << *RtnType <<
"\n");
195 // Create a new wrapper that simply contains `unreachable`.
198 F->getName() +
"_bitcast_invalid", M);
199 Wrapper->setAttributes(
F->getAttributes());
201 Builder.CreateUnreachable();
202 }
else if (!WrapperNeeded) {
203 LLVM_DEBUG(
dbgs() <<
"createWrapper: no wrapper needed: " <<
F->getName()
212// Test whether a main function with type FuncTy should be rewritten to have
215 // Only fix the main function if it's the standard zero-arg form. That way,
216 // the standard cases will work as expected, and users will see signature
217 // mismatches from the linker for non-standard cases.
218 return FuncTy->getReturnType() == MainTy->getReturnType() &&
219 FuncTy->getNumParams() == 0 &&
223bool FixFunctionBitcasts::runOnModule(
Module &M) {
224 LLVM_DEBUG(
dbgs() <<
"********** Fix Function Bitcasts **********\n");
227 CallInst *CallMain =
nullptr;
230 // Collect all the places that need wrappers.
231 for (Function &
F : M) {
232 // Skip to fix when the function is swiftcc because swiftcc allows
233 // bitcast type difference for swiftself and swifterror.
234 if (
F.getCallingConv() == CallingConv::Swift)
238 // If we have a "main" function, and its type isn't
239 // "int main(int argc, char *argv[])", create an artificial call with it
240 // bitcasted to that type so that we generate a wrapper for it, so that
241 // the C runtime can call it.
242 if (
F.getName() ==
"main") {
244 LLVMContext &
C =
M.getContext();
245 Type *MainArgTys[] = {Type::getInt32Ty(
C), PointerType::get(
C, 0)};
246 FunctionType *MainTy = FunctionType::get(Type::getInt32Ty(
C), MainArgTys,
249 LLVM_DEBUG(
dbgs() <<
"Found `main` function with incorrect type: "
250 << *
F.getFunctionType() <<
"\n");
254 Uses.push_back(std::make_pair(CallMain, &
F));
259 DenseMap<std::pair<Function *, FunctionType *>,
Function *> Wrappers;
261 for (
auto &UseFunc :
Uses) {
262 CallBase *CB = UseFunc.first;
266 auto Pair = Wrappers.
try_emplace(std::make_pair(
F, Ty));
277 // If we created a wrapper for main, rename the wrapper so that it's the
278 // one that gets called from startup.
280 Main->
setName(
"__original_main");
285 // The wrapper is not needed in this case as we don't need to export
286 // it to anyone else.
287 MainWrapper->eraseFromParent();
289 // Otherwise give the wrapper the same linkage as the original main
290 // function, so that it can be called from the same places.
291 MainWrapper->setName(
"main");
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Module.h This file contains the declarations for the Module class.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Remove Loads Into Fake Uses
static void findUses(Value *V, Function &F, SmallVectorImpl< std::pair< CallBase *, Function * > > &Uses)
static bool shouldFixMainFunction(FunctionType *FuncTy, FunctionType *MainTy)
static Function * createWrapper(Function *F, FunctionType *Ty)
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
Represent the analysis usage information of a pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
LLVM Basic Block Representation.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this basic block belongs to.
Value * getCalledOperand() const
FunctionType * getFunctionType() const
void setCalledOperand(Value *V)
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
static LLVM_ABI bool isBitOrNoopPointerCastable(Type *SrcTy, Type *DestTy, const DataLayout &DL)
Check whether a bitcast, inttoptr, or ptrtoint cast between these types is valid and a no-op.
A parsed version of the target data layout string in and methods for querying it.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Type::subtype_iterator param_iterator
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
VisibilityTypes getVisibility() const
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
LinkageTypes getLinkage() const
@ PrivateLinkage
Like Internal, but omit from symbol table.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isStructTy() const
True if this is an instance of StructType.
bool isVoidTy() const
Return true if this is 'void'.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
iterator_range< user_iterator > users()
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
ModulePass * createWebAssemblyFixFunctionBitcasts()
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.