Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Parser] Parse v128.const #6275

Merged
merged 1 commit into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions src/parser/contexts.h
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,20 @@ struct NullInstrParserCtx {
Result<> makeI64Const(Index, uint64_t) { return Ok{}; }
Result<> makeF32Const(Index, float) { return Ok{}; }
Result<> makeF64Const(Index, double) { return Ok{}; }
Result<> makeI8x16Const(Index, const std::array<uint8_t, 16>&) {
return Ok{};
}
Result<> makeI16x8Const(Index, const std::array<uint16_t, 8>&) {
return Ok{};
}
Result<> makeI32x4Const(Index, const std::array<uint32_t, 4>&) {
return Ok{};
}
Result<> makeI64x2Const(Index, const std::array<uint64_t, 2>&) {
return Ok{};
}
Result<> makeF32x4Const(Index, const std::array<float, 4>&) { return Ok{}; }
Result<> makeF64x2Const(Index, const std::array<double, 2>&) { return Ok{}; }
Result<> makeLoad(Index, Type, bool, int, bool, MemoryIdxT*, MemargT) {
return Ok{};
}
Expand Down Expand Up @@ -1542,6 +1556,54 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
return withLoc(pos, irBuilder.makeConst(Literal(c)));
}

Result<> makeI8x16Const(Index pos, const std::array<uint8_t, 16>& vals) {
std::array<Literal, 16> lanes;
for (size_t i = 0; i < 16; ++i) {
lanes[i] = Literal(uint32_t(vals[i]));
}
return withLoc(pos, irBuilder.makeConst(Literal(lanes)));
}

Result<> makeI16x8Const(Index pos, const std::array<uint16_t, 8>& vals) {
std::array<Literal, 8> lanes;
for (size_t i = 0; i < 8; ++i) {
lanes[i] = Literal(uint32_t(vals[i]));
}
return withLoc(pos, irBuilder.makeConst(Literal(lanes)));
}

Result<> makeI32x4Const(Index pos, const std::array<uint32_t, 4>& vals) {
std::array<Literal, 4> lanes;
for (size_t i = 0; i < 4; ++i) {
lanes[i] = Literal(vals[i]);
}
return withLoc(pos, irBuilder.makeConst(Literal(lanes)));
}

Result<> makeI64x2Const(Index pos, const std::array<uint64_t, 2>& vals) {
std::array<Literal, 2> lanes;
for (size_t i = 0; i < 2; ++i) {
lanes[i] = Literal(vals[i]);
}
return withLoc(pos, irBuilder.makeConst(Literal(lanes)));
}

Result<> makeF32x4Const(Index pos, const std::array<float, 4>& vals) {
std::array<Literal, 4> lanes;
for (size_t i = 0; i < 4; ++i) {
lanes[i] = Literal(vals[i]);
}
return withLoc(pos, irBuilder.makeConst(Literal(lanes)));
}

Result<> makeF64x2Const(Index pos, const std::array<double, 2>& vals) {
std::array<Literal, 2> lanes;
for (size_t i = 0; i < 2; ++i) {
lanes[i] = Literal(vals[i]);
}
return withLoc(pos, irBuilder.makeConst(Literal(lanes)));
}

Result<> makeLoad(Index pos,
Type type,
bool signed_,
Expand Down
6 changes: 6 additions & 0 deletions src/parser/input-impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,14 @@ inline std::optional<uint32_t> ParseInput::takeI32() {
return takeI<uint32_t>();
}

inline std::optional<uint16_t> ParseInput::takeI16() {
return takeI<uint16_t>();
}

inline std::optional<uint8_t> ParseInput::takeU8() { return takeU<uint8_t>(); }

inline std::optional<uint8_t> ParseInput::takeI8() { return takeI<uint8_t>(); }

inline std::optional<double> ParseInput::takeF64() {
if (auto t = peek()) {
if (auto d = t->getF64()) {
Expand Down
2 changes: 2 additions & 0 deletions src/parser/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ struct ParseInput {
std::optional<uint64_t> takeI64();
std::optional<uint32_t> takeU32();
std::optional<uint32_t> takeI32();
std::optional<uint16_t> takeI16();
std::optional<uint8_t> takeU8();
std::optional<uint8_t> takeI8();
std::optional<double> takeF64();
std::optional<float> takeF32();
std::optional<std::string> takeString();
Expand Down
5 changes: 5 additions & 0 deletions src/parser/lexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,12 @@ template std::optional<uint64_t> Token::getI<uint64_t>() const;
template std::optional<uint32_t> Token::getU<uint32_t>() const;
template std::optional<int32_t> Token::getS<int32_t>() const;
template std::optional<uint32_t> Token::getI<uint32_t>() const;
template std::optional<uint16_t> Token::getU<uint16_t>() const;
template std::optional<int16_t> Token::getS<int16_t>() const;
template std::optional<uint16_t> Token::getI<uint16_t>() const;
template std::optional<uint8_t> Token::getU<uint8_t>() const;
template std::optional<int8_t> Token::getS<int8_t>() const;
template std::optional<uint8_t> Token::getI<uint8_t>() const;

std::optional<double> Token::getF64() const {
constexpr int signif = 52;
Expand Down
68 changes: 67 additions & 1 deletion src/parser/parsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -1362,7 +1362,73 @@ template<typename Ctx> Result<> makeConst(Ctx& ctx, Index pos, Type type) {
}
return ctx.in.err("expected f64");
case Type::v128:
return ctx.in.err("unimplemented instruction");
if (ctx.in.takeKeyword("i8x16"sv)) {
std::array<uint8_t, 16> vals;
for (size_t i = 0; i < 16; ++i) {
auto val = ctx.in.takeI8();
if (!val) {
return ctx.in.err("expected i8 value");
}
vals[i] = *val;
}
return ctx.makeI8x16Const(pos, vals);
}
if (ctx.in.takeKeyword("i16x8"sv)) {
std::array<uint16_t, 8> vals;
for (size_t i = 0; i < 8; ++i) {
auto val = ctx.in.takeI16();
if (!val) {
return ctx.in.err("expected i16 value");
}
vals[i] = *val;
}
return ctx.makeI16x8Const(pos, vals);
}
if (ctx.in.takeKeyword("i32x4"sv)) {
std::array<uint32_t, 4> vals;
for (size_t i = 0; i < 4; ++i) {
auto val = ctx.in.takeI32();
if (!val) {
return ctx.in.err("expected i32 value");
}
vals[i] = *val;
}
return ctx.makeI32x4Const(pos, vals);
}
if (ctx.in.takeKeyword("i64x2"sv)) {
std::array<uint64_t, 2> vals;
for (size_t i = 0; i < 2; ++i) {
auto val = ctx.in.takeI64();
if (!val) {
return ctx.in.err("expected i64 value");
}
vals[i] = *val;
}
return ctx.makeI64x2Const(pos, vals);
}
if (ctx.in.takeKeyword("f32x4"sv)) {
std::array<float, 4> vals;
for (size_t i = 0; i < 4; ++i) {
auto val = ctx.in.takeF32();
if (!val) {
return ctx.in.err("expected f32 value");
}
vals[i] = *val;
}
return ctx.makeF32x4Const(pos, vals);
}
if (ctx.in.takeKeyword("f64x2"sv)) {
std::array<double, 2> vals;
for (size_t i = 0; i < 2; ++i) {
auto val = ctx.in.takeF64();
if (!val) {
return ctx.in.err("expected f64 value");
}
vals[i] = *val;
}
return ctx.makeF64x2Const(pos, vals);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems tempting to use some C macros for these...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, macros or templates could definitely reduce the line count here, but I'm not sure they would do much for overall code clarity :)

return ctx.in.err("expected SIMD vector shape");
case Type::none:
case Type::unreachable:
break;
Expand Down
39 changes: 37 additions & 2 deletions test/lit/wat-kitchen-sink.wast
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@
;; CHECK: (elem $passive-2 anyref (struct.new_default $s0) (struct.new_default $s0))
(elem $passive-2 anyref (item struct.new $s0) (struct.new $s0))

;; CHECK: (elem declare func $ref-func $table-fill $table-grow $table-set)
;; CHECK: (elem declare func $ref-func $ref-is-null $table-fill $table-grow $table-set)
(elem declare func 0 1 2 3)

(elem $declare-2 declare funcref (item ref.func 0) (ref.func 1) (item (ref.func 2)))
Expand Down Expand Up @@ -3302,6 +3302,41 @@
atomic.fence
)

;; CHECK: (func $simd-const (type $void)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (v128.const i32x4 0x03020100 0x07060504 0x0b0a0908 0x0f0e0d0c)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (v128.const i32x4 0x00010000 0x00030002 0x00050004 0x00070006)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (v128.const i32x4 0x00000000 0x00000001 0x00000002 0x00000003)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (v128.const i32x4 0x00000000 0x00000000 0x00000001 0x00000000)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (v128.const i32x4 0x00000000 0x3f800000 0x40000000 0x40400000)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x3ff00000)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $simd-const
v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
drop
v128.const i16x8 0 1 2 3 4 5 6 7
drop
v128.const i32x4 0 1 2 3
drop
v128.const i64x2 0 1
drop
v128.const f32x4 0.0 1.0 2.0 3.0
drop
v128.const f64x2 0.0 1.0
drop
)

;; CHECK: (func $simd-extract (type $33) (param $0 v128) (result i32)
;; CHECK-NEXT: (i32x4.extract_lane 3
;; CHECK-NEXT: (local.get $0)
Expand Down Expand Up @@ -3587,7 +3622,7 @@
;; CHECK-NEXT: (ref.func $ref-func)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.func $ref-func)
;; CHECK-NEXT: (ref.func $ref-is-null)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $ref-func
Expand Down
Loading