[llvm] ce1c59d - [WebAssembly] Add new pass to lower int/ptr conversions of reftypes
Paulo Matos via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 2 10:40:32 PDT 2021
Author: Paulo Matos
Date: 2021-08-02T19:40:00+02:00
New Revision: ce1c59dea6d01e8ec3d4cb911438254283e4646c
URL: https://github.com/llvm/llvm-project/commit/ce1c59dea6d01e8ec3d4cb911438254283e4646c
DIFF: https://github.com/llvm/llvm-project/commit/ce1c59dea6d01e8ec3d4cb911438254283e4646c.diff
LOG: [WebAssembly] Add new pass to lower int/ptr conversions of reftypes
Add new pass LowerRefTypesIntPtrConv to generate trap
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..55fdbb4b2719f
--- /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::trap);
+ 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