@@ -63,6 +63,7 @@ class WasmExpressionBuilder(ctx: FunctionTypeWriterWasmContext, fctx: WasmFuncti
63
63
transformApplyStatically(t)
64
64
case t : IRTrees .Apply => transformApply(t)
65
65
case t : IRTrees .ApplyDynamicImport => ???
66
+ case t : IRTrees .AsInstanceOf => transformAsInstanceOf(t)
66
67
case t : IRTrees .Block => transformBlock(t)
67
68
case t : IRTrees .Labeled => transformLabeled(t)
68
69
case t : IRTrees .Return => transformReturn(t)
@@ -180,8 +181,9 @@ class WasmExpressionBuilder(ctx: FunctionTypeWriterWasmContext, fctx: WasmFuncti
180
181
val wasmArgs = t.args.flatMap(transformTree)
181
182
182
183
val receiverClassName = t.receiver.tpe match {
183
- case ClassType (className) => className
184
- case _ => throw new Error (s " Invalid receiver type ${t.receiver.tpe}" )
184
+ case ClassType (className) => className
185
+ case prim : IRTypes .PrimType => IRTypes .PrimTypeToBoxedClass (prim)
186
+ case _ => throw new Error (s " Invalid receiver type ${t.receiver.tpe}" )
185
187
}
186
188
val receiverClassInfo = ctx.getClassInfo(receiverClassName)
187
189
@@ -228,6 +230,18 @@ class WasmExpressionBuilder(ctx: FunctionTypeWriterWasmContext, fctx: WasmFuncti
228
230
TypeIdx (method.toWasmFunctionType()(ctx).name)
229
231
)
230
232
)
233
+ } else if (receiverClassInfo.kind == ClassKind .HijackedClass ) {
234
+ // statically resolved call
235
+ val info = receiverClassInfo.getMethodInfo(t.method.name)
236
+ val castIfNeeded =
237
+ if (receiverClassName == IRNames .BoxedStringClass && t.receiver.tpe == ClassType (IRNames .BoxedStringClass ))
238
+ List (REF_CAST (HeapType (Types .WasmHeapType .Type (WasmStructTypeName .string))))
239
+ else
240
+ Nil
241
+ pushReceiver ++ castIfNeeded ++ wasmArgs ++
242
+ List (
243
+ CALL (FuncIdx (info.name))
244
+ )
231
245
} else { // virtual dispatch
232
246
val (methodIdx, info) = ctx
233
247
.calculateVtable(receiverClassName)
@@ -401,6 +415,17 @@ class WasmExpressionBuilder(ctx: FunctionTypeWriterWasmContext, fctx: WasmFuncti
401
415
case BinaryOp .Long_>>> => longShiftOp(I64_SHR_U )
402
416
case BinaryOp .Long_>> => longShiftOp(I64_SHR_S )
403
417
418
+ // New in 1.11
419
+ case BinaryOp .String_charAt =>
420
+ transformTree(binary.lhs) ++ // push the string
421
+ List (
422
+ STRUCT_GET (TypeIdx (WasmStructTypeName .string), StructFieldIdx (0 )), // get the array
423
+ ) ++
424
+ transformTree(binary.rhs) ++ // push the index
425
+ List (
426
+ ARRAY_GET_U (TypeIdx (WasmArrayTypeName .stringData)) // access the element of the array
427
+ )
428
+
404
429
case _ => transformElementaryBinaryOp(binary)
405
430
}
406
431
}
@@ -479,9 +504,6 @@ class WasmExpressionBuilder(ctx: FunctionTypeWriterWasmContext, fctx: WasmFuncti
479
504
case BinaryOp .Double_<= => F64_LE
480
505
case BinaryOp .Double_> => F64_GT
481
506
case BinaryOp .Double_>= => F64_GE
482
-
483
- // // New in 1.11
484
- case BinaryOp .String_charAt => ??? // TODO
485
507
}
486
508
lhsInstrs ++ rhsInstrs :+ operation
487
509
}
@@ -539,6 +561,24 @@ class WasmExpressionBuilder(ctx: FunctionTypeWriterWasmContext, fctx: WasmFuncti
539
561
}
540
562
}
541
563
564
+ private def transformAsInstanceOf (tree : IRTrees .AsInstanceOf ): List [WasmInstr ] = {
565
+ val exprInstrs = transformTree(tree.expr)
566
+
567
+ val sourceTpe = tree.expr.tpe
568
+ val targetTpe = tree.tpe
569
+
570
+ if (IRTypes .isSubtype(sourceTpe, targetTpe)(isSubclass(_, _))) {
571
+ // Common case where no cast is necessary
572
+ exprInstrs
573
+ } else {
574
+ println(tree)
575
+ ???
576
+ }
577
+ }
578
+
579
+ private def isSubclass (subClass : IRNames .ClassName , superClass : IRNames .ClassName ): Boolean =
580
+ ctx.getClassInfo(subClass).ancestors.contains(superClass)
581
+
542
582
private def transformVarRef (r : IRTrees .VarRef ): LOCAL_GET = {
543
583
val name = WasmLocalName .fromIR(r.ident.name)
544
584
LOCAL_GET (LocalIdx (name))
0 commit comments