diff options
author | Daniel Wirtz <dcode@dcode.io> | 2020-09-29 17:10:16 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-29 17:10:16 +0200 |
commit | e9e5f30212f44927859d3dad5fe48499d860f61c (patch) | |
tree | 242f856f04b95db6dc2e8e67b78da8cc410d0da1 /src/wasm/literal.cpp | |
parent | 9de15862c1bc4e2b092ccbe89fdb4b850704bbfc (diff) | |
download | binaryen-e9e5f30212f44927859d3dad5fe48499d860f61c.tar.gz binaryen-e9e5f30212f44927859d3dad5fe48499d860f61c.tar.bz2 binaryen-e9e5f30212f44927859d3dad5fe48499d860f61c.zip |
Refactor literal equality and hashing to not depend on getBits (#3159)
Comparing and hashing literals previously depended on `getBits`, which was fine while there were only basic numeric types, but doesn't map well to reference types anymore. Hence this change limits the use of `getBits` to basic numeric types, and implements reference types-aware comparisons and hashing do deal with the newer types.
Diffstat (limited to 'src/wasm/literal.cpp')
-rw-r--r-- | src/wasm/literal.cpp | 73 |
1 files changed, 47 insertions, 26 deletions
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 6b63d2ca5..a7c14fdb6 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -220,11 +220,9 @@ double Literal::getFloat() const { void Literal::getBits(uint8_t (&buf)[16]) const { memset(buf, 0, 16); - TODO_SINGLE_COMPOUND(type); switch (type.getBasic()) { case Type::i32: case Type::f32: - case Type::i31ref: memcpy(buf, &i32, sizeof(i32)); break; case Type::i64: @@ -234,19 +232,14 @@ void Literal::getBits(uint8_t (&buf)[16]) const { case Type::v128: memcpy(buf, &v128, sizeof(v128)); break; - // TODO: investigate changing bits returned for reference types. currently, - // `null` values and even non-`null` functions return all zeroes, but only - // to avoid introducing a functional change. + case Type::none: + case Type::unreachable: case Type::funcref: - break; case Type::externref: case Type::exnref: case Type::anyref: case Type::eqref: - assert(isNull() && "unexpected non-null reference type literal"); - break; - case Type::none: - case Type::unreachable: + case Type::i31ref: WASM_UNREACHABLE("invalid type"); } } @@ -255,23 +248,51 @@ bool Literal::operator==(const Literal& other) const { if (type != other.type) { return false; } - if (type == Type::none) { - return true; - } - if (isNull() || other.isNull()) { - return isNull() == other.isNull(); - } - if (type.isFunction()) { - return func == other.func; - } - if (type.isException()) { - assert(exn != nullptr && other.exn != nullptr); - return *exn == *other.exn; + auto compareRef = [&]() { + assert(type.isRef()); + if (isNull() || other.isNull()) { + return isNull() == other.isNull(); + } + if (type.isFunction()) { + assert(func.is() && other.func.is()); + return func == other.func; + } + if (type.isException()) { + assert(exn != nullptr && other.exn != nullptr); + return *exn == *other.exn; + } + // other non-null reference type literals cannot represent concrete values, + // i.e. there is no concrete externref, anyref or eqref other than null. + WASM_UNREACHABLE("unexpected type"); + }; + if (type.isBasic()) { + switch (type.getBasic()) { + case Type::none: + return true; // special voided literal + case Type::i32: + case Type::f32: + case Type::i31ref: + return i32 == other.i32; + case Type::i64: + case Type::f64: + return i64 == other.i64; + case Type::v128: + return memcmp(v128, other.v128, 16) == 0; + case Type::funcref: + case Type::externref: + case Type::exnref: + case Type::anyref: + case Type::eqref: + return compareRef(); + case Type::unreachable: + break; + } + } else if (type.isRef()) { + return compareRef(); + } else if (type.isRtt()) { + WASM_UNREACHABLE("TODO: rtt literals"); } - uint8_t bits[16], other_bits[16]; - getBits(bits); - other.getBits(other_bits); - return memcmp(bits, other_bits, 16) == 0; + WASM_UNREACHABLE("unexpected type"); } bool Literal::operator!=(const Literal& other) const { |