Skip to content

Commit e09fb56

Browse files
authored
Emit call_ref with a type annotation (#5079)
Emit call_ref instructions with type annotations and a temporary opcode. Also implement support for parsing optional type annotations on call_ref in the text and binary formats. This is part of a multi-part graceful update to switch Binaryen and all of its users over to using the type-annotated version of call_ref without there being any breakage.
1 parent e750809 commit e09fb56

21 files changed

+97
-99
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ Current Trunk
1616
-------------
1717

1818
- Add extra `memory64` argument for `BinaryenSetMemory` and new `BinaryenMemoryIs64` C-API method to determine 64-bit memory. (#4963)
19-
- `TypeBuilderSetSubType` now takes a super type as the second argument.
19+
- `TypeBuilderSetSubType` now takes a supertype as the second argument.
20+
- `call_ref` can now take a signature type immediate in the text format. The
21+
type immediate will become mandatory in the future.
2022

2123
v110
2224
----

src/passes/Print.cpp

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2060,23 +2060,17 @@ struct PrintExpressionContents
20602060
}
20612061

20622062
void visitCallRef(CallRef* curr) {
2063-
if (curr->isReturn) {
2064-
if (printUnreachableReplacement(curr->target)) {
2065-
return;
2066-
}
2067-
printMedium(o, "return_call_ref ");
2068-
assert(curr->target->type != Type::unreachable);
2069-
// TODO: Workaround if target has bottom type.
2070-
printHeapType(o, curr->target->type.getHeapType(), wasm);
2071-
} else {
2072-
printMedium(o, "call_ref");
2063+
// TODO: Workaround if target has bottom type.
2064+
if (printUnreachableReplacement(curr->target)) {
2065+
return;
20732066
}
2067+
printMedium(o, curr->isReturn ? "return_call_ref " : "call_ref ");
2068+
printHeapType(o, curr->target->type.getHeapType(), wasm);
20742069
}
20752070
void visitRefTest(RefTest* curr) {
20762071
printMedium(o, "ref.test_static ");
20772072
printHeapType(o, curr->intendedType, wasm);
20782073
}
2079-
20802074
void visitRefCast(RefCast* curr) {
20812075
if (curr->safety == RefCast::Unsafe) {
20822076
printMedium(o, "ref.cast_nop_static ");
@@ -2085,6 +2079,7 @@ struct PrintExpressionContents
20852079
}
20862080
printHeapType(o, curr->intendedType, wasm);
20872081
}
2082+
20882083
void visitBrOn(BrOn* curr) {
20892084
switch (curr->op) {
20902085
case BrOnNull:
@@ -2139,7 +2134,6 @@ struct PrintExpressionContents
21392134
o << ' ';
21402135
TypeNamePrinter(o, wasm).print(curr->type.getHeapType());
21412136
}
2142-
21432137
void printFieldName(HeapType type, Index index) {
21442138
processFieldName(wasm, type, index, [&](Name name) {
21452139
if (name.is()) {
@@ -2755,11 +2749,7 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> {
27552749
decIndent();
27562750
}
27572751
void visitCallRef(CallRef* curr) {
2758-
if (curr->isReturn) {
2759-
maybePrintUnreachableReplacement(curr, curr->target->type);
2760-
} else {
2761-
visitExpression(curr);
2762-
}
2752+
maybePrintUnreachableReplacement(curr, curr->target->type);
27632753
}
27642754
void visitStructNew(StructNew* curr) {
27652755
maybePrintUnreachableReplacement(curr, curr->type);

src/wasm-binary.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1083,7 +1083,8 @@ enum ASTNodes {
10831083

10841084
// typed function references opcodes
10851085

1086-
CallRef = 0x14,
1086+
CallRefUnannotated = 0x14,
1087+
CallRef = 0x17,
10871088
RetCallRef = 0x15,
10881089

10891090
// gc opcodes

src/wasm/wasm-binary.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3776,12 +3776,13 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
37763776
visitMemoryGrow(grow);
37773777
break;
37783778
}
3779-
case BinaryConsts::CallRef:
3779+
case BinaryConsts::CallRefUnannotated:
37803780
visitCallRef((curr = allocator.alloc<CallRef>())->cast<CallRef>());
37813781
break;
3782+
case BinaryConsts::CallRef:
37823783
case BinaryConsts::RetCallRef: {
37833784
auto call = allocator.alloc<CallRef>();
3784-
call->isReturn = true;
3785+
call->isReturn = code == BinaryConsts::RetCallRef;
37853786
curr = call;
37863787
visitCallRef(call, getTypeByIndex(getU32LEB()));
37873788
break;
@@ -6810,11 +6811,7 @@ void WasmBinaryBuilder::visitCallRef(CallRef* curr,
68106811
for (size_t i = 0; i < num; i++) {
68116812
curr->operands[num - i - 1] = popNonVoidExpression();
68126813
}
6813-
if (maybeType) {
6814-
curr->finalize();
6815-
} else {
6816-
curr->finalize(sig.results);
6817-
}
6814+
curr->finalize(sig.results);
68186815
}
68196816

68206817
bool WasmBinaryBuilder::maybeVisitI31New(Expression*& out, uint32_t code) {

src/wasm/wasm-s-parser.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2831,22 +2831,31 @@ Expression* SExpressionWasmBuilder::makeTupleExtract(Element& s) {
28312831

28322832
Expression* SExpressionWasmBuilder::makeCallRef(Element& s, bool isReturn) {
28332833
Index operandsStart = 1;
2834-
HeapType sigType;
2835-
if (isReturn) {
2834+
std::optional<HeapType> sigType;
2835+
try {
28362836
sigType = parseHeapType(*s[1]);
28372837
operandsStart = 2;
2838+
} catch (ParseException& p) {
2839+
// The type annotation is required for return_call_ref but temporarily
2840+
// optional for call_ref.
2841+
if (isReturn) {
2842+
throw;
2843+
}
28382844
}
28392845
std::vector<Expression*> operands;
28402846
parseOperands(s, operandsStart, s.size() - 1, operands);
28412847
auto* target = parseExpression(s[s.size() - 1]);
28422848

2843-
if (isReturn) {
2844-
if (!sigType.isSignature()) {
2849+
if (sigType) {
2850+
if (!sigType->isSignature()) {
28452851
throw ParseException(
2846-
"return_call_ref type annotation should be a signature", s.line, s.col);
2852+
std::string(isReturn ? "return_call_ref" : "call_ref") +
2853+
" type annotation should be a signature",
2854+
s.line,
2855+
s.col);
28472856
}
28482857
return Builder(wasm).makeCallRef(
2849-
target, operands, sigType.getSignature().results, isReturn);
2858+
target, operands, sigType->getSignature().results, isReturn);
28502859
}
28512860
return ValidatingBuilder(wasm, s.line, s.col)
28522861
.validateAndMakeCallRef(target, operands, isReturn);

src/wasm/wasm-stack.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,14 +2013,11 @@ void BinaryInstWriter::visitI31Get(I31Get* curr) {
20132013
}
20142014

20152015
void BinaryInstWriter::visitCallRef(CallRef* curr) {
2016-
if (curr->isReturn) {
2017-
assert(curr->target->type != Type::unreachable);
2018-
// TODO: `emitUnreachable` if target has bottom type.
2019-
o << int8_t(BinaryConsts::RetCallRef);
2020-
parent.writeIndexedHeapType(curr->target->type.getHeapType());
2021-
return;
2022-
}
2023-
o << int8_t(BinaryConsts::CallRef);
2016+
assert(curr->target->type != Type::unreachable);
2017+
// TODO: `emitUnreachable` if target has bottom type.
2018+
o << int8_t(curr->isReturn ? BinaryConsts::RetCallRef
2019+
: BinaryConsts::CallRef);
2020+
parent.writeIndexedHeapType(curr->target->type.getHeapType());
20242021
}
20252022

20262023
void BinaryInstWriter::visitRefTest(RefTest* curr) {

test/lit/passes/dae_all-features.wast

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@
504504
(unreachable)
505505
)
506506
;; CHECK: (func $1
507-
;; CHECK-NEXT: (call_ref
507+
;; CHECK-NEXT: (call_ref $i64
508508
;; CHECK-NEXT: (i64.const 0)
509509
;; CHECK-NEXT: (global.get $global$0)
510510
;; CHECK-NEXT: )

test/lit/passes/gufa-refs.wast

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,7 @@
831831
;; CHECK-NEXT: (drop
832832
;; CHECK-NEXT: (local.get $y)
833833
;; CHECK-NEXT: )
834-
;; CHECK-NEXT: (call_ref
834+
;; CHECK-NEXT: (call_ref $two-params
835835
;; CHECK-NEXT: (unreachable)
836836
;; CHECK-NEXT: (struct.new_default $struct)
837837
;; CHECK-NEXT: (ref.func $func-2params-a)
@@ -3744,19 +3744,19 @@
37443744
)
37453745

37463746
;; CHECK: (func $do-calls (type $none_=>_none)
3747-
;; CHECK-NEXT: (call_ref
3747+
;; CHECK-NEXT: (call_ref $i1
37483748
;; CHECK-NEXT: (i32.const 42)
37493749
;; CHECK-NEXT: (ref.func $reffed1)
37503750
;; CHECK-NEXT: )
3751-
;; CHECK-NEXT: (call_ref
3751+
;; CHECK-NEXT: (call_ref $i1
37523752
;; CHECK-NEXT: (i32.const 42)
37533753
;; CHECK-NEXT: (ref.func $reffed1)
37543754
;; CHECK-NEXT: )
3755-
;; CHECK-NEXT: (call_ref
3755+
;; CHECK-NEXT: (call_ref $i2
37563756
;; CHECK-NEXT: (i32.const 1337)
37573757
;; CHECK-NEXT: (ref.func $reffed2)
37583758
;; CHECK-NEXT: )
3759-
;; CHECK-NEXT: (call_ref
3759+
;; CHECK-NEXT: (call_ref $i2
37603760
;; CHECK-NEXT: (i32.const 99999)
37613761
;; CHECK-NEXT: (ref.func $reffed2)
37623762
;; CHECK-NEXT: )

test/lit/passes/inlining-optimizing.wast

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
)
1414
;; CHECK: (func $1
1515
;; CHECK-NEXT: (drop
16-
;; CHECK-NEXT: (call_ref
17-
;; CHECK-NEXT: (unreachable)
16+
;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit)
17+
;; CHECK-NEXT: (drop
18+
;; CHECK-NEXT: (unreachable)
19+
;; CHECK-NEXT: )
1820
;; CHECK-NEXT: )
1921
;; CHECK-NEXT: )
2022
;; CHECK-NEXT: )

test/lit/passes/inlining_all-features.wast

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@
142142
;; CHECK: (func $1
143143
;; CHECK-NEXT: (block $__inlined_func$0
144144
;; CHECK-NEXT: (block
145-
;; CHECK-NEXT: (call_ref
145+
;; CHECK-NEXT: (call_ref $none_=>_none
146146
;; CHECK-NEXT: (ref.null $none_=>_none)
147147
;; CHECK-NEXT: )
148148
;; CHECK-NEXT: (br $__inlined_func$0)
@@ -153,7 +153,7 @@
153153
;; NOMNL: (func $1 (type $none_=>_none)
154154
;; NOMNL-NEXT: (block $__inlined_func$0
155155
;; NOMNL-NEXT: (block
156-
;; NOMNL-NEXT: (call_ref
156+
;; NOMNL-NEXT: (call_ref $none_=>_none
157157
;; NOMNL-NEXT: (ref.null $none_=>_none)
158158
;; NOMNL-NEXT: )
159159
;; NOMNL-NEXT: (br $__inlined_func$0)

test/lit/passes/intrinsic-lowering.wast

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
;; CHECK-NEXT: (i32.const 42)
2828
;; CHECK-NEXT: )
2929
;; CHECK-NEXT: )
30-
;; CHECK-NEXT: (call_ref
30+
;; CHECK-NEXT: (call_ref $none
3131
;; CHECK-NEXT: (ref.null $none)
3232
;; CHECK-NEXT: )
3333
;; CHECK-NEXT: (i32.const 1)

test/lit/passes/local-cse_all-features.wast

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212

1313
;; CHECK: (func $calls (param $x i32) (result i32)
1414
;; CHECK-NEXT: (drop
15-
;; CHECK-NEXT: (call_ref
15+
;; CHECK-NEXT: (call_ref $i32_=>_i32
1616
;; CHECK-NEXT: (i32.const 10)
1717
;; CHECK-NEXT: (ref.func $calls)
1818
;; CHECK-NEXT: )
1919
;; CHECK-NEXT: )
2020
;; CHECK-NEXT: (drop
21-
;; CHECK-NEXT: (call_ref
21+
;; CHECK-NEXT: (call_ref $i32_=>_i32
2222
;; CHECK-NEXT: (i32.const 10)
2323
;; CHECK-NEXT: (ref.func $calls)
2424
;; CHECK-NEXT: )

test/lit/passes/merge-similar-functions.wast

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@
328328
;; CHECK-NEXT: (nop)
329329
;; CHECK-NEXT: (nop)
330330
;; CHECK-NEXT: (nop)
331-
;; CHECK-NEXT: (call_ref
331+
;; CHECK-NEXT: (call_ref $none_=>_i32
332332
;; CHECK-NEXT: (local.get $0)
333333
;; CHECK-NEXT: )
334334
;; CHECK-NEXT: )
@@ -352,7 +352,7 @@
352352
;; CHECK-NEXT: (nop)
353353
;; CHECK-NEXT: (nop)
354354
;; CHECK-NEXT: (nop)
355-
;; CHECK-NEXT: (call_ref
355+
;; CHECK-NEXT: (call_ref $i32_=>_i32
356356
;; CHECK-NEXT: (local.get $1)
357357
;; CHECK-NEXT: (local.get $0)
358358
;; CHECK-NEXT: )

test/lit/passes/merge-similar-functions_types.wast

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@
151151
;; CHECK-NEXT: (nop)
152152
;; CHECK-NEXT: (nop)
153153
;; CHECK-NEXT: (nop)
154-
;; CHECK-NEXT: (call_ref
154+
;; CHECK-NEXT: (call_ref $type$0
155155
;; CHECK-NEXT: (local.get $0)
156156
;; CHECK-NEXT: )
157157
;; CHECK-NEXT: (nop)
@@ -287,7 +287,7 @@
287287
;; CHECK-NEXT: (nop)
288288
;; CHECK-NEXT: (nop)
289289
;; CHECK-NEXT: (nop)
290-
;; CHECK-NEXT: (call_ref
290+
;; CHECK-NEXT: (call_ref $type$0
291291
;; CHECK-NEXT: (local.get $0)
292292
;; CHECK-NEXT: )
293293
;; CHECK-NEXT: (nop)
@@ -309,7 +309,7 @@
309309
;; NOMNL-NEXT: (nop)
310310
;; NOMNL-NEXT: (nop)
311311
;; NOMNL-NEXT: (nop)
312-
;; NOMNL-NEXT: (call_ref
312+
;; NOMNL-NEXT: (call_ref $type$1
313313
;; NOMNL-NEXT: (local.get $0)
314314
;; NOMNL-NEXT: )
315315
;; NOMNL-NEXT: (nop)

test/lit/passes/optimize-instructions-call_ref.wast

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@
158158
)
159159

160160
;; CHECK: (func $fallthrough-bad-type (result i32)
161-
;; CHECK-NEXT: (call_ref
161+
;; CHECK-NEXT: (call_ref $none_=>_i32
162162
;; CHECK-NEXT: (block (result (ref $none_=>_i32))
163163
;; CHECK-NEXT: (drop
164164
;; CHECK-NEXT: (ref.func $return-nothing)
@@ -188,7 +188,7 @@
188188
(func $return-nothing)
189189

190190
;; CHECK: (func $fallthrough-unreachable
191-
;; CHECK-NEXT: (call_ref
191+
;; CHECK-NEXT: (call_ref $i32_i32_=>_none
192192
;; CHECK-NEXT: (unreachable)
193193
;; CHECK-NEXT: (unreachable)
194194
;; CHECK-NEXT: (block (result (ref $i32_i32_=>_none))
@@ -258,7 +258,7 @@
258258
;; CHECK-NEXT: )
259259
;; CHECK-NEXT: )
260260
;; CHECK-NEXT: )
261-
;; CHECK-NEXT: (call_ref
261+
;; CHECK-NEXT: (call_ref $i32_i32_=>_none
262262
;; CHECK-NEXT: (local.get $x)
263263
;; CHECK-NEXT: (local.get $y)
264264
;; CHECK-NEXT: (select (result (ref $i32_i32_=>_none))

test/lit/passes/precompute-gc.wast

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,7 +1157,7 @@
11571157
;; CHECK-NEXT: )
11581158
;; CHECK-NEXT: )
11591159
;; CHECK-NEXT: (drop
1160-
;; CHECK-NEXT: (call_ref
1160+
;; CHECK-NEXT: (call_ref $func-return-i32
11611161
;; CHECK-NEXT: (local.get $temp)
11621162
;; CHECK-NEXT: )
11631163
;; CHECK-NEXT: )
@@ -1169,7 +1169,7 @@
11691169
;; NOMNL-NEXT: )
11701170
;; NOMNL-NEXT: )
11711171
;; NOMNL-NEXT: (drop
1172-
;; NOMNL-NEXT: (call_ref
1172+
;; NOMNL-NEXT: (call_ref $func-return-i32
11731173
;; NOMNL-NEXT: (local.get $temp)
11741174
;; NOMNL-NEXT: )
11751175
;; NOMNL-NEXT: )

0 commit comments

Comments
 (0)