[llvm] 7f058ce - [WebAssembly] Support opaque pointers in FixFunctionBitcasts

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 1 13:17:34 PDT 2021


Author: Nikita Popov
Date: 2021-09-01T22:17:24+02:00
New Revision: 7f058ce8c2cb433bec71445c770fb3f7a401b3e4

URL: https://github.com/llvm/llvm-project/commit/7f058ce8c2cb433bec71445c770fb3f7a401b3e4
DIFF: https://github.com/llvm/llvm-project/commit/7f058ce8c2cb433bec71445c770fb3f7a401b3e4.diff

LOG: [WebAssembly] Support opaque pointers in FixFunctionBitcasts

With opaque pointers, no actual bitcasts will be present. Instead,
there will be a mismatch between the call FunctionType and the
function ValueType. Change the code to collect CallBases
specifically (rather than general Uses) and compare these types.

RAUW is no longer performed, as there would no longer be any
bitcasts that can be RAUWd.

Differential Revision: https://reviews.llvm.org/D108880

Added: 
    

Modified: 
    llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp
    llvm/test/CodeGen/WebAssembly/function-bitcasts.ll
    llvm/test/CodeGen/WebAssembly/main-declaration.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp
index 7abb6fa8905cc..2a4349e02f1b7 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp
@@ -64,29 +64,21 @@ ModulePass *llvm::createWebAssemblyFixFunctionBitcasts() {
 // Recursively descend the def-use lists from V to find non-bitcast users of
 // bitcasts of V.
 static void findUses(Value *V, Function &F,
-                     SmallVectorImpl<std::pair<Use *, Function *>> &Uses,
-                     SmallPtrSetImpl<Constant *> &ConstantBCs) {
-  for (Use &U : V->uses()) {
-    if (auto *BC = dyn_cast<BitCastOperator>(U.getUser()))
-      findUses(BC, F, Uses, ConstantBCs);
-    else if (auto *A = dyn_cast<GlobalAlias>(U.getUser()))
-      findUses(A, F, Uses, ConstantBCs);
-    else if (U.get()->getType() != F.getType()) {
-      CallBase *CB = dyn_cast<CallBase>(U.getUser());
-      if (!CB)
-        // Skip uses that aren't immediately called
-        continue;
+                     SmallVectorImpl<std::pair<CallBase *, Function *>> &Uses) {
+  for (User *U : V->users()) {
+    if (auto *BC = dyn_cast<BitCastOperator>(U))
+      findUses(BC, F, Uses);
+    else if (auto *A = dyn_cast<GlobalAlias>(U))
+      findUses(A, F, Uses);
+    else if (auto *CB = dyn_cast<CallBase>(U)) {
       Value *Callee = CB->getCalledOperand();
       if (Callee != V)
         // Skip calls where the function isn't the callee
         continue;
-      if (isa<Constant>(U.get())) {
-        // Only add constant bitcasts to the list once; they get RAUW'd
-        auto C = ConstantBCs.insert(cast<Constant>(U.get()));
-        if (!C.second)
-          continue;
-      }
-      Uses.push_back(std::make_pair(&U, &F));
+      if (CB->getFunctionType() == F.getValueType())
+        // Skip uses that are immediately called
+        continue;
+      Uses.push_back(std::make_pair(CB, &F));
     }
   }
 }
@@ -238,8 +230,7 @@ bool FixFunctionBitcasts::runOnModule(Module &M) {
 
   Function *Main = nullptr;
   CallInst *CallMain = nullptr;
-  SmallVector<std::pair<Use *, Function *>, 0> Uses;
-  SmallPtrSet<Constant *, 2> ConstantBCs;
+  SmallVector<std::pair<CallBase *, Function *>, 0> Uses;
 
   // Collect all the places that need wrappers.
   for (Function &F : M) {
@@ -247,7 +238,7 @@ bool FixFunctionBitcasts::runOnModule(Module &M) {
     // bitcast type 
diff erence for swiftself and swifterror.
     if (F.getCallingConv() == CallingConv::Swift)
       continue;
-    findUses(&F, F, Uses, ConstantBCs);
+    findUses(&F, F, Uses);
 
     // If we have a "main" function, and its type isn't
     // "int main(int argc, char *argv[])", create an artificial call with it
@@ -268,8 +259,7 @@ bool FixFunctionBitcasts::runOnModule(Module &M) {
         Value *Casted =
             ConstantExpr::getBitCast(Main, PointerType::get(MainTy, 0));
         CallMain = CallInst::Create(MainTy, Casted, Args, "call_main");
-        Use *UseMain = &CallMain->getOperandUse(2);
-        Uses.push_back(std::make_pair(UseMain, &F));
+        Uses.push_back(std::make_pair(CallMain, &F));
       }
     }
   }
@@ -277,16 +267,9 @@ bool FixFunctionBitcasts::runOnModule(Module &M) {
   DenseMap<std::pair<Function *, FunctionType *>, Function *> Wrappers;
 
   for (auto &UseFunc : Uses) {
-    Use *U = UseFunc.first;
+    CallBase *CB = UseFunc.first;
     Function *F = UseFunc.second;
-    auto *PTy = cast<PointerType>(U->get()->getType());
-    auto *Ty = dyn_cast<FunctionType>(PTy->getElementType());
-
-    // If the function is casted to something like i8* as a "generic pointer"
-    // to be later casted to something else, we can't generate a wrapper for it.
-    // Just ignore such casts for now.
-    if (!Ty)
-      continue;
+    FunctionType *Ty = CB->getFunctionType();
 
     auto Pair = Wrappers.insert(std::make_pair(std::make_pair(F, Ty), nullptr));
     if (Pair.second)
@@ -296,10 +279,7 @@ bool FixFunctionBitcasts::runOnModule(Module &M) {
     if (!Wrapper)
       continue;
 
-    if (isa<Constant>(U->get()))
-      U->get()->replaceAllUsesWith(Wrapper);
-    else
-      U->set(Wrapper);
+    CB->setCalledOperand(Wrapper);
   }
 
   // If we created a wrapper for main, rename the wrapper so that it's the

diff  --git a/llvm/test/CodeGen/WebAssembly/function-bitcasts.ll b/llvm/test/CodeGen/WebAssembly/function-bitcasts.ll
index 36cd5d8094e61..5ebf2bc119764 100644
--- a/llvm/test/CodeGen/WebAssembly/function-bitcasts.ll
+++ b/llvm/test/CodeGen/WebAssembly/function-bitcasts.ll
@@ -1,7 +1,10 @@
-; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers -enable-emscripten-cxx-exceptions | FileCheck %s
+; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers -enable-emscripten-cxx-exceptions | FileCheck %s --check-prefixes=CHECK,TYPED
+; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers -enable-emscripten-cxx-exceptions -force-opaque-pointers | FileCheck %s --check-prefixes=CHECK,OPAQUE
 
 ; Test that function pointer casts are replaced with wrappers.
 
+; The TYPED and OPAQUE prefixes only 
diff er in function ordering.
+
 target triple = "wasm32-unknown-unknown"
 
 define void @has_i32_arg(i32) {
@@ -20,8 +23,10 @@ declare void @foo2()
 declare void @foo3()
 
 ; CHECK-LABEL: test:
-; CHECK:      call        .Lhas_i32_arg_bitcast.2{{$}}
-; CHECK-NEXT: call        .Lhas_i32_arg_bitcast.2{{$}}
+; TYPED:      call        .Lhas_i32_arg_bitcast.2{{$}}
+; TYPED-NEXT: call        .Lhas_i32_arg_bitcast.2{{$}}
+; OPAQUE:      call       .Lhas_i32_arg_bitcast{{$}}
+; OPAQUE-NEXT: call       .Lhas_i32_arg_bitcast{{$}}
 ; CHECK-NEXT: call        .Lhas_i32_ret_bitcast{{$}}
 ; CHECK-NEXT: call        $drop=, has_i32_ret
 ; CHECK-NEXT: i32.const   $push[[L0:[0-9]+]]=, 0
@@ -62,7 +67,8 @@ entry:
 @alias_i32_arg = weak hidden alias void (i32), void (i32)* @has_i32_arg
 
 ; CHECK-LABEL: test_alias:
-; CHECK: call    .Lhas_i32_arg_bitcast.2
+; TYPED: call    .Lhas_i32_arg_bitcast.2
+; OPAQUE: call   .Lhas_i32_arg_bitcast
 define void @test_alias() {
 entry:
   call void bitcast (void (i32)* @alias_i32_arg to void ()*)()
@@ -71,8 +77,10 @@ entry:
 
 
 ; CHECK-LABEL: test_structs:
-; CHECK: call     .Lhas_i32_arg_bitcast.1, $pop{{[0-9]+}}, $pop{{[0-9]+$}}
-; CHECK: call     .Lhas_i32_arg_bitcast, $0, $pop2
+; TYPED: call     .Lhas_i32_arg_bitcast.1, $pop{{[0-9]+}}, $pop{{[0-9]+$}}
+; TYPED: call     .Lhas_i32_arg_bitcast, $0, $pop2
+; OPAQUE: call    .Lhas_i32_arg_bitcast.2, $pop{{[0-9]+}}, $pop{{[0-9]+$}}
+; OPAQUE: call    .Lhas_i32_arg_bitcast.1, $0, $pop2
 ; CHECK: call     .Lhas_struct_arg_bitcast{{$}}
 define void @test_structs() {
 entry:
@@ -156,7 +164,8 @@ define void @test_argument() {
 ; CHECK:      i32.const   $push[[L3:[0-9]+]]=, call_func{{$}}
 ; CHECK-NEXT: i32.const   $push[[L2:[0-9]+]]=, has_i32_arg{{$}}
 ; CHECK-NEXT: call        invoke_vi, $pop[[L3]], $pop[[L2]]{{$}}
-; CHECK:      i32.const   $push[[L4:[0-9]+]]=, .Lhas_i32_arg_bitcast.2{{$}}
+; TYPED:      i32.const   $push[[L4:[0-9]+]]=, .Lhas_i32_arg_bitcast.2{{$}}
+; OPAQUE:     i32.const   $push[[L4:[0-9]+]]=, .Lhas_i32_arg_bitcast{{$}}
 ; CHECK-NEXT: call        invoke_v, $pop[[L4]]{{$}}
 declare i32 @personality(...)
 define void @test_invoke() personality i32 (...)* @personality {
@@ -181,19 +190,35 @@ end:
   ret void
 }
 
-; CHECK-LABEL: .Lhas_i32_arg_bitcast:
-; CHECK-NEXT: .functype .Lhas_i32_arg_bitcast (i32, i32) -> ()
-; CHECK-NEXT: call        has_i32_arg, $1{{$}}
-; CHECK-NEXT: end_function
-
-; CHECK-LABEL: .Lhas_i32_arg_bitcast.1:
-; CHECK-NEXT: .functype .Lhas_i32_arg_bitcast.1 (i32, i32) -> ()
-; CHECK-NEXT: call        has_i32_arg, $0{{$}}
-; CHECK-NEXT: end_function
-
-; CHECK-LABEL: .Lhas_i32_arg_bitcast.2:
-; CHECK:      call        has_i32_arg, $0{{$}}
-; CHECK-NEXT: end_function
+; TYPED-LABEL: .Lhas_i32_arg_bitcast:
+; TYPED-NEXT: .functype .Lhas_i32_arg_bitcast (i32, i32) -> ()
+; TYPED-NEXT: call        has_i32_arg, $1{{$}}
+; TYPED-NEXT: end_function
+
+; TYPED-LABEL: .Lhas_i32_arg_bitcast.1:
+; TYPED-NEXT: .functype .Lhas_i32_arg_bitcast.1 (i32, i32) -> ()
+; TYPED-NEXT: call        has_i32_arg, $0{{$}}
+; TYPED-NEXT: end_function
+
+; TYPED-LABEL: .Lhas_i32_arg_bitcast.2:
+; TYPED-NEXT: .functype	.Lhas_i32_arg_bitcast.2 () -> ()
+; TYPED-NEXT: call        has_i32_arg, $0{{$}}
+; TYPED-NEXT: end_function
+
+; OPAQUE-LABEL: .Lhas_i32_arg_bitcast:
+; OPAQUE-NEXT: .functype	.Lhas_i32_arg_bitcast () -> ()
+; OPAQUE-NEXT: call        has_i32_arg, $0{{$}}
+; OPAQUE-NEXT: end_function
+
+; OPAQUE-LABEL: .Lhas_i32_arg_bitcast.1:
+; OPAQUE-NEXT: .functype .Lhas_i32_arg_bitcast.1 (i32, i32) -> ()
+; OPAQUE-NEXT: call        has_i32_arg, $1{{$}}
+; OPAQUE-NEXT: end_function
+
+; OPAQUE-LABEL: .Lhas_i32_arg_bitcast.2:
+; OPAQUE-NEXT: .functype .Lhas_i32_arg_bitcast.2 (i32, i32) -> ()
+; OPAQUE-NEXT: call        has_i32_arg, $0{{$}}
+; OPAQUE-NEXT: end_function
 
 ; CHECK-LABEL: .Lhas_i32_ret_bitcast:
 ; CHECK:      call        $drop=, has_i32_ret{{$}}

diff  --git a/llvm/test/CodeGen/WebAssembly/main-declaration.ll b/llvm/test/CodeGen/WebAssembly/main-declaration.ll
index 445300f73fd14..81b5b1bc81df6 100644
--- a/llvm/test/CodeGen/WebAssembly/main-declaration.ll
+++ b/llvm/test/CodeGen/WebAssembly/main-declaration.ll
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -asm-verbose=false | FileCheck %s
+; RUN: llc < %s -asm-verbose=false -force-opaque-pointers | FileCheck %s
 
 ; Test main functions with alternate signatures.
 


        


More information about the llvm-commits mailing list