LLVM: lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
34using namespace llvm;
35
36#define DEBUG_TYPE "wasm-fix-function-bitcasts"
37
38namespace {
39class FixFunctionBitcasts final : public ModulePass {
40 StringRef getPassName() const override {
41 return "WebAssembly Fix Function Bitcasts";
42 }
43
44 void getAnalysisUsage(AnalysisUsage &AU) const override {
47 }
48
49 bool runOnModule(Module &M) override;
50
51public:
52 static char ID;
54};
55}
56
57char FixFunctionBitcasts::ID = 0;
59 "Fix mismatching bitcasts for WebAssembly", false, false)
60
62 return new FixFunctionBitcasts();
63}
64
65
66
75 Value *Callee = CB->getCalledOperand();
76 if (Callee != V)
77
78 continue;
79 if (CB->getFunctionType() == F.getValueType())
80
81 continue;
82 Uses.push_back(std::make_pair(CB, &F));
83 }
84 }
85}
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
111 Module *M = F->getParent();
112
114 F->getName() + "_bitcast", M);
115 Wrapper->setAttributes(F->getAttributes());
119
120
126 bool TypeMismatch = false;
127 bool WrapperNeeded = false;
128
129 Type *ExpectedRtnType = F->getFunctionType()->getReturnType();
130 Type *RtnType = Ty->getReturnType();
131
132 if ((F->getFunctionType()->getNumParams() != Ty->getNumParams()) ||
133 (F->getFunctionType()->isVarArg() != Ty->isVarArg()) ||
134 (ExpectedRtnType != RtnType))
135 WrapperNeeded = true;
136
137 for (; AI != AE && PI != PE; ++AI, ++PI) {
139 Type *ParamType = *PI;
140
141 if (ArgType == ParamType) {
142 Args.push_back(&*AI);
143 } else {
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;
150 } else {
151 LLVM_DEBUG(dbgs() << "createWrapper: arg type mismatch calling: "
152 << F->getName() << "\n");
153 LLVM_DEBUG(dbgs() << "Arg[" << Args.size() << "] Expected: "
154 << *ParamType << " Got: " << *ArgType << "\n");
155 TypeMismatch = true;
156 break;
157 }
158 }
159 }
160
161 if (WrapperNeeded && !TypeMismatch) {
162 for (; PI != PE; ++PI)
164 if (F->isVarArg())
165 for (; AI != AE; ++AI)
166 Args.push_back(&*AI);
167
169
170
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);
179 DL)) {
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;
185 } else {
186 LLVM_DEBUG(dbgs() << "createWrapper: return type mismatch calling: "
187 << F->getName() << "\n");
188 LLVM_DEBUG(dbgs() << "Expected: " << *ExpectedRtnType
189 << " Got: " << *RtnType << "\n");
190 TypeMismatch = true;
191 }
192 }
193
194 if (TypeMismatch) {
195
196 Wrapper->eraseFromParent();
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()
204 << "\n");
205 Wrapper->eraseFromParent();
206 return nullptr;
207 }
208 LLVM_DEBUG(dbgs() << "createWrapper: " << F->getName() << "\n");
210}
211
212
213
215
216
217
218 return FuncTy->getReturnType() == MainTy->getReturnType() &&
219 FuncTy->getNumParams() == 0 &&
220 !FuncTy->isVarArg();
221}
222
223bool FixFunctionBitcasts::runOnModule(Module &M) {
224 LLVM_DEBUG(dbgs() << "********** Fix Function Bitcasts **********\n");
225
227 CallInst *CallMain = nullptr;
229
230
231 for (Function &F : M) {
232
233
234 if (F.getCallingConv() == CallingConv::Swift)
235 continue;
237
238
239
240
241
242 if (F.getName() == "main") {
243 Main = &F;
244 LLVMContext &C = M.getContext();
245 Type *MainArgTys[] = {Type::getInt32Ty(C), PointerType::get(C, 0)};
246 FunctionType *MainTy = FunctionType::get(Type::getInt32Ty(C), MainArgTys,
247 false);
249 LLVM_DEBUG(dbgs() << "Found `main` function with incorrect type: "
250 << *F.getFunctionType() << "\n");
253 CallMain = CallInst::Create(MainTy, Main, Args, "call_main");
254 Uses.push_back(std::make_pair(CallMain, &F));
255 }
256 }
257 }
258
259 DenseMap<std::pair<Function *, FunctionType *>, Function *> Wrappers;
260
261 for (auto &UseFunc : Uses) {
262 CallBase *CB = UseFunc.first;
265
266 auto Pair = Wrappers.try_emplace(std::make_pair(F, Ty));
267 if (Pair.second)
269
272 continue;
273
275 }
276
277
278
279 if (CallMain) {
280 Main->setName("__original_main");
281 auto *MainWrapper =
283 delete CallMain;
285
286
287 MainWrapper->eraseFromParent();
288 } else {
289
290
291 MainWrapper->setName("main");
292 MainWrapper->setLinkage(Main->getLinkage());
293 MainWrapper->setVisibility(Main->getVisibility());
294 }
295 }
296
297 return true;
298}
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)
Definition WebAssemblyFixFunctionBitcasts.cpp:67
static bool shouldFixMainFunction(FunctionType *FuncTy, FunctionType *MainTy)
Definition WebAssemblyFixFunctionBitcasts.cpp:214
static Function * createWrapper(Function *F, FunctionType *Ty)
Definition WebAssemblyFixFunctionBitcasts.cpp:110
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 - 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 - Return the argument parameter cast to the specified type.