WASM: Implement finally blocks for try/catch'es

This commit is contained in:
Igor Laevsky
2021-09-02 18:55:11 +03:00
committed by TeamCityServer
parent d99473fe4d
commit 4299915326
4 changed files with 38 additions and 13 deletions
@@ -217,7 +217,7 @@ class FinallyBlocksLowering(val context: CommonBackendContext, private val throw
val syntheticTry = IrTryImpl(
startOffset = startOffset,
endOffset = endOffset,
type = context.irBuiltIns.unitType
type = context.irBuiltIns.nothingType
).apply {
this.catches += irCatch(
catchParameter,
@@ -241,7 +241,7 @@ class FinallyBlocksLowering(val context: CommonBackendContext, private val throw
val transformedTry = IrTryImpl(
startOffset = startOffset,
endOffset = endOffset,
type = context.irBuiltIns.unitType
type = context.irBuiltIns.nothingType
)
transformedTry.tryResult = returnedResult
for (aCatch in aTry.catches) {
@@ -291,13 +291,6 @@ private val excludeDeclarationsFromCodegenPhase = makeCustomWasmModulePhase(
description = "Move excluded declarations to separate place"
)
private val returnableBlockLoweringPhase = makeWasmModulePhase(
::ReturnableBlockLowering,
name = "ReturnableBlockLowering",
description = "Replace returnable block with do-while loop",
prerequisite = setOf(functionInliningPhase)
)
private val tryCatchCanonicalization = makeWasmModulePhase(
::TryCatchCanonicalization,
name = "TryCatchCanonicalization",
@@ -305,6 +298,13 @@ private val tryCatchCanonicalization = makeWasmModulePhase(
prerequisite = setOf(functionInliningPhase)
)
private val returnableBlockLoweringPhase = makeWasmModulePhase(
::ReturnableBlockLowering,
name = "ReturnableBlockLowering",
description = "Replace returnable block with do-while loop",
prerequisite = setOf(functionInliningPhase)
)
private val bridgesConstructionPhase = makeWasmModulePhase(
::WasmBridgesConstruction,
name = "BridgesConstruction",
@@ -467,8 +467,8 @@ val wasmPhases = NamedCompilerPhase(
// suspendFunctionsLoweringPhase then
stringConstructorLowering then
returnableBlockLoweringPhase then
tryCatchCanonicalization then
returnableBlockLoweringPhase then
forLoopsLoweringPhase then
propertyAccessorInlinerLoweringPhase then
@@ -68,7 +68,6 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
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)
@@ -40,12 +40,38 @@ import org.jetbrains.kotlin.name.Name
// is Bar -> ...exprs
// }
// }
// TODO: Describe finally transformation
// With finally we transform this:
// try {
// ...exprs
// } catch (e: Throwable) {
// ...exprs
// } finally {
// ...<finally exprs>
// }
// Into something like this (tmp variable is used only if we return some result):
// val tmp = block { // this is where we return if we return from original try/catch with the result
// try {
// try {
// return@block ...exprs
// } catch (e: Throwable) {
// return@block ...exprs
// }
// }
// catch (e: Throwable) {
// ...<finally exprs>
// throw e // rethrow exception if it happened inside of the catch statement
// }
// }
// ...<finally exprs>
// tmp // result
internal class TryCatchCanonicalization(private val ctx: WasmBackendContext) : FileLoweringPass {
override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid(CatchMerger(ctx))
irFile.transformChildrenVoid(FinallyBlocksLowering(ctx, ctx.irBuiltIns.throwableType))
irFile.acceptVoid(object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
@@ -58,7 +84,7 @@ internal class TryCatchCanonicalization(private val ctx: WasmBackendContext) : F
}
}
internal class CatchMerger(private val ctx: WasmBackendContext): IrElementTransformerVoidWithContext() {
internal class CatchMerger(private val ctx: WasmBackendContext) : IrElementTransformerVoidWithContext() {
override fun visitTry(aTry: IrTry): IrExpression {
// First, handle all nested constructs
aTry.transformChildrenVoid(this)