Index: lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp +++ lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp @@ -90,16 +90,24 @@ Function *NewF = nullptr; for (Use &U : F.uses()) { LLVM_DEBUG(dbgs() << "prototype-less use: " << F.getName() << "\n"); - if (BitCastOperator *BC = dyn_cast(U.getUser())) { - FunctionType *DestType = - cast(BC->getDestTy()->getPointerElementType()); - - // Create a new function with the correct type - NewType = DestType; - NewF = Function::Create(NewType, F.getLinkage(), F.getName()); - NewF->setAttributes(F.getAttributes()); - NewF->removeFnAttr("no-prototype"); - break; + if (auto *BC = dyn_cast(U.getUser())) { + if (auto *DestType = dyn_cast( + BC->getDestTy()->getPointerElementType())) { + + if (!NewType) { + // Create a new function with the correct type + NewType = DestType; + NewF = Function::Create(NewType, F.getLinkage(), F.getName()); + NewF->setAttributes(F.getAttributes()); + NewF->removeFnAttr("no-prototype"); + } else { + if (NewType != DestType) { + report_fatal_error("Prototypeless function used with " + "conflicting signatures: " + + F.getName()); + } + } + } } } @@ -110,26 +118,30 @@ continue; } - for (Use &U : F.uses()) { - if (BitCastOperator *BC = dyn_cast(U.getUser())) { - FunctionType *DestType = - cast(BC->getDestTy()->getPointerElementType()); - if (NewType != DestType) { + for (Use &US : F.uses()) { + User* U = US.getUser(); + if (BitCastOperator *BC = dyn_cast(U)) { + if (BitCastInst *Inst = dyn_cast(U)) { + // Replace with a new bitcast + IRBuilder<> Builder(Inst); + Value *NewCast = Builder.CreatePointerCast(NewF, BC->getDestTy()); + Inst->replaceAllUsesWith(NewCast); + Inst->eraseFromParent(); + } else if (ConstantExpr *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( - "Prototypeless function used with conflicting signatures: " + - F.getName()); + "unexpected use of prototypeless function: " + F.getName() + "\n"); } - BC->replaceAllUsesWith(NewF); - Replacements.emplace_back(&F, NewF); - } else { - dbgs() << *U.getUser()->getType() << "\n"; -#ifndef NDEBUG - U.getUser()->dump(); -#endif - report_fatal_error( - "unexpected use of prototypeless function: " + F.getName() + "\n"); } } + + Replacements.emplace_back(&F, NewF); } // Finally replace the old function declarations with the new ones Index: test/CodeGen/WebAssembly/add-prototypes.ll =================================================================== --- test/CodeGen/WebAssembly/add-prototypes.ll +++ test/CodeGen/WebAssembly/add-prototypes.ll @@ -4,13 +4,28 @@ target triple = "wasm32-unknown-unknown" @foo_addr = global i64 (i32)* bitcast (i64 (...)* @foo to i64 (i32)*), align 8 +@foo_addr_i8 = global i8* bitcast (i64 (...)* @foo to i8*), align 8 -define void @bar(i32 %a) { -entry: +define void @call_foo(i32 %a) { %call = call i64 bitcast (i64 (...)* @foo to i64 (i32)*)(i32 42) ret void } +define i64 @call_foo_ptr(i32 %a) { + %1 = bitcast i64 (...)* @foo to i64 (i32)* + %call = call i64 (i32) %1(i32 1) + ret i64 %call +} + +define i8* @to_intptr_inst() { + %1 = bitcast i64 (...)* @foo to i8* + ret i8* %1 +} + +define i8* @to_intptr_const() { + ret i8* bitcast (i64 (...)* @foo to i8*) +} + declare i64 @foo(...) #1 attributes #1 = { "no-prototype" }