[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