38#define DEBUG_TYPE "wasm-fix-function-bitcasts"
41class WebAssemblyFixFunctionBitcastsLegacy final :
public ModulePass {
43 return "WebAssembly Fix Function Bitcasts";
51 bool runOnModule(
Module &M)
override;
55 WebAssemblyFixFunctionBitcastsLegacy() :
ModulePass(
ID) {}
59char WebAssemblyFixFunctionBitcastsLegacy::ID = 0;
61 "Fix mismatching bitcasts for WebAssembly",
false,
false)
64 return new WebAssemblyFixFunctionBitcastsLegacy();
77 Value *Callee = CB->getCalledOperand();
81 if (CB->getFunctionType() ==
F.getFunctionType())
84 Uses.push_back(std::make_pair(CB, &
F));
116 F->getName() +
"_bitcast", M);
117 Wrapper->setAttributes(
F->getAttributes());
128 bool TypeMismatch =
false;
129 bool WrapperNeeded =
false;
131 Type *ExpectedRtnType =
F->getFunctionType()->getReturnType();
132 Type *RtnType = Ty->getReturnType();
134 if ((
F->getFunctionType()->getNumParams() != Ty->getNumParams()) ||
135 (
F->getFunctionType()->isVarArg() != Ty->isVarArg()) ||
136 (ExpectedRtnType != RtnType))
137 WrapperNeeded =
true;
139 for (; AI != AE && PI != PE; ++AI, ++PI) {
141 Type *ParamType = *PI;
143 if (ArgType == ParamType) {
144 Args.push_back(&*AI);
147 Args.push_back(Builder.CreateBitOrPointerCast(AI, ParamType,
"cast"));
149 LLVM_DEBUG(
dbgs() <<
"createWrapper: struct param type in bitcast: "
150 <<
F->getName() <<
"\n");
151 WrapperNeeded =
false;
154 <<
F->getName() <<
"\n");
156 << *ParamType <<
" Got: " << *ArgType <<
"\n");
163 if (WrapperNeeded && !TypeMismatch) {
164 for (; PI != PE; ++PI)
167 for (; AI != AE; ++AI)
168 Args.push_back(&*AI);
174 Builder.CreateRetVoid();
175 }
else if (ExpectedRtnType->
isVoidTy()) {
176 LLVM_DEBUG(
dbgs() <<
"Creating dummy return: " << *RtnType <<
"\n");
178 }
else if (RtnType == ExpectedRtnType) {
179 Builder.CreateRet(
Call);
182 Builder.CreateRet(Builder.CreateBitOrPointerCast(
Call, RtnType,
"cast"));
184 LLVM_DEBUG(
dbgs() <<
"createWrapper: struct return type in bitcast: "
185 <<
F->getName() <<
"\n");
186 WrapperNeeded =
false;
188 LLVM_DEBUG(
dbgs() <<
"createWrapper: return type mismatch calling: "
189 <<
F->getName() <<
"\n");
191 <<
" Got: " << *RtnType <<
"\n");
200 F->getName() +
"_bitcast_invalid", M);
201 Wrapper->setAttributes(
F->getAttributes());
203 Builder.CreateUnreachable();
204 }
else if (!WrapperNeeded) {
205 LLVM_DEBUG(
dbgs() <<
"createWrapper: no wrapper needed: " <<
F->getName()
220 return FuncTy->getReturnType() == MainTy->getReturnType() &&
221 FuncTy->getNumParams() == 0 &&
226 LLVM_DEBUG(
dbgs() <<
"********** Fix Function Bitcasts **********\n");
246 if (
F.getName() ==
"main") {
253 LLVM_DEBUG(
dbgs() <<
"Found `main` function with incorrect type: "
254 << *
F.getFunctionType() <<
"\n");
258 Uses.push_back(std::make_pair(CallMain, &
F));
265 for (
auto &UseFunc :
Uses) {
270 auto Pair = Wrappers.
try_emplace(std::make_pair(
F, Ty));
284 Main->
setName(
"__original_main");
291 MainWrapper->eraseFromParent();
295 MainWrapper->setName(
"main");
304bool WebAssemblyFixFunctionBitcastsLegacy::runOnModule(
Module &M) {
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.
This header defines various interfaces for pass management in LLVM.
ModuleAnalysisManager MAM
#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)
static bool fixFunctionBitcasts(Module &M)
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.
Represents analyses that only rely on functions' control flow.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
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 LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
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...
This is an important class for using LLVM in a threaded context.
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 PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
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.
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.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
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.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
Pass manager infrastructure for declaring and invalidating analyses.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Swift
Calling convention for Swift.
@ SwiftTail
This follows the Swift calling convention in how arguments are passed but guarantees tail calls will ...
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
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.
ModulePass * createWebAssemblyFixFunctionBitcastsLegacyPass()
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.