summaryrefslogtreecommitdiff
path: root/src/passes
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes')
-rw-r--r--src/passes/ConstHoisting.cpp8
-rw-r--r--src/passes/FuncCastEmulation.cpp14
-rw-r--r--src/passes/InstrumentLocals.cpp167
-rw-r--r--src/passes/OptimizeInstructions.cpp8
-rw-r--r--src/passes/Precompute.cpp3
-rw-r--r--src/passes/Print.cpp98
6 files changed, 144 insertions, 154 deletions
diff --git a/src/passes/ConstHoisting.cpp b/src/passes/ConstHoisting.cpp
index 3320c129b..3d9ac5e90 100644
--- a/src/passes/ConstHoisting.cpp
+++ b/src/passes/ConstHoisting.cpp
@@ -89,15 +89,9 @@ private:
size = value.type.getByteSize();
break;
}
- // not implemented yet
+ // not implemented yet
case Type::v128:
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref: {
return false;
- }
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
diff --git a/src/passes/FuncCastEmulation.cpp b/src/passes/FuncCastEmulation.cpp
index 704f44e03..5e62ec9fc 100644
--- a/src/passes/FuncCastEmulation.cpp
+++ b/src/passes/FuncCastEmulation.cpp
@@ -62,13 +62,6 @@ static Expression* toABI(Expression* value, Module* module) {
case Type::v128: {
WASM_UNREACHABLE("v128 not implemented yet");
}
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref: {
- WASM_UNREACHABLE("reference types cannot be converted to i64");
- }
case Type::none: {
// the value is none, but we need a value here
value =
@@ -107,13 +100,6 @@ static Expression* fromABI(Expression* value, Type type, Module* module) {
case Type::v128: {
WASM_UNREACHABLE("v128 not implemented yet");
}
- case Type::funcref:
- case Type::anyref:
- case Type::eqref:
- case Type::i31ref:
- case Type::dataref: {
- WASM_UNREACHABLE("reference types cannot be converted from i64");
- }
case Type::none: {
value = builder.makeDrop(value);
break;
diff --git a/src/passes/InstrumentLocals.cpp b/src/passes/InstrumentLocals.cpp
index 3bf23b61c..761aac2a9 100644
--- a/src/passes/InstrumentLocals.cpp
+++ b/src/passes/InstrumentLocals.cpp
@@ -58,9 +58,6 @@ Name get_f64("get_f64");
Name get_v128("get_v128");
Name get_funcref("get_funcref");
Name get_anyref("get_anyref");
-Name get_eqref("get_eqref");
-Name get_i31ref("get_i31ref");
-Name get_dataref("get_dataref");
Name set_i32("set_i32");
Name set_i64("set_i64");
@@ -69,48 +66,41 @@ Name set_f64("set_f64");
Name set_v128("set_v128");
Name set_funcref("set_funcref");
Name set_anyref("set_anyref");
-Name set_eqref("set_eqref");
-Name set_i31ref("set_i31ref");
-Name set_dataref("set_dataref");
struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
void visitLocalGet(LocalGet* curr) {
Builder builder(*getModule());
Name import;
- TODO_SINGLE_COMPOUND(curr->type);
- switch (curr->type.getBasic()) {
- case Type::i32:
- import = get_i32;
- break;
- case Type::i64:
- return; // TODO
- case Type::f32:
- import = get_f32;
- break;
- case Type::f64:
- import = get_f64;
- break;
- case Type::v128:
- import = get_v128;
- break;
- case Type::funcref:
+ if (curr->type.isRef()) {
+ auto heapType = curr->type.getHeapType();
+ if (heapType == HeapType::func && curr->type.isNullable()) {
import = get_funcref;
- break;
- case Type::anyref:
+ } else if (heapType == HeapType::any && curr->type.isNullable()) {
import = get_anyref;
- break;
- case Type::eqref:
- import = get_eqref;
- break;
- case Type::i31ref:
- import = get_i31ref;
- break;
- case Type::dataref:
- import = get_dataref;
- break;
- case Type::none:
- case Type::unreachable:
- WASM_UNREACHABLE("unexpected type");
+ } else {
+ WASM_UNREACHABLE("TODO: general reference types");
+ }
+ } else {
+ TODO_SINGLE_COMPOUND(curr->type);
+ switch (curr->type.getBasic()) {
+ case Type::i32:
+ import = get_i32;
+ break;
+ case Type::i64:
+ return; // TODO
+ case Type::f32:
+ import = get_f32;
+ break;
+ case Type::f64:
+ import = get_f64;
+ break;
+ case Type::v128:
+ import = get_v128;
+ break;
+ case Type::none:
+ case Type::unreachable:
+ WASM_UNREACHABLE("unexpected type");
+ }
}
replaceCurrent(builder.makeCall(import,
{builder.makeConst(int32_t(id++)),
@@ -130,45 +120,41 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
Builder builder(*getModule());
Name import;
auto type = curr->value->type;
- if (type.isFunction() && type != Type::funcref) {
+ if (type.isFunction() && type.getHeapType() != HeapType::func) {
// FIXME: support typed function references
return;
}
- TODO_SINGLE_COMPOUND(curr->value->type);
- switch (type.getBasic()) {
- case Type::i32:
- import = set_i32;
- break;
- case Type::i64:
- return; // TODO
- case Type::f32:
- import = set_f32;
- break;
- case Type::f64:
- import = set_f64;
- break;
- case Type::v128:
- import = set_v128;
- break;
- case Type::funcref:
+ if (type.isRef()) {
+ auto heapType = type.getHeapType();
+ if (heapType == HeapType::func && type.isNullable()) {
import = set_funcref;
- break;
- case Type::anyref:
+ } else if (heapType == HeapType::any && type.isNullable()) {
import = set_anyref;
- break;
- case Type::eqref:
- import = set_eqref;
- break;
- case Type::i31ref:
- import = set_i31ref;
- break;
- case Type::dataref:
- import = set_dataref;
- break;
- case Type::unreachable:
- return; // nothing to do here
- default:
- WASM_UNREACHABLE("unexpected type");
+ } else {
+ WASM_UNREACHABLE("TODO: general reference types");
+ }
+ } else {
+ TODO_SINGLE_COMPOUND(curr->value->type);
+ switch (type.getBasic()) {
+ case Type::i32:
+ import = set_i32;
+ break;
+ case Type::i64:
+ return; // TODO
+ case Type::f32:
+ import = set_f32;
+ break;
+ case Type::f64:
+ import = set_f64;
+ break;
+ case Type::v128:
+ import = set_v128;
+ break;
+ case Type::unreachable:
+ return; // nothing to do here
+ case Type::none:
+ WASM_UNREACHABLE("unexpected type");
+ }
}
curr->value = builder.makeCall(import,
{builder.makeConst(int32_t(id++)),
@@ -188,36 +174,13 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
addImport(curr, set_f64, {Type::i32, Type::i32, Type::f64}, Type::f64);
if (curr->features.hasReferenceTypes()) {
- addImport(curr,
- get_funcref,
- {Type::i32, Type::i32, Type::funcref},
- Type::funcref);
- addImport(curr,
- set_funcref,
- {Type::i32, Type::i32, Type::funcref},
- Type::funcref);
- addImport(
- curr, get_anyref, {Type::i32, Type::i32, Type::anyref}, Type::anyref);
- addImport(
- curr, set_anyref, {Type::i32, Type::i32, Type::anyref}, Type::anyref);
- if (curr->features.hasGC()) {
- addImport(
- curr, get_eqref, {Type::i32, Type::i32, Type::eqref}, Type::eqref);
- addImport(
- curr, set_eqref, {Type::i32, Type::i32, Type::eqref}, Type::eqref);
- addImport(
- curr, get_i31ref, {Type::i32, Type::i32, Type::i31ref}, Type::i31ref);
- addImport(
- curr, set_i31ref, {Type::i32, Type::i32, Type::i31ref}, Type::i31ref);
- addImport(curr,
- get_dataref,
- {Type::i32, Type::i32, Type::dataref},
- Type::dataref);
- addImport(curr,
- set_dataref,
- {Type::i32, Type::i32, Type::dataref},
- Type::dataref);
- }
+ Type func = Type(HeapType::func, Nullable);
+ Type any = Type(HeapType::any, Nullable);
+
+ addImport(curr, get_funcref, {Type::i32, Type::i32, func}, func);
+ addImport(curr, set_funcref, {Type::i32, Type::i32, func}, func);
+ addImport(curr, get_anyref, {Type::i32, Type::i32, any}, any);
+ addImport(curr, set_anyref, {Type::i32, Type::i32, any}, any);
}
if (curr->features.hasSIMD()) {
addImport(curr, get_v128, {Type::i32, Type::i32, Type::v128}, Type::v128);
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 9d50275b9..9ab8e20d9 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -1472,7 +1472,8 @@ struct OptimizeInstructions
// there.
//
// See "notes on removing casts", above, for when this is safe to do.
- void skipCast(Expression*& input, Type requiredType = Type::anyref) {
+ void skipCast(Expression*& input,
+ Type requiredType = Type(HeapType::any, Nullable)) {
// Traps-never-happen mode is a requirement for us to optimize here.
if (!getPassOptions().trapsNeverHappen) {
return;
@@ -1523,8 +1524,9 @@ struct OptimizeInstructions
// This is safe to do first because nothing farther down cares about the
// type, and we consume the two input references, so removing a cast could
// not help our parents (see "notes on removing casts").
- skipCast(curr->left, Type::eqref);
- skipCast(curr->right, Type::eqref);
+ Type nullableEq = Type(HeapType::eq, Nullable);
+ skipCast(curr->left, nullableEq);
+ skipCast(curr->right, nullableEq);
// Identical references compare equal.
// (Technically we do not need to check if the inputs are also foldable into
diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp
index f599990a0..156c33c3f 100644
--- a/src/passes/Precompute.cpp
+++ b/src/passes/Precompute.cpp
@@ -249,7 +249,8 @@ struct Precompute
curr->finalize();
return;
}
- } else if (singleValue.type == Type::funcref) {
+ } else if (singleValue.type.isRef() &&
+ singleValue.type.getHeapType() == HeapType::func) {
if (auto* r = curr->value->template dynCast<RefFunc>()) {
r->func = singleValue.getFunc();
r->finalize();
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index ca2985240..440ff114f 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -72,6 +72,62 @@ static std::ostream& printLocal(Index index, Function* func, std::ostream& o) {
namespace {
+static bool maybePrintRefShorthand(std::ostream& o, Type type) {
+ if (!type.isRef()) {
+ return false;
+ }
+ auto heapType = type.getHeapType();
+ if (heapType.isBasic()) {
+ if (type.isNullable()) {
+ switch (heapType.getBasic()) {
+ case HeapType::func:
+ o << "funcref";
+ return true;
+ case HeapType::any:
+ o << "anyref";
+ return true;
+ case HeapType::eq:
+ o << "eqref";
+ return true;
+ case HeapType::i31:
+ case HeapType::data:
+ break;
+ case HeapType::string:
+ o << "stringref";
+ return true;
+ case HeapType::stringview_wtf8:
+ o << "stringview_wtf8";
+ return true;
+ case HeapType::stringview_wtf16:
+ o << "stringview_wtf16";
+ return true;
+ case HeapType::stringview_iter:
+ o << "stringview_iter";
+ return true;
+ }
+ } else {
+ switch (heapType.getBasic()) {
+ case HeapType::func:
+ case HeapType::any:
+ case HeapType::eq:
+ break;
+ case HeapType::i31:
+ o << "i31ref";
+ return true;
+ case HeapType::data:
+ o << "dataref";
+ return true;
+ case HeapType::string:
+ case HeapType::stringview_wtf8:
+ case HeapType::stringview_wtf16:
+ case HeapType::stringview_iter:
+ break;
+ }
+ }
+ }
+ return false;
+}
+
// Helper for printing the name of a type. This output is guaranteed to not
// contain spaces.
struct TypeNamePrinter {
@@ -126,13 +182,15 @@ void TypeNamePrinter::print(Type type) {
} else if (type.isRtt()) {
print(type.getRtt());
} else if (type.isRef()) {
- os << "ref";
- if (type.isNullable()) {
- os << "?";
+ if (!maybePrintRefShorthand(os, type)) {
+ os << "ref";
+ if (type.isNullable()) {
+ os << "?";
+ }
+ os << '|';
+ print(type.getHeapType());
+ os << '|';
}
- os << '|';
- print(type.getHeapType());
- os << '|';
} else {
WASM_UNREACHABLE("unexpected type");
}
@@ -273,29 +331,15 @@ static std::ostream& printType(std::ostream& o, Type type, Module* wasm) {
}
TypeNamePrinter(o, wasm).print(rtt.heapType);
o << ')';
- } else if (type.isRef() && !type.isBasic()) {
- auto heapType = type.getHeapType();
- if (type.isNullable() && heapType.isBasic()) {
- // Print shorthands for certain nullable basic heap types.
- switch (heapType.getBasic()) {
- case HeapType::string:
- return o << "stringref";
- case HeapType::stringview_wtf8:
- return o << "stringview_wtf8";
- case HeapType::stringview_wtf16:
- return o << "stringview_wtf16";
- case HeapType::stringview_iter:
- return o << "stringview_iter";
- default:
- break;
+ } else if (type.isRef()) {
+ if (!maybePrintRefShorthand(o, type)) {
+ o << "(ref ";
+ if (type.isNullable()) {
+ o << "null ";
}
+ TypeNamePrinter(o, wasm).print(type.getHeapType());
+ o << ')';
}
- o << "(ref ";
- if (type.isNullable()) {
- o << "null ";
- }
- TypeNamePrinter(o, wasm).print(type.getHeapType());
- o << ')';
} else {
WASM_UNREACHABLE("unexpected type");
}