[llvm] r346778 - [WebAssembly] Fix broken assumption that all bitcasts are to functions types
Sam Clegg via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 13 11:14:03 PST 2018
Author: sbc
Date: Tue Nov 13 11:14:02 2018
New Revision: 346778
URL: http://llvm.org/viewvc/llvm-project?rev=346778&view=rev
Log:
[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
Modified:
llvm/trunk/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp
llvm/trunk/test/CodeGen/WebAssembly/add-prototypes.ll
Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp?rev=346778&r1=346777&r2=346778&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp Tue Nov 13 11:14:02 2018
@@ -90,16 +90,23 @@ bool WebAssemblyAddMissingPrototypes::ru
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::ru
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;
Modified: llvm/trunk/test/CodeGen/WebAssembly/add-prototypes.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/add-prototypes.ll?rev=346778&r1=346777&r2=346778&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/add-prototypes.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/add-prototypes.ll Tue Nov 13 11:14:02 2018
@@ -3,18 +3,42 @@
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32-unknown-unknown"
+; CHECK: @foo_addr = global i64 (i32)* @foo, align 8
@foo_addr = global i64 (i32)* bitcast (i64 (...)* @foo to i64 (i32)*), align 8
-define void @bar(i32 %a) {
-entry:
+; CHECK: @foo_addr_i8 = global i8* bitcast (i64 (i32)* @foo to i8*), align 8
+ at foo_addr_i8 = global i8* bitcast (i64 (...)* @foo to i8*), align 8
+
+; CHECK-LABEL: @call_foo
+; CHECK: %call = call i64 @foo(i32 42)
+define void @call_foo(i32 %a) {
%call = call i64 bitcast (i64 (...)* @foo to i64 (i32)*)(i32 42)
ret void
}
-declare i64 @foo(...) #1
+; CHECK-LABEL: @call_foo_ptr
+; CHECK: %call = call i64 @foo(i32 43)
+define i64 @call_foo_ptr(i32 %a) {
+ %1 = bitcast i64 (...)* @foo to i64 (i32)*
+ %call = call i64 (i32) %1(i32 43)
+ ret i64 %call
+}
-attributes #1 = { "no-prototype" }
+; CHECK-LABEL: @to_intptr_inst
+; CHECK: ret i8* bitcast (i64 (i32)* @foo to i8*)
+define i8* @to_intptr_inst() {
+ %1 = bitcast i64 (...)* @foo to i8*
+ ret i8* %1
+}
+
+; CHECK-LABEL: @to_intptr_constexpr
+; CHECK: ret i8* bitcast (i64 (i32)* @foo to i8*)
+define i8* @to_intptr_constexpr() {
+ ret i8* bitcast (i64 (...)* @foo to i8*)
+}
-; CHECK: %call = call i64 @foo(i32 42)
; CHECK: declare i64 @foo(i32)
+declare i64 @foo(...) #1
+
; CHECK-NOT: attributes {{.*}} = { {{.*}}"no-prototype"{{.*}} }
+attributes #1 = { "no-prototype" }
More information about the llvm-commits
mailing list