Index: lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp +++ lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp @@ -96,9 +96,10 @@ if (!NewType) { // Create a new function with the correct type NewType = DestType; - NewF = Function::Create(NewType, F.getLinkage(), F.getName()); + NewF = Function::Create(NewType, F.getLinkage(), F.getName() + ".fixed_sig"); NewF->setAttributes(F.getAttributes()); NewF->removeFnAttr("no-prototype"); + Replacements.emplace_back(&F, NewF); } else { if (NewType != DestType) { report_fatal_error("Prototypeless function used with " @@ -116,45 +117,17 @@ F.getName() + "\n"); continue; } - - SmallVector DeadInsts; - - for (Use &US : F.uses()) { - User *U = US.getUser(); - if (auto *BC = dyn_cast(U)) { - if (auto *Inst = dyn_cast(U)) { - // Replace with a new bitcast - IRBuilder<> Builder(Inst); - Value *NewCast = Builder.CreatePointerCast(NewF, BC->getDestTy()); - Inst->replaceAllUsesWith(NewCast); - DeadInsts.push_back(Inst); - } else if (auto *Const = dyn_cast(U)) { - Constant *NewConst = - ConstantExpr::getPointerCast(NewF, BC->getDestTy()); - Const->replaceAllUsesWith(NewConst); - } else { - dbgs() << *U->getType() << "\n"; -#ifndef NDEBUG - U->dump(); -#endif - report_fatal_error("unexpected use of prototypeless function: " + - F.getName() + "\n"); - } - } - } - - for (auto I : DeadInsts) - I->eraseFromParent(); - Replacements.emplace_back(&F, NewF); } - - // Finally replace the old function declarations with the new ones for (auto &Pair : Replacements) { - Function *Old = Pair.first; - Function *New = Pair.second; - Old->eraseFromParent(); - M.getFunctionList().push_back(New); + Function *OldF = Pair.first; + Function *NewF = Pair.second; + std::string Name = OldF->getName(); + M.getFunctionList().push_back(NewF); + OldF->replaceAllUsesWith( + ConstantExpr::getPointerBitCastOrAddrSpaceCast(NewF, OldF->getType())); + OldF->eraseFromParent(); + NewF->setName(Name); } return !Replacements.empty(); Index: test/CodeGen/WebAssembly/add-prototypes.ll =================================================================== --- test/CodeGen/WebAssembly/add-prototypes.ll +++ test/CodeGen/WebAssembly/add-prototypes.ll @@ -17,7 +17,8 @@ } ; CHECK-LABEL: @call_foo_ptr -; CHECK: %call = call i64 @foo(i32 43) +; CHECK: %1 = bitcast i64 (...)* bitcast (i64 (i32)* @foo to i64 (...)*) to i64 (i32)* +; CHECK-NEXT: %call = call i64 %1(i32 43) define i64 @call_foo_ptr(i32 %a) { %1 = bitcast i64 (...)* @foo to i64 (i32)* %call = call i64 (i32) %1(i32 43) @@ -25,7 +26,8 @@ } ; CHECK-LABEL: @to_intptr_inst -; CHECK: ret i8* bitcast (i64 (i32)* @foo to i8*) +; CHECK: %1 = bitcast i64 (...)* bitcast (i64 (i32)* @foo to i64 (...)*) to i8* +; CHECK-NEXT: ret i8* %1 define i8* @to_intptr_inst() { %1 = bitcast i64 (...)* @foo to i8* ret i8* %1 @@ -37,8 +39,27 @@ ret i8* bitcast (i64 (...)* @foo to i8*) } -; CHECK: declare i64 @foo(i32) -declare i64 @foo(...) #1 +; CHECK-LABEL: @null_compare +; CHECK: br i1 icmp eq (i64 (...)* bitcast (i64 (i32)* @foo to i64 (...)*), i64 (...)* null), label %if.then, label %if.end +define i8 @null_compare() { + br i1 icmp eq (i64 (...)* @foo, i64 (...)* null), label %if.then, label %if.end +if.then: + ret i8 0 +if.end: + ret i8 1 +} + +; CHECK-LABEL: @as_paramater +; CHECK: call void @func_param(i64 (...)* bitcast (i64 (i32)* @foo to i64 (...)*)) +define void @as_paramater() { + call void @func_param(i64 (...)* @foo) + ret void +} + +declare void @func_param(i64 (...)*) + +; CHECK: declare extern_weak i64 @foo(i32) +declare extern_weak i64 @foo(...) #1 ; CHECK-NOT: attributes {{.*}} = { {{.*}}"no-prototype"{{.*}} } attributes #1 = { "no-prototype" }