@@ -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
0 commit comments