From 13361b3f0018bd61ef15a54bef9502c2290c7878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Tue, 21 May 2024 15:41:24 +0200 Subject: [PATCH 1/3] Import `TypeTransformer._` and make `ctx` implicit in `FunctionEmitter`. That cleans up a number of call sites. --- .../backend/wasmemitter/FunctionEmitter.scala | 51 +++++++++---------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/FunctionEmitter.scala b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/FunctionEmitter.scala index 4aa7d06..3e884d0 100644 --- a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/FunctionEmitter.scala +++ b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/FunctionEmitter.scala @@ -19,6 +19,7 @@ import org.scalajs.linker.backend.webassembly.Types.{FunctionType => Sig} import EmbeddedConstants._ import SWasmGen._ import VarGen._ +import TypeTransformer._ object FunctionEmitter { @@ -58,7 +59,7 @@ object FunctionEmitter { hasNewTarget = false, receiverTyp, paramDefs ::: restParam.toList, - TypeTransformer.transformResultType(resultType) + transformResultType(resultType) ) emitter.genBody(body, resultType) emitter.fb.buildAndAddToModule() @@ -205,7 +206,7 @@ object FunctionEmitter { val normalParamsEnv = paramDefs.map { paramDef => val param = fb.addParam( paramDef.originalName.orElse(paramDef.name.name), - TypeTransformer.transformType(paramDef.ptpe) + transformType(paramDef.ptpe) ) paramDef.name.name -> VarStorage.Local(param) } @@ -215,7 +216,6 @@ object FunctionEmitter { fb.setResultTypes(resultTypes) new FunctionEmitter( - ctx, fb, enclosingClassName, newTargetStorage, @@ -257,13 +257,12 @@ object FunctionEmitter { } private class FunctionEmitter private ( - ctx: WasmContext, val fb: FunctionBuilder, enclosingClassName: Option[ClassName], _newTargetStorage: Option[FunctionEmitter.VarStorage.Local], _receiverStorage: Option[FunctionEmitter.VarStorage.Local], paramsEnv: FunctionEmitter.Env -) { +)(implicit ctx: WasmContext) { import FunctionEmitter._ private val instrs = fb @@ -726,7 +725,7 @@ private class FunctionEmitter private ( assert(receiverClassInfo.kind != ClassKind.HijackedClass, receiverClassName) - val resultTyp = TypeTransformer.transformResultType(t.tpe)(ctx) + val resultTyp = transformResultType(t.tpe) instrs.block(resultTyp) { labelDone => def pushArgs(argsLocals: List[wanme.LocalID]): Unit = @@ -750,7 +749,7 @@ private class FunctionEmitter private ( for ((arg, typeRef) <- t.args.zip(t.method.name.paramTypeRefs)) yield { val typ = ctx.inferTypeFromTypeRef(typeRef) genTree(arg, typ) - val localName = addSyntheticLocal(TypeTransformer.transformType(typ)(ctx)) + val localName = addSyntheticLocal(transformType(typ)) instrs += wa.LocalSet(localName) localName } @@ -1246,7 +1245,7 @@ private class FunctionEmitter private ( */ val tpe = binary.tpe - val wasmTyp = TypeTransformer.transformType(tpe)(ctx) + val wasmTyp = transformType(tpe) val lhsLocal = addSyntheticLocal(wasmTyp) val rhsLocal = addSyntheticLocal(wasmTyp) @@ -1738,8 +1737,8 @@ private class FunctionEmitter private ( } else { // By IR checker rules, targetTpe is none of NothingType, NullType, NoType or RecordType - val sourceWasmType = TypeTransformer.transformType(sourceTpe)(ctx) - val targetWasmType = TypeTransformer.transformType(targetTpe)(ctx) + val sourceWasmType = transformType(sourceTpe) + val targetWasmType = transformType(targetTpe) if (sourceWasmType == targetWasmType) { /* Common case where no cast is necessary at the Wasm level. @@ -1798,7 +1797,7 @@ private class FunctionEmitter private ( if (targetTpe == CharType) SpecialNames.CharBoxClass else SpecialNames.LongBoxClass val fieldName = FieldName(boxClass, SpecialNames.valueFieldSimpleName) - val resultType = TypeTransformer.transformType(targetTpe)(ctx) + val resultType = transformType(targetTpe) instrs.block(Sig(List(watpe.RefType.anyref), List(resultType))) { doneLabel => instrs.block(Sig(List(watpe.RefType.anyref), Nil)) { isNullLabel => @@ -1901,7 +1900,7 @@ private class FunctionEmitter private ( } private def genIf(t: If, expectedType: Type): Type = { - val ty = TypeTransformer.transformResultType(expectedType)(ctx) + val ty = transformResultType(expectedType) genTree(t.cond, BooleanType) markPosition(t) @@ -1999,7 +1998,7 @@ private class FunctionEmitter private ( } private def genTryCatch(t: TryCatch, expectedType: Type): Type = { - val resultType = TypeTransformer.transformResultType(expectedType)(ctx) + val resultType = transformResultType(expectedType) if (UseLegacyExceptionsForTryCatch) { markPosition(t) @@ -2066,7 +2065,7 @@ private class FunctionEmitter private ( case (stat @ VarDef(name, originalName, vtpe, _, rhs)) :: rest => genTree(rhs, vtpe) markPosition(stat) - withNewLocal(name.name, originalName, TypeTransformer.transformType(vtpe)(ctx)) { local => + withNewLocal(name.name, originalName, transformType(vtpe)) { local => instrs += wa.LocalSet(local) genBlockStats(rest)(inner) } @@ -2111,7 +2110,7 @@ private class FunctionEmitter private ( boxClassName: ClassName ): Type = { // `primTyp` is `i32` for `char` (containing a `u16` value) or `i64` for `long`. - val primTyp = TypeTransformer.transformType(primType)(ctx) + val primTyp = transformType(primType) val primLocal = addSyntheticLocal(primTyp) /* We use a direct `StructNew` instead of the logical call to `newDefault` @@ -2143,7 +2142,7 @@ private class FunctionEmitter private ( val nonNullThrowableTyp = watpe.RefType(genTypeID.ThrowableStruct) val jsExceptionTyp = - TypeTransformer.transformClassType(SpecialNames.JSExceptionClass)(ctx).toNonNullable + transformClassType(SpecialNames.JSExceptionClass).toNonNullable instrs.block(nonNullThrowableTyp) { doneLabel => genTree(tree.expr, AnyType) @@ -2252,7 +2251,7 @@ private class FunctionEmitter private ( private def genLoadJSConstructor(tree: LoadJSConstructor): Type = { markPosition(tree) - SWasmGen.genLoadJSConstructor(instrs, tree.className)(ctx) + SWasmGen.genLoadJSConstructor(instrs, tree.className) AnyType } @@ -2261,7 +2260,7 @@ private class FunctionEmitter private ( ctx.getClassInfo(tree.className).jsNativeLoadSpec match { case Some(loadSpec) => - genLoadJSFromSpec(instrs, loadSpec)(ctx) + genLoadJSFromSpec(instrs, loadSpec) case None => // This is a non-native JS module instrs += wa.Call(genFunctionID.loadModule(tree.className)) @@ -2277,7 +2276,7 @@ private class FunctionEmitter private ( throw new AssertionError(s"Found $tree for non-existing JS native member at ${tree.pos}") } ) - genLoadJSFromSpec(instrs, jsNativeLoadSpec)(ctx) + genLoadJSFromSpec(instrs, jsNativeLoadSpec) AnyType } @@ -2509,7 +2508,7 @@ private class FunctionEmitter private ( // a primitive array type always has the correct () case _ => - TypeTransformer.transformType(t.tpe)(ctx) match { + transformType(t.tpe) match { case watpe.RefType.anyref => // nothing to do () @@ -2612,7 +2611,7 @@ private class FunctionEmitter private ( } private def genClone(t: Clone): Type = { - val expr = addSyntheticLocal(TypeTransformer.transformType(t.expr.tpe)(ctx)) + val expr = addSyntheticLocal(transformType(t.expr.tpe)) genTree(t.expr, ClassType(CloneableClass)) @@ -2643,7 +2642,7 @@ private class FunctionEmitter private ( private def genMatch(tree: Match, expectedType: Type): Type = { val Match(selector, cases, defaultBody) = tree - val selectorLocal = addSyntheticLocal(TypeTransformer.transformType(selector.tpe)(ctx)) + val selectorLocal = addSyntheticLocal(transformType(selector.tpe)) genTreeAuto(selector) @@ -2651,7 +2650,7 @@ private class FunctionEmitter private ( instrs += wa.LocalSet(selectorLocal) - instrs.block(TypeTransformer.transformResultType(expectedType)(ctx)) { doneLabel => + instrs.block(transformResultType(expectedType)) { doneLabel => instrs.block() { defaultLabel => val caseLabels = cases.map(c => c._1 -> instrs.genLabel()) for (caseLabel <- caseLabels) @@ -3035,7 +3034,7 @@ private class FunctionEmitter private ( def requireCrossInfo(): (Int, List[wanme.LocalID], wanme.LabelID) = { if (destinationTag == 0) { destinationTag = allocateDestinationTag() - val resultTypes = TypeTransformer.transformResultType(expectedType)(ctx) + val resultTypes = transformResultType(expectedType) resultLocals = resultTypes.map(addSyntheticLocal(_)) crossLabel = instrs.genLabel() } @@ -3047,7 +3046,7 @@ private class FunctionEmitter private ( def genLabeled(t: Labeled, expectedType: Type): Type = { val entry = new LabeledEntry(currentUnwindingStackDepth, t.label.name, expectedType) - val ty = TypeTransformer.transformResultType(expectedType)(ctx) + val ty = transformResultType(expectedType) markPosition(t) @@ -3122,7 +3121,7 @@ private class FunctionEmitter private ( def genTryFinally(t: TryFinally, expectedType: Type): Type = { val entry = new TryFinallyEntry(currentUnwindingStackDepth) - val resultType = TypeTransformer.transformResultType(expectedType)(ctx) + val resultType = transformResultType(expectedType) val resultLocals = resultType.map(addSyntheticLocal(_)) markPosition(t) From dd94b8d5d5efedc3e4115c97c7808992a52b5375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Tue, 21 May 2024 15:52:47 +0200 Subject: [PATCH 2/3] Do not alias `fb` as `instrs` anymore; consistently use `fb`. We previously used aliases not to disrupt the codebase, but now it is time to clean up. --- .../backend/wasmemitter/ClassEmitter.scala | 240 ++-- .../backend/wasmemitter/CoreWasmLib.scala | 1214 ++++++++--------- .../linker/backend/wasmemitter/Emitter.scala | 59 +- .../backend/wasmemitter/FunctionEmitter.scala | 788 ++++++----- 4 files changed, 1123 insertions(+), 1178 deletions(-) diff --git a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/ClassEmitter.scala b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/ClassEmitter.scala index 648d677..98bac37 100644 --- a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/ClassEmitter.scala +++ b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/ClassEmitter.scala @@ -126,18 +126,16 @@ class ClassEmitter(coreSpec: CoreSpec) { fb.setResultType(watpe.Int32) fb.setFunctionType(genTypeID.isJSClassInstanceFuncType) - val instrs = fb - if (clazz.kind == ClassKind.JSClass && !clazz.hasInstances) { /* We need to constant-fold the instance test, to avoid trying to * call $loadJSClass.className, since it will not exist at all. */ - instrs += wa.I32Const(0) // false + fb += wa.I32Const(0) // false } else { - instrs += wa.LocalGet(xParam) - genLoadJSConstructor(instrs, className) - instrs += wa.Call(genFunctionID.jsBinaryOps(JSBinaryOp.instanceof)) - instrs += wa.Call(genFunctionID.unbox(BooleanRef)) + fb += wa.LocalGet(xParam) + genLoadJSConstructor(fb, className) + fb += wa.Call(genFunctionID.jsBinaryOps(JSBinaryOp.instanceof)) + fb += wa.Call(genFunctionID.unbox(BooleanRef)) } val func = fb.buildAndAddToModule() @@ -417,37 +415,35 @@ class ClassEmitter(coreSpec: CoreSpec) { val exprParam = fb.addParam("expr", watpe.RefType.anyref) fb.setResultType(watpe.Int32) - val instrs = fb - val itables = fb.addLocal("itables", watpe.RefType.nullable(genTypeID.itables)) val exprNonNullLocal = fb.addLocal("exprNonNull", watpe.RefType.any) val itableIdx = ctx.getItableIdx(classInfo) - instrs.block(watpe.RefType.anyref) { testFail => + fb.block(watpe.RefType.anyref) { testFail => // if expr is not an instance of Object, return false - instrs += wa.LocalGet(exprParam) - instrs += wa.BrOnCastFail( + fb += wa.LocalGet(exprParam) + fb += wa.BrOnCastFail( testFail, watpe.RefType.anyref, watpe.RefType(genTypeID.ObjectStruct) ) // get itables and store - instrs += wa.StructGet(genTypeID.ObjectStruct, genFieldID.objStruct.itables) - instrs += wa.LocalSet(itables) + fb += wa.StructGet(genTypeID.ObjectStruct, genFieldID.objStruct.itables) + fb += wa.LocalSet(itables) // Dummy return value from the block - instrs += wa.RefNull(watpe.HeapType.Any) + fb += wa.RefNull(watpe.HeapType.Any) // if the itables is null (no interfaces are implemented) - instrs += wa.LocalGet(itables) - instrs += wa.BrOnNull(testFail) - - instrs += wa.LocalGet(itables) - instrs += wa.I32Const(itableIdx) - instrs += wa.ArrayGet(genTypeID.itables) - instrs += wa.RefTest(watpe.RefType(genTypeID.forITable(className))) - instrs += wa.Return + fb += wa.LocalGet(itables) + fb += wa.BrOnNull(testFail) + + fb += wa.LocalGet(itables) + fb += wa.I32Const(itableIdx) + fb += wa.ArrayGet(genTypeID.itables) + fb += wa.RefTest(watpe.RefType(genTypeID.forITable(className))) + fb += wa.Return } // test fail if (classInfo.isAncestorOfHijackedClass) { @@ -465,29 +461,29 @@ class ClassEmitter(coreSpec: CoreSpec) { */ val anyRefToVoidSig = watpe.FunctionType(List(watpe.RefType.anyref), Nil) - instrs.block(anyRefToVoidSig) { isNullLabel => + fb.block(anyRefToVoidSig) { isNullLabel => // exprNonNull := expr; branch to isNullLabel if it is null - instrs += wa.BrOnNull(isNullLabel) - instrs += wa.LocalSet(exprNonNullLocal) + fb += wa.BrOnNull(isNullLabel) + fb += wa.LocalSet(exprNonNullLocal) // Load 1 << jsValueType(expr) - instrs += wa.I32Const(1) - instrs += wa.LocalGet(exprNonNullLocal) - instrs += wa.Call(genFunctionID.jsValueType) - instrs += wa.I32Shl + fb += wa.I32Const(1) + fb += wa.LocalGet(exprNonNullLocal) + fb += wa.Call(genFunctionID.jsValueType) + fb += wa.I32Shl // return (... & specialInstanceTypes) != 0 - instrs += wa.I32Const(classInfo.specialInstanceTypes) - instrs += wa.I32And - instrs += wa.I32Const(0) - instrs += wa.I32Ne - instrs += wa.Return + fb += wa.I32Const(classInfo.specialInstanceTypes) + fb += wa.I32And + fb += wa.I32Const(0) + fb += wa.I32Ne + fb += wa.Return } - instrs += wa.I32Const(0) // false + fb += wa.I32Const(0) // false } else { - instrs += wa.Drop - instrs += wa.I32Const(0) // false + fb += wa.Drop + fb += wa.I32Const(0) // false } fb.buildAndAddToModule() @@ -507,19 +503,17 @@ class ClassEmitter(coreSpec: CoreSpec) { ) fb.setResultType(watpe.RefType(structName)) - val instrs = fb - - instrs += wa.GlobalGet(genGlobalID.forVTable(className)) + fb += wa.GlobalGet(genGlobalID.forVTable(className)) if (classInfo.classImplementsAnyInterface) - instrs += wa.GlobalGet(genGlobalID.forITable(className)) + fb += wa.GlobalGet(genGlobalID.forITable(className)) else - instrs += wa.RefNull(watpe.HeapType(genTypeID.itables)) + fb += wa.RefNull(watpe.HeapType(genTypeID.itables)) classInfo.allFieldDefs.foreach { f => - instrs += genZeroOf(f.ftpe) + fb += genZeroOf(f.ftpe) } - instrs += wa.StructNew(structName) + fb += wa.StructNew(structName) fb.buildAndAddToModule() } @@ -543,30 +537,28 @@ class ClassEmitter(coreSpec: CoreSpec) { fb.setResultType(watpe.RefType(genTypeID.ObjectStruct)) fb.setFunctionType(genTypeID.cloneFunctionType) - val instrs = fb - val structTypeID = genTypeID.forClass(className) val structRefType = watpe.RefType(structTypeID) val fromTypedLocal = fb.addLocal("fromTyped", structRefType) // Downcast fromParam to fromTyped - instrs += wa.LocalGet(fromParam) - instrs += wa.RefCast(structRefType) - instrs += wa.LocalSet(fromTypedLocal) + fb += wa.LocalGet(fromParam) + fb += wa.RefCast(structRefType) + fb += wa.LocalSet(fromTypedLocal) // Push vtable and itables on the stack (there is at least Cloneable in the itables) - instrs += wa.GlobalGet(genGlobalID.forVTable(className)) - instrs += wa.GlobalGet(genGlobalID.forITable(className)) + fb += wa.GlobalGet(genGlobalID.forVTable(className)) + fb += wa.GlobalGet(genGlobalID.forITable(className)) // Push every field of `fromTyped` on the stack info.allFieldDefs.foreach { field => - instrs += wa.LocalGet(fromTypedLocal) - instrs += wa.StructGet(structTypeID, genFieldID.forClassInstanceField(field.name.name)) + fb += wa.LocalGet(fromTypedLocal) + fb += wa.StructGet(structTypeID, genFieldID.forClassInstanceField(field.name.name)) } // Create the result - instrs += wa.StructNew(structTypeID) + fb += wa.StructNew(structTypeID) fb.buildAndAddToModule() } @@ -590,24 +582,22 @@ class ClassEmitter(coreSpec: CoreSpec) { val instanceLocal = fb.addLocal("instance", resultTyp) - val instrs = fb - - instrs.block(resultTyp) { nonNullLabel => + fb.block(resultTyp) { nonNullLabel => // load global, return if not null - instrs += wa.GlobalGet(globalInstanceName) - instrs += wa.BrOnNonNull(nonNullLabel) + fb += wa.GlobalGet(globalInstanceName) + fb += wa.BrOnNonNull(nonNullLabel) // create an instance and call its constructor - instrs += wa.Call(genFunctionID.newDefault(className)) - instrs += wa.LocalTee(instanceLocal) - instrs += wa.Call(ctorName) + fb += wa.Call(genFunctionID.newDefault(className)) + fb += wa.LocalTee(instanceLocal) + fb += wa.Call(ctorName) // store it in the global - instrs += wa.LocalGet(instanceLocal) - instrs += wa.GlobalSet(globalInstanceName) + fb += wa.LocalGet(instanceLocal) + fb += wa.GlobalSet(globalInstanceName) // return it - instrs += wa.LocalGet(instanceLocal) + fb += wa.LocalGet(instanceLocal) } fb.buildAndAddToModule() @@ -746,8 +736,6 @@ class ClassEmitter(coreSpec: CoreSpec) { } fb.setResultType(watpe.RefType.any) - val instrs = fb - val dataStructTypeName = ctx.getClosureDataStructType(jsClassCaptures.map(_.ptpe)) // --- Internal name management of `createJSClass` @@ -759,9 +747,9 @@ class ClassEmitter(coreSpec: CoreSpec) { // Bundle class captures in a capture data struct -- leave it on the stack for createJSClass for (classCaptureParam <- classCaptureParams) - instrs += wa.LocalGet(classCaptureParam) - instrs += wa.StructNew(dataStructTypeName) - instrs += wa.LocalTee(dataStructLocal) + fb += wa.LocalGet(classCaptureParam) + fb += wa.StructNew(dataStructTypeName) + fb += wa.LocalTee(dataStructLocal) val classCaptureParamsOfTypeAny: Map[LocalName, wanme.LocalID] = { jsClassCaptures @@ -776,14 +764,14 @@ class ClassEmitter(coreSpec: CoreSpec) { tree match { case StringLiteral(value) => // Common shape for all the `nameTree` expressions - instrs ++= ctx.getConstantStringInstr(value) + fb ++= ctx.getConstantStringInstr(value) case VarRef(LocalIdent(localName)) if classCaptureParamsOfTypeAny.contains(localName) => /* Common shape for the `jsSuperClass` value * We can only deal with class captures of type `AnyType` in this way, * since otherwise we might need `adapt` to box the values. */ - instrs += wa.LocalGet(classCaptureParamsOfTypeAny(localName)) + fb += wa.LocalGet(classCaptureParamsOfTypeAny(localName)) case _ => // For everything else, put the tree in its own function and call it @@ -799,8 +787,8 @@ class ClassEmitter(coreSpec: CoreSpec) { tree, AnyType ) - instrs += wa.LocalGet(dataStructLocal) - instrs += wa.Call(closureFuncID) + fb += wa.LocalGet(dataStructLocal) + fb += wa.Call(closureFuncID) } } @@ -812,56 +800,56 @@ class ClassEmitter(coreSpec: CoreSpec) { */ clazz.jsSuperClass match { case None => - genLoadJSConstructor(instrs, clazz.superClass.get.name) + genLoadJSConstructor(fb, clazz.superClass.get.name) case Some(jsSuperClassTree) => genLoadIsolatedTree(jsSuperClassTree) } // Load the references to the 3 functions that make up the constructor - instrs += ctx.refFuncWithDeclaration(preSuperStatsFunctionName) - instrs += ctx.refFuncWithDeclaration(superArgsFunctionName) - instrs += ctx.refFuncWithDeclaration(postSuperStatsFunctionName) + fb += ctx.refFuncWithDeclaration(preSuperStatsFunctionName) + fb += ctx.refFuncWithDeclaration(superArgsFunctionName) + fb += ctx.refFuncWithDeclaration(postSuperStatsFunctionName) // Load the array of field names and initial values - instrs += wa.Call(genFunctionID.jsNewArray) + fb += wa.Call(genFunctionID.jsNewArray) for (fieldDef <- clazz.fields if !fieldDef.flags.namespace.isStatic) { // Append the name fieldDef match { case FieldDef(_, name, _, _) => - instrs += wa.GlobalGet(genGlobalID.forJSPrivateField(name.name)) + fb += wa.GlobalGet(genGlobalID.forJSPrivateField(name.name)) case JSFieldDef(_, nameTree, _) => genLoadIsolatedTree(nameTree) } - instrs += wa.Call(genFunctionID.jsArrayPush) + fb += wa.Call(genFunctionID.jsArrayPush) // Append the boxed representation of the zero of the field - instrs += genBoxedZeroOf(fieldDef.ftpe) - instrs += wa.Call(genFunctionID.jsArrayPush) + fb += genBoxedZeroOf(fieldDef.ftpe) + fb += wa.Call(genFunctionID.jsArrayPush) } // Call the createJSClass helper to bundle everything if (ctor.restParam.isDefined) { - instrs += wa.I32Const(ctor.args.size) // number of fixed params - instrs += wa.Call(genFunctionID.createJSClassRest) + fb += wa.I32Const(ctor.args.size) // number of fixed params + fb += wa.Call(genFunctionID.createJSClassRest) } else { - instrs += wa.Call(genFunctionID.createJSClass) + fb += wa.Call(genFunctionID.createJSClass) } // Store the result, locally in `jsClass` and possibly in the global cache if (clazz.jsClassCaptures.isEmpty) { // Static JS class with a global cache - instrs += wa.LocalTee(jsClassLocal) - instrs += wa.GlobalSet(genGlobalID.forJSClassValue(className)) + fb += wa.LocalTee(jsClassLocal) + fb += wa.GlobalSet(genGlobalID.forJSClassValue(className)) } else { // Local or inner JS class, which is new every time - instrs += wa.LocalSet(jsClassLocal) + fb += wa.LocalSet(jsClassLocal) } // Install methods and properties for (methodOrProp <- clazz.exportedMembers) { val isStatic = methodOrProp.flags.namespace.isStatic - instrs += wa.LocalGet(dataStructLocal) - instrs += wa.LocalGet(jsClassLocal) + fb += wa.LocalGet(dataStructLocal) + fb += wa.LocalGet(jsClassLocal) val receiverTyp = if (isStatic) None else Some(watpe.RefType.anyref) @@ -881,20 +869,20 @@ class ClassEmitter(coreSpec: CoreSpec) { body, AnyType ) - instrs += ctx.refFuncWithDeclaration(closureFuncID) + fb += ctx.refFuncWithDeclaration(closureFuncID) - instrs += wa.I32Const(if (restParam.isDefined) params.size else -1) + fb += wa.I32Const(if (restParam.isDefined) params.size else -1) if (isStatic) - instrs += wa.Call(genFunctionID.installJSStaticMethod) + fb += wa.Call(genFunctionID.installJSStaticMethod) else - instrs += wa.Call(genFunctionID.installJSMethod) + fb += wa.Call(genFunctionID.installJSMethod) case JSPropertyDef(flags, nameTree, optGetter, optSetter) => genLoadIsolatedTree(nameTree) optGetter match { case None => - instrs += wa.RefNull(watpe.HeapType.Func) + fb += wa.RefNull(watpe.HeapType.Func) case Some(getterBody) => val closureFuncID = new JSClassClosureFunctionID(className) @@ -909,12 +897,12 @@ class ClassEmitter(coreSpec: CoreSpec) { getterBody, resultType = AnyType ) - instrs += ctx.refFuncWithDeclaration(closureFuncID) + fb += ctx.refFuncWithDeclaration(closureFuncID) } optSetter match { case None => - instrs += wa.RefNull(watpe.HeapType.Func) + fb += wa.RefNull(watpe.HeapType.Func) case Some((setterParamDef, setterBody)) => val closureFuncID = new JSClassClosureFunctionID(className) @@ -929,20 +917,20 @@ class ClassEmitter(coreSpec: CoreSpec) { setterBody, resultType = NoType ) - instrs += ctx.refFuncWithDeclaration(closureFuncID) + fb += ctx.refFuncWithDeclaration(closureFuncID) } if (isStatic) - instrs += wa.Call(genFunctionID.installJSStaticProperty) + fb += wa.Call(genFunctionID.installJSStaticProperty) else - instrs += wa.Call(genFunctionID.installJSProperty) + fb += wa.Call(genFunctionID.installJSProperty) } } // Static fields for (fieldDef <- clazz.fields if fieldDef.flags.namespace.isStatic) { // Load class value - instrs += wa.LocalGet(jsClassLocal) + fb += wa.LocalGet(jsClassLocal) // Load name fieldDef match { @@ -956,9 +944,9 @@ class ClassEmitter(coreSpec: CoreSpec) { } // Generate boxed representation of the zero of the field - instrs += genBoxedZeroOf(fieldDef.ftpe) + fb += genBoxedZeroOf(fieldDef.ftpe) - instrs += wa.Call(genFunctionID.installJSField) + fb += wa.Call(genFunctionID.installJSField) } // Class initializer @@ -968,13 +956,13 @@ class ClassEmitter(coreSpec: CoreSpec) { s"Illegal class initializer in non-static class ${className.nameString}" ) val namespace = MemberNamespace.StaticConstructor - instrs += wa.Call( + fb += wa.Call( genFunctionID.forMethod(namespace, className, ClassInitializerName) ) } // Final result - instrs += wa.LocalGet(jsClassLocal) + fb += wa.LocalGet(jsClassLocal) fb.buildAndAddToModule() } @@ -1000,14 +988,12 @@ class ClassEmitter(coreSpec: CoreSpec) { ) fb.setResultType(watpe.RefType.any) - val instrs = fb - - instrs.block(watpe.RefType.any) { doneLabel => + fb.block(watpe.RefType.any) { doneLabel => // Load cached JS class, return if non-null - instrs += wa.GlobalGet(cachedJSClassGlobal.id) - instrs += wa.BrOnNonNull(doneLabel) + fb += wa.GlobalGet(cachedJSClassGlobal.id) + fb += wa.BrOnNonNull(doneLabel) // Otherwise, call createJSClass -- it will also store the class in the cache - instrs += wa.Call(genFunctionID.createJSClassOf(className)) + fb += wa.Call(genFunctionID.createJSClassOf(className)) } fb.buildAndAddToModule() @@ -1035,21 +1021,19 @@ class ClassEmitter(coreSpec: CoreSpec) { ) fb.setResultType(watpe.RefType.anyref) - val instrs = fb - - instrs.block(watpe.RefType.anyref) { doneLabel => + fb.block(watpe.RefType.anyref) { doneLabel => // Load cached instance; return if non-null - instrs += wa.GlobalGet(cacheGlobalName) - instrs += wa.BrOnNonNull(doneLabel) + fb += wa.GlobalGet(cacheGlobalName) + fb += wa.BrOnNonNull(doneLabel) // Get the JS class and instantiate it - instrs += wa.Call(genFunctionID.loadJSClass(className)) - instrs += wa.Call(genFunctionID.jsNewArray) - instrs += wa.Call(genFunctionID.jsNew) + fb += wa.Call(genFunctionID.loadJSClass(className)) + fb += wa.Call(genFunctionID.jsNewArray) + fb += wa.Call(genFunctionID.jsNew) // Store and return the result - instrs += wa.GlobalSet(cacheGlobalName) - instrs += wa.GlobalGet(cacheGlobalName) + fb += wa.GlobalSet(cacheGlobalName) + fb += wa.GlobalGet(cacheGlobalName) } fb.buildAndAddToModule() @@ -1165,25 +1149,23 @@ class ClassEmitter(coreSpec: CoreSpec) { fb.setResultTypes(TypeTransformer.transformResultType(method.resultType)) fb.setFunctionType(ctx.tableFunctionType(methodName)) - val instrs = fb - // Load and cast down the receiver - instrs += wa.LocalGet(receiverParam) + fb += wa.LocalGet(receiverParam) receiverTyp match { case Some(watpe.RefType(_, watpe.HeapType.Any)) => () // no cast necessary case Some(receiverTyp: watpe.RefType) => - instrs += wa.RefCast(receiverTyp) + fb += wa.RefCast(receiverTyp) case _ => throw new AssertionError(s"Unexpected receiver type $receiverTyp") } // Load the other parameters for (argParam <- argParams) - instrs += wa.LocalGet(argParam) + fb += wa.LocalGet(argParam) // Call the statically resolved method - instrs += wa.ReturnCall(functionName) + fb += wa.ReturnCall(functionName) fb.buildAndAddToModule() } diff --git a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/CoreWasmLib.scala b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/CoreWasmLib.scala index bd32706..c237568 100644 --- a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/CoreWasmLib.scala +++ b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/CoreWasmLib.scala @@ -592,27 +592,25 @@ object CoreWasmLib { val str = fb.addLocal("str", RefType.any) - val instrs = fb + fb.block(RefType.any) { cacheHit => + fb += GlobalGet(genGlobalID.stringLiteralCache) + fb += LocalGet(stringIndexParam) + fb += ArrayGet(genTypeID.anyArray) - instrs.block(RefType.any) { cacheHit => - instrs += GlobalGet(genGlobalID.stringLiteralCache) - instrs += LocalGet(stringIndexParam) - instrs += ArrayGet(genTypeID.anyArray) - - instrs += BrOnNonNull(cacheHit) + fb += BrOnNonNull(cacheHit) // cache miss, create a new string and cache it - instrs += GlobalGet(genGlobalID.stringLiteralCache) - instrs += LocalGet(stringIndexParam) + fb += GlobalGet(genGlobalID.stringLiteralCache) + fb += LocalGet(stringIndexParam) - instrs += LocalGet(offsetParam) - instrs += LocalGet(sizeParam) - instrs += ArrayNewData(genTypeID.i16Array, genDataID.string) - instrs += Call(genFunctionID.createStringFromData) - instrs += LocalTee(str) - instrs += ArraySet(genTypeID.anyArray) + fb += LocalGet(offsetParam) + fb += LocalGet(sizeParam) + fb += ArrayNewData(genTypeID.i16Array, genDataID.string) + fb += Call(genFunctionID.createStringFromData) + fb += LocalTee(str) + fb += ArraySet(genTypeID.anyArray) - instrs += LocalGet(str) + fb += LocalGet(str) } fb.buildAndAddToModule() @@ -626,55 +624,53 @@ object CoreWasmLib { val dataParam = fb.addParam("data", dataType) fb.setResultType(RefType.any) - val instrs = fb - val lenLocal = fb.addLocal("len", Int32) val iLocal = fb.addLocal("i", Int32) val resultLocal = fb.addLocal("result", RefType.any) // len := data.length - instrs += LocalGet(dataParam) - instrs += ArrayLen - instrs += LocalSet(lenLocal) + fb += LocalGet(dataParam) + fb += ArrayLen + fb += LocalSet(lenLocal) // i := 0 - instrs += I32Const(0) - instrs += LocalSet(iLocal) + fb += I32Const(0) + fb += LocalSet(iLocal) // result := "" - instrs += GlobalGet(genGlobalID.emptyString) - instrs += LocalSet(resultLocal) + fb += GlobalGet(genGlobalID.emptyString) + fb += LocalSet(resultLocal) - instrs.loop() { labelLoop => + fb.loop() { labelLoop => // if i == len - instrs += LocalGet(iLocal) - instrs += LocalGet(lenLocal) - instrs += I32Eq - instrs.ifThen() { + fb += LocalGet(iLocal) + fb += LocalGet(lenLocal) + fb += I32Eq + fb.ifThen() { // then return result - instrs += LocalGet(resultLocal) - instrs += Return + fb += LocalGet(resultLocal) + fb += Return } // result := concat(result, charToString(data(i))) - instrs += LocalGet(resultLocal) - instrs += LocalGet(dataParam) - instrs += LocalGet(iLocal) - instrs += ArrayGetU(genTypeID.i16Array) - instrs += Call(genFunctionID.charToString) - instrs += Call(genFunctionID.stringConcat) - instrs += LocalSet(resultLocal) + fb += LocalGet(resultLocal) + fb += LocalGet(dataParam) + fb += LocalGet(iLocal) + fb += ArrayGetU(genTypeID.i16Array) + fb += Call(genFunctionID.charToString) + fb += Call(genFunctionID.stringConcat) + fb += LocalSet(resultLocal) // i := i - 1 - instrs += LocalGet(iLocal) - instrs += I32Const(1) - instrs += I32Add - instrs += LocalSet(iLocal) + fb += LocalGet(iLocal) + fb += I32Const(1) + fb += I32Add + fb += LocalSet(iLocal) // loop back to the beginning - instrs += Br(labelLoop) + fb += Br(labelLoop) } // end loop $loop - instrs += Unreachable + fb += Unreachable fb.buildAndAddToModule() } @@ -698,102 +694,100 @@ object CoreWasmLib { val typeDataParam = fb.addParam("typeData", typeDataType) fb.setResultType(RefType.any) - val instrs = fb - val componentTypeDataLocal = fb.addLocal("componentTypeData", typeDataType) val componentNameDataLocal = fb.addLocal("componentNameData", nameDataType) val firstCharLocal = fb.addLocal("firstChar", Int32) val nameLocal = fb.addLocal("name", RefType.any) - instrs.block(RefType.any) { alreadyInitializedLabel => + fb.block(RefType.any) { alreadyInitializedLabel => // br_on_non_null $alreadyInitialized typeData.name - instrs += LocalGet(typeDataParam) - instrs += StructGet(genTypeID.typeData, genFieldID.typeData.name) - instrs += BrOnNonNull(alreadyInitializedLabel) + fb += LocalGet(typeDataParam) + fb += StructGet(genTypeID.typeData, genFieldID.typeData.name) + fb += BrOnNonNull(alreadyInitializedLabel) // for the STRUCT_SET typeData.name near the end - instrs += LocalGet(typeDataParam) + fb += LocalGet(typeDataParam) // if typeData.kind == KindArray - instrs += LocalGet(typeDataParam) - instrs += StructGet(genTypeID.typeData, genFieldID.typeData.kind) - instrs += I32Const(KindArray) - instrs += I32Eq - instrs.ifThenElse(RefType.any) { + fb += LocalGet(typeDataParam) + fb += StructGet(genTypeID.typeData, genFieldID.typeData.kind) + fb += I32Const(KindArray) + fb += I32Eq + fb.ifThenElse(RefType.any) { // it is an array; compute its name from the component type name // := "[", for the CALL to stringConcat near the end - instrs += I32Const('['.toInt) - instrs += Call(genFunctionID.charToString) + fb += I32Const('['.toInt) + fb += Call(genFunctionID.charToString) // componentTypeData := ref_as_non_null(typeData.componentType) - instrs += LocalGet(typeDataParam) - instrs += StructGet( + fb += LocalGet(typeDataParam) + fb += StructGet( genTypeID.typeData, genFieldID.typeData.componentType ) - instrs += RefAsNotNull - instrs += LocalSet(componentTypeDataLocal) + fb += RefAsNotNull + fb += LocalSet(componentTypeDataLocal) // switch (componentTypeData.kind) // the result of this switch is the string that must come after "[" - instrs.switch(RefType.any) { () => + fb.switch(RefType.any) { () => // scrutinee - instrs += LocalGet(componentTypeDataLocal) - instrs += StructGet(genTypeID.typeData, genFieldID.typeData.kind) + fb += LocalGet(componentTypeDataLocal) + fb += StructGet(genTypeID.typeData, genFieldID.typeData.kind) }( List(KindBoolean) -> { () => - instrs += I32Const('Z'.toInt) - instrs += Call(genFunctionID.charToString) + fb += I32Const('Z'.toInt) + fb += Call(genFunctionID.charToString) }, List(KindChar) -> { () => - instrs += I32Const('C'.toInt) - instrs += Call(genFunctionID.charToString) + fb += I32Const('C'.toInt) + fb += Call(genFunctionID.charToString) }, List(KindByte) -> { () => - instrs += I32Const('B'.toInt) - instrs += Call(genFunctionID.charToString) + fb += I32Const('B'.toInt) + fb += Call(genFunctionID.charToString) }, List(KindShort) -> { () => - instrs += I32Const('S'.toInt) - instrs += Call(genFunctionID.charToString) + fb += I32Const('S'.toInt) + fb += Call(genFunctionID.charToString) }, List(KindInt) -> { () => - instrs += I32Const('I'.toInt) - instrs += Call(genFunctionID.charToString) + fb += I32Const('I'.toInt) + fb += Call(genFunctionID.charToString) }, List(KindLong) -> { () => - instrs += I32Const('J'.toInt) - instrs += Call(genFunctionID.charToString) + fb += I32Const('J'.toInt) + fb += Call(genFunctionID.charToString) }, List(KindFloat) -> { () => - instrs += I32Const('F'.toInt) - instrs += Call(genFunctionID.charToString) + fb += I32Const('F'.toInt) + fb += Call(genFunctionID.charToString) }, List(KindDouble) -> { () => - instrs += I32Const('D'.toInt) - instrs += Call(genFunctionID.charToString) + fb += I32Const('D'.toInt) + fb += Call(genFunctionID.charToString) }, List(KindArray) -> { () => // the component type is an array; get its own name - instrs += LocalGet(componentTypeDataLocal) - instrs += Call(genFunctionID.typeDataName) + fb += LocalGet(componentTypeDataLocal) + fb += Call(genFunctionID.typeDataName) } ) { () => // default: the component type is neither a primitive nor an array; // concatenate "L" + + ";" - instrs += I32Const('L'.toInt) - instrs += Call(genFunctionID.charToString) - instrs += LocalGet(componentTypeDataLocal) - instrs += Call(genFunctionID.typeDataName) - instrs += Call(genFunctionID.stringConcat) - instrs += I32Const(';'.toInt) - instrs += Call(genFunctionID.charToString) - instrs += Call(genFunctionID.stringConcat) + fb += I32Const('L'.toInt) + fb += Call(genFunctionID.charToString) + fb += LocalGet(componentTypeDataLocal) + fb += Call(genFunctionID.typeDataName) + fb += Call(genFunctionID.stringConcat) + fb += I32Const(';'.toInt) + fb += Call(genFunctionID.charToString) + fb += Call(genFunctionID.stringConcat) } // At this point, the stack contains "[" and the string that must be concatenated with it - instrs += Call(genFunctionID.stringConcat) + fb += Call(genFunctionID.stringConcat) } { // it is not an array; its name is stored in nameData for ( @@ -803,16 +797,16 @@ object CoreWasmLib { genFieldID.typeData.nameStringIndex ) ) { - instrs += LocalGet(typeDataParam) - instrs += StructGet(genTypeID.typeData, idx) + fb += LocalGet(typeDataParam) + fb += StructGet(genTypeID.typeData, idx) } - instrs += Call(genFunctionID.stringLiteral) + fb += Call(genFunctionID.stringLiteral) } // typeData.name := ; leave it on the stack - instrs += LocalTee(nameLocal) - instrs += StructSet(genTypeID.typeData, genFieldID.typeData.name) - instrs += LocalGet(nameLocal) + fb += LocalTee(nameLocal) + fb += StructSet(genTypeID.typeData, genFieldID.typeData.name) + fb += LocalGet(nameLocal) } fb.buildAndAddToModule() @@ -833,87 +827,85 @@ object CoreWasmLib { val typeDataParam = fb.addParam("typeData", typeDataType) fb.setResultType(RefType(genTypeID.ClassStruct)) - val instrs = fb - val classInstanceLocal = fb.addLocal("classInstance", RefType(genTypeID.ClassStruct)) // classInstance := newDefault$java.lang.Class() // leave it on the stack for the constructor call - instrs += Call(genFunctionID.newDefault(ClassClass)) - instrs += LocalTee(classInstanceLocal) + fb += Call(genFunctionID.newDefault(ClassClass)) + fb += LocalTee(classInstanceLocal) /* The JS object containing metadata to pass as argument to the `jl.Class` constructor. * Specified by https://lampwww.epfl.ch/~doeraene/sjsir-semantics/#sec-sjsir-createclassdataof * Leave it on the stack. */ - instrs += Call(genFunctionID.jsNewObject) + fb += Call(genFunctionID.jsNewObject) // "__typeData": typeData (TODO hide this better? although nobody will notice anyway) - instrs ++= ctx.getConstantStringInstr("__typeData") - instrs += LocalGet(typeDataParam) - instrs += Call(genFunctionID.jsObjectPush) + fb ++= ctx.getConstantStringInstr("__typeData") + fb += LocalGet(typeDataParam) + fb += Call(genFunctionID.jsObjectPush) // "name": typeDataName(typeData) - instrs ++= ctx.getConstantStringInstr("name") - instrs += LocalGet(typeDataParam) - instrs += Call(genFunctionID.typeDataName) - instrs += Call(genFunctionID.jsObjectPush) + fb ++= ctx.getConstantStringInstr("name") + fb += LocalGet(typeDataParam) + fb += Call(genFunctionID.typeDataName) + fb += Call(genFunctionID.jsObjectPush) // "isPrimitive": (typeData.kind <= KindLastPrimitive) - instrs ++= ctx.getConstantStringInstr("isPrimitive") - instrs += LocalGet(typeDataParam) - instrs += StructGet(genTypeID.typeData, genFieldID.typeData.kind) - instrs += I32Const(KindLastPrimitive) - instrs += I32LeU - instrs += Call(genFunctionID.box(BooleanRef)) - instrs += Call(genFunctionID.jsObjectPush) + fb ++= ctx.getConstantStringInstr("isPrimitive") + fb += LocalGet(typeDataParam) + fb += StructGet(genTypeID.typeData, genFieldID.typeData.kind) + fb += I32Const(KindLastPrimitive) + fb += I32LeU + fb += Call(genFunctionID.box(BooleanRef)) + fb += Call(genFunctionID.jsObjectPush) // "isArrayClass": (typeData.kind == KindArray) - instrs ++= ctx.getConstantStringInstr("isArrayClass") - instrs += LocalGet(typeDataParam) - instrs += StructGet(genTypeID.typeData, genFieldID.typeData.kind) - instrs += I32Const(KindArray) - instrs += I32Eq - instrs += Call(genFunctionID.box(BooleanRef)) - instrs += Call(genFunctionID.jsObjectPush) + fb ++= ctx.getConstantStringInstr("isArrayClass") + fb += LocalGet(typeDataParam) + fb += StructGet(genTypeID.typeData, genFieldID.typeData.kind) + fb += I32Const(KindArray) + fb += I32Eq + fb += Call(genFunctionID.box(BooleanRef)) + fb += Call(genFunctionID.jsObjectPush) // "isInterface": (typeData.kind == KindInterface) - instrs ++= ctx.getConstantStringInstr("isInterface") - instrs += LocalGet(typeDataParam) - instrs += StructGet(genTypeID.typeData, genFieldID.typeData.kind) - instrs += I32Const(KindInterface) - instrs += I32Eq - instrs += Call(genFunctionID.box(BooleanRef)) - instrs += Call(genFunctionID.jsObjectPush) + fb ++= ctx.getConstantStringInstr("isInterface") + fb += LocalGet(typeDataParam) + fb += StructGet(genTypeID.typeData, genFieldID.typeData.kind) + fb += I32Const(KindInterface) + fb += I32Eq + fb += Call(genFunctionID.box(BooleanRef)) + fb += Call(genFunctionID.jsObjectPush) // "isInstance": closure(isInstance, typeData) - instrs ++= ctx.getConstantStringInstr("isInstance") - instrs += ctx.refFuncWithDeclaration(genFunctionID.isInstance) - instrs += LocalGet(typeDataParam) - instrs += Call(genFunctionID.closure) - instrs += Call(genFunctionID.jsObjectPush) + fb ++= ctx.getConstantStringInstr("isInstance") + fb += ctx.refFuncWithDeclaration(genFunctionID.isInstance) + fb += LocalGet(typeDataParam) + fb += Call(genFunctionID.closure) + fb += Call(genFunctionID.jsObjectPush) // "isAssignableFrom": closure(isAssignableFrom, typeData) - instrs ++= ctx.getConstantStringInstr("isAssignableFrom") - instrs += ctx.refFuncWithDeclaration(genFunctionID.isAssignableFromExternal) - instrs += LocalGet(typeDataParam) - instrs += Call(genFunctionID.closure) - instrs += Call(genFunctionID.jsObjectPush) + fb ++= ctx.getConstantStringInstr("isAssignableFrom") + fb += ctx.refFuncWithDeclaration(genFunctionID.isAssignableFromExternal) + fb += LocalGet(typeDataParam) + fb += Call(genFunctionID.closure) + fb += Call(genFunctionID.jsObjectPush) // "checkCast": closure(checkCast, typeData) - instrs ++= ctx.getConstantStringInstr("checkCast") - instrs += ctx.refFuncWithDeclaration(genFunctionID.checkCast) - instrs += LocalGet(typeDataParam) - instrs += Call(genFunctionID.closure) - instrs += Call(genFunctionID.jsObjectPush) + fb ++= ctx.getConstantStringInstr("checkCast") + fb += ctx.refFuncWithDeclaration(genFunctionID.checkCast) + fb += LocalGet(typeDataParam) + fb += Call(genFunctionID.closure) + fb += Call(genFunctionID.jsObjectPush) // "isAssignableFrom": closure(isAssignableFrom, typeData) // "getComponentType": closure(getComponentType, typeData) - instrs ++= ctx.getConstantStringInstr("getComponentType") - instrs += ctx.refFuncWithDeclaration(genFunctionID.getComponentType) - instrs += LocalGet(typeDataParam) - instrs += Call(genFunctionID.closure) - instrs += Call(genFunctionID.jsObjectPush) + fb ++= ctx.getConstantStringInstr("getComponentType") + fb += ctx.refFuncWithDeclaration(genFunctionID.getComponentType) + fb += LocalGet(typeDataParam) + fb += Call(genFunctionID.closure) + fb += Call(genFunctionID.jsObjectPush) // "newArrayOfThisClass": closure(newArrayOfThisClass, typeData) - instrs ++= ctx.getConstantStringInstr("newArrayOfThisClass") - instrs += ctx.refFuncWithDeclaration(genFunctionID.newArrayOfThisClass) - instrs += LocalGet(typeDataParam) - instrs += Call(genFunctionID.closure) - instrs += Call(genFunctionID.jsObjectPush) + fb ++= ctx.getConstantStringInstr("newArrayOfThisClass") + fb += ctx.refFuncWithDeclaration(genFunctionID.newArrayOfThisClass) + fb += LocalGet(typeDataParam) + fb += Call(genFunctionID.closure) + fb += Call(genFunctionID.jsObjectPush) // Call java.lang.Class::(dataObject) - instrs += Call( + fb += Call( genFunctionID.forMethod( MemberNamespace.Constructor, ClassClass, @@ -922,12 +914,12 @@ object CoreWasmLib { ) // typeData.classOfValue := classInstance - instrs += LocalGet(typeDataParam) - instrs += LocalGet(classInstanceLocal) - instrs += StructSet(genTypeID.typeData, genFieldID.typeData.classOfValue) + fb += LocalGet(typeDataParam) + fb += LocalGet(classInstanceLocal) + fb += StructSet(genTypeID.typeData, genFieldID.typeData.classOfValue) // := classInstance for the implicit return - instrs += LocalGet(classInstanceLocal) + fb += LocalGet(classInstanceLocal) fb.buildAndAddToModule() } @@ -947,16 +939,14 @@ object CoreWasmLib { val typeDataParam = fb.addParam("typeData", typeDataType) fb.setResultType(RefType(genTypeID.ClassStruct)) - val instrs = fb - - instrs.block(RefType(genTypeID.ClassStruct)) { alreadyInitializedLabel => + fb.block(RefType(genTypeID.ClassStruct)) { alreadyInitializedLabel => // fast path - instrs += LocalGet(typeDataParam) - instrs += StructGet(genTypeID.typeData, genFieldID.typeData.classOfValue) - instrs += BrOnNonNull(alreadyInitializedLabel) + fb += LocalGet(typeDataParam) + fb += StructGet(genTypeID.typeData, genFieldID.typeData.classOfValue) + fb += BrOnNonNull(alreadyInitializedLabel) // slow path - instrs += LocalGet(typeDataParam) - instrs += Call(genFunctionID.createClassOf) + fb += LocalGet(typeDataParam) + fb += Call(genFunctionID.createClassOf) } // end bock alreadyInitializedLabel fb.buildAndAddToModule() @@ -984,116 +974,114 @@ object CoreWasmLib { val dimsParam = fb.addParam("dims", Int32) fb.setResultType(objectVTableType) - val instrs = fb - val arrayTypeDataLocal = fb.addLocal("arrayTypeData", objectVTableType) - instrs.loop() { loopLabel => - instrs.block(objectVTableType) { arrayOfIsNonNullLabel => + fb.loop() { loopLabel => + fb.block(objectVTableType) { arrayOfIsNonNullLabel => // br_on_non_null $arrayOfIsNonNull typeData.arrayOf - instrs += LocalGet(typeDataParam) - instrs += StructGet( + fb += LocalGet(typeDataParam) + fb += StructGet( genTypeID.typeData, genFieldID.typeData.arrayOf ) - instrs += BrOnNonNull(arrayOfIsNonNullLabel) + fb += BrOnNonNull(arrayOfIsNonNullLabel) // := typeData ; for the .arrayOf := ... later on - instrs += LocalGet(typeDataParam) + fb += LocalGet(typeDataParam) // typeData := new typeData(...) - instrs += I32Const(0) // nameOffset - instrs += I32Const(0) // nameSize - instrs += I32Const(0) // nameStringIndex - instrs += I32Const(KindArray) // kind = KindArray - instrs += I32Const(0) // specialInstanceTypes = 0 + fb += I32Const(0) // nameOffset + fb += I32Const(0) // nameSize + fb += I32Const(0) // nameStringIndex + fb += I32Const(KindArray) // kind = KindArray + fb += I32Const(0) // specialInstanceTypes = 0 // strictAncestors for (strictAncestor <- strictAncestors) - instrs += GlobalGet(genGlobalID.forVTable(strictAncestor)) - instrs += ArrayNewFixed( + fb += GlobalGet(genGlobalID.forVTable(strictAncestor)) + fb += ArrayNewFixed( genTypeID.typeDataArray, strictAncestors.size ) - instrs += LocalGet(typeDataParam) // componentType - instrs += RefNull(HeapType.None) // name - instrs += RefNull(HeapType.None) // classOf - instrs += RefNull(HeapType.None) // arrayOf + fb += LocalGet(typeDataParam) // componentType + fb += RefNull(HeapType.None) // name + fb += RefNull(HeapType.None) // classOf + fb += RefNull(HeapType.None) // arrayOf // clone - instrs.switch(RefType(genTypeID.cloneFunctionType)) { () => - instrs += LocalGet(typeDataParam) - instrs += StructGet(genTypeID.typeData, genFieldID.typeData.kind) + fb.switch(RefType(genTypeID.cloneFunctionType)) { () => + fb += LocalGet(typeDataParam) + fb += StructGet(genTypeID.typeData, genFieldID.typeData.kind) }( List(KindBoolean) -> { () => - instrs += ctx.refFuncWithDeclaration(genFunctionID.clone(BooleanRef)) + fb += ctx.refFuncWithDeclaration(genFunctionID.clone(BooleanRef)) }, List(KindChar) -> { () => - instrs += ctx.refFuncWithDeclaration(genFunctionID.clone(CharRef)) + fb += ctx.refFuncWithDeclaration(genFunctionID.clone(CharRef)) }, List(KindByte) -> { () => - instrs += ctx.refFuncWithDeclaration(genFunctionID.clone(ByteRef)) + fb += ctx.refFuncWithDeclaration(genFunctionID.clone(ByteRef)) }, List(KindShort) -> { () => - instrs += ctx.refFuncWithDeclaration(genFunctionID.clone(ShortRef)) + fb += ctx.refFuncWithDeclaration(genFunctionID.clone(ShortRef)) }, List(KindInt) -> { () => - instrs += ctx.refFuncWithDeclaration(genFunctionID.clone(IntRef)) + fb += ctx.refFuncWithDeclaration(genFunctionID.clone(IntRef)) }, List(KindLong) -> { () => - instrs += ctx.refFuncWithDeclaration(genFunctionID.clone(LongRef)) + fb += ctx.refFuncWithDeclaration(genFunctionID.clone(LongRef)) }, List(KindFloat) -> { () => - instrs += ctx.refFuncWithDeclaration(genFunctionID.clone(FloatRef)) + fb += ctx.refFuncWithDeclaration(genFunctionID.clone(FloatRef)) }, List(KindDouble) -> { () => - instrs += ctx.refFuncWithDeclaration(genFunctionID.clone(DoubleRef)) + fb += ctx.refFuncWithDeclaration(genFunctionID.clone(DoubleRef)) } ) { () => - instrs += ctx.refFuncWithDeclaration( + fb += ctx.refFuncWithDeclaration( genFunctionID.clone(ClassRef(ObjectClass)) ) } // isJSClassInstance - instrs += RefNull(HeapType.NoFunc) + fb += RefNull(HeapType.NoFunc) // reflectiveProxies - instrs += ArrayNewFixed(genTypeID.reflectiveProxies, 0) // TODO + fb += ArrayNewFixed(genTypeID.reflectiveProxies, 0) // TODO val objectClassInfo = ctx.getClassInfo(ObjectClass) - instrs ++= objectClassInfo.tableEntries.map { methodName => + fb ++= objectClassInfo.tableEntries.map { methodName => ctx.refFuncWithDeclaration(objectClassInfo.resolvedMethodInfos(methodName).tableEntryName) } - instrs += StructNew(genTypeID.ObjectVTable) - instrs += LocalTee(arrayTypeDataLocal) + fb += StructNew(genTypeID.ObjectVTable) + fb += LocalTee(arrayTypeDataLocal) // .arrayOf := typeData - instrs += StructSet(genTypeID.typeData, genFieldID.typeData.arrayOf) + fb += StructSet(genTypeID.typeData, genFieldID.typeData.arrayOf) // put arrayTypeData back on the stack - instrs += LocalGet(arrayTypeDataLocal) + fb += LocalGet(arrayTypeDataLocal) } // end block $arrayOfIsNonNullLabel // dims := dims - 1 -- leave dims on the stack - instrs += LocalGet(dimsParam) - instrs += I32Const(1) - instrs += I32Sub - instrs += LocalTee(dimsParam) + fb += LocalGet(dimsParam) + fb += I32Const(1) + fb += I32Sub + fb += LocalTee(dimsParam) // if dims == 0 then // return typeData.arrayOf (which is on the stack) - instrs += I32Eqz - instrs.ifThen(FunctionType(List(objectVTableType), List(objectVTableType))) { - instrs += Return + fb += I32Eqz + fb.ifThen(FunctionType(List(objectVTableType), List(objectVTableType))) { + fb += Return } // typeData := typeData.arrayOf (which is on the stack), then loop back to the beginning - instrs += LocalSet(typeDataParam) - instrs += Br(loopLabel) + fb += LocalSet(typeDataParam) + fb += Br(loopLabel) } // end loop $loop - instrs += Unreachable + fb += Unreachable fb.buildAndAddToModule() } @@ -1116,109 +1104,107 @@ object CoreWasmLib { val valueParam = fb.addParam("value", RefType.anyref) fb.setResultType(Int32) - val instrs = fb - val valueNonNullLocal = fb.addLocal("valueNonNull", RefType.any) val specialInstanceTypesLocal = fb.addLocal("specialInstanceTypes", Int32) // switch (typeData.kind) - instrs.switch(Int32) { () => - instrs += LocalGet(typeDataParam) - instrs += StructGet(genTypeID.typeData, kind) + fb.switch(Int32) { () => + fb += LocalGet(typeDataParam) + fb += StructGet(genTypeID.typeData, kind) }( // case anyPrimitiveKind => false (KindVoid to KindLastPrimitive).toList -> { () => - instrs += I32Const(0) + fb += I32Const(0) }, // case KindObject => value ne null List(KindObject) -> { () => - instrs += LocalGet(valueParam) - instrs += RefIsNull - instrs += I32Eqz + fb += LocalGet(valueParam) + fb += RefIsNull + fb += I32Eqz }, // for each boxed class, the corresponding primitive type test List(KindBoxedUnit) -> { () => - instrs += LocalGet(valueParam) - instrs += Call(genFunctionID.isUndef) + fb += LocalGet(valueParam) + fb += Call(genFunctionID.isUndef) }, List(KindBoxedBoolean) -> { () => - instrs += LocalGet(valueParam) - instrs += Call(genFunctionID.typeTest(BooleanRef)) + fb += LocalGet(valueParam) + fb += Call(genFunctionID.typeTest(BooleanRef)) }, List(KindBoxedCharacter) -> { () => - instrs += LocalGet(valueParam) + fb += LocalGet(valueParam) val structTypeName = genTypeID.forClass(SpecialNames.CharBoxClass) - instrs += RefTest(RefType(structTypeName)) + fb += RefTest(RefType(structTypeName)) }, List(KindBoxedByte) -> { () => - instrs += LocalGet(valueParam) - instrs += Call(genFunctionID.typeTest(ByteRef)) + fb += LocalGet(valueParam) + fb += Call(genFunctionID.typeTest(ByteRef)) }, List(KindBoxedShort) -> { () => - instrs += LocalGet(valueParam) - instrs += Call(genFunctionID.typeTest(ShortRef)) + fb += LocalGet(valueParam) + fb += Call(genFunctionID.typeTest(ShortRef)) }, List(KindBoxedInteger) -> { () => - instrs += LocalGet(valueParam) - instrs += Call(genFunctionID.typeTest(IntRef)) + fb += LocalGet(valueParam) + fb += Call(genFunctionID.typeTest(IntRef)) }, List(KindBoxedLong) -> { () => - instrs += LocalGet(valueParam) + fb += LocalGet(valueParam) val structTypeName = genTypeID.forClass(SpecialNames.LongBoxClass) - instrs += RefTest(RefType(structTypeName)) + fb += RefTest(RefType(structTypeName)) }, List(KindBoxedFloat) -> { () => - instrs += LocalGet(valueParam) - instrs += Call(genFunctionID.typeTest(FloatRef)) + fb += LocalGet(valueParam) + fb += Call(genFunctionID.typeTest(FloatRef)) }, List(KindBoxedDouble) -> { () => - instrs += LocalGet(valueParam) - instrs += Call(genFunctionID.typeTest(DoubleRef)) + fb += LocalGet(valueParam) + fb += Call(genFunctionID.typeTest(DoubleRef)) }, List(KindBoxedString) -> { () => - instrs += LocalGet(valueParam) - instrs += Call(genFunctionID.isString) + fb += LocalGet(valueParam) + fb += Call(genFunctionID.isString) }, // case KindJSType => call typeData.isJSClassInstance(value) or throw if it is null List(KindJSType) -> { () => - instrs.block(RefType.anyref) { isJSClassInstanceIsNull => + fb.block(RefType.anyref) { isJSClassInstanceIsNull => // Load value as the argument to the function - instrs += LocalGet(valueParam) + fb += LocalGet(valueParam) // Load the function reference; break if null - instrs += LocalGet(typeDataParam) - instrs += StructGet(genTypeID.typeData, isJSClassInstance) - instrs += BrOnNull(isJSClassInstanceIsNull) + fb += LocalGet(typeDataParam) + fb += StructGet(genTypeID.typeData, isJSClassInstance) + fb += BrOnNull(isJSClassInstanceIsNull) // Call the function - instrs += CallRef(genTypeID.isJSClassInstanceFuncType) - instrs += Return + fb += CallRef(genTypeID.isJSClassInstanceFuncType) + fb += Return } - instrs += Drop // drop `value` which was left on the stack + fb += Drop // drop `value` which was left on the stack // throw new TypeError("...") - instrs ++= ctx.getConstantStringInstr("TypeError") - instrs += Call(genFunctionID.jsGlobalRefGet) - instrs += Call(genFunctionID.jsNewArray) - instrs ++= ctx.getConstantStringInstr( + fb ++= ctx.getConstantStringInstr("TypeError") + fb += Call(genFunctionID.jsGlobalRefGet) + fb += Call(genFunctionID.jsNewArray) + fb ++= ctx.getConstantStringInstr( "Cannot call isInstance() on a Class representing a JS trait/object" ) - instrs += Call(genFunctionID.jsArrayPush) - instrs += Call(genFunctionID.jsNew) - instrs += ExternConvertAny - instrs += Throw(genTagID.exception) + fb += Call(genFunctionID.jsArrayPush) + fb += Call(genFunctionID.jsNew) + fb += ExternConvertAny + fb += Throw(genTagID.exception) } ) { () => // case _ => // valueNonNull := as_non_null value; return false if null - instrs.block(RefType.any) { nonNullLabel => - instrs += LocalGet(valueParam) - instrs += BrOnNonNull(nonNullLabel) - instrs += I32Const(0) - instrs += Return + fb.block(RefType.any) { nonNullLabel => + fb += LocalGet(valueParam) + fb += BrOnNonNull(nonNullLabel) + fb += I32Const(0) + fb += Return } - instrs += LocalSet(valueNonNullLocal) + fb += LocalSet(valueNonNullLocal) /* If `typeData` represents an ancestor of a hijacked classes, we have to * answer `true` if `valueNonNull` is a primitive instance of any of the @@ -1241,56 +1227,56 @@ object CoreWasmLib { * There is a more elaborated concrete example of this algorithm in * `genInstanceTest`. */ - instrs += LocalGet(typeDataParam) - instrs += StructGet(genTypeID.typeData, specialInstanceTypes) - instrs += LocalTee(specialInstanceTypesLocal) - instrs += I32Const(0) - instrs += I32Ne - instrs.ifThen() { + fb += LocalGet(typeDataParam) + fb += StructGet(genTypeID.typeData, specialInstanceTypes) + fb += LocalTee(specialInstanceTypesLocal) + fb += I32Const(0) + fb += I32Ne + fb.ifThen() { // Load (1 << jsValueType(valueNonNull)) - instrs += I32Const(1) - instrs += LocalGet(valueNonNullLocal) - instrs += Call(genFunctionID.jsValueType) - instrs += I32Shl + fb += I32Const(1) + fb += LocalGet(valueNonNullLocal) + fb += Call(genFunctionID.jsValueType) + fb += I32Shl // if ((... & specialInstanceTypes) != 0) - instrs += LocalGet(specialInstanceTypesLocal) - instrs += I32And - instrs += I32Const(0) - instrs += I32Ne - instrs.ifThen() { + fb += LocalGet(specialInstanceTypesLocal) + fb += I32And + fb += I32Const(0) + fb += I32Ne + fb.ifThen() { // then return true - instrs += I32Const(1) - instrs += Return + fb += I32Const(1) + fb += Return } } // Get the vtable and delegate to isAssignableFrom // Load typeData - instrs += LocalGet(typeDataParam) + fb += LocalGet(typeDataParam) // Load the vtable; return false if it is not one of our object - instrs.block(objectRefType) { ourObjectLabel => + fb.block(objectRefType) { ourObjectLabel => // Try cast to jl.Object - instrs += LocalGet(valueNonNullLocal) - instrs += BrOnCast( + fb += LocalGet(valueNonNullLocal) + fb += BrOnCast( ourObjectLabel, RefType.any, RefType(objectRefType.heapType) ) // on cast fail, return false - instrs += I32Const(0) - instrs += Return + fb += I32Const(0) + fb += Return } - instrs += StructGet( + fb += StructGet( genTypeID.forClass(ObjectClass), genFieldID.objStruct.vtable ) // Call isAssignableFrom - instrs += Call(genFunctionID.isAssignableFrom) + fb += Call(genFunctionID.isAssignableFrom) } fb.buildAndAddToModule() @@ -1308,19 +1294,17 @@ object CoreWasmLib { val fromParam = fb.addParam("from", RefType.anyref) fb.setResultType(Int32) - val instrs = fb - // load typeData - instrs += LocalGet(typeDataParam) + fb += LocalGet(typeDataParam) // load ref.cast from["__typeData"] (as a JS selection) - instrs += LocalGet(fromParam) - instrs ++= ctx.getConstantStringInstr("__typeData") - instrs += Call(genFunctionID.jsSelect) - instrs += RefCast(RefType(typeDataType.heapType)) + fb += LocalGet(fromParam) + fb ++= ctx.getConstantStringInstr("__typeData") + fb += Call(genFunctionID.jsSelect) + fb += RefCast(RefType(typeDataType.heapType)) // delegate to isAssignableFrom - instrs += Call(genFunctionID.isAssignableFrom) + fb += Call(genFunctionID.isAssignableFrom) fb.buildAndAddToModule() } @@ -1339,112 +1323,110 @@ object CoreWasmLib { val fromTypeDataParam = fb.addParam("fromTypeData", typeDataType) fb.setResultType(Int32) - val instrs = fb - val fromAncestorsLocal = fb.addLocal("fromAncestors", RefType(genTypeID.typeDataArray)) val lenLocal = fb.addLocal("len", Int32) val iLocal = fb.addLocal("i", Int32) // if (fromTypeData eq typeData) - instrs += LocalGet(fromTypeDataParam) - instrs += LocalGet(typeDataParam) - instrs += RefEq - instrs.ifThen() { + fb += LocalGet(fromTypeDataParam) + fb += LocalGet(typeDataParam) + fb += RefEq + fb.ifThen() { // then return true - instrs += I32Const(1) - instrs += Return + fb += I32Const(1) + fb += Return } // "Tail call" loop for diving into array component types - instrs.loop(Int32) { loopForArrayLabel => + fb.loop(Int32) { loopForArrayLabel => // switch (typeData.kind) - instrs.switch(Int32) { () => + fb.switch(Int32) { () => // typeData.kind - instrs += LocalGet(typeDataParam) - instrs += StructGet(genTypeID.typeData, kind) + fb += LocalGet(typeDataParam) + fb += StructGet(genTypeID.typeData, kind) }( // case anyPrimitiveKind => return false (KindVoid to KindLastPrimitive).toList -> { () => - instrs += I32Const(0) + fb += I32Const(0) }, // case KindArray => check that from is an array, recurse into component types List(KindArray) -> { () => - instrs.block() { fromComponentTypeIsNullLabel => + fb.block() { fromComponentTypeIsNullLabel => // fromTypeData := fromTypeData.componentType; jump out if null - instrs += LocalGet(fromTypeDataParam) - instrs += StructGet(genTypeID.typeData, componentType) - instrs += BrOnNull(fromComponentTypeIsNullLabel) - instrs += LocalSet(fromTypeDataParam) + fb += LocalGet(fromTypeDataParam) + fb += StructGet(genTypeID.typeData, componentType) + fb += BrOnNull(fromComponentTypeIsNullLabel) + fb += LocalSet(fromTypeDataParam) // typeData := ref.as_non_null typeData.componentType (OK because KindArray) - instrs += LocalGet(typeDataParam) - instrs += StructGet(genTypeID.typeData, componentType) - instrs += RefAsNotNull - instrs += LocalSet(typeDataParam) + fb += LocalGet(typeDataParam) + fb += StructGet(genTypeID.typeData, componentType) + fb += RefAsNotNull + fb += LocalSet(typeDataParam) // loop back ("tail call") - instrs += Br(loopForArrayLabel) + fb += Br(loopForArrayLabel) } // return false - instrs += I32Const(0) + fb += I32Const(0) }, // case KindObject => return (fromTypeData.kind > KindLastPrimitive) List(KindObject) -> { () => - instrs += LocalGet(fromTypeDataParam) - instrs += StructGet(genTypeID.typeData, kind) - instrs += I32Const(KindLastPrimitive) - instrs += I32GtU + fb += LocalGet(fromTypeDataParam) + fb += StructGet(genTypeID.typeData, kind) + fb += I32Const(KindLastPrimitive) + fb += I32GtU } ) { () => // All other cases: test whether `fromTypeData.strictAncestors` contains `typeData` - instrs.block() { fromAncestorsIsNullLabel => + fb.block() { fromAncestorsIsNullLabel => // fromAncestors := fromTypeData.strictAncestors; go to fromAncestorsIsNull if null - instrs += LocalGet(fromTypeDataParam) - instrs += StructGet(genTypeID.typeData, strictAncestors) - instrs += BrOnNull(fromAncestorsIsNullLabel) - instrs += LocalTee(fromAncestorsLocal) + fb += LocalGet(fromTypeDataParam) + fb += StructGet(genTypeID.typeData, strictAncestors) + fb += BrOnNull(fromAncestorsIsNullLabel) + fb += LocalTee(fromAncestorsLocal) // if fromAncestors contains typeData, return true // len := fromAncestors.length - instrs += ArrayLen - instrs += LocalSet(lenLocal) + fb += ArrayLen + fb += LocalSet(lenLocal) // i := 0 - instrs += I32Const(0) - instrs += LocalSet(iLocal) + fb += I32Const(0) + fb += LocalSet(iLocal) // while (i != len) - instrs.whileLoop() { - instrs += LocalGet(iLocal) - instrs += LocalGet(lenLocal) - instrs += I32Ne + fb.whileLoop() { + fb += LocalGet(iLocal) + fb += LocalGet(lenLocal) + fb += I32Ne } { // if (fromAncestors[i] eq typeData) - instrs += LocalGet(fromAncestorsLocal) - instrs += LocalGet(iLocal) - instrs += ArrayGet(genTypeID.typeDataArray) - instrs += LocalGet(typeDataParam) - instrs += RefEq - instrs.ifThen() { + fb += LocalGet(fromAncestorsLocal) + fb += LocalGet(iLocal) + fb += ArrayGet(genTypeID.typeDataArray) + fb += LocalGet(typeDataParam) + fb += RefEq + fb.ifThen() { // then return true - instrs += I32Const(1) - instrs += Return + fb += I32Const(1) + fb += Return } // i := i + 1 - instrs += LocalGet(iLocal) - instrs += I32Const(1) - instrs += I32Add - instrs += LocalSet(iLocal) + fb += LocalGet(iLocal) + fb += I32Const(1) + fb += I32Add + fb += LocalSet(iLocal) } } // from.strictAncestors is null or does not contain typeData // return false - instrs += I32Const(0) + fb += I32Const(0) } } @@ -1463,13 +1445,11 @@ object CoreWasmLib { val valueParam = fb.addParam("value", RefType.anyref) fb.setResultType(RefType.anyref) - val instrs = fb - /* Given that we only implement `CheckedBehavior.Unchecked` semantics for * now, this is always the identity. */ - instrs += LocalGet(valueParam) + fb += LocalGet(valueParam) fb.buildAndAddToModule() } @@ -1485,20 +1465,18 @@ object CoreWasmLib { val typeDataParam = fb.addParam("typeData", typeDataType) fb.setResultType(RefType.nullable(genTypeID.ClassStruct)) - val instrs = fb - val componentTypeDataLocal = fb.addLocal("componentTypeData", typeDataType) - instrs.block() { nullResultLabel => + fb.block() { nullResultLabel => // Try and extract non-null component type data - instrs += LocalGet(typeDataParam) - instrs += StructGet(genTypeID.typeData, genFieldID.typeData.componentType) - instrs += BrOnNull(nullResultLabel) + fb += LocalGet(typeDataParam) + fb += StructGet(genTypeID.typeData, genFieldID.typeData.componentType) + fb += BrOnNull(nullResultLabel) // Get the corresponding classOf - instrs += Call(genFunctionID.getClassOf) - instrs += Return + fb += Call(genFunctionID.getClassOf) + fb += Return } // end block nullResultLabel - instrs += RefNull(HeapType(genTypeID.ClassStruct)) + fb += RefNull(HeapType(genTypeID.ClassStruct)) fb.buildAndAddToModule() } @@ -1516,60 +1494,58 @@ object CoreWasmLib { val lengthsParam = fb.addParam("lengths", RefType.anyref) fb.setResultType(RefType(genTypeID.ObjectStruct)) - val instrs = fb - val lengthsLenLocal = fb.addLocal("lengthsLenLocal", Int32) val lengthsValuesLocal = fb.addLocal("lengthsValues", i32ArrayType) val iLocal = fb.addLocal("i", Int32) // lengthsLen := lengths.length // as a JS field access - instrs += LocalGet(lengthsParam) - instrs ++= ctx.getConstantStringInstr("length") - instrs += Call(genFunctionID.jsSelect) - instrs += Call(genFunctionID.unbox(IntRef)) - instrs += LocalTee(lengthsLenLocal) + fb += LocalGet(lengthsParam) + fb ++= ctx.getConstantStringInstr("length") + fb += Call(genFunctionID.jsSelect) + fb += Call(genFunctionID.unbox(IntRef)) + fb += LocalTee(lengthsLenLocal) // lengthsValues := array.new lengthsLen - instrs += ArrayNewDefault(genTypeID.i32Array) - instrs += LocalSet(lengthsValuesLocal) + fb += ArrayNewDefault(genTypeID.i32Array) + fb += LocalSet(lengthsValuesLocal) // i := 0 - instrs += I32Const(0) - instrs += LocalSet(iLocal) + fb += I32Const(0) + fb += LocalSet(iLocal) // while (i != lengthsLen) - instrs.whileLoop() { - instrs += LocalGet(iLocal) - instrs += LocalGet(lengthsLenLocal) - instrs += I32Ne + fb.whileLoop() { + fb += LocalGet(iLocal) + fb += LocalGet(lengthsLenLocal) + fb += I32Ne } { // lengthsValue[i] := lengths[i] (where the rhs is a JS field access) - instrs += LocalGet(lengthsValuesLocal) - instrs += LocalGet(iLocal) + fb += LocalGet(lengthsValuesLocal) + fb += LocalGet(iLocal) - instrs += LocalGet(lengthsParam) - instrs += LocalGet(iLocal) - instrs += RefI31 - instrs += Call(genFunctionID.jsSelect) - instrs += Call(genFunctionID.unbox(IntRef)) + fb += LocalGet(lengthsParam) + fb += LocalGet(iLocal) + fb += RefI31 + fb += Call(genFunctionID.jsSelect) + fb += Call(genFunctionID.unbox(IntRef)) - instrs += ArraySet(genTypeID.i32Array) + fb += ArraySet(genTypeID.i32Array) // i += 1 - instrs += LocalGet(iLocal) - instrs += I32Const(1) - instrs += I32Add - instrs += LocalSet(iLocal) + fb += LocalGet(iLocal) + fb += I32Const(1) + fb += I32Add + fb += LocalSet(iLocal) } // return newArrayObject(arrayTypeData(typeData, lengthsLen), lengthsValues, 0) - instrs += LocalGet(typeDataParam) - instrs += LocalGet(lengthsLenLocal) - instrs += Call(genFunctionID.arrayTypeData) - instrs += LocalGet(lengthsValuesLocal) - instrs += I32Const(0) - instrs += Call(genFunctionID.newArrayObject) + fb += LocalGet(typeDataParam) + fb += LocalGet(lengthsLenLocal) + fb += Call(genFunctionID.arrayTypeData) + fb += LocalGet(lengthsValuesLocal) + fb += I32Const(0) + fb += Call(genFunctionID.newArrayObject) fb.buildAndAddToModule() } @@ -1589,8 +1565,6 @@ object CoreWasmLib { val valueParam = fb.addParam("value", RefType.any) fb.setResultType(RefType.nullable(genTypeID.ClassStruct)) - val instrs = fb - val typeDataLocal = fb.addLocal("typeData", typeDataType) val doubleValueLocal = fb.addLocal("doubleValue", Float64) val intValueLocal = fb.addLocal("intValue", Int32) @@ -1599,30 +1573,30 @@ object CoreWasmLib { def getHijackedClassTypeDataInstr(className: ClassName): Instr = GlobalGet(genGlobalID.forVTable(className)) - instrs.block(RefType.nullable(genTypeID.ClassStruct)) { nonNullClassOfLabel => - instrs.block(typeDataType) { gotTypeDataLabel => - instrs.block(RefType(genTypeID.ObjectStruct)) { ourObjectLabel => + fb.block(RefType.nullable(genTypeID.ClassStruct)) { nonNullClassOfLabel => + fb.block(typeDataType) { gotTypeDataLabel => + fb.block(RefType(genTypeID.ObjectStruct)) { ourObjectLabel => // if value is our object, jump to $ourObject - instrs += LocalGet(valueParam) - instrs += BrOnCast( + fb += LocalGet(valueParam) + fb += BrOnCast( ourObjectLabel, RefType.any, RefType(genTypeID.ObjectStruct) ) // switch(jsValueType(value)) { ... } - instrs.switch(typeDataType) { () => + fb.switch(typeDataType) { () => // scrutinee - instrs += LocalGet(valueParam) - instrs += Call(genFunctionID.jsValueType) + fb += LocalGet(valueParam) + fb += Call(genFunctionID.jsValueType) }( // case JSValueTypeFalse, JSValueTypeTrue => typeDataOf[jl.Boolean] List(JSValueTypeFalse, JSValueTypeTrue) -> { () => - instrs += getHijackedClassTypeDataInstr(BoxedBooleanClass) + fb += getHijackedClassTypeDataInstr(BoxedBooleanClass) }, // case JSValueTypeString => typeDataOf[jl.String] List(JSValueTypeString) -> { () => - instrs += getHijackedClassTypeDataInstr(BoxedStringClass) + fb += getHijackedClassTypeDataInstr(BoxedStringClass) }, // case JSValueTypeNumber => ... List(JSValueTypeNumber) -> { () => @@ -1631,83 +1605,83 @@ object CoreWasmLib { */ // doubleValue := unboxDouble(value) - instrs += LocalGet(valueParam) - instrs += Call(genFunctionID.unbox(DoubleRef)) - instrs += LocalTee(doubleValueLocal) + fb += LocalGet(valueParam) + fb += Call(genFunctionID.unbox(DoubleRef)) + fb += LocalTee(doubleValueLocal) // intValue := doubleValue.toInt - instrs += I32TruncSatF64S - instrs += LocalTee(intValueLocal) + fb += I32TruncSatF64S + fb += LocalTee(intValueLocal) // if same(intValue.toDouble, doubleValue) -- same bit pattern to avoid +0.0 == -0.0 - instrs += F64ConvertI32S - instrs += I64ReinterpretF64 - instrs += LocalGet(doubleValueLocal) - instrs += I64ReinterpretF64 - instrs += I64Eq - instrs.ifThenElse(typeDataType) { + fb += F64ConvertI32S + fb += I64ReinterpretF64 + fb += LocalGet(doubleValueLocal) + fb += I64ReinterpretF64 + fb += I64Eq + fb.ifThenElse(typeDataType) { // then it is a Byte, a Short, or an Integer // if intValue.toByte.toInt == intValue - instrs += LocalGet(intValueLocal) - instrs += I32Extend8S - instrs += LocalGet(intValueLocal) - instrs += I32Eq - instrs.ifThenElse(typeDataType) { + fb += LocalGet(intValueLocal) + fb += I32Extend8S + fb += LocalGet(intValueLocal) + fb += I32Eq + fb.ifThenElse(typeDataType) { // then it is a Byte - instrs += getHijackedClassTypeDataInstr(BoxedByteClass) + fb += getHijackedClassTypeDataInstr(BoxedByteClass) } { // else, if intValue.toShort.toInt == intValue - instrs += LocalGet(intValueLocal) - instrs += I32Extend16S - instrs += LocalGet(intValueLocal) - instrs += I32Eq - instrs.ifThenElse(typeDataType) { + fb += LocalGet(intValueLocal) + fb += I32Extend16S + fb += LocalGet(intValueLocal) + fb += I32Eq + fb.ifThenElse(typeDataType) { // then it is a Short - instrs += getHijackedClassTypeDataInstr(BoxedShortClass) + fb += getHijackedClassTypeDataInstr(BoxedShortClass) } { // else, it is an Integer - instrs += getHijackedClassTypeDataInstr(BoxedIntegerClass) + fb += getHijackedClassTypeDataInstr(BoxedIntegerClass) } } } { // else, it is a Float or a Double // if doubleValue.toFloat.toDouble == doubleValue - instrs += LocalGet(doubleValueLocal) - instrs += F32DemoteF64 - instrs += F64PromoteF32 - instrs += LocalGet(doubleValueLocal) - instrs += F64Eq - instrs.ifThenElse(typeDataType) { + fb += LocalGet(doubleValueLocal) + fb += F32DemoteF64 + fb += F64PromoteF32 + fb += LocalGet(doubleValueLocal) + fb += F64Eq + fb.ifThenElse(typeDataType) { // then it is a Float - instrs += getHijackedClassTypeDataInstr(BoxedFloatClass) + fb += getHijackedClassTypeDataInstr(BoxedFloatClass) } { // else, if it is NaN - instrs += LocalGet(doubleValueLocal) - instrs += LocalGet(doubleValueLocal) - instrs += F64Ne - instrs.ifThenElse(typeDataType) { + fb += LocalGet(doubleValueLocal) + fb += LocalGet(doubleValueLocal) + fb += F64Ne + fb.ifThenElse(typeDataType) { // then it is a Float - instrs += getHijackedClassTypeDataInstr(BoxedFloatClass) + fb += getHijackedClassTypeDataInstr(BoxedFloatClass) } { // else, it is a Double - instrs += getHijackedClassTypeDataInstr(BoxedDoubleClass) + fb += getHijackedClassTypeDataInstr(BoxedDoubleClass) } } } }, // case JSValueTypeUndefined => typeDataOf[jl.Void] List(JSValueTypeUndefined) -> { () => - instrs += getHijackedClassTypeDataInstr(BoxedUnitClass) + fb += getHijackedClassTypeDataInstr(BoxedUnitClass) } ) { () => // case _ (JSValueTypeOther) => return null - instrs += RefNull(HeapType(genTypeID.ClassStruct)) - instrs += Return + fb += RefNull(HeapType(genTypeID.ClassStruct)) + fb += Return } - instrs += Br(gotTypeDataLabel) + fb += Br(gotTypeDataLabel) } /* Now we have one of our objects. Normally we only have to get the @@ -1715,18 +1689,18 @@ object CoreWasmLib { * `jl.CharacterBox` or `jl.LongBox`, we must use the typeData of * `jl.Character` or `jl.Long`, respectively. */ - instrs += LocalTee(ourObjectLocal) - instrs += RefTest(RefType(genTypeID.forClass(SpecialNames.CharBoxClass))) - instrs.ifThenElse(typeDataType) { - instrs += getHijackedClassTypeDataInstr(BoxedCharacterClass) + fb += LocalTee(ourObjectLocal) + fb += RefTest(RefType(genTypeID.forClass(SpecialNames.CharBoxClass))) + fb.ifThenElse(typeDataType) { + fb += getHijackedClassTypeDataInstr(BoxedCharacterClass) } { - instrs += LocalGet(ourObjectLocal) - instrs += RefTest(RefType(genTypeID.forClass(SpecialNames.LongBoxClass))) - instrs.ifThenElse(typeDataType) { - instrs += getHijackedClassTypeDataInstr(BoxedLongClass) + fb += LocalGet(ourObjectLocal) + fb += RefTest(RefType(genTypeID.forClass(SpecialNames.LongBoxClass))) + fb.ifThenElse(typeDataType) { + fb += getHijackedClassTypeDataInstr(BoxedLongClass) } { - instrs += LocalGet(ourObjectLocal) - instrs += StructGet( + fb += LocalGet(ourObjectLocal) + fb += StructGet( genTypeID.forClass(ObjectClass), genFieldID.objStruct.vtable ) @@ -1734,7 +1708,7 @@ object CoreWasmLib { } } - instrs += Call(genFunctionID.getClassOf) + fb += Call(genFunctionID.getClassOf) } fb.buildAndAddToModule() @@ -1766,8 +1740,6 @@ object CoreWasmLib { val lengthIndexParam = fb.addParam("lengthIndex", Int32) fb.setResultType(nonNullObjectType) - val instrs = fb - val lenLocal = fb.addLocal("len", Int32) val underlyingLocal = fb.addLocal("underlying", anyArrayType) val subLengthIndexLocal = fb.addLocal("subLengthIndex", Int32) @@ -1811,13 +1783,13 @@ object CoreWasmLib { ) // Load the vtable and itable or the resulting array on the stack - instrs += LocalGet(arrayTypeDataParam) // vtable - instrs += GlobalGet(genGlobalID.arrayClassITable) // itable + fb += LocalGet(arrayTypeDataParam) // vtable + fb += GlobalGet(genGlobalID.arrayClassITable) // itable // Load the first length - instrs += LocalGet(lengthsParam) - instrs += LocalGet(lengthIndexParam) - instrs += ArrayGet(genTypeID.i32Array) + fb += LocalGet(lengthsParam) + fb += LocalGet(lengthIndexParam) + fb += ArrayGet(genTypeID.i32Array) // componentTypeData := ref_as_non_null(arrayTypeData.componentType) // switch (componentTypeData.kind) @@ -1825,19 +1797,19 @@ object CoreWasmLib { List(arrayTypeDataType, itablesType, Int32), List(nonNullObjectType) ) - instrs.switch(switchClauseSig) { () => + fb.switch(switchClauseSig) { () => // scrutinee - instrs += LocalGet(arrayTypeDataParam) - instrs += StructGet(genTypeID.typeData, genFieldID.typeData.componentType) - instrs += StructGet(genTypeID.typeData, genFieldID.typeData.kind) + fb += LocalGet(arrayTypeDataParam) + fb += StructGet(genTypeID.typeData, genFieldID.typeData.componentType) + fb += StructGet(genTypeID.typeData, genFieldID.typeData.kind) }( // For all the primitive types, by construction, this is the bottom dimension // case KindPrim => array.new_default underlyingPrimArray; struct.new PrimArray primRefsWithArrayTypes.map { case (primRef, kind) => List(kind) -> { () => val arrayTypeRef = ArrayTypeRef(primRef, 1) - instrs += ArrayNewDefault(genTypeID.underlyingOf(arrayTypeRef)) - instrs += StructNew(genTypeID.forArrayClass(arrayTypeRef)) + fb += ArrayNewDefault(genTypeID.underlyingOf(arrayTypeRef)) + fb += StructNew(genTypeID.forArrayClass(arrayTypeRef)) () // required for correct type inference } }: _* @@ -1845,65 +1817,65 @@ object CoreWasmLib { // default -- all non-primitive array types // len := (which is the first length) - instrs += LocalTee(lenLocal) + fb += LocalTee(lenLocal) // underlying := array.new_default anyArray val arrayTypeRef = ArrayTypeRef(ClassRef(ObjectClass), 1) - instrs += ArrayNewDefault(genTypeID.underlyingOf(arrayTypeRef)) - instrs += LocalSet(underlyingLocal) + fb += ArrayNewDefault(genTypeID.underlyingOf(arrayTypeRef)) + fb += LocalSet(underlyingLocal) // subLengthIndex := lengthIndex + 1 - instrs += LocalGet(lengthIndexParam) - instrs += I32Const(1) - instrs += I32Add - instrs += LocalTee(subLengthIndexLocal) + fb += LocalGet(lengthIndexParam) + fb += I32Const(1) + fb += I32Add + fb += LocalTee(subLengthIndexLocal) // if subLengthIndex != lengths.length - instrs += LocalGet(lengthsParam) - instrs += ArrayLen - instrs += I32Ne - instrs.ifThen() { + fb += LocalGet(lengthsParam) + fb += ArrayLen + fb += I32Ne + fb.ifThen() { // then, recursively initialize all the elements // arrayComponentTypeData := ref_cast arrayTypeData.componentTypeData - instrs += LocalGet(arrayTypeDataParam) - instrs += StructGet(genTypeID.typeData, genFieldID.typeData.componentType) - instrs += RefCast(RefType(arrayTypeDataType.heapType)) - instrs += LocalSet(arrayComponentTypeDataLocal) + fb += LocalGet(arrayTypeDataParam) + fb += StructGet(genTypeID.typeData, genFieldID.typeData.componentType) + fb += RefCast(RefType(arrayTypeDataType.heapType)) + fb += LocalSet(arrayComponentTypeDataLocal) // i := 0 - instrs += I32Const(0) - instrs += LocalSet(iLocal) + fb += I32Const(0) + fb += LocalSet(iLocal) // while (i != len) - instrs.whileLoop() { - instrs += LocalGet(iLocal) - instrs += LocalGet(lenLocal) - instrs += I32Ne + fb.whileLoop() { + fb += LocalGet(iLocal) + fb += LocalGet(lenLocal) + fb += I32Ne } { // underlying[i] := newArrayObject(arrayComponentType, lengths, subLengthIndex) - instrs += LocalGet(underlyingLocal) - instrs += LocalGet(iLocal) + fb += LocalGet(underlyingLocal) + fb += LocalGet(iLocal) - instrs += LocalGet(arrayComponentTypeDataLocal) - instrs += LocalGet(lengthsParam) - instrs += LocalGet(subLengthIndexLocal) - instrs += Call(genFunctionID.newArrayObject) + fb += LocalGet(arrayComponentTypeDataLocal) + fb += LocalGet(lengthsParam) + fb += LocalGet(subLengthIndexLocal) + fb += Call(genFunctionID.newArrayObject) - instrs += ArraySet(genTypeID.anyArray) + fb += ArraySet(genTypeID.anyArray) // i += 1 - instrs += LocalGet(iLocal) - instrs += I32Const(1) - instrs += I32Add - instrs += LocalSet(iLocal) + fb += LocalGet(iLocal) + fb += I32Const(1) + fb += I32Add + fb += LocalSet(iLocal) } } // load underlying; struct.new ObjectArray - instrs += LocalGet(underlyingLocal) - instrs += StructNew(genTypeID.forArrayClass(arrayTypeRef)) + fb += LocalGet(underlyingLocal) + fb += StructNew(genTypeID.forArrayClass(arrayTypeRef)) } fb.buildAndAddToModule() @@ -1939,72 +1911,70 @@ object CoreWasmLib { val objParam = fb.addParam("obj", RefType.anyref) fb.setResultType(Int32) - val instrs = fb - val objNonNullLocal = fb.addLocal("objNonNull", RefType.any) val resultLocal = fb.addLocal("result", Int32) // If `obj` is `null`, return 0 (by spec) - instrs.block(RefType.any) { nonNullLabel => - instrs += LocalGet(objParam) - instrs += BrOnNonNull(nonNullLabel) - instrs += I32Const(0) - instrs += Return + fb.block(RefType.any) { nonNullLabel => + fb += LocalGet(objParam) + fb += BrOnNonNull(nonNullLabel) + fb += I32Const(0) + fb += Return } - instrs += LocalTee(objNonNullLocal) + fb += LocalTee(objNonNullLocal) // If `obj` is one of our objects, skip all the jsValueType tests - instrs += RefTest(RefType(genTypeID.ObjectStruct)) - instrs += I32Eqz - instrs.ifThen() { - instrs.switch() { () => - instrs += LocalGet(objNonNullLocal) - instrs += Call(genFunctionID.jsValueType) + fb += RefTest(RefType(genTypeID.ObjectStruct)) + fb += I32Eqz + fb.ifThen() { + fb.switch() { () => + fb += LocalGet(objNonNullLocal) + fb += Call(genFunctionID.jsValueType) }( List(JSValueTypeFalse) -> { () => - instrs += I32Const(1237) // specified by jl.Boolean.hashCode() - instrs += Return + fb += I32Const(1237) // specified by jl.Boolean.hashCode() + fb += Return }, List(JSValueTypeTrue) -> { () => - instrs += I32Const(1231) // specified by jl.Boolean.hashCode() - instrs += Return + fb += I32Const(1231) // specified by jl.Boolean.hashCode() + fb += Return }, List(JSValueTypeString) -> { () => - instrs += LocalGet(objNonNullLocal) - instrs += Call( + fb += LocalGet(objNonNullLocal) + fb += Call( genFunctionID.forMethod(Public, BoxedStringClass, hashCodeMethodName) ) - instrs += Return + fb += Return }, List(JSValueTypeNumber) -> { () => - instrs += LocalGet(objNonNullLocal) - instrs += Call(genFunctionID.unbox(DoubleRef)) - instrs += Call( + fb += LocalGet(objNonNullLocal) + fb += Call(genFunctionID.unbox(DoubleRef)) + fb += Call( genFunctionID.forMethod(Public, BoxedDoubleClass, hashCodeMethodName) ) - instrs += Return + fb += Return }, List(JSValueTypeUndefined) -> { () => - instrs += I32Const(0) // specified by jl.Void.hashCode(), Scala.js only - instrs += Return + fb += I32Const(0) // specified by jl.Void.hashCode(), Scala.js only + fb += Return }, List(JSValueTypeBigInt) -> { () => - instrs += LocalGet(objNonNullLocal) - instrs += Call(genFunctionID.bigintHashCode) - instrs += Return + fb += LocalGet(objNonNullLocal) + fb += Call(genFunctionID.bigintHashCode) + fb += Return }, List(JSValueTypeSymbol) -> { () => - instrs.block() { descriptionIsNullLabel => - instrs += LocalGet(objNonNullLocal) - instrs += Call(genFunctionID.symbolDescription) - instrs += BrOnNull(descriptionIsNullLabel) - instrs += Call( + fb.block() { descriptionIsNullLabel => + fb += LocalGet(objNonNullLocal) + fb += Call(genFunctionID.symbolDescription) + fb += BrOnNull(descriptionIsNullLabel) + fb += Call( genFunctionID.forMethod(Public, BoxedStringClass, hashCodeMethodName) ) - instrs += Return + fb += Return } - instrs += I32Const(0) - instrs += Return + fb += I32Const(0) + fb += Return } ) { () => // JSValueTypeOther -- fall through to using idHashCodeMap @@ -2015,29 +1985,29 @@ object CoreWasmLib { // If we get here, use the idHashCodeMap // Read the existing idHashCode, if one exists - instrs += GlobalGet(genGlobalID.idHashCodeMap) - instrs += LocalGet(objNonNullLocal) - instrs += Call(genFunctionID.idHashCodeGet) - instrs += LocalTee(resultLocal) + fb += GlobalGet(genGlobalID.idHashCodeMap) + fb += LocalGet(objNonNullLocal) + fb += Call(genFunctionID.idHashCodeGet) + fb += LocalTee(resultLocal) // If it is 0, there was no recorded idHashCode yet; allocate a new one - instrs += I32Eqz - instrs.ifThen() { + fb += I32Eqz + fb.ifThen() { // Allocate a new idHashCode - instrs += GlobalGet(genGlobalID.lastIDHashCode) - instrs += I32Const(1) - instrs += I32Add - instrs += LocalTee(resultLocal) - instrs += GlobalSet(genGlobalID.lastIDHashCode) + fb += GlobalGet(genGlobalID.lastIDHashCode) + fb += I32Const(1) + fb += I32Add + fb += LocalTee(resultLocal) + fb += GlobalSet(genGlobalID.lastIDHashCode) // Store it for next time - instrs += GlobalGet(genGlobalID.idHashCodeMap) - instrs += LocalGet(objNonNullLocal) - instrs += LocalGet(resultLocal) - instrs += Call(genFunctionID.idHashCodeSet) + fb += GlobalGet(genGlobalID.idHashCodeMap) + fb += LocalGet(objNonNullLocal) + fb += LocalGet(resultLocal) + fb += Call(genFunctionID.idHashCodeSet) } - instrs += LocalGet(resultLocal) + fb += LocalGet(resultLocal) fb.buildAndAddToModule() } @@ -2057,61 +2027,59 @@ object CoreWasmLib { val methodIdParam = fb.addParam("methodId", Int32) fb.setResultType(RefType(HeapType.Func)) - val instrs = fb - val reflectiveProxies = fb.addLocal("reflectiveProxies", Types.RefType(genTypeID.reflectiveProxies)) val size = fb.addLocal("size", Types.Int32) val i = fb.addLocal("i", Types.Int32) - instrs += LocalGet(typeDataParam) - instrs += StructGet(genTypeID.typeData, genFieldID.typeData.reflectiveProxies) - instrs += LocalTee(reflectiveProxies) - instrs += ArrayLen - instrs += LocalSet(size) + fb += LocalGet(typeDataParam) + fb += StructGet(genTypeID.typeData, genFieldID.typeData.reflectiveProxies) + fb += LocalTee(reflectiveProxies) + fb += ArrayLen + fb += LocalSet(size) - instrs += I32Const(0) - instrs += LocalSet(i) + fb += I32Const(0) + fb += LocalSet(i) - instrs.whileLoop() { - instrs += LocalGet(i) - instrs += LocalGet(size) - instrs += I32Ne + fb.whileLoop() { + fb += LocalGet(i) + fb += LocalGet(size) + fb += I32Ne } { - instrs += LocalGet(reflectiveProxies) - instrs += LocalGet(i) - instrs += ArrayGet(genTypeID.reflectiveProxies) + fb += LocalGet(reflectiveProxies) + fb += LocalGet(i) + fb += ArrayGet(genTypeID.reflectiveProxies) - instrs += StructGet(genTypeID.reflectiveProxy, genFieldID.reflectiveProxy.func_name) - instrs += LocalGet(methodIdParam) - instrs += I32Eq + fb += StructGet(genTypeID.reflectiveProxy, genFieldID.reflectiveProxy.func_name) + fb += LocalGet(methodIdParam) + fb += I32Eq - instrs.ifThen() { - instrs += LocalGet(reflectiveProxies) - instrs += LocalGet(i) - instrs += ArrayGet(genTypeID.reflectiveProxies) + fb.ifThen() { + fb += LocalGet(reflectiveProxies) + fb += LocalGet(i) + fb += ArrayGet(genTypeID.reflectiveProxies) // get function reference - instrs += StructGet(genTypeID.reflectiveProxy, genFieldID.reflectiveProxy.func_ref) - instrs += Return + fb += StructGet(genTypeID.reflectiveProxy, genFieldID.reflectiveProxy.func_ref) + fb += Return } // i += 1 - instrs += LocalGet(i) - instrs += I32Const(1) - instrs += I32Add - instrs += LocalSet(i) + fb += LocalGet(i) + fb += I32Const(1) + fb += I32Add + fb += LocalSet(i) } // throw new TypeError("...") - instrs ++= ctx.getConstantStringInstr("TypeError") - instrs += Call(genFunctionID.jsGlobalRefGet) - instrs += Call(genFunctionID.jsNewArray) + fb ++= ctx.getConstantStringInstr("TypeError") + fb += Call(genFunctionID.jsGlobalRefGet) + fb += Call(genFunctionID.jsNewArray) // Originally, exception is thrown from JS saying e.g. "obj2.z1__ is not a function" - instrs ++= ctx.getConstantStringInstr("Method not found") - instrs += Call(genFunctionID.jsArrayPush) - instrs += Call(genFunctionID.jsNew) - instrs += ExternConvertAny - instrs += Throw(genTagID.exception) + fb ++= ctx.getConstantStringInstr("Method not found") + fb += Call(genFunctionID.jsArrayPush) + fb += Call(genFunctionID.jsNew) + fb += ExternConvertAny + fb += Throw(genTagID.exception) fb.buildAndAddToModule() } @@ -2146,8 +2114,6 @@ object CoreWasmLib { fb.setResultType(RefType(genTypeID.ObjectStruct)) fb.setFunctionType(genTypeID.cloneFunctionType) - val instrs = fb - val arrayTypeRef = ArrayTypeRef(baseRef, 1) val arrayStructTypeName = genTypeID.forArrayClass(arrayTypeRef) @@ -2162,31 +2128,31 @@ object CoreWasmLib { val resultUnderlyingLocal = fb.addLocal("resultUnderlying", underlyingArrayType) // Cast down the from argument - instrs += LocalGet(fromParam) - instrs += RefCast(arrayClassType) - instrs += LocalTee(fromLocal) + fb += LocalGet(fromParam) + fb += RefCast(arrayClassType) + fb += LocalTee(fromLocal) // Load the underlying array - instrs += StructGet(arrayStructTypeName, genFieldID.objStruct.arrayUnderlying) - instrs += LocalTee(fromUnderlyingLocal) + fb += StructGet(arrayStructTypeName, genFieldID.objStruct.arrayUnderlying) + fb += LocalTee(fromUnderlyingLocal) // Make a copy of the underlying array - instrs += ArrayLen - instrs += LocalTee(lengthLocal) - instrs += ArrayNewDefault(underlyingArrayTypeName) - instrs += LocalTee(resultUnderlyingLocal) // also dest for array.copy - instrs += I32Const(0) // destOffset - instrs += LocalGet(fromUnderlyingLocal) // src - instrs += I32Const(0) // srcOffset - instrs += LocalGet(lengthLocal) // length - instrs += ArrayCopy(underlyingArrayTypeName, underlyingArrayTypeName) + fb += ArrayLen + fb += LocalTee(lengthLocal) + fb += ArrayNewDefault(underlyingArrayTypeName) + fb += LocalTee(resultUnderlyingLocal) // also dest for array.copy + fb += I32Const(0) // destOffset + fb += LocalGet(fromUnderlyingLocal) // src + fb += I32Const(0) // srcOffset + fb += LocalGet(lengthLocal) // length + fb += ArrayCopy(underlyingArrayTypeName, underlyingArrayTypeName) // Build the result arrayStruct - instrs += LocalGet(fromLocal) - instrs += StructGet(arrayStructTypeName, genFieldID.objStruct.vtable) // vtable - instrs += GlobalGet(genGlobalID.arrayClassITable) // itable - instrs += LocalGet(resultUnderlyingLocal) - instrs += StructNew(arrayStructTypeName) + fb += LocalGet(fromLocal) + fb += StructGet(arrayStructTypeName, genFieldID.objStruct.vtable) // vtable + fb += GlobalGet(genGlobalID.arrayClassITable) // itable + fb += LocalGet(resultUnderlyingLocal) + fb += StructNew(arrayStructTypeName) fb.buildAndAddToModule() } diff --git a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/Emitter.scala b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/Emitter.scala index c4be761..1809407 100644 --- a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/Emitter.scala +++ b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/Emitter.scala @@ -141,7 +141,6 @@ final class Emitter(config: Emitter.Config) { val fb = new FunctionBuilder(ctx.moduleBuilder, genFunctionID.start, OriginalName("start"), pos) - val instrs: fb.type = fb // Initialize itables for (clazz <- sortedClasses if clazz.kind.isClass && clazz.hasDirectInstances) { @@ -154,13 +153,13 @@ final class Emitter(config: Emitter.Config) { interfaces.foreach { iface => val idx = ctx.getItableIdx(iface) - instrs += wa.GlobalGet(genGlobalID.forITable(className)) - instrs += wa.I32Const(idx) + fb += wa.GlobalGet(genGlobalID.forITable(className)) + fb += wa.I32Const(idx) for (method <- iface.tableEntries) - instrs += ctx.refFuncWithDeclaration(resolvedMethodInfos(method).tableEntryName) - instrs += wa.StructNew(genTypeID.forITable(iface.name)) - instrs += wa.ArraySet(genTypeID.itables) + fb += ctx.refFuncWithDeclaration(resolvedMethodInfos(method).tableEntryName) + fb += wa.StructNew(genTypeID.forITable(iface.name)) + fb += wa.ArraySet(genTypeID.itables) } } } @@ -175,13 +174,13 @@ final class Emitter(config: Emitter.Config) { // Use getClassInfoOption in case the reachability analysis got rid of those interfaces interfaceInfo <- ctx.getClassInfoOption(interfaceName) } { - instrs += wa.GlobalGet(globalName) - instrs += wa.I32Const(ctx.getItableIdx(interfaceInfo)) + fb += wa.GlobalGet(globalName) + fb += wa.I32Const(ctx.getItableIdx(interfaceInfo)) for (method <- interfaceInfo.tableEntries) - instrs += ctx.refFuncWithDeclaration(resolvedMethodInfos(method).tableEntryName) - instrs += wa.StructNew(genTypeID.forITable(interfaceName)) - instrs += wa.ArraySet(genTypeID.itables) + fb += ctx.refFuncWithDeclaration(resolvedMethodInfos(method).tableEntryName) + fb += wa.StructNew(genTypeID.forITable(interfaceName)) + fb += wa.ArraySet(genTypeID.itables) } } @@ -191,8 +190,8 @@ final class Emitter(config: Emitter.Config) { for (fieldDef <- clazz.fields) { fieldDef match { case FieldDef(flags, name, _, _) if !flags.namespace.isStatic => - instrs += wa.Call(genFunctionID.newSymbol) - instrs += wa.GlobalSet(genGlobalID.forJSPrivateField(name.name)) + fb += wa.Call(genFunctionID.newSymbol) + fb += wa.GlobalSet(genGlobalID.forJSPrivateField(name.name)) case _ => () } @@ -207,7 +206,7 @@ final class Emitter(config: Emitter.Config) { clazz.className, StaticInitializerName ) - instrs += wa.Call(funcName) + fb += wa.Call(funcName) } // Initialize the top-level exports that require it @@ -216,16 +215,16 @@ final class Emitter(config: Emitter.Config) { // Load the (initial) exported value on the stack tle.tree match { case TopLevelJSClassExportDef(_, exportName) => - instrs += wa.Call(genFunctionID.loadJSClass(tle.owningClass)) + fb += wa.Call(genFunctionID.loadJSClass(tle.owningClass)) case TopLevelModuleExportDef(_, exportName) => - instrs += wa.Call(genFunctionID.loadModule(tle.owningClass)) + fb += wa.Call(genFunctionID.loadModule(tle.owningClass)) case TopLevelMethodExportDef(_, methodDef) => - instrs += ctx.refFuncWithDeclaration(genFunctionID.forExport(tle.exportName)) + fb += ctx.refFuncWithDeclaration(genFunctionID.forExport(tle.exportName)) if (methodDef.restParam.isDefined) { - instrs += wa.I32Const(methodDef.args.size) - instrs += wa.Call(genFunctionID.makeExportedDefRest) + fb += wa.I32Const(methodDef.args.size) + fb += wa.Call(genFunctionID.makeExportedDefRest) } else { - instrs += wa.Call(genFunctionID.makeExportedDef) + fb += wa.Call(genFunctionID.makeExportedDef) } case TopLevelFieldExportDef(_, _, fieldIdent) => /* Usually redundant, but necessary if the static field is never @@ -233,11 +232,11 @@ final class Emitter(config: Emitter.Config) { * case this initial call is required to publish that zero value (as * opposed to the default `undefined` value of the JS `let`). */ - instrs += wa.GlobalGet(genGlobalID.forStaticField(fieldIdent.name)) + fb += wa.GlobalGet(genGlobalID.forStaticField(fieldIdent.name)) } // Call the export setter - instrs += wa.Call(genFunctionID.forTopLevelExportSetter(tle.exportName)) + fb += wa.Call(genFunctionID.forTopLevelExportSetter(tle.exportName)) } // Emit the module initializers @@ -246,26 +245,26 @@ final class Emitter(config: Emitter.Config) { def genCallStatic(className: ClassName, methodName: MethodName): Unit = { val functionName = genFunctionID.forMethod(MemberNamespace.PublicStatic, className, methodName) - instrs += wa.Call(functionName) + fb += wa.Call(functionName) } ModuleInitializerImpl.fromInitializer(init) match { case ModuleInitializerImpl.MainMethodWithArgs(className, encodedMainMethodName, args) => // vtable of Array[String] - instrs += wa.GlobalGet(genGlobalID.forVTable(BoxedStringClass)) - instrs += wa.I32Const(1) - instrs += wa.Call(genFunctionID.arrayTypeData) + fb += wa.GlobalGet(genGlobalID.forVTable(BoxedStringClass)) + fb += wa.I32Const(1) + fb += wa.Call(genFunctionID.arrayTypeData) // itable of Array[String] - instrs += wa.GlobalGet(genGlobalID.arrayClassITable) + fb += wa.GlobalGet(genGlobalID.arrayClassITable) // underlying array of args - args.foreach(arg => instrs ++= ctx.getConstantStringInstr(arg)) - instrs += wa.ArrayNewFixed(genTypeID.anyArray, args.size) + args.foreach(arg => fb ++= ctx.getConstantStringInstr(arg)) + fb += wa.ArrayNewFixed(genTypeID.anyArray, args.size) // array object val stringArrayTypeRef = ArrayTypeRef(ClassRef(BoxedStringClass), 1) - instrs += wa.StructNew(genTypeID.forArrayClass(stringArrayTypeRef)) + fb += wa.StructNew(genTypeID.forArrayClass(stringArrayTypeRef)) // call genCallStatic(className, encodedMainMethodName) diff --git a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/FunctionEmitter.scala b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/FunctionEmitter.scala index 3e884d0..b1be667 100644 --- a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/FunctionEmitter.scala +++ b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/FunctionEmitter.scala @@ -265,8 +265,6 @@ private class FunctionEmitter private ( )(implicit ctx: WasmContext) { import FunctionEmitter._ - private val instrs = fb - private var innerFuncIdx = 0 private var currentEnv: Env = paramsEnv @@ -314,7 +312,7 @@ private class FunctionEmitter private ( } private def markPosition(tree: Tree): Unit = - instrs += wa.PositionMark(tree.pos) + fb += wa.PositionMark(tree.pos) def genBody(tree: Tree, expectedType: Type): Unit = genTree(tree, expectedType) @@ -412,7 +410,7 @@ private class FunctionEmitter private ( case (NothingType, _) => () case (_, NoType) => - instrs += wa.Drop + fb += wa.Drop case (primType: PrimTypeWithRef, _) => // box primType match { @@ -436,7 +434,7 @@ private class FunctionEmitter private ( * asks the JS host to turn a primitive `i32` into its generic * representation, which we can store in an `anyref`. */ - instrs += wa.Call(genFunctionID.box(primType.primRef)) + fb += wa.Call(genFunctionID.box(primType.primRef)) } case _ => () @@ -457,10 +455,10 @@ private class FunctionEmitter private ( * However we necessarily have a `null` receiver if we reach this * point, so we can trap as NPE. */ - instrs += wa.Unreachable + fb += wa.Unreachable } else { genTree(t.rhs, t.lhs.tpe) - instrs += wa.StructSet( + fb += wa.StructSet( genTypeID.forClass(className), genFieldID.forClassInstanceField(sel.field.name) ) @@ -471,14 +469,14 @@ private class FunctionEmitter private ( val globalName = genGlobalID.forStaticField(fieldName) genTree(t.rhs, sel.tpe) - instrs += wa.GlobalSet(globalName) + fb += wa.GlobalSet(globalName) // Update top-level export mirrors val classInfo = ctx.getClassInfo(fieldName.className) val mirrors = classInfo.staticFieldMirrors.getOrElse(fieldName, Nil) for (exportedName <- mirrors) { - instrs += wa.GlobalGet(globalName) - instrs += wa.Call(genFunctionID.forTopLevelExportSetter(exportedName)) + fb += wa.GlobalGet(globalName) + fb += wa.Call(genFunctionID.forTopLevelExportSetter(exportedName)) } case sel: ArraySelect => @@ -486,18 +484,18 @@ private class FunctionEmitter private ( sel.array.tpe match { case ArrayType(arrayTypeRef) => // Get the underlying array; implicit trap on null - instrs += wa.StructGet( + fb += wa.StructGet( genTypeID.forArrayClass(arrayTypeRef), genFieldID.objStruct.arrayUnderlying ) genTree(sel.index, IntType) genTree(t.rhs, sel.tpe) - instrs += wa.ArraySet(genTypeID.underlyingOf(arrayTypeRef)) + fb += wa.ArraySet(genTypeID.underlyingOf(arrayTypeRef)) case NothingType => // unreachable () case NullType => - instrs += wa.Unreachable + fb += wa.Unreachable case _ => throw new IllegalArgumentException( s"ArraySelect.array must be an array type, but has type ${sel.array.tpe}" @@ -506,37 +504,37 @@ private class FunctionEmitter private ( case sel: JSPrivateSelect => genTree(sel.qualifier, AnyType) - instrs += wa.GlobalGet(genGlobalID.forJSPrivateField(sel.field.name)) + fb += wa.GlobalGet(genGlobalID.forJSPrivateField(sel.field.name)) genTree(t.rhs, AnyType) - instrs += wa.Call(genFunctionID.jsSelectSet) + fb += wa.Call(genFunctionID.jsSelectSet) case assign: JSSelect => genTree(assign.qualifier, AnyType) genTree(assign.item, AnyType) genTree(t.rhs, AnyType) - instrs += wa.Call(genFunctionID.jsSelectSet) + fb += wa.Call(genFunctionID.jsSelectSet) case assign: JSSuperSelect => genTree(assign.superClass, AnyType) genTree(assign.receiver, AnyType) genTree(assign.item, AnyType) genTree(t.rhs, AnyType) - instrs += wa.Call(genFunctionID.jsSuperSet) + fb += wa.Call(genFunctionID.jsSuperSet) case assign: JSGlobalRef => - instrs ++= ctx.getConstantStringInstr(assign.name) + fb ++= ctx.getConstantStringInstr(assign.name) genTree(t.rhs, AnyType) - instrs += wa.Call(genFunctionID.jsGlobalRefSet) + fb += wa.Call(genFunctionID.jsGlobalRefSet) case ref: VarRef => lookupLocal(ref.ident.name) match { case VarStorage.Local(local) => genTree(t.rhs, t.lhs.tpe) - instrs += wa.LocalSet(local) + fb += wa.LocalSet(local) case VarStorage.StructField(structLocal, structTypeName, fieldIdx) => - instrs += wa.LocalGet(structLocal) + fb += wa.LocalGet(structLocal) genTree(t.rhs, t.lhs.tpe) - instrs += wa.StructSet(structTypeName, fieldIdx) + fb += wa.StructSet(structTypeName, fieldIdx) } case assign: RecordSelect => @@ -555,7 +553,7 @@ private class FunctionEmitter private ( case NullType => genTree(t.receiver, NullType) - instrs += wa.Unreachable // trap + fb += wa.Unreachable // trap NothingType case _ if t.method.name.isReflectiveProxy => @@ -598,34 +596,34 @@ private class FunctionEmitter private ( val proxyId = ctx.getReflectiveProxyId(t.method.name) val funcTypeName = ctx.tableFunctionType(t.method.name) - instrs.block(watpe.RefType.anyref) { done => - instrs.block(watpe.RefType.any) { labelNotOurObject => + fb.block(watpe.RefType.anyref) { done => + fb.block(watpe.RefType.any) { labelNotOurObject => // arguments genTree(t.receiver, AnyType) - instrs += wa.RefAsNotNull - instrs += wa.LocalTee(receiverLocalForDispatch) + fb += wa.RefAsNotNull + fb += wa.LocalTee(receiverLocalForDispatch) genArgs(t.args, t.method.name) // Looks up the method to be (reflectively) called - instrs += wa.LocalGet(receiverLocalForDispatch) - instrs += wa.BrOnCastFail( + fb += wa.LocalGet(receiverLocalForDispatch) + fb += wa.BrOnCastFail( labelNotOurObject, watpe.RefType.any, watpe.RefType(genTypeID.ObjectStruct) ) - instrs += wa.StructGet( + fb += wa.StructGet( genTypeID.forClass(ObjectClass), genFieldID.objStruct.vtable ) - instrs += wa.I32Const(proxyId) + fb += wa.I32Const(proxyId) // `searchReflectiveProxy`: [typeData, i32] -> [(ref func)] - instrs += wa.Call(genFunctionID.searchReflectiveProxy) + fb += wa.Call(genFunctionID.searchReflectiveProxy) - instrs += wa.RefCast(watpe.RefType(watpe.HeapType(funcTypeName))) - instrs += wa.CallRef(funcTypeName) - instrs += wa.Br(done) + fb += wa.RefCast(watpe.RefType(watpe.HeapType(funcTypeName))) + fb += wa.CallRef(funcTypeName) + fb += wa.Br(done) } // labelNotFound - instrs += wa.Unreachable + fb += wa.Unreachable // TODO? reflective call on primitive types t.tpe } @@ -668,7 +666,7 @@ private class FunctionEmitter private ( */ def genReceiverNotNull(): Unit = { genTreeAuto(t.receiver) - instrs += wa.RefAsNotNull + fb += wa.RefAsNotNull } /* Generates a resolved call to a method of a hijacked class. @@ -681,7 +679,7 @@ private class FunctionEmitter private ( hijackedClass, t.method.name ) - instrs += wa.Call(funcName) + fb += wa.Call(funcName) } if (!receiverClassInfo.hasInstances) { @@ -693,11 +691,11 @@ private class FunctionEmitter private ( * cannot emit the corresponding vtable/itable calls. */ genTreeAuto(t.receiver) - instrs += wa.Unreachable // NPE + fb += wa.Unreachable // NPE } else if (!receiverClassInfo.isAncestorOfHijackedClass) { // Standard dispatch codegen genReceiverNotNull() - instrs += wa.LocalTee(receiverLocalForDispatch) + fb += wa.LocalTee(receiverLocalForDispatch) genArgs(t.args, t.method.name) genTableDispatch(receiverClassInfo, t.method.name, receiverLocalForDispatch) } else { @@ -727,12 +725,12 @@ private class FunctionEmitter private ( val resultTyp = transformResultType(t.tpe) - instrs.block(resultTyp) { labelDone => + fb.block(resultTyp) { labelDone => def pushArgs(argsLocals: List[wanme.LocalID]): Unit = - argsLocals.foreach(argLocal => instrs += wa.LocalGet(argLocal)) + argsLocals.foreach(argLocal => fb += wa.LocalGet(argLocal)) // First try the case where the value is one of our objects - val argsLocals = instrs.block(watpe.RefType.any) { labelNotOurObject => + val argsLocals = fb.block(watpe.RefType.any) { labelNotOurObject => // Load receiver and arguments and store them in temporary variables genReceiverNotNull() val argsLocals = if (t.args.isEmpty) { @@ -744,24 +742,24 @@ private class FunctionEmitter private ( } else { val receiverLocal = addSyntheticLocal(watpe.RefType.any) - instrs += wa.LocalSet(receiverLocal) + fb += wa.LocalSet(receiverLocal) val argsLocals: List[wanme.LocalID] = for ((arg, typeRef) <- t.args.zip(t.method.name.paramTypeRefs)) yield { val typ = ctx.inferTypeFromTypeRef(typeRef) genTree(arg, typ) val localName = addSyntheticLocal(transformType(typ)) - instrs += wa.LocalSet(localName) + fb += wa.LocalSet(localName) localName } - instrs += wa.LocalGet(receiverLocal) + fb += wa.LocalGet(receiverLocal) argsLocals } - instrs += wa.BrOnCastFail(labelNotOurObject, watpe.RefType.any, refTypeForDispatch) - instrs += wa.LocalTee(receiverLocalForDispatch) + fb += wa.BrOnCastFail(labelNotOurObject, watpe.RefType.any, refTypeForDispatch) + fb += wa.LocalTee(receiverLocalForDispatch) pushArgs(argsLocals) genTableDispatch(receiverClassInfo, t.method.name, receiverLocalForDispatch) - instrs += wa.Br(labelDone) + fb += wa.Br(labelDone) argsLocals } // end block labelNotOurObject @@ -781,7 +779,7 @@ private class FunctionEmitter private ( if (t.method.name == toStringMethodName) { // By spec, toString() is special assert(argsLocals.isEmpty) - instrs += wa.Call(genFunctionID.jsValueToString) + fb += wa.Call(genFunctionID.jsValueToString) } else if (receiverClassName == JLNumberClass) { // the value must be a `number`, hence we can unbox to `double` genUnbox(DoubleType) @@ -799,32 +797,32 @@ private class FunctionEmitter private ( assert(argsLocals.size == 1) val receiverLocal = addSyntheticLocal(watpe.RefType.any) - instrs += wa.LocalTee(receiverLocal) + fb += wa.LocalTee(receiverLocal) val jsValueTypeLocal = addSyntheticLocal(watpe.Int32) - instrs += wa.Call(genFunctionID.jsValueType) - instrs += wa.LocalTee(jsValueTypeLocal) + fb += wa.Call(genFunctionID.jsValueType) + fb += wa.LocalTee(jsValueTypeLocal) - instrs.switch(Sig(List(watpe.Int32), Nil), Sig(Nil, List(watpe.Int32))) { () => + fb.switch(Sig(List(watpe.Int32), Nil), Sig(Nil, List(watpe.Int32))) { () => // scrutinee is already on the stack }( // case JSValueTypeFalse | JSValueTypeTrue => List(JSValueTypeFalse, JSValueTypeTrue) -> { () => // the jsValueTypeLocal is the boolean value, thanks to the chosen encoding - instrs += wa.LocalGet(jsValueTypeLocal) + fb += wa.LocalGet(jsValueTypeLocal) pushArgs(argsLocals) genHijackedClassCall(BoxedBooleanClass) }, // case JSValueTypeString => List(JSValueTypeString) -> { () => - instrs += wa.LocalGet(receiverLocal) + fb += wa.LocalGet(receiverLocal) // no need to unbox for string pushArgs(argsLocals) genHijackedClassCall(BoxedStringClass) } ) { () => // case _ (JSValueTypeNumber) => - instrs += wa.LocalGet(receiverLocal) + fb += wa.LocalGet(receiverLocal) genUnbox(DoubleType) pushArgs(argsLocals) genHijackedClassCall(BoxedDoubleClass) @@ -840,9 +838,9 @@ private class FunctionEmitter private ( pushArgs(argsLocals) t.method.name match { case SpecialNames.hashCodeMethodName => - instrs += wa.Call(genFunctionID.identityHashCode) + fb += wa.Call(genFunctionID.identityHashCode) case `equalsMethodName` => - instrs += wa.Call(genFunctionID.is) + fb += wa.Call(genFunctionID.is) case _ => genHijackedClassCall(ObjectClass) } @@ -851,7 +849,7 @@ private class FunctionEmitter private ( } if (t.tpe == NothingType) - instrs += wa.Unreachable + fb += wa.Unreachable t.tpe } @@ -875,21 +873,21 @@ private class FunctionEmitter private ( def genITableDispatch(): Unit = { val itableIdx = ctx.getItableIdx(receiverClassInfo) - instrs += wa.LocalGet(receiverLocalForDispatch) - instrs += wa.StructGet( + fb += wa.LocalGet(receiverLocalForDispatch) + fb += wa.StructGet( // receiver type should be upcasted into `Object` if it's interface // by TypeTransformer#transformType genTypeID.forClass(ObjectClass), genFieldID.objStruct.itables ) - instrs += wa.I32Const(itableIdx) - instrs += wa.ArrayGet(genTypeID.itables) - instrs += wa.RefCast(watpe.RefType(genTypeID.forITable(receiverClassInfo.name))) - instrs += wa.StructGet( + fb += wa.I32Const(itableIdx) + fb += wa.ArrayGet(genTypeID.itables) + fb += wa.RefCast(watpe.RefType(genTypeID.forITable(receiverClassInfo.name))) + fb += wa.StructGet( genTypeID.forITable(receiverClassInfo.name), genFieldID.forMethodTableEntry(methodName) ) - instrs += wa.CallRef(ctx.tableFunctionType(methodName)) + fb += wa.CallRef(ctx.tableFunctionType(methodName)) } // Generates a vtable-based dispatch. @@ -902,17 +900,17 @@ private class FunctionEmitter private ( // struct.get $classType 0 ;; get vtable // struct.get $vtableType $methodIdx ;; get funcref // call.ref (type $funcType) ;; call funcref - instrs += wa.LocalGet(receiverLocalForDispatch) - instrs += wa.RefCast(watpe.RefType(genTypeID.forClass(receiverClassName))) - instrs += wa.StructGet( + fb += wa.LocalGet(receiverLocalForDispatch) + fb += wa.RefCast(watpe.RefType(genTypeID.forClass(receiverClassName))) + fb += wa.StructGet( genTypeID.forClass(receiverClassName), genFieldID.objStruct.vtable ) - instrs += wa.StructGet( + fb += wa.StructGet( genTypeID.forVTable(receiverClassName), genFieldID.forMethodTableEntry(methodName) ) - instrs += wa.CallRef(ctx.tableFunctionType(methodName)) + fb += wa.CallRef(ctx.tableFunctionType(methodName)) } if (receiverClassInfo.isInterface) @@ -930,7 +928,7 @@ private class FunctionEmitter private ( case NullType => genTree(t.receiver, NullType) - instrs += wa.Unreachable // trap + fb += wa.Unreachable // trap NothingType case _ => @@ -946,14 +944,14 @@ private class FunctionEmitter private ( BoxedClassToPrimType.get(targetClassName) match { case None => genTree(t.receiver, ClassType(targetClassName)) - instrs += wa.RefAsNotNull + fb += wa.RefAsNotNull case Some(primReceiverType) => if (t.receiver.tpe == primReceiverType) { genTreeAuto(t.receiver) } else { genTree(t.receiver, AnyType) - instrs += wa.RefAsNotNull + fb += wa.RefAsNotNull genUnbox(primReceiverType)(t.pos) } } @@ -961,9 +959,9 @@ private class FunctionEmitter private ( genArgs(t.args, t.method.name) val funcName = genFunctionID.forMethod(namespace, targetClassName, t.method.name) - instrs += wa.Call(funcName) + fb += wa.Call(funcName) if (t.tpe == NothingType) - instrs += wa.Unreachable + fb += wa.Unreachable t.tpe } } @@ -972,9 +970,9 @@ private class FunctionEmitter private ( genArgs(tree.args, tree.method.name) val namespace = MemberNamespace.forStaticCall(tree.flags) val funcName = genFunctionID.forMethod(namespace, tree.className, tree.method.name) - instrs += wa.Call(funcName) + fb += wa.Call(funcName) if (tree.tpe == NothingType) - instrs += wa.Unreachable + fb += wa.Unreachable tree.tpe } @@ -1004,22 +1002,22 @@ private class FunctionEmitter private ( markPosition(l) l match { - case BooleanLiteral(v) => instrs += wa.I32Const(if (v) 1 else 0) - case ByteLiteral(v) => instrs += wa.I32Const(v) - case ShortLiteral(v) => instrs += wa.I32Const(v) - case IntLiteral(v) => instrs += wa.I32Const(v) - case CharLiteral(v) => instrs += wa.I32Const(v) - case LongLiteral(v) => instrs += wa.I64Const(v) - case FloatLiteral(v) => instrs += wa.F32Const(v) - case DoubleLiteral(v) => instrs += wa.F64Const(v) + case BooleanLiteral(v) => fb += wa.I32Const(if (v) 1 else 0) + case ByteLiteral(v) => fb += wa.I32Const(v) + case ShortLiteral(v) => fb += wa.I32Const(v) + case IntLiteral(v) => fb += wa.I32Const(v) + case CharLiteral(v) => fb += wa.I32Const(v) + case LongLiteral(v) => fb += wa.I64Const(v) + case FloatLiteral(v) => fb += wa.F32Const(v) + case DoubleLiteral(v) => fb += wa.F64Const(v) case v: Undefined => - instrs += wa.GlobalGet(genGlobalID.undef) + fb += wa.GlobalGet(genGlobalID.undef) case v: Null => - instrs += wa.RefNull(watpe.HeapType.None) + fb += wa.RefNull(watpe.HeapType.None) case v: StringLiteral => - instrs ++= ctx.getConstantStringInstr(v.value) + fb ++= ctx.getConstantStringInstr(v.value) case v: ClassOf => v.typeRef match { @@ -1031,7 +1029,7 @@ private class FunctionEmitter private ( val typeDataLocal = addSyntheticLocal(typeDataType) genLoadArrayTypeData(typeRef) - instrs += wa.LocalSet(typeDataLocal) + fb += wa.LocalSet(typeDataLocal) genClassOfFromTypeData(wa.LocalGet(typeDataLocal)) } } @@ -1044,20 +1042,20 @@ private class FunctionEmitter private ( wa.GlobalGet(genGlobalID.forVTable(typeRef)) private def genLoadArrayTypeData(arrayTypeRef: ArrayTypeRef): Unit = { - instrs += getNonArrayTypeDataInstr(arrayTypeRef.base) - instrs += wa.I32Const(arrayTypeRef.dimensions) - instrs += wa.Call(genFunctionID.arrayTypeData) + fb += getNonArrayTypeDataInstr(arrayTypeRef.base) + fb += wa.I32Const(arrayTypeRef.dimensions) + fb += wa.Call(genFunctionID.arrayTypeData) } private def genClassOfFromTypeData(loadTypeDataInstr: wa.Instr): Unit = { - instrs.block(watpe.RefType(genTypeID.ClassStruct)) { nonNullLabel => + fb.block(watpe.RefType(genTypeID.ClassStruct)) { nonNullLabel => // fast path first - instrs += loadTypeDataInstr - instrs += wa.StructGet(genTypeID.typeData, genFieldID.typeData.classOfValue) - instrs += wa.BrOnNonNull(nonNullLabel) + fb += loadTypeDataInstr + fb += wa.StructGet(genTypeID.typeData, genFieldID.typeData.classOfValue) + fb += wa.BrOnNonNull(nonNullLabel) // slow path - instrs += loadTypeDataInstr - instrs += wa.Call(genFunctionID.createClassOf) + fb += loadTypeDataInstr + fb += wa.Call(genFunctionID.createClassOf) } } @@ -1075,9 +1073,9 @@ private class FunctionEmitter private ( * However we necessarily have a `null` receiver if we reach this point, * so we can trap as NPE. */ - instrs += wa.Unreachable + fb += wa.Unreachable } else { - instrs += wa.StructGet( + fb += wa.StructGet( genTypeID.forClass(className), genFieldID.forClassInstanceField(sel.field.name) ) @@ -1088,7 +1086,7 @@ private class FunctionEmitter private ( private def genSelectStatic(tree: SelectStatic): Type = { markPosition(tree) - instrs += wa.GlobalGet(genGlobalID.forStaticField(tree.field.name)) + fb += wa.GlobalGet(genGlobalID.forStaticField(tree.field.name)) tree.tpe } @@ -1100,7 +1098,7 @@ private class FunctionEmitter private ( genTreeAuto(This()(ClassType(className))(t.pos)) markPosition(t) - instrs += wa.GlobalSet(genGlobalID.forModuleInstance(className)) + fb += wa.GlobalSet(genGlobalID.forModuleInstance(className)) NoType } @@ -1110,7 +1108,7 @@ private class FunctionEmitter private ( */ private def genLoadModule(t: LoadModule): Type = { markPosition(t) - instrs += wa.Call(genFunctionID.loadModule(t.className)) + fb += wa.Call(genFunctionID.loadModule(t.className)) t.tpe } @@ -1123,47 +1121,47 @@ private class FunctionEmitter private ( (unary.op: @switch) match { case Boolean_! => - instrs += wa.I32Const(1) - instrs += wa.I32Xor + fb += wa.I32Const(1) + fb += wa.I32Xor // Widening conversions case CharToInt | ByteToInt | ShortToInt => () // these are no-ops because they are all represented as i32's with the right mathematical value case IntToLong => - instrs += wa.I64ExtendI32S + fb += wa.I64ExtendI32S case IntToDouble => - instrs += wa.F64ConvertI32S + fb += wa.F64ConvertI32S case FloatToDouble => - instrs += wa.F64PromoteF32 + fb += wa.F64PromoteF32 // Narrowing conversions case IntToChar => - instrs += wa.I32Const(0xFFFF) - instrs += wa.I32And + fb += wa.I32Const(0xFFFF) + fb += wa.I32And case IntToByte => - instrs += wa.I32Extend8S + fb += wa.I32Extend8S case IntToShort => - instrs += wa.I32Extend16S + fb += wa.I32Extend16S case LongToInt => - instrs += wa.I32WrapI64 + fb += wa.I32WrapI64 case DoubleToInt => - instrs += wa.I32TruncSatF64S + fb += wa.I32TruncSatF64S case DoubleToFloat => - instrs += wa.F32DemoteF64 + fb += wa.F32DemoteF64 // Long <-> Double (neither widening nor narrowing) case LongToDouble => - instrs += wa.F64ConvertI64S + fb += wa.F64ConvertI64S case DoubleToLong => - instrs += wa.I64TruncSatF64S + fb += wa.I64TruncSatF64S // Long -> Float (neither widening nor narrowing), introduced in 1.6 case LongToFloat => - instrs += wa.F32ConvertI64S + fb += wa.F32ConvertI64S // String.length, introduced in 1.11 case String_length => - instrs += wa.Call(genFunctionID.stringLength) + fb += wa.Call(genFunctionID.stringLength) } unary.tpe @@ -1174,8 +1172,8 @@ private class FunctionEmitter private ( genTree(binary.lhs, LongType) genTree(binary.rhs, IntType) markPosition(binary) - instrs += wa.I64ExtendI32S - instrs += shiftInstr + fb += wa.I64ExtendI32S + fb += shiftInstr LongType } @@ -1217,17 +1215,17 @@ private class FunctionEmitter private ( * We rewrite as `0 - lhs` so that we do not need any test. */ markPosition(binary) - instrs += const(num.zero) + fb += const(num.zero) genTree(binary.lhs, tpe) markPosition(binary) - instrs += sub + fb += sub tpe } else { genTree(binary.lhs, tpe) markPosition(binary.rhs) - instrs += const(rhsValue) + fb += const(rhsValue) markPosition(binary) - instrs += mainOp + fb += mainOp tpe } } @@ -1250,37 +1248,37 @@ private class FunctionEmitter private ( val lhsLocal = addSyntheticLocal(wasmTyp) val rhsLocal = addSyntheticLocal(wasmTyp) genTree(binary.lhs, tpe) - instrs += wa.LocalSet(lhsLocal) + fb += wa.LocalSet(lhsLocal) genTree(binary.rhs, tpe) - instrs += wa.LocalTee(rhsLocal) + fb += wa.LocalTee(rhsLocal) markPosition(binary) - instrs += eqz - instrs.ifThen() { + fb += eqz + fb.ifThen() { genThrowArithmeticException() } if (isDiv) { // Handle the MinValue / -1 corner case - instrs += wa.LocalGet(rhsLocal) - instrs += const(num.fromInt(-1)) - instrs += eq - instrs.ifThenElse(wasmTyp) { + fb += wa.LocalGet(rhsLocal) + fb += const(num.fromInt(-1)) + fb += eq + fb.ifThenElse(wasmTyp) { // 0 - lhs - instrs += const(num.zero) - instrs += wa.LocalGet(lhsLocal) - instrs += sub + fb += const(num.zero) + fb += wa.LocalGet(lhsLocal) + fb += sub } { // lhs / rhs - instrs += wa.LocalGet(lhsLocal) - instrs += wa.LocalGet(rhsLocal) - instrs += mainOp + fb += wa.LocalGet(lhsLocal) + fb += wa.LocalGet(rhsLocal) + fb += mainOp } } else { // lhs % rhs - instrs += wa.LocalGet(lhsLocal) - instrs += wa.LocalGet(rhsLocal) - instrs += mainOp + fb += wa.LocalGet(lhsLocal) + fb += wa.LocalGet(rhsLocal) + fb += mainOp } tpe @@ -1335,18 +1333,18 @@ private class FunctionEmitter private ( */ case BinaryOp.Float_% => genTree(binary.lhs, FloatType) - instrs += wa.F64PromoteF32 + fb += wa.F64PromoteF32 genTree(binary.rhs, FloatType) - instrs += wa.F64PromoteF32 + fb += wa.F64PromoteF32 markPosition(binary) - instrs += wa.Call(genFunctionID.fmod) - instrs += wa.F32DemoteF64 + fb += wa.Call(genFunctionID.fmod) + fb += wa.F32DemoteF64 FloatType case BinaryOp.Double_% => genTree(binary.lhs, DoubleType) genTree(binary.rhs, DoubleType) markPosition(binary) - instrs += wa.Call(genFunctionID.fmod) + fb += wa.Call(genFunctionID.fmod) DoubleType // New in 1.11 @@ -1354,7 +1352,7 @@ private class FunctionEmitter private ( genTree(binary.lhs, StringType) // push the string genTree(binary.rhs, IntType) // push the index markPosition(binary) - instrs += wa.Call(genFunctionID.stringCharAt) + fb += wa.Call(genFunctionID.stringCharAt) CharType case _ => genElementaryBinaryOp(binary) @@ -1368,11 +1366,11 @@ private class FunctionEmitter private ( markPosition(binary) - instrs += wa.Call(genFunctionID.is) + fb += wa.Call(genFunctionID.is) if (binary.op == BinaryOp.!==) { - instrs += wa.I32Const(1) - instrs += wa.I32Xor + fb += wa.I32Const(1) + fb += wa.I32Xor } BooleanType @@ -1441,7 +1439,7 @@ private class FunctionEmitter private ( case BinaryOp.Double_> => wa.F64Gt case BinaryOp.Double_>= => wa.F64Ge } - instrs += operation + fb += operation binary.tpe } @@ -1480,17 +1478,17 @@ private class FunctionEmitter private ( * end $done */ - instrs.block(watpe.RefType.any) { labelDone => - instrs.block() { labelIsNull => + fb.block(watpe.RefType.any) { labelDone => + fb.block() { labelIsNull => genTreeAuto(tree) markPosition(binary) - instrs += wa.BrOnNull(labelIsNull) - instrs += wa.LocalTee(receiverLocalForDispatch) + fb += wa.BrOnNull(labelIsNull) + fb += wa.LocalTee(receiverLocalForDispatch) genTableDispatch(objectClassInfo, toStringMethodName, receiverLocalForDispatch) - instrs += wa.BrOnNonNull(labelDone) + fb += wa.BrOnNonNull(labelDone) } - instrs ++= ctx.getConstantStringInstr("null") + fb ++= ctx.getConstantStringInstr("null") } } else { /* Dispatch where the receiver can be a JS value. @@ -1509,27 +1507,27 @@ private class FunctionEmitter private ( * end $done */ - instrs.block(watpe.RefType.any) { labelDone => + fb.block(watpe.RefType.any) { labelDone => // First try the case where the value is one of our objects - instrs.block(watpe.RefType.anyref) { labelNotOurObject => + fb.block(watpe.RefType.anyref) { labelNotOurObject => // Load receiver genTreeAuto(tree) markPosition(binary) - instrs += wa.BrOnCastFail( + fb += wa.BrOnCastFail( labelNotOurObject, watpe.RefType.anyref, watpe.RefType(genTypeID.ObjectStruct) ) - instrs += wa.LocalTee(receiverLocalForDispatch) + fb += wa.LocalTee(receiverLocalForDispatch) genTableDispatch(objectClassInfo, toStringMethodName, receiverLocalForDispatch) - instrs += wa.BrOnNonNull(labelDone) - instrs += wa.RefNull(watpe.HeapType.Any) + fb += wa.BrOnNonNull(labelDone) + fb += wa.RefNull(watpe.HeapType.Any) } // end block labelNotOurObject // Now we have a value that is not one of our objects; the anyref is still on the stack - instrs += wa.Call(genFunctionID.jsValueToStringForConcat) + fb += wa.Call(genFunctionID.jsValueToStringForConcat) } // end block labelDone } } @@ -1544,20 +1542,20 @@ private class FunctionEmitter private ( case StringType => () // no-op case BooleanType => - instrs += wa.Call(genFunctionID.booleanToString) + fb += wa.Call(genFunctionID.booleanToString) case CharType => - instrs += wa.Call(genFunctionID.charToString) + fb += wa.Call(genFunctionID.charToString) case ByteType | ShortType | IntType => - instrs += wa.Call(genFunctionID.intToString) + fb += wa.Call(genFunctionID.intToString) case LongType => - instrs += wa.Call(genFunctionID.longToString) + fb += wa.Call(genFunctionID.longToString) case FloatType => - instrs += wa.F64PromoteF32 - instrs += wa.Call(genFunctionID.doubleToString) + fb += wa.F64PromoteF32 + fb += wa.Call(genFunctionID.doubleToString) case DoubleType => - instrs += wa.Call(genFunctionID.doubleToString) + fb += wa.Call(genFunctionID.doubleToString) case NullType | UndefType => - instrs += wa.Call(genFunctionID.jsValueToStringForConcat) + fb += wa.Call(genFunctionID.jsValueToStringForConcat) case NothingType => () // unreachable case NoType => @@ -1570,7 +1568,7 @@ private class FunctionEmitter private ( // Common case for which we want to avoid the hijacked class dispatch genTreeAuto(tree) markPosition(binary) - instrs += wa.Call(genFunctionID.jsValueToStringForConcat) // for `null` + fb += wa.Call(genFunctionID.jsValueToStringForConcat) // for `null` case ClassType(className) => genWithDispatch(ctx.getClassInfo(className).isAncestorOfHijackedClass) @@ -1595,7 +1593,7 @@ private class FunctionEmitter private ( genToString(binary.lhs) genToString(binary.rhs) markPosition(binary) - instrs += wa.Call(genFunctionID.stringConcat) + fb += wa.Call(genFunctionID.stringConcat) } StringType @@ -1609,18 +1607,18 @@ private class FunctionEmitter private ( def genIsPrimType(testType: PrimType): Unit = { testType match { case UndefType => - instrs += wa.Call(genFunctionID.isUndef) + fb += wa.Call(genFunctionID.isUndef) case StringType => - instrs += wa.Call(genFunctionID.isString) + fb += wa.Call(genFunctionID.isString) case testType: PrimTypeWithRef => testType match { case CharType => val structTypeName = genTypeID.forClass(SpecialNames.CharBoxClass) - instrs += wa.RefTest(watpe.RefType(structTypeName)) + fb += wa.RefTest(watpe.RefType(structTypeName)) case LongType => val structTypeName = genTypeID.forClass(SpecialNames.LongBoxClass) - instrs += wa.RefTest(watpe.RefType(structTypeName)) + fb += wa.RefTest(watpe.RefType(structTypeName)) case NoType | NothingType | NullType => throw new AssertionError(s"Illegal isInstanceOf[$testType]") case _ => @@ -1629,7 +1627,7 @@ private class FunctionEmitter private ( * https://www.scala-js.org/doc/semantics.html * All the `tX` helpers have Wasm type `anyref -> i32` (interpreted as `boolean`). */ - instrs += wa.Call(genFunctionID.typeTest(testType.primRef)) + fb += wa.Call(genFunctionID.typeTest(testType.primRef)) } } } @@ -1639,22 +1637,22 @@ private class FunctionEmitter private ( genIsPrimType(testType) case AnyType | ClassType(ObjectClass) => - instrs += wa.RefIsNull - instrs += wa.I32Const(1) - instrs += wa.I32Xor + fb += wa.RefIsNull + fb += wa.I32Const(1) + fb += wa.I32Xor case ClassType(JLNumberClass) => /* Special case: the only non-Object *class* that is an ancestor of a * hijacked class. We need to accept `number` primitives here. */ val tempLocal = addSyntheticLocal(watpe.RefType.anyref) - instrs += wa.LocalTee(tempLocal) - instrs += wa.RefTest(watpe.RefType(genTypeID.forClass(JLNumberClass))) - instrs.ifThenElse(watpe.Int32) { - instrs += wa.I32Const(1) + fb += wa.LocalTee(tempLocal) + fb += wa.RefTest(watpe.RefType(genTypeID.forClass(JLNumberClass))) + fb.ifThenElse(watpe.Int32) { + fb += wa.I32Const(1) } { - instrs += wa.LocalGet(tempLocal) - instrs += wa.Call(genFunctionID.typeTest(DoubleRef)) + fb += wa.LocalGet(tempLocal) + fb += wa.Call(genFunctionID.typeTest(DoubleRef)) } case ClassType(testClassName) => @@ -1665,9 +1663,9 @@ private class FunctionEmitter private ( val info = ctx.getClassInfo(testClassName) if (info.isInterface) - instrs += wa.Call(genFunctionID.instanceTest(testClassName)) + fb += wa.Call(genFunctionID.instanceTest(testClassName)) else - instrs += wa.RefTest(watpe.RefType(genTypeID.forClass(testClassName))) + fb += wa.RefTest(watpe.RefType(genTypeID.forClass(testClassName))) } case ArrayType(arrayTypeRef) => @@ -1678,7 +1676,7 @@ private class FunctionEmitter private ( ) => // For primitive arrays and exactly Array[Object], a wa.REF_TEST is enough val structTypeName = genTypeID.forArrayClass(arrayTypeRef) - instrs += wa.RefTest(watpe.RefType(structTypeName)) + fb += wa.RefTest(watpe.RefType(structTypeName)) case _ => /* Non-Object reference arra types need a sophisticated type test @@ -1686,11 +1684,11 @@ private class FunctionEmitter private ( */ import watpe.RefType.anyref - instrs.block(Sig(List(anyref), List(watpe.Int32))) { doneLabel => - instrs.block(Sig(List(anyref), List(anyref))) { notARefArrayLabel => + fb.block(Sig(List(anyref), List(watpe.Int32))) { doneLabel => + fb.block(Sig(List(anyref), List(anyref))) { notARefArrayLabel => // Try and cast to the generic representation first val refArrayStructTypeName = genTypeID.forArrayClass(arrayTypeRef) - instrs += wa.BrOnCastFail( + fb += wa.BrOnCastFail( notARefArrayLabel, watpe.RefType.anyref, watpe.RefType(refArrayStructTypeName) @@ -1699,23 +1697,23 @@ private class FunctionEmitter private ( // refArrayValue := the generic representation val refArrayValueLocal = addSyntheticLocal(watpe.RefType(refArrayStructTypeName)) - instrs += wa.LocalSet(refArrayValueLocal) + fb += wa.LocalSet(refArrayValueLocal) // Load typeDataOf(arrayTypeRef) genLoadArrayTypeData(arrayTypeRef) // Load refArrayValue.vtable - instrs += wa.LocalGet(refArrayValueLocal) - instrs += wa.StructGet(refArrayStructTypeName, genFieldID.objStruct.vtable) + fb += wa.LocalGet(refArrayValueLocal) + fb += wa.StructGet(refArrayStructTypeName, genFieldID.objStruct.vtable) // Call isAssignableFrom and return its result - instrs += wa.Call(genFunctionID.isAssignableFrom) - instrs += wa.Br(doneLabel) + fb += wa.Call(genFunctionID.isAssignableFrom) + fb += wa.Br(doneLabel) } // Here, the value is not a reference array type, so return false - instrs += wa.Drop - instrs += wa.I32Const(0) + fb += wa.Drop + fb += wa.I32Const(0) } } @@ -1763,7 +1761,7 @@ private class FunctionEmitter private ( case watpe.RefType(true, watpe.HeapType.Any) => () // nothing to do case targetWasmType: watpe.RefType => - instrs += wa.RefCast(targetWasmType) + fb += wa.RefCast(targetWasmType) case _ => throw new AssertionError(s"Unexpected type in AsInstanceOf: $targetTpe") } @@ -1783,10 +1781,10 @@ private class FunctionEmitter private ( private def genUnbox(targetTpe: PrimType)(implicit pos: Position): Unit = { targetTpe match { case UndefType => - instrs += wa.Drop - instrs += wa.GlobalGet(genGlobalID.undef) + fb += wa.Drop + fb += wa.GlobalGet(genGlobalID.undef) case StringType => - instrs += wa.RefAsNotNull + fb += wa.RefAsNotNull case targetTpe: PrimTypeWithRef => targetTpe match { @@ -1799,16 +1797,16 @@ private class FunctionEmitter private ( val fieldName = FieldName(boxClass, SpecialNames.valueFieldSimpleName) val resultType = transformType(targetTpe) - instrs.block(Sig(List(watpe.RefType.anyref), List(resultType))) { doneLabel => - instrs.block(Sig(List(watpe.RefType.anyref), Nil)) { isNullLabel => - instrs += wa.BrOnNull(isNullLabel) + fb.block(Sig(List(watpe.RefType.anyref), List(resultType))) { doneLabel => + fb.block(Sig(List(watpe.RefType.anyref), Nil)) { isNullLabel => + fb += wa.BrOnNull(isNullLabel) val structTypeName = genTypeID.forClass(boxClass) - instrs += wa.RefCast(watpe.RefType(structTypeName)) - instrs += wa.StructGet( + fb += wa.RefCast(watpe.RefType(structTypeName)) + fb += wa.StructGet( structTypeName, genFieldID.forClassInstanceField(fieldName) ) - instrs += wa.Br(doneLabel) + fb += wa.Br(doneLabel) } genTree(zeroOf(targetTpe), targetTpe) } @@ -1816,7 +1814,7 @@ private class FunctionEmitter private ( case NothingType | NullType | NoType => throw new IllegalArgumentException(s"Illegal type in genUnbox: $targetTpe") case _ => - instrs += wa.Call(genFunctionID.unbox(targetTpe.primRef)) + fb += wa.Call(genFunctionID.unbox(targetTpe.primRef)) } } } @@ -1844,14 +1842,14 @@ private class FunctionEmitter private ( genTreeAuto(tree.expr) markPosition(tree) - instrs += wa.StructGet(objectTypeIdx, genFieldID.objStruct.vtable) // implicit trap on null - instrs += wa.LocalSet(typeDataLocal) + fb += wa.StructGet(objectTypeIdx, genFieldID.objStruct.vtable) // implicit trap on null + fb += wa.LocalSet(typeDataLocal) genClassOfFromTypeData(wa.LocalGet(typeDataLocal)) } else { genTree(tree.expr, AnyType) markPosition(tree) - instrs += wa.RefAsNotNull - instrs += wa.Call(genFunctionID.anyGetClass) + fb += wa.RefAsNotNull + fb += wa.Call(genFunctionID.anyGetClass) } tree.tpe @@ -1860,10 +1858,10 @@ private class FunctionEmitter private ( private def genReadStorage(storage: VarStorage): Unit = { storage match { case VarStorage.Local(localIdx) => - instrs += wa.LocalGet(localIdx) + fb += wa.LocalGet(localIdx) case VarStorage.StructField(structLocalIdx, structTypeName, fieldIdx) => - instrs += wa.LocalGet(structLocalIdx) - instrs += wa.StructGet(structTypeName, fieldIdx) + fb += wa.LocalGet(structLocalIdx) + fb += wa.StructGet(structTypeName, fieldIdx) } } @@ -1908,11 +1906,11 @@ private class FunctionEmitter private ( t.elsep match { case Skip() => assert(expectedType == NoType) - instrs.ifThen() { + fb.ifThen() { genTree(t.thenp, expectedType) } case _ => - instrs.ifThenElse(ty) { + fb.ifThenElse(ty) { genTree(t.thenp, expectedType) } { genTree(t.elsep, expectedType) @@ -1920,7 +1918,7 @@ private class FunctionEmitter private ( } if (expectedType == NothingType) - instrs += wa.Unreachable + fb += wa.Unreachable expectedType } @@ -1935,12 +1933,12 @@ private class FunctionEmitter private ( // end // unreachable markPosition(t) - instrs.loop() { label => + fb.loop() { label => genTree(t.body, NoType) markPosition(t) - instrs += wa.Br(label) + fb += wa.Br(label) } - instrs += wa.Unreachable + fb += wa.Unreachable NothingType case _ => @@ -1952,13 +1950,13 @@ private class FunctionEmitter private ( // end // end markPosition(t) - instrs.loop() { label => + fb.loop() { label => genTree(t.cond, BooleanType) markPosition(t) - instrs.ifThen() { + fb.ifThen() { genTree(t.body, NoType) markPosition(t) - instrs += wa.Br(label) + fb += wa.Br(label) } } NoType @@ -1988,7 +1986,7 @@ private class FunctionEmitter private ( genTree(t.obj, AnyType) genTree(fVarRef, AnyType) markPosition(t) - instrs += wa.Call(genFunctionID.jsForInSimple) + fb += wa.Call(genFunctionID.jsForInSimple) case _ => throw new NotImplementedError(s"Unsupported shape of ForIn node at ${t.pos}: $t") @@ -2002,44 +2000,44 @@ private class FunctionEmitter private ( if (UseLegacyExceptionsForTryCatch) { markPosition(t) - instrs += wa.Try(instrs.sigToBlockType(Sig(Nil, resultType))) + fb += wa.Try(fb.sigToBlockType(Sig(Nil, resultType))) genTree(t.block, expectedType) markPosition(t) - instrs += wa.Catch(genTagID.exception) + fb += wa.Catch(genTagID.exception) withNewLocal(t.errVar.name, t.errVarOriginalName, watpe.RefType.anyref) { exceptionLocal => - instrs += wa.AnyConvertExtern - instrs += wa.LocalSet(exceptionLocal) + fb += wa.AnyConvertExtern + fb += wa.LocalSet(exceptionLocal) genTree(t.handler, expectedType) } - instrs += wa.End + fb += wa.End } else { markPosition(t) - instrs.block(resultType) { doneLabel => - instrs.block(watpe.RefType.externref) { catchLabel => + fb.block(resultType) { doneLabel => + fb.block(watpe.RefType.externref) { catchLabel => /* We used to have `resultType` as result of the try_table, with the * `wa.BR(doneLabel)` outside of the try_table. Unfortunately it seems * V8 cannot handle try_table with a result type that is `(ref ...)`. * The current encoding with `externref` as result type (to match the * enclosing block) and the `br` *inside* the `try_table` works. */ - instrs.tryTable(watpe.RefType.externref)( + fb.tryTable(watpe.RefType.externref)( List(wa.CatchClause.Catch(genTagID.exception, catchLabel)) ) { genTree(t.block, expectedType) markPosition(t) - instrs += wa.Br(doneLabel) + fb += wa.Br(doneLabel) } } // end block $catch withNewLocal(t.errVar.name, t.errVarOriginalName, watpe.RefType.anyref) { exceptionLocal => - instrs += wa.AnyConvertExtern - instrs += wa.LocalSet(exceptionLocal) + fb += wa.AnyConvertExtern + fb += wa.LocalSet(exceptionLocal) genTree(t.handler, expectedType) } } // end block $done } if (expectedType == NothingType) - instrs += wa.Unreachable + fb += wa.Unreachable expectedType } @@ -2047,8 +2045,8 @@ private class FunctionEmitter private ( private def genThrow(tree: Throw): Type = { genTree(tree.expr, AnyType) markPosition(tree) - instrs += wa.ExternConvertAny - instrs += wa.Throw(genTagID.exception) + fb += wa.ExternConvertAny + fb += wa.Throw(genTagID.exception) NothingType } @@ -2066,7 +2064,7 @@ private class FunctionEmitter private ( genTree(rhs, vtpe) markPosition(stat) withNewLocal(name.name, originalName, transformType(vtpe)) { local => - instrs += wa.LocalSet(local) + fb += wa.LocalSet(local) genBlockStats(rest)(inner) } case stat :: rest => @@ -2086,21 +2084,21 @@ private class FunctionEmitter private ( val localInstance = addSyntheticLocal(instanceTyp) markPosition(n) - instrs += wa.Call(genFunctionID.newDefault(n.className)) - instrs += wa.LocalTee(localInstance) + fb += wa.Call(genFunctionID.newDefault(n.className)) + fb += wa.LocalTee(localInstance) genArgs(n.args, n.ctor.name) markPosition(n) - instrs += wa.Call( + fb += wa.Call( genFunctionID.forMethod( MemberNamespace.Constructor, n.className, n.ctor.name ) ) - instrs += wa.LocalGet(localInstance) + fb += wa.LocalGet(localInstance) n.tpe } @@ -2118,11 +2116,11 @@ private class FunctionEmitter private ( * what the constructor would do anyway (so we're basically inlining it). */ - instrs += wa.LocalSet(primLocal) - instrs += wa.GlobalGet(genGlobalID.forVTable(boxClassName)) - instrs += wa.GlobalGet(genGlobalID.forITable(boxClassName)) - instrs += wa.LocalGet(primLocal) - instrs += wa.StructNew(genTypeID.forClass(boxClassName)) + fb += wa.LocalSet(primLocal) + fb += wa.GlobalGet(genGlobalID.forVTable(boxClassName)) + fb += wa.GlobalGet(genGlobalID.forITable(boxClassName)) + fb += wa.LocalGet(primLocal) + fb += wa.StructNew(genTypeID.forClass(boxClassName)) ClassType(boxClassName) } @@ -2132,7 +2130,7 @@ private class FunctionEmitter private ( genTree(tree.expr, AnyType) markPosition(tree) - instrs += wa.Call(genFunctionID.identityHashCode) + fb += wa.Call(genFunctionID.identityHashCode) IntType } @@ -2144,13 +2142,13 @@ private class FunctionEmitter private ( val jsExceptionTyp = transformClassType(SpecialNames.JSExceptionClass).toNonNullable - instrs.block(nonNullThrowableTyp) { doneLabel => + fb.block(nonNullThrowableTyp) { doneLabel => genTree(tree.expr, AnyType) markPosition(tree) // if expr.isInstanceOf[Throwable], then br $done - instrs += wa.BrOnCast( + fb += wa.BrOnCast( doneLabel, watpe.RefType.anyref, nonNullThrowableTyp @@ -2161,40 +2159,40 @@ private class FunctionEmitter private ( val exprLocal = addSyntheticLocal(watpe.RefType.anyref) val instanceLocal = addSyntheticLocal(jsExceptionTyp) - instrs += wa.LocalSet(exprLocal) - instrs += wa.Call(genFunctionID.newDefault(SpecialNames.JSExceptionClass)) - instrs += wa.LocalTee(instanceLocal) - instrs += wa.LocalGet(exprLocal) - instrs += wa.Call( + fb += wa.LocalSet(exprLocal) + fb += wa.Call(genFunctionID.newDefault(SpecialNames.JSExceptionClass)) + fb += wa.LocalTee(instanceLocal) + fb += wa.LocalGet(exprLocal) + fb += wa.Call( genFunctionID.forMethod( MemberNamespace.Constructor, SpecialNames.JSExceptionClass, SpecialNames.JSExceptionCtor ) ) - instrs += wa.LocalGet(instanceLocal) + fb += wa.LocalGet(instanceLocal) } throwableClassType } private def genUnwrapFromThrowable(tree: UnwrapFromThrowable): Type = { - instrs.block(watpe.RefType.anyref) { doneLabel => + fb.block(watpe.RefType.anyref) { doneLabel => genTree(tree.expr, ClassType(ThrowableClass)) markPosition(tree) - instrs += wa.RefAsNotNull + fb += wa.RefAsNotNull // if !expr.isInstanceOf[js.JavaScriptException], then br $done - instrs += wa.BrOnCastFail( + fb += wa.BrOnCastFail( doneLabel, watpe.RefType(genTypeID.ThrowableStruct), watpe.RefType(genTypeID.JSExceptionStruct) ) // otherwise, unwrap the JavaScriptException by reading its field - instrs += wa.StructGet( + fb += wa.StructGet( genTypeID.forClass(SpecialNames.JSExceptionClass), genFieldID.forClassInstanceField(SpecialNames.JSExceptionField) ) @@ -2207,7 +2205,7 @@ private class FunctionEmitter private ( genTree(tree.ctor, AnyType) genJSArgsArray(tree.args) markPosition(tree) - instrs += wa.Call(genFunctionID.jsNew) + fb += wa.Call(genFunctionID.jsNew) AnyType } @@ -2215,7 +2213,7 @@ private class FunctionEmitter private ( genTree(tree.qualifier, AnyType) genTree(tree.item, AnyType) markPosition(tree) - instrs += wa.Call(genFunctionID.jsSelect) + fb += wa.Call(genFunctionID.jsSelect) AnyType } @@ -2223,7 +2221,7 @@ private class FunctionEmitter private ( genTree(tree.fun, AnyType) genJSArgsArray(tree.args) markPosition(tree) - instrs += wa.Call(genFunctionID.jsFunctionApply) + fb += wa.Call(genFunctionID.jsFunctionApply) AnyType } @@ -2232,26 +2230,26 @@ private class FunctionEmitter private ( genTree(tree.method, AnyType) genJSArgsArray(tree.args) markPosition(tree) - instrs += wa.Call(genFunctionID.jsMethodApply) + fb += wa.Call(genFunctionID.jsMethodApply) AnyType } private def genJSImportCall(tree: JSImportCall): Type = { genTree(tree.arg, AnyType) markPosition(tree) - instrs += wa.Call(genFunctionID.jsImportCall) + fb += wa.Call(genFunctionID.jsImportCall) AnyType } private def genJSImportMeta(tree: JSImportMeta): Type = { markPosition(tree) - instrs += wa.Call(genFunctionID.jsImportMeta) + fb += wa.Call(genFunctionID.jsImportMeta) AnyType } private def genLoadJSConstructor(tree: LoadJSConstructor): Type = { markPosition(tree) - SWasmGen.genLoadJSConstructor(instrs, tree.className) + SWasmGen.genLoadJSConstructor(fb, tree.className) AnyType } @@ -2260,10 +2258,10 @@ private class FunctionEmitter private ( ctx.getClassInfo(tree.className).jsNativeLoadSpec match { case Some(loadSpec) => - genLoadJSFromSpec(instrs, loadSpec) + genLoadJSFromSpec(fb, loadSpec) case None => // This is a non-native JS module - instrs += wa.Call(genFunctionID.loadModule(tree.className)) + fb += wa.Call(genFunctionID.loadModule(tree.className)) } AnyType @@ -2276,7 +2274,7 @@ private class FunctionEmitter private ( throw new AssertionError(s"Found $tree for non-existing JS native member at ${tree.pos}") } ) - genLoadJSFromSpec(instrs, jsNativeLoadSpec) + genLoadJSFromSpec(fb, jsNativeLoadSpec) AnyType } @@ -2284,14 +2282,14 @@ private class FunctionEmitter private ( genTree(tree.qualifier, AnyType) genTree(tree.item, AnyType) markPosition(tree) - instrs += wa.Call(genFunctionID.jsDelete) + fb += wa.Call(genFunctionID.jsDelete) NoType } private def genJSUnaryOp(tree: JSUnaryOp): Type = { genTree(tree.lhs, AnyType) markPosition(tree) - instrs += wa.Call(genFunctionID.jsUnaryOps(tree.op)) + fb += wa.Call(genFunctionID.jsUnaryOps(tree.op)) AnyType } @@ -2304,27 +2302,27 @@ private class FunctionEmitter private ( val lhsLocal = addSyntheticLocal(watpe.RefType.anyref) genTree(tree.lhs, AnyType) markPosition(tree) - instrs += wa.LocalTee(lhsLocal) - instrs += wa.Call(genFunctionID.jsIsTruthy) - instrs += wa.If(wa.BlockType.ValueType(watpe.RefType.anyref)) + fb += wa.LocalTee(lhsLocal) + fb += wa.Call(genFunctionID.jsIsTruthy) + fb += wa.If(wa.BlockType.ValueType(watpe.RefType.anyref)) if (tree.op == JSBinaryOp.||) { - instrs += wa.LocalGet(lhsLocal) - instrs += wa.Else + fb += wa.LocalGet(lhsLocal) + fb += wa.Else genTree(tree.rhs, AnyType) markPosition(tree) } else { genTree(tree.rhs, AnyType) markPosition(tree) - instrs += wa.Else - instrs += wa.LocalGet(lhsLocal) + fb += wa.Else + fb += wa.LocalGet(lhsLocal) } - instrs += wa.End + fb += wa.End case _ => genTree(tree.lhs, AnyType) genTree(tree.rhs, AnyType) markPosition(tree) - instrs += wa.Call(genFunctionID.jsBinaryOps(tree.op)) + fb += wa.Call(genFunctionID.jsBinaryOps(tree.op)) } tree.tpe @@ -2337,46 +2335,46 @@ private class FunctionEmitter private ( private def genJSObjectConstr(tree: JSObjectConstr): Type = { markPosition(tree) - instrs += wa.Call(genFunctionID.jsNewObject) + fb += wa.Call(genFunctionID.jsNewObject) for ((prop, value) <- tree.fields) { genTree(prop, AnyType) genTree(value, AnyType) - instrs += wa.Call(genFunctionID.jsObjectPush) + fb += wa.Call(genFunctionID.jsObjectPush) } AnyType } private def genJSGlobalRef(tree: JSGlobalRef): Type = { markPosition(tree) - instrs ++= ctx.getConstantStringInstr(tree.name) - instrs += wa.Call(genFunctionID.jsGlobalRefGet) + fb ++= ctx.getConstantStringInstr(tree.name) + fb += wa.Call(genFunctionID.jsGlobalRefGet) AnyType } private def genJSTypeOfGlobalRef(tree: JSTypeOfGlobalRef): Type = { markPosition(tree) - instrs ++= ctx.getConstantStringInstr(tree.globalRef.name) - instrs += wa.Call(genFunctionID.jsGlobalRefTypeof) + fb ++= ctx.getConstantStringInstr(tree.globalRef.name) + fb += wa.Call(genFunctionID.jsGlobalRefTypeof) AnyType } private def genJSArgsArray(args: List[TreeOrJSSpread]): Unit = { - instrs += wa.Call(genFunctionID.jsNewArray) + fb += wa.Call(genFunctionID.jsNewArray) for (arg <- args) { arg match { case arg: Tree => genTree(arg, AnyType) - instrs += wa.Call(genFunctionID.jsArrayPush) + fb += wa.Call(genFunctionID.jsArrayPush) case JSSpread(items) => genTree(items, AnyType) - instrs += wa.Call(genFunctionID.jsArraySpreadPush) + fb += wa.Call(genFunctionID.jsArraySpreadPush) } } } private def genJSLinkingInfo(tree: JSLinkingInfo): Type = { markPosition(tree) - instrs += wa.Call(genFunctionID.jsLinkingInfo) + fb += wa.Call(genFunctionID.jsLinkingInfo) AnyType } @@ -2391,19 +2389,19 @@ private class FunctionEmitter private ( t.array.tpe match { case ArrayType(arrayTypeRef) => // Get the underlying array; implicit trap on null - instrs += wa.StructGet( + fb += wa.StructGet( genTypeID.forArrayClass(arrayTypeRef), genFieldID.objStruct.arrayUnderlying ) // Get the length - instrs += wa.ArrayLen + fb += wa.ArrayLen IntType case NothingType => // unreachable NothingType case NullType => - instrs += wa.Unreachable + fb += wa.Unreachable NothingType case _ => throw new IllegalArgumentException( @@ -2430,10 +2428,10 @@ private class FunctionEmitter private ( markPosition(t) val underlyingArrayType = genTypeID.underlyingOf(arrayTypeRef) - instrs += wa.ArrayNewDefault(underlyingArrayType) + fb += wa.ArrayNewDefault(underlyingArrayType) // Create the array object - instrs += wa.StructNew(genTypeID.forArrayClass(arrayTypeRef)) + fb += wa.StructNew(genTypeID.forArrayClass(arrayTypeRef)) } else { /* There is no Scala source code that produces `NewArray` with more than * one specified dimension, so this branch is not tested. @@ -2448,12 +2446,12 @@ private class FunctionEmitter private ( for (length <- t.lengths) genTree(length, IntType) markPosition(t) - instrs += wa.ArrayNewFixed(genTypeID.i32Array, t.lengths.size) + fb += wa.ArrayNewFixed(genTypeID.i32Array, t.lengths.size) // Third arg: constant 0 (start index inside the array of lengths) - instrs += wa.I32Const(0) + fb += wa.I32Const(0) - instrs += wa.Call(genFunctionID.newArrayObject) + fb += wa.Call(genFunctionID.newArrayObject) } t.tpe @@ -2465,7 +2463,7 @@ private class FunctionEmitter private ( genLoadArrayTypeData(arrayTypeRef) // Load the itables for the array type - instrs += wa.GlobalGet(genGlobalID.arrayClassITable) + fb += wa.GlobalGet(genGlobalID.arrayClassITable) } /** For getting element from an array, array.set should be generated by transformation of @@ -2479,7 +2477,7 @@ private class FunctionEmitter private ( t.array.tpe match { case ArrayType(arrayTypeRef) => // Get the underlying array; implicit trap on null - instrs += wa.StructGet( + fb += wa.StructGet( genTypeID.forArrayClass(arrayTypeRef), genFieldID.objStruct.arrayUnderlying ) @@ -2493,11 +2491,11 @@ private class FunctionEmitter private ( val typeIdx = genTypeID.underlyingOf(arrayTypeRef) arrayTypeRef match { case ArrayTypeRef(BooleanRef | CharRef, 1) => - instrs += wa.ArrayGetU(typeIdx) + fb += wa.ArrayGetU(typeIdx) case ArrayTypeRef(ByteRef | ShortRef, 1) => - instrs += wa.ArrayGetS(typeIdx) + fb += wa.ArrayGetS(typeIdx) case _ => - instrs += wa.ArrayGet(typeIdx) + fb += wa.ArrayGet(typeIdx) } /* If it is a reference array type whose element type does not translate @@ -2513,7 +2511,7 @@ private class FunctionEmitter private ( // nothing to do () case refType: watpe.RefType => - instrs += wa.RefCast(refType) + fb += wa.RefCast(refType) case typ => throw new AssertionError(s"Unexpected result type for reference array: $typ") } @@ -2525,7 +2523,7 @@ private class FunctionEmitter private ( // unreachable NothingType case NullType => - instrs += wa.Unreachable + fb += wa.Unreachable NothingType case _ => throw new IllegalArgumentException( @@ -2550,10 +2548,10 @@ private class FunctionEmitter private ( t.elems.foreach(genTree(_, expectedElemType)) markPosition(t) val underlyingArrayType = genTypeID.underlyingOf(arrayTypeRef) - instrs += wa.ArrayNewFixed(underlyingArrayType, t.elems.size) + fb += wa.ArrayNewFixed(underlyingArrayType, t.elems.size) // Create the array object - instrs += wa.StructNew(genTypeID.forArrayClass(arrayTypeRef)) + fb += wa.StructNew(genTypeID.forArrayClass(arrayTypeRef)) t.tpe } @@ -2584,19 +2582,19 @@ private class FunctionEmitter private ( markPosition(tree) // Put a reference to the function on the stack - instrs += ctx.refFuncWithDeclaration(closureFuncID) + fb += ctx.refFuncWithDeclaration(closureFuncID) // Evaluate the capture values and instantiate the capture data struct for ((param, value) <- tree.captureParams.zip(tree.captureValues)) genTree(value, param.ptpe) markPosition(tree) - instrs += wa.StructNew(dataStructTypeName) + fb += wa.StructNew(dataStructTypeName) /* If there is a ...rest param, the helper requires as third argument the * number of regular arguments. */ if (hasRestParam) - instrs += wa.I32Const(tree.params.size) + fb += wa.I32Const(tree.params.size) // Call the appropriate helper val helper = (hasThis, hasRestParam) match { @@ -2605,7 +2603,7 @@ private class FunctionEmitter private ( case (false, true) => genFunctionID.closureRest case (true, true) => genFunctionID.closureThisRest } - instrs += wa.Call(helper) + fb += wa.Call(helper) AnyType } @@ -2617,21 +2615,21 @@ private class FunctionEmitter private ( markPosition(t) - instrs += wa.RefCast(watpe.RefType(genTypeID.ObjectStruct)) - instrs += wa.LocalTee(expr) - instrs += wa.RefAsNotNull // cloneFunction argument is not nullable + fb += wa.RefCast(watpe.RefType(genTypeID.ObjectStruct)) + fb += wa.LocalTee(expr) + fb += wa.RefAsNotNull // cloneFunction argument is not nullable - instrs += wa.LocalGet(expr) - instrs += wa.StructGet(genTypeID.forClass(ObjectClass), genFieldID.objStruct.vtable) - instrs += wa.StructGet(genTypeID.typeData, genFieldID.typeData.cloneFunction) + fb += wa.LocalGet(expr) + fb += wa.StructGet(genTypeID.forClass(ObjectClass), genFieldID.objStruct.vtable) + fb += wa.StructGet(genTypeID.typeData, genFieldID.typeData.cloneFunction) // cloneFunction: (ref j.l.Object) -> ref j.l.Object - instrs += wa.CallRef(genTypeID.cloneFunctionType) + fb += wa.CallRef(genTypeID.cloneFunctionType) t.tpe match { case ClassType(className) => val info = ctx.getClassInfo(className) if (!info.isInterface) // if it's interface, no need to cast from j.l.Object - instrs += wa.RefCast(watpe.RefType(genTypeID.forClass(className))) + fb += wa.RefCast(watpe.RefType(genTypeID.forClass(className))) case _ => throw new IllegalArgumentException( s"Clone result type must be a class type, but is ${t.tpe}" @@ -2648,13 +2646,13 @@ private class FunctionEmitter private ( markPosition(tree) - instrs += wa.LocalSet(selectorLocal) + fb += wa.LocalSet(selectorLocal) - instrs.block(transformResultType(expectedType)) { doneLabel => - instrs.block() { defaultLabel => - val caseLabels = cases.map(c => c._1 -> instrs.genLabel()) + fb.block(transformResultType(expectedType)) { doneLabel => + fb.block() { defaultLabel => + val caseLabels = cases.map(c => c._1 -> fb.genLabel()) for (caseLabel <- caseLabels) - instrs += wa.Block(wa.BlockType.ValueType(), Some(caseLabel._2)) + fb += wa.Block(wa.BlockType.ValueType(), Some(caseLabel._2)) for { caseLabel <- caseLabels @@ -2662,35 +2660,35 @@ private class FunctionEmitter private ( } { markPosition(matchableLiteral) val label = caseLabel._2 - instrs += wa.LocalGet(selectorLocal) + fb += wa.LocalGet(selectorLocal) matchableLiteral match { case IntLiteral(value) => - instrs += wa.I32Const(value) - instrs += wa.I32Eq - instrs += wa.BrIf(label) + fb += wa.I32Const(value) + fb += wa.I32Eq + fb += wa.BrIf(label) case StringLiteral(value) => - instrs ++= ctx.getConstantStringInstr(value) - instrs += wa.Call(genFunctionID.is) - instrs += wa.BrIf(label) + fb ++= ctx.getConstantStringInstr(value) + fb += wa.Call(genFunctionID.is) + fb += wa.BrIf(label) case Null() => - instrs += wa.RefIsNull - instrs += wa.BrIf(label) + fb += wa.RefIsNull + fb += wa.BrIf(label) } } - instrs += wa.Br(defaultLabel) + fb += wa.Br(defaultLabel) for ((caseLabel, caze) <- caseLabels.zip(cases).reverse) { markPosition(caze._2) - instrs += wa.End + fb += wa.End genTree(caze._2, expectedType) - instrs += wa.Br(doneLabel) + fb += wa.Br(doneLabel) } } genTree(defaultBody, expectedType) } if (expectedType == NothingType) - instrs += wa.Unreachable + fb += wa.Unreachable expectedType } @@ -2708,7 +2706,7 @@ private class FunctionEmitter private ( markPosition(tree) - instrs += wa.Call(genFunctionID.createJSClassOf(tree.className)) + fb += wa.Call(genFunctionID.createJSClassOf(tree.className)) AnyType } @@ -2718,8 +2716,8 @@ private class FunctionEmitter private ( markPosition(tree) - instrs += wa.GlobalGet(genGlobalID.forJSPrivateField(tree.field.name)) - instrs += wa.Call(genFunctionID.jsSelect) + fb += wa.GlobalGet(genGlobalID.forJSPrivateField(tree.field.name)) + fb += wa.Call(genFunctionID.jsSelect) AnyType } @@ -2731,7 +2729,7 @@ private class FunctionEmitter private ( markPosition(tree) - instrs += wa.Call(genFunctionID.jsSuperGet) + fb += wa.Call(genFunctionID.jsSuperGet) AnyType } @@ -2744,7 +2742,7 @@ private class FunctionEmitter private ( markPosition(tree) - instrs += wa.Call(genFunctionID.jsSuperCall) + fb += wa.Call(genFunctionID.jsSuperCall) AnyType } @@ -2994,7 +2992,7 @@ private class FunctionEmitter private ( def requireCrossInfo(): (wanme.LocalID, wanme.LabelID) = { _crossInfo.getOrElse { - val info = (addSyntheticLocal(watpe.Int32), instrs.genLabel()) + val info = (addSyntheticLocal(watpe.Int32), fb.genLabel()) _crossInfo = Some(info) info } @@ -3011,7 +3009,7 @@ private class FunctionEmitter private ( /** The regular label for this `Labeled` block, used for `Return`s that do not cross a * `TryFinally`. */ - val regularWasmLabel: wanme.LabelID = instrs.genLabel() + val regularWasmLabel: wanme.LabelID = fb.genLabel() /** The destination tag allocated to this label, used by the `finally` blocks to keep * propagating to the right destination. @@ -3036,7 +3034,7 @@ private class FunctionEmitter private ( destinationTag = allocateDestinationTag() val resultTypes = transformResultType(expectedType) resultLocals = resultTypes.map(addSyntheticLocal(_)) - crossLabel = instrs.genLabel() + crossLabel = fb.genLabel() } (destinationTag, resultLocals, crossLabel) @@ -3051,15 +3049,15 @@ private class FunctionEmitter private ( markPosition(t) // Manual wa.BLOCK here because we have a specific `label` - instrs += wa.Block( - instrs.sigToBlockType(Sig(Nil, ty)), + fb += wa.Block( + fb.sigToBlockType(Sig(Nil, ty)), Some(entry.regularWasmLabel) ) /* Remember the position in the instruction stream, in case we need to * come back and insert the wa.BLOCK for the cross handling. */ - val instrsBlockBeginIndex = instrs.markCurrentInstructionIndex() + val instrsBlockBeginIndex = fb.markCurrentInstructionIndex() // Emit the body enterLabeled(entry) { @@ -3101,19 +3099,19 @@ private class FunctionEmitter private ( val (_, resultLocals, crossLabel) = entry.requireCrossInfo() // Go back and insert the `block $crossLabel` right after `block $labeled` - instrs.insert(instrsBlockBeginIndex, wa.Block(wa.BlockType.ValueType(), Some(crossLabel))) + fb.insert(instrsBlockBeginIndex, wa.Block(wa.BlockType.ValueType(), Some(crossLabel))) // Add the `br`, `end` and `local.get` at the current position, as usual - instrs += wa.Br(entry.regularWasmLabel) - instrs += wa.End + fb += wa.Br(entry.regularWasmLabel) + fb += wa.End for (local <- resultLocals) - instrs += wa.LocalGet(local) + fb += wa.LocalGet(local) } - instrs += wa.End + fb += wa.End if (expectedType == NothingType) - instrs += wa.Unreachable + fb += wa.Unreachable expectedType } @@ -3126,14 +3124,14 @@ private class FunctionEmitter private ( markPosition(t) - instrs.block() { doneLabel => - instrs.block(watpe.RefType.exnref) { catchLabel => + fb.block() { doneLabel => + fb.block(watpe.RefType.exnref) { catchLabel => /* Remember the position in the instruction stream, in case we need * to come back and insert the wa.BLOCK for the cross handling. */ - val instrsBlockBeginIndex = instrs.markCurrentInstructionIndex() + val instrsBlockBeginIndex = fb.markCurrentInstructionIndex() - instrs.tryTable()(List(wa.CatchClause.CatchAllRef(catchLabel))) { + fb.tryTable()(List(wa.CatchClause.CatchAllRef(catchLabel))) { // try block enterTryFinally(entry) { genTree(t.block, expectedType) @@ -3143,7 +3141,7 @@ private class FunctionEmitter private ( // store the result in locals during the finally block for (resultLocal <- resultLocals.reverse) - instrs += wa.LocalSet(resultLocal) + fb += wa.LocalSet(resultLocal) } /* If this try..finally was crossed by a `Return`, we need to amend @@ -3165,19 +3163,19 @@ private class FunctionEmitter private ( val (destinationTagLocal, crossLabel) = entry.requireCrossInfo() // Go back and insert the `block $cross` right after `block $catch` - instrs.insert( + fb.insert( instrsBlockBeginIndex, wa.Block(wa.BlockType.ValueType(), Some(crossLabel)) ) // And the other amendments normally - instrs += wa.I32Const(0) - instrs += wa.LocalSet(destinationTagLocal) - instrs += wa.End // of the inserted wa.BLOCK + fb += wa.I32Const(0) + fb += wa.LocalSet(destinationTagLocal) + fb += wa.End // of the inserted wa.BLOCK } // on success, push a `null_ref exn` on the stack - instrs += wa.RefNull(watpe.HeapType.Exn) + fb += wa.RefNull(watpe.HeapType.Exn) } // end block $catch // finally block (during which we leave the `(ref null exn)` on the stack) @@ -3187,15 +3185,15 @@ private class FunctionEmitter private ( if (!entry.wasCrossed) { // If the `exnref` is non-null, rethrow it - instrs += wa.BrOnNull(doneLabel) - instrs += wa.ThrowRef + fb += wa.BrOnNull(doneLabel) + fb += wa.ThrowRef } else { /* If the `exnref` is non-null, rethrow it. * Otherwise, stay within the `$done` block. */ - instrs.block(Sig(List(watpe.RefType.exnref), Nil)) { exnrefIsNullLabel => - instrs += wa.BrOnNull(exnrefIsNullLabel) - instrs += wa.ThrowRef + fb.block(Sig(List(watpe.RefType.exnref), Nil)) { exnrefIsNullLabel => + fb += wa.BrOnNull(exnrefIsNullLabel) + fb += wa.ThrowRef } /* Otherwise, use a br_table to dispatch to the right destination @@ -3223,10 +3221,10 @@ private class FunctionEmitter private ( destinationTag -> label } - instrs += wa.LocalGet(entry.requireCrossInfo()._1) + fb += wa.LocalGet(entry.requireCrossInfo()._1) for (nextTry <- nextTryFinallyEntry) { // Transfer the destinationTag to the next try..finally in line - instrs += wa.LocalTee(nextTry.requireCrossInfo()._1) + fb += wa.LocalTee(nextTry.requireCrossInfo()._1) } emitBRTable(brTableDests, doneLabel) } @@ -3234,10 +3232,10 @@ private class FunctionEmitter private ( // reload the result onto the stack for (resultLocal <- resultLocals) - instrs += wa.LocalGet(resultLocal) + fb += wa.LocalGet(resultLocal) if (expectedType == NothingType) - instrs += wa.Unreachable + fb += wa.Unreachable expectedType } @@ -3248,25 +3246,25 @@ private class FunctionEmitter private ( ): Unit = { dests match { case Nil => - instrs += wa.Drop - instrs += wa.Br(defaultLabel) + fb += wa.Drop + fb += wa.Br(defaultLabel) case (singleDestValue, singleDestLabel) :: Nil => /* Common case (as far as getting here in the first place is concerned): * All the `Return`s that cross the current `TryFinally` have the same * target destination (namely the enclosing `def` in the original program). */ - instrs += wa.I32Const(singleDestValue) - instrs += wa.I32Eq - instrs += wa.BrIf(singleDestLabel) - instrs += wa.Br(defaultLabel) + fb += wa.I32Const(singleDestValue) + fb += wa.I32Eq + fb += wa.BrIf(singleDestLabel) + fb += wa.Br(defaultLabel) case _ :: _ => // `max` is safe here because the list is non-empty val table = Array.fill(dests.map(_._1).max + 1)(defaultLabel) for (dest <- dests) table(dest._1) = dest._2 - instrs += wa.BrTable(table.toList, defaultLabel) + fb += wa.BrTable(table.toList, defaultLabel) } } @@ -3281,7 +3279,7 @@ private class FunctionEmitter private ( innermostTryFinally.filter(_.isInside(targetEntry)) match { case None => // Easy case: directly branch out of the block - instrs += wa.Br(targetEntry.regularWasmLabel) + fb += wa.Br(targetEntry.regularWasmLabel) case Some(tryFinallyEntry) => /* Here we need to branch to the innermost enclosing `finally` block, @@ -3292,14 +3290,14 @@ private class FunctionEmitter private ( // 1. Store the result in the label's result locals. for (local <- resultLocals.reverse) - instrs += wa.LocalSet(local) + fb += wa.LocalSet(local) // 2. Store the label's destination tag into the try..finally's destination local. - instrs += wa.I32Const(destinationTag) - instrs += wa.LocalSet(destinationTagLocal) + fb += wa.I32Const(destinationTag) + fb += wa.LocalSet(destinationTagLocal) // 3. Branch to the enclosing `finally` block's cross label. - instrs += wa.Br(crossLabel) + fb += wa.Br(crossLabel) } } From 25306a3d78c91cbf3aa2a15f4efa22032a2e2c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Tue, 21 May 2024 17:51:25 +0200 Subject: [PATCH 3/3] Consistent identifier names. * `xName` -> `xID` where appropriate. * `typ` -> `tpe` when alone, to be consistent with Core conventions. * `xTyp` -> `xType`, likewise. --- .../backend/wasmemitter/ClassEmitter.scala | 139 ++++++------ .../backend/wasmemitter/CoreWasmLib.scala | 74 +++---- .../linker/backend/wasmemitter/Emitter.scala | 21 +- .../backend/wasmemitter/FunctionEmitter.scala | 198 ++++++++---------- .../backend/wasmemitter/WasmContext.scala | 32 +-- .../backend/webassembly/BinaryWriter.scala | 78 +++---- .../backend/webassembly/FunctionBuilder.scala | 38 ++-- .../backend/webassembly/Instructions.scala | 17 +- .../backend/webassembly/ModuleBuilder.scala | 12 +- .../linker/backend/webassembly/Modules.scala | 16 +- .../backend/webassembly/TextWriter.scala | 72 +++---- .../linker/backend/webassembly/Types.scala | 28 +-- 12 files changed, 354 insertions(+), 371 deletions(-) diff --git a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/ClassEmitter.scala b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/ClassEmitter.scala index 98bac37..e2c1cdf 100644 --- a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/ClassEmitter.scala +++ b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/ClassEmitter.scala @@ -210,8 +210,8 @@ class ClassEmitter(coreSpec: CoreSpec) { } val isJSClassInstance = genIsJSClassInstanceFunction(clazz) match { - case None => wa.RefNull(watpe.HeapType.NoFunc) - case Some(funcName) => wa.RefFunc(funcName) + case None => wa.RefNull(watpe.HeapType.NoFunc) + case Some(funcID) => wa.RefFunc(funcID) } val reflectiveProxiesInstrs: List[wa.Instr] = { @@ -219,7 +219,7 @@ class ClassEmitter(coreSpec: CoreSpec) { val proxyId = ctx.getReflectiveProxyId(proxyInfo.methodName) List( wa.I32Const(proxyId), - wa.RefFunc(proxyInfo.tableEntryName), + wa.RefFunc(proxyInfo.tableEntryID), wa.StructNew(genTypeID.reflectiveProxy) ) } :+ wa.ArrayNewFixed(genTypeID.reflectiveProxies, reflectiveProxies.size) @@ -257,17 +257,17 @@ class ClassEmitter(coreSpec: CoreSpec) { private def genTypeDataGlobal( className: ClassName, - typeDataTypeName: wanme.TypeID, + typeDataTypeID: wanme.TypeID, typeDataFieldValues: List[wa.Instr], vtableElems: List[wa.RefFunc] )(implicit ctx: WasmContext): Unit = { val instrs: List[wa.Instr] = - typeDataFieldValues ::: vtableElems ::: wa.StructNew(typeDataTypeName) :: Nil + typeDataFieldValues ::: vtableElems ::: wa.StructNew(typeDataTypeID) :: Nil ctx.addGlobal( wamod.Global( genGlobalID.forVTable(className), makeOriginalName(ns.TypeData, className), - watpe.RefType(typeDataTypeName), + watpe.RefType(typeDataTypeID), wa.Expr(instrs), isMutable = false ) @@ -281,7 +281,7 @@ class ClassEmitter(coreSpec: CoreSpec) { val classInfo = ctx.getClassInfo(className) // generate vtable type, this should be done for both abstract and concrete classes - val vtableTypeName = genVTableType(clazz, classInfo) + val vtableTypeID = genVTableType(clazz, classInfo) val isAbstractClass = !clazz.hasDirectInstances @@ -297,9 +297,9 @@ class ClassEmitter(coreSpec: CoreSpec) { classInfo.resolvedMethodInfos.valuesIterator.filter(_.methodName.isReflectiveProxy).toList val typeDataFieldValues = genTypeDataFieldValues(clazz, reflectiveProxies) val vtableElems = classInfo.tableEntries.map { methodName => - wa.RefFunc(classInfo.resolvedMethodInfos(methodName).tableEntryName) + wa.RefFunc(classInfo.resolvedMethodInfos(methodName).tableEntryID) } - genTypeDataGlobal(className, vtableTypeName, typeDataFieldValues, vtableElems) + genTypeDataGlobal(className, vtableTypeID, typeDataFieldValues, vtableElems) // Generate the itable genGlobalClassItable(clazz) @@ -309,7 +309,7 @@ class ClassEmitter(coreSpec: CoreSpec) { val vtableField = watpe.StructField( genFieldID.objStruct.vtable, vtableOriginalName, - watpe.RefType(vtableTypeName), + watpe.RefType(vtableTypeID), isMutable = false ) val itablesField = watpe.StructField( @@ -326,11 +326,11 @@ class ClassEmitter(coreSpec: CoreSpec) { isMutable = true // initialized by the constructors, so always mutable at the Wasm level ) } - val structTypeName = genTypeID.forClass(className) + val structTypeID = genTypeID.forClass(className) val superType = clazz.superClass.map(s => genTypeID.forClass(s.name)) val structType = watpe.StructType(vtableField :: itablesField :: fields) val subType = watpe.SubType( - structTypeName, + structTypeID, makeOriginalName(ns.ClassInstance, className), isFinal = false, superType, @@ -350,7 +350,6 @@ class ClassEmitter(coreSpec: CoreSpec) { val heapType = watpe.HeapType(genTypeID.forClass(clazz.className)) // global instance - // (global name (ref null type)) val global = wamod.Global( genGlobalID.forModuleInstance(className), makeOriginalName(ns.ModuleInstance, className), @@ -369,7 +368,7 @@ class ClassEmitter(coreSpec: CoreSpec) { classInfo: ClassInfo )(implicit ctx: WasmContext): wanme.TypeID = { val className = classInfo.name - val typeName = genTypeID.forVTable(className) + val typeID = genTypeID.forVTable(className) val vtableFields = classInfo.tableEntries.map { methodName => watpe.StructField( @@ -385,14 +384,14 @@ class ClassEmitter(coreSpec: CoreSpec) { } val structType = watpe.StructType(CoreWasmLib.typeDataStructFields ::: vtableFields) val subType = watpe.SubType( - typeName, + typeID, makeOriginalName(ns.VTable, className), isFinal = false, Some(superType), structType ) ctx.mainRecType.addSubType(subType) - typeName + typeID } /** Generate type inclusion test for interfaces. @@ -494,14 +493,14 @@ class ClassEmitter(coreSpec: CoreSpec) { val classInfo = ctx.getClassInfo(className) assert(clazz.hasDirectInstances) - val structName = genTypeID.forClass(className) + val structTypeID = genTypeID.forClass(className) val fb = new FunctionBuilder( ctx.moduleBuilder, genFunctionID.newDefault(className), makeOriginalName(ns.NewDefault, className), clazz.pos ) - fb.setResultType(watpe.RefType(structName)) + fb.setResultType(watpe.RefType(structTypeID)) fb += wa.GlobalGet(genGlobalID.forVTable(className)) @@ -513,7 +512,7 @@ class ClassEmitter(coreSpec: CoreSpec) { classInfo.allFieldDefs.foreach { f => fb += genZeroOf(f.ftpe) } - fb += wa.StructNew(structName) + fb += wa.StructNew(structTypeID) fb.buildAndAddToModule() } @@ -567,10 +566,10 @@ class ClassEmitter(coreSpec: CoreSpec) { assert(clazz.kind == ClassKind.ModuleClass) val className = clazz.className - val globalInstanceName = genGlobalID.forModuleInstance(className) - val ctorName = + val globalInstanceID = genGlobalID.forModuleInstance(className) + val ctorID = genFunctionID.forMethod(MemberNamespace.Constructor, className, NoArgConstructorName) - val resultTyp = watpe.RefType(genTypeID.forClass(className)) + val resultType = watpe.RefType(genTypeID.forClass(className)) val fb = new FunctionBuilder( ctx.moduleBuilder, @@ -578,23 +577,23 @@ class ClassEmitter(coreSpec: CoreSpec) { makeOriginalName(ns.ModuleAccessor, className), clazz.pos ) - fb.setResultType(resultTyp) + fb.setResultType(resultType) - val instanceLocal = fb.addLocal("instance", resultTyp) + val instanceLocal = fb.addLocal("instance", resultType) - fb.block(resultTyp) { nonNullLabel => + fb.block(resultType) { nonNullLabel => // load global, return if not null - fb += wa.GlobalGet(globalInstanceName) + fb += wa.GlobalGet(globalInstanceID) fb += wa.BrOnNonNull(nonNullLabel) // create an instance and call its constructor fb += wa.Call(genFunctionID.newDefault(className)) fb += wa.LocalTee(instanceLocal) - fb += wa.Call(ctorName) + fb += wa.Call(ctorID) // store it in the global fb += wa.LocalGet(instanceLocal) - fb += wa.GlobalSet(globalInstanceName) + fb += wa.GlobalSet(globalInstanceID) // return it fb += wa.LocalGet(instanceLocal) @@ -610,13 +609,13 @@ class ClassEmitter(coreSpec: CoreSpec) { val className = clazz.className if (ctx.getClassInfo(className).classImplementsAnyInterface) { - val globalName = genGlobalID.forITable(className) + val globalID = genGlobalID.forITable(className) val itablesInit = List( wa.I32Const(ctx.itablesLength), wa.ArrayNewDefault(genTypeID.itables) ) val global = wamod.Global( - globalName, + globalID, makeOriginalName(ns.ITable, className), watpe.RefType(genTypeID.itables), wa.Expr(itablesInit), @@ -631,7 +630,7 @@ class ClassEmitter(coreSpec: CoreSpec) { // gen itable type val className = clazz.name.name val classInfo = ctx.getClassInfo(clazz.className) - val itableTypeName = genTypeID.forITable(className) + val itableTypeID = genTypeID.forITable(className) val itableType = watpe.StructType( classInfo.tableEntries.map { methodName => watpe.StructField( @@ -643,7 +642,7 @@ class ClassEmitter(coreSpec: CoreSpec) { } ) ctx.mainRecType.addSubType( - itableTypeName, + itableTypeID, makeOriginalName(ns.ITable, className), itableType ) @@ -709,15 +708,15 @@ class ClassEmitter(coreSpec: CoreSpec) { * are still used by `superArgs` and/or `postSuperArgs`. */ - val preSuperStatsFunctionName = genFunctionID.preSuperStats(className) - val superArgsFunctionName = genFunctionID.superArgs(className) - val postSuperStatsFunctionName = genFunctionID.postSuperStats(className) + val preSuperStatsFunctionID = genFunctionID.preSuperStats(className) + val superArgsFunctionID = genFunctionID.superArgs(className) + val postSuperStatsFunctionID = genFunctionID.postSuperStats(className) val ctor = clazz.jsConstructorDef.get FunctionEmitter.emitJSConstructorFunctions( - preSuperStatsFunctionName, - superArgsFunctionName, - postSuperStatsFunctionName, + preSuperStatsFunctionID, + superArgsFunctionID, + postSuperStatsFunctionID, className, jsClassCaptures, ctor @@ -736,11 +735,9 @@ class ClassEmitter(coreSpec: CoreSpec) { } fb.setResultType(watpe.RefType.any) - val dataStructTypeName = ctx.getClosureDataStructType(jsClassCaptures.map(_.ptpe)) - - // --- Internal name management of `createJSClass` + val dataStructTypeID = ctx.getClosureDataStructType(jsClassCaptures.map(_.ptpe)) - val dataStructLocal = fb.addLocal("classCaptures", watpe.RefType(dataStructTypeName)) + val dataStructLocal = fb.addLocal("classCaptures", watpe.RefType(dataStructTypeID)) val jsClassLocal = fb.addLocal("jsClass", watpe.RefType.any) // --- Actual start of instructions of `createJSClass` @@ -748,7 +745,7 @@ class ClassEmitter(coreSpec: CoreSpec) { // Bundle class captures in a capture data struct -- leave it on the stack for createJSClass for (classCaptureParam <- classCaptureParams) fb += wa.LocalGet(classCaptureParam) - fb += wa.StructNew(dataStructTypeName) + fb += wa.StructNew(dataStructTypeID) fb += wa.LocalTee(dataStructLocal) val classCaptureParamsOfTypeAny: Map[LocalName, wanme.LocalID] = { @@ -781,7 +778,7 @@ class ClassEmitter(coreSpec: CoreSpec) { NoOriginalName, enclosingClassName = None, Some(jsClassCaptures), - receiverTyp = None, + receiverType = None, paramDefs = Nil, restParam = None, tree, @@ -806,9 +803,9 @@ class ClassEmitter(coreSpec: CoreSpec) { } // Load the references to the 3 functions that make up the constructor - fb += ctx.refFuncWithDeclaration(preSuperStatsFunctionName) - fb += ctx.refFuncWithDeclaration(superArgsFunctionName) - fb += ctx.refFuncWithDeclaration(postSuperStatsFunctionName) + fb += ctx.refFuncWithDeclaration(preSuperStatsFunctionID) + fb += ctx.refFuncWithDeclaration(superArgsFunctionID) + fb += ctx.refFuncWithDeclaration(postSuperStatsFunctionID) // Load the array of field names and initial values fb += wa.Call(genFunctionID.jsNewArray) @@ -851,7 +848,7 @@ class ClassEmitter(coreSpec: CoreSpec) { fb += wa.LocalGet(dataStructLocal) fb += wa.LocalGet(jsClassLocal) - val receiverTyp = if (isStatic) None else Some(watpe.RefType.anyref) + val receiverType = if (isStatic) None else Some(watpe.RefType.anyref) methodOrProp match { case JSMethodDef(flags, nameTree, params, restParam, body) => @@ -863,7 +860,7 @@ class ClassEmitter(coreSpec: CoreSpec) { NoOriginalName, // TODO Come up with something here? Some(className), Some(jsClassCaptures), - receiverTyp, + receiverType, params, restParam, body, @@ -891,7 +888,7 @@ class ClassEmitter(coreSpec: CoreSpec) { NoOriginalName, // TODO Come up with something here? Some(className), Some(jsClassCaptures), - receiverTyp, + receiverType, paramDefs = Nil, restParam = None, getterBody, @@ -911,7 +908,7 @@ class ClassEmitter(coreSpec: CoreSpec) { NoOriginalName, // TODO Come up with something here? Some(className), Some(jsClassCaptures), - receiverTyp, + receiverType, setterParamDef :: Nil, restParam = None, setterBody, @@ -1001,11 +998,11 @@ class ClassEmitter(coreSpec: CoreSpec) { private def genLoadJSModuleFunction(clazz: LinkedClass)(implicit ctx: WasmContext): Unit = { val className = clazz.className - val cacheGlobalName = genGlobalID.forModuleInstance(className) + val cacheGlobalID = genGlobalID.forModuleInstance(className) ctx.addGlobal( wamod.Global( - cacheGlobalName, + cacheGlobalID, makeOriginalName(ns.ModuleInstance, className), watpe.RefType.anyref, wa.Expr(List(wa.RefNull(watpe.HeapType.Any))), @@ -1023,7 +1020,7 @@ class ClassEmitter(coreSpec: CoreSpec) { fb.block(watpe.RefType.anyref) { doneLabel => // Load cached instance; return if non-null - fb += wa.GlobalGet(cacheGlobalName) + fb += wa.GlobalGet(cacheGlobalID) fb += wa.BrOnNonNull(doneLabel) // Get the JS class and instantiate it @@ -1032,8 +1029,8 @@ class ClassEmitter(coreSpec: CoreSpec) { fb += wa.Call(genFunctionID.jsNew) // Store and return the result - fb += wa.GlobalSet(cacheGlobalName) - fb += wa.GlobalGet(cacheGlobalName) + fb += wa.GlobalSet(cacheGlobalID) + fb += wa.GlobalGet(cacheGlobalID) } fb.buildAndAddToModule() @@ -1041,16 +1038,16 @@ class ClassEmitter(coreSpec: CoreSpec) { /** Generates the function import for a top-level export setter. */ private def genTopLevelExportSetter(exportedName: String)(implicit ctx: WasmContext): Unit = { - val functionName = genFunctionID.forTopLevelExportSetter(exportedName) + val functionID = genFunctionID.forTopLevelExportSetter(exportedName) val functionSig = watpe.FunctionType(List(watpe.RefType.anyref), Nil) - val functionType = ctx.moduleBuilder.functionTypeToTypeName(functionSig) + val functionType = ctx.moduleBuilder.functionTypeToTypeID(functionSig) ctx.moduleBuilder.addImport( wamod.Import( "__scalaJSExportSetters", exportedName, wamod.ImportDesc.Func( - functionName, + functionID, makeOriginalName(ns.TopLevelExportSetter, exportedName), functionType ) @@ -1065,14 +1062,14 @@ class ClassEmitter(coreSpec: CoreSpec) { val method = exportDef.methodDef val exportedName = exportDef.topLevelExportName - val functionName = genFunctionID.forExport(exportedName) + val functionID = genFunctionID.forExport(exportedName) FunctionEmitter.emitFunction( - functionName, + functionID, makeOriginalName(ns.TopLevelExport, exportedName), enclosingClassName = None, captureParamDefs = None, - receiverTyp = None, + receiverType = None, method.args, method.restParam, method.body, @@ -1090,7 +1087,7 @@ class ClassEmitter(coreSpec: CoreSpec) { val className = clazz.className val methodName = method.methodName - val functionName = genFunctionID.forMethod(namespace, className, methodName) + val functionID = genFunctionID.forMethod(namespace, className, methodName) val namespaceUTF8String = namespace match { case MemberNamespace.Public => ns.Public @@ -1104,7 +1101,7 @@ class ClassEmitter(coreSpec: CoreSpec) { val isHijackedClass = clazz.kind == ClassKind.HijackedClass - val receiverTyp = + val receiverType = if (namespace.isStatic) None else if (isHijackedClass) @@ -1116,11 +1113,11 @@ class ClassEmitter(coreSpec: CoreSpec) { // Emit the function FunctionEmitter.emitFunction( - functionName, + functionID, originalName, Some(className), captureParamDefs = None, - receiverTyp, + receiverType, method.args, restParam = None, body, @@ -1151,13 +1148,13 @@ class ClassEmitter(coreSpec: CoreSpec) { // Load and cast down the receiver fb += wa.LocalGet(receiverParam) - receiverTyp match { + receiverType match { case Some(watpe.RefType(_, watpe.HeapType.Any)) => () // no cast necessary - case Some(receiverTyp: watpe.RefType) => - fb += wa.RefCast(receiverTyp) + case Some(receiverType: watpe.RefType) => + fb += wa.RefCast(receiverType) case _ => - throw new AssertionError(s"Unexpected receiver type $receiverTyp") + throw new AssertionError(s"Unexpected receiver type $receiverType") } // Load the other parameters @@ -1165,7 +1162,7 @@ class ClassEmitter(coreSpec: CoreSpec) { fb += wa.LocalGet(argParam) // Call the statically resolved method - fb += wa.ReturnCall(functionName) + fb += wa.ReturnCall(functionID) fb.buildAndAddToModule() } diff --git a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/CoreWasmLib.scala b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/CoreWasmLib.scala index c237568..d4ed3db 100644 --- a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/CoreWasmLib.scala +++ b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/CoreWasmLib.scala @@ -26,14 +26,14 @@ object CoreWasmLib { * definition. * * @see - * [[VarGen.genFieldName.typeData]], which contains documentation of what is in each field. + * [[VarGen.genFieldID.typeData]], which contains documentation of what is in each field. */ val typeDataStructFields: List[StructField] = { import genFieldID.typeData._ import RefType.nullable - def make(id: FieldID, typ: Type, isMutable: Boolean): StructField = - StructField(id, OriginalName(id.toString()), typ, isMutable) + def make(id: FieldID, tpe: Type, isMutable: Boolean): StructField = + StructField(id, OriginalName(id.toString()), tpe, isMutable) List( make(nameOffset, Int32, isMutable = false), @@ -169,11 +169,11 @@ object CoreWasmLib { private def genArrayClassTypes()(implicit ctx: WasmContext): Unit = { // The vtable type is always the same as j.l.Object - val vtableTypeName = genTypeID.ObjectVTable + val vtableTypeID = genTypeID.ObjectVTable val vtableField = StructField( genFieldID.objStruct.vtable, OriginalName(genFieldID.objStruct.vtable.toString()), - RefType(vtableTypeName), + RefType(vtableTypeID), isMutable = false ) val itablesField = StructField( @@ -196,13 +196,13 @@ object CoreWasmLib { (genTypeID.ObjectArray, genTypeID.anyArray) ) - for ((structTypeName, underlyingArrayTypeName) <- typeRefsWithArrays) { - val origName = OriginalName(structTypeName.toString()) + for ((structTypeID, underlyingArrayTypeID) <- typeRefsWithArrays) { + val origName = OriginalName(structTypeID.toString()) val underlyingArrayField = StructField( genFieldID.objStruct.arrayUnderlying, OriginalName(genFieldID.objStruct.arrayUnderlying.toString()), - RefType(underlyingArrayTypeName), + RefType(underlyingArrayTypeID), isMutable = false ) @@ -210,14 +210,14 @@ object CoreWasmLib { val structType = StructType( List(vtableField, itablesField, underlyingArrayField) ) - val subType = SubType(structTypeName, origName, isFinal = true, Some(superType), structType) + val subType = SubType(structTypeID, origName, isFinal = true, Some(superType), structType) ctx.mainRecType.addSubType(subType) } } private def genTags()(implicit ctx: WasmContext): Unit = { val exceptionSig = FunctionType(List(RefType.externref), Nil) - val typeName = ctx.moduleBuilder.functionTypeToTypeName(exceptionSig) + val typeID = ctx.moduleBuilder.functionTypeToTypeID(exceptionSig) ctx.moduleBuilder.addImport( Import( "__scalaJSHelpers", @@ -225,7 +225,7 @@ object CoreWasmLib { ImportDesc.Tag( genTagID.exception, OriginalName(genTagID.exception.toString()), - typeName + typeID ) ) ) @@ -234,14 +234,14 @@ object CoreWasmLib { private def genGlobalImports()(implicit ctx: WasmContext): Unit = { def addGlobalHelperImport( id: genGlobalID.JSHelperGlobalID, - typ: Type, + tpe: Type, isMutable: Boolean ): Unit = { ctx.moduleBuilder.addImport( Import( "__scalaJSHelpers", id.toString(), // import name, guaranteed by JSHelperGlobalID - ImportDesc.Global(id, OriginalName(id.toString()), typ, isMutable) + ImportDesc.Global(id, OriginalName(id.toString()), tpe, isMutable) ) ) } @@ -268,7 +268,7 @@ object CoreWasmLib { DoubleRef -> KindDouble ) - val typeDataTypeName = genTypeID.typeData + val typeDataTypeID = genTypeID.typeData // Other than `name` and `kind`, all the fields have the same value for all primitives val commonFieldValues = List( @@ -319,7 +319,7 @@ object CoreWasmLib { (genGlobalID.bZeroLong, SpecialNames.LongBoxClass, I64Const(0)) ) - for ((globalName, boxClassName, zeroValueInstr) <- primTypesWithBoxClasses) { + for ((globalID, boxClassName, zeroValueInstr) <- primTypesWithBoxClasses) { val boxStruct = genTypeID.forClass(boxClassName) val instrs: List[Instr] = List( GlobalGet(genGlobalID.forVTable(boxClassName)), @@ -330,8 +330,8 @@ object CoreWasmLib { ctx.addGlobal( Global( - globalName, - OriginalName(globalName.toString()), + globalID, + OriginalName(globalID.toString()), RefType(boxStruct), Expr(instrs), isMutable = false @@ -366,12 +366,12 @@ object CoreWasmLib { results: List[Type] ): Unit = { val sig = FunctionType(params, results) - val typeName = ctx.moduleBuilder.functionTypeToTypeName(sig) + val typeID = ctx.moduleBuilder.functionTypeToTypeID(sig) ctx.moduleBuilder.addImport( Import( "__scalaJSHelpers", id.toString(), // import name, guaranteed by JSHelperFunctionID - ImportDesc.Func(id, OriginalName(id.toString()), typeName) + ImportDesc.Func(id, OriginalName(id.toString()), typeID) ) ) } @@ -487,14 +487,14 @@ object CoreWasmLib { addHelperImport(genFunctionID.jsIsTruthy, List(anyref), List(Int32)) addHelperImport(genFunctionID.jsLinkingInfo, Nil, List(anyref)) - for ((op, name) <- genFunctionID.jsUnaryOps) - addHelperImport(name, List(anyref), List(anyref)) + for ((op, funcID) <- genFunctionID.jsUnaryOps) + addHelperImport(funcID, List(anyref), List(anyref)) - for ((op, name) <- genFunctionID.jsBinaryOps) { + for ((op, funcID) <- genFunctionID.jsBinaryOps) { val resultType = if (op == JSBinaryOp.=== || op == JSBinaryOp.!==) Int32 else anyref - addHelperImport(name, List(anyref, anyref), List(resultType)) + addHelperImport(funcID, List(anyref, anyref), List(resultType)) } addHelperImport(genFunctionID.newSymbol, Nil, List(anyref)) @@ -1052,7 +1052,7 @@ object CoreWasmLib { val objectClassInfo = ctx.getClassInfo(ObjectClass) fb ++= objectClassInfo.tableEntries.map { methodName => - ctx.refFuncWithDeclaration(objectClassInfo.resolvedMethodInfos(methodName).tableEntryName) + ctx.refFuncWithDeclaration(objectClassInfo.resolvedMethodInfos(methodName).tableEntryID) } fb += StructNew(genTypeID.ObjectVTable) fb += LocalTee(arrayTypeDataLocal) @@ -1133,8 +1133,8 @@ object CoreWasmLib { }, List(KindBoxedCharacter) -> { () => fb += LocalGet(valueParam) - val structTypeName = genTypeID.forClass(SpecialNames.CharBoxClass) - fb += RefTest(RefType(structTypeName)) + val structTypeID = genTypeID.forClass(SpecialNames.CharBoxClass) + fb += RefTest(RefType(structTypeID)) }, List(KindBoxedByte) -> { () => fb += LocalGet(valueParam) @@ -1150,8 +1150,8 @@ object CoreWasmLib { }, List(KindBoxedLong) -> { () => fb += LocalGet(valueParam) - val structTypeName = genTypeID.forClass(SpecialNames.LongBoxClass) - fb += RefTest(RefType(structTypeName)) + val structTypeID = genTypeID.forClass(SpecialNames.LongBoxClass) + fb += RefTest(RefType(structTypeID)) }, List(KindBoxedFloat) -> { () => fb += LocalGet(valueParam) @@ -2116,11 +2116,11 @@ object CoreWasmLib { val arrayTypeRef = ArrayTypeRef(baseRef, 1) - val arrayStructTypeName = genTypeID.forArrayClass(arrayTypeRef) - val arrayClassType = RefType(arrayStructTypeName) + val arrayStructTypeID = genTypeID.forArrayClass(arrayTypeRef) + val arrayClassType = RefType(arrayStructTypeID) - val underlyingArrayTypeName = genTypeID.underlyingOf(arrayTypeRef) - val underlyingArrayType = RefType(underlyingArrayTypeName) + val underlyingArrayTypeID = genTypeID.underlyingOf(arrayTypeRef) + val underlyingArrayType = RefType(underlyingArrayTypeID) val fromLocal = fb.addLocal("fromTyped", arrayClassType) val fromUnderlyingLocal = fb.addLocal("fromUnderlying", underlyingArrayType) @@ -2133,26 +2133,26 @@ object CoreWasmLib { fb += LocalTee(fromLocal) // Load the underlying array - fb += StructGet(arrayStructTypeName, genFieldID.objStruct.arrayUnderlying) + fb += StructGet(arrayStructTypeID, genFieldID.objStruct.arrayUnderlying) fb += LocalTee(fromUnderlyingLocal) // Make a copy of the underlying array fb += ArrayLen fb += LocalTee(lengthLocal) - fb += ArrayNewDefault(underlyingArrayTypeName) + fb += ArrayNewDefault(underlyingArrayTypeID) fb += LocalTee(resultUnderlyingLocal) // also dest for array.copy fb += I32Const(0) // destOffset fb += LocalGet(fromUnderlyingLocal) // src fb += I32Const(0) // srcOffset fb += LocalGet(lengthLocal) // length - fb += ArrayCopy(underlyingArrayTypeName, underlyingArrayTypeName) + fb += ArrayCopy(underlyingArrayTypeID, underlyingArrayTypeID) // Build the result arrayStruct fb += LocalGet(fromLocal) - fb += StructGet(arrayStructTypeName, genFieldID.objStruct.vtable) // vtable + fb += StructGet(arrayStructTypeID, genFieldID.objStruct.vtable) // vtable fb += GlobalGet(genGlobalID.arrayClassITable) // itable fb += LocalGet(resultUnderlyingLocal) - fb += StructNew(arrayStructTypeName) + fb += StructNew(arrayStructTypeID) fb.buildAndAddToModule() } diff --git a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/Emitter.scala b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/Emitter.scala index 1809407..4769379 100644 --- a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/Emitter.scala +++ b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/Emitter.scala @@ -157,7 +157,7 @@ final class Emitter(config: Emitter.Config) { fb += wa.I32Const(idx) for (method <- iface.tableEntries) - fb += ctx.refFuncWithDeclaration(resolvedMethodInfos(method).tableEntryName) + fb += ctx.refFuncWithDeclaration(resolvedMethodInfos(method).tableEntryID) fb += wa.StructNew(genTypeID.forITable(iface.name)) fb += wa.ArraySet(genTypeID.itables) } @@ -166,7 +166,7 @@ final class Emitter(config: Emitter.Config) { locally { // For array classes, resolve methods in jl.Object - val globalName = genGlobalID.arrayClassITable + val globalID = genGlobalID.arrayClassITable val resolvedMethodInfos = ctx.getClassInfo(ObjectClass).resolvedMethodInfos for { @@ -174,11 +174,11 @@ final class Emitter(config: Emitter.Config) { // Use getClassInfoOption in case the reachability analysis got rid of those interfaces interfaceInfo <- ctx.getClassInfoOption(interfaceName) } { - fb += wa.GlobalGet(globalName) + fb += wa.GlobalGet(globalID) fb += wa.I32Const(ctx.getItableIdx(interfaceInfo)) for (method <- interfaceInfo.tableEntries) - fb += ctx.refFuncWithDeclaration(resolvedMethodInfos(method).tableEntryName) + fb += ctx.refFuncWithDeclaration(resolvedMethodInfos(method).tableEntryID) fb += wa.StructNew(genTypeID.forITable(interfaceName)) fb += wa.ArraySet(genTypeID.itables) } @@ -201,12 +201,12 @@ final class Emitter(config: Emitter.Config) { // Emit the static initializers for (clazz <- sortedClasses if clazz.hasStaticInitializer) { - val funcName = genFunctionID.forMethod( + val funcID = genFunctionID.forMethod( MemberNamespace.StaticConstructor, clazz.className, StaticInitializerName ) - fb += wa.Call(funcName) + fb += wa.Call(funcID) } // Initialize the top-level exports that require it @@ -243,9 +243,8 @@ final class Emitter(config: Emitter.Config) { moduleInitializers.foreach { init => def genCallStatic(className: ClassName, methodName: MethodName): Unit = { - val functionName = - genFunctionID.forMethod(MemberNamespace.PublicStatic, className, methodName) - fb += wa.Call(functionName) + val funcID = genFunctionID.forMethod(MemberNamespace.PublicStatic, className, methodName) + fb += wa.Call(funcID) } ModuleInitializerImpl.fromInitializer(init) match { @@ -294,8 +293,8 @@ final class Emitter(config: Emitter.Config) { * Element section with the declarative mode is the recommended way to * introduce these declarations. */ - val exprs = funcDeclarations.map { name => - wa.Expr(List(wa.RefFunc(name))) + val exprs = funcDeclarations.map { funcID => + wa.Expr(List(wa.RefFunc(funcID))) } ctx.moduleBuilder.addElement( wamod.Element(watpe.RefType.funcref, exprs, wamod.Element.Mode.Declarative) diff --git a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/FunctionEmitter.scala b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/FunctionEmitter.scala index b1be667..d2c7e49 100644 --- a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/FunctionEmitter.scala +++ b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/FunctionEmitter.scala @@ -40,24 +40,24 @@ object FunctionEmitter { private final val UseLegacyExceptionsForTryCatch = true def emitFunction( - functionName: wanme.FunctionID, + functionID: wanme.FunctionID, originalName: OriginalName, enclosingClassName: Option[ClassName], captureParamDefs: Option[List[ParamDef]], - receiverTyp: Option[watpe.Type], + receiverType: Option[watpe.Type], paramDefs: List[ParamDef], restParam: Option[ParamDef], body: Tree, resultType: Type )(implicit ctx: WasmContext, pos: Position): Unit = { val emitter = prepareEmitter( - functionName, + functionID, originalName, enclosingClassName, captureParamDefs, preSuperVarDefs = None, hasNewTarget = false, - receiverTyp, + receiverType, paramDefs ::: restParam.toList, transformResultType(resultType) ) @@ -66,9 +66,9 @@ object FunctionEmitter { } def emitJSConstructorFunctions( - preSuperStatsFunctionName: wanme.FunctionID, - superArgsFunctionName: wanme.FunctionID, - postSuperStatsFunctionName: wanme.FunctionID, + preSuperStatsFunctionID: wanme.FunctionID, + superArgsFunctionID: wanme.FunctionID, + postSuperStatsFunctionID: wanme.FunctionID, enclosingClassName: ClassName, jsClassCaptures: List[ParamDef], ctor: JSConstructorDef @@ -85,26 +85,26 @@ object FunctionEmitter { // Build the `preSuperStats` function locally { - val preSuperEnvStructTypeName = ctx.getClosureDataStructType(preSuperDecls.map(_.vtpe)) - val preSuperEnvTyp = watpe.RefType(preSuperEnvStructTypeName) + val preSuperEnvStructTypeID = ctx.getClosureDataStructType(preSuperDecls.map(_.vtpe)) + val preSuperEnvType = watpe.RefType(preSuperEnvStructTypeID) val emitter = prepareEmitter( - preSuperStatsFunctionName, + preSuperStatsFunctionID, OriginalName(UTF8String("preSuperStats.") ++ enclosingClassName.encoded), Some(enclosingClassName), Some(jsClassCaptures), preSuperVarDefs = None, hasNewTarget = true, - receiverTyp = None, + receiverType = None, allCtorParams, - List(preSuperEnvTyp) + List(preSuperEnvType) ) emitter.genBlockStats(ctorBody.beforeSuper) { // Build and return the preSuperEnv struct for (varDef <- preSuperDecls) emitter.fb += wa.LocalGet(emitter.lookupLocalAssertLocalStorage(varDef.name.name)) - emitter.fb += wa.StructNew(preSuperEnvStructTypeName) + emitter.fb += wa.StructNew(preSuperEnvStructTypeID) } emitter.fb.buildAndAddToModule() @@ -113,13 +113,13 @@ object FunctionEmitter { // Build the `superArgs` function locally { val emitter = prepareEmitter( - superArgsFunctionName, + superArgsFunctionID, OriginalName(UTF8String("superArgs.") ++ enclosingClassName.encoded), Some(enclosingClassName), Some(jsClassCaptures), Some(preSuperDecls), hasNewTarget = true, - receiverTyp = None, + receiverType = None, allCtorParams, List(watpe.RefType.anyref) // a js.Array ) @@ -130,13 +130,13 @@ object FunctionEmitter { // Build the `postSuperStats` function locally { val emitter = prepareEmitter( - postSuperStatsFunctionName, + postSuperStatsFunctionID, OriginalName(UTF8String("postSuperStats.") ++ enclosingClassName.encoded), Some(enclosingClassName), Some(jsClassCaptures), Some(preSuperDecls), hasNewTarget = true, - receiverTyp = Some(watpe.RefType.anyref), + receiverType = Some(watpe.RefType.anyref), allCtorParams, List(watpe.RefType.anyref) ) @@ -146,17 +146,17 @@ object FunctionEmitter { } private def prepareEmitter( - functionName: wanme.FunctionID, + functionID: wanme.FunctionID, originalName: OriginalName, enclosingClassName: Option[ClassName], captureParamDefs: Option[List[ParamDef]], preSuperVarDefs: Option[List[VarDef]], hasNewTarget: Boolean, - receiverTyp: Option[watpe.Type], + receiverType: Option[watpe.Type], paramDefs: List[ParamDef], resultTypes: List[watpe.Type] )(implicit ctx: WasmContext, pos: Position): FunctionEmitter = { - val fb = new FunctionBuilder(ctx.moduleBuilder, functionName, originalName, pos) + val fb = new FunctionBuilder(ctx.moduleBuilder, functionID, originalName, pos) def addCaptureLikeParamListAndMakeEnv( captureParamName: String, @@ -167,12 +167,12 @@ object FunctionEmitter { Map.empty case Some(captureLikes) => - val dataStructTypeName = ctx.getClosureDataStructType(captureLikes.map(_._2)) - val param = fb.addParam(captureParamName, watpe.RefType(dataStructTypeName)) + val dataStructTypeID = ctx.getClosureDataStructType(captureLikes.map(_._2)) + val param = fb.addParam(captureParamName, watpe.RefType(dataStructTypeID)) val env: Env = captureLikes.zipWithIndex.map { case (captureLike, idx) => val storage = VarStorage.StructField( param, - dataStructTypeName, + dataStructTypeID, genFieldID.captureParam(idx) ) captureLike._1 -> storage @@ -198,8 +198,8 @@ object FunctionEmitter { Some(VarStorage.Local(newTargetParam)) } - val receiverStorage = receiverTyp.map { typ => - val receiverParam = fb.addParam(receiverOriginalName, typ) + val receiverStorage = receiverType.map { tpe => + val receiverParam = fb.addParam(receiverOriginalName, tpe) VarStorage.Local(receiverParam) } @@ -240,12 +240,12 @@ object FunctionEmitter { private sealed abstract class VarStorage private object VarStorage { - final case class Local(idx: wanme.LocalID) extends VarStorage + final case class Local(localID: wanme.LocalID) extends VarStorage final case class StructField( - structIdx: wanme.LocalID, - structTypeName: wanme.TypeID, - fieldIdx: wanme.FieldID + structLocalID: wanme.LocalID, + structTypeID: wanme.TypeID, + fieldID: wanme.FieldID ) extends VarStorage } @@ -274,11 +274,11 @@ private class FunctionEmitter private ( private def receiverStorage: VarStorage.Local = _receiverStorage.getOrElse(throw new Error("Cannot access to the receiver in this context.")) - private def withNewLocal[A](name: LocalName, originalName: OriginalName, typ: watpe.Type)( + private def withNewLocal[A](name: LocalName, originalName: OriginalName, tpe: watpe.Type)( body: wanme.LocalID => A ): A = { val savedEnv = currentEnv - val local = fb.addLocal(originalName.orElse(name), typ) + val local = fb.addLocal(originalName.orElse(name), tpe) currentEnv = currentEnv.updated(name, VarStorage.Local(local)) try body(local) finally currentEnv = savedEnv @@ -298,8 +298,8 @@ private class FunctionEmitter private ( } } - private def addSyntheticLocal(typ: watpe.Type): wanme.LocalID = - fb.addLocal(NoOriginalName, typ) + private def addSyntheticLocal(tpe: watpe.Type): wanme.LocalID = + fb.addLocal(NoOriginalName, tpe) private def genInnerFuncOriginalName(): OriginalName = { if (fb.functionOriginalName.isEmpty) { @@ -421,9 +421,9 @@ private class FunctionEmitter private ( * We implement them with real Wasm classes following the correct * vtable. Upcasting wraps a primitive into the corresponding class. */ - genBox(CharType, SpecialNames.CharBoxClass) + genBox(watpe.Int32, SpecialNames.CharBoxClass) case LongType => - genBox(LongType, SpecialNames.LongBoxClass) + genBox(watpe.Int64, SpecialNames.LongBoxClass) case NoType | NothingType => throw new AssertionError(s"Unexpected adaptation from $primType to $expectedType") case _ => @@ -466,16 +466,16 @@ private class FunctionEmitter private ( case sel: SelectStatic => val fieldName = sel.field.name - val globalName = genGlobalID.forStaticField(fieldName) + val globalID = genGlobalID.forStaticField(fieldName) genTree(t.rhs, sel.tpe) - fb += wa.GlobalSet(globalName) + fb += wa.GlobalSet(globalID) // Update top-level export mirrors val classInfo = ctx.getClassInfo(fieldName.className) val mirrors = classInfo.staticFieldMirrors.getOrElse(fieldName, Nil) for (exportedName <- mirrors) { - fb += wa.GlobalGet(globalName) + fb += wa.GlobalGet(globalID) fb += wa.Call(genFunctionID.forTopLevelExportSetter(exportedName)) } @@ -531,10 +531,10 @@ private class FunctionEmitter private ( case VarStorage.Local(local) => genTree(t.rhs, t.lhs.tpe) fb += wa.LocalSet(local) - case VarStorage.StructField(structLocal, structTypeName, fieldIdx) => + case VarStorage.StructField(structLocal, structTypeID, fieldID) => fb += wa.LocalGet(structLocal) genTree(t.rhs, t.lhs.tpe) - fb += wa.StructSet(structTypeName, fieldIdx) + fb += wa.StructSet(structTypeID, fieldID) } case assign: RecordSelect => @@ -594,7 +594,7 @@ private class FunctionEmitter private ( addSyntheticLocal(watpe.RefType.any) val proxyId = ctx.getReflectiveProxyId(t.method.name) - val funcTypeName = ctx.tableFunctionType(t.method.name) + val funcTypeID = ctx.tableFunctionType(t.method.name) fb.block(watpe.RefType.anyref) { done => fb.block(watpe.RefType.any) { labelNotOurObject => @@ -619,8 +619,8 @@ private class FunctionEmitter private ( // `searchReflectiveProxy`: [typeData, i32] -> [(ref func)] fb += wa.Call(genFunctionID.searchReflectiveProxy) - fb += wa.RefCast(watpe.RefType(watpe.HeapType(funcTypeName))) - fb += wa.CallRef(funcTypeName) + fb += wa.RefCast(watpe.RefType(watpe.HeapType(funcTypeID))) + fb += wa.CallRef(funcTypeID) fb += wa.Br(done) } // labelNotFound fb += wa.Unreachable @@ -674,12 +674,8 @@ private class FunctionEmitter private ( * After this code gen, the stack contains the result. */ def genHijackedClassCall(hijackedClass: ClassName): Unit = { - val funcName = genFunctionID.forMethod( - MemberNamespace.Public, - hijackedClass, - t.method.name - ) - fb += wa.Call(funcName) + val funcID = genFunctionID.forMethod(MemberNamespace.Public, hijackedClass, t.method.name) + fb += wa.Call(funcID) } if (!receiverClassInfo.hasInstances) { @@ -723,9 +719,9 @@ private class FunctionEmitter private ( assert(receiverClassInfo.kind != ClassKind.HijackedClass, receiverClassName) - val resultTyp = transformResultType(t.tpe) + val resultType = transformResultType(t.tpe) - fb.block(resultTyp) { labelDone => + fb.block(resultType) { labelDone => def pushArgs(argsLocals: List[wanme.LocalID]): Unit = argsLocals.foreach(argLocal => fb += wa.LocalGet(argLocal)) @@ -745,11 +741,11 @@ private class FunctionEmitter private ( fb += wa.LocalSet(receiverLocal) val argsLocals: List[wanme.LocalID] = for ((arg, typeRef) <- t.args.zip(t.method.name.paramTypeRefs)) yield { - val typ = ctx.inferTypeFromTypeRef(typeRef) - genTree(arg, typ) - val localName = addSyntheticLocal(transformType(typ)) - fb += wa.LocalSet(localName) - localName + val tpe = ctx.inferTypeFromTypeRef(typeRef) + genTree(arg, tpe) + val localID = addSyntheticLocal(transformType(tpe)) + fb += wa.LocalSet(localID) + localID } fb += wa.LocalGet(receiverLocal) argsLocals @@ -958,8 +954,8 @@ private class FunctionEmitter private ( genArgs(t.args, t.method.name) - val funcName = genFunctionID.forMethod(namespace, targetClassName, t.method.name) - fb += wa.Call(funcName) + val funcID = genFunctionID.forMethod(namespace, targetClassName, t.method.name) + fb += wa.Call(funcID) if (t.tpe == NothingType) fb += wa.Unreachable t.tpe @@ -969,8 +965,8 @@ private class FunctionEmitter private ( private def genApplyStatic(tree: ApplyStatic): Type = { genArgs(tree.args, tree.method.name) val namespace = MemberNamespace.forStaticCall(tree.flags) - val funcName = genFunctionID.forMethod(namespace, tree.className, tree.method.name) - fb += wa.Call(funcName) + val funcID = genFunctionID.forMethod(namespace, tree.className, tree.method.name) + fb += wa.Call(funcID) if (tree.tpe == NothingType) fb += wa.Unreachable tree.tpe @@ -1243,10 +1239,10 @@ private class FunctionEmitter private ( */ val tpe = binary.tpe - val wasmTyp = transformType(tpe) + val wasmType = transformType(tpe) - val lhsLocal = addSyntheticLocal(wasmTyp) - val rhsLocal = addSyntheticLocal(wasmTyp) + val lhsLocal = addSyntheticLocal(wasmType) + val rhsLocal = addSyntheticLocal(wasmType) genTree(binary.lhs, tpe) fb += wa.LocalSet(lhsLocal) genTree(binary.rhs, tpe) @@ -1263,7 +1259,7 @@ private class FunctionEmitter private ( fb += wa.LocalGet(rhsLocal) fb += const(num.fromInt(-1)) fb += eq - fb.ifThenElse(wasmTyp) { + fb.ifThenElse(wasmType) { // 0 - lhs fb += const(num.zero) fb += wa.LocalGet(lhsLocal) @@ -1614,11 +1610,11 @@ private class FunctionEmitter private ( case testType: PrimTypeWithRef => testType match { case CharType => - val structTypeName = genTypeID.forClass(SpecialNames.CharBoxClass) - fb += wa.RefTest(watpe.RefType(structTypeName)) + val structTypeID = genTypeID.forClass(SpecialNames.CharBoxClass) + fb += wa.RefTest(watpe.RefType(structTypeID)) case LongType => - val structTypeName = genTypeID.forClass(SpecialNames.LongBoxClass) - fb += wa.RefTest(watpe.RefType(structTypeName)) + val structTypeID = genTypeID.forClass(SpecialNames.LongBoxClass) + fb += wa.RefTest(watpe.RefType(structTypeID)) case NoType | NothingType | NullType => throw new AssertionError(s"Illegal isInstanceOf[$testType]") case _ => @@ -1670,13 +1666,10 @@ private class FunctionEmitter private ( case ArrayType(arrayTypeRef) => arrayTypeRef match { - case ArrayTypeRef( - ClassRef(ObjectClass) | _: PrimRef, - 1 - ) => + case ArrayTypeRef(ClassRef(ObjectClass) | _: PrimRef, 1) => // For primitive arrays and exactly Array[Object], a wa.REF_TEST is enough - val structTypeName = genTypeID.forArrayClass(arrayTypeRef) - fb += wa.RefTest(watpe.RefType(structTypeName)) + val structTypeID = genTypeID.forArrayClass(arrayTypeRef) + fb += wa.RefTest(watpe.RefType(structTypeID)) case _ => /* Non-Object reference arra types need a sophisticated type test @@ -1687,16 +1680,16 @@ private class FunctionEmitter private ( fb.block(Sig(List(anyref), List(watpe.Int32))) { doneLabel => fb.block(Sig(List(anyref), List(anyref))) { notARefArrayLabel => // Try and cast to the generic representation first - val refArrayStructTypeName = genTypeID.forArrayClass(arrayTypeRef) + val refArrayStructTypeID = genTypeID.forArrayClass(arrayTypeRef) fb += wa.BrOnCastFail( notARefArrayLabel, watpe.RefType.anyref, - watpe.RefType(refArrayStructTypeName) + watpe.RefType(refArrayStructTypeID) ) // refArrayValue := the generic representation val refArrayValueLocal = - addSyntheticLocal(watpe.RefType(refArrayStructTypeName)) + addSyntheticLocal(watpe.RefType(refArrayStructTypeID)) fb += wa.LocalSet(refArrayValueLocal) // Load typeDataOf(arrayTypeRef) @@ -1704,7 +1697,7 @@ private class FunctionEmitter private ( // Load refArrayValue.vtable fb += wa.LocalGet(refArrayValueLocal) - fb += wa.StructGet(refArrayStructTypeName, genFieldID.objStruct.vtable) + fb += wa.StructGet(refArrayStructTypeID, genFieldID.objStruct.vtable) // Call isAssignableFrom and return its result fb += wa.Call(genFunctionID.isAssignableFrom) @@ -1800,10 +1793,10 @@ private class FunctionEmitter private ( fb.block(Sig(List(watpe.RefType.anyref), List(resultType))) { doneLabel => fb.block(Sig(List(watpe.RefType.anyref), Nil)) { isNullLabel => fb += wa.BrOnNull(isNullLabel) - val structTypeName = genTypeID.forClass(boxClass) - fb += wa.RefCast(watpe.RefType(structTypeName)) + val structTypeID = genTypeID.forClass(boxClass) + fb += wa.RefCast(watpe.RefType(structTypeID)) fb += wa.StructGet( - structTypeName, + structTypeID, genFieldID.forClassInstanceField(fieldName) ) fb += wa.Br(doneLabel) @@ -1857,11 +1850,11 @@ private class FunctionEmitter private ( private def genReadStorage(storage: VarStorage): Unit = { storage match { - case VarStorage.Local(localIdx) => - fb += wa.LocalGet(localIdx) - case VarStorage.StructField(structLocalIdx, structTypeName, fieldIdx) => - fb += wa.LocalGet(structLocalIdx) - fb += wa.StructGet(structTypeName, fieldIdx) + case VarStorage.Local(localID) => + fb += wa.LocalGet(localID) + case VarStorage.StructField(structLocal, structTypeID, fieldID) => + fb += wa.LocalGet(structLocal) + fb += wa.StructGet(structTypeID, fieldID) } } @@ -2080,8 +2073,8 @@ private class FunctionEmitter private ( * if the given class is an ancestor of hijacked classes (which in practice * is only the case for j.l.Object). */ - val instanceTyp = watpe.RefType(genTypeID.forClass(n.className)) - val localInstance = addSyntheticLocal(instanceTyp) + val instanceType = watpe.RefType(genTypeID.forClass(n.className)) + val localInstance = addSyntheticLocal(instanceType) markPosition(n) fb += wa.Call(genFunctionID.newDefault(n.className)) @@ -2103,13 +2096,8 @@ private class FunctionEmitter private ( } /** Codegen to box a primitive `char`/`long` into a `CharacterBox`/`LongBox`. */ - private def genBox( - primType: PrimTypeWithRef, - boxClassName: ClassName - ): Type = { - // `primTyp` is `i32` for `char` (containing a `u16` value) or `i64` for `long`. - val primTyp = transformType(primType) - val primLocal = addSyntheticLocal(primTyp) + private def genBox(primType: watpe.SimpleType, boxClassName: ClassName): Type = { + val primLocal = addSyntheticLocal(primType) /* We use a direct `StructNew` instead of the logical call to `newDefault` * plus constructor call. We can do this because we know that this is @@ -2137,12 +2125,12 @@ private class FunctionEmitter private ( private def genWrapAsThrowable(tree: WrapAsThrowable): Type = { val throwableClassType = ClassType(ThrowableClass) - val nonNullThrowableTyp = watpe.RefType(genTypeID.ThrowableStruct) + val nonNullThrowableType = watpe.RefType(genTypeID.ThrowableStruct) - val jsExceptionTyp = + val jsExceptionType = transformClassType(SpecialNames.JSExceptionClass).toNonNullable - fb.block(nonNullThrowableTyp) { doneLabel => + fb.block(nonNullThrowableType) { doneLabel => genTree(tree.expr, AnyType) markPosition(tree) @@ -2151,13 +2139,13 @@ private class FunctionEmitter private ( fb += wa.BrOnCast( doneLabel, watpe.RefType.anyref, - nonNullThrowableTyp + nonNullThrowableType ) // otherwise, wrap in a new JavaScriptException val exprLocal = addSyntheticLocal(watpe.RefType.anyref) - val instanceLocal = addSyntheticLocal(jsExceptionTyp) + val instanceLocal = addSyntheticLocal(jsExceptionType) fb += wa.LocalSet(exprLocal) fb += wa.Call(genFunctionID.newDefault(SpecialNames.JSExceptionClass)) @@ -2512,8 +2500,8 @@ private class FunctionEmitter private ( () case refType: watpe.RefType => fb += wa.RefCast(refType) - case typ => - throw new AssertionError(s"Unexpected result type for reference array: $typ") + case otherType => + throw new AssertionError(s"Unexpected result type for reference array: $otherType") } } @@ -2562,7 +2550,7 @@ private class FunctionEmitter private ( val hasThis = !tree.arrow val hasRestParam = tree.restParam.isDefined - val dataStructTypeName = ctx.getClosureDataStructType(tree.captureParams.map(_.ptpe)) + val dataStructTypeID = ctx.getClosureDataStructType(tree.captureParams.map(_.ptpe)) // Define the function where captures are reified as a `__captureData` argument. val closureFuncOrigName = genInnerFuncOriginalName() @@ -2572,7 +2560,7 @@ private class FunctionEmitter private ( closureFuncOrigName, enclosingClassName = None, Some(tree.captureParams), - receiverTyp = if (!hasThis) None else Some(watpe.RefType.anyref), + receiverType = if (!hasThis) None else Some(watpe.RefType.anyref), tree.params, tree.restParam, tree.body, @@ -2588,7 +2576,7 @@ private class FunctionEmitter private ( for ((param, value) <- tree.captureParams.zip(tree.captureValues)) genTree(value, param.ptpe) markPosition(tree) - fb += wa.StructNew(dataStructTypeName) + fb += wa.StructNew(dataStructTypeID) /* If there is a ...rest param, the helper requires as third argument the * number of regular arguments. diff --git a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/WasmContext.scala b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/WasmContext.scala index d67e8eb..e53c908 100644 --- a/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/WasmContext.scala +++ b/wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/WasmContext.scala @@ -39,12 +39,12 @@ final class WasmContext( val moduleBuilder: ModuleBuilder = { new ModuleBuilder(new ModuleBuilder.FunctionTypeProvider { - def functionTypeToTypeName(sig: watpe.FunctionType): wanme.TypeID = { + def functionTypeToTypeID(sig: watpe.FunctionType): wanme.TypeID = { functionTypes.getOrElseUpdate( sig, { - val typeName = genTypeID.forFunction(functionTypes.size) - moduleBuilder.addRecType(typeName, NoOriginalName, sig) - typeName + val typeID = genTypeID.forFunction(functionTypes.size) + moduleBuilder.addRecType(typeID, NoOriginalName, sig) + typeID } ) } @@ -111,20 +111,20 @@ final class WasmContext( tableFunctionTypes.getOrElseUpdate( normalizedName, { - val typeName = genTypeID.forTableFunctionType(normalizedName) + val typeID = genTypeID.forTableFunctionType(normalizedName) val regularParamTyps = normalizedName.paramTypeRefs.map { typeRef => TypeTransformer.transformType(inferTypeFromTypeRef(typeRef))(this) } - val resultTyp = + val resultType = TypeTransformer.transformResultType(inferTypeFromTypeRef(normalizedName.resultTypeRef))( this ) mainRecType.addSubType( - typeName, + typeID, NoOriginalName, - watpe.FunctionType(watpe.RefType.any :: regularParamTyps, resultTyp) + watpe.FunctionType(watpe.RefType.any :: regularParamTyps, resultType) ) - typeName + typeID } ) } @@ -174,18 +174,18 @@ final class WasmContext( TypeTransformer.transformType(tpe)(this), isMutable = false ) - val structTypeName = genTypeID.captureData(nextClosureDataTypeIndex) + val structTypeID = genTypeID.captureData(nextClosureDataTypeIndex) nextClosureDataTypeIndex += 1 val structType = watpe.StructType(fields) - moduleBuilder.addRecType(structTypeName, NoOriginalName, structType) - structTypeName + moduleBuilder.addRecType(structTypeID, NoOriginalName, structType) + structTypeID } ) } - def refFuncWithDeclaration(name: wanme.FunctionID): wa.RefFunc = { - _funcDeclarations += name - wa.RefFunc(name) + def refFuncWithDeclaration(funcID: wanme.FunctionID): wa.RefFunc = { + _funcDeclarations += funcID + wa.RefFunc(funcID) } def addGlobal(g: wamod.Global): Unit = @@ -341,7 +341,7 @@ object WasmContext { val ownerClass: ClassName, val methodName: MethodName ) { - val tableEntryName = genFunctionID.forTableEntry(ownerClass, methodName) + val tableEntryID = genFunctionID.forTableEntry(ownerClass, methodName) private var effectivelyFinal: Boolean = true diff --git a/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/BinaryWriter.scala b/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/BinaryWriter.scala index 2cb34e9..2db00a0 100644 --- a/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/BinaryWriter.scala +++ b/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/BinaryWriter.scala @@ -143,7 +143,7 @@ class BinaryWriter(module: Module, emitDebugInfo: Boolean) { private def writeCompositeType(buf: Buffer, compositeType: CompositeType): Unit = { def writeFieldType(fieldType: FieldType): Unit = { - writeType(buf, fieldType.typ) + writeType(buf, fieldType.tpe) buf.boolean(fieldType.isMutable) } @@ -167,37 +167,37 @@ class BinaryWriter(module: Module, emitDebugInfo: Boolean) { buf.name(imprt.name) imprt.desc match { - case ImportDesc.Func(_, _, typeName) => + case ImportDesc.Func(_, _, typeID) => buf.byte(0x00) // func - writeTypeIdx(buf, typeName) - case ImportDesc.Global(_, _, typ, isMutable) => + writeTypeIdx(buf, typeID) + case ImportDesc.Global(_, _, tpe, isMutable) => buf.byte(0x03) // global - writeType(buf, typ) + writeType(buf, tpe) buf.boolean(isMutable) - case ImportDesc.Tag(_, _, typeName) => + case ImportDesc.Tag(_, _, typeID) => buf.byte(0x04) // tag buf.byte(0x00) // exception kind (that is the only valid kind for now) - writeTypeIdx(buf, typeName) + writeTypeIdx(buf, typeID) } } } private def writeFunctionSection(buf: Buffer): Unit = { buf.vec(module.funcs) { fun => - writeTypeIdx(buf, fun.typeName) + writeTypeIdx(buf, fun.typeID) } } private def writeTagSection(buf: Buffer): Unit = { buf.vec(module.tags) { tag => buf.byte(0x00) // exception kind (that is the only valid kind for now) - writeTypeIdx(buf, tag.typ) + writeTypeIdx(buf, tag.typeID) } } private def writeGlobalSection(buf: Buffer): Unit = { buf.vec(module.globals) { global => - writeType(buf, global.typ) + writeType(buf, global.tpe) buf.boolean(global.isMutable) writeExpr(buf, global.init) } @@ -227,7 +227,7 @@ class BinaryWriter(module: Module, emitDebugInfo: Boolean) { case Element.Mode.Passive => buf.byte(5) case Element.Mode.Declarative => buf.byte(7) } - writeType(buf, element.typ) + writeType(buf, element.tpe) buf.vec(element.init) { expr => writeExpr(buf, expr) } @@ -279,7 +279,7 @@ class BinaryWriter(module: Module, emitDebugInfo: Boolean) { buf.vec(func.locals) { local => buf.u32(1) - writeType(buf, local.typ) + writeType(buf, local.tpe) } withLocalIdxValues((func.params ::: func.locals).map(_.id).zipWithIndex.toMap) { @@ -289,10 +289,10 @@ class BinaryWriter(module: Module, emitDebugInfo: Boolean) { emitEndFuncPosition(buf) } - private def writeType(buf: Buffer, typ: StorageType): Unit = { - typ match { - case typ: SimpleType => buf.byte(typ.binaryCode) - case typ: PackedType => buf.byte(typ.binaryCode) + private def writeType(buf: Buffer, tpe: StorageType): Unit = { + tpe match { + case tpe: SimpleType => buf.byte(tpe.binaryCode) + case tpe: PackedType => buf.byte(tpe.binaryCode) case RefType(true, heapType: HeapType.AbsHeapType) => buf.byte(heapType.binaryCode) @@ -305,7 +305,7 @@ class BinaryWriter(module: Module, emitDebugInfo: Boolean) { private def writeHeapType(buf: Buffer, heapType: HeapType): Unit = { heapType match { - case HeapType.Type(typeName) => writeTypeIdxs33(buf, typeName) + case HeapType.Type(typeID) => writeTypeIdxs33(buf, typeID) case heapType: HeapType.AbsHeapType => buf.byte(heapType.binaryCode) } } @@ -313,38 +313,38 @@ class BinaryWriter(module: Module, emitDebugInfo: Boolean) { private def writeResultType(buf: Buffer, resultType: List[Type]): Unit = buf.vec(resultType)(writeType(buf, _)) - private def writeTypeIdx(buf: Buffer, typeName: TypeID): Unit = - buf.u32(typeIdxValues(typeName)) + private def writeTypeIdx(buf: Buffer, typeID: TypeID): Unit = + buf.u32(typeIdxValues(typeID)) private def writeFieldIdx(buf: Buffer, typeID: TypeID, fieldID: FieldID): Unit = buf.u32(fieldIdxValues(typeID)(fieldID)) - private def writeDataIdx(buf: Buffer, dataName: DataID): Unit = - buf.u32(dataIdxValues(dataName)) + private def writeDataIdx(buf: Buffer, dataID: DataID): Unit = + buf.u32(dataIdxValues(dataID)) - private def writeTypeIdxs33(buf: Buffer, typeName: TypeID): Unit = - buf.s33OfUInt(typeIdxValues(typeName)) + private def writeTypeIdxs33(buf: Buffer, typeID: TypeID): Unit = + buf.s33OfUInt(typeIdxValues(typeID)) - private def writeFuncIdx(buf: Buffer, funcName: FunctionID): Unit = - buf.u32(funcIdxValues(funcName)) + private def writeFuncIdx(buf: Buffer, funcID: FunctionID): Unit = + buf.u32(funcIdxValues(funcID)) - private def writeTagIdx(buf: Buffer, tagName: TagID): Unit = - buf.u32(tagIdxValues(tagName)) + private def writeTagIdx(buf: Buffer, tagID: TagID): Unit = + buf.u32(tagIdxValues(tagID)) - private def writeGlobalIdx(buf: Buffer, globalName: GlobalID): Unit = - buf.u32(globalIdxValues(globalName)) + private def writeGlobalIdx(buf: Buffer, globalID: GlobalID): Unit = + buf.u32(globalIdxValues(globalID)) - private def writeLocalIdx(buf: Buffer, localName: LocalID): Unit = { + private def writeLocalIdx(buf: Buffer, localID: LocalID): Unit = { localIdxValues match { - case Some(values) => buf.u32(values(localName)) + case Some(values) => buf.u32(values(localID)) case None => throw new IllegalStateException(s"Local name table is not available") } } - private def writeLabelIdx(buf: Buffer, labelIdx: LabelID): Unit = { - val relativeNumber = labelsInScope.indexOf(Some(labelIdx)) + private def writeLabelIdx(buf: Buffer, labelID: LabelID): Unit = { + val relativeNumber = labelsInScope.indexOf(Some(labelID)) if (relativeNumber < 0) - throw new IllegalStateException(s"Cannot find $labelIdx in scope") + throw new IllegalStateException(s"Cannot find $labelID in scope") buf.u32(relativeNumber) } @@ -423,8 +423,8 @@ class BinaryWriter(module: Module, emitDebugInfo: Boolean) { case instr: RefTypeInstr => writeHeapType(buf, instr.refTypeArgument.heapType) case instr: StructFieldInstr => - writeTypeIdx(buf, instr.structTypeName) - writeFieldIdx(buf, instr.structTypeName, instr.fieldIdx) + writeTypeIdx(buf, instr.structTypeID) + writeFieldIdx(buf, instr.structTypeID, instr.fieldID) // Specific instructions with unique-ish shapes @@ -469,9 +469,9 @@ class BinaryWriter(module: Module, emitDebugInfo: Boolean) { private def writeBlockType(buf: Buffer, blockType: BlockType): Unit = { blockType match { - case BlockType.ValueType(None) => buf.byte(0x40) - case BlockType.ValueType(Some(typ)) => writeType(buf, typ) - case BlockType.FunctionType(typeName) => writeTypeIdxs33(buf, typeName) + case BlockType.ValueType(None) => buf.byte(0x40) + case BlockType.ValueType(Some(tpe)) => writeType(buf, tpe) + case BlockType.FunctionType(typeID) => writeTypeIdxs33(buf, typeID) } } } diff --git a/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/FunctionBuilder.scala b/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/FunctionBuilder.scala index af23b9e..bc2d4b3 100644 --- a/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/FunctionBuilder.scala +++ b/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/FunctionBuilder.scala @@ -28,23 +28,23 @@ final class FunctionBuilder( /** The instructions buffer. */ private val instrs: mutable.ListBuffer[Instr] = mutable.ListBuffer.empty - def setFunctionType(typ: TypeID): Unit = - specialFunctionType = Some(typ) + def setFunctionType(typeID: TypeID): Unit = + specialFunctionType = Some(typeID) - def setResultTypes(typs: List[Type]): Unit = - resultTypes = typs + def setResultTypes(tpes: List[Type]): Unit = + resultTypes = tpes - def setResultType(typ: Type): Unit = - setResultTypes(typ :: Nil) + def setResultType(tpe: Type): Unit = + setResultTypes(tpe :: Nil) - def addParam(originalName: OriginalName, typ: Type): LocalID = { + def addParam(originalName: OriginalName, tpe: Type): LocalID = { val id = new ParamIDImpl(params.size, originalName) - params += Local(id, originalName, typ) + params += Local(id, originalName, tpe) id } - def addParam(name: String, typ: Type): LocalID = - addParam(OriginalName(name), typ) + def addParam(name: String, tpe: Type): LocalID = + addParam(OriginalName(name), tpe) def genLabel(): LabelID = { val label = new LabelIDImpl(labelIdx) @@ -52,14 +52,14 @@ final class FunctionBuilder( label } - def addLocal(originalName: OriginalName, typ: Type): LocalID = { + def addLocal(originalName: OriginalName, tpe: Type): LocalID = { val id = new LocalIDImpl(locals.size, originalName) - locals += Local(id, originalName, typ) + locals += Local(id, originalName, tpe) id } - def addLocal(name: String, typ: Type): LocalID = - addLocal(OriginalName(name), typ) + def addLocal(name: String, tpe: Type): LocalID = + addLocal(OriginalName(name), tpe) // Instructions @@ -83,7 +83,7 @@ final class FunctionBuilder( case FunctionType(Nil, resultType :: Nil) => BlockType.ValueType(resultType) case _ => - BlockType.FunctionType(moduleBuilder.functionTypeToTypeName(sig)) + BlockType.FunctionType(moduleBuilder.functionTypeToTypeID(sig)) } def ifThenElse(blockType: BlockType)(thenp: => Unit)(elsep: => Unit): Unit = { @@ -300,9 +300,9 @@ final class FunctionBuilder( // Final result def buildAndAddToModule(): Function = { - val functionTypeName = specialFunctionType.getOrElse { - val sig = FunctionType(params.toList.map(_.typ), resultTypes) - moduleBuilder.functionTypeToTypeName(sig) + val functionTypeID = specialFunctionType.getOrElse { + val sig = FunctionType(params.toList.map(_.tpe), resultTypes) + moduleBuilder.functionTypeToTypeID(sig) } val dcedInstrs = localDeadCodeEliminationOfInstrs() @@ -310,7 +310,7 @@ final class FunctionBuilder( val func = Function( functionID, functionOriginalName, - functionTypeName, + functionTypeID, params.toList, resultTypes, locals.toList, diff --git a/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/Instructions.scala b/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/Instructions.scala index 2cadb22..97f33be 100644 --- a/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/Instructions.scala +++ b/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/Instructions.scala @@ -48,29 +48,29 @@ object Instructions { val labelArgument: LabelID ) extends Instr(mnemonic, opcode) - /** An instruction with a single `FunctionName` argument. */ + /** An instruction with a single `FunctionID` argument. */ sealed abstract class FuncInstr( mnemonic: String, opcode: Int, val funcArgument: FunctionID ) extends Instr(mnemonic, opcode) - /** An instruction with a single `TypeName` argument. */ + /** An instruction with a single `TypeID` argument. */ sealed abstract class TypeInstr(mnemonic: String, opcode: Int, val typeArgument: TypeID) extends Instr(mnemonic, opcode) - /** An instruction with a single `TagName` argument. */ + /** An instruction with a single `TagID` argument. */ sealed abstract class TagInstr(mnemonic: String, opcode: Int, val tagArgument: TagID) extends Instr(mnemonic, opcode) - /** An instruction with a single `LocalName` argument. */ + /** An instruction with a single `LocalID` argument. */ sealed abstract class LocalInstr( mnemonic: String, opcode: Int, val localArgument: LocalID ) extends Instr(mnemonic, opcode) - /** An instruction with a single `GlobalName` argument. */ + /** An instruction with a single `GlobalID` argument. */ sealed abstract class GlobalInstr( mnemonic: String, opcode: Int, @@ -95,12 +95,12 @@ object Instructions { val refTypeArgument: RefType ) extends Instr(mnemonic, if (refTypeArgument.nullable) nullOpcode else nonNullOpcode) - /** An instruction with a pair of `TypeName`, `StructFieldIdx` arguments. */ + /** An instruction with a pair of `TypeID`, `FieldID` arguments. */ sealed abstract class StructFieldInstr( mnemonic: String, opcode: Int, - val structTypeName: TypeID, - val fieldIdx: FieldID + val structTypeID: TypeID, + val fieldID: FieldID ) extends Instr(mnemonic, opcode) // The actual instruction list @@ -277,7 +277,6 @@ object Instructions { extends BlockTypeLabeledInstr("try", 0x06, i) case class Catch(i: TagID) extends TagInstr("catch", 0x07, i) case object CatchAll extends SimpleInstr("catch_all", 0x19) - // case class Delegate(i: LabelName) extends LabelInstr("delegate", 0x18, i) case class Rethrow(i: LabelID) extends LabelInstr("rethrow", 0x09, i) with StackPolymorphicInstr // Parametric instructions diff --git a/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/ModuleBuilder.scala b/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/ModuleBuilder.scala index 542cf33..eb57067 100644 --- a/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/ModuleBuilder.scala +++ b/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/ModuleBuilder.scala @@ -23,11 +23,11 @@ final class ModuleBuilder(functionSignatureProvider: ModuleBuilder.FunctionTypeP private val elems: mutable.ListBuffer[Element] = new mutable.ListBuffer() private val datas: mutable.ListBuffer[Data] = new mutable.ListBuffer() - def functionTypeToTypeName(sig: FunctionType): TypeID = - functionSignatureProvider.functionTypeToTypeName(sig) + def functionTypeToTypeID(sig: FunctionType): TypeID = + functionSignatureProvider.functionTypeToTypeID(sig) - def addRecType(typ: RecType): Unit = types += typ - def addRecType(typ: SubType): Unit = addRecType(RecType(typ)) + def addRecType(recType: RecType): Unit = types += recType + def addRecType(subType: SubType): Unit = addRecType(RecType(subType)) def addRecType(id: TypeID, originalName: OriginalName, compositeType: CompositeType): Unit = addRecType(SubType(id, originalName, compositeType)) @@ -38,7 +38,7 @@ final class ModuleBuilder(functionSignatureProvider: ModuleBuilder.FunctionTypeP def addImport(imprt: Import): Unit = imports += imprt def addFunction(function: Function): Unit = funcs += function def addTag(tag: Tag): Unit = tags += tag - def addGlobal(typ: Global): Unit = globals += typ + def addGlobal(global: Global): Unit = globals += global def addExport(exprt: Export): Unit = exports += exprt def setStart(startFunction: FunctionID): Unit = start = Some(startFunction) def addElement(element: Element): Unit = elems += element @@ -68,7 +68,7 @@ final class ModuleBuilder(functionSignatureProvider: ModuleBuilder.FunctionTypeP object ModuleBuilder { trait FunctionTypeProvider { - def functionTypeToTypeName(sig: FunctionType): TypeID + def functionTypeToTypeID(sig: FunctionType): TypeID } final class RecTypeBuilder { diff --git a/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/Modules.scala b/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/Modules.scala index 146c81c..9254cec 100644 --- a/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/Modules.scala +++ b/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/Modules.scala @@ -31,20 +31,20 @@ object Modules { sealed abstract class ImportDesc object ImportDesc { - final case class Func(id: FunctionID, originalName: OriginalName, typeName: TypeID) + final case class Func(id: FunctionID, originalName: OriginalName, typeID: TypeID) extends ImportDesc - final case class Global(id: GlobalID, originalName: OriginalName, typ: Type, isMutable: Boolean) + final case class Global(id: GlobalID, originalName: OriginalName, tpe: Type, isMutable: Boolean) extends ImportDesc - final case class Tag(id: TagID, originalName: OriginalName, typeName: TypeID) extends ImportDesc + final case class Tag(id: TagID, originalName: OriginalName, typeID: TypeID) extends ImportDesc } /** A WebAssembly `func`, including names for parameters and locals. */ final case class Function( id: FunctionID, originalName: OriginalName, - typeName: TypeID, + typeID: TypeID, params: List[Local], results: List[Type], locals: List[Local], @@ -55,9 +55,9 @@ object Modules { /** The index space for locals is only accessible inside a function and includes the parameters of * that function, which precede the local variables. */ - final case class Local(id: LocalID, originalName: OriginalName, typ: Type) + final case class Local(id: LocalID, originalName: OriginalName, tpe: Type) - final case class Tag(id: TagID, originalName: OriginalName, typ: TypeID) + final case class Tag(id: TagID, originalName: OriginalName, typeID: TypeID) final case class Data(id: DataID, originalName: OriginalName, bytes: Array[Byte], mode: Data.Mode) @@ -72,12 +72,12 @@ object Modules { final case class Global( id: GlobalID, originalName: OriginalName, - typ: Type, + tpe: Type, init: Expr, isMutable: Boolean ) - final case class Element(typ: Type, init: List[Expr], mode: Element.Mode) + final case class Element(tpe: Type, init: List[Expr], mode: Element.Mode) object Element { sealed abstract class Mode diff --git a/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/TextWriter.scala b/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/TextWriter.scala index 6b24e7f..da4356c 100644 --- a/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/TextWriter.scala +++ b/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/TextWriter.scala @@ -151,10 +151,10 @@ class TextWriter(module: Module) { if (fieldType.isMutable) b.sameLineList( "mut", { - writeType(fieldType.typ) + writeType(fieldType.tpe) } ) - else writeType(fieldType.typ) + else writeType(fieldType.tpe) } def writeField(field: StructField): Unit = { @@ -202,28 +202,28 @@ class TextWriter(module: Module) { b.appendElement("\"" + i.name + "\"") i.desc match { - case ImportDesc.Func(id, _, typeName) => + case ImportDesc.Func(id, _, typeID) => b.sameLineList( "func", { appendName(id) - writeTypeUse(typeName) + writeTypeUse(typeID) } ) - case ImportDesc.Global(id, _, typ, isMutable) => + case ImportDesc.Global(id, _, tpe, isMutable) => b.sameLineList( "global", { appendName(id) if (isMutable) - b.sameLineList("mut", writeType(typ)) + b.sameLineList("mut", writeType(tpe)) else - writeType(typ) + writeType(tpe) } ) - case ImportDesc.Tag(id, _, typeName) => + case ImportDesc.Tag(id, _, typeID) => b.sameLineList( "tag", { appendName(id) - writeTypeUse(typeName) + writeTypeUse(typeID) } ) } @@ -234,8 +234,8 @@ class TextWriter(module: Module) { private def writeSig(params: List[Type], results: List[Type])(implicit b: WatBuilder ): Unit = { - params.foreach(typ => b.sameLineList("param", writeType(typ))) - results.foreach(typ => b.sameLineList("result", writeType(typ))) + params.foreach(tpe => b.sameLineList("param", writeType(tpe))) + results.foreach(tpe => b.sameLineList("result", writeType(tpe))) } private def writeFunction(f: Function)(implicit b: WatBuilder): Unit = { @@ -243,7 +243,7 @@ class TextWriter(module: Module) { b.sameLineList( "param", { appendName(l.id) - writeType(l.typ) + writeType(l.tpe) } ) } @@ -252,7 +252,7 @@ class TextWriter(module: Module) { b.sameLineList( "local", { appendName(l.id) - writeType(l.typ) + writeType(l.tpe) } ) } @@ -267,7 +267,7 @@ class TextWriter(module: Module) { b.newLineList( "func", { appendName(f.id) - writeTypeUse(f.typeName) + writeTypeUse(f.typeID) b.newLine() f.params.foreach(writeParam) @@ -288,7 +288,7 @@ class TextWriter(module: Module) { b.newLineList( "tag", { appendName(tag.id) - writeTypeUse(tag.typ) + writeTypeUse(tag.typeID) } ) } @@ -298,8 +298,8 @@ class TextWriter(module: Module) { "global", { appendName(g.id) if (g.isMutable) - b.sameLineList("mut", writeType(g.typ)) - else writeType(g.typ) + b.sameLineList("mut", writeType(g.tpe)) + else writeType(g.tpe) g.init.instr.foreach(writeInstr) } ) @@ -310,15 +310,15 @@ class TextWriter(module: Module) { "export", { b.appendElement("\"" + e.name + "\"") e.desc match { - case ExportDesc.Func(funcName, _) => + case ExportDesc.Func(id, _) => b.sameLineList( "func", - { appendName(funcName) } + { appendName(id) } ) - case ExportDesc.Global(globalName, _) => + case ExportDesc.Global(id, _) => b.sameLineList( "global", - { appendName(globalName) } + { appendName(id) } ) } } @@ -339,7 +339,7 @@ class TextWriter(module: Module) { case Element.Mode.Passive => () case Element.Mode.Declarative => b.appendElement("declare") } - writeType(element.typ) + writeType(element.tpe) element.init.foreach { item => b.newLineList( "item", @@ -362,14 +362,14 @@ class TextWriter(module: Module) { ) } - private def writeTypeUse(typeName: TypeID)(implicit b: WatBuilder): Unit = { - b.sameLineList("type", appendName(typeName)) + private def writeTypeUse(typeID: TypeID)(implicit b: WatBuilder): Unit = { + b.sameLineList("type", appendName(typeID)) } - private def writeType(typ: StorageType)(implicit b: WatBuilder): Unit = { - typ match { - case typ: SimpleType => b.appendElement(typ.textName) - case typ: PackedType => b.appendElement(typ.textName) + private def writeType(tpe: StorageType)(implicit b: WatBuilder): Unit = { + tpe match { + case tpe: SimpleType => b.appendElement(tpe.textName) + case tpe: PackedType => b.appendElement(tpe.textName) case RefType(true, heapType: HeapType.AbsHeapType) => b.appendElement(heapType.nullableRefTextName) @@ -387,7 +387,7 @@ class TextWriter(module: Module) { private def writeHeapType(heapType: HeapType)(implicit b: WatBuilder): Unit = { heapType match { - case HeapType.Type(typeName) => appendName(typeName) + case HeapType.Type(typeID) => appendName(typeID) case heapType: HeapType.AbsHeapType => b.appendElement(heapType.textName) } } @@ -402,11 +402,11 @@ class TextWriter(module: Module) { private def writeBlockType(blockType: BlockType)(implicit b: WatBuilder): Unit = { blockType match { - case BlockType.FunctionType(name) => - writeTypeUse(name) - case BlockType.ValueType(optTy) => - for (ty <- optTy) - b.sameLineList("result", writeType(ty)) + case BlockType.FunctionType(typeID) => + writeTypeUse(typeID) + case BlockType.ValueType(optType) => + for (tpe <- optType) + b.sameLineList("result", writeType(tpe)) } } @@ -470,8 +470,8 @@ class TextWriter(module: Module) { case instr: RefTypeInstr => writeType(instr.refTypeArgument) case instr: StructFieldInstr => - appendName(instr.structTypeName) - appendName(instr.structTypeName, instr.fieldIdx) + appendName(instr.structTypeID) + appendName(instr.structTypeID, instr.fieldID) // Specific instructions with unique-ish shapes diff --git a/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/Types.scala b/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/Types.scala index 79cc975..378c7f6 100644 --- a/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/Types.scala +++ b/wasm/src/main/scala/org/scalajs/linker/backend/webassembly/Types.scala @@ -39,17 +39,17 @@ object Types { object RefType { - /** Builds a non-nullable `(ref ht)` for the given `ht`. */ - def apply(ht: HeapType): RefType = RefType(false, ht) + /** Builds a non-nullable `(ref heapType)` for the given `heapType`. */ + def apply(heapType: HeapType): RefType = RefType(false, heapType) - /** Builds a non-nullable `(ref typ)` for the given `typ`. */ - def apply(typ: TypeID): RefType = apply(HeapType(typ)) + /** Builds a non-nullable `(ref typeID)` for the given `typeID`. */ + def apply(typeID: TypeID): RefType = apply(HeapType(typeID)) - /** Builds a nullable `(ref null ht)` for the given `ht`. */ - def nullable(ht: HeapType): RefType = RefType(true, ht) + /** Builds a nullable `(ref null heapType)` for the given `heapType`. */ + def nullable(heapType: HeapType): RefType = RefType(true, heapType) - /** Builds a nullable `(ref null typ)` for the given `typ`. */ - def nullable(typ: TypeID): RefType = nullable(HeapType(typ)) + /** Builds a nullable `(ref null typeID)` for the given `typeID`. */ + def nullable(typeID: TypeID): RefType = nullable(HeapType(typeID)) /** `(ref any)`. */ val any: RefType = apply(HeapType.Any) @@ -82,7 +82,7 @@ object Types { object HeapType { /** Reference to a named composite type. */ - final case class Type(val typ: TypeID) extends HeapType + final case class Type(typeID: TypeID) extends HeapType /** A WebAssembly `absheaptype`. */ sealed abstract class AbsHeapType( @@ -103,8 +103,8 @@ object Types { case object NoFunc extends AbsHeapType("nofunc", "nullfuncref", 0x73) case object NoExn extends AbsHeapType("noexn", "nullexnref", 0x74) - def apply(typ: TypeID): HeapType.Type = - HeapType.Type(typ) + def apply(typeID: TypeID): HeapType.Type = + HeapType.Type(typeID) } /** A WebAssembly `rectype`. */ @@ -153,16 +153,16 @@ object Types { final case class ArrayType(fieldType: FieldType) extends CompositeType /** A WebAssembly `fieldtype`. */ - final case class FieldType(typ: StorageType, isMutable: Boolean) + final case class FieldType(tpe: StorageType, isMutable: Boolean) object StructField { def apply( id: FieldID, originalName: OriginalName, - typ: StorageType, + tpe: StorageType, isMutable: Boolean ): StructField = { - StructField(id, originalName, FieldType(typ, isMutable)) + StructField(id, originalName, FieldType(tpe, isMutable)) } } }