summaryrefslogtreecommitdiff
path: root/src/wasm/literal.cpp
diff options
context:
space:
mode:
authorDaniel Wirtz <dcode@dcode.io>2020-09-29 17:10:16 +0200
committerGitHub <noreply@github.com>2020-09-29 17:10:16 +0200
commite9e5f30212f44927859d3dad5fe48499d860f61c (patch)
tree242f856f04b95db6dc2e8e67b78da8cc410d0da1 /src/wasm/literal.cpp
parent9de15862c1bc4e2b092ccbe89fdb4b850704bbfc (diff)
downloadbinaryen-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.cpp73
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 {