From f2f4c63720deba6c39ca151dc5701615d34f8bca Mon Sep 17 00:00:00 2001 From: Zalim Bashorov Date: Tue, 6 Dec 2022 20:34:47 +0100 Subject: [PATCH] [Wasm] Require location for `buildConstI32` and fix all usages --- .../backend/wasm/ir2wasm/BodyGenerator.kt | 207 +++++++++--------- .../wasm/ir2wasm/DeclarationGenerator.kt | 42 ++-- .../wasm/ir2wasm/OptimisedWhenGenerator.kt | 17 +- .../ir2wasm/WasmCompiledModuleFragment.kt | 2 +- .../jetbrains/kotlin/wasm/ir/Declarations.kt | 4 +- .../kotlin/wasm/ir/WasmExpressionBuilder.kt | 2 +- 6 files changed, 147 insertions(+), 127 deletions(-) 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 e0b221bb6de..37354a824a6 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 @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.wasm.utils.isCanonical import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.IrElement 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.findUnitGetInstanceFunction import org.jetbrains.kotlin.ir.backend.js.utils.isDispatchReceiver @@ -97,9 +98,11 @@ class BodyGenerator( val constantArrayId = context.referenceConstantArray(resource) - body.buildConstI32(0) - body.buildConstI32(irVararg.elements.size) - body.buildInstr(WasmOp.ARRAY_NEW_DATA, wasmArrayType, WasmImmediate.DataIdx(constantArrayId)) + withLocation(irVararg.getSourceLocation()) { + body.buildConstI32(0, location) + body.buildConstI32(irVararg.elements.size, location) + body.buildInstr(WasmOp.ARRAY_NEW_DATA, wasmArrayType, WasmImmediate.DataIdx(constantArrayId)) + } return true } @@ -125,7 +128,7 @@ class BodyGenerator( check(wasmArrayType != null) - generateAnyParameters(arrayClass.symbol) + generateAnyParameters(arrayClass.symbol, expression.getSourceLocation()) if (!tryGenerateConstVarargArray(expression, wasmArrayType)) tryGenerateVarargArray(expression, wasmArrayType) body.buildStructNew(context.referenceGcType(expression.type.getRuntimeClass(irBuiltIns).symbol)) } @@ -274,7 +277,7 @@ class BodyGenerator( } if (expression.symbol.owner.hasWasmPrimitiveConstructorAnnotation()) { - generateAnyParameters(klassSymbol) + generateAnyParameters(klassSymbol, expression.getSourceLocation()) for (i in 0 until expression.valueArgumentsCount) { generateExpression(expression.getValueArgument(i)!!) } @@ -287,7 +290,7 @@ class BodyGenerator( generateCall(expression) } - private fun generateAnyParameters(klassSymbol: IrClassSymbol) { + private fun generateAnyParameters(klassSymbol: IrClassSymbol, location: SourceLocation) { //ClassITable and VTable load body.commentGroupStart { "Any parameters" } body.buildGetGlobal(context.referenceGlobalVTable(klassSymbol)) @@ -298,7 +301,7 @@ class BodyGenerator( } body.buildConstI32Symbol(context.referenceClassId(klassSymbol)) - body.buildConstI32(0) // Any::_hashCode + body.buildConstI32(0, location) // Any::_hashCode body.commentGroupEnd() } @@ -311,7 +314,7 @@ class BodyGenerator( body.buildGetLocal(thisParameter) body.buildInstr(WasmOp.REF_IS_NULL) body.buildIf("this_init") - generateAnyParameters(parentClass.symbol) + generateAnyParameters(parentClass.symbol, SourceLocation.NoLocation("Constructor preamble")) val irFields: List = parentClass.allFields(backendContext.irBuiltIns) irFields.forEachIndexed { index, field -> if (index > 1) { @@ -339,7 +342,7 @@ class BodyGenerator( private fun generateBox(expression: IrExpression, type: IrType) { val klassSymbol = type.getRuntimeClass(irBuiltIns).symbol - generateAnyParameters(klassSymbol) + generateAnyParameters(klassSymbol, expression.getSourceLocation()) generateExpression(expression) body.buildStructNew(context.referenceGcType(klassSymbol)) 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)) { body.buildRefTestStatic( toType = context.referenceGcType(toType.getRuntimeClass(irBuiltIns).symbol) ) } else { body.buildDrop() - body.buildConstI32(1) + body.buildConstI32(1, location) } } @@ -488,109 +491,115 @@ class BodyGenerator( return true } - when (function.symbol) { - wasmSymbols.wasmClassId -> { - val klass = call.getTypeArgument(0)!!.getClass() - ?: error("No class given for wasmClassId intrinsic") - assert(!klass.isInterface) - body.buildConstI32Symbol(context.referenceClassId(klass.symbol)) - } + withLocation(call.getSourceLocation()) { + when (function.symbol) { + wasmSymbols.wasmClassId -> { + val klass = call.getTypeArgument(0)!!.getClass() + ?: error("No class given for wasmClassId intrinsic") + assert(!klass.isInterface) + body.buildConstI32Symbol(context.referenceClassId(klass.symbol)) + } - wasmSymbols.wasmInterfaceId -> { - val irInterface = call.getTypeArgument(0)!!.getClass() - ?: error("No interface given for wasmInterfaceId intrinsic") - assert(irInterface.isInterface) - body.buildConstI32Symbol(context.referenceInterfaceId(irInterface.symbol)) - } + wasmSymbols.wasmInterfaceId -> { + val irInterface = call.getTypeArgument(0)!!.getClass() + ?: error("No interface given for wasmInterfaceId intrinsic") + assert(irInterface.isInterface) + body.buildConstI32Symbol(context.referenceInterfaceId(irInterface.symbol)) + } - wasmSymbols.wasmIsInterface -> { - val irInterface = call.getTypeArgument(0)!!.getClass() - ?: error("No interface given for wasmInterfaceId intrinsic") - assert(irInterface.isInterface) - if (irInterface.symbol in hierarchyDisjointUnions) { - val classITable = context.referenceClassITableGcType(irInterface.symbol) - val parameterLocal = functionContext.referenceLocal(SyntheticLocalType.IS_INTERFACE_PARAMETER) - body.buildSetLocal(parameterLocal) - body.buildBlock("isInterface", WasmI32) { outerLabel -> - body.buildBlock("isInterface", WasmRefNullType(WasmHeapType.Simple.Data)) { innerLabel -> - body.buildGetLocal(parameterLocal) - body.buildStructGet(context.referenceGcType(irBuiltIns.anyClass), WasmSymbol(1)) - body.buildBrInstr(WasmOp.BR_ON_CAST_FAIL_DEPRECATED, innerLabel, classITable) - body.buildStructGet(classITable, context.referenceClassITableInterfaceSlot(irInterface.symbol)) - body.buildInstr(WasmOp.REF_IS_NULL) - body.buildInstr(WasmOp.I32_EQZ) - body.buildBr(outerLabel) + wasmSymbols.wasmIsInterface -> { + val irInterface = call.getTypeArgument(0)!!.getClass() + ?: error("No interface given for wasmInterfaceId intrinsic") + assert(irInterface.isInterface) + if (irInterface.symbol in hierarchyDisjointUnions) { + val classITable = context.referenceClassITableGcType(irInterface.symbol) + val parameterLocal = functionContext.referenceLocal(SyntheticLocalType.IS_INTERFACE_PARAMETER) + body.buildSetLocal(parameterLocal) + body.buildBlock("isInterface", WasmI32) { outerLabel -> + body.buildBlock("isInterface", WasmRefNullType(WasmHeapType.Simple.Data)) { innerLabel -> + body.buildGetLocal(parameterLocal) + body.buildStructGet(context.referenceGcType(irBuiltIns.anyClass), WasmSymbol(1)) + body.buildBrInstr(WasmOp.BR_ON_CAST_FAIL_DEPRECATED, innerLabel, classITable) + body.buildStructGet(classITable, context.referenceClassITableInterfaceSlot(irInterface.symbol)) + body.buildInstr(WasmOp.REF_IS_NULL) + body.buildInstr(WasmOp.I32_EQZ) + body.buildBr(outerLabel) + } + body.buildDrop() + body.buildConstI32(0, location) } + } else { body.buildDrop() - body.buildConstI32(0) + body.buildConstI32(0, location) } - } else { - body.buildDrop() - body.buildConstI32(0) - } - } - - wasmSymbols.refCastNull -> { - generateRefNullCast( - fromType = call.getValueArgument(0)!!.type, - toType = call.getTypeArgument(0)!! - ) - } - - wasmSymbols.refTest -> { - generateRefTest( - fromType = call.getValueArgument(0)!!.type, - toType = call.getTypeArgument(0)!! - ) - } - - wasmSymbols.unboxIntrinsic -> { - val fromType = call.getTypeArgument(0)!! - - if (fromType.isNothing()) { - body.buildUnreachable() - // TODO: Investigate why? - return true } - // Workaround test codegen/box/elvis/nullNullOk.kt - if (fromType.makeNotNull().isNothing()) { - body.buildUnreachable() - return true + wasmSymbols.refCastNull -> { + generateRefNullCast( + fromType = call.getValueArgument(0)!!.type, + toType = call.getTypeArgument(0)!! + ) } - val toType = call.getTypeArgument(1)!! - val klass: IrClass = backendContext.inlineClassesUtils.getInlinedClass(toType)!! - val field = getInlineClassBackingField(klass) + wasmSymbols.refTest -> { + generateRefTest( + fromType = call.getValueArgument(0)!!.type, + toType = call.getTypeArgument(0)!!, + location + ) + } - generateRefNullCast(fromType, toType) - generateInstanceFieldAccess(field) - } + wasmSymbols.unboxIntrinsic -> { + val fromType = call.getTypeArgument(0)!! - wasmSymbols.unsafeGetScratchRawMemory -> { - body.buildConstI32Symbol(context.scratchMemAddr) - } + if (fromType.isNothing()) { + body.buildUnreachable() + // TODO: Investigate why? + return true + } - wasmSymbols.wasmArrayCopy -> { - val immediate = WasmImmediate.GcType( - context.referenceGcType(call.getTypeArgument(0)!!.getRuntimeClass(irBuiltIns).symbol) - ) - body.buildInstr(WasmOp.ARRAY_COPY, immediate, immediate) - } + // Workaround test codegen/box/elvis/nullNullOk.kt + if (fromType.makeNotNull().isNothing()) { + body.buildUnreachable() + return true + } - wasmSymbols.stringGetPoolSize -> { - body.buildConstI32Symbol(context.stringPoolSize) - } + val toType = call.getTypeArgument(1)!! + val klass: IrClass = backendContext.inlineClassesUtils.getInlinedClass(toType)!! + val field = getInlineClassBackingField(klass) - wasmSymbols.wasmArrayNewData0 -> { - val arrayGcType = WasmImmediate.GcType( - context.referenceGcType(call.getTypeArgument(0)!!.getRuntimeClass(irBuiltIns).symbol) - ) - body.buildInstr(WasmOp.ARRAY_NEW_DATA, arrayGcType, WasmImmediate.DataIdx(0)) - } + generateRefNullCast(fromType, toType) + generateInstanceFieldAccess(field) + } - else -> { - return false + wasmSymbols.unsafeGetScratchRawMemory -> { + + body.buildConstI32Symbol(context.scratchMemAddr) + } + + + + wasmSymbols.wasmArrayCopy -> { + val immediate = WasmImmediate.GcType( + context.referenceGcType(call.getTypeArgument(0)!!.getRuntimeClass(irBuiltIns).symbol) + ) + body.buildInstr(WasmOp.ARRAY_COPY, immediate, immediate) + } + + wasmSymbols.stringGetPoolSize -> { + body.buildConstI32Symbol(context.stringPoolSize) + } + + wasmSymbols.wasmArrayNewData0 -> { + val arrayGcType = WasmImmediate.GcType( + context.referenceGcType(call.getTypeArgument(0)!!.getRuntimeClass(irBuiltIns).symbol) + ) + body.buildInstr(WasmOp.ARRAY_NEW_DATA, arrayGcType, WasmImmediate.DataIdx(0)) + } + + else -> { + return false + } } } return true 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 84b291daf00..2a95c82d993 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 @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.name.parentOrNull import org.jetbrains.kotlin.wasm.ir.* import org.jetbrains.kotlin.wasm.ir.source.location.withLocation +import org.jetbrains.kotlin.wasm.ir.source.location.withNoLocation class DeclarationGenerator( val context: WasmModuleCodegenContext, @@ -472,19 +473,22 @@ class DeclarationGenerator( } } -fun generateDefaultInitializerForType(type: WasmType, g: WasmExpressionBuilder) = when (type) { - WasmI32 -> g.buildConstI32(0) - WasmI64 -> g.buildConstI64(0) - WasmF32 -> g.buildConstF32(0f) - WasmF64 -> g.buildConstF64(0.0) - is WasmRefNullType -> g.buildRefNull(type.heapType) - is WasmRefNullNoneType -> g.buildRefNull(WasmHeapType.Simple.NullNone) - is WasmRefNullExternrefType -> g.buildRefNull(WasmHeapType.Simple.NullNoExtern) - is WasmAnyRef -> g.buildRefNull(WasmHeapType.Simple.Any) - is WasmExternRef -> g.buildRefNull(WasmHeapType.Simple.Extern) - WasmUnreachableType -> error("Unreachable type can't be initialized") - else -> error("Unknown value type ${type.name}") -} +fun generateDefaultInitializerForType(type: WasmType, g: WasmExpressionBuilder) = + withNoLocation("Default initializer, usually don't require location") { + when (type) { + WasmI32 -> g.buildConstI32(0, location) + WasmI64 -> g.buildConstI64(0) + WasmF32 -> g.buildConstF32(0f) + WasmF64 -> g.buildConstF64(0.0) + is WasmRefNullType -> g.buildRefNull(type.heapType) + is WasmRefNullNoneType -> g.buildRefNull(WasmHeapType.Simple.NullNone) + is WasmRefNullExternrefType -> g.buildRefNull(WasmHeapType.Simple.NullNoExtern) + is WasmAnyRef -> g.buildRefNull(WasmHeapType.Simple.Any) + is WasmExternRef -> g.buildRefNull(WasmHeapType.Simple.Extern) + WasmUnreachableType -> error("Unreachable type can't be initialized") + else -> error("Unknown value type ${type.name}") + } + } fun IrFunction.getEffectiveValueParameters(): List { 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 body.buildInstr(WasmOp.REF_NULL, WasmImmediate.HeapType(bottomType)) } - is IrConstKind.Boolean -> body.buildConstI32(if (kind.valueOf(expression)) 1 else 0) - is IrConstKind.Byte -> body.buildConstI32(kind.valueOf(expression).toInt()) - is IrConstKind.Short -> body.buildConstI32(kind.valueOf(expression).toInt()) - is IrConstKind.Int -> body.buildConstI32(kind.valueOf(expression)) + 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.Short -> body.buildConstI32(kind.valueOf(expression).toInt(), location) + is IrConstKind.Int -> body.buildConstI32(kind.valueOf(expression), location) 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.Double -> body.buildConstF64(kind.valueOf(expression)) is IrConstKind.String -> { @@ -516,7 +520,7 @@ fun generateConstExpression(expression: IrConst<*>, body: WasmExpressionBuilder, body.commentGroupStart { "const string: \"$stringValue\"" } body.buildConstI32Symbol(literalPoolId) body.buildConstI32Symbol(literalAddress) - body.buildConstI32(stringValue.length) + body.buildConstI32(stringValue.length, location) body.buildCall(context.referenceFunction(context.backendContext.wasmSymbols.stringGetLiteral), location) body.commentGroupEnd() } 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 9c351995767..58a06c6fd3d 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 @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.ir.util.isElseBranch import org.jetbrains.kotlin.wasm.ir.* +import org.jetbrains.kotlin.wasm.ir.source.location.SourceLocation private class ExtractedWhenCondition(val condition: IrCall, val const: IrConst) private class ExtractedWhenBranch(val conditions: List>, 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 } } sortedCaseToBranchIndex.sortBy { it.first } + val location = SourceLocation.NoLocation("When's binary search infra") + val thenBody = { result: Int -> - body.buildConstI32(result) + body.buildConstI32(result, location) } val elseBody: () -> Unit = { - body.buildConstI32(intBranches.size) + body.buildConstI32(intBranches.size, location) } createBinaryTable(selectorLocal, WasmI32, sortedCaseToBranchIndex, 0, sortedCaseToBranchIndex.size, thenBody, elseBody) } @@ -240,11 +243,13 @@ private fun BodyGenerator.createBinaryTable( thenBody: (T) -> Unit, elseBody: () -> Unit ) { + val location = SourceLocation.NoLocation("When's binary search infra") + val size = toExcl - fromIncl if (size == 1) { val (case, result) = sortedCases[fromIncl] body.buildGetLocal(selectorLocal) - body.buildConstI32(case) + body.buildConstI32(case, location) body.buildInstr(WasmOp.I32_EQ) body.buildIf("binary_tree_branch", resultType) thenBody(result) @@ -257,7 +262,7 @@ private fun BodyGenerator.createBinaryTable( val border = fromIncl + size / 2 body.buildGetLocal(selectorLocal) - body.buildConstI32(sortedCases[border].first) + body.buildConstI32(sortedCases[border].first, location) body.buildInstr(WasmOp.I32_LT_S) body.buildIf("binary_tree_node", resultType) createBinaryTable(selectorLocal, resultType, sortedCases, fromIncl, border, thenBody, elseBody) @@ -299,6 +304,8 @@ private fun BodyGenerator.genTableIntSwitch( brTable: List, expectedType: IrType, ) { + val location = SourceLocation.NoLocation("When's binary search infra") + val baseBlockIndex = body.numberOfNestedBlocks //expressions + else branch + br_table repeat(branches.size + 2) { @@ -308,7 +315,7 @@ private fun BodyGenerator.genTableIntSwitch( resultType?.let { generateDefaultInitializerForType(it, body) } //stub value body.buildGetLocal(selectorLocal) if (shift != 0) { - body.buildConstI32(shift) + body.buildConstI32(shift, location) body.buildInstr(WasmOp.I32_SUB) } body.buildInstr( diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt index 6456709a6b2..ee8f8698efc 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt @@ -257,7 +257,7 @@ inline fun WasmCompiledModuleFragment.ReferencableAndDefinable() - WasmIrExpressionBuilder(offset).buildConstI32(id) + WasmIrExpressionBuilder(offset).buildConstI32(id, SourceLocation.NoLocation("Compile time data per class")) WasmData(WasmDataMode.Active(0, offset), it.toBytes()) } } diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt index 0f5b2a6d34d..0676ed6c44c 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt @@ -65,8 +65,8 @@ sealed class WasmDataMode { val memoryIdx: Int, val offset: MutableList ) : WasmDataMode() { - constructor(memoryIdx: Int, offset: Int) : this(memoryIdx, mutableListOf().also> { - WasmIrExpressionBuilder(it).buildConstI32(offset) + constructor(memoryIdx: Int, offset: Int, location: SourceLocation) : this(memoryIdx, mutableListOf().also> { + WasmIrExpressionBuilder(it).buildConstI32(offset, location) }) } 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 4519bbb088f..e9dd82337f1 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 @@ -16,7 +16,7 @@ abstract class WasmExpressionBuilder { 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)) }