[dart2wasm] Update switch-case compilation

With https://dart-review.googlesource.com/c/sdk/+/289224 the front-end
can now generate switch-case expressions where type of the `switch`
expression is different than the types of expressions in `case`s.

To handle this case we have two options:

1. Compare type of `switch` and `case`s and compile the code to just
   evaluate the switch expressions and the default case.

2. Use reference equality

This CL implements (2) as it's simpler and no correct code will have a
switch-case with differently typed switch and case expressions.

Fixes #51793,

Fixes tests:

- co19/Language/Statements/Switch/execution_t01
- co19/Language/Statements/Switch/type_t01
- co19/Language/Statements/Switch/type_t02

Change-Id: I7eece161249498cf19c9f5245b3898c15a721b60
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/290063
Reviewed-by: Aske Simon Christensen <askesc@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
This commit is contained in:
Ömer Sinan Ağacan
2023-04-03 14:17:49 +00:00
committed by Commit Queue
parent e1c2192110
commit 4ecbae0aaf
+6 -2
View File
@@ -1366,12 +1366,17 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
return;
}
final switchExprClass =
translator.classForType(dartTypeOf(node.expression));
bool check<L extends Expression, C extends Constant>() =>
node.cases.expand((c) => c.expressions).every((e) =>
e is L ||
e is NullLiteral ||
(e is ConstantExpression &&
(e.constant is C || e.constant is NullConstant)));
(e.constant is C || e.constant is NullConstant) &&
(translator.hierarchy.isSubtypeOf(
translator.classForType(dartTypeOf(e)), switchExprClass))));
// Identify kind of switch. One of `nullableType` or `nonNullableType` will
// be the type for Wasm local that holds the switch value.
@@ -1407,7 +1412,6 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
compare = () => call(translator.stringEquals.reference);
} else {
// Object switch
assert(check<InvalidExpression, Constant>());
nonNullableType = w.RefType.eq(nullable: false);
nullableType = w.RefType.eq(nullable: true);
compare = () => b.ref_eq();