Skip to content

Commit 0f2c98b

Browse files
mattjohnsonpintCountBleck
authored andcommitted
fix: support more types in switch statements
1 parent e5539ef commit 0f2c98b

File tree

4 files changed

+5508
-112
lines changed

4 files changed

+5508
-112
lines changed

src/compiler.ts

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2816,19 +2816,48 @@ export class Compiler extends DiagnosticEmitter {
28162816
let numCases = cases.length;
28172817

28182818
// Compile the condition (always executes)
2819-
let condExpr = this.compileExpression(statement.condition, Type.u32,
2820-
Constraints.ConvImplicit
2821-
);
2819+
let condExpr = this.compileExpression(statement.condition, Type.auto);
2820+
2821+
// Get the type set from compiling the condition expression
2822+
let currentType = this.currentType;
2823+
2824+
// Determine the binary operation to use for comparison
2825+
let binaryOp: BinaryOp;
2826+
switch (currentType.toRef()) {
2827+
case TypeRef.I32: {
2828+
binaryOp = BinaryOp.EqI32;
2829+
break;
2830+
}
2831+
case TypeRef.I64: {
2832+
binaryOp = BinaryOp.EqI64;
2833+
break;
2834+
}
2835+
case TypeRef.F32: {
2836+
binaryOp = BinaryOp.EqF32;
2837+
break;
2838+
}
2839+
case TypeRef.F64: {
2840+
binaryOp = BinaryOp.EqF64;
2841+
break;
2842+
}
2843+
default: {
2844+
this.error(
2845+
DiagnosticCode.Not_implemented_0,
2846+
statement.range, `Switch condition of type ${currentType}`
2847+
);
2848+
return module.unreachable();
2849+
}
2850+
}
28222851

28232852
// Shortcut if there are no cases
28242853
if (!numCases) return module.drop(condExpr);
28252854

28262855
// Assign the condition to a temporary local as we compare it multiple times
28272856
let outerFlow = this.currentFlow;
2828-
let tempLocal = outerFlow.getTempLocal(Type.u32);
2857+
let tempLocal = outerFlow.getTempLocal(currentType);
28292858
let tempLocalIndex = tempLocal.index;
28302859
let breaks = new Array<ExpressionRef>(1 + numCases);
2831-
breaks[0] = module.local_set(tempLocalIndex, condExpr, false); // u32
2860+
breaks[0] = module.local_set(tempLocalIndex, condExpr, currentType.isManaged);
28322861

28332862
// Make one br_if per labeled case and leave it to Binaryen to optimize the
28342863
// sequence of br_ifs to a br_table according to optimization levels
@@ -2842,9 +2871,9 @@ export class Compiler extends DiagnosticEmitter {
28422871
continue;
28432872
}
28442873
breaks[breakIndex++] = module.br(`case${i}|${label}`,
2845-
module.binary(BinaryOp.EqI32,
2846-
module.local_get(tempLocalIndex, TypeRef.I32),
2847-
this.compileExpression(assert(case_.label), Type.u32,
2874+
module.binary(binaryOp,
2875+
module.local_get(tempLocalIndex, currentType.toRef()),
2876+
this.compileExpression(assert(case_.label), currentType,
28482877
Constraints.ConvImplicit
28492878
)
28502879
)

0 commit comments

Comments
 (0)