diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt index 1ad239aef10..c87fc81a297 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt @@ -47,7 +47,11 @@ class BodyGenerator( private val unitGetInstance by lazy { backendContext.findUnitGetInstanceFunction() } fun WasmExpressionBuilder.buildGetUnit() { - buildInstr(WasmOp.GET_UNIT, WasmImmediate.FuncIdx(context.referenceFunction(unitGetInstance.symbol))) + buildInstr( + WasmOp.GET_UNIT, + SourceLocation.NoLocation("GET_UNIT"), + WasmImmediate.FuncIdx(context.referenceFunction(unitGetInstance.symbol)) + ) } private val anyConstructor by lazy { @@ -107,7 +111,7 @@ class BodyGenerator( withLocation(irVararg.getSourceLocation()) { body.buildConstI32(0, location) body.buildConstI32(irVararg.elements.size, location) - body.buildInstr(WasmOp.ARRAY_NEW_DATA, wasmArrayType, WasmImmediate.DataIdx(constantArrayId)) + body.buildInstr(WasmOp.ARRAY_NEW_DATA, location, wasmArrayType, WasmImmediate.DataIdx(constantArrayId)) } return true } @@ -119,7 +123,7 @@ class BodyGenerator( } val length = WasmImmediate.ConstI32(irVararg.elements.size) - body.buildInstr(WasmOp.ARRAY_NEW_FIXED, wasmArrayType, length) + body.buildInstr(WasmOp.ARRAY_NEW_FIXED, irVararg.getSourceLocation(), wasmArrayType, length) } override fun visitVararg(expression: IrVararg) { @@ -181,21 +185,22 @@ class BodyGenerator( override fun visitGetField(expression: IrGetField) { val field: IrField = expression.symbol.owner val receiver: IrExpression? = expression.receiver + val location = expression.getSourceLocation() if (receiver != null) { generateExpression(receiver) if (backendContext.inlineClassesUtils.isClassInlineLike(field.parentAsClass)) { // Unboxed inline class instance is already represented as backing field. // Doing nothing. } else { - generateInstanceFieldAccess(field) + generateInstanceFieldAccess(field, location) } } else { - body.buildGetGlobal(context.referenceGlobalField(field.symbol), expression.getSourceLocation()) + body.buildGetGlobal(context.referenceGlobalField(field.symbol), location) body.commentPreviousInstr { "type: ${field.type.render()}" } } } - private fun generateInstanceFieldAccess(field: IrField) { + private fun generateInstanceFieldAccess(field: IrField, location: SourceLocation) { val opcode = when (field.type) { irBuiltIns.charType -> WasmOp.STRUCT_GET_U @@ -210,6 +215,7 @@ class BodyGenerator( body.buildInstr( opcode, + location, WasmImmediate.GcType(context.referenceGcType(field.parentAsClass.symbol)), WasmImmediate.StructFieldIdx(context.getStructFieldRef(field)) ) @@ -275,20 +281,20 @@ class BodyGenerator( } val wasmGcType: WasmSymbol = context.referenceGcType(klassSymbol) + val location = expression.getSourceLocation() if (klass.getWasmArrayAnnotation() != null) { require(expression.valueArgumentsCount == 1) { "@WasmArrayOf constructs must have exactly one argument" } generateExpression(expression.getValueArgument(0)!!) body.buildInstr( WasmOp.ARRAY_NEW_DEFAULT, + location, WasmImmediate.GcType(wasmGcType) ) body.commentPreviousInstr { "@WasmArrayOf ctor call: ${klass.fqNameWhenAvailable}" } return } - val location = expression.getSourceLocation() - if (expression.symbol.owner.hasWasmPrimitiveConstructorAnnotation()) { generateAnyParameters(klassSymbol, location) for (i in 0 until expression.valueArgumentsCount) { @@ -326,7 +332,7 @@ class BodyGenerator( body.commentGroupStart { "Object creation prefix" } withNoLocation("Constructor preamble") { body.buildGetLocal(thisParameter, location) - body.buildInstr(WasmOp.REF_IS_NULL) + body.buildInstr(WasmOp.REF_IS_NULL, location) body.buildIf("this_init") generateAnyParameters(parentClass.symbol, location) val irFields: List = parentClass.allFields(backendContext.irBuiltIns) @@ -435,7 +441,7 @@ class BodyGenerator( body.buildStructGet(context.referenceGcType(klass.symbol), WasmSymbol(0), location) body.buildStructGet(context.referenceVTableGcType(klass.symbol), WasmSymbol(vfSlot), location) - body.buildInstr(WasmOp.CALL_REF, WasmImmediate.TypeIdx(context.referenceFunctionType(function.symbol))) + body.buildInstr(WasmOp.CALL_REF, location, WasmImmediate.TypeIdx(context.referenceFunctionType(function.symbol))) body.commentGroupEnd() } else { val symbol = klass.symbol @@ -453,7 +459,7 @@ class BodyGenerator( .indexOfFirst { it.function == function } body.buildStructGet(context.referenceVTableGcType(symbol), WasmSymbol(vfSlot), location) - body.buildInstr(WasmOp.CALL_REF, WasmImmediate.TypeIdx(context.referenceFunctionType(function.symbol))) + body.buildInstr(WasmOp.CALL_REF, location, WasmImmediate.TypeIdx(context.referenceFunctionType(function.symbol))) body.commentGroupEnd() } else { // We came here for a call to an interface method which interface is not implemented anywhere, @@ -542,8 +548,8 @@ class BodyGenerator( body.buildStructGet(context.referenceGcType(irBuiltIns.anyClass), WasmSymbol(1), location) body.buildBrInstr(WasmOp.BR_ON_CAST_FAIL_DEPRECATED, innerLabel, classITable, location) body.buildStructGet(classITable, context.referenceClassITableInterfaceSlot(irInterface.symbol), location) - body.buildInstr(WasmOp.REF_IS_NULL) - body.buildInstr(WasmOp.I32_EQZ) + body.buildInstr(WasmOp.REF_IS_NULL, location) + body.buildInstr(WasmOp.I32_EQZ, location) body.buildBr(outerLabel, location) } body.buildDrop(location) @@ -585,7 +591,7 @@ class BodyGenerator( val field = getInlineClassBackingField(klass) generateRefNullCast(fromType, toType, location) - generateInstanceFieldAccess(field) + generateInstanceFieldAccess(field, location) } wasmSymbols.unsafeGetScratchRawMemory -> { @@ -596,7 +602,7 @@ class BodyGenerator( val immediate = WasmImmediate.GcType( context.referenceGcType(call.getTypeArgument(0)!!.getRuntimeClass(irBuiltIns).symbol) ) - body.buildInstr(WasmOp.ARRAY_COPY, immediate, immediate) + body.buildInstr(WasmOp.ARRAY_COPY, location, immediate, immediate) } wasmSymbols.stringGetPoolSize -> { @@ -607,7 +613,7 @@ class BodyGenerator( val arrayGcType = WasmImmediate.GcType( context.referenceGcType(call.getTypeArgument(0)!!.getRuntimeClass(irBuiltIns).symbol) ) - body.buildInstr(WasmOp.ARRAY_NEW_DATA, arrayGcType, WasmImmediate.DataIdx(0)) + body.buildInstr(WasmOp.ARRAY_NEW_DATA, location, arrayGcType, WasmImmediate.DataIdx(0)) } else -> { @@ -892,10 +898,11 @@ class BodyGenerator( val opString = function.getWasmOpAnnotation() if (opString != null) { + val location = call.getSourceLocation() val op = WasmOp.valueOf(opString) when (op.immediates.size) { 0 -> { - body.buildInstr(op) + body.buildInstr(op, location) } 1 -> { fun getReferenceGcType(): WasmSymbol { @@ -920,7 +927,7 @@ class BodyGenerator( error("Immediate $imm is unsupported") } ) - body.buildInstr(op, *immediates) + body.buildInstr(op, location, *immediates) } else -> error("Op $opString is unsupported") diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt index 4581c23bfa1..07b7c571205 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt @@ -166,7 +166,7 @@ class DeclarationGenerator( // TODO: Redesign construction scheme. if (declaration is IrConstructor) { exprGen.buildGetLocal(/*implicit this*/ function.locals[0], SourceLocation.NoLocation("Get implicit dispatch receiver")) - exprGen.buildInstr(WasmOp.RETURN) + exprGen.buildInstr(WasmOp.RETURN, SourceLocation.NoLocation("Implicit return from constructor")) } // Add unreachable if function returns something but not as a last instruction. @@ -261,7 +261,7 @@ class DeclarationGenerator( val location = SourceLocation.NoLocation("Create instance of vtable struct") metadata.virtualMethods.forEachIndexed { i, method -> if (method.function.modality != Modality.ABSTRACT) { - buildInstr(WasmOp.REF_FUNC, WasmImmediate.FuncIdx(context.referenceFunction(method.function.symbol))) + buildInstr(WasmOp.REF_FUNC, location, WasmImmediate.FuncIdx(context.referenceFunction(method.function.symbol))) } else { check(allowIncompleteImplementations) { "Cannot find class implementation of method ${method.signature} in class ${klass.fqNameWhenAvailable}" @@ -309,7 +309,7 @@ class DeclarationGenerator( if (classMethod != null) { val functionTypeReference = context.referenceFunction(classMethod.function.symbol) - buildInstr(WasmOp.REF_FUNC, WasmImmediate.FuncIdx(functionTypeReference)) + buildInstr(WasmOp.REF_FUNC, location, WasmImmediate.FuncIdx(functionTypeReference)) } else { //This erased by DCE so abstract version appeared in non-abstract class buildRefNull(WasmHeapType.Type(context.referenceFunctionType(method.function.symbol)), location) @@ -507,7 +507,7 @@ fun generateConstExpression(expression: IrConst<*>, body: WasmExpressionBuilder, when (val kind = expression.kind) { is IrConstKind.Null -> { val bottomType = if (expression.type.getClass()?.isExternal == true) WasmRefNullExternrefType else WasmRefNullNoneType - body.buildInstr(WasmOp.REF_NULL, WasmImmediate.HeapType(bottomType)) + body.buildInstr(WasmOp.REF_NULL, location, WasmImmediate.HeapType(bottomType)) } is IrConstKind.Boolean -> body.buildConstI32(if (kind.valueOf(expression)) 1 else 0, location) is IrConstKind.Byte -> body.buildConstI32(kind.valueOf(expression).toInt(), location) diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/OptimisedWhenGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/OptimisedWhenGenerator.kt index 8c5bc45cdaa..74c5cc6ad3b 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/OptimisedWhenGenerator.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/OptimisedWhenGenerator.kt @@ -256,7 +256,7 @@ private fun BodyGenerator.createBinaryTable( val (case, result) = sortedCases[fromIncl] body.buildGetLocal(selectorLocal, location) body.buildConstI32(case, location) - body.buildInstr(WasmOp.I32_EQ) + body.buildInstr(WasmOp.I32_EQ, location) body.buildIf("binary_tree_branch", resultType) thenBody(result) body.buildElse() @@ -269,7 +269,7 @@ private fun BodyGenerator.createBinaryTable( body.buildGetLocal(selectorLocal, location) body.buildConstI32(sortedCases[border].first, location) - body.buildInstr(WasmOp.I32_LT_S) + body.buildInstr(WasmOp.I32_LT_S, location) body.buildIf("binary_tree_node", resultType) createBinaryTable(selectorLocal, resultType, sortedCases, fromIncl, border, thenBody, elseBody) body.buildElse() @@ -322,10 +322,11 @@ private fun BodyGenerator.genTableIntSwitch( body.buildGetLocal(selectorLocal, location) if (shift != 0) { body.buildConstI32(shift, location) - body.buildInstr(WasmOp.I32_SUB) + body.buildInstr(WasmOp.I32_SUB, location) } body.buildInstr( WasmOp.BR_TABLE, + location, WasmImmediate.LabelIdxVector(brTable), WasmImmediate.LabelIdx(branches.size) ) diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/WasmExpressionBuilder.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/WasmExpressionBuilder.kt index 62ae816675d..f715e27b142 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/WasmExpressionBuilder.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/WasmExpressionBuilder.kt @@ -10,10 +10,6 @@ import org.jetbrains.kotlin.wasm.ir.source.location.SourceLocation abstract class WasmExpressionBuilder { abstract fun buildInstr(op: WasmOp, location: SourceLocation, vararg immediates: WasmImmediate) - fun buildInstr(op: WasmOp, vararg immediates: WasmImmediate) { - buildInstr(op, SourceLocation.TBDLocation, *immediates) - } - abstract var numberOfNestedBlocks: Int fun buildConstI32(value: Int, location: SourceLocation) { @@ -43,7 +39,7 @@ abstract class WasmExpressionBuilder { @Suppress("UNUSED_PARAMETER") inline fun buildBlock(label: String?, resultType: WasmType? = null, body: (Int) -> Unit) { numberOfNestedBlocks++ - buildInstr(WasmOp.BLOCK, WasmImmediate.BlockType.Value(resultType)) + buildInstr(WasmOp.BLOCK, SourceLocation.NoLocation("BLOCK"), WasmImmediate.BlockType.Value(resultType)) body(numberOfNestedBlocks) buildEnd() } @@ -51,30 +47,34 @@ abstract class WasmExpressionBuilder { @Suppress("UNUSED_PARAMETER") inline fun buildLoop(label: String?, resultType: WasmType? = null, body: (Int) -> Unit) { numberOfNestedBlocks++ - buildInstr(WasmOp.LOOP, WasmImmediate.BlockType.Value(resultType)) + buildInstr(WasmOp.LOOP, SourceLocation.NoLocation("LOOP"), WasmImmediate.BlockType.Value(resultType)) body(numberOfNestedBlocks) buildEnd() } + private fun buildInstrWithNoLocation(op: WasmOp, vararg immediates: WasmImmediate) { + buildInstr(op, SourceLocation.NoLocation(op.mnemonic), *immediates) + } + @Suppress("UNUSED_PARAMETER") fun buildIf(label: String?, resultType: WasmType? = null) { numberOfNestedBlocks++ - buildInstr(WasmOp.IF, WasmImmediate.BlockType.Value(resultType)) + buildInstrWithNoLocation(WasmOp.IF, WasmImmediate.BlockType.Value(resultType)) } fun buildElse() { - buildInstr(WasmOp.ELSE) + buildInstrWithNoLocation(WasmOp.ELSE) } fun buildBlock(resultType: WasmType? = null): Int { numberOfNestedBlocks++ - buildInstr(WasmOp.BLOCK, WasmImmediate.BlockType.Value(resultType)) + buildInstrWithNoLocation(WasmOp.BLOCK, WasmImmediate.BlockType.Value(resultType)) return numberOfNestedBlocks } fun buildEnd() { numberOfNestedBlocks-- - buildInstr(WasmOp.END) + buildInstrWithNoLocation(WasmOp.END) } @@ -101,11 +101,11 @@ abstract class WasmExpressionBuilder { @Suppress("UNUSED_PARAMETER") fun buildTry(label: String?, resultType: WasmType? = null) { numberOfNestedBlocks++ - buildInstr(WasmOp.TRY, WasmImmediate.BlockType.Value(resultType)) + buildInstrWithNoLocation(WasmOp.TRY, WasmImmediate.BlockType.Value(resultType)) } fun buildCatch(tagIdx: Int) { - buildInstr(WasmOp.CATCH, WasmImmediate.TagIdx(tagIdx)) + buildInstrWithNoLocation(WasmOp.CATCH, WasmImmediate.TagIdx(tagIdx)) } fun buildBrIf(absoluteBlockLevel: Int, location: SourceLocation) {