diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt index 9b7188069b7..68c1aad2485 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt @@ -48,6 +48,9 @@ internal class KonanLower(val context: Context) { DefaultArgumentStubGenerator(context).runOnFilePostfix(irFile) DefaultParameterInjector(context).runOnFilePostfix(irFile) } + phaser.phase(KonanPhase.LOWER_LATEINIT) { + LateinitLowering(context).lower(irFile) + } phaser.phase(KonanPhase.LOWER_BUILTIN_OPERATORS) { BuiltinOperatorLowering(context).runOnFilePostfix(irFile) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt index d39be6c8281..0e8bba96ee6 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt @@ -3,7 +3,7 @@ package org.jetbrains.kotlin.backend.konan import org.jetbrains.kotlin.backend.konan.util.* enum class KonanPhase(val description: String, - val prerequisite: Set = setOf(), + vararg prerequisite: KonanPhase, var enabled: Boolean = true, var verbose: Boolean = false) { /* */ FRONTEND("Frontend builds AST"), @@ -14,27 +14,29 @@ enum class KonanPhase(val description: String, /* ... ... */ LOWER_INTEROP("Interop lowering"), /* ... ... */ LOWER_ENUMS("Enum classes lowering"), /* ... ... */ LOWER_DELEGATION("Delegation lowering"), - /* ... ... */ LOWER_INITIALIZERS("Initializers lowering", setOf(LOWER_ENUMS)), - /* ... ... */ LOWER_SHARED_VARIABLES("Shared Variable Lowering", setOf(LOWER_INITIALIZERS)), - /* ... ... */ LOWER_CALLABLES("Callable references Lowering", setOf( - LOWER_INTEROP, LOWER_INITIALIZERS, LOWER_DELEGATION)), - /* ... ... */ LOWER_VARARG("Vararg lowering", setOf(LOWER_CALLABLES)), - /* ... ... */ LOWER_LOCAL_FUNCTIONS("Local Function Lowering", setOf(LOWER_SHARED_VARIABLES)), - /* ... ... */ LOWER_TAILREC("tailrec lowering", setOf(LOWER_LOCAL_FUNCTIONS)), - /* ... ... */ LOWER_DEFAULT_PARAMETER_EXTENT("Default Parameter Extent Lowering", setOf( - LOWER_TAILREC, LOWER_ENUMS)), - /* ... ... */ LOWER_INNER_CLASSES("Inner classes lowering", setOf(LOWER_DEFAULT_PARAMETER_EXTENT)), - /* ... ... */ LOWER_BUILTIN_OPERATORS("BuiltIn Operators Lowering", setOf( - LOWER_DEFAULT_PARAMETER_EXTENT)), + /* ... ... */ LOWER_INITIALIZERS("Initializers lowering", LOWER_ENUMS), + /* ... ... */ LOWER_SHARED_VARIABLES("Shared Variable Lowering", LOWER_INITIALIZERS), + /* ... ... */ LOWER_CALLABLES("Callable references Lowering", + LOWER_INTEROP, LOWER_INITIALIZERS, LOWER_DELEGATION), + /* ... ... */ LOWER_VARARG("Vararg lowering", LOWER_CALLABLES), + /* ... ... */ LOWER_LOCAL_FUNCTIONS("Local Function Lowering", LOWER_SHARED_VARIABLES), + /* ... ... */ LOWER_TAILREC("tailrec lowering", LOWER_LOCAL_FUNCTIONS), + /* ... ... */ LOWER_DEFAULT_PARAMETER_EXTENT("Default Parameter Extent Lowering", + LOWER_TAILREC, LOWER_ENUMS), + /* ... ... */ LOWER_INNER_CLASSES("Inner classes lowering", LOWER_DEFAULT_PARAMETER_EXTENT), + /* ... ... */ LOWER_LATEINIT("Lateinit properties lowering"), + /* ... ... */ LOWER_BUILTIN_OPERATORS("BuiltIn Operators Lowering", LOWER_DEFAULT_PARAMETER_EXTENT, LOWER_LATEINIT), /* ... ... */ LOWER_TYPE_OPERATORS("Type operators lowering"), /* ... ... */ BRIDGES_BUILDING("Bridges building"), /* ... ... */ LOWER_STRING_CONCAT("String concatenation lowering"), - /* ... ... */ AUTOBOX("Autoboxing of primitive types", setOf(BRIDGES_BUILDING)), + /* ... ... */ AUTOBOX("Autoboxing of primitive types", BRIDGES_BUILDING), /* ... */ BITCODE("LLVM BitCode Generation"), /* ... ... */ RTTI("RTTI Generation"), /* ... ... */ CODEGEN("Code Generation"), /* ... ... */ METADATOR("Metadata Generation"), - /* */ LINKER("Link Stage") + /* */ LINKER("Link Stage"); + + val prerequisite = prerequisite.toSet() } object KonanPhases { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LateinitLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LateinitLowering.kt new file mode 100644 index 00000000000..c9935a65ed5 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LateinitLowering.kt @@ -0,0 +1,57 @@ +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrProperty +import org.jetbrains.kotlin.ir.expressions.IrBlock +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.types.KotlinType + +internal class LateinitLowering(val context: Context): FileLoweringPass { + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(object: IrElementTransformerVoid() { + override fun visitProperty(declaration: IrProperty): IrStatement { + if (declaration.descriptor.isLateInit) + transformGetter(declaration.descriptor, declaration.getter!!) + return declaration + } + + private fun transformGetter(propertyDescriptor: PropertyDescriptor, getter: IrFunction) { + val startOffset = getter.startOffset + val endOffset = getter.endOffset + val irBuilder = context.createIrBuilder(getter.descriptor, startOffset, endOffset) + irBuilder.run { + val block = irBlock(propertyDescriptor.type) + val resultVar = scope.createTemporaryVariable(irGetField(irThis(), propertyDescriptor)) + block.statements.add(resultVar) + val throwIfNull = irIfThenElse(context.builtIns.nothingType, + irNotEquals(irGet(resultVar.descriptor), irNull()), + irReturn(irGet(resultVar.descriptor)), + irCall(throwErrorFunction)) + block.statements.add(throwIfNull) + getter.body = IrExpressionBodyImpl(startOffset, endOffset, block) + } + } + }) + } + + private val throwErrorFunction = context.builtIns.getKonanInternalFunctions("ThrowUninitializedPropertyAccessException").single() + + private fun IrBuilderWithScope.irBlock(type: KotlinType): IrBlock + = IrBlockImpl(startOffset, endOffset, type) + + private fun IrBuilderWithScope.irGetField(receiver: IrExpression?, property: PropertyDescriptor): IrExpression + = IrGetFieldImpl(startOffset, endOffset, property, receiver) +} \ No newline at end of file diff --git a/runtime/src/main/kotlin/konan/internal/RuntimeUtils.kt b/runtime/src/main/kotlin/konan/internal/RuntimeUtils.kt index 4066932e358..e70a0f26e23 100644 --- a/runtime/src/main/kotlin/konan/internal/RuntimeUtils.kt +++ b/runtime/src/main/kotlin/konan/internal/RuntimeUtils.kt @@ -24,6 +24,10 @@ fun ThrowNoWhenBranchMatchedException(): Nothing { throw NoWhenBranchMatchedException() } +fun ThrowUninitializedPropertyAccessException(): Nothing { + throw UninitializedPropertyAccessException() +} + @ExportForCppRuntime internal fun TheEmptyString() = "" diff --git a/runtime/src/main/kotlin/kotlin/Exceptions.kt b/runtime/src/main/kotlin/kotlin/Exceptions.kt index 789b118e55b..9de433a99d0 100644 --- a/runtime/src/main/kotlin/kotlin/Exceptions.kt +++ b/runtime/src/main/kotlin/kotlin/Exceptions.kt @@ -176,6 +176,15 @@ public open class NoWhenBranchMatchedException : RuntimeException { } } +public open class UninitializedPropertyAccessException : RuntimeException { + + constructor() : super() { + } + + constructor(s: String) : super(s) { + } +} + public open class OutOfMemoryError : Error { constructor() : super() {