From 31adeded0d1767e1ce43fbfcba5fe72c4e34121d Mon Sep 17 00:00:00 2001 From: Paulo Matos Date: Tue, 7 Nov 2023 08:28:36 +0100 Subject: [PATCH 1/4] [WebAssembly] Refactor Wasm Reference Types as TargetExtType Originally reference types were designed as pointers to different address spaces. More recently TargetExtType were added to LLVM IR making it easier to represent reference types. This refactoring gets rid of wasm reftypes as pointers and just uses target extension types to represent them. --- .../test/CodeGen/WebAssembly/builtins-table.c | 16 ++-- .../test/CodeGen/WebAssembly/wasm-externref.c | 8 +- clang/test/CodeGen/builtins-wasm.c | 2 +- llvm/include/llvm/IR/Intrinsics.h | 1 + llvm/include/llvm/IR/Type.h | 2 + llvm/lib/CodeGen/ValueTypes.cpp | 2 + llvm/lib/IR/Function.cpp | 8 +- llvm/lib/IR/Type.cpp | 7 +- llvm/lib/Target/WebAssembly/CMakeLists.txt | 1 - .../WebAssembly/Utils/WasmAddressSpaces.h | 2 - .../Utils/WebAssemblyTypeUtilities.h | 5 +- llvm/lib/Target/WebAssembly/WebAssembly.h | 2 - .../WebAssembly/WebAssemblyISelLowering.cpp | 4 - .../WebAssemblyLowerRefTypesIntPtrConv.cpp | 86 ------------------- .../WebAssembly/WebAssemblyTargetMachine.cpp | 2 - .../WebAssembly/externref-globalget.ll | 2 +- .../WebAssembly/externref-globalset.ll | 2 +- .../CodeGen/WebAssembly/externref-inttoptr.ll | 12 +-- .../CodeGen/WebAssembly/externref-ptrtoint.ll | 11 +-- .../CodeGen/WebAssembly/externref-tableget.ll | 2 +- .../CodeGen/WebAssembly/externref-tableset.ll | 2 +- .../WebAssembly/externref-unsized-load.ll | 4 +- .../WebAssembly/externref-unsized-store.ll | 4 +- llvm/test/CodeGen/WebAssembly/ref-null.ll | 2 +- llvm/test/CodeGen/WebAssembly/table-copy.ll | 2 +- llvm/test/CodeGen/WebAssembly/table-fill.ll | 2 +- llvm/test/CodeGen/WebAssembly/table-grow.ll | 2 +- llvm/test/CodeGen/WebAssembly/table-size.ll | 2 +- llvm/test/CodeGen/WebAssembly/table-types.ll | 2 +- .../llvm/lib/Target/WebAssembly/BUILD.gn | 1 - 30 files changed, 51 insertions(+), 149 deletions(-) delete mode 100644 llvm/lib/Target/WebAssembly/WebAssemblyLowerRefTypesIntPtrConv.cpp diff --git a/clang/test/CodeGen/WebAssembly/builtins-table.c b/clang/test/CodeGen/WebAssembly/builtins-table.c index 74bb2442fe552..eeed335855e40 100644 --- a/clang/test/CodeGen/WebAssembly/builtins-table.c +++ b/clang/test/CodeGen/WebAssembly/builtins-table.c @@ -7,17 +7,17 @@ static __externref_t table[0]; // CHECK-LABEL: define {{[^@]+}}@test_builtin_wasm_table_get // CHECK-SAME: (i32 noundef [[INDEX:%.*]]) #[[ATTR0:[0-9]+]] { // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = call ptr addrspace(10) @llvm.wasm.table.get.externref(ptr addrspace(1) @table, i32 [[INDEX]]) -// CHECK-NEXT: ret ptr addrspace(10) [[TMP0]] +// CHECK-NEXT: [[TMP0:%.*]] = call target("wasm.externref") @llvm.wasm.table.get.externref(ptr addrspace(1) @table, i32 [[INDEX]]) +// CHECK-NEXT: ret target("wasm.externref") [[TMP0]] // __externref_t test_builtin_wasm_table_get(int index) { return __builtin_wasm_table_get(table, index); } // CHECK-LABEL: define {{[^@]+}}@test_builtin_wasm_table_set -// CHECK-SAME: (i32 noundef [[INDEX:%.*]], ptr addrspace(10) [[REF:%.*]]) #[[ATTR0]] { +// CHECK-SAME: (i32 noundef [[INDEX:%.*]], target("wasm.externref") [[REF:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: -// CHECK-NEXT: call void @llvm.wasm.table.set.externref(ptr addrspace(1) @table, i32 [[INDEX]], ptr addrspace(10) [[REF]]) +// CHECK-NEXT: call void @llvm.wasm.table.set.externref(ptr addrspace(1) @table, i32 [[INDEX]], target("wasm.externref") [[REF]]) // CHECK-NEXT: ret void // void test_builtin_wasm_table_set(int index, __externref_t ref) { @@ -35,9 +35,9 @@ int test_builtin_wasm_table_size() { } // CHECK-LABEL: define {{[^@]+}}@test_builtin_wasm_table_grow -// CHECK-SAME: (ptr addrspace(10) [[REF:%.*]], i32 noundef [[NELEM:%.*]]) #[[ATTR0]] { +// CHECK-SAME: (target("wasm.externref") [[REF:%.*]], i32 noundef [[NELEM:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.wasm.table.grow.externref(ptr addrspace(1) @table, ptr addrspace(10) [[REF]], i32 [[NELEM]]) +// CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.wasm.table.grow.externref(ptr addrspace(1) @table, target("wasm.externref") [[REF]], i32 [[NELEM]]) // CHECK-NEXT: ret i32 [[TMP0]] // int test_builtin_wasm_table_grow(__externref_t ref, int nelem) { @@ -45,9 +45,9 @@ int test_builtin_wasm_table_grow(__externref_t ref, int nelem) { } // CHECK-LABEL: define {{[^@]+}}@test_builtin_wasm_table_fill -// CHECK-SAME: (i32 noundef [[INDEX:%.*]], ptr addrspace(10) [[REF:%.*]], i32 noundef [[NELEM:%.*]]) #[[ATTR0]] { +// CHECK-SAME: (i32 noundef [[INDEX:%.*]], target("wasm.externref") [[REF:%.*]], i32 noundef [[NELEM:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: -// CHECK-NEXT: call void @llvm.wasm.table.fill.externref(ptr addrspace(1) @table, i32 [[INDEX]], ptr addrspace(10) [[REF]], i32 [[NELEM]]) +// CHECK-NEXT: call void @llvm.wasm.table.fill.externref(ptr addrspace(1) @table, i32 [[INDEX]], target("wasm.externref") [[REF]], i32 [[NELEM]]) // CHECK-NEXT: ret void // void test_builtin_wasm_table_fill(int index, __externref_t ref, int nelem) { diff --git a/clang/test/CodeGen/WebAssembly/wasm-externref.c b/clang/test/CodeGen/WebAssembly/wasm-externref.c index 788438bb4a86a..d226c51b7fd4e 100644 --- a/clang/test/CodeGen/WebAssembly/wasm-externref.c +++ b/clang/test/CodeGen/WebAssembly/wasm-externref.c @@ -7,10 +7,10 @@ void helper(externref_t); // CHECK-LABEL: @handle( // CHECK-NEXT: entry: -// CHECK-NEXT: [[OBJ_ADDR:%.*]] = alloca ptr addrspace(10), align 1 -// CHECK-NEXT: store ptr addrspace(10) [[OBJ:%.*]], ptr [[OBJ_ADDR]], align 1 -// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(10), ptr [[OBJ_ADDR]], align 1 -// CHECK-NEXT: call void @helper(ptr addrspace(10) [[TMP0]]) +// CHECK-NEXT: [[OBJ_ADDR:%.*]] = alloca target("wasm.externref"), align 1 +// CHECK-NEXT: store target("wasm.externref") [[OBJ:%.*]], ptr [[OBJ_ADDR]], align 1 +// CHECK-NEXT: [[TMP0:%.*]] = load target("wasm.externref"), ptr [[OBJ_ADDR]], align 1 +// CHECK-NEXT: call void @helper(target("wasm.externref") [[TMP0]]) // CHECK-NEXT: ret void // void handle(externref_t obj) { diff --git a/clang/test/CodeGen/builtins-wasm.c b/clang/test/CodeGen/builtins-wasm.c index d486d12085f9f..135334c0cd0a1 100644 --- a/clang/test/CodeGen/builtins-wasm.c +++ b/clang/test/CodeGen/builtins-wasm.c @@ -804,6 +804,6 @@ f32x4 relaxed_dot_bf16x8_add_f32_f32x4(u16x8 a, u16x8 b, f32x4 c) { __externref_t externref_null() { return __builtin_wasm_ref_null_extern(); - // WEBASSEMBLY: tail call ptr addrspace(10) @llvm.wasm.ref.null.extern() + // WEBASSEMBLY: tail call target("wasm.externref") @llvm.wasm.ref.null.extern() // WEBASSEMBLY-NEXT: ret } diff --git a/llvm/include/llvm/IR/Intrinsics.h b/llvm/include/llvm/IR/Intrinsics.h index 0dfe9f029f9b1..0121717423a40 100644 --- a/llvm/include/llvm/IR/Intrinsics.h +++ b/llvm/include/llvm/IR/Intrinsics.h @@ -136,6 +136,7 @@ namespace Intrinsic { AMX, PPCQuad, AArch64Svcount, + WasmExternref, } Kind; union { diff --git a/llvm/include/llvm/IR/Type.h b/llvm/include/llvm/IR/Type.h index 1f0133c08e7d6..1fa31d5da83e3 100644 --- a/llvm/include/llvm/IR/Type.h +++ b/llvm/include/llvm/IR/Type.h @@ -305,11 +305,13 @@ class Type { getTypeID() == PointerTyID || getTypeID() == X86_MMXTyID || getTypeID() == X86_AMXTyID) return true; + // If it is not something that can have a size (e.g. a function or label), // it doesn't have a size. if (getTypeID() != StructTyID && getTypeID() != ArrayTyID && !isVectorTy() && getTypeID() != TargetExtTyID) return false; + // Otherwise we have to try harder to decide. return isSizedDerivedType(Visited); } diff --git a/llvm/lib/CodeGen/ValueTypes.cpp b/llvm/lib/CodeGen/ValueTypes.cpp index 2d16ff2dfb2fb..e9d6a14228b09 100644 --- a/llvm/lib/CodeGen/ValueTypes.cpp +++ b/llvm/lib/CodeGen/ValueTypes.cpp @@ -590,6 +590,8 @@ MVT MVT::getVT(Type *Ty, bool HandleUnknown){ TargetExtType *TargetExtTy = cast(Ty); if (TargetExtTy->getName() == "aarch64.svcount") return MVT(MVT::aarch64svcount); + else if(TargetExtTy->getName() == "wasm.externref") + return MVT(MVT::externref); else if (TargetExtTy->getName().starts_with("spirv.")) return MVT(MVT::spirvbuiltin); if (HandleUnknown) diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index 49e0c1c5883c2..ece0fb075fe74 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -1183,7 +1183,7 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef Infos, DecodeIITType(NextElt, Infos, Info, OutputTable); return; case IIT_EXTERNREF: - OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 10)); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::WasmExternref, 0)); return; case IIT_FUNCREF: OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 20)); @@ -1339,7 +1339,8 @@ static Type *DecodeFixedType(ArrayRef &Infos, case IITDescriptor::PPCQuad: return Type::getPPC_FP128Ty(Context); case IITDescriptor::AArch64Svcount: return TargetExtType::get(Context, "aarch64.svcount"); - + case IITDescriptor::WasmExternref: + return TargetExtType::get(Context, "wasm.externref"); case IITDescriptor::Integer: return IntegerType::get(Context, D.Integer_Width); case IITDescriptor::Vector: @@ -1500,6 +1501,9 @@ static bool matchIntrinsicType( case IITDescriptor::AArch64Svcount: return !isa(Ty) || cast(Ty)->getName() != "aarch64.svcount"; + case IITDescriptor::WasmExternref: + return !isa(Ty) || + cast(Ty)->getName() != "wasm.externref"; case IITDescriptor::Vector: { VectorType *VT = dyn_cast(Ty); return !VT || VT->getElementCount() != D.Vector_Width || diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp index 8a1bf9654fdc6..3bf06a24d8204 100644 --- a/llvm/lib/IR/Type.cpp +++ b/llvm/lib/IR/Type.cpp @@ -257,8 +257,7 @@ IntegerType *Type::getIntNTy(LLVMContext &C, unsigned N) { } Type *Type::getWasm_ExternrefTy(LLVMContext &C) { - // opaque pointer in addrspace(10) - static PointerType *Ty = PointerType::get(C, 10); + static TargetExtType *Ty = TargetExtType::get(C, "wasm.externref", {}, {}); return Ty; } @@ -840,6 +839,10 @@ static TargetTypeInfo getTargetTypeInfo(const TargetExtType *Ty) { return TargetTypeInfo(ScalableVectorType::get(Type::getInt1Ty(C), 16), TargetExtType::HasZeroInit); + // Opaque types in the WebAssembly name space. + if (Name == "wasm.externref") + return TargetTypeInfo(PointerType::getUnqual(C), TargetExtType::HasZeroInit, TargetExtType::CanBeGlobal); + return TargetTypeInfo(Type::getVoidTy(C)); } diff --git a/llvm/lib/Target/WebAssembly/CMakeLists.txt b/llvm/lib/Target/WebAssembly/CMakeLists.txt index bb2ccea5c1459..9cd1af1483272 100644 --- a/llvm/lib/Target/WebAssembly/CMakeLists.txt +++ b/llvm/lib/Target/WebAssembly/CMakeLists.txt @@ -35,7 +35,6 @@ add_llvm_target(WebAssemblyCodeGen WebAssemblyInstrInfo.cpp WebAssemblyLowerBrUnless.cpp WebAssemblyLowerEmscriptenEHSjLj.cpp - WebAssemblyLowerRefTypesIntPtrConv.cpp WebAssemblyMachineFunctionInfo.cpp WebAssemblyMCInstLower.cpp WebAssemblyMCLowerPrePass.cpp diff --git a/llvm/lib/Target/WebAssembly/Utils/WasmAddressSpaces.h b/llvm/lib/Target/WebAssembly/Utils/WasmAddressSpaces.h index 2239badca69c3..9603b338e90b2 100644 --- a/llvm/lib/Target/WebAssembly/Utils/WasmAddressSpaces.h +++ b/llvm/lib/Target/WebAssembly/Utils/WasmAddressSpaces.h @@ -25,8 +25,6 @@ enum WasmAddressSpace : unsigned { // to these pointers are lowered to global.get / global.set or local.get / // local.set, as appropriate. WASM_ADDRESS_SPACE_VAR = 1, - // A non-integral address space for externref values - WASM_ADDRESS_SPACE_EXTERNREF = 10, // A non-integral address space for funcref values WASM_ADDRESS_SPACE_FUNCREF = 20, }; diff --git a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h index a8860477a2472..670cf46ba30b0 100644 --- a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h +++ b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h @@ -28,9 +28,8 @@ namespace WebAssembly { /// Return true if this is a WebAssembly Externref Type. inline bool isWebAssemblyExternrefType(const Type *Ty) { - return Ty->isPointerTy() && - Ty->getPointerAddressSpace() == - WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_EXTERNREF; + const TargetExtType *TargetTy = dyn_cast(Ty); + return TargetTy && TargetTy->getName() == "wasm.externref"; } /// Return true if this is a WebAssembly Funcref Type. diff --git a/llvm/lib/Target/WebAssembly/WebAssembly.h b/llvm/lib/Target/WebAssembly/WebAssembly.h index 91765ad117bdb..4a1fec52ce7a6 100644 --- a/llvm/lib/Target/WebAssembly/WebAssembly.h +++ b/llvm/lib/Target/WebAssembly/WebAssembly.h @@ -29,7 +29,6 @@ ModulePass *createWebAssemblyLowerEmscriptenEHSjLj(); ModulePass *createWebAssemblyAddMissingPrototypes(); ModulePass *createWebAssemblyFixFunctionBitcasts(); FunctionPass *createWebAssemblyOptimizeReturned(); -FunctionPass *createWebAssemblyLowerRefTypesIntPtrConv(); // ISel and immediate followup passes. FunctionPass *createWebAssemblyISelDag(WebAssemblyTargetMachine &TM, @@ -72,7 +71,6 @@ void initializeWebAssemblyFixIrreducibleControlFlowPass(PassRegistry &); void initializeWebAssemblyLateEHPreparePass(PassRegistry &); void initializeWebAssemblyLowerBrUnlessPass(PassRegistry &); void initializeWebAssemblyLowerEmscriptenEHSjLjPass(PassRegistry &); -void initializeWebAssemblyLowerRefTypesIntPtrConvPass(PassRegistry &); void initializeWebAssemblyMCLowerPrePassPass(PassRegistry &); void initializeWebAssemblyMemIntrinsicResultsPass(PassRegistry &); void initializeWebAssemblyNullifyDebugValueListsPass(PassRegistry &); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index 4bcf89690505e..ab40061807e55 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -364,8 +364,6 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering( MVT WebAssemblyTargetLowering::getPointerTy(const DataLayout &DL, uint32_t AS) const { - if (AS == WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_EXTERNREF) - return MVT::externref; if (AS == WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF) return MVT::funcref; return TargetLowering::getPointerTy(DL, AS); @@ -373,8 +371,6 @@ MVT WebAssemblyTargetLowering::getPointerTy(const DataLayout &DL, MVT WebAssemblyTargetLowering::getPointerMemTy(const DataLayout &DL, uint32_t AS) const { - if (AS == WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_EXTERNREF) - return MVT::externref; if (AS == WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF) return MVT::funcref; return TargetLowering::getPointerMemTy(DL, AS); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerRefTypesIntPtrConv.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerRefTypesIntPtrConv.cpp deleted file mode 100644 index e0a2192112285..0000000000000 --- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerRefTypesIntPtrConv.cpp +++ /dev/null @@ -1,86 +0,0 @@ -//=== 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 "Utils/WebAssemblyTypeUtilities.h" -#include "WebAssembly.h" -#include "WebAssemblySubtarget.h" -#include "llvm/IR/InstIterator.h" -#include "llvm/Pass.h" -#include - -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"; - } - - 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::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 worklist; - - for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { - PtrToIntInst *PTI = dyn_cast(&*I); - IntToPtrInst *ITP = dyn_cast(&*I); - if (!(PTI && WebAssembly::isWebAssemblyReferenceType( - PTI->getPointerOperand()->getType())) && - !(ITP && WebAssembly::isWebAssemblyReferenceType(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 2db1b6493cc47..df71b9828142a 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp @@ -87,7 +87,6 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeWebAssemblyTarget() { initializeWebAssemblyDebugFixupPass(PR); initializeWebAssemblyPeepholePass(PR); initializeWebAssemblyMCLowerPrePassPass(PR); - initializeWebAssemblyLowerRefTypesIntPtrConvPass(PR); initializeWebAssemblyFixBrTableDefaultsPass(PR); initializeWebAssemblyDAGToDAGISelPass(PR); } @@ -609,7 +608,6 @@ void WebAssemblyPassConfig::addPreEmitPass() { bool WebAssemblyPassConfig::addPreISel() { TargetPassConfig::addPreISel(); - addPass(createWebAssemblyLowerRefTypesIntPtrConv()); return false; } diff --git a/llvm/test/CodeGen/WebAssembly/externref-globalget.ll b/llvm/test/CodeGen/WebAssembly/externref-globalget.ll index cdf98c42439f2..9ee98150a66f3 100644 --- a/llvm/test/CodeGen/WebAssembly/externref-globalget.ll +++ b/llvm/test/CodeGen/WebAssembly/externref-globalget.ll @@ -1,6 +1,6 @@ ; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types | FileCheck %s -%externref = type ptr addrspace(10) ;; addrspace 10 is nonintegral +%externref = type target("wasm.externref") ;; addrspace 10 is nonintegral @externref_global = local_unnamed_addr addrspace(1) global %externref undef diff --git a/llvm/test/CodeGen/WebAssembly/externref-globalset.ll b/llvm/test/CodeGen/WebAssembly/externref-globalset.ll index 5bfd673e89fa1..c5f9fe1fff8bf 100644 --- a/llvm/test/CodeGen/WebAssembly/externref-globalset.ll +++ b/llvm/test/CodeGen/WebAssembly/externref-globalset.ll @@ -1,6 +1,6 @@ ; RUN: llc --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types < %s | FileCheck %s -%externref = type ptr addrspace(10) ;; addrspace 10 is nonintegral +%externref = type target("wasm.externref") ;; addrspace 10 is nonintegral @externref_global = local_unnamed_addr addrspace(1) global %externref undef diff --git a/llvm/test/CodeGen/WebAssembly/externref-inttoptr.ll b/llvm/test/CodeGen/WebAssembly/externref-inttoptr.ll index 64f955b6ed0f0..bdf04f73c54a7 100644 --- a/llvm/test/CodeGen/WebAssembly/externref-inttoptr.ll +++ b/llvm/test/CodeGen/WebAssembly/externref-inttoptr.ll @@ -1,16 +1,10 @@ -; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types 2>&1 | FileCheck %s +; RUN: not llc --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types < %s 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR -%externref = type ptr addrspace(10) +%externref = type target("wasm.externref") define %externref @int_to_externref(i32 %i) { %ref = inttoptr i32 %i to %externref ret %externref %ref } - -; 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 +# CHECK-ERROR: error: invalid cast opcode for cast from 'i32' to 'target("wasm.externref")' diff --git a/llvm/test/CodeGen/WebAssembly/externref-ptrtoint.ll b/llvm/test/CodeGen/WebAssembly/externref-ptrtoint.ll index 22558796f0624..f3cfe31445b60 100644 --- a/llvm/test/CodeGen/WebAssembly/externref-ptrtoint.ll +++ b/llvm/test/CodeGen/WebAssembly/externref-ptrtoint.ll @@ -1,15 +1,10 @@ -; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types 2>&1 | FileCheck %s +; RUN: not llc --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types < %s 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR -%externref = type ptr addrspace(10) +%externref = type target("wasm.externref") define i32 @externref_to_int(%externref %ref) { %i = ptrtoint %externref %ref to i32 ret i32 %i } -; 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 +# CHECK-ERROR: error: invalid cast opcode for cast from 'target("wasm.externref")' to 'i32' diff --git a/llvm/test/CodeGen/WebAssembly/externref-tableget.ll b/llvm/test/CodeGen/WebAssembly/externref-tableget.ll index d9ae7c8f6c9b1..1e36ea7efa164 100644 --- a/llvm/test/CodeGen/WebAssembly/externref-tableget.ll +++ b/llvm/test/CodeGen/WebAssembly/externref-tableget.ll @@ -1,6 +1,6 @@ ; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types | FileCheck %s -%externref = type ptr addrspace(10) ;; addrspace 10 is nonintegral +%externref = type target("wasm.externref") ;; addrspace 10 is nonintegral @externref_table = local_unnamed_addr addrspace(1) global [0 x %externref] undef diff --git a/llvm/test/CodeGen/WebAssembly/externref-tableset.ll b/llvm/test/CodeGen/WebAssembly/externref-tableset.ll index 37c663869428e..4ce77df9bfdd8 100644 --- a/llvm/test/CodeGen/WebAssembly/externref-tableset.ll +++ b/llvm/test/CodeGen/WebAssembly/externref-tableset.ll @@ -1,6 +1,6 @@ ; RUN: llc --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types < %s | FileCheck %s -%externref = type ptr addrspace(10) ;; addrspace 10 is nonintegral +%externref = type target("wasm.externref") ;; addrspace 10 is nonintegral @externref_table = local_unnamed_addr addrspace(1) global [0 x %externref] undef diff --git a/llvm/test/CodeGen/WebAssembly/externref-unsized-load.ll b/llvm/test/CodeGen/WebAssembly/externref-unsized-load.ll index 945045d902ef5..98a0e801af387 100644 --- a/llvm/test/CodeGen/WebAssembly/externref-unsized-load.ll +++ b/llvm/test/CodeGen/WebAssembly/externref-unsized-load.ll @@ -1,10 +1,10 @@ ; RUN: not llc --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types < %s 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR -%externref = type ptr addrspace(10) +%externref = type target("wasm.externref") define void @load_extern(%externref %ref) { %e = load %extern, %externref %ref ret void } -; CHECK-ERROR: error: loading unsized types is not allowed +; CHECK-ERROR: error: load operand must be a pointer to a first class type diff --git a/llvm/test/CodeGen/WebAssembly/externref-unsized-store.ll b/llvm/test/CodeGen/WebAssembly/externref-unsized-store.ll index ca01f69a08ad2..933fb61e8577f 100644 --- a/llvm/test/CodeGen/WebAssembly/externref-unsized-store.ll +++ b/llvm/test/CodeGen/WebAssembly/externref-unsized-store.ll @@ -1,10 +1,10 @@ ; RUN: not llc --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types < %s 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR -%externref = type ptr addrspace(10) +%externref = type target("wasm.externref") define void @store_extern(%externref %ref) { store %extern undef, %externref %ref ret void } -; CHECK-ERROR: error: storing unsized types is not allowed +; CHECK-ERROR: error: store operand must be a pointer diff --git a/llvm/test/CodeGen/WebAssembly/ref-null.ll b/llvm/test/CodeGen/WebAssembly/ref-null.ll index af6ddfd8e0814..f4aa31577cdaf 100644 --- a/llvm/test/CodeGen/WebAssembly/ref-null.ll +++ b/llvm/test/CodeGen/WebAssembly/ref-null.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc --mtriple=wasm32-unknown-unknown -mattr=+reference-types < %s | FileCheck %s -%externref = type ptr addrspace(10) ;; addrspace 10 is nonintegral +%externref = type target("wasm.externref") %funcref = type ptr addrspace(20) ;; addrspace 20 is nonintegral declare %externref @llvm.wasm.ref.null.extern() nounwind diff --git a/llvm/test/CodeGen/WebAssembly/table-copy.ll b/llvm/test/CodeGen/WebAssembly/table-copy.ll index 5c0647ada4ab0..6740d4863239c 100644 --- a/llvm/test/CodeGen/WebAssembly/table-copy.ll +++ b/llvm/test/CodeGen/WebAssembly/table-copy.ll @@ -1,6 +1,6 @@ ; RUN: llc --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types < %s | FileCheck %s -%externref = type ptr addrspace(10) ;; addrspace 10 is nonintegral +%externref = type target("wasm.externref") ;; addrspace 10 is nonintegral @externref_table1 = local_unnamed_addr addrspace(1) global [0 x %externref] undef @externref_table2 = local_unnamed_addr addrspace(1) global [0 x %externref] undef diff --git a/llvm/test/CodeGen/WebAssembly/table-fill.ll b/llvm/test/CodeGen/WebAssembly/table-fill.ll index 0b78124f038b1..13a3fc28a8ae9 100644 --- a/llvm/test/CodeGen/WebAssembly/table-fill.ll +++ b/llvm/test/CodeGen/WebAssembly/table-fill.ll @@ -1,6 +1,6 @@ ; RUN: llc --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types < %s | FileCheck %s -%externref = type ptr addrspace(10) ;; addrspace 10 is nonintegral +%externref = type target("wasm.externref") ;; addrspace 10 is nonintegral @externref_table = local_unnamed_addr addrspace(1) global [0 x %externref] undef diff --git a/llvm/test/CodeGen/WebAssembly/table-grow.ll b/llvm/test/CodeGen/WebAssembly/table-grow.ll index 614c3400a782b..2b5801ea2fa17 100644 --- a/llvm/test/CodeGen/WebAssembly/table-grow.ll +++ b/llvm/test/CodeGen/WebAssembly/table-grow.ll @@ -1,6 +1,6 @@ ; RUN: llc --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types < %s | FileCheck %s -%externref = type ptr addrspace(10) ;; addrspace 10 is nonintegral +%externref = type target("wasm.externref") @externref_table = local_unnamed_addr addrspace(1) global [0 x %externref] undef diff --git a/llvm/test/CodeGen/WebAssembly/table-size.ll b/llvm/test/CodeGen/WebAssembly/table-size.ll index 42cd2e8a909d7..2b8d0185bb049 100644 --- a/llvm/test/CodeGen/WebAssembly/table-size.ll +++ b/llvm/test/CodeGen/WebAssembly/table-size.ll @@ -1,6 +1,6 @@ ; RUN: llc --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types < %s | FileCheck %s -%externref = type ptr addrspace(10) ;; addrspace 10 is nonintegral +%externref = type target("wasm.externref") @externref_table = local_unnamed_addr addrspace(1) global [0 x %externref] undef diff --git a/llvm/test/CodeGen/WebAssembly/table-types.ll b/llvm/test/CodeGen/WebAssembly/table-types.ll index cb5e54e2af230..f0cd7e30b5c1f 100644 --- a/llvm/test/CodeGen/WebAssembly/table-types.ll +++ b/llvm/test/CodeGen/WebAssembly/table-types.ll @@ -1,6 +1,6 @@ ; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types | FileCheck %s -%externref = type ptr addrspace(10) ;; addrspace 10 is nonintegral +%externref = type target("wasm.externref") %funcref = type ptr addrspace(20) ;; addrspace 20 is nonintegral ; CHECK: .tabletype eref_table, externref 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 949b3b2147405..e08a7603378cf 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Target/WebAssembly/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Target/WebAssembly/BUILD.gn @@ -52,7 +52,6 @@ static_library("LLVMWebAssemblyCodeGen") { "WebAssemblyLateEHPrepare.cpp", "WebAssemblyLowerBrUnless.cpp", "WebAssemblyLowerEmscriptenEHSjLj.cpp", - "WebAssemblyLowerRefTypesIntPtrConv.cpp", "WebAssemblyMCInstLower.cpp", "WebAssemblyMCLowerPrePass.cpp", "WebAssemblyMachineFunctionInfo.cpp", From 41bb0d7580bc6d60c4da040034cc98179e9e5ff5 Mon Sep 17 00:00:00 2001 From: Paulo Matos Date: Fri, 10 Nov 2023 10:29:53 +0100 Subject: [PATCH 2/4] Funcref impl - still missing calls --- llvm/include/llvm/IR/Intrinsics.h | 1 + llvm/include/llvm/IR/Type.h | 2 -- llvm/lib/CodeGen/ValueTypes.cpp | 2 ++ llvm/lib/IR/Function.cpp | 7 ++++++- llvm/lib/IR/Type.cpp | 5 ++--- .../WebAssembly/Utils/WasmAddressSpaces.h | 4 +--- .../Utils/WebAssemblyTypeUtilities.h | 5 ++--- .../WebAssembly/WebAssemblyISelLowering.cpp | 18 +----------------- .../WebAssembly/WebAssemblyISelLowering.h | 3 --- llvm/test/CodeGen/WebAssembly/funcref-call.ll | 6 +++--- .../CodeGen/WebAssembly/funcref-globalget.ll | 2 +- .../CodeGen/WebAssembly/funcref-globalset.ll | 2 +- .../CodeGen/WebAssembly/funcref-table_call.ll | 2 +- .../CodeGen/WebAssembly/funcref-tableget.ll | 2 +- .../CodeGen/WebAssembly/funcref-tableset.ll | 2 +- llvm/test/CodeGen/WebAssembly/ref-null.ll | 2 +- llvm/test/CodeGen/WebAssembly/table-types.ll | 2 +- 17 files changed, 25 insertions(+), 42 deletions(-) diff --git a/llvm/include/llvm/IR/Intrinsics.h b/llvm/include/llvm/IR/Intrinsics.h index 0121717423a40..15802c366a116 100644 --- a/llvm/include/llvm/IR/Intrinsics.h +++ b/llvm/include/llvm/IR/Intrinsics.h @@ -137,6 +137,7 @@ namespace Intrinsic { PPCQuad, AArch64Svcount, WasmExternref, + WasmFuncref, } Kind; union { diff --git a/llvm/include/llvm/IR/Type.h b/llvm/include/llvm/IR/Type.h index 1fa31d5da83e3..1f0133c08e7d6 100644 --- a/llvm/include/llvm/IR/Type.h +++ b/llvm/include/llvm/IR/Type.h @@ -305,13 +305,11 @@ class Type { getTypeID() == PointerTyID || getTypeID() == X86_MMXTyID || getTypeID() == X86_AMXTyID) return true; - // If it is not something that can have a size (e.g. a function or label), // it doesn't have a size. if (getTypeID() != StructTyID && getTypeID() != ArrayTyID && !isVectorTy() && getTypeID() != TargetExtTyID) return false; - // Otherwise we have to try harder to decide. return isSizedDerivedType(Visited); } diff --git a/llvm/lib/CodeGen/ValueTypes.cpp b/llvm/lib/CodeGen/ValueTypes.cpp index e9d6a14228b09..fc77eb65d47a5 100644 --- a/llvm/lib/CodeGen/ValueTypes.cpp +++ b/llvm/lib/CodeGen/ValueTypes.cpp @@ -592,6 +592,8 @@ MVT MVT::getVT(Type *Ty, bool HandleUnknown){ return MVT(MVT::aarch64svcount); else if(TargetExtTy->getName() == "wasm.externref") return MVT(MVT::externref); + else if(TargetExtTy->getName() == "wasm.funcref") + return MVT(MVT::funcref); else if (TargetExtTy->getName().starts_with("spirv.")) return MVT(MVT::spirvbuiltin); if (HandleUnknown) diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index ece0fb075fe74..679bf97bbe007 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -1186,7 +1186,7 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef Infos, OutputTable.push_back(IITDescriptor::get(IITDescriptor::WasmExternref, 0)); return; case IIT_FUNCREF: - OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 20)); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::WasmFuncref, 0)); return; case IIT_PTR: OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 0)); @@ -1341,6 +1341,8 @@ static Type *DecodeFixedType(ArrayRef &Infos, return TargetExtType::get(Context, "aarch64.svcount"); case IITDescriptor::WasmExternref: return TargetExtType::get(Context, "wasm.externref"); + case IITDescriptor::WasmFuncref: + return TargetExtType::get(Context, "wasm.funcref"); case IITDescriptor::Integer: return IntegerType::get(Context, D.Integer_Width); case IITDescriptor::Vector: @@ -1504,6 +1506,9 @@ static bool matchIntrinsicType( case IITDescriptor::WasmExternref: return !isa(Ty) || cast(Ty)->getName() != "wasm.externref"; + case IITDescriptor::WasmFuncref: + return !isa(Ty) || + cast(Ty)->getName() != "wasm.funcref"; case IITDescriptor::Vector: { VectorType *VT = dyn_cast(Ty); return !VT || VT->getElementCount() != D.Vector_Width || diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp index 3bf06a24d8204..127dc5b9147c9 100644 --- a/llvm/lib/IR/Type.cpp +++ b/llvm/lib/IR/Type.cpp @@ -262,8 +262,7 @@ Type *Type::getWasm_ExternrefTy(LLVMContext &C) { } Type *Type::getWasm_FuncrefTy(LLVMContext &C) { - // opaque pointer in addrspace(20) - static PointerType *Ty = PointerType::get(C, 20); + static TargetExtType *Ty = TargetExtType::get(C, "wasm.funcref", {}, {}); return Ty; } @@ -840,7 +839,7 @@ static TargetTypeInfo getTargetTypeInfo(const TargetExtType *Ty) { TargetExtType::HasZeroInit); // Opaque types in the WebAssembly name space. - if (Name == "wasm.externref") + if (Name.startswith("wasm.")) return TargetTypeInfo(PointerType::getUnqual(C), TargetExtType::HasZeroInit, TargetExtType::CanBeGlobal); return TargetTypeInfo(Type::getVoidTy(C)); diff --git a/llvm/lib/Target/WebAssembly/Utils/WasmAddressSpaces.h b/llvm/lib/Target/WebAssembly/Utils/WasmAddressSpaces.h index 9603b338e90b2..d2ab2c0f9e777 100644 --- a/llvm/lib/Target/WebAssembly/Utils/WasmAddressSpaces.h +++ b/llvm/lib/Target/WebAssembly/Utils/WasmAddressSpaces.h @@ -24,9 +24,7 @@ enum WasmAddressSpace : unsigned { // linear memory: WebAssembly globals or WebAssembly locals. Loads and stores // to these pointers are lowered to global.get / global.set or local.get / // local.set, as appropriate. - WASM_ADDRESS_SPACE_VAR = 1, - // A non-integral address space for funcref values - WASM_ADDRESS_SPACE_FUNCREF = 20, + WASM_ADDRESS_SPACE_VAR = 1 }; inline bool isDefaultAddressSpace(unsigned AS) { diff --git a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h index 670cf46ba30b0..768e883d2aba6 100644 --- a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h +++ b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h @@ -34,9 +34,8 @@ inline bool isWebAssemblyExternrefType(const Type *Ty) { /// Return true if this is a WebAssembly Funcref Type. inline bool isWebAssemblyFuncrefType(const Type *Ty) { - return Ty->isPointerTy() && - Ty->getPointerAddressSpace() == - WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF; + const TargetExtType *TargetTy = dyn_cast(Ty); + return TargetTy && TargetTy->getName() == "wasm.funcref"; } /// Return true if this is a WebAssembly Reference Type. diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index ab40061807e55..35d7d431bdf8e 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -362,20 +362,6 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering( setMinimumJumpTableEntries(2); } -MVT WebAssemblyTargetLowering::getPointerTy(const DataLayout &DL, - uint32_t AS) const { - if (AS == WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF) - return MVT::funcref; - return TargetLowering::getPointerTy(DL, AS); -} - -MVT WebAssemblyTargetLowering::getPointerMemTy(const DataLayout &DL, - uint32_t AS) const { - if (AS == WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF) - return MVT::funcref; - return TargetLowering::getPointerMemTy(DL, AS); -} - TargetLowering::AtomicExpansionKind WebAssemblyTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const { // We have wasm instructions for these @@ -1253,9 +1239,7 @@ WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI, SDValue TableSet = DAG.getMemIntrinsicNode( WebAssemblyISD::TABLE_SET, DL, DAG.getVTList(MVT::Other), TableSetOps, MVT::funcref, - // Machine Mem Operand args - MachinePointerInfo( - WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF), + MachinePointerInfo(), CLI.CB->getCalledOperand()->getPointerAlignment(DAG.getDataLayout()), MachineMemOperand::MOStore); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h index 1d1338ab40d0e..91c71bbc2e561 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h @@ -45,9 +45,6 @@ class WebAssemblyTargetLowering final : public TargetLowering { WebAssemblyTargetLowering(const TargetMachine &TM, const WebAssemblySubtarget &STI); - MVT getPointerTy(const DataLayout &DL, uint32_t AS = 0) const override; - MVT getPointerMemTy(const DataLayout &DL, uint32_t AS = 0) const override; - private: /// Keep a pointer to the WebAssemblySubtarget around so that we can make the /// right decision when generating code for different targets. diff --git a/llvm/test/CodeGen/WebAssembly/funcref-call.ll b/llvm/test/CodeGen/WebAssembly/funcref-call.ll index c4eb425244450..d87a6322c067d 100644 --- a/llvm/test/CodeGen/WebAssembly/funcref-call.ll +++ b/llvm/test/CodeGen/WebAssembly/funcref-call.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s --mtriple=wasm32-unknown-unknown -mattr=+reference-types | FileCheck %s -%funcref = type ptr addrspace(20) ;; addrspace 20 is nonintegral +%funcref = type target("wasm.funcref") ; CHECK: .tabletype __funcref_call_table, funcref, 1 @@ -18,7 +18,7 @@ define void @call_funcref(%funcref %ref) { ; CHECK-NEXT: ref.null_func ; CHECK-NEXT: table.set __funcref_call_table ; CHECK-NEXT: # fallthrough-return - call addrspace(20) void %ref() + call void %ref() ret void } @@ -40,6 +40,6 @@ define float @call_funcref_with_args(%funcref %ref) { ; CHECK-NEXT: table.set __funcref_call_table ; CHECK-NEXT: local.get 1 ; CHECK-NEXT: # fallthrough-return - %ret = call addrspace(20) float %ref(double 1.0, i32 2) + %ret = call float %ref(double 1.0, i32 2) ret float %ret } diff --git a/llvm/test/CodeGen/WebAssembly/funcref-globalget.ll b/llvm/test/CodeGen/WebAssembly/funcref-globalget.ll index 9aa7fdabfdea9..2634e5a6fc57e 100644 --- a/llvm/test/CodeGen/WebAssembly/funcref-globalget.ll +++ b/llvm/test/CodeGen/WebAssembly/funcref-globalget.ll @@ -1,6 +1,6 @@ ; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types | FileCheck %s -%funcref = type ptr addrspace(20) ;; addrspace 20 is nonintegral +%funcref = type target("wasm.funcref") @funcref_global = local_unnamed_addr addrspace(1) global %funcref undef diff --git a/llvm/test/CodeGen/WebAssembly/funcref-globalset.ll b/llvm/test/CodeGen/WebAssembly/funcref-globalset.ll index ca2feb6617996..791e8648537c0 100644 --- a/llvm/test/CodeGen/WebAssembly/funcref-globalset.ll +++ b/llvm/test/CodeGen/WebAssembly/funcref-globalset.ll @@ -1,6 +1,6 @@ ; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types | FileCheck %s -%funcref = type ptr addrspace(20) ;; addrspace 20 is nonintegral +%funcref = type target("wasm.funcref") @funcref_global = local_unnamed_addr addrspace(1) global %funcref undef diff --git a/llvm/test/CodeGen/WebAssembly/funcref-table_call.ll b/llvm/test/CodeGen/WebAssembly/funcref-table_call.ll index 74bbc802ac077..dc8cb19d3239a 100644 --- a/llvm/test/CodeGen/WebAssembly/funcref-table_call.ll +++ b/llvm/test/CodeGen/WebAssembly/funcref-table_call.ll @@ -1,6 +1,6 @@ ; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types | FileCheck %s -%funcref = type ptr addrspace(20) ;; addrspace 20 is nonintegral +%funcref = type target("wasm.funcref") @funcref_table = local_unnamed_addr addrspace(1) global [0 x %funcref] undef diff --git a/llvm/test/CodeGen/WebAssembly/funcref-tableget.ll b/llvm/test/CodeGen/WebAssembly/funcref-tableget.ll index 3df308c5ddf80..2621dcde6a79b 100644 --- a/llvm/test/CodeGen/WebAssembly/funcref-tableget.ll +++ b/llvm/test/CodeGen/WebAssembly/funcref-tableget.ll @@ -1,6 +1,6 @@ ; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types | FileCheck %s -%funcref = type ptr addrspace(20) ;; addrspace 20 is nonintegral +%funcref = type target("wasm.funcref") @funcref_table = local_unnamed_addr addrspace(1) global [0 x %funcref] undef diff --git a/llvm/test/CodeGen/WebAssembly/funcref-tableset.ll b/llvm/test/CodeGen/WebAssembly/funcref-tableset.ll index 98e1b55613d7d..e62eb8a6f2d20 100644 --- a/llvm/test/CodeGen/WebAssembly/funcref-tableset.ll +++ b/llvm/test/CodeGen/WebAssembly/funcref-tableset.ll @@ -1,6 +1,6 @@ ; RUN: llc --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types < %s | FileCheck %s -%funcref = type ptr addrspace(20) ;; addrspace 20 is nonintegral +%funcref = type target("wasm.funcref") @funcref_table = local_unnamed_addr addrspace(1) global [0 x %funcref] undef diff --git a/llvm/test/CodeGen/WebAssembly/ref-null.ll b/llvm/test/CodeGen/WebAssembly/ref-null.ll index f4aa31577cdaf..f2f2a0dad378b 100644 --- a/llvm/test/CodeGen/WebAssembly/ref-null.ll +++ b/llvm/test/CodeGen/WebAssembly/ref-null.ll @@ -2,7 +2,7 @@ ; RUN: llc --mtriple=wasm32-unknown-unknown -mattr=+reference-types < %s | FileCheck %s %externref = type target("wasm.externref") -%funcref = type ptr addrspace(20) ;; addrspace 20 is nonintegral +%funcref = type target("wasm.funcref") declare %externref @llvm.wasm.ref.null.extern() nounwind declare %funcref @llvm.wasm.ref.null.func() nounwind diff --git a/llvm/test/CodeGen/WebAssembly/table-types.ll b/llvm/test/CodeGen/WebAssembly/table-types.ll index f0cd7e30b5c1f..da04ba35dd58e 100644 --- a/llvm/test/CodeGen/WebAssembly/table-types.ll +++ b/llvm/test/CodeGen/WebAssembly/table-types.ll @@ -1,7 +1,7 @@ ; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types | FileCheck %s %externref = type target("wasm.externref") -%funcref = type ptr addrspace(20) ;; addrspace 20 is nonintegral +%funcref = type target("wasm.funcref") ; CHECK: .tabletype eref_table, externref ; CHECK-NEXT: .globl eref_table From 3faec82d3a2988718ac0762956a991e9c0224295 Mon Sep 17 00:00:00 2001 From: Paulo Matos Date: Thu, 16 Nov 2023 12:35:48 +0100 Subject: [PATCH 3/4] wip --- llvm/include/llvm/IR/IntrinsicsWebAssembly.td | 7 +++++++ llvm/test/CodeGen/WebAssembly/funcref-call.ll | 8 ++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td index b93a5e7be1b51..f635a9c1fc95e 100644 --- a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td +++ b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td @@ -38,6 +38,13 @@ def int_wasm_ref_is_null_func : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_funcref_ty], [IntrNoMem], "llvm.wasm.ref.is_null.func">; +//===----------------------------------------------------------------------===// +// funcref target ext type -> pointer intrinsic +//===----------------------------------------------------------------------===// +def int_wasm_funcref_to_ptr : + DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_funcref_ty], + [IntrNoMem], "llvm.wasm.funcref.to_ptr">; + //===----------------------------------------------------------------------===// // Table intrinsics //===----------------------------------------------------------------------===// diff --git a/llvm/test/CodeGen/WebAssembly/funcref-call.ll b/llvm/test/CodeGen/WebAssembly/funcref-call.ll index d87a6322c067d..397f56acda64d 100644 --- a/llvm/test/CodeGen/WebAssembly/funcref-call.ll +++ b/llvm/test/CodeGen/WebAssembly/funcref-call.ll @@ -3,6 +3,8 @@ %funcref = type target("wasm.funcref") +declare ptr @llvm.wasm.funcref.to_ptr(%funcref) nounwind + ; CHECK: .tabletype __funcref_call_table, funcref, 1 define void @call_funcref(%funcref %ref) { @@ -18,7 +20,8 @@ define void @call_funcref(%funcref %ref) { ; CHECK-NEXT: ref.null_func ; CHECK-NEXT: table.set __funcref_call_table ; CHECK-NEXT: # fallthrough-return - call void %ref() + %refptr = call ptr @llvm.wasm.funcref.to_ptr(%funcref %ref) + call void %refptr() ret void } @@ -40,6 +43,7 @@ define float @call_funcref_with_args(%funcref %ref) { ; CHECK-NEXT: table.set __funcref_call_table ; CHECK-NEXT: local.get 1 ; CHECK-NEXT: # fallthrough-return - %ret = call float %ref(double 1.0, i32 2) + %refptr = call ptr @llvm.wasm.funcref.to_ptr(%funcref %ref) + %ret = call float %refptr(double 1.0, i32 2) ret float %ret } From c642159c3db5a5ac56ea2d8d7a177bc274597429 Mon Sep 17 00:00:00 2001 From: Paulo Matos Date: Fri, 17 Nov 2023 11:23:44 +0100 Subject: [PATCH 4/4] wip --- llvm/lib/Target/WebAssembly/WebAssemblyISD.def | 3 +++ llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISD.def b/llvm/lib/Target/WebAssembly/WebAssemblyISD.def index b8954f4693f0a..f4476b999804f 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISD.def +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISD.def @@ -45,6 +45,9 @@ HANDLE_NODETYPE(DEMOTE_ZERO) HANDLE_NODETYPE(MEMORY_COPY) HANDLE_NODETYPE(MEMORY_FILL) +// Pointer Conversion intrinsic for funcref +HANDLE_NODETYPE(FUNCREF_TO_PTR) + // Memory intrinsics HANDLE_MEM_NODETYPE(GLOBAL_GET) HANDLE_MEM_NODETYPE(GLOBAL_SET) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td index 608963d588635..46480fce5c666 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td @@ -44,3 +44,10 @@ def : Pat<(select (i32 (setne I32:$cond, 0)), rc:$lhs, rc:$rhs), def : Pat<(select (i32 (seteq I32:$cond, 0)), rc:$lhs, rc:$rhs), (!cast("SELECT_"#rc) rc:$rhs, rc:$lhs, I32:$cond)>; } + +// Define node for wasm.funcref.to_ptr intrinsic +// This will then be combined with a call to the result of the intrinsic +// to generate a proper funcref call, which is a table.set + a call indirect. +def WebAssemblyFuncrefToPtr_t : SDTypeProfile<1, 1, [SDTCisPtrTy<0>]>; +def WebAssemblyFuncrefToPtr : SDNode<"WebAssemblyISD::FUNCREF_TO_PTR", WebAssemblyFuncrefToPtr_t, + []>;