WASM: Implement finally blocks for try/catch'es
This commit is contained in:
committed by
TeamCityServer
parent
d99473fe4d
commit
4299915326
+2
-2
@@ -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) {
|
||||
|
||||
+8
-8
@@ -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
|
||||
|
||||
-1
@@ -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)
|
||||
|
||||
+28
-2
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user