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)
|
||||
|
||||
val compiledWasmModule = WasmCompiledModuleFragment()
|
||||
val compiledWasmModule = WasmCompiledModuleFragment(context.irBuiltIns)
|
||||
val codeGenerator = WasmModuleFragmentGenerator(context, compiledWasmModule)
|
||||
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.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.generateExpressionValue
|
||||
import org.jetbrains.kotlin.wasm.ir.*
|
||||
|
||||
class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorVoid {
|
||||
@@ -67,6 +66,26 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
|
||||
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) {
|
||||
when (expression.operator) {
|
||||
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.wasm.lower.WasmSignature
|
||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
|
||||
import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment
|
||||
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.wasm.ir.*
|
||||
|
||||
class WasmCompiledModuleFragment {
|
||||
class WasmCompiledModuleFragment(val irBuiltIns: IrBuiltIns) {
|
||||
val functions =
|
||||
ReferencableAndDefinable<IrFunctionSymbol, WasmFunction>()
|
||||
val globals =
|
||||
@@ -33,12 +34,20 @@ class WasmCompiledModuleFragment {
|
||||
ReferencableElements<WasmSignature, Int>()
|
||||
val stringLiteralId =
|
||||
ReferencableElements<String, Int>()
|
||||
val tagFuncType = WasmFunctionType("ex_handling_tag", listOf(WasmAnyRef), emptyList())
|
||||
val tag = WasmTag(tagFuncType)
|
||||
|
||||
val runtimeTypes =
|
||||
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 interfaces = mutableListOf<IrClassSymbol>()
|
||||
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))
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun buildTry(label: String?, resultType: WasmType? = null) {
|
||||
numberOfNestedBlocks++
|
||||
buildInstr(WasmOp.TRY, WasmImmediate.BlockType.Value(resultType))
|
||||
}
|
||||
|
||||
fun buildCatch(tagIdx: Int) {
|
||||
buildInstr(WasmOp.CATCH, WasmImmediate.TagIdx(tagIdx))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user