35#define DEBUG_TYPE "wasm-fix-function-bitcasts"
38class FixFunctionBitcasts final :
public ModulePass {
40 return "WebAssembly Fix Function Bitcasts";
48 bool runOnModule(
Module &M)
override;
56char FixFunctionBitcasts::ID = 0;
58 "Fix mismatching bitcasts for WebAssembly",
false,
false)
61 return new FixFunctionBitcasts();
74 Value *Callee = CB->getCalledOperand();
78 if (CB->getFunctionType() ==
F.getValueType())
81 Uses.push_back(std::make_pair(CB, &
F));
113 F->getName() +
"_bitcast", M);
114 Wrapper->setAttributes(
F->getAttributes());
124 bool TypeMismatch =
false;
125 bool WrapperNeeded =
false;
127 Type *ExpectedRtnType =
F->getFunctionType()->getReturnType();
128 Type *RtnType = Ty->getReturnType();
130 if ((
F->getFunctionType()->getNumParams() != Ty->getNumParams()) ||
131 (
F->getFunctionType()->isVarArg() != Ty->isVarArg()) ||
132 (ExpectedRtnType != RtnType))
133 WrapperNeeded =
true;
135 for (; AI != AE && PI != PE; ++AI, ++PI) {
137 Type *ParamType = *PI;
139 if (ArgType == ParamType) {
140 Args.push_back(&*AI);
146 Args.push_back(PtrCast);
148 LLVM_DEBUG(
dbgs() <<
"createWrapper: struct param type in bitcast: "
149 <<
F->getName() <<
"\n");
150 WrapperNeeded =
false;
153 <<
F->getName() <<
"\n");
155 << *ParamType <<
" Got: " << *ArgType <<
"\n");
162 if (WrapperNeeded && !TypeMismatch) {
163 for (; PI != PE; ++PI)
166 for (; AI != AE; ++AI)
167 Args.push_back(&*AI);
171 Type *ExpectedRtnType =
F->getFunctionType()->getReturnType();
172 Type *RtnType = Ty->getReturnType();
176 }
else if (ExpectedRtnType->
isVoidTy()) {
177 LLVM_DEBUG(
dbgs() <<
"Creating dummy return: " << *RtnType <<
"\n");
179 }
else if (RtnType == ExpectedRtnType) {
188 LLVM_DEBUG(
dbgs() <<
"createWrapper: struct return type in bitcast: "
189 <<
F->getName() <<
"\n");
190 WrapperNeeded =
false;
192 LLVM_DEBUG(
dbgs() <<
"createWrapper: return type mismatch calling: "
193 <<
F->getName() <<
"\n");
195 <<
" Got: " << *RtnType <<
"\n");
204 F->getName() +
"_bitcast_invalid", M);
205 Wrapper->setAttributes(
F->getAttributes());
208 Wrapper->setName(
F->getName() +
"_bitcast_invalid");
209 }
else if (!WrapperNeeded) {
210 LLVM_DEBUG(
dbgs() <<
"createWrapper: no wrapper needed: " <<
F->getName()
225 return FuncTy->getReturnType() == MainTy->getReturnType() &&
226 FuncTy->getNumParams() == 0 &&
230bool FixFunctionBitcasts::runOnModule(
Module &M) {
231 LLVM_DEBUG(
dbgs() <<
"********** Fix Function Bitcasts **********\n");
234 CallInst *CallMain =
nullptr;
238 for (Function &
F : M) {
241 if (
F.getCallingConv() == CallingConv::Swift)
249 if (
F.getName() ==
"main") {
251 LLVMContext &
C =
M.getContext();
252 Type *MainArgTys[] = {Type::getInt32Ty(
C), PointerType::get(
C, 0)};
253 FunctionType *MainTy = FunctionType::get(Type::getInt32Ty(
C), MainArgTys,
256 LLVM_DEBUG(
dbgs() <<
"Found `main` function with incorrect type: "
257 << *
F.getFunctionType() <<
"\n");
261 Uses.push_back(std::make_pair(CallMain, &
F));
266 DenseMap<std::pair<Function *, FunctionType *>,
Function *> Wrappers;
268 for (
auto &UseFunc :
Uses) {
269 CallBase *CB = UseFunc.first;
273 auto Pair = Wrappers.
try_emplace(std::make_pair(
F, Ty));
287 Main->
setName(
"__original_main");
294 MainWrapper->eraseFromParent();
298 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.
static LLVM_ABI CastInst * CreateBitOrPointerCast(Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Create a BitCast, a PtrToInt, or an IntToPTr cast instruction.
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.
LLVM_ABI InstListType::iterator insertInto(BasicBlock *ParentBB, InstListType::iterator It)
Inserts an unlinked instruction into ParentBB at position It and returns the iterator of the inserted...
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.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
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'.
This function has undefined behavior.
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.