[llvm] d3a0a65 - Reland: "[WebAssembly] Add new pass to lower int/ptr conversions of reftypes"

Paulo Matos via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 3 00:21:16 PDT 2021


Author: Paulo Matos
Date: 2021-08-03T09:20:51+02:00
New Revision: d3a0a65bf01dccadee38d726b6c4d9813c84a048

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

LOG: Reland: "[WebAssembly] Add new pass to lower int/ptr conversions of reftypes"

Add new pass LowerRefTypesIntPtrConv to generate debugtrap
instruction for an inttoptr and ptrtoint of a reference type instead
of erroring, since calling these instructions on non-integral pointers
has been since allowed (see ac81cb7e6).

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

Added: 
    llvm/lib/Target/WebAssembly/WebAssemblyLowerRefTypesIntPtrConv.cpp

Modified: 
    llvm/lib/Target/WebAssembly/CMakeLists.txt
    llvm/lib/Target/WebAssembly/WebAssembly.h
    llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
    llvm/test/CodeGen/WebAssembly/externref-inttoptr.ll
    llvm/test/CodeGen/WebAssembly/externref-ptrtoint.ll
    llvm/utils/gn/secondary/llvm/lib/Target/WebAssembly/BUILD.gn

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/WebAssembly/CMakeLists.txt b/llvm/lib/Target/WebAssembly/CMakeLists.txt
index 5ce8df82c8445..c8216aacb59e8 100644
--- a/llvm/lib/Target/WebAssembly/CMakeLists.txt
+++ b/llvm/lib/Target/WebAssembly/CMakeLists.txt
@@ -36,6 +36,7 @@ add_llvm_target(WebAssemblyCodeGen
   WebAssemblyLowerBrUnless.cpp
   WebAssemblyLowerEmscriptenEHSjLj.cpp
   WebAssemblyLowerGlobalDtors.cpp
+  WebAssemblyLowerRefTypesIntPtrConv.cpp
   WebAssemblyMachineFunctionInfo.cpp
   WebAssemblyMCInstLower.cpp
   WebAssemblyMCLowerPrePass.cpp

diff  --git a/llvm/lib/Target/WebAssembly/WebAssembly.h b/llvm/lib/Target/WebAssembly/WebAssembly.h
index 9eb960d018d3f..aefca2e6120e4 100644
--- a/llvm/lib/Target/WebAssembly/WebAssembly.h
+++ b/llvm/lib/Target/WebAssembly/WebAssembly.h
@@ -31,6 +31,7 @@ ModulePass *createWebAssemblyLowerGlobalDtors();
 ModulePass *createWebAssemblyAddMissingPrototypes();
 ModulePass *createWebAssemblyFixFunctionBitcasts();
 FunctionPass *createWebAssemblyOptimizeReturned();
+FunctionPass *createWebAssemblyLowerRefTypesIntPtrConv();
 
 // ISel and immediate followup passes.
 FunctionPass *createWebAssemblyISelDag(WebAssemblyTargetMachine &TM,
@@ -85,6 +86,7 @@ void initializeWebAssemblyRegNumberingPass(PassRegistry &);
 void initializeWebAssemblyDebugFixupPass(PassRegistry &);
 void initializeWebAssemblyPeepholePass(PassRegistry &);
 void initializeWebAssemblyMCLowerPrePassPass(PassRegistry &);
+void initializeWebAssemblyLowerRefTypesIntPtrConvPass(PassRegistry &);
 
 namespace WebAssembly {
 enum TargetIndex {

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
index f4bae59132e68..804b41b467b5a 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
@@ -24,6 +24,7 @@
 #include "llvm/Support/KnownBits.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
+
 using namespace llvm;
 
 #define DEBUG_TYPE "wasm-isel"
@@ -48,32 +49,11 @@ class WebAssemblyDAGToDAGISel final : public SelectionDAGISel {
     return "WebAssembly Instruction Selection";
   }
 
-  void checkForInvalidNodes(const Function &F) {
-    // This function will check for uses of ptrtoint on reference types and
-    // report a fatal error if these are found.
-    for (const BasicBlock &BB : F) {
-      for (const Instruction &I : BB) {
-        if (const PtrToIntInst *PTI = dyn_cast<const PtrToIntInst>(&I)) {
-          const Value *V = PTI->getPointerOperand();
-          if (WebAssemblyTargetLowering::isFuncrefType(V->getType()) ||
-              WebAssemblyTargetLowering::isExternrefType(V->getType()))
-            report_fatal_error("ptrtoint not allowed on reference types");
-        } else if (const IntToPtrInst *ITP = dyn_cast<const IntToPtrInst>(&I)) {
-          if (WebAssemblyTargetLowering::isFuncrefType(ITP->getDestTy()) ||
-              WebAssemblyTargetLowering::isExternrefType(ITP->getDestTy()))
-            report_fatal_error("inttoptr not allowed on reference types");
-        }
-      }
-    }
-  }
-
   bool runOnMachineFunction(MachineFunction &MF) override {
     LLVM_DEBUG(dbgs() << "********** ISelDAGToDAG **********\n"
                          "********** Function: "
                       << MF.getName() << '\n');
 
-    checkForInvalidNodes(MF.getFunction());
-
     Subtarget = &MF.getSubtarget<WebAssemblySubtarget>();
 
     return SelectionDAGISel::runOnMachineFunction(MF);

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerRefTypesIntPtrConv.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerRefTypesIntPtrConv.cpp
new file mode 100644
index 0000000000000..e81e5e0e9b30f
--- /dev/null
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerRefTypesIntPtrConv.cpp
@@ -0,0 +1,90 @@
+//=== WebAssemblyLowerRefTypesIntPtrConv.cpp -
+//                     Lower IntToPtr and PtrToInt on Reference Types   ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Lowers IntToPtr and PtrToInt instructions on reference types to
+/// Trap instructions since they have been allowed to operate
+/// on non-integral pointers.
+///
+//===----------------------------------------------------------------------===//
+
+#include "WebAssembly.h"
+#include "WebAssemblySubtarget.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/Pass.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "wasm-lower-reftypes-intptr-conv"
+
+namespace {
+class WebAssemblyLowerRefTypesIntPtrConv final : public FunctionPass {
+  StringRef getPassName() const override {
+    return "WebAssembly Lower RefTypes Int-Ptr Conversions";
+  }
+
+  static bool isRefType(Type *T);
+
+  bool runOnFunction(Function &MF) override;
+
+public:
+  static char ID; // Pass identification
+  WebAssemblyLowerRefTypesIntPtrConv() : FunctionPass(ID) {}
+};
+} // end anonymous namespace
+
+char WebAssemblyLowerRefTypesIntPtrConv::ID = 0;
+INITIALIZE_PASS(WebAssemblyLowerRefTypesIntPtrConv, DEBUG_TYPE,
+                "WebAssembly Lower RefTypes Int-Ptr Conversions", false, false)
+
+FunctionPass *llvm::createWebAssemblyLowerRefTypesIntPtrConv() {
+  return new WebAssemblyLowerRefTypesIntPtrConv();
+}
+
+bool WebAssemblyLowerRefTypesIntPtrConv::isRefType(Type *T) {
+  return WebAssemblyTargetLowering::isFuncrefType(T) ||
+         WebAssemblyTargetLowering::isExternrefType(T);
+}
+
+bool WebAssemblyLowerRefTypesIntPtrConv::runOnFunction(Function &F) {
+  LLVM_DEBUG(dbgs() << "********** Lower RefTypes IntPtr Convs **********\n"
+                       "********** Function: "
+                    << F.getName() << '\n');
+
+  // This function will check for uses of ptrtoint and inttoptr on reference
+  // types and replace them with a trap instruction.
+  //
+  // We replace the instruction by a trap instruction
+  // and its uses by null in the case of inttoptr and 0 in the
+  // case of ptrtoint.
+  std::set<Instruction *> worklist;
+
+  for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
+    PtrToIntInst *PTI = dyn_cast<PtrToIntInst>(&*I);
+    IntToPtrInst *ITP = dyn_cast<IntToPtrInst>(&*I);
+    if (!(PTI && isRefType(PTI->getPointerOperand()->getType())) &&
+        !(ITP && isRefType(ITP->getDestTy())))
+      continue;
+
+    UndefValue *U = UndefValue::get(I->getType());
+    I->replaceAllUsesWith(U);
+
+    Function *TrapIntrin =
+        Intrinsic::getDeclaration(F.getParent(), Intrinsic::debugtrap);
+    CallInst::Create(TrapIntrin, {}, "", &*I);
+
+    worklist.insert(&*I);
+  }
+
+  // erase each instruction replaced by trap
+  for (Instruction *I : worklist)
+    I->eraseFromParent();
+
+  return !worklist.empty();
+}

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index 746a7599c58ce..10497e45b4bf9 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -332,6 +332,7 @@ class WebAssemblyPassConfig final : public TargetPassConfig {
   void addPostRegAlloc() override;
   bool addGCPasses() override { return false; }
   void addPreEmitPass() override;
+  bool addPreISel() override;
 
   // No reg alloc
   bool addRegAssignAndRewriteFast() override { return false; }
@@ -518,6 +519,12 @@ void WebAssemblyPassConfig::addPreEmitPass() {
   addPass(createWebAssemblyMCLowerPrePass());
 }
 
+bool WebAssemblyPassConfig::addPreISel() {
+  TargetPassConfig::addPreISel();
+  addPass(createWebAssemblyLowerRefTypesIntPtrConv());
+  return false;
+}
+
 yaml::MachineFunctionInfo *
 WebAssemblyTargetMachine::createDefaultFuncInfoYAML() const {
   return new yaml::WebAssemblyFunctionInfo();

diff  --git a/llvm/test/CodeGen/WebAssembly/externref-inttoptr.ll b/llvm/test/CodeGen/WebAssembly/externref-inttoptr.ll
index cc106b5dee32e..252dbfe12040d 100644
--- a/llvm/test/CodeGen/WebAssembly/externref-inttoptr.ll
+++ b/llvm/test/CodeGen/WebAssembly/externref-inttoptr.ll
@@ -1,4 +1,4 @@
-; RUN: not --crash llc --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types < %s 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
+; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types 2>&1 | FileCheck %s
 
 %extern = type opaque
 %externref = type %extern addrspace(10)*
@@ -8,4 +8,10 @@ define %externref @int_to_externref(i32 %i) {
   ret %externref %ref
 }
 
-; CHECK-ERROR: LLVM ERROR: inttoptr not allowed on reference types
+
+; CHECK-LABEL: int_to_externref:
+; CHECK-NEXT: .functype       int_to_externref (i32) -> (externref)
+; CHECK-NEXT: .local externref
+; CHECK-NEXT: unreachable
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: end_function

diff  --git a/llvm/test/CodeGen/WebAssembly/externref-ptrtoint.ll b/llvm/test/CodeGen/WebAssembly/externref-ptrtoint.ll
index 8aea1506a903e..648bfc510a549 100644
--- a/llvm/test/CodeGen/WebAssembly/externref-ptrtoint.ll
+++ b/llvm/test/CodeGen/WebAssembly/externref-ptrtoint.ll
@@ -1,4 +1,4 @@
-; RUN: not --crash llc --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types < %s 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
+; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types 2>&1 | FileCheck %s
 
 %extern = type opaque
 %externref = type %extern addrspace(10)*
@@ -8,4 +8,9 @@ define i32 @externref_to_int(%externref %ref) {
   ret i32 %i
 }
 
-; CHECK-ERROR: LLVM ERROR: ptrtoint not allowed on reference types
+; CHECK-LABEL: externref_to_int:
+; CHECK-NEXT: .functype       externref_to_int (externref) -> (i32)
+; CHECK-NEXT: .local i32
+; CHECK-NEXT: unreachable
+; CHECK-NEXT: local.get 1
+; CHECK-NEXT: end_function

diff  --git a/llvm/utils/gn/secondary/llvm/lib/Target/WebAssembly/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Target/WebAssembly/BUILD.gn
index 39cfa79e15663..4710c08d75b83 100644
--- a/llvm/utils/gn/secondary/llvm/lib/Target/WebAssembly/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/Target/WebAssembly/BUILD.gn
@@ -52,6 +52,7 @@ static_library("LLVMWebAssemblyCodeGen") {
     "WebAssemblyLowerBrUnless.cpp",
     "WebAssemblyLowerEmscriptenEHSjLj.cpp",
     "WebAssemblyLowerGlobalDtors.cpp",
+    "WebAssemblyLowerRefTypesIntPtrConv.cpp",
     "WebAssemblyMCInstLower.cpp",
     "WebAssemblyMCLowerPrePass.cpp",
     "WebAssemblyMachineFunctionInfo.cpp",


        


More information about the llvm-commits mailing list