summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/literal.h67
-rw-r--r--src/wasm/literal.cpp73
2 files changed, 107 insertions, 33 deletions
diff --git a/src/literal.h b/src/literal.h
index ce245d940..c0e43eb88 100644
--- a/src/literal.h
+++ b/src/literal.h
@@ -215,6 +215,7 @@ public:
int64_t getInteger() const;
uint64_t getUnsigned() const;
double getFloat() const;
+ // Obtains the bits of a basic value typed literal.
void getBits(uint8_t (&buf)[16]) const;
// Equality checks for the type and the bits, so a nan float would
// be compared bitwise (which means that a Literal containing a nan
@@ -562,14 +563,66 @@ std::ostream& operator<<(std::ostream& o, const ExceptionPackage& exn);
namespace std {
template<> struct hash<wasm::Literal> {
size_t operator()(const wasm::Literal& a) const {
- uint8_t bytes[16];
- a.getBits(bytes);
- int64_t chunks[2];
- memcpy(chunks, bytes, sizeof(chunks));
auto digest = wasm::hash(a.type.getID());
- wasm::rehash(digest, chunks[0]);
- wasm::rehash(digest, chunks[1]);
- return digest;
+ auto hashRef = [&]() {
+ assert(a.type.isRef());
+ if (a.isNull()) {
+ return digest;
+ }
+ if (a.type.isFunction()) {
+ wasm::rehash(digest, a.getFunc());
+ return digest;
+ }
+ if (a.type.isException()) {
+ auto exn = a.getExceptionPackage();
+ wasm::rehash(digest, exn.event);
+ wasm::rehash(digest, exn.values);
+ return digest;
+ }
+ // 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 (a.type.isBasic()) {
+ switch (a.type.getBasic()) {
+ case wasm::Type::i32:
+ wasm::rehash(digest, a.geti32());
+ return digest;
+ case wasm::Type::f32:
+ wasm::rehash(digest, a.reinterpreti32());
+ return digest;
+ case wasm::Type::i64:
+ wasm::rehash(digest, a.geti64());
+ return digest;
+ case wasm::Type::f64:
+ wasm::rehash(digest, a.reinterpreti64());
+ return digest;
+ case wasm::Type::v128:
+ uint64_t chunks[2];
+ memcpy(&chunks, a.getv128Ptr(), 16);
+ wasm::rehash(digest, chunks[0]);
+ wasm::rehash(digest, chunks[1]);
+ return digest;
+ case wasm::Type::funcref:
+ case wasm::Type::externref:
+ case wasm::Type::exnref:
+ case wasm::Type::anyref:
+ case wasm::Type::eqref:
+ return hashRef();
+ case wasm::Type::i31ref:
+ wasm::rehash(digest, a.geti31(true));
+ return digest;
+ case wasm::Type::none:
+ case wasm::Type::unreachable:
+ break;
+ }
+ } else if (a.type.isRef()) {
+ return hashRef();
+ } else if (a.type.isRtt()) {
+ WASM_UNREACHABLE("TODO: rtt literals");
+ }
+ WASM_UNREACHABLE("unexpected type");
}
};
template<> struct hash<wasm::Literals> {
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 {