[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

``