[lld] [llvm] [WebAssembly] Add exnref type (PR #93586)
Heejin Ahn via llvm-commits
llvm-commits at lists.llvm.org
Tue May 28 11:34:44 PDT 2024
https://github.com/aheejin updated https://github.com/llvm/llvm-project/pull/93586
>From 5a7c331aa4cae9f20dbfc058258901fb4d789c55 Mon Sep 17 00:00:00 2001
From: Heejin Ahn <aheejin at gmail.com>
Date: Sat, 25 May 2024 00:46:11 +0000
Subject: [PATCH 1/2] [WebAssembly] Add exnref type
This adds (back) the exnref type restored in the new EH proposal adopted
in Oct 2023 CG meeting:
https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md:x
---
lld/wasm/WriterUtils.cpp | 2 ++
llvm/include/llvm/BinaryFormat/Wasm.h | 9 ++++---
llvm/include/llvm/CodeGen/ValueTypes.td | 9 ++++---
llvm/include/llvm/IR/Intrinsics.td | 2 ++
llvm/include/llvm/IR/IntrinsicsWebAssembly.td | 18 +++++++++++++
llvm/lib/CodeGen/ValueTypes.cpp | 1 +
llvm/lib/Object/WasmObjectFile.cpp | 4 +++
llvm/lib/ObjectYAML/WasmYAML.cpp | 2 ++
.../MCTargetDesc/WebAssemblyMCTargetDesc.h | 12 +++++++++
.../WebAssemblyMCTypeUtilities.cpp | 6 +++++
.../MCTargetDesc/WebAssemblyMCTypeUtilities.h | 4 ++-
.../Utils/WebAssemblyTypeUtilities.cpp | 3 +++
.../WebAssembly/WebAssemblyAsmPrinter.cpp | 2 ++
.../WebAssembly/WebAssemblyExplicitLocals.cpp | 10 +++++++
.../WebAssembly/WebAssemblyFastISel.cpp | 16 ++++++++++++
.../WebAssembly/WebAssemblyISelLowering.cpp | 3 +++
.../WebAssembly/WebAssemblyInstrInfo.td | 3 +++
.../Target/WebAssembly/WebAssemblyInstrRef.td | 8 +++---
.../WebAssembly/WebAssemblyInstrTable.td | 2 ++
.../WebAssembly/WebAssemblyRegStackify.cpp | 2 ++
.../WebAssembly/WebAssemblyRegisterInfo.td | 2 ++
.../WebAssembly/WebAssemblyUtilities.cpp | 2 ++
.../test/CodeGen/WebAssembly/reg-argument.mir | 11 ++++++++
llvm/test/CodeGen/WebAssembly/reg-copy.mir | 11 ++++++++
llvm/test/MC/WebAssembly/basic-assembly.s | 21 +++++++++------
llvm/test/MC/WebAssembly/reference-types.s | 26 +++++++++++++++++--
.../test/MC/WebAssembly/type-checker-errors.s | 16 ++++++++++++
llvm/utils/TableGen/Common/CodeGenTarget.cpp | 1 +
28 files changed, 187 insertions(+), 21 deletions(-)
diff --git a/lld/wasm/WriterUtils.cpp b/lld/wasm/WriterUtils.cpp
index cdd2c42f939ef..c6a1592012e64 100644
--- a/lld/wasm/WriterUtils.cpp
+++ b/lld/wasm/WriterUtils.cpp
@@ -35,6 +35,8 @@ std::string toString(ValType type) {
return "funcref";
case ValType::EXTERNREF:
return "externref";
+ case ValType::EXNREF:
+ return "exnref";
case ValType::OTHERREF:
return "otherref";
}
diff --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h
index 38ef8e37df91d..d8aa899080097 100644
--- a/llvm/include/llvm/BinaryFormat/Wasm.h
+++ b/llvm/include/llvm/BinaryFormat/Wasm.h
@@ -58,15 +58,16 @@ enum : unsigned {
WASM_TYPE_V128 = 0x7B,
WASM_TYPE_NULLFUNCREF = 0x73,
WASM_TYPE_NULLEXTERNREF = 0x72,
+ WASM_TYPE_NULLEXNREF= 0x74,
WASM_TYPE_NULLREF = 0x71,
WASM_TYPE_FUNCREF = 0x70,
WASM_TYPE_EXTERNREF = 0x6F,
+ WASM_TYPE_EXNREF = 0x69,
WASM_TYPE_ANYREF = 0x6E,
WASM_TYPE_EQREF = 0x6D,
WASM_TYPE_I31REF = 0x6C,
WASM_TYPE_STRUCTREF = 0x6B,
WASM_TYPE_ARRAYREF = 0x6A,
- WASM_TYPE_EXNREF = 0x69,
WASM_TYPE_NONNULLABLE = 0x64,
WASM_TYPE_NULLABLE = 0x63,
WASM_TYPE_FUNC = 0x60,
@@ -261,8 +262,9 @@ enum class ValType {
V128 = WASM_TYPE_V128,
FUNCREF = WASM_TYPE_FUNCREF,
EXTERNREF = WASM_TYPE_EXTERNREF,
+ EXNREF = WASM_TYPE_EXNREF,
// Unmodeled value types include ref types with heap types other than
- // func or extern, and type-specialized funcrefs
+ // func, extern or exn, and type-specialized funcrefs
OTHERREF = 0xff,
};
@@ -410,7 +412,8 @@ struct WasmDataSegment {
// 1) Does not model passive or declarative segments (Segment will end up with
// an Offset field of i32.const 0)
// 2) Does not model init exprs (Segment will get an empty Functions list)
-// 2) Does not model types other than basic funcref/externref (see ValType)
+// 3) Does not model types other than basic funcref/externref/exnref (see
+// ValType)
struct WasmElemSegment {
uint32_t Flags;
uint32_t TableNumber;
diff --git a/llvm/include/llvm/CodeGen/ValueTypes.td b/llvm/include/llvm/CodeGen/ValueTypes.td
index 900b30d9b0249..6ae283b9c5a85 100644
--- a/llvm/include/llvm/CodeGen/ValueTypes.td
+++ b/llvm/include/llvm/CodeGen/ValueTypes.td
@@ -280,11 +280,12 @@ def untyped : ValueType<8, 193> { // Produces an untyped value
}
def funcref : ValueType<0, 194>; // WebAssembly's funcref type
def externref : ValueType<0, 195>; // WebAssembly's externref type
-def x86amx : ValueType<8192, 196>; // X86 AMX value
-def i64x8 : ValueType<512, 197>; // 8 Consecutive GPRs (AArch64)
+def exnref : ValueType<0, 196>; // WebAssembly's exnref type
+def x86amx : ValueType<8192, 197>; // X86 AMX value
+def i64x8 : ValueType<512, 198>; // 8 Consecutive GPRs (AArch64)
def aarch64svcount
- : ValueType<16, 198>; // AArch64 predicate-as-counter
-def spirvbuiltin : ValueType<0, 199>; // SPIR-V's builtin type
+ : ValueType<16, 199>; // AArch64 predicate-as-counter
+def spirvbuiltin : ValueType<0, 200>; // SPIR-V's builtin type
def token : ValueType<0, 248>; // TokenTy
def MetadataVT : ValueType<0, 249> { // Metadata
diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index 3019f68083d42..c3ac53837444e 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -316,6 +316,7 @@ def IIT_PPCF128 : IIT_VT<ppcf128, 52>;
def IIT_V3 : IIT_Vec<3, 53>;
def IIT_EXTERNREF : IIT_VT<externref, 54>;
def IIT_FUNCREF : IIT_VT<funcref, 55>;
+def IIT_EXNREF: IIT_VT<exnref, 56>;
def IIT_I2 : IIT_Int<2, 57>;
def IIT_I4 : IIT_Int<4, 58>;
def IIT_AARCH64_SVCOUNT : IIT_VT<aarch64svcount, 59>;
@@ -581,6 +582,7 @@ def llvm_vararg_ty : LLVMType<isVoid>; // this means vararg here
def llvm_externref_ty : LLVMType<externref>;
def llvm_funcref_ty : LLVMType<funcref>;
+def llvm_exnref_ty : LLVMType<exnref>;
//===----------------------------------------------------------------------===//
diff --git a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td
index 572d334ac9552..373a816f476a3 100644
--- a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td
+++ b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td
@@ -31,12 +31,17 @@ def int_wasm_ref_null_extern :
DefaultAttrsIntrinsic<[llvm_externref_ty], [], [IntrNoMem]>;
def int_wasm_ref_null_func :
DefaultAttrsIntrinsic<[llvm_funcref_ty], [], [IntrNoMem]>;
+def int_wasm_ref_null_exn:
+ DefaultAttrsIntrinsic<[llvm_exnref_ty], [], [IntrNoMem]>;
def int_wasm_ref_is_null_extern :
DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_externref_ty], [IntrNoMem],
"llvm.wasm.ref.is_null.extern">;
def int_wasm_ref_is_null_func :
DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_funcref_ty],
[IntrNoMem], "llvm.wasm.ref.is_null.func">;
+def int_wasm_ref_is_null_exn :
+ DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_exnref_ty], [IntrNoMem],
+ "llvm.wasm.ref.is_null.exn">;
//===----------------------------------------------------------------------===//
// Table intrinsics
@@ -47,6 +52,9 @@ def int_wasm_table_set_externref :
def int_wasm_table_set_funcref :
DefaultAttrsIntrinsic<[], [llvm_table_ty, llvm_i32_ty, llvm_funcref_ty],
[IntrWriteMem]>;
+def int_wasm_table_set_exnref :
+ DefaultAttrsIntrinsic<[], [llvm_table_ty, llvm_i32_ty, llvm_exnref_ty],
+ [IntrWriteMem]>;
def int_wasm_table_get_externref :
DefaultAttrsIntrinsic<[llvm_externref_ty], [llvm_table_ty, llvm_i32_ty],
@@ -54,6 +62,9 @@ def int_wasm_table_get_externref :
def int_wasm_table_get_funcref :
DefaultAttrsIntrinsic<[llvm_funcref_ty], [llvm_table_ty, llvm_i32_ty],
[IntrReadMem]>;
+def int_wasm_table_get_exnref :
+ DefaultAttrsIntrinsic<[llvm_exnref_ty], [llvm_table_ty, llvm_i32_ty],
+ [IntrReadMem]>;
// Query the current table size, and increase the current table size.
def int_wasm_table_size :
@@ -68,6 +79,9 @@ def int_wasm_table_grow_externref :
def int_wasm_table_grow_funcref :
DefaultAttrsIntrinsic<[llvm_i32_ty],
[llvm_table_ty, llvm_funcref_ty, llvm_i32_ty], []>;
+def int_wasm_table_grow_exnref :
+ DefaultAttrsIntrinsic<[llvm_i32_ty],
+ [llvm_table_ty, llvm_exnref_ty, llvm_i32_ty], []>;
def int_wasm_table_fill_externref :
DefaultAttrsIntrinsic<[],
[llvm_table_ty, llvm_i32_ty, llvm_externref_ty,
@@ -76,6 +90,10 @@ def int_wasm_table_fill_funcref :
DefaultAttrsIntrinsic<[],
[llvm_table_ty, llvm_i32_ty, llvm_funcref_ty,
llvm_i32_ty], []>;
+def int_wasm_table_fill_exnref :
+ DefaultAttrsIntrinsic<[],
+ [llvm_table_ty, llvm_i32_ty, llvm_exnref_ty,
+ llvm_i32_ty], []>;
//===----------------------------------------------------------------------===//
// Trapping float-to-int conversions
diff --git a/llvm/lib/CodeGen/ValueTypes.cpp b/llvm/lib/CodeGen/ValueTypes.cpp
index 58db686ec7d57..078894d5ac4ed 100644
--- a/llvm/lib/CodeGen/ValueTypes.cpp
+++ b/llvm/lib/CodeGen/ValueTypes.cpp
@@ -181,6 +181,7 @@ std::string EVT::getEVTString() const {
case MVT::Metadata: return "Metadata";
case MVT::Untyped: return "Untyped";
case MVT::funcref: return "funcref";
+ case MVT::exnref: return "exnref";
case MVT::externref: return "externref";
case MVT::aarch64svcount:
return "aarch64svcount";
diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp
index 6507a0e5950eb..872a1214d4f0e 100644
--- a/llvm/lib/Object/WasmObjectFile.cpp
+++ b/llvm/lib/Object/WasmObjectFile.cpp
@@ -187,6 +187,7 @@ static wasm::ValType parseValType(WasmObjectFile::ReadContext &Ctx,
case wasm::WASM_TYPE_V128:
case wasm::WASM_TYPE_FUNCREF:
case wasm::WASM_TYPE_EXTERNREF:
+ case wasm::WASM_TYPE_EXNREF:
return wasm::ValType(Code);
}
if (Code == wasm::WASM_TYPE_NULLABLE || Code == wasm::WASM_TYPE_NONNULLABLE) {
@@ -1288,6 +1289,7 @@ Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
auto ElemType = Im.Table.ElemType;
if (ElemType != wasm::ValType::FUNCREF &&
ElemType != wasm::ValType::EXTERNREF &&
+ ElemType != wasm::ValType::EXNREF &&
ElemType != wasm::ValType::OTHERREF)
return make_error<GenericBinaryError>("invalid table element type",
object_error::parse_failed);
@@ -1346,6 +1348,7 @@ Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
auto ElemType = Tables.back().Type.ElemType;
if (ElemType != wasm::ValType::FUNCREF &&
ElemType != wasm::ValType::EXTERNREF &&
+ ElemType != wasm::ValType::EXNREF &&
ElemType != wasm::ValType::OTHERREF) {
return make_error<GenericBinaryError>("invalid table element type",
object_error::parse_failed);
@@ -1680,6 +1683,7 @@ Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
Segment.ElemKind = parseValType(Ctx, ElemKind);
if (Segment.ElemKind != wasm::ValType::FUNCREF &&
Segment.ElemKind != wasm::ValType::EXTERNREF &&
+ Segment.ElemKind != wasm::ValType::EXNREF &&
Segment.ElemKind != wasm::ValType::OTHERREF) {
return make_error<GenericBinaryError>("invalid elem type",
object_error::parse_failed);
diff --git a/llvm/lib/ObjectYAML/WasmYAML.cpp b/llvm/lib/ObjectYAML/WasmYAML.cpp
index 544a91d03dce0..7ad338f65706d 100644
--- a/llvm/lib/ObjectYAML/WasmYAML.cpp
+++ b/llvm/lib/ObjectYAML/WasmYAML.cpp
@@ -606,6 +606,7 @@ void ScalarEnumerationTraits<WasmYAML::ValueType>::enumeration(
ECase(V128);
ECase(FUNCREF);
ECase(EXTERNREF);
+ ECase(EXNREF);
ECase(OTHERREF);
#undef ECase
}
@@ -640,6 +641,7 @@ void ScalarEnumerationTraits<WasmYAML::TableType>::enumeration(
#define ECase(X) IO.enumCase(Type, #X, CONCAT(X));
ECase(FUNCREF);
ECase(EXTERNREF);
+ ECase(EXNREF);
ECase(OTHERREF);
#undef ECase
}
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
index d4e9fb057c44d..c1859a28488e1 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
@@ -353,6 +353,8 @@ inline bool isArgument(unsigned Opc) {
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;
default:
return false;
@@ -375,6 +377,8 @@ inline bool isCopy(unsigned Opc) {
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;
default:
return false;
@@ -397,6 +401,8 @@ inline bool isTee(unsigned Opc) {
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;
default:
return false;
@@ -487,6 +493,8 @@ inline bool isLocalGet(unsigned Opc) {
case WebAssembly::LOCAL_GET_FUNCREF_S:
case WebAssembly::LOCAL_GET_EXTERNREF:
case WebAssembly::LOCAL_GET_EXTERNREF_S:
+ case WebAssembly::LOCAL_GET_EXNREF:
+ case WebAssembly::LOCAL_GET_EXNREF_S:
return true;
default:
return false;
@@ -509,6 +517,8 @@ inline bool isLocalSet(unsigned Opc) {
case WebAssembly::LOCAL_SET_FUNCREF_S:
case WebAssembly::LOCAL_SET_EXTERNREF:
case WebAssembly::LOCAL_SET_EXTERNREF_S:
+ case WebAssembly::LOCAL_SET_EXNREF:
+ case WebAssembly::LOCAL_SET_EXNREF_S:
return true;
default:
return false;
@@ -531,6 +541,8 @@ inline bool isLocalTee(unsigned Opc) {
case WebAssembly::LOCAL_TEE_FUNCREF_S:
case WebAssembly::LOCAL_TEE_EXTERNREF:
case WebAssembly::LOCAL_TEE_EXTERNREF_S:
+ case WebAssembly::LOCAL_TEE_EXNREF:
+ case WebAssembly::LOCAL_TEE_EXNREF_S:
return true;
default:
return false;
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTypeUtilities.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTypeUtilities.cpp
index 8ea02bd2ad1ff..d9c8e22bbbaf5 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTypeUtilities.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTypeUtilities.cpp
@@ -27,6 +27,7 @@ std::optional<wasm::ValType> WebAssembly::parseType(StringRef Type) {
wasm::ValType::V128)
.Case("funcref", wasm::ValType::FUNCREF)
.Case("externref", wasm::ValType::EXTERNREF)
+ .Case("exnref", wasm::ValType::EXNREF)
.Default(std::nullopt);
}
@@ -40,6 +41,7 @@ WebAssembly::BlockType WebAssembly::parseBlockType(StringRef Type) {
.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);
}
@@ -62,6 +64,8 @@ const char *WebAssembly::anyTypeToString(unsigned Type) {
return "funcref";
case wasm::WASM_TYPE_EXTERNREF:
return "externref";
+ case wasm::WASM_TYPE_EXNREF:
+ return "exnref";
case wasm::WASM_TYPE_FUNC:
return "func";
case wasm::WASM_TYPE_NORESULT:
@@ -110,6 +114,8 @@ wasm::ValType WebAssembly::regClassToValType(unsigned RC) {
return wasm::ValType::FUNCREF;
case WebAssembly::EXTERNREFRegClassID:
return wasm::ValType::EXTERNREF;
+ case WebAssembly::EXNREFRegClassID:
+ return wasm::ValType::EXNREF;
default:
llvm_unreachable("unexpected type");
}
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTypeUtilities.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTypeUtilities.h
index 486cf264d13e2..063ee4dba9068 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTypeUtilities.h
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTypeUtilities.h
@@ -32,6 +32,7 @@ enum class BlockType : unsigned {
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
// WebAssemblyCFGStackify::fixEndsAtEndOfFunction). They also are never made
@@ -41,7 +42,8 @@ enum class BlockType : unsigned {
};
inline bool isRefType(wasm::ValType Type) {
- return Type == wasm::ValType::EXTERNREF || Type == wasm::ValType::FUNCREF;
+ return Type == wasm::ValType::EXTERNREF || Type == wasm::ValType::FUNCREF ||
+ Type == wasm::ValType::EXNREF;
}
// Convert ValType or a list/signature of ValTypes to a string.
diff --git a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp
index fac2e0d935f5a..6e5905c301ad5 100644
--- a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp
+++ b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp
@@ -33,6 +33,7 @@ MVT WebAssembly::parseMVT(StringRef Type) {
.Case("v2i64", MVT::v2i64)
.Case("funcref", MVT::funcref)
.Case("externref", MVT::externref)
+ .Case("exnref", MVT::exnref)
.Default(MVT::INVALID_SIMPLE_VALUE_TYPE);
}
@@ -57,6 +58,8 @@ wasm::ValType WebAssembly::toValType(MVT Type) {
return wasm::ValType::FUNCREF;
case MVT::externref:
return wasm::ValType::EXTERNREF;
+ case MVT::exnref:
+ return wasm::ValType::EXNREF;
default:
llvm_unreachable("unexpected type");
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index 3524abba8990a..958705d7c51a0 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -125,6 +125,8 @@ static char getInvokeSig(wasm::ValType VT) {
return 'F';
case wasm::ValType::EXTERNREF:
return 'X';
+ case wasm::ValType::EXNREF:
+ return 'E';
default:
llvm_unreachable("Unhandled wasm::ValType enum");
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
index 0159c44a79b76..3c6a29311a10e 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
@@ -100,6 +100,8 @@ static unsigned getDropOpcode(const TargetRegisterClass *RC) {
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");
}
@@ -119,6 +121,8 @@ static unsigned getLocalGetOpcode(const TargetRegisterClass *RC) {
return WebAssembly::LOCAL_GET_FUNCREF;
if (RC == &WebAssembly::EXTERNREFRegClass)
return WebAssembly::LOCAL_GET_EXTERNREF;
+ if (RC == &WebAssembly::EXNREFRegClass)
+ return WebAssembly::LOCAL_GET_EXNREF;
llvm_unreachable("Unexpected register class");
}
@@ -138,6 +142,8 @@ static unsigned getLocalSetOpcode(const TargetRegisterClass *RC) {
return WebAssembly::LOCAL_SET_FUNCREF;
if (RC == &WebAssembly::EXTERNREFRegClass)
return WebAssembly::LOCAL_SET_EXTERNREF;
+ if (RC == &WebAssembly::EXNREFRegClass)
+ return WebAssembly::LOCAL_SET_EXNREF;
llvm_unreachable("Unexpected register class");
}
@@ -157,6 +163,8 @@ static unsigned getLocalTeeOpcode(const TargetRegisterClass *RC) {
return WebAssembly::LOCAL_TEE_FUNCREF;
if (RC == &WebAssembly::EXTERNREFRegClass)
return WebAssembly::LOCAL_TEE_EXTERNREF;
+ if (RC == &WebAssembly::EXNREFRegClass)
+ return WebAssembly::LOCAL_TEE_EXNREF;
llvm_unreachable("Unexpected register class");
}
@@ -176,6 +184,8 @@ static MVT typeForRegClass(const TargetRegisterClass *RC) {
return MVT::funcref;
if (RC == &WebAssembly::EXTERNREFRegClass)
return MVT::externref;
+ if (RC == &WebAssembly::EXNREFRegClass)
+ return MVT::exnref;
llvm_unreachable("unrecognized register class");
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
index 1c62290704fe4..708e259d1a4cd 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
@@ -137,6 +137,10 @@ class WebAssemblyFastISel final : public FastISel {
if (Subtarget->hasReferenceTypes())
return VT;
break;
+ case MVT::exnref:
+ if (Subtarget->hasReferenceTypes() && Subtarget->hasExceptionHandling())
+ return VT;
+ break;
case MVT::f16:
return MVT::f32;
case MVT::v16i8:
@@ -717,6 +721,10 @@ bool WebAssemblyFastISel::fastLowerArguments() {
Opc = WebAssembly::ARGUMENT_externref;
RC = &WebAssembly::EXTERNREFRegClass;
break;
+ case MVT::exnref:
+ Opc = WebAssembly::ARGUMENT_exnref;
+ RC = &WebAssembly::EXNREFRegClass;
+ break;
default:
return false;
}
@@ -821,6 +829,9 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) {
case MVT::externref:
ResultReg = createResultReg(&WebAssembly::EXTERNREFRegClass);
break;
+ case MVT::exnref:
+ ResultReg = createResultReg(&WebAssembly::EXNREFRegClass);
+ break;
default:
return false;
}
@@ -960,6 +971,10 @@ bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
Opc = WebAssembly::SELECT_EXTERNREF;
RC = &WebAssembly::EXTERNREFRegClass;
break;
+ case MVT::exnref:
+ Opc = WebAssembly::SELECT_EXNREF;
+ RC = &WebAssembly::EXNREFRegClass;
+ break;
default:
return false;
}
@@ -1367,6 +1382,7 @@ bool WebAssemblyFastISel::selectRet(const Instruction *I) {
case MVT::v2f64:
case MVT::funcref:
case MVT::externref:
+ case MVT::exnref:
break;
default:
return false;
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index 527bb4c9fbea6..aeb6831c7f3b8 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -73,6 +73,9 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
if (Subtarget->hasReferenceTypes()) {
addRegisterClass(MVT::externref, &WebAssembly::EXTERNREFRegClass);
addRegisterClass(MVT::funcref, &WebAssembly::FUNCREFRegClass);
+ if (Subtarget->hasExceptionHandling()) {
+ addRegisterClass(MVT::exnref, &WebAssembly::EXNREFRegClass);
+ }
}
// Compute derived properties from the register classes.
computeRegisterProperties(Subtarget->getRegisterInfo());
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
index c1a5a45395e87..3d37eb2fa27bc 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
@@ -292,6 +292,7 @@ defm "": ARGUMENT<F32, f32>;
defm "": ARGUMENT<F64, f64>;
defm "": ARGUMENT<FUNCREF, funcref>;
defm "": ARGUMENT<EXTERNREF, externref>;
+defm "": ARGUMENT<EXNREF, exnref>;
// local.get and local.set are not generated by instruction selection; they
// are implied by virtual register uses and defs.
@@ -375,6 +376,8 @@ defm "" : LOCAL<F64, global_op32>;
defm "" : LOCAL<V128, global_op32>, Requires<[HasSIMD128]>;
defm "" : LOCAL<FUNCREF, global_op32>, Requires<[HasReferenceTypes]>;
defm "" : LOCAL<EXTERNREF, global_op32>, Requires<[HasReferenceTypes]>;
+defm "" : LOCAL<EXNREF, global_op32>,
+ Requires<[HasReferenceTypes, HasExceptionHandling]>;
let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in {
defm CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm),
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td
index 608963d588635..2654a09387fd4 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td
@@ -17,8 +17,9 @@ multiclass REF_I<WebAssemblyRegClass rc, ValueType vt, string ht> {
[(set rc:$dst, (!cast<Intrinsic>("int_wasm_ref_null_" # ht)))],
"ref.null_" # ht # "$dst",
"ref.null_" # ht,
- !cond(!eq(ht, "func") : 0xd070,
- !eq(ht, "extern") : 0xd06f)>,
+ !cond(!eq(ht, "func") : 0xd070,
+ !eq(ht, "extern") : 0xd06f,
+ !eq(ht, "exn") : 0xd069)>,
Requires<[HasReferenceTypes]>;
defm SELECT_#rc: I<(outs rc:$dst), (ins rc:$lhs, rc:$rhs, I32:$cond),
(outs), (ins),
@@ -37,8 +38,9 @@ multiclass REF_I<WebAssemblyRegClass rc, ValueType vt, string ht> {
defm "" : REF_I<FUNCREF, funcref, "func">;
defm "" : REF_I<EXTERNREF, externref, "extern">;
+defm "" : REF_I<EXNREF, exnref, "exn">;
-foreach rc = [FUNCREF, EXTERNREF] in {
+foreach rc = [FUNCREF, EXTERNREF, EXNREF] in {
def : Pat<(select (i32 (setne I32:$cond, 0)), rc:$lhs, rc:$rhs),
(!cast<Instruction>("SELECT_"#rc) rc:$lhs, rc:$rhs, I32:$cond)>;
def : Pat<(select (i32 (seteq I32:$cond, 0)), rc:$lhs, rc:$rhs),
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td
index 069ce5e3bc94a..02f0ab8577c3d 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td
@@ -64,6 +64,8 @@ multiclass TABLE<WebAssemblyRegClass rc, string suffix> {
defm "" : TABLE<FUNCREF, "funcref">, Requires<[HasReferenceTypes]>;
defm "" : TABLE<EXTERNREF, "externref">, Requires<[HasReferenceTypes]>;
+defm "" : TABLE<EXNREF, "exnref">,
+ Requires<[HasReferenceTypes, HasExceptionHandling]>;
def : Pat<(WebAssemblyTableSet mcsym:$table, i32:$idx, funcref:$r),
(TABLE_SET_FUNCREF mcsym:$table, i32:$idx, funcref:$r)>,
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
index ef174e1716ef1..d4edb6bf18d93 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
@@ -504,6 +504,8 @@ static unsigned getTeeOpcode(const TargetRegisterClass *RC) {
return WebAssembly::TEE_EXTERNREF;
if (RC == &WebAssembly::FUNCREFRegClass)
return WebAssembly::TEE_FUNCREF;
+ if (RC == &WebAssembly::EXNREFRegClass)
+ return WebAssembly::TEE_EXNREF;
llvm_unreachable("Unexpected register class");
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td
index ba2936b492a9a..38a276319c41d 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td
@@ -45,6 +45,7 @@ def V128_0: WebAssemblyReg<"%v128">;
def FUNCREF_0 : WebAssemblyReg<"%funcref.0">;
def EXTERNREF_0 : WebAssemblyReg<"%externref.0">;
+def EXNREF_0 : WebAssemblyReg<"%exnref.0">;
// The value stack "register". This is an opaque entity which serves to order
// uses and defs that must remain in LIFO order.
@@ -67,3 +68,4 @@ def V128 : WebAssemblyRegClass<[v4f32, v2f64, v2i64, v4i32, v16i8, v8i16], 128,
(add V128_0)>;
def FUNCREF : WebAssemblyRegClass<[funcref], 0, (add FUNCREF_0)>;
def EXTERNREF : WebAssemblyRegClass<[externref], 0, (add EXTERNREF_0)>;
+def EXNREF : WebAssemblyRegClass<[exnref], 0, (add EXNREF_0)>;
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp
index 60e872549f87d..5e7279808cce6 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp
@@ -175,6 +175,8 @@ unsigned WebAssembly::getCopyOpcodeForRegClass(const TargetRegisterClass *RC) {
return WebAssembly::COPY_FUNCREF;
case WebAssembly::EXTERNREFRegClassID:
return WebAssembly::COPY_EXTERNREF;
+ case WebAssembly::EXNREFRegClassID:
+ return WebAssembly::COPY_EXNREF;
default:
llvm_unreachable("Unexpected register class");
}
diff --git a/llvm/test/CodeGen/WebAssembly/reg-argument.mir b/llvm/test/CodeGen/WebAssembly/reg-argument.mir
index 23e66dfc71fa1..a549990bdb0a2 100644
--- a/llvm/test/CodeGen/WebAssembly/reg-argument.mir
+++ b/llvm/test/CodeGen/WebAssembly/reg-argument.mir
@@ -68,3 +68,14 @@ body: |
%1:externref = ARGUMENT_externref 0, implicit $arguments
RETURN implicit-def $arguments
...
+---
+name: argument_exnref
+# CHECK-LABEL: argument_exnref
+body: |
+ ; CHECK-LABEL: bb.0:
+ ; CHECK-NEXT: %1:exnref = ARGUMENT_exnref 0
+ bb.0:
+ %0:i32 = CONST_I32 0, implicit-def $arguments
+ %1:exnref = ARGUMENT_exnref 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
index 31a5bfa63a4ea..763fe42d07b61 100644
--- a/llvm/test/CodeGen/WebAssembly/reg-copy.mir
+++ b/llvm/test/CodeGen/WebAssembly/reg-copy.mir
@@ -77,3 +77,14 @@ body: |
%0:externref = COPY %1:externref
RETURN implicit-def $arguments
...
+---
+name: copy_exnref
+# CHECK-LABEL: copy_exnref
+body: |
+ ; CHECK-LABEL: bb.0:
+ ; CHECK-NEXT: %0:exnref = COPY_EXNREF %1:exnref
+ ; CHECK-NEXT: RETURN
+ bb.0:
+ %0:exnref = COPY %1:exnref
+ RETURN implicit-def $arguments
+...
diff --git a/llvm/test/MC/WebAssembly/basic-assembly.s b/llvm/test/MC/WebAssembly/basic-assembly.s
index 769cd7edfa8a3..ac358c1b5c7a5 100644
--- a/llvm/test/MC/WebAssembly/basic-assembly.s
+++ b/llvm/test/MC/WebAssembly/basic-assembly.s
@@ -146,12 +146,14 @@ test0:
.ident "clang version 9.0.0 (trunk 364502) (llvm/trunk 364571)"
-.tabletype empty_eref_table, externref
-empty_eref_table:
+.tabletype empty_externref_table, externref
+empty_externref_table:
-.tabletype empty_fref_table, funcref
-empty_fref_table:
+.tabletype empty_funcref_table, funcref
+empty_funcref_table:
+.tabletype empty_exnref_table, exnref
+empty_exnref_table:
# CHECK: .text
# CHECK: .globaltype __stack_pointer, i32
@@ -283,8 +285,11 @@ empty_fref_table:
# CHECK-NEXT: .p2align 2
# CHECK-NEXT: .int32 test0
-# CHECK: .tabletype empty_eref_table, externref
-# CHECK-NEXT: empty_eref_table:
+# CHECK: .tabletype empty_externref_table, externref
+# CHECK-NEXT: empty_externref_table:
-# CHECK: .tabletype empty_fref_table, funcref
-# CHECK-NEXT: empty_fref_table:
+# CHECK: .tabletype empty_funcref_table, funcref
+# CHECK-NEXT: empty_funcref_table:
+
+# CHECK: .tabletype empty_exnref_table, exnref
+# CHECK-NEXT: empty_exnref_table:
diff --git a/llvm/test/MC/WebAssembly/reference-types.s b/llvm/test/MC/WebAssembly/reference-types.s
index ab3e3ee6b155b..2f8bfba68dcea 100644
--- a/llvm/test/MC/WebAssembly/reference-types.s
+++ b/llvm/test/MC/WebAssembly/reference-types.s
@@ -4,22 +4,27 @@
# CHECK-LABEL:ref_is_null:
# CHECK: ref.is_null # encoding: [0xd1]
ref_is_null:
- .functype ref_is_null () -> (i32, i32)
+ .functype ref_is_null () -> (i32, i32, i32)
ref.null_extern
ref.is_null
ref.null_func
ref.is_null
+ ref.null_exn
+ ref.is_null
end_function
# CHECK-LABEL: ref_null_test:
# CHECK: ref.null_func # encoding: [0xd0,0x70]
# CHECK: ref.null_extern # encoding: [0xd0,0x6f]
+# CHECK: ref.null_exn # encoding: [0xd0,0x69]
ref_null_test:
.functype ref_null_test () -> ()
ref.null_func
drop
ref.null_extern
drop
+ ref.null_exn
+ drop
end_function
# CHECK-LABEL: ref_sig_test_funcref:
@@ -36,9 +41,17 @@ ref_sig_test_externref:
local.get 0
end_function
+# CHECK-LABEL: ref_sig_test_exnref:
+# CHECK-NEXT: .functype ref_sig_test_exnref (exnref) -> (exnref)
+ref_sig_test_exnref:
+ .functype ref_sig_test_exnref (exnref) -> (exnref)
+ local.get 0
+ end_function
+
# CHECK-LABEL: ref_select_test:
# CHECK: funcref.select # encoding: [0x1b]
# CHECK: externref.select # encoding: [0x1b]
+# CHECK: exnref.select # encoding: [0x1b]
ref_select_test:
.functype ref_select_test () -> ()
ref.null_func
@@ -51,15 +64,24 @@ ref_select_test:
i32.const 0
externref.select
drop
+ ref.null_exn
+ ref.null_exn
+ i32.const 0
+ exnref.select
+ drop
end_function
# CHECK-LABEL: ref_block_test:
# CHECK: block funcref
# CHECK: block externref
+# CHECK: block exnref
ref_block_test:
- .functype ref_block_test () -> (externref, funcref)
+ .functype ref_block_test () -> (exnref, externref, funcref)
block funcref
block externref
+ block exnref
+ ref.null_exn
+ end_block
ref.null_extern
end_block
ref.null_func
diff --git a/llvm/test/MC/WebAssembly/type-checker-errors.s b/llvm/test/MC/WebAssembly/type-checker-errors.s
index 5e28d117501e9..d2841250137a8 100644
--- a/llvm/test/MC/WebAssembly/type-checker-errors.s
+++ b/llvm/test/MC/WebAssembly/type-checker-errors.s
@@ -215,6 +215,22 @@ table_fill_type_mismatch_3:
table.fill valid_table
end_function
+table_fill_type_mismatch_4:
+ .functype table_fill_type_mismatch_4 () -> ()
+ ref.null_exn
+ i32.const 1
+# CHECK: [[@LINE+1]]:3: error: popped exnref, expected externref
+ table.fill valid_table
+ end_function
+
+table_fill_type_mismatch_5:
+ .functype table_fill_type_mismatch_5 () -> ()
+ ref.null_exn
+ i32.const 1
+# CHECK: [[@LINE+1]]:3: error: popped exnref, expected externref
+ table.fill valid_table
+ end_function
+
table_grow_non_exist_table:
.functype table_grow_non_exist_table (externref, i32) -> (i32)
local.get 0
diff --git a/llvm/utils/TableGen/Common/CodeGenTarget.cpp b/llvm/utils/TableGen/Common/CodeGenTarget.cpp
index e1cf33e7f62ff..52d1dde587903 100644
--- a/llvm/utils/TableGen/Common/CodeGenTarget.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenTarget.cpp
@@ -269,6 +269,7 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::Untyped: return "MVT::Untyped";
case MVT::funcref: return "MVT::funcref";
case MVT::externref: return "MVT::externref";
+ case MVT::exnref: return "MVT::exnref";
default: llvm_unreachable("ILLEGAL VALUE TYPE!");
}
// clang-format on
>From 10d37817e4af60e0cf76527d577b1071b1a30127 Mon Sep 17 00:00:00 2001
From: Heejin Ahn <aheejin at gmail.com>
Date: Tue, 28 May 2024 18:34:12 +0000
Subject: [PATCH 2/2] Fix comment
---
llvm/lib/Object/WasmObjectFile.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp
index 872a1214d4f0e..23381955c60a8 100644
--- a/llvm/lib/Object/WasmObjectFile.cpp
+++ b/llvm/lib/Object/WasmObjectFile.cpp
@@ -177,8 +177,8 @@ static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
static wasm::ValType parseValType(WasmObjectFile::ReadContext &Ctx,
uint32_t Code) {
- // only directly encoded FUNCREF/EXTERNREF are supported
- // (not ref null func or ref null extern)
+ // only directly encoded FUNCREF/EXTERNREF/EXNREF are supported
+ // (not ref null func, ref null extern, or ref null exn)
switch (Code) {
case wasm::WASM_TYPE_I32:
case wasm::WASM_TYPE_I64:
More information about the llvm-commits
mailing list