diff options
Diffstat (limited to 'src/passes')
-rw-r--r-- | src/passes/ConstHoisting.cpp | 8 | ||||
-rw-r--r-- | src/passes/FuncCastEmulation.cpp | 14 | ||||
-rw-r--r-- | src/passes/InstrumentLocals.cpp | 167 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 8 | ||||
-rw-r--r-- | src/passes/Precompute.cpp | 3 | ||||
-rw-r--r-- | src/passes/Print.cpp | 98 |
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"); } |