summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2018-11-13 19:14:02 +0000
committerSam Clegg <sbc@chromium.org>2018-11-13 19:14:02 +0000
commitf98ba05f3d01517c9fee4e64da13101fccb821b7 (patch)
treee7b90d5c1ff6262165e1dcdbfe27f5b9b75d1f2e /llvm/lib
parent551acf03dc7dc81acffd3a0816ad4d6283ccc61f (diff)
downloadbcm5719-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.cpp69
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;
OpenPOWER on IntegriCloud