-
Notifications
You must be signed in to change notification settings - Fork 791
Update testsuite (for SIMD) #1373
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
Conversation
Lots of changes necessary to make this work, as well as some bug fixes.
The main change is allowing `nan:canonical` and `nan:arithmetic` as a
possible value for each lane of a `v128`. This needs to propogate
through the parser, IR, the JSON format, and the spec interpreter.
This also changes the format of the spec JSON file, where a SIMD value
is now stored as a list of values instead of a single u128:
```
{"type": "v128", "lane_type": "i32", "value": ["0", "0", "0", "0"]}
```
Since the lane type can be `i8` and `i16`, these types can now be used
in more places (not just the decompiler). They'll be used for the GC
proposal too (for packed values), so I've updated them to use the binary
value specified for that proposal.
Here are the actual SIMD fixes:
* SIMD lanes are malformed if they don't match the binary format, but
invalid if they are smaller than the lane width. For example,
`i8x16.extract_lane_s` is malformed if the lane is >= 256, because the
lane is stored as a byte. But it is invalid if the lane is >= 16.
* The `i8x16.narrow_i16x8_u`, `i16x8.narrow_i32x4_u` and
`i64x2.load_32x2_u` instructions were not handling sign-extension
propoerly.
TODO: This code is pretty clumsy now; it would be better to have a
universal `Value` and `ExpectedValue` that can be used everywhere, so
the logic doesn't need to be duplicated.
| break; | ||
|
|
||
| case ExpectedNan::Arithmetic: | ||
| WriteString("nan:arithmetic"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated: Why is this called BinaryWriter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question, it should be JSONWriter I suppose. I think it was historical, because the old binary-writer used to contain this stuff too, so I probably kept the name when I split it out.
| case O::I32X4Load16X4S: return DoSimdLoadExtend<s32x4, s16x4>(instr, out_trap); | ||
| case O::I32X4Load16X4U: return DoSimdLoadExtend<u32x4, u16x4>(instr, out_trap); | ||
| case O::I64X2Load32X2S: return DoSimdLoadExtend<s64x2, s32x2>(instr, out_trap); | ||
| case O::I64X2Load32X2U: return DoSimdLoadExtend<s64x2, s32x2>(instr, out_trap); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this simply a bugfix here? Why didn't it show up before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There weren't any tests of the output before, this is a relatively new instruction.
| void set_f32(ExpectedNan nan) { From<float>(Type::F32, 0); nan_ = nan; } | ||
| void set_f64(ExpectedNan nan) { From<double>(Type::F64, 0); nan_ = nan; } | ||
| void set_f32(ExpectedNan nan) { set_f32(0); set_expected_nan(0, nan); } | ||
| void set_f64(ExpectedNan nan) { set_f64(0); set_expected_nan(0, nan); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is clang format OK with multiple statements on one line like this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it will expand, though I kind of prefer keeping it on a single line for readability. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depends what you want the policy for wabt to be ? Absolute deferral to clang-format, or programmer discretion. I don't think there is one correct answer. It depends on the project. We don't have a lot of formatting discussions so allowing discretion isn't currently effecting productivity. So I'm OK with either way right now. We should probably document it though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm thinking I'll spend some time writing up a C++ style guide finally this week.
src/tools/spectest-interp.cc
Outdated
| PARSE_KEY_STRING_VALUE("value", &value_str); | ||
| EXPECT("}"); | ||
| ExpectedValue expected; | ||
| CHECK_RESULT(ParseExpectedValue(&expected)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are all the consts in the JSON expected values? What about const argument values?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the expected values are more expressive. It's nice to be able to share the code since it's a significant amount of code. But yeah, I'll add an enum to make sure we don't parse stuff that isn't valid.
| ProcessProposalDir('bulk-memory-operations', '--enable-bulk-memory') | ||
| ProcessProposalDir('reference-types', '--enable-reference-types') | ||
| ProcessProposalDir('simd', '--enable-simd') | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops.. is this why there were so many new tests added here? I guess we were not updating the simd tests previously?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I guess there weren't SIMD tests for a while...
* Remove private from v128 (causes gcc warning) * Fix stack smashing in `Const` (need to use `set_expected_nan` to avoid writing past lane 3) * Add `AllowExpected` enum, used to prevent parsing `nan:canonical` and `nan:arithmetic` for const values (i.e. invocation arguments).
`u16 * u16` has the type `int`. If the values are 65535 and 65535, then the value can't be stored in an int (`0xfffe0001`), which makes UBSan complain. We want wrapping behavior anyway, so cast this to a T. Note that this isn't an issue with the other operations, since those all fit in an `int`.
Lots of changes necessary to make this work, as well as some bug fixes.
The main change is allowing
nan:canonicalandnan:arithmeticas apossible value for each lane of a
v128. This needs to propogatethrough the parser, IR, the JSON format, and the spec interpreter.
This also changes the format of the spec JSON file, where a SIMD value
is now stored as a list of values instead of a single u128:
Since the lane type can be
i8andi16, these types can now be usedin more places (not just the decompiler). They'll be used for the GC
proposal too (for packed values), so I've updated them to use the binary
value specified for that proposal.
Here are the actual SIMD fixes:
invalid if they are smaller than the lane width. For example,
i8x16.extract_lane_sis malformed if the lane is >= 256, because thelane is stored as a byte. But it is invalid if the lane is >= 16.
i8x16.narrow_i16x8_u,i16x8.narrow_i32x4_uandi64x2.load_32x2_uinstructions were not handling sign-extensionpropoerly.
TODO: This code is pretty clumsy now; it would be better to have a
universal
ValueandExpectedValuethat can be used everywhere, sothe logic doesn't need to be duplicated.