diff options
| author | Sam Clegg <sbc@chromium.org> | 2018-11-13 19:14:02 +0000 |
|---|---|---|
| committer | Sam Clegg <sbc@chromium.org> | 2018-11-13 19:14:02 +0000 |
| commit | f98ba05f3d01517c9fee4e64da13101fccb821b7 (patch) | |
| tree | e7b90d5c1ff6262165e1dcdbfe27f5b9b75d1f2e /llvm/lib | |
| parent | 551acf03dc7dc81acffd3a0816ad4d6283ccc61f (diff) | |
| download | bcm5719-llvm-f98ba05f3d01517c9fee4e64da13101fccb821b7.tar.gz bcm5719-llvm-f98ba05f3d01517c9fee4e64da13101fccb821b7.zip | |
[WebAssembly] Fix broken assumption that all bitcasts are to functions types
Specifically, we can bitcast to void.
Fixes PR39591
Differential Revision: https://reviews.llvm.org/D54447
llvm-svn: 346778
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp | 69 |
1 files changed, 43 insertions, 26 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp index a4d276c7936..3f17160964b 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp @@ -90,16 +90,23 @@ bool WebAssemblyAddMissingPrototypes::runOnModule(Module &M) { Function *NewF = nullptr; for (Use &U : F.uses()) { LLVM_DEBUG(dbgs() << "prototype-less use: " << F.getName() << "\n"); - if (BitCastOperator *BC = dyn_cast<BitCastOperator>(U.getUser())) { - FunctionType *DestType = - cast<FunctionType>(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<BitCastOperator>(U.getUser())) { + if (auto *DestType = dyn_cast<FunctionType>( + 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,28 +117,38 @@ bool WebAssemblyAddMissingPrototypes::runOnModule(Module &M) { continue; } - for (Use &U : F.uses()) { - if (BitCastOperator *BC = dyn_cast<BitCastOperator>(U.getUser())) { - FunctionType *DestType = - cast<FunctionType>(BC->getDestTy()->getPointerElementType()); - if (NewType != DestType) { - report_fatal_error( - "Prototypeless function used with conflicting signatures: " + - F.getName()); - } - BC->replaceAllUsesWith(NewF); - Replacements.emplace_back(&F, NewF); - } else { - dbgs() << *U.getUser()->getType() << "\n"; + SmallVector<Instruction *, 4> DeadInsts; + + for (Use &US : F.uses()) { + User *U = US.getUser(); + if (auto *BC = dyn_cast<BitCastOperator>(U)) { + if (auto *Inst = dyn_cast<BitCastInst>(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<ConstantExpr>(U)) { + Constant *NewConst = + ConstantExpr::getPointerCast(NewF, BC->getDestTy()); + Const->replaceAllUsesWith(NewConst); + } else { + dbgs() << *U->getType() << "\n"; #ifndef NDEBUG - U.getUser()->dump(); + U->dump(); #endif - report_fatal_error( - "unexpected use of prototypeless function: " + F.getName() + "\n"); + 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; |

