[Wasm] Remove buildInstr without location and fix usages

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