Skip to content

Commit 6991373

Browse files
aheejinvg0204
authored andcommitted
[WebAssembly] Add exnref type (llvm#93586)
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
1 parent ca3142a commit 6991373

27 files changed

+188
-23
lines changed

lld/wasm/WriterUtils.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ std::string toString(ValType type) {
3535
return "funcref";
3636
case ValType::EXTERNREF:
3737
return "externref";
38+
case ValType::EXNREF:
39+
return "exnref";
3840
case ValType::OTHERREF:
3941
return "otherref";
4042
}

llvm/include/llvm/BinaryFormat/Wasm.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,16 @@ enum : unsigned {
5858
WASM_TYPE_V128 = 0x7B,
5959
WASM_TYPE_NULLFUNCREF = 0x73,
6060
WASM_TYPE_NULLEXTERNREF = 0x72,
61+
WASM_TYPE_NULLEXNREF = 0x74,
6162
WASM_TYPE_NULLREF = 0x71,
6263
WASM_TYPE_FUNCREF = 0x70,
6364
WASM_TYPE_EXTERNREF = 0x6F,
65+
WASM_TYPE_EXNREF = 0x69,
6466
WASM_TYPE_ANYREF = 0x6E,
6567
WASM_TYPE_EQREF = 0x6D,
6668
WASM_TYPE_I31REF = 0x6C,
6769
WASM_TYPE_STRUCTREF = 0x6B,
6870
WASM_TYPE_ARRAYREF = 0x6A,
69-
WASM_TYPE_EXNREF = 0x69,
7071
WASM_TYPE_NONNULLABLE = 0x64,
7172
WASM_TYPE_NULLABLE = 0x63,
7273
WASM_TYPE_FUNC = 0x60,
@@ -261,8 +262,9 @@ enum class ValType {
261262
V128 = WASM_TYPE_V128,
262263
FUNCREF = WASM_TYPE_FUNCREF,
263264
EXTERNREF = WASM_TYPE_EXTERNREF,
265+
EXNREF = WASM_TYPE_EXNREF,
264266
// Unmodeled value types include ref types with heap types other than
265-
// func or extern, and type-specialized funcrefs
267+
// func, extern or exn, and type-specialized funcrefs
266268
OTHERREF = 0xff,
267269
};
268270

@@ -410,7 +412,8 @@ struct WasmDataSegment {
410412
// 1) Does not model passive or declarative segments (Segment will end up with
411413
// an Offset field of i32.const 0)
412414
// 2) Does not model init exprs (Segment will get an empty Functions list)
413-
// 2) Does not model types other than basic funcref/externref (see ValType)
415+
// 3) Does not model types other than basic funcref/externref/exnref (see
416+
// ValType)
414417
struct WasmElemSegment {
415418
uint32_t Flags;
416419
uint32_t TableNumber;

llvm/include/llvm/CodeGen/ValueTypes.td

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -280,11 +280,12 @@ def untyped : ValueType<8, 193> { // Produces an untyped value
280280
}
281281
def funcref : ValueType<0, 194>; // WebAssembly's funcref type
282282
def externref : ValueType<0, 195>; // WebAssembly's externref type
283-
def x86amx : ValueType<8192, 196>; // X86 AMX value
284-
def i64x8 : ValueType<512, 197>; // 8 Consecutive GPRs (AArch64)
283+
def exnref : ValueType<0, 196>; // WebAssembly's exnref type
284+
def x86amx : ValueType<8192, 197>; // X86 AMX value
285+
def i64x8 : ValueType<512, 198>; // 8 Consecutive GPRs (AArch64)
285286
def aarch64svcount
286-
: ValueType<16, 198>; // AArch64 predicate-as-counter
287-
def spirvbuiltin : ValueType<0, 199>; // SPIR-V's builtin type
287+
: ValueType<16, 199>; // AArch64 predicate-as-counter
288+
def spirvbuiltin : ValueType<0, 200>; // SPIR-V's builtin type
288289

289290
def token : ValueType<0, 248>; // TokenTy
290291
def MetadataVT : ValueType<0, 249> { // Metadata

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ def IIT_PPCF128 : IIT_VT<ppcf128, 52>;
316316
def IIT_V3 : IIT_Vec<3, 53>;
317317
def IIT_EXTERNREF : IIT_VT<externref, 54>;
318318
def IIT_FUNCREF : IIT_VT<funcref, 55>;
319+
def IIT_EXNREF: IIT_VT<exnref, 56>;
319320
def IIT_I2 : IIT_Int<2, 57>;
320321
def IIT_I4 : IIT_Int<4, 58>;
321322
def IIT_AARCH64_SVCOUNT : IIT_VT<aarch64svcount, 59>;
@@ -581,6 +582,7 @@ def llvm_vararg_ty : LLVMType<isVoid>; // this means vararg here
581582

582583
def llvm_externref_ty : LLVMType<externref>;
583584
def llvm_funcref_ty : LLVMType<funcref>;
585+
def llvm_exnref_ty : LLVMType<exnref>;
584586

585587
//===----------------------------------------------------------------------===//
586588

llvm/include/llvm/IR/IntrinsicsWebAssembly.td

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,17 @@ def int_wasm_ref_null_extern :
3131
DefaultAttrsIntrinsic<[llvm_externref_ty], [], [IntrNoMem]>;
3232
def int_wasm_ref_null_func :
3333
DefaultAttrsIntrinsic<[llvm_funcref_ty], [], [IntrNoMem]>;
34+
def int_wasm_ref_null_exn:
35+
DefaultAttrsIntrinsic<[llvm_exnref_ty], [], [IntrNoMem]>;
3436
def int_wasm_ref_is_null_extern :
3537
DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_externref_ty], [IntrNoMem],
3638
"llvm.wasm.ref.is_null.extern">;
3739
def int_wasm_ref_is_null_func :
3840
DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_funcref_ty],
3941
[IntrNoMem], "llvm.wasm.ref.is_null.func">;
42+
def int_wasm_ref_is_null_exn :
43+
DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_exnref_ty], [IntrNoMem],
44+
"llvm.wasm.ref.is_null.exn">;
4045

4146
//===----------------------------------------------------------------------===//
4247
// Table intrinsics
@@ -47,13 +52,19 @@ def int_wasm_table_set_externref :
4752
def int_wasm_table_set_funcref :
4853
DefaultAttrsIntrinsic<[], [llvm_table_ty, llvm_i32_ty, llvm_funcref_ty],
4954
[IntrWriteMem]>;
55+
def int_wasm_table_set_exnref :
56+
DefaultAttrsIntrinsic<[], [llvm_table_ty, llvm_i32_ty, llvm_exnref_ty],
57+
[IntrWriteMem]>;
5058

5159
def int_wasm_table_get_externref :
5260
DefaultAttrsIntrinsic<[llvm_externref_ty], [llvm_table_ty, llvm_i32_ty],
5361
[IntrReadMem]>;
5462
def int_wasm_table_get_funcref :
5563
DefaultAttrsIntrinsic<[llvm_funcref_ty], [llvm_table_ty, llvm_i32_ty],
5664
[IntrReadMem]>;
65+
def int_wasm_table_get_exnref :
66+
DefaultAttrsIntrinsic<[llvm_exnref_ty], [llvm_table_ty, llvm_i32_ty],
67+
[IntrReadMem]>;
5768

5869
// Query the current table size, and increase the current table size.
5970
def int_wasm_table_size :
@@ -68,6 +79,9 @@ def int_wasm_table_grow_externref :
6879
def int_wasm_table_grow_funcref :
6980
DefaultAttrsIntrinsic<[llvm_i32_ty],
7081
[llvm_table_ty, llvm_funcref_ty, llvm_i32_ty], []>;
82+
def int_wasm_table_grow_exnref :
83+
DefaultAttrsIntrinsic<[llvm_i32_ty],
84+
[llvm_table_ty, llvm_exnref_ty, llvm_i32_ty], []>;
7185
def int_wasm_table_fill_externref :
7286
DefaultAttrsIntrinsic<[],
7387
[llvm_table_ty, llvm_i32_ty, llvm_externref_ty,
@@ -76,6 +90,10 @@ def int_wasm_table_fill_funcref :
7690
DefaultAttrsIntrinsic<[],
7791
[llvm_table_ty, llvm_i32_ty, llvm_funcref_ty,
7892
llvm_i32_ty], []>;
93+
def int_wasm_table_fill_exnref :
94+
DefaultAttrsIntrinsic<[],
95+
[llvm_table_ty, llvm_i32_ty, llvm_exnref_ty,
96+
llvm_i32_ty], []>;
7997

8098
//===----------------------------------------------------------------------===//
8199
// Trapping float-to-int conversions

llvm/lib/CodeGen/ValueTypes.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ std::string EVT::getEVTString() const {
181181
case MVT::Metadata: return "Metadata";
182182
case MVT::Untyped: return "Untyped";
183183
case MVT::funcref: return "funcref";
184+
case MVT::exnref: return "exnref";
184185
case MVT::externref: return "externref";
185186
case MVT::aarch64svcount:
186187
return "aarch64svcount";

llvm/lib/Object/WasmObjectFile.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
177177

178178
static wasm::ValType parseValType(WasmObjectFile::ReadContext &Ctx,
179179
uint32_t Code) {
180-
// only directly encoded FUNCREF/EXTERNREF are supported
181-
// (not ref null func or ref null extern)
180+
// only directly encoded FUNCREF/EXTERNREF/EXNREF are supported
181+
// (not ref null func, ref null extern, or ref null exn)
182182
switch (Code) {
183183
case wasm::WASM_TYPE_I32:
184184
case wasm::WASM_TYPE_I64:
@@ -187,6 +187,7 @@ static wasm::ValType parseValType(WasmObjectFile::ReadContext &Ctx,
187187
case wasm::WASM_TYPE_V128:
188188
case wasm::WASM_TYPE_FUNCREF:
189189
case wasm::WASM_TYPE_EXTERNREF:
190+
case wasm::WASM_TYPE_EXNREF:
190191
return wasm::ValType(Code);
191192
}
192193
if (Code == wasm::WASM_TYPE_NULLABLE || Code == wasm::WASM_TYPE_NONNULLABLE) {
@@ -1288,6 +1289,7 @@ Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
12881289
auto ElemType = Im.Table.ElemType;
12891290
if (ElemType != wasm::ValType::FUNCREF &&
12901291
ElemType != wasm::ValType::EXTERNREF &&
1292+
ElemType != wasm::ValType::EXNREF &&
12911293
ElemType != wasm::ValType::OTHERREF)
12921294
return make_error<GenericBinaryError>("invalid table element type",
12931295
object_error::parse_failed);
@@ -1346,6 +1348,7 @@ Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
13461348
auto ElemType = Tables.back().Type.ElemType;
13471349
if (ElemType != wasm::ValType::FUNCREF &&
13481350
ElemType != wasm::ValType::EXTERNREF &&
1351+
ElemType != wasm::ValType::EXNREF &&
13491352
ElemType != wasm::ValType::OTHERREF) {
13501353
return make_error<GenericBinaryError>("invalid table element type",
13511354
object_error::parse_failed);
@@ -1680,6 +1683,7 @@ Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
16801683
Segment.ElemKind = parseValType(Ctx, ElemKind);
16811684
if (Segment.ElemKind != wasm::ValType::FUNCREF &&
16821685
Segment.ElemKind != wasm::ValType::EXTERNREF &&
1686+
Segment.ElemKind != wasm::ValType::EXNREF &&
16831687
Segment.ElemKind != wasm::ValType::OTHERREF) {
16841688
return make_error<GenericBinaryError>("invalid elem type",
16851689
object_error::parse_failed);

llvm/lib/ObjectYAML/WasmYAML.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,7 @@ void ScalarEnumerationTraits<WasmYAML::ValueType>::enumeration(
606606
ECase(V128);
607607
ECase(FUNCREF);
608608
ECase(EXTERNREF);
609+
ECase(EXNREF);
609610
ECase(OTHERREF);
610611
#undef ECase
611612
}
@@ -640,6 +641,7 @@ void ScalarEnumerationTraits<WasmYAML::TableType>::enumeration(
640641
#define ECase(X) IO.enumCase(Type, #X, CONCAT(X));
641642
ECase(FUNCREF);
642643
ECase(EXTERNREF);
644+
ECase(EXNREF);
643645
ECase(OTHERREF);
644646
#undef ECase
645647
}

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,8 @@ inline bool isArgument(unsigned Opc) {
355355
case WebAssembly::ARGUMENT_funcref_S:
356356
case WebAssembly::ARGUMENT_externref:
357357
case WebAssembly::ARGUMENT_externref_S:
358+
case WebAssembly::ARGUMENT_exnref:
359+
case WebAssembly::ARGUMENT_exnref_S:
358360
return true;
359361
default:
360362
return false;
@@ -377,6 +379,8 @@ inline bool isCopy(unsigned Opc) {
377379
case WebAssembly::COPY_FUNCREF_S:
378380
case WebAssembly::COPY_EXTERNREF:
379381
case WebAssembly::COPY_EXTERNREF_S:
382+
case WebAssembly::COPY_EXNREF:
383+
case WebAssembly::COPY_EXNREF_S:
380384
return true;
381385
default:
382386
return false;
@@ -399,6 +403,8 @@ inline bool isTee(unsigned Opc) {
399403
case WebAssembly::TEE_FUNCREF_S:
400404
case WebAssembly::TEE_EXTERNREF:
401405
case WebAssembly::TEE_EXTERNREF_S:
406+
case WebAssembly::TEE_EXNREF:
407+
case WebAssembly::TEE_EXNREF_S:
402408
return true;
403409
default:
404410
return false;
@@ -489,6 +495,8 @@ inline bool isLocalGet(unsigned Opc) {
489495
case WebAssembly::LOCAL_GET_FUNCREF_S:
490496
case WebAssembly::LOCAL_GET_EXTERNREF:
491497
case WebAssembly::LOCAL_GET_EXTERNREF_S:
498+
case WebAssembly::LOCAL_GET_EXNREF:
499+
case WebAssembly::LOCAL_GET_EXNREF_S:
492500
return true;
493501
default:
494502
return false;
@@ -511,6 +519,8 @@ inline bool isLocalSet(unsigned Opc) {
511519
case WebAssembly::LOCAL_SET_FUNCREF_S:
512520
case WebAssembly::LOCAL_SET_EXTERNREF:
513521
case WebAssembly::LOCAL_SET_EXTERNREF_S:
522+
case WebAssembly::LOCAL_SET_EXNREF:
523+
case WebAssembly::LOCAL_SET_EXNREF_S:
514524
return true;
515525
default:
516526
return false;
@@ -533,6 +543,8 @@ inline bool isLocalTee(unsigned Opc) {
533543
case WebAssembly::LOCAL_TEE_FUNCREF_S:
534544
case WebAssembly::LOCAL_TEE_EXTERNREF:
535545
case WebAssembly::LOCAL_TEE_EXTERNREF_S:
546+
case WebAssembly::LOCAL_TEE_EXNREF:
547+
case WebAssembly::LOCAL_TEE_EXNREF_S:
536548
return true;
537549
default:
538550
return false;

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTypeUtilities.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ std::optional<wasm::ValType> WebAssembly::parseType(StringRef Type) {
2727
wasm::ValType::V128)
2828
.Case("funcref", wasm::ValType::FUNCREF)
2929
.Case("externref", wasm::ValType::EXTERNREF)
30+
.Case("exnref", wasm::ValType::EXNREF)
3031
.Default(std::nullopt);
3132
}
3233

@@ -40,6 +41,7 @@ WebAssembly::BlockType WebAssembly::parseBlockType(StringRef Type) {
4041
.Case("v128", WebAssembly::BlockType::V128)
4142
.Case("funcref", WebAssembly::BlockType::Funcref)
4243
.Case("externref", WebAssembly::BlockType::Externref)
44+
.Case("exnref", WebAssembly::BlockType::Exnref)
4345
.Case("void", WebAssembly::BlockType::Void)
4446
.Default(WebAssembly::BlockType::Invalid);
4547
}
@@ -62,6 +64,8 @@ const char *WebAssembly::anyTypeToString(unsigned Type) {
6264
return "funcref";
6365
case wasm::WASM_TYPE_EXTERNREF:
6466
return "externref";
67+
case wasm::WASM_TYPE_EXNREF:
68+
return "exnref";
6569
case wasm::WASM_TYPE_FUNC:
6670
return "func";
6771
case wasm::WASM_TYPE_NORESULT:
@@ -110,6 +114,8 @@ wasm::ValType WebAssembly::regClassToValType(unsigned RC) {
110114
return wasm::ValType::FUNCREF;
111115
case WebAssembly::EXTERNREFRegClassID:
112116
return wasm::ValType::EXTERNREF;
117+
case WebAssembly::EXNREFRegClassID:
118+
return wasm::ValType::EXNREF;
113119
default:
114120
llvm_unreachable("unexpected type");
115121
}

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTypeUtilities.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ enum class BlockType : unsigned {
3232
V128 = unsigned(wasm::ValType::V128),
3333
Externref = unsigned(wasm::ValType::EXTERNREF),
3434
Funcref = unsigned(wasm::ValType::FUNCREF),
35+
Exnref = unsigned(wasm::ValType::EXNREF),
3536
// Multivalue blocks (and other non-void blocks) are only emitted when the
3637
// blocks will never be exited and are at the ends of functions (see
3738
// WebAssemblyCFGStackify::fixEndsAtEndOfFunction). They also are never made
@@ -41,7 +42,8 @@ enum class BlockType : unsigned {
4142
};
4243

4344
inline bool isRefType(wasm::ValType Type) {
44-
return Type == wasm::ValType::EXTERNREF || Type == wasm::ValType::FUNCREF;
45+
return Type == wasm::ValType::EXTERNREF || Type == wasm::ValType::FUNCREF ||
46+
Type == wasm::ValType::EXNREF;
4547
}
4648

4749
// Convert ValType or a list/signature of ValTypes to a string.

llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ MVT WebAssembly::parseMVT(StringRef Type) {
3333
.Case("v2i64", MVT::v2i64)
3434
.Case("funcref", MVT::funcref)
3535
.Case("externref", MVT::externref)
36+
.Case("exnref", MVT::exnref)
3637
.Default(MVT::INVALID_SIMPLE_VALUE_TYPE);
3738
}
3839

@@ -58,6 +59,8 @@ wasm::ValType WebAssembly::toValType(MVT Type) {
5859
return wasm::ValType::FUNCREF;
5960
case MVT::externref:
6061
return wasm::ValType::EXTERNREF;
62+
case MVT::exnref:
63+
return wasm::ValType::EXNREF;
6164
default:
6265
llvm_unreachable("unexpected type");
6366
}

llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ static char getInvokeSig(wasm::ValType VT) {
125125
return 'F';
126126
case wasm::ValType::EXTERNREF:
127127
return 'X';
128+
case wasm::ValType::EXNREF:
129+
return 'E';
128130
default:
129131
llvm_unreachable("Unhandled wasm::ValType enum");
130132
}

llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ static unsigned getDropOpcode(const TargetRegisterClass *RC) {
100100
return WebAssembly::DROP_FUNCREF;
101101
if (RC == &WebAssembly::EXTERNREFRegClass)
102102
return WebAssembly::DROP_EXTERNREF;
103+
if (RC == &WebAssembly::EXNREFRegClass)
104+
return WebAssembly::DROP_EXNREF;
103105
llvm_unreachable("Unexpected register class");
104106
}
105107

@@ -119,6 +121,8 @@ static unsigned getLocalGetOpcode(const TargetRegisterClass *RC) {
119121
return WebAssembly::LOCAL_GET_FUNCREF;
120122
if (RC == &WebAssembly::EXTERNREFRegClass)
121123
return WebAssembly::LOCAL_GET_EXTERNREF;
124+
if (RC == &WebAssembly::EXNREFRegClass)
125+
return WebAssembly::LOCAL_GET_EXNREF;
122126
llvm_unreachable("Unexpected register class");
123127
}
124128

@@ -138,6 +142,8 @@ static unsigned getLocalSetOpcode(const TargetRegisterClass *RC) {
138142
return WebAssembly::LOCAL_SET_FUNCREF;
139143
if (RC == &WebAssembly::EXTERNREFRegClass)
140144
return WebAssembly::LOCAL_SET_EXTERNREF;
145+
if (RC == &WebAssembly::EXNREFRegClass)
146+
return WebAssembly::LOCAL_SET_EXNREF;
141147
llvm_unreachable("Unexpected register class");
142148
}
143149

@@ -157,6 +163,8 @@ static unsigned getLocalTeeOpcode(const TargetRegisterClass *RC) {
157163
return WebAssembly::LOCAL_TEE_FUNCREF;
158164
if (RC == &WebAssembly::EXTERNREFRegClass)
159165
return WebAssembly::LOCAL_TEE_EXTERNREF;
166+
if (RC == &WebAssembly::EXNREFRegClass)
167+
return WebAssembly::LOCAL_TEE_EXNREF;
160168
llvm_unreachable("Unexpected register class");
161169
}
162170

@@ -176,6 +184,8 @@ static MVT typeForRegClass(const TargetRegisterClass *RC) {
176184
return MVT::funcref;
177185
if (RC == &WebAssembly::EXTERNREFRegClass)
178186
return MVT::externref;
187+
if (RC == &WebAssembly::EXNREFRegClass)
188+
return MVT::exnref;
179189
llvm_unreachable("unrecognized register class");
180190
}
181191

0 commit comments

Comments
 (0)