[K/N] Supported outer this references from cached inline bodies
This commit is contained in:
+7
-5
@@ -40,6 +40,7 @@ import kotlin.LazyThreadSafetyMode.PUBLICATION
|
|||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||||
import org.jetbrains.kotlin.backend.common.ir.copyToWithoutSuperTypes
|
import org.jetbrains.kotlin.backend.common.ir.copyToWithoutSuperTypes
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.getSuperClassNotAny
|
||||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager
|
import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager
|
||||||
import org.jetbrains.kotlin.backend.konan.serialization.KonanIrLinker
|
import org.jetbrains.kotlin.backend.konan.serialization.KonanIrLinker
|
||||||
@@ -77,9 +78,9 @@ internal class SpecialDeclarationsFactory(val context: Context) {
|
|||||||
object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS :
|
object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS :
|
||||||
IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS")
|
IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS")
|
||||||
|
|
||||||
fun getOuterThisField(innerClass: IrClass): IrField =
|
fun getOuterThisField(innerClass: IrClass): IrField {
|
||||||
if (!innerClass.isInner) throw AssertionError("Class is not inner: ${innerClass.descriptor}")
|
assert(innerClass.isInner) { "Class is not inner: ${innerClass.render()}" }
|
||||||
else outerThisFields.getOrPut(innerClass) {
|
return outerThisFields.getOrPut(innerClass) {
|
||||||
val outerClass = innerClass.parent as? IrClass
|
val outerClass = innerClass.parent as? IrClass
|
||||||
?: throw AssertionError("No containing class for inner class ${innerClass.descriptor}")
|
?: throw AssertionError("No containing class for inner class ${innerClass.descriptor}")
|
||||||
|
|
||||||
@@ -112,6 +113,7 @@ internal class SpecialDeclarationsFactory(val context: Context) {
|
|||||||
parent = innerClass
|
parent = innerClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getLoweredEnumOrNull(enumClass: IrClass): LoweredEnumAccess? {
|
fun getLoweredEnumOrNull(enumClass: IrClass): LoweredEnumAccess? {
|
||||||
assert(enumClass.kind == ClassKind.ENUM_CLASS) { "Expected enum class but was: ${enumClass.descriptor}" }
|
assert(enumClass.kind == ClassKind.ENUM_CLASS) { "Expected enum class but was: ${enumClass.descriptor}" }
|
||||||
@@ -291,12 +293,12 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
|||||||
fun getLayoutBuilder(irClass: IrClass): ClassLayoutBuilder {
|
fun getLayoutBuilder(irClass: IrClass): ClassLayoutBuilder {
|
||||||
if (irClass is IrLazyClass)
|
if (irClass is IrLazyClass)
|
||||||
return layoutBuilders.getOrPut(irClass) {
|
return layoutBuilders.getOrPut(irClass) {
|
||||||
ClassLayoutBuilder(irClass, this, isLowered = shouldLower(this, irClass))
|
ClassLayoutBuilder(irClass, this)
|
||||||
}
|
}
|
||||||
val metadata = irClass.metadata as? CodegenClassMetadata
|
val metadata = irClass.metadata as? CodegenClassMetadata
|
||||||
?: CodegenClassMetadata(irClass).also { irClass.metadata = it }
|
?: CodegenClassMetadata(irClass).also { irClass.metadata = it }
|
||||||
metadata.layoutBuilder?.let { return it }
|
metadata.layoutBuilder?.let { return it }
|
||||||
val layoutBuilder = ClassLayoutBuilder(irClass, this, isLowered = shouldLower(this, irClass))
|
val layoutBuilder = ClassLayoutBuilder(irClass, this)
|
||||||
metadata.layoutBuilder = layoutBuilder
|
metadata.layoutBuilder = layoutBuilder
|
||||||
return layoutBuilder
|
return layoutBuilder
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -77,6 +77,9 @@ internal class InternalAbi(private val context: Context) {
|
|||||||
fun getEnumValuesAccessorName(enum: IrClass): Name =
|
fun getEnumValuesAccessorName(enum: IrClass): Name =
|
||||||
getMangledNameFor("getValues", enum)
|
getMangledNameFor("getValues", enum)
|
||||||
|
|
||||||
|
fun getInnerClassOuterThisAccessorName(innerClass: IrClass): Name =
|
||||||
|
getMangledNameFor("outerThis", innerClass)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate name for declaration that will be a part of internal ABI.
|
* Generate name for declaration that will be a part of internal ABI.
|
||||||
*/
|
*/
|
||||||
|
|||||||
+65
-11
@@ -15,15 +15,16 @@ import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
|||||||
import org.jetbrains.kotlin.backend.konan.serialization.*
|
import org.jetbrains.kotlin.backend.konan.serialization.*
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||||
import org.jetbrains.kotlin.ir.builders.irBlockBody
|
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
||||||
import org.jetbrains.kotlin.ir.builders.irGetObjectValue
|
|
||||||
import org.jetbrains.kotlin.ir.builders.irReturn
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrGetObjectValue
|
import org.jetbrains.kotlin.ir.expressions.IrGetObjectValue
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrGetField
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
@@ -32,6 +33,7 @@ import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
|||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
internal fun moduleValidationCallback(state: ActionState, module: IrModuleFragment, context: Context) {
|
internal fun moduleValidationCallback(state: ActionState, module: IrModuleFragment, context: Context) {
|
||||||
if (!context.config.needVerifyIr) return
|
if (!context.config.needVerifyIr) return
|
||||||
@@ -140,7 +142,8 @@ internal val buildAdditionalCacheInfoPhase = konanUnitPhase(
|
|||||||
override fun visitClass(declaration: IrClass) {
|
override fun visitClass(declaration: IrClass) {
|
||||||
declaration.acceptChildrenVoid(this)
|
declaration.acceptChildrenVoid(this)
|
||||||
|
|
||||||
if (declaration.isExported && declaration.origin != DECLARATION_ORIGIN_FUNCTION_CLASS)
|
if (!declaration.isInterface && declaration.visibility != DescriptorVisibilities.LOCAL
|
||||||
|
&& declaration.isExported && declaration.origin != DECLARATION_ORIGIN_FUNCTION_CLASS)
|
||||||
classFields.add(moduleDeserializer.buildClassFields(declaration, getLayoutBuilder(declaration).getDeclaredFields()))
|
classFields.add(moduleDeserializer.buildClassFields(declaration, getLayoutBuilder(declaration).getDeclaredFields()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,11 +168,6 @@ internal val buildAdditionalCacheInfoPhase = konanUnitPhase(
|
|||||||
prerequisite = setOf(psiToIrPhase)
|
prerequisite = setOf(psiToIrPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Coupled with [psiToIrPhase] logic above.
|
|
||||||
internal fun shouldLower(context: Context, declaration: IrDeclaration): Boolean {
|
|
||||||
return context.llvmModuleSpecification.containsDeclaration(declaration)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal val destroySymbolTablePhase = konanUnitPhase(
|
internal val destroySymbolTablePhase = konanUnitPhase(
|
||||||
op = {
|
op = {
|
||||||
this.symbolTable = null // TODO: invalidate symbolTable itself.
|
this.symbolTable = null // TODO: invalidate symbolTable itself.
|
||||||
@@ -393,6 +391,28 @@ internal val exportInternalAbiPhase = makeKonanModuleOpPhase(
|
|||||||
context.internalAbi.declare(function, declaration.module)
|
context.internalAbi.declare(function, declaration.module)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (declaration.isInner) {
|
||||||
|
val function = context.irFactory.buildFun {
|
||||||
|
name = InternalAbi.getInnerClassOuterThisAccessorName(declaration)
|
||||||
|
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||||
|
returnType = declaration.parentAsClass.defaultType
|
||||||
|
}
|
||||||
|
function.addValueParameter {
|
||||||
|
name = Name.identifier("innerClass")
|
||||||
|
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||||
|
type = declaration.defaultType
|
||||||
|
}
|
||||||
|
|
||||||
|
context.createIrBuilder(function.symbol).apply {
|
||||||
|
function.body = irBlockBody {
|
||||||
|
+irReturn(irGetField(
|
||||||
|
irGet(function.valueParameters[0]),
|
||||||
|
context.specialDeclarationsFactory.getOuterThisField(declaration))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.internalAbi.declare(function, declaration.module)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
module.acceptChildrenVoid(visitor)
|
module.acceptChildrenVoid(visitor)
|
||||||
@@ -404,7 +424,8 @@ internal val useInternalAbiPhase = makeKonanModuleOpPhase(
|
|||||||
description = "Use internal ABI functions to access private entities",
|
description = "Use internal ABI functions to access private entities",
|
||||||
prerequisite = emptySet(),
|
prerequisite = emptySet(),
|
||||||
op = { context, module ->
|
op = { context, module ->
|
||||||
val accessors = mutableMapOf<IrClass, IrSimpleFunction>()
|
val companionObjectAccessors = mutableMapOf<IrClass, IrSimpleFunction>()
|
||||||
|
val outerThisAccessors = mutableMapOf<IrClass, IrSimpleFunction>()
|
||||||
val transformer = object : IrElementTransformerVoid() {
|
val transformer = object : IrElementTransformerVoid() {
|
||||||
override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression {
|
override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression {
|
||||||
val irClass = expression.symbol.owner
|
val irClass = expression.symbol.owner
|
||||||
@@ -416,7 +437,7 @@ internal val useInternalAbiPhase = makeKonanModuleOpPhase(
|
|||||||
// Access to Obj-C metaclass is done via intrinsic.
|
// Access to Obj-C metaclass is done via intrinsic.
|
||||||
return expression
|
return expression
|
||||||
}
|
}
|
||||||
val accessor = accessors.getOrPut(irClass) {
|
val accessor = companionObjectAccessors.getOrPut(irClass) {
|
||||||
context.irFactory.buildFun {
|
context.irFactory.buildFun {
|
||||||
name = InternalAbi.getCompanionObjectAccessorName(irClass)
|
name = InternalAbi.getCompanionObjectAccessorName(irClass)
|
||||||
returnType = irClass.defaultType
|
returnType = irClass.defaultType
|
||||||
@@ -428,6 +449,39 @@ internal val useInternalAbiPhase = makeKonanModuleOpPhase(
|
|||||||
}
|
}
|
||||||
return IrCallImpl(expression.startOffset, expression.endOffset, expression.type, accessor.symbol, accessor.typeParameters.size, accessor.valueParameters.size)
|
return IrCallImpl(expression.startOffset, expression.endOffset, expression.type, accessor.symbol, accessor.typeParameters.size, accessor.valueParameters.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitGetField(expression: IrGetField): IrExpression {
|
||||||
|
val field = expression.symbol.owner
|
||||||
|
val irClass = field.parentClassOrNull ?: return expression
|
||||||
|
if (!irClass.isInner || context.llvmModuleSpecification.containsDeclaration(irClass)
|
||||||
|
|| context.specialDeclarationsFactory.getOuterThisField(irClass) != field
|
||||||
|
) {
|
||||||
|
return expression
|
||||||
|
}
|
||||||
|
val accessor = outerThisAccessors.getOrPut(irClass) {
|
||||||
|
context.irFactory.buildFun {
|
||||||
|
name = InternalAbi.getInnerClassOuterThisAccessorName(irClass)
|
||||||
|
returnType = irClass.parentAsClass.defaultType
|
||||||
|
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||||
|
isExternal = true
|
||||||
|
}.also { function ->
|
||||||
|
context.internalAbi.reference(function, irClass.module)
|
||||||
|
|
||||||
|
function.addValueParameter {
|
||||||
|
name = Name.identifier("innerClass")
|
||||||
|
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||||
|
type = irClass.defaultType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return IrCallImpl(
|
||||||
|
expression.startOffset, expression.endOffset,
|
||||||
|
expression.type, accessor.symbol,
|
||||||
|
accessor.typeParameters.size, accessor.valueParameters.size
|
||||||
|
).apply {
|
||||||
|
putValueArgument(0, expression.receiver)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
module.transformChildrenVoid(transformer)
|
module.transformChildrenVoid(transformer)
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-16
@@ -260,7 +260,12 @@ internal class GlobalHierarchyAnalysis(val context: Context, val irModule: IrMod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context, val isLowered: Boolean) {
|
internal fun IrField.toFieldInfo() =
|
||||||
|
ClassLayoutBuilder.FieldInfo(name.asString(), type,
|
||||||
|
correspondingPropertySymbol?.owner?.isConst ?: false,
|
||||||
|
initializer?.expression is IrConst<*>, this)
|
||||||
|
|
||||||
|
internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context) {
|
||||||
val vtableEntries: List<OverriddenFunctionInfo> by lazy {
|
val vtableEntries: List<OverriddenFunctionInfo> by lazy {
|
||||||
require(!irClass.isInterface)
|
require(!irClass.isInterface)
|
||||||
|
|
||||||
@@ -458,15 +463,13 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context, va
|
|||||||
|
|
||||||
lateinit var hierarchyInfo: ClassGlobalHierarchyInfo
|
lateinit var hierarchyInfo: ClassGlobalHierarchyInfo
|
||||||
|
|
||||||
private fun IrField.toFieldInfo() =
|
|
||||||
FieldInfo(name.asString(), type,
|
|
||||||
correspondingPropertySymbol?.owner?.isConst ?: false,
|
|
||||||
initializer?.expression is IrConst<*>, this)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fields declared in the class.
|
* Fields declared in the class.
|
||||||
*/
|
*/
|
||||||
fun getDeclaredFields(): List<FieldInfo> {
|
fun getDeclaredFields(): List<FieldInfo> {
|
||||||
|
val outerThisField = if (irClass.isInner)
|
||||||
|
context.specialDeclarationsFactory.getOuterThisField(irClass)
|
||||||
|
else null
|
||||||
if (context.config.lazyIrForCaches && !context.llvmModuleSpecification.containsDeclaration(irClass)) {
|
if (context.config.lazyIrForCaches && !context.llvmModuleSpecification.containsDeclaration(irClass)) {
|
||||||
val packageFragment = irClass.findPackage()
|
val packageFragment = irClass.findPackage()
|
||||||
val moduleDescriptor = packageFragment.packageFragmentDescriptor.containingDeclaration
|
val moduleDescriptor = packageFragment.packageFragmentDescriptor.containingDeclaration
|
||||||
@@ -474,18 +477,13 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context, va
|
|||||||
return emptyList()
|
return emptyList()
|
||||||
val moduleDeserializer = context.irLinker.cachedLibraryModuleDeserializers[moduleDescriptor]
|
val moduleDeserializer = context.irLinker.cachedLibraryModuleDeserializers[moduleDescriptor]
|
||||||
?: error("No module deserializer for ${irClass.render()}")
|
?: error("No module deserializer for ${irClass.render()}")
|
||||||
val fields = moduleDeserializer.deserializeClassFields(irClass).toMutableList()
|
return moduleDeserializer.deserializeClassFields(irClass, outerThisField)
|
||||||
if (irClass.isInner)
|
|
||||||
fields.add(InnerClassLowering.addOuterThisField(mutableListOf(), irClass, context).toFieldInfo())
|
|
||||||
return fields
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val declarations: List<IrDeclaration> = if (irClass.isInner && !isLowered) {
|
val declarations = irClass.declarations.toMutableList()
|
||||||
// Note: copying to avoid mutation of the original class.
|
outerThisField?.let {
|
||||||
irClass.declarations.toMutableList()
|
if (!declarations.contains(it))
|
||||||
.also { InnerClassLowering.addOuterThisField(it, irClass, context) }
|
declarations += it
|
||||||
} else {
|
|
||||||
irClass.declarations
|
|
||||||
}
|
}
|
||||||
return declarations.mapNotNull {
|
return declarations.mapNotNull {
|
||||||
when (it) {
|
when (it) {
|
||||||
|
|||||||
+2
-9
@@ -119,14 +119,6 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
InnerClassTransformer(irClass).lowerInnerClass()
|
InnerClassTransformer(irClass).lowerInnerClass()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun addOuterThisField(declarations: MutableList<IrDeclaration>, irClass: IrClass, context: Context): IrField {
|
|
||||||
val outerThisField = context.specialDeclarationsFactory.getOuterThisField(irClass)
|
|
||||||
declarations += outerThisField
|
|
||||||
return outerThisField
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private inner class InnerClassTransformer(val irClass: IrClass) {
|
private inner class InnerClassTransformer(val irClass: IrClass) {
|
||||||
lateinit var outerThisFieldSymbol: IrFieldSymbol
|
lateinit var outerThisFieldSymbol: IrFieldSymbol
|
||||||
|
|
||||||
@@ -138,7 +130,8 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createOuterThisField() {
|
private fun createOuterThisField() {
|
||||||
val outerThisField = addOuterThisField(irClass.declarations, irClass, context)
|
val outerThisField = context.specialDeclarationsFactory.getOuterThisField(irClass)
|
||||||
|
irClass.declarations += outerThisField
|
||||||
outerThisFieldSymbol = outerThisField.symbol
|
outerThisFieldSymbol = outerThisField.symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+84
-48
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.backend.konan.*
|
|||||||
import org.jetbrains.kotlin.backend.konan.descriptors.ClassLayoutBuilder
|
import org.jetbrains.kotlin.backend.konan.descriptors.ClassLayoutBuilder
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.findPackage
|
import org.jetbrains.kotlin.backend.konan.descriptors.findPackage
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isInteropLibrary
|
import org.jetbrains.kotlin.backend.konan.descriptors.isInteropLibrary
|
||||||
|
import org.jetbrains.kotlin.backend.konan.descriptors.toFieldInfo
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs
|
import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin
|
import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin
|
||||||
@@ -92,14 +93,14 @@ internal class ByteArrayStream(val buf: ByteArray) {
|
|||||||
|
|
||||||
class SerializedInlineFunctionReference(val file: Int, val functionSignature: Int, val body: Int,
|
class SerializedInlineFunctionReference(val file: Int, val functionSignature: Int, val body: Int,
|
||||||
val startOffset: Int, val endOffset: Int,
|
val startOffset: Int, val endOffset: Int,
|
||||||
val extensionReceiverSig: Int, val dispatchReceiverSig: Int,
|
val extensionReceiverSig: Int, val dispatchReceiverSig: Int, val outerReceiverSigs: IntArray,
|
||||||
val valueParameterSigs: IntArray, val typeParameterSigs: IntArray,
|
val valueParameterSigs: IntArray, val typeParameterSigs: IntArray,
|
||||||
val defaultValues: IntArray)
|
val defaultValues: IntArray)
|
||||||
|
|
||||||
internal object InlineFunctionBodyReferenceSerializer {
|
internal object InlineFunctionBodyReferenceSerializer {
|
||||||
fun serialize(bodies: List<SerializedInlineFunctionReference>): ByteArray {
|
fun serialize(bodies: List<SerializedInlineFunctionReference>): ByteArray {
|
||||||
val size = bodies.sumOf {
|
val size = bodies.sumOf {
|
||||||
Int.SIZE_BYTES * (10 + it.valueParameterSigs.size + it.typeParameterSigs.size + it.defaultValues.size)
|
Int.SIZE_BYTES * (11 + it.outerReceiverSigs.size + it.valueParameterSigs.size + it.typeParameterSigs.size + it.defaultValues.size)
|
||||||
}
|
}
|
||||||
val stream = ByteArrayStream(ByteArray(size))
|
val stream = ByteArrayStream(ByteArray(size))
|
||||||
bodies.forEach {
|
bodies.forEach {
|
||||||
@@ -110,6 +111,8 @@ internal object InlineFunctionBodyReferenceSerializer {
|
|||||||
stream.writeInt(it.endOffset)
|
stream.writeInt(it.endOffset)
|
||||||
stream.writeInt(it.extensionReceiverSig)
|
stream.writeInt(it.extensionReceiverSig)
|
||||||
stream.writeInt(it.dispatchReceiverSig)
|
stream.writeInt(it.dispatchReceiverSig)
|
||||||
|
stream.writeInt(it.outerReceiverSigs.size)
|
||||||
|
it.outerReceiverSigs.forEach { sig -> stream.writeInt(sig) }
|
||||||
stream.writeInt(it.valueParameterSigs.size)
|
stream.writeInt(it.valueParameterSigs.size)
|
||||||
it.valueParameterSigs.forEach { sig -> stream.writeInt(sig) }
|
it.valueParameterSigs.forEach { sig -> stream.writeInt(sig) }
|
||||||
stream.writeInt(it.typeParameterSigs.size)
|
stream.writeInt(it.typeParameterSigs.size)
|
||||||
@@ -131,6 +134,8 @@ internal object InlineFunctionBodyReferenceSerializer {
|
|||||||
val endOffset = stream.readInt()
|
val endOffset = stream.readInt()
|
||||||
val extensionReceiverSig = stream.readInt()
|
val extensionReceiverSig = stream.readInt()
|
||||||
val dispatchReceiverSig = stream.readInt()
|
val dispatchReceiverSig = stream.readInt()
|
||||||
|
val outerReceiverSigsCount = stream.readInt()
|
||||||
|
val outerReceiverSigs = IntArray(outerReceiverSigsCount) { stream.readInt() }
|
||||||
val valueParameterSigsCount = stream.readInt()
|
val valueParameterSigsCount = stream.readInt()
|
||||||
val valueParameterSigs = IntArray(valueParameterSigsCount) { stream.readInt() }
|
val valueParameterSigs = IntArray(valueParameterSigsCount) { stream.readInt() }
|
||||||
val typeParameterSigsCount = stream.readInt()
|
val typeParameterSigsCount = stream.readInt()
|
||||||
@@ -138,7 +143,7 @@ internal object InlineFunctionBodyReferenceSerializer {
|
|||||||
val defaultValuesCount = stream.readInt()
|
val defaultValuesCount = stream.readInt()
|
||||||
val defaultValues = IntArray(defaultValuesCount) { stream.readInt() }
|
val defaultValues = IntArray(defaultValuesCount) { stream.readInt() }
|
||||||
result.add(SerializedInlineFunctionReference(file, functionSignature, body, startOffset, endOffset,
|
result.add(SerializedInlineFunctionReference(file, functionSignature, body, startOffset, endOffset,
|
||||||
extensionReceiverSig, dispatchReceiverSig, valueParameterSigs, typeParameterSigs, defaultValues))
|
extensionReceiverSig, dispatchReceiverSig, outerReceiverSigs, valueParameterSigs, typeParameterSigs, defaultValues))
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -153,18 +158,19 @@ class SerializedClassFieldInfo(val name: Int, val binaryType: Int, val type: Int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SerializedClassFields(val file: Int, val classSignature: Int,
|
class SerializedClassFields(val file: Int, val classSignature: Int, val typeParameterSigs: IntArray,
|
||||||
val typeParameterSigs: IntArray, val fields: Array<SerializedClassFieldInfo>)
|
val outerThisIndex: Int, val fields: Array<SerializedClassFieldInfo>)
|
||||||
|
|
||||||
internal object ClassFieldsSerializer {
|
internal object ClassFieldsSerializer {
|
||||||
fun serialize(classFields: List<SerializedClassFields>): ByteArray {
|
fun serialize(classFields: List<SerializedClassFields>): ByteArray {
|
||||||
val size = classFields.sumOf { Int.SIZE_BYTES * (4 + it.typeParameterSigs.size + it.fields.size * 4) }
|
val size = classFields.sumOf { Int.SIZE_BYTES * (5 + it.typeParameterSigs.size + it.fields.size * 4) }
|
||||||
val stream = ByteArrayStream(ByteArray(size))
|
val stream = ByteArrayStream(ByteArray(size))
|
||||||
classFields.forEach {
|
classFields.forEach {
|
||||||
stream.writeInt(it.file)
|
stream.writeInt(it.file)
|
||||||
stream.writeInt(it.classSignature)
|
stream.writeInt(it.classSignature)
|
||||||
stream.writeInt(it.typeParameterSigs.size)
|
stream.writeInt(it.typeParameterSigs.size)
|
||||||
it.typeParameterSigs.forEach { stream.writeInt(it) }
|
it.typeParameterSigs.forEach { stream.writeInt(it) }
|
||||||
|
stream.writeInt(it.outerThisIndex)
|
||||||
stream.writeInt(it.fields.size)
|
stream.writeInt(it.fields.size)
|
||||||
it.fields.forEach { field ->
|
it.fields.forEach { field ->
|
||||||
stream.writeInt(field.name)
|
stream.writeInt(field.name)
|
||||||
@@ -184,6 +190,7 @@ internal object ClassFieldsSerializer {
|
|||||||
val classSignature = stream.readInt()
|
val classSignature = stream.readInt()
|
||||||
val typeParameterSigsCount = stream.readInt()
|
val typeParameterSigsCount = stream.readInt()
|
||||||
val typeParameterSigs = IntArray(typeParameterSigsCount) { stream.readInt() }
|
val typeParameterSigs = IntArray(typeParameterSigsCount) { stream.readInt() }
|
||||||
|
val outerThisIndex = stream.readInt()
|
||||||
val fieldsCount = stream.readInt()
|
val fieldsCount = stream.readInt()
|
||||||
val fields = Array(fieldsCount) {
|
val fields = Array(fieldsCount) {
|
||||||
val name = stream.readInt()
|
val name = stream.readInt()
|
||||||
@@ -192,7 +199,7 @@ internal object ClassFieldsSerializer {
|
|||||||
val flags = stream.readInt()
|
val flags = stream.readInt()
|
||||||
SerializedClassFieldInfo(name, binaryType, type, flags)
|
SerializedClassFieldInfo(name, binaryType, type, flags)
|
||||||
}
|
}
|
||||||
result.add(SerializedClassFields(file, classSignature, typeParameterSigs, fields))
|
result.add(SerializedClassFields(file, classSignature, typeParameterSigs, outerThisIndex, fields))
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -412,6 +419,7 @@ internal class KonanIrLinker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val typeParameterSigs = mutableListOf<Int>()
|
val typeParameterSigs = mutableListOf<Int>()
|
||||||
|
val outerReceiverSigs = mutableListOf<Int>()
|
||||||
val protoFunction = if (outerClasses.isEmpty()) {
|
val protoFunction = if (outerClasses.isEmpty()) {
|
||||||
val irProperty = (irFunction as? IrSimpleFunction)?.correspondingPropertySymbol?.owner
|
val irProperty = (irFunction as? IrSimpleFunction)?.correspondingPropertySymbol?.owner
|
||||||
if (irProperty == null)
|
if (irProperty == null)
|
||||||
@@ -426,8 +434,11 @@ internal class KonanIrLinker(
|
|||||||
BinarySymbolData.decode(protoClass.getTypeParameter(it).base.symbol).signatureId
|
BinarySymbolData.decode(protoClass.getTypeParameter(it).base.symbol).signatureId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (classIndex < outerClasses.size - 1)
|
if (classIndex < outerClasses.size - 1) {
|
||||||
|
if (classIndex >= firstNotInnerClassIndex)
|
||||||
|
outerReceiverSigs.add(BinarySymbolData.decode(protoClass.thisReceiver.base.symbol).signatureId)
|
||||||
protoClass = protoClass.findClass(outerClasses[classIndex + 1], fileReader, symbolDeserializer)
|
protoClass = protoClass.findClass(outerClasses[classIndex + 1], fileReader, symbolDeserializer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
protoClass.findInlineFunction(irFunction, fileReader, symbolDeserializer)
|
protoClass.findInlineFunction(irFunction, fileReader, symbolDeserializer)
|
||||||
}
|
}
|
||||||
@@ -450,7 +461,7 @@ internal class KonanIrLinker(
|
|||||||
} ?: InvalidIndex
|
} ?: InvalidIndex
|
||||||
|
|
||||||
return SerializedInlineFunctionReference(fileDeserializationState.fileIndex, functionSignature, protoFunction.base.body,
|
return SerializedInlineFunctionReference(fileDeserializationState.fileIndex, functionSignature, protoFunction.base.body,
|
||||||
irFunction.startOffset, irFunction.endOffset, extensionReceiverSig, dispatchReceiverSig,
|
irFunction.startOffset, irFunction.endOffset, extensionReceiverSig, dispatchReceiverSig, outerReceiverSigs.toIntArray(),
|
||||||
valueParameterSigs.toIntArray(), typeParameterSigs.toIntArray(), defaultValues.toIntArray())
|
valueParameterSigs.toIntArray(), typeParameterSigs.toIntArray(), defaultValues.toIntArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,6 +483,7 @@ internal class KonanIrLinker(
|
|||||||
|
|
||||||
val typeParameterSigs = mutableListOf<Int>()
|
val typeParameterSigs = mutableListOf<Int>()
|
||||||
var protoClass = protoDeclaration.irClass
|
var protoClass = protoDeclaration.irClass
|
||||||
|
val protoClasses = mutableListOf(protoClass)
|
||||||
val firstNotInnerClassIndex = outerClasses.indexOfLast { !it.isInner }
|
val firstNotInnerClassIndex = outerClasses.indexOfLast { !it.isInner }
|
||||||
for (classIndex in outerClasses.indices) {
|
for (classIndex in outerClasses.indices) {
|
||||||
if (classIndex >= firstNotInnerClassIndex /* owner's type parameters are always accessible */) {
|
if (classIndex >= firstNotInnerClassIndex /* owner's type parameters are always accessible */) {
|
||||||
@@ -479,8 +491,10 @@ internal class KonanIrLinker(
|
|||||||
BinarySymbolData.decode(protoClass.getTypeParameter(it).base.symbol).signatureId
|
BinarySymbolData.decode(protoClass.getTypeParameter(it).base.symbol).signatureId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (classIndex < outerClasses.size - 1)
|
if (classIndex < outerClasses.size - 1) {
|
||||||
protoClass = protoClass.findClass(outerClasses[classIndex + 1], fileReader, symbolDeserializer)
|
protoClass = protoClass.findClass(outerClasses[classIndex + 1], fileReader, symbolDeserializer)
|
||||||
|
protoClasses += protoClass
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val protoFields = mutableListOf<ProtoField>()
|
val protoFields = mutableListOf<ProtoField>()
|
||||||
@@ -504,31 +518,43 @@ internal class KonanIrLinker(
|
|||||||
protoFieldsMap[name] = it
|
protoFieldsMap[name] = it
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val outerThisIndex = fields.indexOfFirst { it.irField?.origin == SpecialDeclarationsFactory.DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS }
|
||||||
val compatibleMode = CompatibilityMode(libraryAbiVersion).oldSignatures
|
val compatibleMode = CompatibilityMode(libraryAbiVersion).oldSignatures
|
||||||
return SerializedClassFields(
|
return SerializedClassFields(
|
||||||
fileDeserializationState.fileIndex,
|
fileDeserializationState.fileIndex,
|
||||||
BinarySymbolData.decode(protoClass.base.symbol).signatureId,
|
BinarySymbolData.decode(protoClass.base.symbol).signatureId,
|
||||||
typeParameterSigs.toIntArray(),
|
typeParameterSigs.toIntArray(),
|
||||||
|
outerThisIndex,
|
||||||
Array(fields.size) {
|
Array(fields.size) {
|
||||||
val field = fields[it]
|
val field = fields[it]
|
||||||
val irField = field.irField ?: error("No IR for field ${field.name} of ${irClass.render()}")
|
val irField = field.irField ?: error("No IR for field ${field.name} of ${irClass.render()}")
|
||||||
val protoField = protoFieldsMap[field.name] ?: error("No proto for ${irField.render()}")
|
if (it == outerThisIndex) {
|
||||||
val nameAndType = BinaryNameAndType.decode(protoField.nameType)
|
require(irClass.isInner) { "Expected an inner class: ${irClass.render()}" }
|
||||||
var flags = 0
|
require(protoClasses.size > 1) { "An inner class must have at least one outer class" }
|
||||||
if (field.isConst)
|
val outerProtoClass = protoClasses[protoClasses.size - 2]
|
||||||
flags = flags or SerializedClassFieldInfo.FLAG_IS_CONST
|
val nameAndType = BinaryNameAndType.decode(outerProtoClass.thisReceiver.nameType)
|
||||||
if (field.hasConstInitializer)
|
|
||||||
flags = flags or SerializedClassFieldInfo.FLAG_CONST_INITIALIZER
|
|
||||||
val classifier = irField.type.classifierOrNull ?: error("Fields of type ${irField.type.render()} are not supported")
|
|
||||||
val primitiveBinaryType = irField.type.computePrimitiveBinaryTypeOrNull()
|
|
||||||
|
|
||||||
SerializedClassFieldInfo(
|
SerializedClassFieldInfo(name = InvalidIndex, binaryType = InvalidIndex, nameAndType.typeIndex, flags = 0)
|
||||||
nameAndType.nameIndex,
|
} else {
|
||||||
primitiveBinaryType?.ordinal ?: InvalidIndex,
|
val protoField = protoFieldsMap[field.name] ?: error("No proto for ${irField.render()}")
|
||||||
if (with(KonanManglerIr) { (classifier as? IrClassSymbol)?.owner?.isExported(compatibleMode) } == false)
|
val nameAndType = BinaryNameAndType.decode(protoField.nameType)
|
||||||
InvalidIndex
|
var flags = 0
|
||||||
else nameAndType.typeIndex,
|
if (field.isConst)
|
||||||
flags)
|
flags = flags or SerializedClassFieldInfo.FLAG_IS_CONST
|
||||||
|
if (field.hasConstInitializer)
|
||||||
|
flags = flags or SerializedClassFieldInfo.FLAG_CONST_INITIALIZER
|
||||||
|
val classifier = irField.type.classifierOrNull
|
||||||
|
?: error("Fields of type ${irField.type.render()} are not supported")
|
||||||
|
val primitiveBinaryType = irField.type.computePrimitiveBinaryTypeOrNull()
|
||||||
|
|
||||||
|
SerializedClassFieldInfo(
|
||||||
|
nameAndType.nameIndex,
|
||||||
|
primitiveBinaryType?.ordinal ?: InvalidIndex,
|
||||||
|
if (with(KonanManglerIr) { (classifier as? IrClassSymbol)?.owner?.isExported(compatibleMode) } == false)
|
||||||
|
InvalidIndex
|
||||||
|
else nameAndType.typeIndex,
|
||||||
|
flags)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -732,6 +758,10 @@ internal class KonanIrLinker(
|
|||||||
require(sigIndex != InvalidIndex) { "Expected a valid sig reference to the dispatch receiver for ${function.render()}" }
|
require(sigIndex != InvalidIndex) { "Expected a valid sig reference to the dispatch receiver for ${function.render()}" }
|
||||||
symbolDeserializer.referenceLocalIrSymbol(parameter.symbol, symbolDeserializer.deserializeIdSignature(sigIndex))
|
symbolDeserializer.referenceLocalIrSymbol(parameter.symbol, symbolDeserializer.deserializeIdSignature(sigIndex))
|
||||||
}
|
}
|
||||||
|
for (index in 0 until outerClasses.size - 1) {
|
||||||
|
val sigIndex = inlineFunctionReference.outerReceiverSigs[index]
|
||||||
|
symbolDeserializer.referenceLocalIrSymbol(outerClasses[index].thisReceiver!!.symbol, symbolDeserializer.deserializeIdSignature(sigIndex))
|
||||||
|
}
|
||||||
|
|
||||||
function.body = declarationDeserializer.deserializeStatementBody(inlineFunctionReference.body) as IrBody
|
function.body = declarationDeserializer.deserializeStatementBody(inlineFunctionReference.body) as IrBody
|
||||||
|
|
||||||
@@ -759,7 +789,7 @@ internal class KonanIrLinker(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deserializeClassFields(irClass: IrClass): List<ClassLayoutBuilder.FieldInfo> {
|
fun deserializeClassFields(irClass: IrClass, outerThisField: IrField?): List<ClassLayoutBuilder.FieldInfo> {
|
||||||
val signature = irClass.symbol.signature
|
val signature = irClass.symbol.signature
|
||||||
?: error("No signature for ${irClass.render()}")
|
?: error("No signature for ${irClass.render()}")
|
||||||
val serializedClassFields = classesFields[signature]
|
val serializedClassFields = classesFields[signature]
|
||||||
@@ -786,29 +816,35 @@ internal class KonanIrLinker(
|
|||||||
return symbolDeserializer.deserializePublicSymbol(classIdSig, BinarySymbolData.SymbolKind.CLASS_SYMBOL) as IrClassSymbol
|
return symbolDeserializer.deserializePublicSymbol(classIdSig, BinarySymbolData.SymbolKind.CLASS_SYMBOL) as IrClassSymbol
|
||||||
}
|
}
|
||||||
|
|
||||||
return serializedClassFields.fields.map {
|
return serializedClassFields.fields.mapIndexed { index, field ->
|
||||||
val name = fileDeserializationInfo.fileReader.string(it.name)
|
if (index == serializedClassFields.outerThisIndex) {
|
||||||
val type = when {
|
require(irClass.isInner) { "Expected an inner class: ${irClass.render()}" }
|
||||||
it.type != InvalidIndex -> declarationDeserializer.deserializeIrType(it.type)
|
require(outerThisField != null) { "For an inner class ${irClass.render()} there should be <outer this> field" }
|
||||||
it.binaryType == InvalidIndex -> builtIns.anyNType
|
outerThisField.toFieldInfo()
|
||||||
else -> when (PrimitiveBinaryType.values().getOrNull(it.binaryType)) {
|
} else {
|
||||||
PrimitiveBinaryType.BOOLEAN -> builtIns.booleanType
|
val name = fileDeserializationInfo.fileReader.string(field.name)
|
||||||
PrimitiveBinaryType.BYTE -> builtIns.byteType
|
val type = when {
|
||||||
PrimitiveBinaryType.SHORT -> builtIns.shortType
|
field.type != InvalidIndex -> declarationDeserializer.deserializeIrType(field.type)
|
||||||
PrimitiveBinaryType.INT -> builtIns.intType
|
field.binaryType == InvalidIndex -> builtIns.anyNType
|
||||||
PrimitiveBinaryType.LONG -> builtIns.longType
|
else -> when (PrimitiveBinaryType.values().getOrNull(field.binaryType)) {
|
||||||
PrimitiveBinaryType.FLOAT -> builtIns.floatType
|
PrimitiveBinaryType.BOOLEAN -> builtIns.booleanType
|
||||||
PrimitiveBinaryType.DOUBLE -> builtIns.doubleType
|
PrimitiveBinaryType.BYTE -> builtIns.byteType
|
||||||
PrimitiveBinaryType.POINTER -> getByClassId(KonanPrimitiveType.NON_NULL_NATIVE_PTR.classId).defaultType
|
PrimitiveBinaryType.SHORT -> builtIns.shortType
|
||||||
PrimitiveBinaryType.VECTOR128 -> getByClassId(KonanPrimitiveType.VECTOR128.classId).defaultType
|
PrimitiveBinaryType.INT -> builtIns.intType
|
||||||
else -> error("Bad binary type of field $name of ${irClass.render()}")
|
PrimitiveBinaryType.LONG -> builtIns.longType
|
||||||
|
PrimitiveBinaryType.FLOAT -> builtIns.floatType
|
||||||
|
PrimitiveBinaryType.DOUBLE -> builtIns.doubleType
|
||||||
|
PrimitiveBinaryType.POINTER -> getByClassId(KonanPrimitiveType.NON_NULL_NATIVE_PTR.classId).defaultType
|
||||||
|
PrimitiveBinaryType.VECTOR128 -> getByClassId(KonanPrimitiveType.VECTOR128.classId).defaultType
|
||||||
|
else -> error("Bad binary type of field $name of ${irClass.render()}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
ClassLayoutBuilder.FieldInfo(
|
||||||
|
name, type,
|
||||||
|
isConst = (field.flags and SerializedClassFieldInfo.FLAG_IS_CONST) != 0,
|
||||||
|
hasConstInitializer = (field.flags and SerializedClassFieldInfo.FLAG_CONST_INITIALIZER) != 0,
|
||||||
|
irField = null)
|
||||||
}
|
}
|
||||||
ClassLayoutBuilder.FieldInfo(
|
|
||||||
name, type,
|
|
||||||
isConst = (it.flags and SerializedClassFieldInfo.FLAG_IS_CONST) != 0,
|
|
||||||
hasConstInitializer = (it.flags and SerializedClassFieldInfo.FLAG_CONST_INITIALIZER) != 0,
|
|
||||||
irField = null)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1416,6 +1416,24 @@ linkTest("innerClass_linkTest") {
|
|||||||
lib = "codegen/innerClass/linkTest_lib.kt"
|
lib = "codegen/innerClass/linkTest_lib.kt"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
linkTest("innerClass_inheritance_linkTest") {
|
||||||
|
useGoldenData = true
|
||||||
|
source = "codegen/innerClass/inheritance_linkTest_main.kt"
|
||||||
|
lib = "codegen/innerClass/inheritance_linkTest_lib.kt"
|
||||||
|
}
|
||||||
|
|
||||||
|
linkTest("innerClass_inheritance2_linkTest") {
|
||||||
|
useGoldenData = true
|
||||||
|
source = "codegen/innerClass/inheritance2_linkTest_main.kt"
|
||||||
|
lib = "codegen/innerClass/inheritance2_linkTest_lib.kt"
|
||||||
|
}
|
||||||
|
|
||||||
|
linkTest("innerClass_inheritance3_linkTest") {
|
||||||
|
useGoldenData = true
|
||||||
|
source = "codegen/innerClass/inheritance3_linkTest_main.kt"
|
||||||
|
lib = "codegen/innerClass/inheritance3_linkTest_lib.kt"
|
||||||
|
}
|
||||||
|
|
||||||
task localClass_localHierarchy(type: KonanLocalTest) {
|
task localClass_localHierarchy(type: KonanLocalTest) {
|
||||||
useGoldenData = true
|
useGoldenData = true
|
||||||
source = "codegen/localClass/localHierarchy.kt"
|
source = "codegen/localClass/localHierarchy.kt"
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
open class Outer(val x: Int) {
|
||||||
|
open inner class Inner1
|
||||||
|
inner class Middle(x: Int) : Outer(x) {
|
||||||
|
inner class Inner2 : Inner1() {
|
||||||
|
fun foo() = this@Outer.x + this@Middle.x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val o = Outer(42).Middle(117).Inner2()
|
||||||
|
println(o.foo())
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
159
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
open class Outer {
|
||||||
|
open inner class Inner1
|
||||||
|
inner class Middle {
|
||||||
|
inner class Inner2 : Inner1() {
|
||||||
|
fun getOuter() = this@Outer
|
||||||
|
fun getMiddle() = this@Middle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val o = Outer().Middle().Inner2()
|
||||||
|
println(o.getOuter() != Outer())
|
||||||
|
println(o.getMiddle() != Outer().Middle())
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
true
|
||||||
|
true
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
open class Foo(val z: Int) {
|
||||||
|
open inner class FooInner {
|
||||||
|
fun foo() = z
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Bar : Foo(42) {
|
||||||
|
inner class BarInner(val x: Int) : FooInner()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val o = Bar().BarInner(117)
|
||||||
|
println(o.x)
|
||||||
|
println(o.foo())
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
117
|
||||||
|
42
|
||||||
Reference in New Issue
Block a user