Skip to content

Commit b7b1d0d

Browse files
authored
Update br_on_cast binary and text format (#5734)
The final versions of the br_on_cast and br_on_cast_fail instructions have two reference type annotations: one for the input type and one for the cast target type. In the binary format, this is represented as a flags byte followed by two encoded heap types. Since these instructions have been in flux for a while, do not attempt to maintain backward compatibility with older versions of the instructions. Instead, upgrade all of the tests at once to use the new versions of the instructions. Drop some binary tests of deprecated instruction encodings that would be more effort to update than they're worth.
1 parent e42a586 commit b7b1d0d

24 files changed

+108
-179
lines changed

src/ir/module-utils.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ struct CodeScanner
9191
counts.note(cast->castType);
9292
} else if (auto* cast = curr->dynCast<BrOn>()) {
9393
if (cast->op == BrOnCast || cast->op == BrOnCastFail) {
94+
counts.note(cast->ref->type);
9495
counts.note(cast->castType);
9596
}
9697
} else if (auto* get = curr->dynCast<StructGet>()) {

src/passes/Print.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2172,10 +2172,9 @@ struct PrintExpressionContents
21722172
printMedium(o, "br_on_cast ");
21732173
printName(curr->name, o);
21742174
o << ' ';
2175-
if (curr->castType.isNullable()) {
2176-
printMedium(o, "null ");
2177-
}
2178-
printHeapType(o, curr->castType.getHeapType(), wasm);
2175+
printType(o, curr->ref->type, wasm);
2176+
o << ' ';
2177+
printType(o, curr->castType, wasm);
21792178
return;
21802179
case BrOnCastFail:
21812180
// TODO: These instructions are deprecated, so stop emitting them.
@@ -2197,10 +2196,9 @@ struct PrintExpressionContents
21972196
printMedium(o, "br_on_cast_fail ");
21982197
printName(curr->name, o);
21992198
o << ' ';
2200-
if (curr->castType.isNullable()) {
2201-
printMedium(o, "null ");
2202-
}
2203-
printHeapType(o, curr->castType.getHeapType(), wasm);
2199+
printType(o, curr->ref->type, wasm);
2200+
o << ' ';
2201+
printType(o, curr->castType, wasm);
22042202
return;
22052203
}
22062204
WASM_UNREACHABLE("Unexpected br_on* op");

src/wasm-binary.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,16 +1119,12 @@ enum ASTNodes {
11191119
I31GetU = 0x22,
11201120
RefTest = 0x40,
11211121
RefCast = 0x41,
1122-
BrOnCast = 0x42,
1123-
BrOnCastFail = 0x43,
1122+
BrOnCast = 0x4e,
1123+
BrOnCastFail = 0x4f,
11241124
RefTestStatic = 0x44,
11251125
RefCastStatic = 0x45,
1126-
BrOnCastStatic = 0x46,
1127-
BrOnCastStaticFail = 0x47,
11281126
RefTestNull = 0x48,
11291127
RefCastNull = 0x49,
1130-
BrOnCastNull = 0x4a,
1131-
BrOnCastFailNull = 0x4b,
11321128
RefCastNop = 0x4c,
11331129
RefAsFunc = 0x58,
11341130
RefAsI31 = 0x5a,

src/wasm/wasm-binary.cpp

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7034,14 +7034,10 @@ bool WasmBinaryBuilder::maybeVisitBrOn(Expression*& out, uint32_t code) {
70347034
case BinaryConsts::BrOnNonNull:
70357035
op = BrOnNonNull;
70367036
break;
7037-
case BinaryConsts::BrOnCastStatic:
70387037
case BinaryConsts::BrOnCast:
7039-
case BinaryConsts::BrOnCastNull:
70407038
op = BrOnCast;
70417039
break;
7042-
case BinaryConsts::BrOnCastStaticFail:
70437040
case BinaryConsts::BrOnCastFail:
7044-
case BinaryConsts::BrOnCastFailNull:
70457041
op = BrOnCastFail;
70467042
break;
70477043
case BinaryConsts::BrOnFunc:
@@ -7063,18 +7059,24 @@ bool WasmBinaryBuilder::maybeVisitBrOn(Expression*& out, uint32_t code) {
70637059
default:
70647060
return false;
70657061
}
7066-
auto name = getBreakTarget(getU32LEB()).name;
7067-
if (castType == Type::none && (op == BrOnCast || op == BrOnCastFail)) {
7068-
auto nullability = (code == BinaryConsts::BrOnCastNull ||
7069-
code == BinaryConsts::BrOnCastFailNull)
7070-
? Nullable
7071-
: NonNullable;
7072-
bool legacy = code == BinaryConsts::BrOnCastStatic ||
7073-
code == BinaryConsts::BrOnCastStaticFail;
7074-
auto type = legacy ? getIndexedHeapType() : getHeapType();
7075-
castType = Type(type, nullability);
7062+
uint8_t flags = 0;
7063+
if (op == BrOnCast || op == BrOnCastFail) {
7064+
flags = getInt8();
70767065
}
7066+
auto name = getBreakTarget(getU32LEB()).name;
70777067
auto* ref = popNonVoidExpression();
7068+
if (op == BrOnCast || op == BrOnCastFail) {
7069+
auto inputNullability = (flags & 1) ? Nullable : NonNullable;
7070+
auto castNullability = (flags & 2) ? Nullable : NonNullable;
7071+
auto inputHeapType = getHeapType();
7072+
auto castHeapType = getHeapType();
7073+
auto inputType = Type(inputHeapType, inputNullability);
7074+
castType = Type(castHeapType, castNullability);
7075+
if (!Type::isSubType(ref->type, inputType)) {
7076+
throwError(std::string("Invalid reference type for ") +
7077+
((op == BrOnCast) ? "br_on_cast" : "br_on_cast_fail"));
7078+
}
7079+
}
70787080
out = Builder(wasm).makeBrOn(op, name, ref, castType);
70797081
return true;
70807082
}

src/wasm/wasm-s-parser.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2892,16 +2892,16 @@ Expression* SExpressionWasmBuilder::makeBrOnCast(Element& s,
28922892
bool onFail) {
28932893
int i = 1;
28942894
auto name = getLabel(*s[i++]);
2895+
std::optional<Type> inputType;
28952896
if (!castType) {
2896-
auto nullability = NonNullable;
2897-
if (s[i]->str().str == "null") {
2898-
nullability = Nullable;
2899-
++i;
2900-
}
2901-
auto type = parseHeapType(*s[i++]);
2902-
castType = Type(type, nullability);
2897+
inputType = elementToType(*s[i++]);
2898+
castType = elementToType(*s[i++]);
29032899
}
29042900
auto* ref = parseExpression(*s[i]);
2901+
if (inputType && !Type::isSubType(ref->type, *inputType)) {
2902+
throw ParseException(
2903+
"br_on_cast* ref type does not match expected type", s.line, s.col);
2904+
}
29052905
auto op = onFail ? BrOnCastFail : BrOnCast;
29062906
return Builder(wasm).makeBrOn(op, name, ref, *castType);
29072907
}

src/wasm/wasm-stack.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2045,25 +2045,22 @@ void BinaryInstWriter::visitBrOn(BrOn* curr) {
20452045
o << U32LEB(getBreakIndex(curr->name));
20462046
return;
20472047
case BrOnCast:
2048+
case BrOnCastFail: {
20482049
o << int8_t(BinaryConsts::GCPrefix);
2049-
if (curr->castType.isNullable()) {
2050-
o << U32LEB(BinaryConsts::BrOnCastNull);
2051-
} else {
2050+
if (curr->op == BrOnCast) {
20522051
o << U32LEB(BinaryConsts::BrOnCast);
2053-
}
2054-
o << U32LEB(getBreakIndex(curr->name));
2055-
parent.writeHeapType(curr->castType.getHeapType());
2056-
return;
2057-
case BrOnCastFail:
2058-
o << int8_t(BinaryConsts::GCPrefix);
2059-
if (curr->castType.isNullable()) {
2060-
o << U32LEB(BinaryConsts::BrOnCastFailNull);
20612052
} else {
20622053
o << U32LEB(BinaryConsts::BrOnCastFail);
20632054
}
2055+
assert(curr->ref->type.isRef());
2056+
uint8_t flags = (curr->ref->type.isNullable() ? 1 : 0) |
2057+
(curr->castType.isNullable() ? 2 : 0);
2058+
o << flags;
20642059
o << U32LEB(getBreakIndex(curr->name));
2060+
parent.writeHeapType(curr->ref->type.getHeapType());
20652061
parent.writeHeapType(curr->castType.getHeapType());
20662062
return;
2063+
}
20672064
}
20682065
WASM_UNREACHABLE("invalid br_on_*");
20692066
}

test/heap-types.wast

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,15 +313,19 @@
313313
(drop
314314
(block $out-B (result (ref $struct.B))
315315
(local.set $temp.A
316-
(br_on_cast $out-B $struct.B (ref.null $struct.A))
316+
(br_on_cast $out-B (ref null $struct.A) (ref $struct.B)
317+
(ref.null $struct.A)
318+
)
317319
)
318320
(unreachable)
319321
)
320322
)
321323
(drop
322324
(block $out-A (result (ref null $struct.A))
323325
(local.set $temp.B
324-
(br_on_cast_fail $out-A $struct.B (ref.null $struct.A))
326+
(br_on_cast_fail $out-A (ref null $struct.A) (ref $struct.B)
327+
(ref.null $struct.A)
328+
)
325329
)
326330
(unreachable)
327331
)

test/heap-types.wast.from-wast

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@
378378
(drop
379379
(block $out-B (result (ref $struct.B))
380380
(local.set $temp.A
381-
(br_on_cast $out-B $struct.B
381+
(br_on_cast $out-B nullref (ref $struct.B)
382382
(ref.null none)
383383
)
384384
)
@@ -388,7 +388,7 @@
388388
(drop
389389
(block $out-A (result (ref null $struct.A))
390390
(local.set $temp.B
391-
(br_on_cast_fail $out-A $struct.B
391+
(br_on_cast_fail $out-A nullref (ref $struct.B)
392392
(ref.null none)
393393
)
394394
)

test/heap-types.wast.fromBinary

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@
331331
(drop
332332
(block $label$1 (result (ref $struct.B))
333333
(local.set $temp.A
334-
(br_on_cast $label$1 $struct.B
334+
(br_on_cast $label$1 nullref (ref $struct.B)
335335
(ref.null none)
336336
)
337337
)
@@ -341,7 +341,7 @@
341341
(drop
342342
(block $label$2 (result (ref null $struct.A))
343343
(local.set $temp.B
344-
(br_on_cast_fail $label$2 $struct.B
344+
(br_on_cast_fail $label$2 nullref (ref $struct.B)
345345
(ref.null none)
346346
)
347347
)

test/heap-types.wast.fromBinary.noDebugInfo

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@
331331
(drop
332332
(block $label$1 (result (ref ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}))
333333
(local.set $0
334-
(br_on_cast $label$1 ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}
334+
(br_on_cast $label$1 nullref (ref ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|})
335335
(ref.null none)
336336
)
337337
)
@@ -341,7 +341,7 @@
341341
(drop
342342
(block $label$2 (result (ref null ${i32_f32_f64}))
343343
(local.set $1
344-
(br_on_cast_fail $label$2 ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}
344+
(br_on_cast_fail $label$2 nullref (ref ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|})
345345
(ref.null none)
346346
)
347347
)

0 commit comments

Comments
 (0)