@@ -114,7 +114,7 @@ private class WasmExpressionBuilder private (
114
114
115
115
def genTree (tree : IRTrees .Tree , expectedType : IRTypes .Type ): Unit = {
116
116
val generatedType : IRTypes .Type = tree match {
117
- case t : IRTrees .Literal => genLiteral(t)
117
+ case t : IRTrees .Literal => genLiteral(t, expectedType )
118
118
case t : IRTrees .UnaryOp => genUnaryOp(t)
119
119
case t : IRTrees .BinaryOp => genBinaryOp(t)
120
120
case t : IRTrees .VarRef => genVarRef(t)
@@ -139,10 +139,10 @@ private class WasmExpressionBuilder private (
139
139
case t : IRTrees .If => genIf(t, expectedType)
140
140
case t : IRTrees .While => genWhile(t)
141
141
case t : IRTrees .ForIn => genForIn(t)
142
- case t : IRTrees .TryCatch => genTryCatch(t)
143
- case t : IRTrees .TryFinally => unwinding.genTryFinally(t)
142
+ case t : IRTrees .TryCatch => genTryCatch(t, expectedType )
143
+ case t : IRTrees .TryFinally => unwinding.genTryFinally(t, expectedType )
144
144
case t : IRTrees .Throw => genThrow(t)
145
- case t : IRTrees .Match => genMatch(t)
145
+ case t : IRTrees .Match => genMatch(t, expectedType )
146
146
case t : IRTrees .Debugger => IRTypes .NoType // ignore
147
147
case t : IRTrees .Skip => IRTypes .NoType
148
148
case t : IRTrees .Clone => genClone(t)
@@ -299,7 +299,7 @@ private class WasmExpressionBuilder private (
299
299
instrs += CALL (WasmFunctionName .jsSuperSet)
300
300
301
301
case assign : IRTrees .JSGlobalRef =>
302
- genLiteral( IRTrees . StringLiteral (assign.name)(assign.pos) )
302
+ instrs ++= ctx.getConstantStringInstr (assign.name)
303
303
genTree(t.rhs, IRTypes .AnyType )
304
304
instrs += CALL (WasmFunctionName .jsGlobalRefSet)
305
305
@@ -788,41 +788,50 @@ private class WasmExpressionBuilder private (
788
788
}
789
789
}
790
790
791
- private def genLiteral (l : IRTrees .Literal ): IRTypes .Type = {
792
- l match {
793
- case IRTrees .BooleanLiteral (v) => instrs += WasmInstr .I32_CONST (if (v) 1 else 0 )
794
- case IRTrees .ByteLiteral (v) => instrs += WasmInstr .I32_CONST (v)
795
- case IRTrees .ShortLiteral (v) => instrs += WasmInstr .I32_CONST (v)
796
- case IRTrees .IntLiteral (v) => instrs += WasmInstr .I32_CONST (v)
797
- case IRTrees .CharLiteral (v) => instrs += WasmInstr .I32_CONST (v)
798
- case IRTrees .LongLiteral (v) => instrs += WasmInstr .I64_CONST (v)
799
- case IRTrees .FloatLiteral (v) => instrs += WasmInstr .F32_CONST (v)
800
- case IRTrees .DoubleLiteral (v) => instrs += WasmInstr .F64_CONST (v)
801
-
802
- case v : IRTrees .Undefined =>
803
- instrs += CALL (WasmFunctionName .undef)
804
- case v : IRTrees .Null =>
805
- instrs += WasmInstr .REF_NULL (Types .WasmHeapType .None )
806
-
807
- case v : IRTrees .StringLiteral =>
808
- instrs ++= ctx.getConstantStringInstr(v.value)
809
-
810
- case v : IRTrees .ClassOf =>
811
- v.typeRef match {
812
- case typeRef : IRTypes .NonArrayTypeRef =>
813
- genClassOfFromTypeData(getNonArrayTypeDataInstr(typeRef))
814
-
815
- case typeRef : IRTypes .ArrayTypeRef =>
816
- val typeDataType = Types .WasmRefType (WasmStructTypeName .typeData)
817
- val typeDataLocal = fctx.addSyntheticLocal(typeDataType)
791
+ private def genLiteral (l : IRTrees .Literal , expectedType : IRTypes .Type ): IRTypes .Type = {
792
+ if (expectedType == IRTypes .NoType ) {
793
+ /* Since all primitives are pure, we can always get rid of them.
794
+ * This is mostly useful for the argument of `Return` nodes that target a
795
+ * `Labeled` in statement position, since they must have a non-`void`
796
+ * type in the IR but they get a `void` expected type.
797
+ */
798
+ expectedType
799
+ } else {
800
+ l match {
801
+ case IRTrees .BooleanLiteral (v) => instrs += WasmInstr .I32_CONST (if (v) 1 else 0 )
802
+ case IRTrees .ByteLiteral (v) => instrs += WasmInstr .I32_CONST (v)
803
+ case IRTrees .ShortLiteral (v) => instrs += WasmInstr .I32_CONST (v)
804
+ case IRTrees .IntLiteral (v) => instrs += WasmInstr .I32_CONST (v)
805
+ case IRTrees .CharLiteral (v) => instrs += WasmInstr .I32_CONST (v)
806
+ case IRTrees .LongLiteral (v) => instrs += WasmInstr .I64_CONST (v)
807
+ case IRTrees .FloatLiteral (v) => instrs += WasmInstr .F32_CONST (v)
808
+ case IRTrees .DoubleLiteral (v) => instrs += WasmInstr .F64_CONST (v)
809
+
810
+ case v : IRTrees .Undefined =>
811
+ instrs += CALL (WasmFunctionName .undef)
812
+ case v : IRTrees .Null =>
813
+ instrs += WasmInstr .REF_NULL (Types .WasmHeapType .None )
814
+
815
+ case v : IRTrees .StringLiteral =>
816
+ instrs ++= ctx.getConstantStringInstr(v.value)
817
+
818
+ case v : IRTrees .ClassOf =>
819
+ v.typeRef match {
820
+ case typeRef : IRTypes .NonArrayTypeRef =>
821
+ genClassOfFromTypeData(getNonArrayTypeDataInstr(typeRef))
822
+
823
+ case typeRef : IRTypes .ArrayTypeRef =>
824
+ val typeDataType = Types .WasmRefType (WasmStructTypeName .typeData)
825
+ val typeDataLocal = fctx.addSyntheticLocal(typeDataType)
826
+
827
+ genLoadArrayTypeData(typeRef)
828
+ instrs += LOCAL_SET (typeDataLocal)
829
+ genClassOfFromTypeData(LOCAL_GET (typeDataLocal))
830
+ }
831
+ }
818
832
819
- genLoadArrayTypeData(typeRef)
820
- instrs += LOCAL_SET (typeDataLocal)
821
- genClassOfFromTypeData(LOCAL_GET (typeDataLocal))
822
- }
833
+ l.tpe
823
834
}
824
-
825
- l.tpe
826
835
}
827
836
828
837
private def getNonArrayTypeDataInstr (typeRef : IRTypes .NonArrayTypeRef ): WasmInstr =
@@ -1194,7 +1203,7 @@ private class WasmExpressionBuilder private (
1194
1203
instrs += BR_ON_NON_NULL (labelDone)
1195
1204
}
1196
1205
1197
- genLiteral( IRTrees . StringLiteral (" null" )(tree.pos) )
1206
+ instrs ++= ctx.getConstantStringInstr (" null" )
1198
1207
}
1199
1208
} else {
1200
1209
/* Dispatch where the receiver can be a JS value.
@@ -1498,7 +1507,7 @@ private class WasmExpressionBuilder private (
1498
1507
targetTpe match {
1499
1508
case IRTypes .UndefType =>
1500
1509
instrs += DROP
1501
- genLiteral( IRTrees . Undefined () )
1510
+ instrs += CALL ( WasmFunctionName .undef )
1502
1511
case IRTypes .StringType =>
1503
1512
instrs += REF_AS_NOT_NULL
1504
1513
@@ -1628,10 +1637,19 @@ private class WasmExpressionBuilder private (
1628
1637
private def genIf (t : IRTrees .If , expectedType : IRTypes .Type ): IRTypes .Type = {
1629
1638
val ty = TypeTransformer .transformResultType(expectedType)(ctx)
1630
1639
genTree(t.cond, IRTypes .BooleanType )
1631
- fctx.ifThenElse(ty) {
1632
- genTree(t.thenp, expectedType)
1633
- } {
1634
- genTree(t.elsep, expectedType)
1640
+
1641
+ t.elsep match {
1642
+ case IRTrees .Skip () =>
1643
+ assert(expectedType == IRTypes .NoType )
1644
+ fctx.ifThen() {
1645
+ genTree(t.thenp, expectedType)
1646
+ }
1647
+ case _ =>
1648
+ fctx.ifThenElse(ty) {
1649
+ genTree(t.thenp, expectedType)
1650
+ } {
1651
+ genTree(t.elsep, expectedType)
1652
+ }
1635
1653
}
1636
1654
1637
1655
if (expectedType == IRTypes .NothingType )
@@ -1706,17 +1724,17 @@ private class WasmExpressionBuilder private (
1706
1724
IRTypes .NoType
1707
1725
}
1708
1726
1709
- private def genTryCatch (t : IRTrees .TryCatch ): IRTypes .Type = {
1710
- val resultType = TypeTransformer .transformResultType(t.tpe )(ctx)
1727
+ private def genTryCatch (t : IRTrees .TryCatch , expectedType : IRTypes . Type ): IRTypes .Type = {
1728
+ val resultType = TypeTransformer .transformResultType(expectedType )(ctx)
1711
1729
1712
1730
if (UseLegacyExceptionsForTryCatch ) {
1713
1731
instrs += TRY (fctx.sigToBlockType(WasmFunctionSignature (Nil , resultType)))
1714
- genTree(t.block, t.tpe )
1732
+ genTree(t.block, expectedType )
1715
1733
instrs += CATCH (ctx.exceptionTagName)
1716
1734
fctx.withNewLocal(t.errVar.name, Types .WasmRefType .anyref) { exceptionLocal =>
1717
1735
instrs += ANY_CONVERT_EXTERN
1718
1736
instrs += LOCAL_SET (exceptionLocal)
1719
- genTree(t.handler, t.tpe )
1737
+ genTree(t.handler, expectedType )
1720
1738
}
1721
1739
instrs += END
1722
1740
} else {
@@ -1731,22 +1749,22 @@ private class WasmExpressionBuilder private (
1731
1749
fctx.tryTable(Types .WasmRefType .externref)(
1732
1750
List (CatchClause .Catch (ctx.exceptionTagName, catchLabel))
1733
1751
) {
1734
- genTree(t.block, t.tpe )
1752
+ genTree(t.block, expectedType )
1735
1753
instrs += BR (doneLabel)
1736
1754
}
1737
1755
} // end block $catch
1738
1756
fctx.withNewLocal(t.errVar.name, Types .WasmRefType .anyref) { exceptionLocal =>
1739
1757
instrs += ANY_CONVERT_EXTERN
1740
1758
instrs += LOCAL_SET (exceptionLocal)
1741
- genTree(t.handler, t.tpe )
1759
+ genTree(t.handler, expectedType )
1742
1760
}
1743
1761
} // end block $done
1744
1762
}
1745
1763
1746
- if (t.tpe == IRTypes .NothingType )
1764
+ if (expectedType == IRTypes .NothingType )
1747
1765
instrs += UNREACHABLE
1748
1766
1749
- t.tpe
1767
+ expectedType
1750
1768
}
1751
1769
1752
1770
private def genThrow (tree : IRTrees .Throw ): IRTypes .Type = {
@@ -2071,13 +2089,13 @@ private class WasmExpressionBuilder private (
2071
2089
}
2072
2090
2073
2091
private def genJSGlobalRef (tree : IRTrees .JSGlobalRef ): IRTypes .Type = {
2074
- genLiteral( IRTrees . StringLiteral (tree.name)(tree.pos) )
2092
+ instrs ++= ctx.getConstantStringInstr (tree.name)
2075
2093
instrs += CALL (WasmFunctionName .jsGlobalRefGet)
2076
2094
IRTypes .AnyType
2077
2095
}
2078
2096
2079
2097
private def genJSTypeOfGlobalRef (tree : IRTrees .JSTypeOfGlobalRef ): IRTypes .Type = {
2080
- genLiteral( IRTrees . StringLiteral (tree.globalRef.name)(tree.pos) )
2098
+ instrs ++= ctx.getConstantStringInstr (tree.globalRef.name)
2081
2099
instrs += CALL (WasmFunctionName .jsGlobalRefTypeof)
2082
2100
IRTypes .AnyType
2083
2101
}
@@ -2354,13 +2372,13 @@ private class WasmExpressionBuilder private (
2354
2372
t.tpe
2355
2373
}
2356
2374
2357
- private def genMatch (tree : IRTrees .Match ): IRTypes .Type = {
2375
+ private def genMatch (tree : IRTrees .Match , expectedType : IRTypes . Type ): IRTypes .Type = {
2358
2376
val IRTrees .Match (selector, cases, defaultBody) = tree
2359
2377
val selectorLocal = fctx.addSyntheticLocal(TypeTransformer .transformType(selector.tpe)(ctx))
2360
2378
genTreeAuto(selector)
2361
2379
instrs += LOCAL_SET (selectorLocal)
2362
2380
2363
- fctx.block(TypeTransformer .transformResultType(tree.tpe )(ctx)) { doneLabel =>
2381
+ fctx.block(TypeTransformer .transformResultType(expectedType )(ctx)) { doneLabel =>
2364
2382
fctx.block() { defaultLabel =>
2365
2383
val caseLabels = cases.map(c => c._1 -> fctx.genLabel())
2366
2384
for (caseLabel <- caseLabels)
@@ -2390,17 +2408,17 @@ private class WasmExpressionBuilder private (
2390
2408
2391
2409
for ((caseLabel, caze) <- caseLabels.zip(cases).reverse) {
2392
2410
instrs += END
2393
- genTree(caze._2, tree.tpe )
2411
+ genTree(caze._2, expectedType )
2394
2412
instrs += BR (doneLabel)
2395
2413
}
2396
2414
}
2397
- genTree(defaultBody, tree.tpe )
2415
+ genTree(defaultBody, expectedType )
2398
2416
}
2399
2417
2400
- if (tree.tpe == IRTypes .NothingType )
2418
+ if (expectedType == IRTypes .NothingType )
2401
2419
instrs += UNREACHABLE
2402
2420
2403
- tree.tpe
2421
+ expectedType
2404
2422
}
2405
2423
2406
2424
private def genCreateJSClass (tree : IRTrees .CreateJSClass ): IRTypes .Type = {
@@ -2809,10 +2827,10 @@ private class WasmExpressionBuilder private (
2809
2827
expectedType
2810
2828
}
2811
2829
2812
- def genTryFinally (t : IRTrees .TryFinally ): IRTypes .Type = {
2830
+ def genTryFinally (t : IRTrees .TryFinally , expectedType : IRTypes . Type ): IRTypes .Type = {
2813
2831
val entry = new TryFinallyEntry (currentUnwindingStackDepth)
2814
2832
2815
- val resultType = TypeTransformer .transformResultType(t.tpe )(ctx)
2833
+ val resultType = TypeTransformer .transformResultType(expectedType )(ctx)
2816
2834
val resultLocals = resultType.map(fctx.addSyntheticLocal(_))
2817
2835
2818
2836
fctx.block() { doneLabel =>
@@ -2825,7 +2843,7 @@ private class WasmExpressionBuilder private (
2825
2843
fctx.tryTable()(List (CatchClause .CatchAllRef (catchLabel))) {
2826
2844
// try block
2827
2845
enterTryFinally(entry) {
2828
- genTree(t.block, t.tpe )
2846
+ genTree(t.block, expectedType )
2829
2847
}
2830
2848
2831
2849
// store the result in locals during the finally block
@@ -2922,10 +2940,10 @@ private class WasmExpressionBuilder private (
2922
2940
for (resultLocal <- resultLocals)
2923
2941
instrs += LOCAL_GET (resultLocal)
2924
2942
2925
- if (t.tpe == IRTypes .NothingType )
2943
+ if (expectedType == IRTypes .NothingType )
2926
2944
instrs += UNREACHABLE
2927
2945
2928
- t.tpe
2946
+ expectedType
2929
2947
}
2930
2948
2931
2949
private def emitBRTable (
0 commit comments