Skip to content

Commit

Permalink
Implement Relaxed SIMD proposal
Browse files Browse the repository at this point in the history
This adds support for the new opcodes from the Relaxed SIMD proposal
(https://github.com/WebAssembly/relaxed-simd) behind the
"--enable-relaxed-simd" flag.
  • Loading branch information
marcusb committed Sep 28, 2022
1 parent a4a77c1 commit 62ead3f
Show file tree
Hide file tree
Showing 35 changed files with 1,766 additions and 1,314 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ Wabt has been compiled to JavaScript via emscripten. Some of the functionality i
| [memory64][] | `--enable-memory64` | ||||| |
| [multi-memory][] | `--enable-multi-memory` | ||||||
| [extended-const][] | `--enable-extended-const` | ||||| |
| [relaxed-simd][] | `--enable-relaxed-simd` | ||||| |

[exception handling]: https://github.com/WebAssembly/exception-handling
[mutable globals]: https://github.com/WebAssembly/mutable-global
Expand All @@ -76,6 +77,7 @@ Wabt has been compiled to JavaScript via emscripten. Some of the functionality i
[memory64]: https://github.com/WebAssembly/memory64
[multi-memory]: https://github.com/WebAssembly/multi-memory
[extended-const]: https://github.com/WebAssembly/extended-const
[relaxed-simd]: https://github.com/WebAssembly/relaxed-simd

## Cloning

Expand Down
1 change: 1 addition & 0 deletions include/wabt/feature.def
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ WABT_FEATURE(gc, "gc", false, "Garbage c
WABT_FEATURE(memory64, "memory64", false, "64-bit memory")
WABT_FEATURE(multi_memory, "multi-memory", false, "Multi-memory")
WABT_FEATURE(extended_const, "extended-const", false, "Extended constant expressions")
WABT_FEATURE(relaxed_simd, "relaxed-simd", false, "Relaxed SIMD")
6 changes: 6 additions & 0 deletions include/wabt/interp/interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,12 @@ class Thread {
template <typename S, typename T>
RunResult DoSimdDot();
template <typename S, typename T>
RunResult DoSimdDotAdd();
template <typename S>
RunResult DoSimdRelaxedFMA();
template <typename S>
RunResult DoSimdRelaxedFMS();
template <typename S, typename T>
RunResult DoSimdLoadExtend(Instr, Trap::Ptr* out_trap);
template <typename S, typename T>
RunResult DoSimdExtaddPairwise();
Expand Down
50 changes: 49 additions & 1 deletion include/wabt/ir.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,54 @@ struct Const {
};
typedef std::vector<Const> ConstVector;

enum class ExpectationType {
Values,
Either,
};

class Expectation {
public:
Expectation() = delete;
virtual ~Expectation() = default;
ExpectationType type() const { return type_; }

Location loc;

ConstVector expected;

protected:
explicit Expectation(ExpectationType type, const Location& loc = Location())
: loc(loc), type_(type) {}

private:
ExpectationType type_;
};

template <ExpectationType TypeEnum>
class ExpectationMixin : public Expectation {
public:
static bool classof(const Expectation* expectation) {
return expectation->type() == TypeEnum;
}

explicit ExpectationMixin(const Location& loc = Location())
: Expectation(TypeEnum, loc) {}
};

class ValueExpectation : public ExpectationMixin<ExpectationType::Values> {
public:
explicit ValueExpectation(const Location& loc = Location())
: ExpectationMixin<ExpectationType::Values>(loc) {}
};

struct EitherExpectation : public ExpectationMixin<ExpectationType::Either> {
public:
explicit EitherExpectation(const Location& loc = Location())
: ExpectationMixin<ExpectationType::Either>(loc) {}
};

typedef std::unique_ptr<Expectation> ExpectationPtr;

struct FuncSignature {
TypeVector param_types;
TypeVector result_types;
Expand Down Expand Up @@ -1375,7 +1423,7 @@ class RegisterCommand : public CommandMixin<CommandType::Register> {
class AssertReturnCommand : public CommandMixin<CommandType::AssertReturn> {
public:
ActionPtr action;
ConstVector expected;
ExpectationPtr expected;
};

template <CommandType TypeEnum>
Expand Down
7 changes: 6 additions & 1 deletion include/wabt/opcode-code-table.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@
extern "C" {
#endif

#define WABT_OPCODE_CODE_TABLE_SIZE 65536
#define WABT_OPCODE_CODE_TABLE_SIZE 131072

/*
* Number of bits required to store an opcode
*/
#define MAX_OPCODE_BITS 9

/* This structure is defined in C because C++ doesn't (yet) allow you to use
* designated array initializers, i.e. [10] = {foo}.
Expand Down
22 changes: 22 additions & 0 deletions include/wabt/opcode.def
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,28 @@ WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xfd, I32X4TruncSatF64X2UZero, "i3
WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xfe, F64X2ConvertLowI32X4S, "f64x2.convert_low_i32x4_s", "")
WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xff, F64X2ConvertLowI32X4U, "f64x2.convert_low_i32x4_u", "")

/* Relaxed-SIMD opcodes */
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x100, I8X16RelaxedSwizzle, "i8x16.relaxed_swizzle", "")
WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x101, I32X4RelaxedTruncF32X4S, "i32x4.relaxed_trunc_f32x4_s", "")
WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x102, I32X4RelaxedTruncF32X4U, "i32x4.relaxed_trunc_f32x4_u", "")
WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x103, I32X4RelaxedTruncF64X2SZero, "i32x4.relaxed_trunc_f64x2_s_zero", "")
WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x104, I32X4RelaxedTruncF64X2UZero, "i32x4.relaxed_trunc_f64x2_u_zero", "")
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x105, F32X4RelaxedFMA, "f32x4.relaxed_fma", "")
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x106, F32X4RelaxedFMS, "f32x4.relaxed_fms", "")
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x107, F64X2RelaxedFMA, "f64x2.relaxed_fma", "")
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x108, F64X2RelaxedFMS, "f64x2.relaxed_fms", "")
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x109, I8X16RelaxedLaneSelect, "i8x16.relaxed_laneselect", "")
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x10a, I16X8RelaxedLaneSelect, "i16x8.relaxed_laneselect", "")
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x10b, I32X4RelaxedLaneSelect, "i32x4.relaxed_laneselect", "")
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x10c, I64X2RelaxedLaneSelect, "i64x2.relaxed_laneselect", "")
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x10d, F32X4RelaxedMin, "f32x4.relaxed_min", "")
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x10e, F32X4RelaxedMax, "f32x4.relaxed_max", "")
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x10f, F64X2RelaxedMin, "f64x2.relaxed_min", "")
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x110, F64X2RelaxedMax, "f64x2.relaxed_max", "")
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x111, I16X8RelaxedQ15mulrS, "i16x8.relaxed_q15mulr_s", "")
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x112, I16X8DotI8X16I7X16S, "i16x8.dot_i8x16_i7x16_s", "")
WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x113, I32X4DotI8X16I7X16AddS, "i32x4.dot_i8x16_i7x16_add_s", "")

/* Thread opcodes (--enable-threads) */
WABT_OPCODE(I32, I32, I32, ___, 4, 0xfe, 0x00, MemoryAtomicNotify, "memory.atomic.notify", "")
WABT_OPCODE(I32, I32, I32, I64, 4, 0xfe, 0x01, MemoryAtomicWait32, "memory.atomic.wait32", "")
Expand Down
11 changes: 5 additions & 6 deletions include/wabt/opcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,11 @@ struct Opcode {
};

static uint32_t PrefixCode(uint8_t prefix, uint32_t code) {
// For now, 8 bits is enough for all codes.
if (code >= 0x100) {
// Clamp to 0xff, since we know that it is an invalid code.
code = 0xff;
if (code >= (1 << MAX_OPCODE_BITS)) {
// Clamp to (2^bits - 1), since we know that it is an invalid code.
code = (1 << MAX_OPCODE_BITS) - 1;
}
return (prefix << 8) | code;
return (prefix << MAX_OPCODE_BITS) | code;
}

// The Opcode struct only stores an enumeration (Opcode::Enum) of all valid
Expand All @@ -145,7 +144,7 @@ struct Opcode {
uint8_t* out_prefix,
uint32_t* out_code) {
uint32_t prefix_code = ~static_cast<uint32_t>(e) + 1;
*out_prefix = prefix_code >> 8;
*out_prefix = prefix_code >> MAX_OPCODE_BITS;
*out_code = prefix_code & 0xff;
}

Expand Down
1 change: 1 addition & 0 deletions include/wabt/token.def
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ WABT_TOKEN(Data, "data")
WABT_TOKEN(Declare, "declare")
WABT_TOKEN(Delegate, "delegate")
WABT_TOKEN(Do, "do")
WABT_TOKEN(Either, "either")
WABT_TOKEN(Elem, "elem")
WABT_TOKEN(Eof, "EOF")
WABT_TOKEN(Tag, "tag")
Expand Down
2 changes: 2 additions & 0 deletions include/wabt/wast-parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ class WastParser {
Result ParseF32(Const*, ConstType type);
Result ParseF64(Const*, ConstType type);
Result ParseConst(Const*, ConstType type);
Result ParseExpectedValues(ExpectationPtr*);
Result ParseEither(ConstVector*);
Result ParseExternref(Const*);
Result ParseExpectedNan(ExpectedNan* expected);
Result ParseConstList(ConstVector*, ConstType type);
Expand Down
20 changes: 20 additions & 0 deletions src/binary-reader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,13 @@ Result BinaryReader::ReadInstructions(bool stop_on_end,
case Opcode::I64X2ExtmulHighI32X4U:
case Opcode::I16X8Q15mulrSatS:
case Opcode::I32X4DotI16X8S:
case Opcode::I8X16RelaxedSwizzle:
case Opcode::F32X4RelaxedMin:
case Opcode::F32X4RelaxedMax:
case Opcode::F64X2RelaxedMin:
case Opcode::F64X2RelaxedMax:
case Opcode::I16X8RelaxedQ15mulrS:
case Opcode::I16X8DotI8X16I7X16S:
CALLBACK(OnBinaryExpr, opcode);
CALLBACK0(OnOpcodeBare);
break;
Expand Down Expand Up @@ -1319,11 +1326,24 @@ Result BinaryReader::ReadInstructions(bool stop_on_end,
case Opcode::I16X8ExtaddPairwiseI8X16U:
case Opcode::I32X4ExtaddPairwiseI16X8S:
case Opcode::I32X4ExtaddPairwiseI16X8U:
case Opcode::I32X4RelaxedTruncF32X4S:
case Opcode::I32X4RelaxedTruncF32X4U:
case Opcode::I32X4RelaxedTruncF64X2SZero:
case Opcode::I32X4RelaxedTruncF64X2UZero:
CALLBACK(OnUnaryExpr, opcode);
CALLBACK0(OnOpcodeBare);
break;

case Opcode::V128BitSelect:
case Opcode::F32X4RelaxedFMA:
case Opcode::F32X4RelaxedFMS:
case Opcode::F64X2RelaxedFMA:
case Opcode::F64X2RelaxedFMS:
case Opcode::I8X16RelaxedLaneSelect:
case Opcode::I16X8RelaxedLaneSelect:
case Opcode::I32X4RelaxedLaneSelect:
case Opcode::I64X2RelaxedLaneSelect:
case Opcode::I32X4DotI8X16I7X16AddS:
CALLBACK(OnTernaryExpr, opcode);
CALLBACK0(OnOpcodeBare);
break;
Expand Down
13 changes: 11 additions & 2 deletions src/binary-writer-spec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -568,8 +568,17 @@ void BinaryWriterSpec::WriteCommands() {
WriteSeparator();
WriteAction(*assert_return_command->action);
WriteSeparator();
WriteKey("expected");
WriteConstVector(assert_return_command->expected);
const Expectation* expectation = assert_return_command->expected.get();
switch (expectation->type()) {
case ExpectationType::Values:
WriteKey("expected");
break;

case ExpectationType::Either:
WriteKey("either");
break;
}
WriteConstVector(expectation->expected);
break;
}

Expand Down
Loading

0 comments on commit 62ead3f

Please sign in to comment.