diff --git a/lld/wasm/WriterUtils.cpp b/lld/wasm/WriterUtils.cpp --- a/lld/wasm/WriterUtils.cpp +++ b/lld/wasm/WriterUtils.cpp @@ -31,9 +31,9 @@ case ValType::V128: return "v128"; case ValType::FUNCREF: - return "func"; + return "funcref"; case ValType::ANYREF: - return "anyref" + return "anyref"; case ValType::EXNREF: return "exnref"; } diff --git a/llvm/include/llvm/Support/MachineValueType.h b/llvm/include/llvm/Support/MachineValueType.h --- a/llvm/include/llvm/Support/MachineValueType.h +++ b/llvm/include/llvm/Support/MachineValueType.h @@ -825,7 +825,7 @@ case v1024f32: return TypeSize::Fixed(32768); case v2048i32: case v2048f32: return TypeSize::Fixed(65536); - case anyref: + case anyref: case exnref: return TypeSize::Fixed(0); // opaque type } } diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -310,6 +310,8 @@ return wasm::ValType::V128; if (Type == "exnref") return wasm::ValType::EXNREF; + if (Type == "anyref") + return wasm::ValType::ANYREF; return Optional(); } @@ -322,6 +324,7 @@ .Case("f64", WebAssembly::BlockType::F64) .Case("v128", WebAssembly::BlockType::V128) .Case("exnref", WebAssembly::BlockType::Exnref) + .Case("anyref", WebAssembly::BlockType::Anyref) .Case("void", WebAssembly::BlockType::Void) .Default(WebAssembly::BlockType::Invalid); } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -130,6 +130,7 @@ case MVT::f32: case MVT::f64: case MVT::exnref: + case MVT::anyref: return VT; case MVT::f16: return MVT::f32; @@ -706,6 +707,10 @@ Opc = WebAssembly::ARGUMENT_exnref; RC = &WebAssembly::EXNREFRegClass; break; + case MVT::anyref: + Opc = WebAssembly::ARGUMENT_anyref; + RC = &WebAssembly::ANYREFRegClass; + break; default: return false; } @@ -824,6 +829,11 @@ : WebAssembly::PCALL_INDIRECT_exnref; ResultReg = createResultReg(&WebAssembly::EXNREFRegClass); break; + case MVT::anyref: + Opc = IsDirect ? WebAssembly::CALL_anyref + : WebAssembly::PCALL_INDIRECT_anyref; + ResultReg = createResultReg(&WebAssembly::ANYREFRegClass); + break; default: return false; } @@ -1329,6 +1339,7 @@ case MVT::v4f32: case MVT::v2f64: case MVT::exnref: + case MVT::anyref: break; default: return false; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -1118,7 +1118,7 @@ "Unexpected target flags on generic GlobalAddressSDNode"); if (GA->getAddressSpace() != 0 && GA->getAddressSpace() != WebAssemblyAS::ANYREF_ADDRESS) - fail(DL, DAG, "WebAssembly only expects the 0 or 1 address space"); + fail(DL, DAG, "WebAssembly only expects the 0 or 256 (anyref) address space"); unsigned OperandFlags = 0; if (isPositionIndependent()) { diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td @@ -143,6 +143,9 @@ def : Pat<(exnref (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), (CALL_exnref tglobaladdr:$callee)>, Requires<[HasExceptionHandling]>; +def : Pat<(anyref (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), + (CALL_anyref tglobaladdr:$callee)>, + Requires<[HasReferenceTypes]>; def : Pat<(WebAssemblycall0 (WebAssemblywrapper tglobaladdr:$callee)), (CALL_VOID tglobaladdr:$callee)>; def : Pat<(WebAssemblyretcall (WebAssemblywrapper tglobaladdr:$callee)), diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp @@ -77,6 +77,8 @@ CopyOpcode = WebAssembly::COPY_V128; else if (RC == &WebAssembly::EXNREFRegClass) CopyOpcode = WebAssembly::COPY_EXNREF; + else if (RC == &WebAssembly::ANYREFRegClass) + CopyOpcode = WebAssembly::COPY_ANYREF; else llvm_unreachable("Unexpected register class"); diff --git a/llvm/test/CodeGen/WebAssembly/anyref.ll b/llvm/test/CodeGen/WebAssembly/anyref.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/anyref.ll @@ -0,0 +1,29 @@ +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+reference-types | FileCheck %s + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +declare i8 addrspace(256)* @test(i8 addrspace(256)*) + + +; CHECK-LABEL: call_test: +; CHECK: .functype call_test (anyref) -> (anyref) +define i8 addrspace(256)* @call_test(i8 addrspace(256)*) { +; CHECK: anyref.call $push0=, test, $0 + %a = call i8 addrspace(256)* @test(i8 addrspace(256)* %0) + ret i8 addrspace(256)* %a +} + +; TODO: nullref? +; define i8 addrspace(256)* @null_test() { +; ret i8 addrspace(256)* null +; } + +; TODO: Loading a anyref from a pointer +; @glob = external global i8 addrspace(256)*, align 4 +; define i8 addrspace(256)* @global_test() { +; %a = load i8 addrspace(256)*, i8 addrspace(256)** @glob +; ret i8 addrspace(256)* %a +; } + +; CHECK: .functype test (anyref) -> (anyref) diff --git a/llvm/test/CodeGen/WebAssembly/reg-argument.mir b/llvm/test/CodeGen/WebAssembly/reg-argument.mir --- a/llvm/test/CodeGen/WebAssembly/reg-argument.mir +++ b/llvm/test/CodeGen/WebAssembly/reg-argument.mir @@ -57,3 +57,14 @@ %1:exnref = ARGUMENT_exnref 0, implicit $arguments RETURN implicit-def $arguments ... +--- +name: argument_anyref +# CHECK-LABEL: argument_anyref +body: | + ; CHECK-LABEL: bb.0: + ; CHECK-NEXT: %1:anyref = ARGUMENT_anyref 0 + bb.0: + %0:i32 = CONST_I32 0, implicit-def $arguments + %1:anyref = ARGUMENT_anyref 0, implicit $arguments + RETURN implicit-def $arguments +... diff --git a/llvm/test/CodeGen/WebAssembly/reg-copy.mir b/llvm/test/CodeGen/WebAssembly/reg-copy.mir --- a/llvm/test/CodeGen/WebAssembly/reg-copy.mir +++ b/llvm/test/CodeGen/WebAssembly/reg-copy.mir @@ -66,3 +66,14 @@ %0:exnref = COPY %1:exnref RETURN implicit-def $arguments ... +--- +name: copy_anyref +# CHECK-LABEL: copy_anyref +body: | + ; CHECK-LABEL: bb.0 + ; CHECK-NEXT: %0:anyref = COPY_ANYREF %1:anyref + ; CHECK-NEXT: RETURN + bb.0: + %0:anyref = COPY %1:anyref + RETURN implicit-def $arguments +...