Skip to content

Commit c6a5e65

Browse files
Support i64.add/sub128 instructions from Wide Arithmetic proposal (#8638)
Part of #8544 i64 to i32 lowering isn't implemented yet because supporting multi-value i64 returns requires more work here. Will add this in a separate change. Spec tests are adapted from the upstream proposal repo, with only tests related to i64.add128 and i64.sub128 included. Drive-by changes: * Remove unneeded template params in wasm-validator.cpp * Unconditionally assign to the result in ckd_add / ckd_sub polyfills to match the behavior of the [std implementations](https://en.cppreference.com/cpp/numeric/ckd_add). All of the existing callers don't observe the result when overflow occurred, but for our case we need the value regardless.
1 parent 6216d24 commit c6a5e65

31 files changed

Lines changed: 570 additions & 21 deletions

scripts/gen-s-parser.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@
148148
("i64.shr_u", "makeBinary(BinaryOp::ShrUInt64)"),
149149
("i64.rotl", "makeBinary(BinaryOp::RotLInt64)"),
150150
("i64.rotr", "makeBinary(BinaryOp::RotRInt64)"),
151+
("i64.add128", "makeWideIntAddSub(WideIntAddSubOp::AddInt128)"),
152+
("i64.sub128", "makeWideIntAddSub(WideIntAddSubOp::SubInt128)"),
151153
("f32.abs", "makeUnary(UnaryOp::AbsFloat32)"),
152154
("f32.neg", "makeUnary(UnaryOp::NegFloat32)"),
153155
("f32.ceil", "makeUnary(UnaryOp::CeilFloat32)"),

src/gen-s-parser.inc

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3427,12 +3427,23 @@ switch (buf[0]) {
34273427
switch (buf[4]) {
34283428
case 'a': {
34293429
switch (buf[5]) {
3430-
case 'd':
3431-
if (op == "i64.add"sv) {
3432-
CHECK_ERR(makeBinary(ctx, pos, annotations, BinaryOp::AddInt64));
3433-
return Ok{};
3430+
case 'd': {
3431+
switch (buf[7]) {
3432+
case '\0':
3433+
if (op == "i64.add"sv) {
3434+
CHECK_ERR(makeBinary(ctx, pos, annotations, BinaryOp::AddInt64));
3435+
return Ok{};
3436+
}
3437+
goto parse_error;
3438+
case '1':
3439+
if (op == "i64.add128"sv) {
3440+
CHECK_ERR(makeWideIntAddSub(ctx, pos, annotations, WideIntAddSubOp::AddInt128));
3441+
return Ok{};
3442+
}
3443+
goto parse_error;
3444+
default: goto parse_error;
34343445
}
3435-
goto parse_error;
3446+
}
34363447
case 'n':
34373448
if (op == "i64.and"sv) {
34383449
CHECK_ERR(makeBinary(ctx, pos, annotations, BinaryOp::AndInt64));
@@ -4113,12 +4124,23 @@ switch (buf[0]) {
41134124
default: goto parse_error;
41144125
}
41154126
}
4116-
case 'u':
4117-
if (op == "i64.sub"sv) {
4118-
CHECK_ERR(makeBinary(ctx, pos, annotations, BinaryOp::SubInt64));
4119-
return Ok{};
4127+
case 'u': {
4128+
switch (buf[7]) {
4129+
case '\0':
4130+
if (op == "i64.sub"sv) {
4131+
CHECK_ERR(makeBinary(ctx, pos, annotations, BinaryOp::SubInt64));
4132+
return Ok{};
4133+
}
4134+
goto parse_error;
4135+
case '1':
4136+
if (op == "i64.sub128"sv) {
4137+
CHECK_ERR(makeWideIntAddSub(ctx, pos, annotations, WideIntAddSubOp::SubInt128));
4138+
return Ok{};
4139+
}
4140+
goto parse_error;
4141+
default: goto parse_error;
41204142
}
4121-
goto parse_error;
4143+
}
41224144
default: goto parse_error;
41234145
}
41244146
}

src/interpreter/interpreter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ struct ExpressionInterpreter : OverriddenVisitor<ExpressionInterpreter, Flow> {
216216
WASM_UNREACHABLE("TODO");
217217
}
218218
}
219+
Flow visitWideIntAddSub(WideIntAddSub* curr) { WASM_UNREACHABLE("TODO"); }
219220
Flow visitSelect(Select* curr) { WASM_UNREACHABLE("TODO"); }
220221
Flow visitDrop(Drop* curr) { WASM_UNREACHABLE("TODO"); }
221222
Flow visitReturn(Return* curr) { WASM_UNREACHABLE("TODO"); }

src/ir/ReFinalize.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ void ReFinalize::visitMemoryFill(MemoryFill* curr) { curr->finalize(); }
109109
void ReFinalize::visitConst(Const* curr) { curr->finalize(); }
110110
void ReFinalize::visitUnary(Unary* curr) { curr->finalize(); }
111111
void ReFinalize::visitBinary(Binary* curr) { curr->finalize(); }
112+
void ReFinalize::visitWideIntAddSub(WideIntAddSub* curr) { curr->finalize(); }
112113
void ReFinalize::visitSelect(Select* curr) { curr->finalize(); }
113114
void ReFinalize::visitDrop(Drop* curr) { curr->finalize(); }
114115
void ReFinalize::visitReturn(Return* curr) { curr->finalize(); }

src/ir/child-typer.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,13 @@ template<typename Subtype> struct ChildTyper : OverriddenVisitor<Subtype> {
705705
}
706706
}
707707

708+
void visitWideIntAddSub(WideIntAddSub* curr) {
709+
note(&curr->leftLow, Type::i64);
710+
note(&curr->leftHigh, Type::i64);
711+
note(&curr->rightLow, Type::i64);
712+
note(&curr->rightHigh, Type::i64);
713+
}
714+
708715
void visitSelect(Select* curr, std::optional<Type> type = std::nullopt) {
709716
if (type) {
710717
note(&curr->ifTrue, *type);

src/ir/cost.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,10 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, CostType> {
575575
}
576576
return ret + visit(curr->left) + visit(curr->right);
577577
}
578+
CostType visitWideIntAddSub(WideIntAddSub* curr) {
579+
return 1 + visit(curr->leftLow) + visit(curr->leftHigh) +
580+
visit(curr->rightLow) + visit(curr->rightHigh);
581+
}
578582
CostType visitSelect(Select* curr) {
579583
return 1 + visit(curr->condition) + visit(curr->ifTrue) +
580584
visit(curr->ifFalse);

src/ir/effects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,7 @@ class EffectAnalyzer {
945945
}
946946
}
947947
}
948+
void visitWideIntAddSub(WideIntAddSub* curr) {}
948949
void visitSelect(Select* curr) {}
949950
void visitDrop(Drop* curr) {}
950951
void visitReturn(Return* curr) { parent.branchesOut = true; }

src/ir/possible-contents.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,7 @@ struct InfoCollector
634634
addRoot(curr);
635635
}
636636
void visitBinary(Binary* curr) { addRoot(curr); }
637+
void visitWideIntAddSub(WideIntAddSub* curr) { addRoot(curr); }
637638
void visitSelect(Select* curr) {
638639
receiveChildValue(curr->ifTrue, curr);
639640
receiveChildValue(curr->ifFalse, curr);

src/ir/subtype-exprs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
213213
void visitConst(Const* curr) {}
214214
void visitUnary(Unary* curr) {}
215215
void visitBinary(Binary* curr) {}
216+
void visitWideIntAddSub(WideIntAddSub* curr) {}
216217
void visitSelect(Select* curr) {
217218
self()->noteSubtype(curr->ifTrue, curr);
218219
self()->noteSubtype(curr->ifFalse, curr);

src/parser/contexts.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,11 @@ struct NullInstrParserCtx {
476476
Result<> makeBinary(Index, const std::vector<Annotation>&, BinaryOp) {
477477
return Ok{};
478478
}
479+
Result<>
480+
makeWideIntAddSub(Index, const std::vector<Annotation>&, WideIntAddSubOp) {
481+
return Ok{};
482+
}
483+
479484
Result<> makeUnary(Index, const std::vector<Annotation>&, UnaryOp) {
480485
return Ok{};
481486
}
@@ -2159,6 +2164,12 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx>, AnnotationParserCtx {
21592164
return withLoc(pos, irBuilder.makeBinary(op));
21602165
}
21612166

2167+
Result<> makeWideIntAddSub(Index pos,
2168+
const std::vector<Annotation>& annotations,
2169+
WideIntAddSubOp op) {
2170+
return withLoc(pos, irBuilder.makeWideIntAddSub(op));
2171+
}
2172+
21622173
Result<>
21632174
makeUnary(Index pos, const std::vector<Annotation>& annotations, UnaryOp op) {
21642175
return withLoc(pos, irBuilder.makeUnary(op));

0 commit comments

Comments
 (0)