[WebAssembly] Be a little more conservative in WebAssemblyFixFunction… · llvm-mirror/llvm@bdeb8b8 (original) (raw)
`@@ -107,14 +107,18 @@ static void FindUses(Value *V, Function &F,
`
107
107
`// I32 vs pointer type) then we don't create a wrapper at all (return nullptr
`
108
108
`// instead).
`
109
109
`//
`
110
``
`-
// If there is a type mismatch that would result in an invalid wasm module
`
111
``
`-
// being written then generate wrapper that contains unreachable (i.e. abort
`
112
``
`-
// at runtime). Such programs are deep into undefined behaviour territory,
`
``
110
`+
// If there is a type mismatch that we know would result in an invalid wasm
`
``
111
`+
// module then generate wrapper that contains unreachable (i.e. abort at
`
``
112
`+
// runtime). Such programs are deep into undefined behaviour territory,
`
113
113
`// but we choose to fail at runtime rather than generate and invalid module
`
114
114
`// or fail at compiler time. The reason we delay the error is that we want
`
115
115
`// to support the CMake which expects to be able to compile and link programs
`
116
116
`// that refer to functions with entirely incorrect signatures (this is how
`
117
117
`// CMake detects the existence of a function in a toolchain).
`
``
118
`+
//
`
``
119
`+
// For bitcasts that involve struct types we don't know at this stage if they
`
``
120
`+
// would be equivalent at the wasm level and so we can't know if we need to
`
``
121
`+
// generate a wrapper.
`
118
122
`static Function *CreateWrapper(Function *F, FunctionType *Ty) {
`
119
123
` Module *M = F->getParent();
`
120
124
``
`@@ -132,8 +136,12 @@ static Function *CreateWrapper(Function *F, FunctionType *Ty) {
`
132
136
`bool TypeMismatch = false;
`
133
137
`bool WrapperNeeded = false;
`
134
138
``
``
139
`+
Type *ExpectedRtnType = F->getFunctionType()->getReturnType();
`
``
140
`+
Type *RtnType = Ty->getReturnType();
`
``
141
+
135
142
`if ((F->getFunctionType()->getNumParams() != Ty->getNumParams()) ||
`
136
``
`-
(F->getFunctionType()->isVarArg() != Ty->isVarArg()))
`
``
143
`+
(F->getFunctionType()->isVarArg() != Ty->isVarArg()) ||
`
``
144
`+
(ExpectedRtnType != RtnType))
`
137
145
` WrapperNeeded = true;
`
138
146
``
139
147
`for (; AI != AE && PI != PE; ++AI, ++PI) {
`
`@@ -148,6 +156,10 @@ static Function *CreateWrapper(Function *F, FunctionType *Ty) {
`
148
156
`CastInst::CreateBitOrPointerCast(AI, ParamType, "cast");
`
149
157
` BB->getInstList().push_back(PtrCast);
`
150
158
` Args.push_back(PtrCast);
`
``
159
`+
} else if (ArgType->isStructTy() || ParamType->isStructTy()) {
`
``
160
`+
LLVM_DEBUG(dbgs() << "CreateWrapper: struct param type in bitcast: "
`
``
161
`+
<< F->getName() << "\n");
`
``
162
`+
WrapperNeeded = false;
`
151
163
` } else {
`
152
164
`LLVM_DEBUG(dbgs() << "CreateWrapper: arg type mismatch calling: "
`
153
165
` << F->getName() << "\n");
`
`@@ -159,7 +171,7 @@ static Function *CreateWrapper(Function *F, FunctionType *Ty) {
`
159
171
` }
`
160
172
` }
`
161
173
``
162
``
`-
if (!TypeMismatch) {
`
``
174
`+
if (WrapperNeeded && !TypeMismatch) {
`
163
175
`for (; PI != PE; ++PI)
`
164
176
` Args.push_back(UndefValue::get(*PI));
`
165
177
`if (F->isVarArg())
`
`@@ -173,10 +185,9 @@ static Function *CreateWrapper(Function *F, FunctionType *Ty) {
`
173
185
`// Determine what value to return.
`
174
186
`if (RtnType->isVoidTy()) {
`
175
187
`ReturnInst::Create(M->getContext(), BB);
`
176
``
`-
WrapperNeeded = true;
`
177
188
` } else if (ExpectedRtnType->isVoidTy()) {
`
``
189
`+
LLVM_DEBUG(dbgs() << "Creating dummy return: " << *RtnType << "\n");
`
178
190
`ReturnInst::Create(M->getContext(), UndefValue::get(RtnType), BB);
`
179
``
`-
WrapperNeeded = true;
`
180
191
` } else if (RtnType == ExpectedRtnType) {
`
181
192
`ReturnInst::Create(M->getContext(), Call, BB);
`
182
193
` } else if (CastInst::isBitOrNoopPointerCastable(ExpectedRtnType, RtnType,
`
`@@ -185,6 +196,10 @@ static Function *CreateWrapper(Function *F, FunctionType *Ty) {
`
185
196
`CastInst::CreateBitOrPointerCast(Call, RtnType, "cast");
`
186
197
` BB->getInstList().push_back(Cast);
`
187
198
`ReturnInst::Create(M->getContext(), Cast, BB);
`
``
199
`+
} else if (RtnType->isStructTy() || ExpectedRtnType->isStructTy()) {
`
``
200
`+
LLVM_DEBUG(dbgs() << "CreateWrapper: struct return type in bitcast: "
`
``
201
`+
<< F->getName() << "\n");
`
``
202
`+
WrapperNeeded = false;
`
188
203
` } else {
`
189
204
`LLVM_DEBUG(dbgs() << "CreateWrapper: return type mismatch calling: "
`
190
205
` << F->getName() << "\n");
`
`@@ -195,6 +210,10 @@ static Function *CreateWrapper(Function *F, FunctionType *Ty) {
`
195
210
` }
`
196
211
``
197
212
`if (TypeMismatch) {
`
``
213
`` +
// Create a new wrapper that simply contains unreachable
.
``
``
214
`+
Wrapper->eraseFromParent();
`
``
215
`+
Wrapper = Function::Create(Ty, Function::PrivateLinkage, F->getName() + "_bitcast_invalid", M);
`
``
216
`+
BasicBlock *BB = BasicBlock::Create(M->getContext(), "body", Wrapper);
`
198
217
`new UnreachableInst(M->getContext(), BB);
`
199
218
` Wrapper->setName(F->getName() + "_bitcast_invalid");
`
200
219
` } else if (!WrapperNeeded) {
`
`@@ -203,6 +222,7 @@ static Function *CreateWrapper(Function *F, FunctionType *Ty) {
`
203
222
` Wrapper->eraseFromParent();
`
204
223
`return nullptr;
`
205
224
` }
`
``
225
`+
LLVM_DEBUG(dbgs() << "CreateWrapper: " << F->getName() << "\n");
`
206
226
`return Wrapper;
`
207
227
`}
`
208
228
``