Skip to content

Commit 6fadc97

Browse files
committed
[threads] ref.i31_shared
Implement `ref.i31_shared` the new instruction for creating references to shared i31s. Implement binary and text parsing and emitting as well as interpretation. Copy the upstream spec test for i31 and modify it so that all the heap types are shared. Comment out some parts that we do not yet support.
1 parent ae4800b commit 6fadc97

21 files changed

Lines changed: 342 additions & 30 deletions

scripts/gen-s-parser.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -572,8 +572,9 @@
572572
("resume", "makeResume()"),
573573
("suspend", "makeSuspend()"),
574574
# GC
575-
("i31.new", "makeRefI31()"), # deprecated
576-
("ref.i31", "makeRefI31()"),
575+
("i31.new", "makeRefI31(Unshared)"), # deprecated
576+
("ref.i31", "makeRefI31(Unshared)"),
577+
("ref.i31_shared", "makeRefI31(Shared)"),
577578
("i31.get_s", "makeI31Get(true)"),
578579
("i31.get_u", "makeI31Get(false)"),
579580
("ref.test", "makeRefTest()"),

src/gen-s-parser.inc

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1831,7 +1831,7 @@ switch (buf[0]) {
18311831
}
18321832
case 'n':
18331833
if (op == "i31.new"sv) {
1834-
CHECK_ERR(makeRefI31(ctx, pos, annotations));
1834+
CHECK_ERR(makeRefI31(ctx, pos, annotations, Unshared));
18351835
return Ok{};
18361836
}
18371837
goto parse_error;
@@ -4505,12 +4505,23 @@ switch (buf[0]) {
45054505
goto parse_error;
45064506
case 'i': {
45074507
switch (buf[5]) {
4508-
case '3':
4509-
if (op == "ref.i31"sv) {
4510-
CHECK_ERR(makeRefI31(ctx, pos, annotations));
4511-
return Ok{};
4508+
case '3': {
4509+
switch (buf[7]) {
4510+
case '\0':
4511+
if (op == "ref.i31"sv) {
4512+
CHECK_ERR(makeRefI31(ctx, pos, annotations, Unshared));
4513+
return Ok{};
4514+
}
4515+
goto parse_error;
4516+
case '_':
4517+
if (op == "ref.i31_shared"sv) {
4518+
CHECK_ERR(makeRefI31(ctx, pos, annotations, Shared));
4519+
return Ok{};
4520+
}
4521+
goto parse_error;
4522+
default: goto parse_error;
45124523
}
4513-
goto parse_error;
4524+
}
45144525
case 's':
45154526
if (op == "ref.is_null"sv) {
45164527
CHECK_ERR(makeRefIsNull(ctx, pos, annotations));

src/ir/properties.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ inline Literal getLiteral(const Expression* curr) {
119119
return Literal(r->func, r->type.getHeapType());
120120
} else if (auto* i = curr->dynCast<RefI31>()) {
121121
if (auto* c = i->value->dynCast<Const>()) {
122-
return Literal::makeI31(c->value.geti32());
122+
return Literal::makeI31(c->value.geti32(), i->share);
123123
}
124124
} else if (auto* s = curr->dynCast<StringConst>()) {
125125
return Literal(s->string.toString());

src/literal.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,8 @@ class Literal {
243243
static Literal makeFunc(Name func, HeapType type) {
244244
return Literal(func, type);
245245
}
246-
static Literal makeI31(int32_t value) {
247-
auto lit = Literal(Type(HeapType::i31, NonNullable));
246+
static Literal makeI31(int32_t value, Shareability share) {
247+
auto lit = Literal(Type(HeapTypes::i31.getBasic(share), NonNullable));
248248
lit.i32 = value | 0x80000000;
249249
return lit;
250250
}
@@ -281,7 +281,7 @@ class Literal {
281281
return i32;
282282
}
283283
int32_t geti31(bool signed_ = true) const {
284-
assert(type.getHeapType() == HeapType::i31);
284+
assert(type.getHeapType().getBasic(Unshared) == HeapType::i31);
285285
// Cast to unsigned for the left shift to avoid undefined behavior.
286286
return signed_ ? int32_t((uint32_t(i32) << 1)) >> 1 : (i32 & 0x7fffffff);
287287
}

src/parser/contexts.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,10 @@ struct NullInstrParserCtx {
695695
Result<> makeCallRef(Index, const std::vector<Annotation>&, HeapTypeT, bool) {
696696
return Ok{};
697697
}
698-
Result<> makeRefI31(Index, const std::vector<Annotation>&) { return Ok{}; }
698+
Result<>
699+
makeRefI31(Index, const std::vector<Annotation>&, Shareability share) {
700+
return Ok{};
701+
}
699702
Result<> makeI31Get(Index, const std::vector<Annotation>&, bool) {
700703
return Ok{};
701704
}
@@ -2363,8 +2366,10 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
23632366
return withLoc(pos, irBuilder.makeCallRef(type, isReturn));
23642367
}
23652368

2366-
Result<> makeRefI31(Index pos, const std::vector<Annotation>& annotations) {
2367-
return withLoc(pos, irBuilder.makeRefI31());
2369+
Result<> makeRefI31(Index pos,
2370+
const std::vector<Annotation>& annotations,
2371+
Shareability share) {
2372+
return withLoc(pos, irBuilder.makeRefI31(share));
23682373
}
23692374

23702375
Result<> makeI31Get(Index pos,

src/parser/parsers.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,8 @@ template<typename Ctx>
221221
Result<>
222222
makeCallRef(Ctx&, Index, const std::vector<Annotation>&, bool isReturn);
223223
template<typename Ctx>
224-
Result<> makeRefI31(Ctx&, Index, const std::vector<Annotation>&);
224+
Result<>
225+
makeRefI31(Ctx&, Index, const std::vector<Annotation>&, Shareability share);
225226
template<typename Ctx>
226227
Result<> makeI31Get(Ctx&, Index, const std::vector<Annotation>&, bool signed_);
227228
template<typename Ctx>
@@ -2127,9 +2128,11 @@ Result<> makeCallRef(Ctx& ctx,
21272128
}
21282129

21292130
template<typename Ctx>
2130-
Result<>
2131-
makeRefI31(Ctx& ctx, Index pos, const std::vector<Annotation>& annotations) {
2132-
return ctx.makeRefI31(pos, annotations);
2131+
Result<> makeRefI31(Ctx& ctx,
2132+
Index pos,
2133+
const std::vector<Annotation>& annotations,
2134+
Shareability share) {
2135+
return ctx.makeRefI31(pos, annotations, share);
21332136
}
21342137

21352138
template<typename Ctx>

src/parser/wast-parser.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,13 @@ Result<ExpectedResult> result(Lexer& in) {
207207
return RefResult{HeapType::func};
208208
}
209209

210+
if (in.takeSExprStart("ref.i31_shared")) {
211+
if (!in.takeRParen()) {
212+
return in.err("expected end of ref.i31_shared");
213+
}
214+
return RefResult{HeapTypes::i31.getBasic(Shared)};
215+
}
216+
210217
return in.err("unrecognized result");
211218
}
212219

src/passes/Print.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2076,7 +2076,9 @@ struct PrintExpressionContents
20762076
o << std::max(curr->tuple->type.size(), size_t(2)) << " ";
20772077
o << curr->index;
20782078
}
2079-
void visitRefI31(RefI31* curr) { printMedium(o, "ref.i31"); }
2079+
void visitRefI31(RefI31* curr) {
2080+
printMedium(o, curr->share == Shared ? "ref.i31_shared" : "ref.i31");
2081+
}
20802082
void visitI31Get(I31Get* curr) {
20812083
printMedium(o, curr->signed_ ? "i31.get_s" : "i31.get_u");
20822084
}

src/wasm-binary.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,7 @@ enum ASTNodes {
11251125
RefI31 = 0x1c,
11261126
I31GetS = 0x1d,
11271127
I31GetU = 0x1e,
1128+
RefI31Shared = 0x1f,
11281129

11291130
// stringref opcodes
11301131

src/wasm-builder.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -873,8 +873,9 @@ class Builder {
873873
ret->finalize();
874874
return ret;
875875
}
876-
RefI31* makeRefI31(Expression* value) {
876+
RefI31* makeRefI31(Expression* value, Shareability share = Unshared) {
877877
auto* ret = wasm.allocator.alloc<RefI31>();
878+
ret->share = share;
878879
ret->value = value;
879880
ret->finalize();
880881
return ret;

0 commit comments

Comments
 (0)