.Case("f32", WebAssembly::BlockType::F32)
.Case("f64", WebAssembly::BlockType::F64)
.Case("v128", WebAssembly::BlockType::V128)
+ .Case("funcref", WebAssembly::BlockType::Funcref)
+ .Case("externref", WebAssembly::BlockType::Externref)
.Case("exnref", WebAssembly::BlockType::Exnref)
.Case("void", WebAssembly::BlockType::Void)
.Default(WebAssembly::BlockType::Invalid);
case MVT::v4f32:
case MVT::v2f64:
return wasm::ValType::V128;
+ case MVT::funcref:
+ return wasm::ValType::FUNCREF;
+ case MVT::externref:
+ return wasm::ValType::EXTERNREF;
case MVT::exnref:
return wasm::ValType::EXNREF;
default:
F32 = unsigned(wasm::ValType::F32),
F64 = unsigned(wasm::ValType::F64),
V128 = unsigned(wasm::ValType::V128),
+ Externref = unsigned(wasm::ValType::EXTERNREF),
+ Funcref = unsigned(wasm::ValType::FUNCREF),
Exnref = unsigned(wasm::ValType::EXNREF),
// Multivalue blocks (and other non-void blocks) are only emitted when the
// blocks will never be exited and are at the ends of functions (see
case WebAssembly::ARGUMENT_v4f32_S:
case WebAssembly::ARGUMENT_v2f64:
case WebAssembly::ARGUMENT_v2f64_S:
+ case WebAssembly::ARGUMENT_funcref:
+ case WebAssembly::ARGUMENT_funcref_S:
+ case WebAssembly::ARGUMENT_externref:
+ case WebAssembly::ARGUMENT_externref_S:
case WebAssembly::ARGUMENT_exnref:
case WebAssembly::ARGUMENT_exnref_S:
return true;
case WebAssembly::COPY_F64_S:
case WebAssembly::COPY_V128:
case WebAssembly::COPY_V128_S:
+ case WebAssembly::COPY_FUNCREF:
+ case WebAssembly::COPY_FUNCREF_S:
+ case WebAssembly::COPY_EXTERNREF:
+ case WebAssembly::COPY_EXTERNREF_S:
case WebAssembly::COPY_EXNREF:
case WebAssembly::COPY_EXNREF_S:
return true;
case WebAssembly::TEE_F64_S:
case WebAssembly::TEE_V128:
case WebAssembly::TEE_V128_S:
+ case WebAssembly::TEE_FUNCREF:
+ case WebAssembly::TEE_FUNCREF_S:
+ case WebAssembly::TEE_EXTERNREF:
+ case WebAssembly::TEE_EXTERNREF_S:
case WebAssembly::TEE_EXNREF:
case WebAssembly::TEE_EXNREF_S:
return true;
return WebAssembly::COPY_F64;
if (RC == &WebAssembly::V128RegClass)
return WebAssembly::COPY_V128;
+ if (RC == &WebAssembly::FUNCREFRegClass)
+ return WebAssembly::COPY_FUNCREF;
+ if (RC == &WebAssembly::EXTERNREFRegClass)
+ return WebAssembly::COPY_EXTERNREF;
if (RC == &WebAssembly::EXNREFRegClass)
return WebAssembly::COPY_EXNREF;
llvm_unreachable("Unexpected register class");
return WebAssembly::DROP_F64;
if (RC == &WebAssembly::V128RegClass)
return WebAssembly::DROP_V128;
+ if (RC == &WebAssembly::FUNCREFRegClass)
+ return WebAssembly::DROP_FUNCREF;
+ if (RC == &WebAssembly::EXTERNREFRegClass)
+ return WebAssembly::DROP_EXTERNREF;
if (RC == &WebAssembly::EXNREFRegClass)
return WebAssembly::DROP_EXNREF;
llvm_unreachable("Unexpected register class");
Opc = WebAssembly::ARGUMENT_v2f64;
RC = &WebAssembly::V128RegClass;
break;
+ case MVT::funcref:
+ Opc = WebAssembly::ARGUMENT_funcref;
+ RC = &WebAssembly::FUNCREFRegClass;
+ break;
+ case MVT::externref:
+ Opc = WebAssembly::ARGUMENT_externref;
+ RC = &WebAssembly::EXTERNREFRegClass;
+ break;
case MVT::exnref:
Opc = WebAssembly::ARGUMENT_exnref;
RC = &WebAssembly::EXNREFRegClass;
Opc = WebAssembly::SELECT_EXNREF;
RC = &WebAssembly::EXNREFRegClass;
break;
+ case MVT::funcref:
+ Opc = WebAssembly::SELECT_FUNCREF;
+ RC = &WebAssembly::FUNCREFRegClass;
+ break;
+ case MVT::externref:
+ Opc = WebAssembly::SELECT_EXTERNREF;
+ RC = &WebAssembly::EXTERNREFRegClass;
+ break;
default:
return false;
}
case MVT::v2i64:
case MVT::v4f32:
case MVT::v2f64:
+ case MVT::funcref:
+ case MVT::externref:
case MVT::exnref:
break;
default:
CopyOpcode = WebAssembly::COPY_F64;
else if (RC == &WebAssembly::V128RegClass)
CopyOpcode = WebAssembly::COPY_V128;
+ else if (RC == &WebAssembly::FUNCREFRegClass)
+ CopyOpcode = WebAssembly::COPY_FUNCREF;
+ else if (RC == &WebAssembly::EXTERNREFRegClass)
+ CopyOpcode = WebAssembly::COPY_EXTERNREF;
else if (RC == &WebAssembly::EXNREFRegClass)
CopyOpcode = WebAssembly::COPY_EXNREF;
else
///
//===----------------------------------------------------------------------===//
-defm SELECT_EXNREF : I<(outs EXNREF:$dst),
- (ins EXNREF:$lhs, EXNREF:$rhs, I32:$cond),
- (outs), (ins),
- [(set EXNREF:$dst,
- (select I32:$cond, EXNREF:$lhs, EXNREF:$rhs))],
- "exnref.select\t$dst, $lhs, $rhs, $cond",
- "exnref.select", 0x1b>;
+multiclass REF_I<WebAssemblyRegClass reg, ValueType vt> {
+ defm REF_NULL_#reg : I<(outs reg:$res), (ins HeapType:$heaptype),
+ (outs), (ins HeapType:$heaptype),
+ [],
+ "ref.null\t$res, $heaptype",
+ "ref.null\t$heaptype",
+ 0xd0>,
+ Requires<[HasReferenceTypes]>;
+ defm SELECT_#reg: I<(outs reg:$dst), (ins reg:$lhs, reg:$rhs, I32:$cond),
+ (outs), (ins),
+ [(set reg:$dst,
+ (select I32:$cond, reg:$lhs, reg:$rhs))],
+ vt#".select\t$dst, $lhs, $rhs, $cond",
+ vt#".select", 0x1b>,
+ Requires<[HasReferenceTypes]>;
+}
-def : Pat<(select (i32 (setne I32:$cond, 0)), EXNREF:$lhs, EXNREF:$rhs),
- (SELECT_EXNREF EXNREF:$lhs, EXNREF:$rhs, I32:$cond)>;
-def : Pat<(select (i32 (seteq I32:$cond, 0)), EXNREF:$lhs, EXNREF:$rhs),
- (SELECT_EXNREF EXNREF:$rhs, EXNREF:$lhs, I32:$cond)>;
+defm "" : REF_I<FUNCREF, funcref>;
+defm "" : REF_I<EXTERNREF, externref>;
+defm "" : REF_I<EXNREF, exnref>;
-multiclass REF<WebAssemblyRegClass rt> {
- defm REF_NULL_#rt : I<(outs rt:$res), (ins HeapType:$heaptype),
- (outs), (ins HeapType:$heaptype),
- [],
- "ref.null\t$res, $heaptype",
- "ref.null\t$heaptype",
- 0xd0>;
+foreach reg = [FUNCREF, EXTERNREF, EXNREF] in {
+def : Pat<(select (i32 (setne I32:$cond, 0)), reg:$lhs, reg:$rhs),
+ (!cast<Instruction>("SELECT_"#reg) reg:$lhs, reg:$rhs, I32:$cond)>;
+def : Pat<(select (i32 (seteq I32:$cond, 0)), reg:$lhs, reg:$rhs),
+ (!cast<Instruction>("SELECT_"#reg) reg:$rhs, reg:$lhs, I32:$cond)>;
}
-
-defm "" : REF<FUNCREF>, Requires<[HasReferenceTypes]>;
-defm "" : REF<EXTERNREF>, Requires<[HasReferenceTypes]>;
case WebAssembly::V128RegClassID:
CopyLocalOpc = WebAssembly::COPY_V128;
break;
+ case WebAssembly::FUNCREFRegClassID:
+ CopyLocalOpc = WebAssembly::COPY_FUNCREF;
+ break;
+ case WebAssembly::EXTERNREFRegClassID:
+ CopyLocalOpc = WebAssembly::COPY_EXTERNREF;
+ break;
case WebAssembly::EXNREFRegClassID:
CopyLocalOpc = WebAssembly::COPY_EXNREF;
break;
# RUN: llvm-mc -show-encoding -triple=wasm32-unknown-unknown -mattr=+reference-types < %s | FileCheck %s
# RUN: llvm-mc -show-encoding -triple=wasm64-unknown-unknown -mattr=+reference-types < %s | FileCheck %s
-# CHECK: ref_null_externref:
-# CHECK-NEXT: .functype ref_null_externref () -> (externref)
-# CHECK: ref.null extern # encoding: [0xd0,0x6f]
-# CHECK-NEXT: end_function
-ref_null_externref:
- .functype ref_null_externref () -> (externref)
+# CHECK-LABEL: ref_null_test:
+# CHECK: ref.null func # encoding: [0xd0,0x70]
+# CHECK: ref.null extern # encoding: [0xd0,0x6f]
+ref_null_test:
+ .functype ref_null_test () -> ()
+ ref.null func
+ drop
ref.null extern
+ drop
+ end_function
+
+# CHECK-LABEL: ref_sig_test_funcref:
+# CHECK-NEXT: .functype ref_sig_test_funcref (funcref) -> (funcref)
+ref_sig_test_funcref:
+ .functype ref_sig_test_funcref (funcref) -> (funcref)
+ end_function
+
+# CHECK-LABEL: ref_sig_test_externref:
+# CHECK-NEXT: .functype ref_sig_test_externref (externref) -> (externref)
+ref_sig_test_externref:
+ .functype ref_sig_test_externref (externref) -> (externref)
end_function
-# CHECK: ref_null_funcref:
-# CHECK-NEXT: .functype ref_null_funcref () -> (funcref)
-# CHECK: ref.null func # encoding: [0xd0,0x70]
-# CHECK-NEXT: end_function
-ref_null_funcref:
- .functype ref_null_funcref () -> (funcref)
+# CHECK-LABEL: ref_select_test:
+# CHECK: funcref.select # encoding: [0x1b]
+# CHECK: externref.select # encoding: [0x1b]
+ref_select_test:
+ .functype ref_select_test () -> ()
ref.null func
+ ref.null func
+ i32.const 0
+ funcref.select
+ drop
+ ref.null extern
+ ref.null extern
+ i32.const 0
+ externref.select
+ drop
+ end_function
+
+# CHECK-LABEL: ref_block_test:
+# CHECK: block funcref
+# CHECK: block externref
+ref_block_test:
+ .functype ref_block_test () -> ()
+ block funcref
+ block externref
+ end_block
+ end_block
end_function