WASM: Implement simple try/catch codegen
This commit is contained in:
committed by
TeamCityServer
parent
6ca965af6f
commit
02aed80e18
@@ -64,7 +64,7 @@ fun compileWasm(
|
|||||||
|
|
||||||
wasmPhases.invokeToplevel(phaseConfig, context, moduleFragment)
|
wasmPhases.invokeToplevel(phaseConfig, context, moduleFragment)
|
||||||
|
|
||||||
val compiledWasmModule = WasmCompiledModuleFragment()
|
val compiledWasmModule = WasmCompiledModuleFragment(context.irBuiltIns)
|
||||||
val codeGenerator = WasmModuleFragmentGenerator(context, compiledWasmModule)
|
val codeGenerator = WasmModuleFragmentGenerator(context, compiledWasmModule)
|
||||||
codeGenerator.generateModule(moduleFragment)
|
codeGenerator.generateModule(moduleFragment)
|
||||||
|
|
||||||
|
|||||||
+20
-1
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.ir.types.*
|
|||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
import org.jetbrains.kotlin.psi2ir.intermediate.generateExpressionValue
|
|
||||||
import org.jetbrains.kotlin.wasm.ir.*
|
import org.jetbrains.kotlin.wasm.ir.*
|
||||||
|
|
||||||
class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorVoid {
|
class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorVoid {
|
||||||
@@ -67,6 +66,26 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
|
|||||||
body.buildThrow(context.tagIdx)
|
body.buildThrow(context.tagIdx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitTry(aTry: IrTry) {
|
||||||
|
assert(aTry.isCanonical(irBuiltIns)) { "expected canonical try/catch" }
|
||||||
|
assert(aTry.type != irBuiltIns.nothingType) { "shouldn't happen" }
|
||||||
|
|
||||||
|
val resultType = context.transformBlockResultType(aTry.type)
|
||||||
|
body.buildTry(null, resultType)
|
||||||
|
generateExpression(aTry.tryResult)
|
||||||
|
|
||||||
|
body.buildCatch(context.tagIdx)
|
||||||
|
|
||||||
|
// Exception object is on top of the stack, store it into the local
|
||||||
|
aTry.catches.single().catchParameter.symbol.let {
|
||||||
|
context.defineLocal(it)
|
||||||
|
body.buildSetLocal(context.referenceLocal(it))
|
||||||
|
}
|
||||||
|
generateExpression(aTry.catches.single().result)
|
||||||
|
|
||||||
|
body.buildEnd()
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitTypeOperator(expression: IrTypeOperatorCall) {
|
override fun visitTypeOperator(expression: IrTypeOperatorCall) {
|
||||||
when (expression.operator) {
|
when (expression.operator) {
|
||||||
IrTypeOperator.REINTERPRET_CAST -> generateExpression(expression.argument)
|
IrTypeOperator.REINTERPRET_CAST -> generateExpression(expression.argument)
|
||||||
|
|||||||
+12
-3
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.wasm.ir2wasm
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.push
|
import org.jetbrains.kotlin.backend.common.push
|
||||||
import org.jetbrains.kotlin.backend.wasm.lower.WasmSignature
|
import org.jetbrains.kotlin.backend.wasm.lower.WasmSignature
|
||||||
|
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment
|
import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
@@ -14,7 +15,7 @@ import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
|||||||
import org.jetbrains.kotlin.ir.util.getPackageFragment
|
import org.jetbrains.kotlin.ir.util.getPackageFragment
|
||||||
import org.jetbrains.kotlin.wasm.ir.*
|
import org.jetbrains.kotlin.wasm.ir.*
|
||||||
|
|
||||||
class WasmCompiledModuleFragment {
|
class WasmCompiledModuleFragment(val irBuiltIns: IrBuiltIns) {
|
||||||
val functions =
|
val functions =
|
||||||
ReferencableAndDefinable<IrFunctionSymbol, WasmFunction>()
|
ReferencableAndDefinable<IrFunctionSymbol, WasmFunction>()
|
||||||
val globals =
|
val globals =
|
||||||
@@ -33,12 +34,20 @@ class WasmCompiledModuleFragment {
|
|||||||
ReferencableElements<WasmSignature, Int>()
|
ReferencableElements<WasmSignature, Int>()
|
||||||
val stringLiteralId =
|
val stringLiteralId =
|
||||||
ReferencableElements<String, Int>()
|
ReferencableElements<String, Int>()
|
||||||
val tagFuncType = WasmFunctionType("ex_handling_tag", listOf(WasmAnyRef), emptyList())
|
|
||||||
val tag = WasmTag(tagFuncType)
|
|
||||||
|
|
||||||
val runtimeTypes =
|
val runtimeTypes =
|
||||||
ReferencableAndDefinable<IrClassSymbol, WasmGlobal>()
|
ReferencableAndDefinable<IrClassSymbol, WasmGlobal>()
|
||||||
|
|
||||||
|
val tagFuncType = WasmFunctionType(
|
||||||
|
"ex_handling_tag",
|
||||||
|
listOf(
|
||||||
|
WasmRefNullType(WasmHeapType.Type(gcTypes.reference(irBuiltIns.throwableClass)))
|
||||||
|
),
|
||||||
|
emptyList()
|
||||||
|
)
|
||||||
|
val tag = WasmTag(tagFuncType)
|
||||||
|
|
||||||
|
|
||||||
val classes = mutableListOf<IrClassSymbol>()
|
val classes = mutableListOf<IrClassSymbol>()
|
||||||
val interfaces = mutableListOf<IrClassSymbol>()
|
val interfaces = mutableListOf<IrClassSymbol>()
|
||||||
val virtualFunctions = mutableListOf<IrSimpleFunctionSymbol>()
|
val virtualFunctions = mutableListOf<IrSimpleFunctionSymbol>()
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.wasm.utils
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrTry
|
||||||
|
|
||||||
|
// Backed codegen can only handle try/catch in canonical form.
|
||||||
|
// Canonical form for the try/catch:
|
||||||
|
// try {
|
||||||
|
// ...exprs
|
||||||
|
// } catch (e: Throwable) {
|
||||||
|
// ...exprs
|
||||||
|
// }
|
||||||
|
// no-finally
|
||||||
|
fun IrTry.isCanonical(builtIns: IrBuiltIns) =
|
||||||
|
catches.singleOrNull()?.catchParameter?.symbol?.owner?.type == builtIns.throwableType &&
|
||||||
|
finallyExpression == null
|
||||||
@@ -76,6 +76,12 @@ abstract class WasmExpressionBuilder {
|
|||||||
buildInstr(WasmOp.THROW, WasmImmediate.TagIdx(tagIdx))
|
buildInstr(WasmOp.THROW, WasmImmediate.TagIdx(tagIdx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
|
fun buildTry(label: String?, resultType: WasmType? = null) {
|
||||||
|
numberOfNestedBlocks++
|
||||||
|
buildInstr(WasmOp.TRY, WasmImmediate.BlockType.Value(resultType))
|
||||||
|
}
|
||||||
|
|
||||||
fun buildCatch(tagIdx: Int) {
|
fun buildCatch(tagIdx: Int) {
|
||||||
buildInstr(WasmOp.CATCH, WasmImmediate.TagIdx(tagIdx))
|
buildInstr(WasmOp.CATCH, WasmImmediate.TagIdx(tagIdx))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user