Skip to content

Commit bd630d7

Browse files
authored
Implement extern.externalize and extern.internalize (#4975)
These new GC instructions infallibly convert between `extern` and `any` references now that those types are not in the same hierarchy.
1 parent 8108ce2 commit bd630d7

File tree

14 files changed

+171
-11
lines changed

14 files changed

+171
-11
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Current Trunk
2929
- HeapType::ext has been restored but is no longer a subtype of HeapType::any to
3030
match the latest updates in the GC spec. (#4898)
3131
- `i31ref` and `dataref` are now nullable to match the latest GC spec. (#4843)
32+
- Add support for `extern.externalize` and `extern.internalize`. (#4975)
3233

3334
v109
3435
----

scripts/fuzz_opt.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,10 @@ def is_git_repo():
270270
INITIAL_CONTENTS_IGNORE = [
271271
# not all relaxed SIMD instructions are implemented in the interpreter
272272
'relaxed-simd.wast',
273-
# TODO fuzzer and interpreter support for strings
273+
# TODO: fuzzer and interpreter support for strings
274274
'strings.wast',
275+
# TODO: fuzzer and interpreter support for extern conversions
276+
'extern-conversions.wast',
275277
# ignore DWARF because it is incompatible with multivalue atm
276278
'zlib.wasm',
277279
'cubescript.wasm',

scripts/gen-s-parser.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,8 @@
604604
("ref.as_func", "makeRefAs(s, RefAsFunc)"),
605605
("ref.as_data", "makeRefAs(s, RefAsData)"),
606606
("ref.as_i31", "makeRefAs(s, RefAsI31)"),
607+
("extern.internalize", "makeRefAs(s, ExternInternalize)"),
608+
("extern.externalize", "makeRefAs(s, ExternExternalize)"),
607609
("string.new_wtf8", "makeStringNew(s, StringNewWTF8)"),
608610
("string.new_wtf16", "makeStringNew(s, StringNewWTF16)"),
609611
("string.new_wtf8_array", "makeStringNew(s, StringNewWTF8Array)"),

src/gen-s-parser.inc

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,25 @@ switch (op[0]) {
185185
default: goto parse_error;
186186
}
187187
}
188-
case 'e':
189-
if (strcmp(op, "else") == 0) { return makeThenOrElse(s); }
190-
goto parse_error;
188+
case 'e': {
189+
switch (op[1]) {
190+
case 'l':
191+
if (strcmp(op, "else") == 0) { return makeThenOrElse(s); }
192+
goto parse_error;
193+
case 'x': {
194+
switch (op[7]) {
195+
case 'e':
196+
if (strcmp(op, "extern.externalize") == 0) { return makeRefAs(s, ExternExternalize); }
197+
goto parse_error;
198+
case 'i':
199+
if (strcmp(op, "extern.internalize") == 0) { return makeRefAs(s, ExternInternalize); }
200+
goto parse_error;
201+
default: goto parse_error;
202+
}
203+
}
204+
default: goto parse_error;
205+
}
206+
}
191207
case 'f': {
192208
switch (op[1]) {
193209
case '3': {
@@ -3816,13 +3832,37 @@ switch (op[0]) {
38163832
default: goto parse_error;
38173833
}
38183834
}
3819-
case 'e':
3820-
if (op == "else"sv) {
3821-
auto ret = makeThenOrElse(ctx, in);
3822-
CHECK_ERR(ret);
3823-
return *ret;
3835+
case 'e': {
3836+
switch (op[1]) {
3837+
case 'l':
3838+
if (op == "else"sv) {
3839+
auto ret = makeThenOrElse(ctx, in);
3840+
CHECK_ERR(ret);
3841+
return *ret;
3842+
}
3843+
goto parse_error;
3844+
case 'x': {
3845+
switch (op[7]) {
3846+
case 'e':
3847+
if (op == "extern.externalize"sv) {
3848+
auto ret = makeRefAs(ctx, in, ExternExternalize);
3849+
CHECK_ERR(ret);
3850+
return *ret;
3851+
}
3852+
goto parse_error;
3853+
case 'i':
3854+
if (op == "extern.internalize"sv) {
3855+
auto ret = makeRefAs(ctx, in, ExternInternalize);
3856+
CHECK_ERR(ret);
3857+
return *ret;
3858+
}
3859+
goto parse_error;
3860+
default: goto parse_error;
3861+
}
3862+
}
3863+
default: goto parse_error;
38243864
}
3825-
goto parse_error;
3865+
}
38263866
case 'f': {
38273867
switch (op[1]) {
38283868
case '3': {

src/ir/effects.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,10 @@ class EffectAnalyzer {
726726
parent.implicitTrap = true;
727727
}
728728
void visitRefAs(RefAs* curr) {
729+
if (curr->op == ExternInternalize || curr->op == ExternExternalize) {
730+
// These conversions are infallible.
731+
return;
732+
}
729733
// traps when the arg is not valid
730734
parent.implicitTrap = true;
731735
// Note: We could be more precise here and report the lack of a possible

src/passes/Print.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2214,6 +2214,12 @@ struct PrintExpressionContents
22142214
case RefAsI31:
22152215
printMedium(o, "ref.as_i31");
22162216
break;
2217+
case ExternInternalize:
2218+
printMedium(o, "extern.internalize");
2219+
break;
2220+
case ExternExternalize:
2221+
printMedium(o, "extern.externalize");
2222+
break;
22172223
default:
22182224
WASM_UNREACHABLE("invalid ref.is_*");
22192225
}

src/wasm-binary.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,8 @@ enum ASTNodes {
11251125
BrOnNonFunc = 0x63,
11261126
BrOnNonData = 0x64,
11271127
BrOnNonI31 = 0x65,
1128+
ExternInternalize = 0x70,
1129+
ExternExternalize = 0x71,
11281130
StringNewWTF8 = 0x80,
11291131
StringNewWTF16 = 0x81,
11301132
StringConst = 0x82,

src/wasm-interpreter.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1874,6 +1874,9 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
18741874
trap("not an i31");
18751875
}
18761876
break;
1877+
case ExternInternalize:
1878+
case ExternExternalize:
1879+
WASM_UNREACHABLE("unimplemented extern conversion");
18771880
default:
18781881
WASM_UNREACHABLE("unimplemented ref.as_*");
18791882
}
@@ -2226,6 +2229,13 @@ class ConstantExpressionRunner : public ExpressionRunner<SubType> {
22262229
Flow visitStringSliceIter(StringSliceIter* curr) {
22272230
return Flow(NONCONSTANT_FLOW);
22282231
}
2232+
Flow visitRefAs(RefAs* curr) {
2233+
// TODO: Remove this once interpretation is implemented.
2234+
if (curr->op == ExternInternalize || curr->op == ExternExternalize) {
2235+
return Flow(NONCONSTANT_FLOW);
2236+
}
2237+
return ExpressionRunner<SubType>::visitRefAs(curr);
2238+
}
22292239

22302240
void trap(const char* why) override { throw NonconstantException(); }
22312241

src/wasm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,8 @@ enum RefAsOp {
568568
RefAsFunc,
569569
RefAsData,
570570
RefAsI31,
571+
ExternInternalize,
572+
ExternExternalize,
571573
};
572574

573575
enum BrOnOp {

src/wasm/wasm-binary.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3978,7 +3978,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
39783978
}
39793979
if (opcode == BinaryConsts::RefAsFunc ||
39803980
opcode == BinaryConsts::RefAsData ||
3981-
opcode == BinaryConsts::RefAsI31) {
3981+
opcode == BinaryConsts::RefAsI31 ||
3982+
opcode == BinaryConsts::ExternInternalize ||
3983+
opcode == BinaryConsts::ExternExternalize) {
39823984
visitRefAs((curr = allocator.alloc<RefAs>())->cast<RefAs>(), opcode);
39833985
break;
39843986
}
@@ -7347,6 +7349,12 @@ void WasmBinaryBuilder::visitRefAs(RefAs* curr, uint8_t code) {
73477349
case BinaryConsts::RefAsI31:
73487350
curr->op = RefAsI31;
73497351
break;
7352+
case BinaryConsts::ExternInternalize:
7353+
curr->op = ExternInternalize;
7354+
break;
7355+
case BinaryConsts::ExternExternalize:
7356+
curr->op = ExternExternalize;
7357+
break;
73507358
default:
73517359
WASM_UNREACHABLE("invalid code for ref.as_*");
73527360
}
@@ -7356,6 +7364,7 @@ void WasmBinaryBuilder::visitRefAs(RefAs* curr, uint8_t code) {
73567364
}
73577365
curr->finalize();
73587366
}
7367+
73597368
void WasmBinaryBuilder::throwError(std::string text) {
73607369
throw ParseException(text, 0, pos);
73617370
}

0 commit comments

Comments
 (0)