[Wasm] Require location for buildConstI32 and fix all usages

This commit is contained in:
Zalim Bashorov
2022-12-06 20:34:47 +01:00
parent cdc1d66b1f
commit f2f4c63720
6 changed files with 147 additions and 127 deletions
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.wasm.utils.isCanonical
import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.lower.PrimaryConstructorLowering import org.jetbrains.kotlin.ir.backend.js.lower.PrimaryConstructorLowering
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.getSourceLocation
import org.jetbrains.kotlin.ir.backend.js.utils.erasedUpperBound import org.jetbrains.kotlin.ir.backend.js.utils.erasedUpperBound
import org.jetbrains.kotlin.ir.backend.js.utils.findUnitGetInstanceFunction import org.jetbrains.kotlin.ir.backend.js.utils.findUnitGetInstanceFunction
import org.jetbrains.kotlin.ir.backend.js.utils.isDispatchReceiver import org.jetbrains.kotlin.ir.backend.js.utils.isDispatchReceiver
@@ -97,9 +98,11 @@ class BodyGenerator(
val constantArrayId = context.referenceConstantArray(resource) val constantArrayId = context.referenceConstantArray(resource)
body.buildConstI32(0) withLocation(irVararg.getSourceLocation()) {
body.buildConstI32(irVararg.elements.size) 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, wasmArrayType, WasmImmediate.DataIdx(constantArrayId))
}
return true return true
} }
@@ -125,7 +128,7 @@ class BodyGenerator(
check(wasmArrayType != null) check(wasmArrayType != null)
generateAnyParameters(arrayClass.symbol) generateAnyParameters(arrayClass.symbol, expression.getSourceLocation())
if (!tryGenerateConstVarargArray(expression, wasmArrayType)) tryGenerateVarargArray(expression, wasmArrayType) if (!tryGenerateConstVarargArray(expression, wasmArrayType)) tryGenerateVarargArray(expression, wasmArrayType)
body.buildStructNew(context.referenceGcType(expression.type.getRuntimeClass(irBuiltIns).symbol)) body.buildStructNew(context.referenceGcType(expression.type.getRuntimeClass(irBuiltIns).symbol))
} }
@@ -274,7 +277,7 @@ class BodyGenerator(
} }
if (expression.symbol.owner.hasWasmPrimitiveConstructorAnnotation()) { if (expression.symbol.owner.hasWasmPrimitiveConstructorAnnotation()) {
generateAnyParameters(klassSymbol) generateAnyParameters(klassSymbol, expression.getSourceLocation())
for (i in 0 until expression.valueArgumentsCount) { for (i in 0 until expression.valueArgumentsCount) {
generateExpression(expression.getValueArgument(i)!!) generateExpression(expression.getValueArgument(i)!!)
} }
@@ -287,7 +290,7 @@ class BodyGenerator(
generateCall(expression) generateCall(expression)
} }
private fun generateAnyParameters(klassSymbol: IrClassSymbol) { private fun generateAnyParameters(klassSymbol: IrClassSymbol, location: SourceLocation) {
//ClassITable and VTable load //ClassITable and VTable load
body.commentGroupStart { "Any parameters" } body.commentGroupStart { "Any parameters" }
body.buildGetGlobal(context.referenceGlobalVTable(klassSymbol)) body.buildGetGlobal(context.referenceGlobalVTable(klassSymbol))
@@ -298,7 +301,7 @@ class BodyGenerator(
} }
body.buildConstI32Symbol(context.referenceClassId(klassSymbol)) body.buildConstI32Symbol(context.referenceClassId(klassSymbol))
body.buildConstI32(0) // Any::_hashCode body.buildConstI32(0, location) // Any::_hashCode
body.commentGroupEnd() body.commentGroupEnd()
} }
@@ -311,7 +314,7 @@ class BodyGenerator(
body.buildGetLocal(thisParameter) body.buildGetLocal(thisParameter)
body.buildInstr(WasmOp.REF_IS_NULL) body.buildInstr(WasmOp.REF_IS_NULL)
body.buildIf("this_init") body.buildIf("this_init")
generateAnyParameters(parentClass.symbol) generateAnyParameters(parentClass.symbol, SourceLocation.NoLocation("Constructor preamble"))
val irFields: List<IrField> = parentClass.allFields(backendContext.irBuiltIns) val irFields: List<IrField> = parentClass.allFields(backendContext.irBuiltIns)
irFields.forEachIndexed { index, field -> irFields.forEachIndexed { index, field ->
if (index > 1) { if (index > 1) {
@@ -339,7 +342,7 @@ class BodyGenerator(
private fun generateBox(expression: IrExpression, type: IrType) { private fun generateBox(expression: IrExpression, type: IrType) {
val klassSymbol = type.getRuntimeClass(irBuiltIns).symbol val klassSymbol = type.getRuntimeClass(irBuiltIns).symbol
generateAnyParameters(klassSymbol) generateAnyParameters(klassSymbol, expression.getSourceLocation())
generateExpression(expression) generateExpression(expression)
body.buildStructNew(context.referenceGcType(klassSymbol)) body.buildStructNew(context.referenceGcType(klassSymbol))
body.commentPreviousInstr { "box" } body.commentPreviousInstr { "box" }
@@ -459,14 +462,14 @@ class BodyGenerator(
} }
} }
private fun generateRefTest(fromType: IrType, toType: IrType) { private fun generateRefTest(fromType: IrType, toType: IrType, location: SourceLocation) {
if (!isDownCastAlwaysSuccessInRuntime(fromType, toType)) { if (!isDownCastAlwaysSuccessInRuntime(fromType, toType)) {
body.buildRefTestStatic( body.buildRefTestStatic(
toType = context.referenceGcType(toType.getRuntimeClass(irBuiltIns).symbol) toType = context.referenceGcType(toType.getRuntimeClass(irBuiltIns).symbol)
) )
} else { } else {
body.buildDrop() body.buildDrop()
body.buildConstI32(1) body.buildConstI32(1, location)
} }
} }
@@ -488,6 +491,7 @@ class BodyGenerator(
return true return true
} }
withLocation(call.getSourceLocation()) {
when (function.symbol) { when (function.symbol) {
wasmSymbols.wasmClassId -> { wasmSymbols.wasmClassId -> {
val klass = call.getTypeArgument(0)!!.getClass() val klass = call.getTypeArgument(0)!!.getClass()
@@ -522,11 +526,11 @@ class BodyGenerator(
body.buildBr(outerLabel) body.buildBr(outerLabel)
} }
body.buildDrop() body.buildDrop()
body.buildConstI32(0) body.buildConstI32(0, location)
} }
} else { } else {
body.buildDrop() body.buildDrop()
body.buildConstI32(0) body.buildConstI32(0, location)
} }
} }
@@ -540,7 +544,8 @@ class BodyGenerator(
wasmSymbols.refTest -> { wasmSymbols.refTest -> {
generateRefTest( generateRefTest(
fromType = call.getValueArgument(0)!!.type, fromType = call.getValueArgument(0)!!.type,
toType = call.getTypeArgument(0)!! toType = call.getTypeArgument(0)!!,
location
) )
} }
@@ -568,9 +573,12 @@ class BodyGenerator(
} }
wasmSymbols.unsafeGetScratchRawMemory -> { wasmSymbols.unsafeGetScratchRawMemory -> {
body.buildConstI32Symbol(context.scratchMemAddr) body.buildConstI32Symbol(context.scratchMemAddr)
} }
wasmSymbols.wasmArrayCopy -> { wasmSymbols.wasmArrayCopy -> {
val immediate = WasmImmediate.GcType( val immediate = WasmImmediate.GcType(
context.referenceGcType(call.getTypeArgument(0)!!.getRuntimeClass(irBuiltIns).symbol) context.referenceGcType(call.getTypeArgument(0)!!.getRuntimeClass(irBuiltIns).symbol)
@@ -593,6 +601,7 @@ class BodyGenerator(
return false return false
} }
} }
}
return true return true
} }
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.name.parentOrNull import org.jetbrains.kotlin.name.parentOrNull
import org.jetbrains.kotlin.wasm.ir.* import org.jetbrains.kotlin.wasm.ir.*
import org.jetbrains.kotlin.wasm.ir.source.location.withLocation import org.jetbrains.kotlin.wasm.ir.source.location.withLocation
import org.jetbrains.kotlin.wasm.ir.source.location.withNoLocation
class DeclarationGenerator( class DeclarationGenerator(
val context: WasmModuleCodegenContext, val context: WasmModuleCodegenContext,
@@ -472,8 +473,10 @@ class DeclarationGenerator(
} }
} }
fun generateDefaultInitializerForType(type: WasmType, g: WasmExpressionBuilder) = when (type) { fun generateDefaultInitializerForType(type: WasmType, g: WasmExpressionBuilder) =
WasmI32 -> g.buildConstI32(0) withNoLocation("Default initializer, usually don't require location") {
when (type) {
WasmI32 -> g.buildConstI32(0, location)
WasmI64 -> g.buildConstI64(0) WasmI64 -> g.buildConstI64(0)
WasmF32 -> g.buildConstF32(0f) WasmF32 -> g.buildConstF32(0f)
WasmF64 -> g.buildConstF64(0.0) WasmF64 -> g.buildConstF64(0.0)
@@ -484,7 +487,8 @@ fun generateDefaultInitializerForType(type: WasmType, g: WasmExpressionBuilder)
is WasmExternRef -> g.buildRefNull(WasmHeapType.Simple.Extern) is WasmExternRef -> g.buildRefNull(WasmHeapType.Simple.Extern)
WasmUnreachableType -> error("Unreachable type can't be initialized") WasmUnreachableType -> error("Unreachable type can't be initialized")
else -> error("Unknown value type ${type.name}") else -> error("Unknown value type ${type.name}")
} }
}
fun IrFunction.getEffectiveValueParameters(): List<IrValueParameter> { fun IrFunction.getEffectiveValueParameters(): List<IrValueParameter> {
val implicitThis = if (this is IrConstructor) parentAsClass.thisReceiver!! else null val implicitThis = if (this is IrConstructor) parentAsClass.thisReceiver!! else null
@@ -502,12 +506,12 @@ fun generateConstExpression(expression: IrConst<*>, body: WasmExpressionBuilder,
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, WasmImmediate.HeapType(bottomType))
} }
is IrConstKind.Boolean -> body.buildConstI32(if (kind.valueOf(expression)) 1 else 0) is IrConstKind.Boolean -> body.buildConstI32(if (kind.valueOf(expression)) 1 else 0, location)
is IrConstKind.Byte -> body.buildConstI32(kind.valueOf(expression).toInt()) is IrConstKind.Byte -> body.buildConstI32(kind.valueOf(expression).toInt(), location)
is IrConstKind.Short -> body.buildConstI32(kind.valueOf(expression).toInt()) is IrConstKind.Short -> body.buildConstI32(kind.valueOf(expression).toInt(), location)
is IrConstKind.Int -> body.buildConstI32(kind.valueOf(expression)) is IrConstKind.Int -> body.buildConstI32(kind.valueOf(expression), location)
is IrConstKind.Long -> body.buildConstI64(kind.valueOf(expression)) is IrConstKind.Long -> body.buildConstI64(kind.valueOf(expression))
is IrConstKind.Char -> body.buildConstI32(kind.valueOf(expression).code) is IrConstKind.Char -> body.buildConstI32(kind.valueOf(expression).code, location)
is IrConstKind.Float -> body.buildConstF32(kind.valueOf(expression)) is IrConstKind.Float -> body.buildConstF32(kind.valueOf(expression))
is IrConstKind.Double -> body.buildConstF64(kind.valueOf(expression)) is IrConstKind.Double -> body.buildConstF64(kind.valueOf(expression))
is IrConstKind.String -> { is IrConstKind.String -> {
@@ -516,7 +520,7 @@ fun generateConstExpression(expression: IrConst<*>, body: WasmExpressionBuilder,
body.commentGroupStart { "const string: \"$stringValue\"" } body.commentGroupStart { "const string: \"$stringValue\"" }
body.buildConstI32Symbol(literalPoolId) body.buildConstI32Symbol(literalPoolId)
body.buildConstI32Symbol(literalAddress) body.buildConstI32Symbol(literalAddress)
body.buildConstI32(stringValue.length) body.buildConstI32(stringValue.length, location)
body.buildCall(context.referenceFunction(context.backendContext.wasmSymbols.stringGetLiteral), location) body.buildCall(context.referenceFunction(context.backendContext.wasmSymbols.stringGetLiteral), location)
body.commentGroupEnd() body.commentGroupEnd()
} }
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.ir.types.isUnit
import org.jetbrains.kotlin.ir.util.isElseBranch import org.jetbrains.kotlin.ir.util.isElseBranch
import org.jetbrains.kotlin.wasm.ir.* import org.jetbrains.kotlin.wasm.ir.*
import org.jetbrains.kotlin.wasm.ir.source.location.SourceLocation
private class ExtractedWhenCondition<T>(val condition: IrCall, val const: IrConst<T>) private class ExtractedWhenCondition<T>(val condition: IrCall, val const: IrConst<T>)
private class ExtractedWhenBranch<T>(val conditions: List<ExtractedWhenCondition<T>>, val expression: IrExpression) private class ExtractedWhenBranch<T>(val conditions: List<ExtractedWhenCondition<T>>, val expression: IrExpression)
@@ -134,11 +135,13 @@ private fun BodyGenerator.createBinaryTable(selectorLocal: WasmLocal, intBranche
intBranches.flatMapIndexedTo(sortedCaseToBranchIndex) { index, branch -> branch.conditions.map { it.const.value to index } } intBranches.flatMapIndexedTo(sortedCaseToBranchIndex) { index, branch -> branch.conditions.map { it.const.value to index } }
sortedCaseToBranchIndex.sortBy { it.first } sortedCaseToBranchIndex.sortBy { it.first }
val location = SourceLocation.NoLocation("When's binary search infra")
val thenBody = { result: Int -> val thenBody = { result: Int ->
body.buildConstI32(result) body.buildConstI32(result, location)
} }
val elseBody: () -> Unit = { val elseBody: () -> Unit = {
body.buildConstI32(intBranches.size) body.buildConstI32(intBranches.size, location)
} }
createBinaryTable(selectorLocal, WasmI32, sortedCaseToBranchIndex, 0, sortedCaseToBranchIndex.size, thenBody, elseBody) createBinaryTable(selectorLocal, WasmI32, sortedCaseToBranchIndex, 0, sortedCaseToBranchIndex.size, thenBody, elseBody)
} }
@@ -240,11 +243,13 @@ private fun <T> BodyGenerator.createBinaryTable(
thenBody: (T) -> Unit, thenBody: (T) -> Unit,
elseBody: () -> Unit elseBody: () -> Unit
) { ) {
val location = SourceLocation.NoLocation("When's binary search infra")
val size = toExcl - fromIncl val size = toExcl - fromIncl
if (size == 1) { if (size == 1) {
val (case, result) = sortedCases[fromIncl] val (case, result) = sortedCases[fromIncl]
body.buildGetLocal(selectorLocal) body.buildGetLocal(selectorLocal)
body.buildConstI32(case) body.buildConstI32(case, location)
body.buildInstr(WasmOp.I32_EQ) body.buildInstr(WasmOp.I32_EQ)
body.buildIf("binary_tree_branch", resultType) body.buildIf("binary_tree_branch", resultType)
thenBody(result) thenBody(result)
@@ -257,7 +262,7 @@ private fun <T> BodyGenerator.createBinaryTable(
val border = fromIncl + size / 2 val border = fromIncl + size / 2
body.buildGetLocal(selectorLocal) body.buildGetLocal(selectorLocal)
body.buildConstI32(sortedCases[border].first) body.buildConstI32(sortedCases[border].first, location)
body.buildInstr(WasmOp.I32_LT_S) body.buildInstr(WasmOp.I32_LT_S)
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)
@@ -299,6 +304,8 @@ private fun BodyGenerator.genTableIntSwitch(
brTable: List<Int>, brTable: List<Int>,
expectedType: IrType, expectedType: IrType,
) { ) {
val location = SourceLocation.NoLocation("When's binary search infra")
val baseBlockIndex = body.numberOfNestedBlocks val baseBlockIndex = body.numberOfNestedBlocks
//expressions + else branch + br_table //expressions + else branch + br_table
repeat(branches.size + 2) { repeat(branches.size + 2) {
@@ -308,7 +315,7 @@ private fun BodyGenerator.genTableIntSwitch(
resultType?.let { generateDefaultInitializerForType(it, body) } //stub value resultType?.let { generateDefaultInitializerForType(it, body) } //stub value
body.buildGetLocal(selectorLocal) body.buildGetLocal(selectorLocal)
if (shift != 0) { if (shift != 0) {
body.buildConstI32(shift) body.buildConstI32(shift, location)
body.buildInstr(WasmOp.I32_SUB) body.buildInstr(WasmOp.I32_SUB)
} }
body.buildInstr( body.buildInstr(
@@ -257,7 +257,7 @@ inline fun WasmCompiledModuleFragment.ReferencableAndDefinable<IrClassSymbol, Co
elements.mapTo(into) { elements.mapTo(into) {
val id = address(wasmToIr.getValue(it)) val id = address(wasmToIr.getValue(it))
val offset = mutableListOf<WasmInstr>() val offset = mutableListOf<WasmInstr>()
WasmIrExpressionBuilder(offset).buildConstI32(id) WasmIrExpressionBuilder(offset).buildConstI32(id, SourceLocation.NoLocation("Compile time data per class"))
WasmData(WasmDataMode.Active(0, offset), it.toBytes()) WasmData(WasmDataMode.Active(0, offset), it.toBytes())
} }
} }
@@ -65,8 +65,8 @@ sealed class WasmDataMode {
val memoryIdx: Int, val memoryIdx: Int,
val offset: MutableList<WasmInstr> val offset: MutableList<WasmInstr>
) : WasmDataMode() { ) : WasmDataMode() {
constructor(memoryIdx: Int, offset: Int) : this(memoryIdx, mutableListOf<WasmInstr>().also<MutableList<WasmInstr>> { constructor(memoryIdx: Int, offset: Int, location: SourceLocation) : this(memoryIdx, mutableListOf<WasmInstr>().also<MutableList<WasmInstr>> {
WasmIrExpressionBuilder(it).buildConstI32(offset) WasmIrExpressionBuilder(it).buildConstI32(offset, location)
}) })
} }
@@ -16,7 +16,7 @@ abstract class WasmExpressionBuilder {
abstract var numberOfNestedBlocks: Int abstract var numberOfNestedBlocks: Int
fun buildConstI32(value: Int, location: SourceLocation = SourceLocation.TBDLocation) { fun buildConstI32(value: Int, location: SourceLocation) {
buildInstr(WasmOp.I32_CONST, location, WasmImmediate.ConstI32(value)) buildInstr(WasmOp.I32_CONST, location, WasmImmediate.ConstI32(value))
} }