Skip to content

Commit 9aa06be

Browse files
authored
Update text format for exact heap types (#7501)
Since exactness is syntactically part of the heap type, it introduces a new level of parentheses inside the reference type. Update type printing and the text parser accordingly.
1 parent 5045571 commit 9aa06be

10 files changed

+191
-188
lines changed

src/parser/context-defs.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ ParseDefsCtx::makeTypeUse(Index pos,
3636

3737
auto sig = Signature(Type(paramTypes), Type(resultTypes));
3838

39-
if (!type->isSignature() || type->getSignature() != sig) {
39+
if (!type->type.isSignature() || type->type.getSignature() != sig) {
4040
return in.err(pos, "type does not match provided signature");
4141
}
4242
}

src/parser/contexts.h

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,7 @@ struct NullTypeParserCtx {
127127
TypeT makeF64() { return Ok{}; }
128128
TypeT makeV128() { return Ok{}; }
129129

130-
TypeT makeRefType(HeapTypeT, Nullability, Exactness) { return Ok{}; }
131-
132-
HeapTypeT getHeapTypeFromRefType(TypeT) { return Ok{}; }
130+
TypeT makeRefType(HeapTypeT, Nullability) { return Ok{}; }
133131

134132
TupleElemListT makeTupleElemList() { return Ok{}; }
135133
void appendTupleElem(TupleElemListT&, TypeT) {}
@@ -169,6 +167,8 @@ struct NullTypeParserCtx {
169167
Result<Index> getTypeIndex(Name) { return 1; }
170168
Result<HeapTypeT> getHeapTypeFromIdx(Index) { return Ok{}; }
171169

170+
HeapTypeT makeExact(HeapTypeT) { return Ok{}; }
171+
172172
DataStringT makeDataString() { return Ok{}; }
173173
void appendDataString(DataStringT&, std::string_view) {}
174174

@@ -182,8 +182,18 @@ struct NullTypeParserCtx {
182182
};
183183

184184
template<typename Ctx> struct TypeParserCtx {
185+
// Exactness is syntactically part of the heap type, but it is not part of the
186+
// HeapType in our IR, so we have to store it separately.
187+
struct HeapTypeT {
188+
HeapType type;
189+
Exactness exactness = Inexact;
190+
// Implicitly convert to and from HeapType.
191+
HeapTypeT(HeapType::BasicHeapType type) : type(type) {}
192+
HeapTypeT(HeapType type) : type(type) {}
193+
operator HeapType() { return type; }
194+
};
195+
185196
using IndexT = Index;
186-
using HeapTypeT = HeapType;
187197
using TypeT = Type;
188198
using ParamsT = std::vector<NameType>;
189199
using ResultsT = std::vector<Type>;
@@ -253,19 +263,21 @@ template<typename Ctx> struct TypeParserCtx {
253263
return HeapTypes::nocont.getBasic(share);
254264
}
255265

266+
HeapTypeT makeExact(HeapTypeT type) {
267+
type.exactness = Exact;
268+
return type;
269+
}
270+
256271
TypeT makeI32() { return Type::i32; }
257272
TypeT makeI64() { return Type::i64; }
258273
TypeT makeF32() { return Type::f32; }
259274
TypeT makeF64() { return Type::f64; }
260275
TypeT makeV128() { return Type::v128; }
261276

262-
TypeT
263-
makeRefType(HeapTypeT ht, Nullability nullability, Exactness exactness) {
264-
return Type(ht, nullability, exactness);
277+
TypeT makeRefType(HeapTypeT ht, Nullability nullability) {
278+
return Type(ht.type, nullability, ht.exactness);
265279
}
266280

267-
HeapTypeT getHeapTypeFromRefType(TypeT t) { return t.getHeapType(); }
268-
269281
std::vector<Type> makeTupleElemList() { return {}; }
270282
void appendTupleElem(std::vector<Type>& elems, Type elem) {
271283
elems.push_back(elem);
@@ -1122,13 +1134,10 @@ struct ParseTypeDefsCtx : TypeParserCtx<ParseTypeDefsCtx> {
11221134
: TypeParserCtx<ParseTypeDefsCtx>(typeIndices), in(in), builder(builder),
11231135
names(builder.size()) {}
11241136

1125-
TypeT
1126-
makeRefType(HeapTypeT ht, Nullability nullability, Exactness exactness) {
1127-
return builder.getTempRefType(ht, nullability, exactness);
1137+
TypeT makeRefType(HeapTypeT ht, Nullability nullability) {
1138+
return builder.getTempRefType(ht.type, nullability, ht.exactness);
11281139
}
11291140

1130-
HeapTypeT getHeapTypeFromRefType(TypeT t) { return t.getHeapType(); }
1131-
11321141
TypeT makeTupleType(const std::vector<Type> types) {
11331142
return builder.getTempTupleType(types);
11341143
}
@@ -1235,7 +1244,7 @@ struct ParseImplicitTypeDefsCtx : TypeParserCtx<ParseImplicitTypeDefsCtx> {
12351244
}
12361245

12371246
auto sig = Signature(Type(paramTypes), Type(resultTypes));
1238-
auto [it, inserted] = sigTypes.insert({sig, HeapType::func});
1247+
auto [it, inserted] = sigTypes.insert({sig, HeapType(HeapType::func)});
12391248
if (inserted) {
12401249
auto type = HeapType(sig);
12411250
it->second = type;

src/parser/parsers.h

Lines changed: 37 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ using namespace std::string_view_literals;
3030
template<typename Ctx>
3131
Result<typename Ctx::HeapTypeT> absheaptype(Ctx&, Shareability);
3232
template<typename Ctx> Result<typename Ctx::HeapTypeT> heaptype(Ctx&);
33-
template<typename Ctx>
34-
MaybeResult<typename Ctx::TypeT> maybeReftypeAbbrev(Ctx&);
3533
template<typename Ctx> MaybeResult<typename Ctx::RefTypeT> maybeReftype(Ctx&);
3634
template<typename Ctx> Result<typename Ctx::RefTypeT> reftype(Ctx&);
3735
template<typename Ctx> MaybeResult<typename Ctx::TypeT> tupletype(Ctx&);
@@ -436,6 +434,7 @@ Result<typename Ctx::HeapTypeT> absheaptype(Ctx& ctx, Shareability share) {
436434
}
437435

438436
// heaptype ::= x:typeidx => types[x]
437+
// | '(' 'exact' x:typeidx ')' => exact types[x]
439438
// | t:absheaptype => unshared t
440439
// | '(' 'shared' t:absheaptype ')' => shared t
441440
template<typename Ctx> Result<typename Ctx::HeapTypeT> heaptype(Ctx& ctx) {
@@ -444,6 +443,15 @@ template<typename Ctx> Result<typename Ctx::HeapTypeT> heaptype(Ctx& ctx) {
444443
return *t;
445444
}
446445

446+
if (ctx.in.takeSExprStart("exact"sv)) {
447+
auto t = typeidx(ctx);
448+
CHECK_ERR(t);
449+
if (!ctx.in.takeRParen()) {
450+
return ctx.in.err("expected end of exact heap type");
451+
}
452+
return ctx.makeExact(*t);
453+
}
454+
447455
auto share = ctx.in.takeSExprStart("shared"sv) ? Shared : Unshared;
448456
auto t = absheaptype(ctx, share);
449457
CHECK_ERR(t);
@@ -460,85 +468,68 @@ template<typename Ctx> Result<typename Ctx::HeapTypeT> heaptype(Ctx& ctx) {
460468
// | 'i31ref' => i31ref
461469
// | 'structref' => structref
462470
// | 'arrayref' => arrayref
463-
// | ...
464-
template<typename Ctx>
465-
MaybeResult<typename Ctx::TypeT> maybeReftypeAbbrev(Ctx& ctx) {
471+
// | '(' ref null? t:heaptype ')' => ref null? t
472+
template<typename Ctx> MaybeResult<typename Ctx::TypeT> maybeReftype(Ctx& ctx) {
466473
if (ctx.in.takeKeyword("funcref"sv)) {
467-
return ctx.makeRefType(ctx.makeFuncType(Unshared), Nullable, Inexact);
474+
return ctx.makeRefType(ctx.makeFuncType(Unshared), Nullable);
468475
}
469476
if (ctx.in.takeKeyword("externref"sv)) {
470-
return ctx.makeRefType(ctx.makeExternType(Unshared), Nullable, Inexact);
477+
return ctx.makeRefType(ctx.makeExternType(Unshared), Nullable);
471478
}
472479
if (ctx.in.takeKeyword("anyref"sv)) {
473-
return ctx.makeRefType(ctx.makeAnyType(Unshared), Nullable, Inexact);
480+
return ctx.makeRefType(ctx.makeAnyType(Unshared), Nullable);
474481
}
475482
if (ctx.in.takeKeyword("eqref"sv)) {
476-
return ctx.makeRefType(ctx.makeEqType(Unshared), Nullable, Inexact);
483+
return ctx.makeRefType(ctx.makeEqType(Unshared), Nullable);
477484
}
478485
if (ctx.in.takeKeyword("i31ref"sv)) {
479-
return ctx.makeRefType(ctx.makeI31Type(Unshared), Nullable, Inexact);
486+
return ctx.makeRefType(ctx.makeI31Type(Unshared), Nullable);
480487
}
481488
if (ctx.in.takeKeyword("structref"sv)) {
482-
return ctx.makeRefType(ctx.makeStructType(Unshared), Nullable, Inexact);
489+
return ctx.makeRefType(ctx.makeStructType(Unshared), Nullable);
483490
}
484491
if (ctx.in.takeKeyword("arrayref"sv)) {
485-
return ctx.makeRefType(ctx.makeArrayType(Unshared), Nullable, Inexact);
492+
return ctx.makeRefType(ctx.makeArrayType(Unshared), Nullable);
486493
}
487494
if (ctx.in.takeKeyword("exnref"sv)) {
488-
return ctx.makeRefType(ctx.makeExnType(Unshared), Nullable, Inexact);
495+
return ctx.makeRefType(ctx.makeExnType(Unshared), Nullable);
489496
}
490497
if (ctx.in.takeKeyword("stringref"sv)) {
491-
return ctx.makeRefType(ctx.makeStringType(Unshared), Nullable, Inexact);
498+
return ctx.makeRefType(ctx.makeStringType(Unshared), Nullable);
492499
}
493500
if (ctx.in.takeKeyword("contref"sv)) {
494-
return ctx.makeRefType(ctx.makeContType(Unshared), Nullable, Inexact);
501+
return ctx.makeRefType(ctx.makeContType(Unshared), Nullable);
495502
}
496503
if (ctx.in.takeKeyword("nullref"sv)) {
497-
return ctx.makeRefType(ctx.makeNoneType(Unshared), Nullable, Inexact);
504+
return ctx.makeRefType(ctx.makeNoneType(Unshared), Nullable);
498505
}
499506
if (ctx.in.takeKeyword("nullexternref"sv)) {
500-
return ctx.makeRefType(ctx.makeNoextType(Unshared), Nullable, Inexact);
507+
return ctx.makeRefType(ctx.makeNoextType(Unshared), Nullable);
501508
}
502509
if (ctx.in.takeKeyword("nullfuncref"sv)) {
503-
return ctx.makeRefType(ctx.makeNofuncType(Unshared), Nullable, Inexact);
510+
return ctx.makeRefType(ctx.makeNofuncType(Unshared), Nullable);
504511
}
505512
if (ctx.in.takeKeyword("nullexnref"sv)) {
506-
return ctx.makeRefType(ctx.makeNoexnType(Unshared), Nullable, Inexact);
513+
return ctx.makeRefType(ctx.makeNoexnType(Unshared), Nullable);
507514
}
508515
if (ctx.in.takeKeyword("nullcontref"sv)) {
509-
return ctx.makeRefType(ctx.makeNocontType(Unshared), Nullable, Inexact);
516+
return ctx.makeRefType(ctx.makeNocontType(Unshared), Nullable);
510517
}
511-
return {};
512-
}
513518

514-
// reftype ::= ...
515-
// | '(' 'exact' (ref null ht):shorthand ')' => ref null exact ht
516-
// | '(' ref null? exact? ht:heaptype ')' => ref null? t
517-
template<typename Ctx> MaybeResult<typename Ctx::TypeT> maybeReftype(Ctx& ctx) {
518-
if (ctx.in.takeSExprStart("exact"sv)) {
519-
auto rt = maybeReftypeAbbrev(ctx);
520-
CHECK_ERR(rt);
521-
if (!rt) {
522-
return ctx.in.err("expected reftype shorthand");
523-
}
524-
if (!ctx.in.takeRParen()) {
525-
return ctx.in.err("expected end of reftype");
526-
}
527-
return ctx.makeRefType(ctx.getHeapTypeFromRefType(*rt), Nullable, Exact);
519+
if (!ctx.in.takeSExprStart("ref"sv)) {
520+
return {};
528521
}
529522

530-
if (ctx.in.takeSExprStart("ref"sv)) {
531-
auto nullability = ctx.in.takeKeyword("null"sv) ? Nullable : NonNullable;
532-
auto exactness = ctx.in.takeKeyword("exact"sv) ? Exact : Inexact;
533-
auto type = heaptype(ctx);
534-
CHECK_ERR(type);
535-
if (!ctx.in.takeRParen()) {
536-
return ctx.in.err("expected end of reftype");
537-
}
538-
return ctx.makeRefType(*type, nullability, exactness);
523+
auto nullability = ctx.in.takeKeyword("null"sv) ? Nullable : NonNullable;
524+
525+
auto type = heaptype(ctx);
526+
CHECK_ERR(type);
527+
528+
if (!ctx.in.takeRParen()) {
529+
return ctx.in.err("expected end of reftype");
539530
}
540531

541-
return maybeReftypeAbbrev(ctx);
532+
return ctx.makeRefType(*type, nullability);
542533
}
543534

544535
template<typename Ctx> Result<typename Ctx::TypeT> reftype(Ctx& ctx) {

src/wasm/wasm-type.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1736,9 +1736,12 @@ std::ostream& TypePrinter::print(Type type) {
17361736
os << "null ";
17371737
}
17381738
if (type.isExact()) {
1739-
os << "exact ";
1739+
os << "(exact ";
17401740
}
17411741
printHeapTypeName(heapType);
1742+
if (type.isExact()) {
1743+
os << ')';
1744+
}
17421745
os << ')';
17431746
} else {
17441747
WASM_UNREACHABLE("unexpected type");

0 commit comments

Comments
 (0)