-
Notifications
You must be signed in to change notification settings - Fork 13.7k
[WebAssembly] Add exnref type #93586
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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
@llvm/pr-subscribers-lld-wasm @llvm/pr-subscribers-objectyaml Author: Heejin Ahn (aheejin) ChangesThis adds (back) the exnref type restored in the new EH proposal adopted in Oct 2023 CG meeting: Patch is 32.31 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/93586.diff 28 Files Affected:
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) {
...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
generally looks good, just a couple of questions
@@ -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: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also update the comment on line 180 above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -137,6 +137,10 @@ class WebAssemblyFastISel final : public FastISel { | |||
if (Subtarget->hasReferenceTypes()) | |||
return VT; | |||
break; | |||
case MVT::exnref: | |||
if (Subtarget->hasReferenceTypes() && Subtarget->hasExceptionHandling()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just noticed it here but this is more of a general question: should we just always assume that hasExceptionHandling will imply hasReferenceTypes (and maybe put some assertions somewhere in addition to whatever user-facing errors we have) rather than always having to test for both features?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can assume that if we call this from clang (#91299). It may not be the case if someone manually calls llc
or wasm-ld
(in case of LTO). But even in those cases it should error out, so I guess that's a reasonable thing to do. But it's not that we can simply check that in WebAssemblyTargetMachine
because each bitcode function can have different set of features, which are coalesced in CoalesceFeaturesAndStripAtomics. But that is a pass that runs as a part of pass manager pipeline so we can't simply check it with an if
in WebAssemblyTargetMachine
, which was the reason I did something like #88916.
ref.null_extern | ||
ref.is_null | ||
ref.null_func | ||
ref.is_null | ||
ref.null_exn | ||
ref.is_null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see any CHECK expectations for this (or for null func). I assume this is just because it's sufficient to check the encoding once and the rest is to make sure the type check passes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It only had one check line before:
# CHECK: ref.is_null # encoding: [0xd1] |
I guess it was written that way because the encoding for ref.is_null
is the same regardless of what type it takes. And encodings for ref.null_[func/extern/exn]
is checked in ref_null_test
below.
also a general question: will we actually need to use a table of exnrefs to compile C++ exceptions (I think not, right?). I guess that also means we don't need to add support for representing exnrefs in LLVM IR (to go along with the existing funcref/externref support), at least for now. |
No we don't need it, but in spec it should be possible. That's kind of the reason I added a couple very minimal
That's why I didn't add it here. Also it requires a new |
You can test this locally with the following command:git-clang-format --diff 08de0b3cf54e4998799673f835e9a7d5ead8efab ea3ee65684e69c56fc2c6d151875c4f71f35f31f -- lld/wasm/WriterUtils.cpp llvm/include/llvm/BinaryFormat/Wasm.h llvm/lib/CodeGen/ValueTypes.cpp llvm/lib/Object/WasmObjectFile.cpp llvm/lib/ObjectYAML/WasmYAML.cpp llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTypeUtilities.cpp llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTypeUtilities.h llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp View the diff from clang-format here.diff --git a/llvm/lib/CodeGen/ValueTypes.cpp b/llvm/lib/CodeGen/ValueTypes.cpp
index df1c02c3dc..a991c6ecd1 100644
--- a/llvm/lib/CodeGen/ValueTypes.cpp
+++ b/llvm/lib/CodeGen/ValueTypes.cpp
@@ -181,7 +181,8 @@ 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::exnref:
+ return "exnref";
case MVT::externref: return "externref";
case MVT::aarch64svcount:
return "aarch64svcount";
|
@@ -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"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This causes a clang-format error, but this is in line with what's there, so won't fix it
This was added in #93586 but caused a compilation warning and is not used anyway.
Sorry, this caused a compilation warning: llvm-project/llvm/lib/IR/Function.cpp:1091:11: warning: enumeration value 'IIT_EXNREF' not handled in switch [-Wswitch]
1091 | switch (Info) {
| ^~~~
1 warning generated. which should be fixed by 6f529aa. |
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
This was added in llvm#93586 but caused a compilation warning and is not used anyway.
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