summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm/literal.cpp110
1 files changed, 63 insertions, 47 deletions
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index e761206bc..ea398acd3 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -30,19 +30,41 @@ namespace wasm {
template<int N> using LaneArray = std::array<Literal, N>;
Literal::Literal(Type type) : type(type) {
- if (type == Type::i31ref) {
- // i31ref is special in that it is non-nullable, so we construct with zero
- i32 = 0;
- } else {
- assert(type != Type::unreachable && !type.isNonNullable());
- if (isData()) {
- new (&gcData) std::shared_ptr<GCData>();
- } else if (type.isRtt()) {
- new (this) Literal(Literal::makeCanonicalRtt(type.getHeapType()));
- } else {
- memset(&v128, 0, 16);
+ if (type.isBasic()) {
+ switch (type.getBasic()) {
+ case Type::i32:
+ case Type::f32:
+ i32 = 0;
+ return;
+ case Type::i64:
+ case Type::f64:
+ i64 = 0;
+ return;
+ case Type::v128:
+ memset(&v128, 0, 16);
+ return;
+ case Type::none:
+ return;
+ case Type::unreachable:
+ case Type::funcref:
+ case Type::externref:
+ case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
+ case Type::dataref:
+ break;
}
}
+
+ if (isData()) {
+ assert(!type.isNonNullable());
+ new (&gcData) std::shared_ptr<GCData>();
+ } else if (type.isRtt()) {
+ new (this) Literal(Literal::makeCanonicalRtt(type.getHeapType()));
+ } else {
+ // For anything else, zero out all the union data.
+ memset(&v128, 0, 16);
+ }
}
Literal::Literal(const uint8_t init[16]) : type(Type::v128) {
@@ -63,6 +85,31 @@ Literal::Literal(std::unique_ptr<RttSupers>&& rttSupers, Type type)
}
Literal::Literal(const Literal& other) : type(other.type) {
+ if (type.isBasic()) {
+ switch (type.getBasic()) {
+ case Type::i32:
+ case Type::f32:
+ i32 = other.i32;
+ return;
+ case Type::i64:
+ case Type::f64:
+ i64 = other.i64;
+ return;
+ case Type::v128:
+ memcpy(&v128, other.v128, 16);
+ return;
+ case Type::none:
+ return;
+ case Type::unreachable:
+ case Type::funcref:
+ case Type::externref:
+ case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
+ case Type::dataref:
+ break;
+ }
+ }
if (other.isData()) {
new (&gcData) std::shared_ptr<GCData>(other.gcData);
return;
@@ -93,49 +140,18 @@ Literal::Literal(const Literal& other) : type(other.type) {
}
}
}
- TODO_SINGLE_COMPOUND(type);
- switch (type.getBasic()) {
- case Type::i32:
- case Type::f32:
- i32 = other.i32;
- break;
- case Type::i64:
- case Type::f64:
- i64 = other.i64;
- break;
- case Type::v128:
- memcpy(&v128, other.v128, 16);
- break;
- case Type::none:
- break;
- case Type::unreachable:
- case Type::funcref:
- case Type::externref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref:
- WASM_UNREACHABLE("invalid type");
- }
}
Literal::~Literal() {
+ // Early exit for the common case; basic types need no special handling.
+ if (type.isBasic()) {
+ return;
+ }
+
if (isData()) {
gcData.~shared_ptr();
} else if (type.isRtt()) {
rttSupers.~unique_ptr();
- } else if (type.isFunction() || type.isRef()) {
- // Nothing special to do for a function or a non-GC reference (GC data was
- // handled earlier). For references, this handles the case of (ref ? i31)
- // for example, which may or may not be basic.
- } else {
- // Basic types need no special handling.
- // TODO: change this to an assert after we figure out the underlying issue
- // on the release builder
- // https://github.com/WebAssembly/binaryen/issues/3459
- if (!type.isBasic()) {
- Fatal() << "~Literal on unhandled type: " << type << '\n';
- }
}
}