[K/N][IR] Moved caches ABI lowerings to a separate file
This commit is contained in:
+4
-225
@@ -3,35 +3,26 @@ package org.jetbrains.kotlin.backend.konan
|
|||||||
import org.jetbrains.kotlin.backend.common.checkDeclarationParents
|
import org.jetbrains.kotlin.backend.common.checkDeclarationParents
|
||||||
import org.jetbrains.kotlin.backend.common.IrValidator
|
import org.jetbrains.kotlin.backend.common.IrValidator
|
||||||
import org.jetbrains.kotlin.backend.common.IrValidatorConfig
|
import org.jetbrains.kotlin.backend.common.IrValidatorConfig
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.atMostOne
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.*
|
import org.jetbrains.kotlin.backend.common.phaser.*
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode
|
import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer
|
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary
|
import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||||
|
import org.jetbrains.kotlin.backend.konan.lower.*
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.CacheInfoBuilder
|
import org.jetbrains.kotlin.backend.konan.lower.CacheInfoBuilder
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_ENUM
|
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.ExpectToActualDefaultValueCopier
|
import org.jetbrains.kotlin.backend.konan.lower.ExpectToActualDefaultValueCopier
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.SamSuperTypesChecker
|
import org.jetbrains.kotlin.backend.konan.lower.SamSuperTypesChecker
|
||||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
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.builders.*
|
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
|
||||||
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.*
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
|
||||||
import org.jetbrains.kotlin.ir.types.typeWith
|
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.*
|
import org.jetbrains.kotlin.ir.visitors.*
|
||||||
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
|
||||||
@@ -383,226 +374,14 @@ internal val exportInternalAbiPhase = makeKonanModuleOpPhase(
|
|||||||
name = "exportInternalAbi",
|
name = "exportInternalAbi",
|
||||||
description = "Add accessors to private entities",
|
description = "Add accessors to private entities",
|
||||||
prerequisite = emptySet(),
|
prerequisite = emptySet(),
|
||||||
op = { context, module ->
|
op = { context, module -> module.acceptChildrenVoid(ExportCachesAbiVisitor(context)) }
|
||||||
val visitor = object : IrElementVisitorVoid {
|
|
||||||
override fun visitElement(element: IrElement) {
|
|
||||||
element.acceptChildrenVoid(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitClass(declaration: IrClass) {
|
|
||||||
declaration.acceptChildrenVoid(this)
|
|
||||||
|
|
||||||
if (declaration.isLocal) return
|
|
||||||
|
|
||||||
if (declaration.isCompanion) {
|
|
||||||
val function = context.irFactory.buildFun {
|
|
||||||
name = InternalAbi.getCompanionObjectAccessorName(declaration)
|
|
||||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
|
||||||
returnType = declaration.defaultType
|
|
||||||
}
|
|
||||||
context.createIrBuilder(function.symbol).apply {
|
|
||||||
function.body = irBlockBody {
|
|
||||||
+irReturn(irGetObjectValue(declaration.defaultType, declaration.symbol))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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.innerClassesSupport.getOuterThisField(declaration))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
context.internalAbi.declare(function, declaration.module)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (declaration.isEnumClass) {
|
|
||||||
val function = context.irFactory.buildFun {
|
|
||||||
name = InternalAbi.getEnumValuesAccessorName(declaration)
|
|
||||||
returnType = context.ir.symbols.array.typeWith(declaration.defaultType)
|
|
||||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
|
||||||
}
|
|
||||||
|
|
||||||
context.createIrBuilder(function.symbol).run {
|
|
||||||
function.body = irBlockBody {
|
|
||||||
+irReturn(with(context.enumsSupport) { irGetValuesField(declaration) })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
context.internalAbi.declare(function, declaration.module)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitProperty(declaration: IrProperty) {
|
|
||||||
declaration.acceptChildrenVoid(this)
|
|
||||||
|
|
||||||
if (!declaration.isLateinit || declaration.isFakeOverride
|
|
||||||
|| DescriptorVisibilities.isPrivate(declaration.visibility) || declaration.isLocal)
|
|
||||||
return
|
|
||||||
|
|
||||||
val backingField = declaration.backingField ?: error("Lateinit property ${declaration.render()} should have a backing field")
|
|
||||||
val function = context.irFactory.buildFun {
|
|
||||||
name = InternalAbi.getLateinitPropertyFieldAccessorName(declaration)
|
|
||||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
|
||||||
returnType = backingField.type
|
|
||||||
}
|
|
||||||
val ownerClass = declaration.parentClassOrNull
|
|
||||||
if (ownerClass != null)
|
|
||||||
function.addValueParameter {
|
|
||||||
name = Name.identifier("owner")
|
|
||||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
|
||||||
type = ownerClass.defaultType
|
|
||||||
}
|
|
||||||
|
|
||||||
context.createIrBuilder(function.symbol).apply {
|
|
||||||
function.body = irBlockBody {
|
|
||||||
+irReturn(irGetField(ownerClass?.let { irGet(function.valueParameters[0]) }, backingField))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
context.internalAbi.declare(function, declaration.module)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
module.acceptChildrenVoid(visitor)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
internal val useInternalAbiPhase = makeKonanModuleOpPhase(
|
internal val useInternalAbiPhase = makeKonanModuleOpPhase(
|
||||||
name = "useInternalAbi",
|
name = "useInternalAbi",
|
||||||
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 -> module.transformChildrenVoid(ImportCachesAbiTransformer(context)) }
|
||||||
val companionObjectAccessors = mutableMapOf<IrClass, IrSimpleFunction>()
|
|
||||||
val outerThisAccessors = mutableMapOf<IrClass, IrSimpleFunction>()
|
|
||||||
val lateinitPropertyAccessors = mutableMapOf<IrProperty, IrSimpleFunction>()
|
|
||||||
val enumValuesAccessors = mutableMapOf<IrClass, IrSimpleFunction>()
|
|
||||||
|
|
||||||
val transformer = object : IrElementTransformerVoid() {
|
|
||||||
override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression {
|
|
||||||
expression.transformChildrenVoid(this)
|
|
||||||
|
|
||||||
val irClass = expression.symbol.owner
|
|
||||||
if (!irClass.isCompanion || context.llvmModuleSpecification.containsDeclaration(irClass)) {
|
|
||||||
return expression
|
|
||||||
}
|
|
||||||
val parent = irClass.parentAsClass
|
|
||||||
if (parent.isObjCClass()) {
|
|
||||||
// Access to Obj-C metaclass is done via intrinsic.
|
|
||||||
return expression
|
|
||||||
}
|
|
||||||
val accessor = companionObjectAccessors.getOrPut(irClass) {
|
|
||||||
context.irFactory.buildFun {
|
|
||||||
name = InternalAbi.getCompanionObjectAccessorName(irClass)
|
|
||||||
returnType = irClass.defaultType
|
|
||||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
|
||||||
isExternal = true
|
|
||||||
}.also {
|
|
||||||
context.internalAbi.reference(it, irClass.module)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return IrCallImpl(expression.startOffset, expression.endOffset, expression.type, accessor.symbol, accessor.typeParameters.size, accessor.valueParameters.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitGetField(expression: IrGetField): IrExpression {
|
|
||||||
expression.transformChildrenVoid(this)
|
|
||||||
|
|
||||||
val field = expression.symbol.owner
|
|
||||||
val irClass = field.parentClassOrNull
|
|
||||||
val property = field.correspondingPropertySymbol?.owner
|
|
||||||
|
|
||||||
return when {
|
|
||||||
context.llvmModuleSpecification.containsDeclaration(field) -> expression
|
|
||||||
|
|
||||||
irClass?.isInner == true && context.innerClassesSupport.getOuterThisField(irClass) == field -> {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
property?.isLateinit == true -> {
|
|
||||||
val accessor = lateinitPropertyAccessors.getOrPut(property) {
|
|
||||||
context.irFactory.buildFun {
|
|
||||||
name = InternalAbi.getLateinitPropertyFieldAccessorName(property)
|
|
||||||
returnType = field.type
|
|
||||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
|
||||||
isExternal = true
|
|
||||||
}.also { function ->
|
|
||||||
context.internalAbi.reference(function, property.module)
|
|
||||||
|
|
||||||
if (irClass != null)
|
|
||||||
function.addValueParameter {
|
|
||||||
name = Name.identifier("owner")
|
|
||||||
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 {
|
|
||||||
if (irClass != null)
|
|
||||||
putValueArgument(0, expression.receiver)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
field.origin == DECLARATION_ORIGIN_ENUM -> {
|
|
||||||
val enumClass = irClass?.parentClassOrNull
|
|
||||||
require(enumClass != null) { "Unexpected usage of enum VALUES field" }
|
|
||||||
require(enumClass.isEnumClass) { "Expected a enum class: ${enumClass.render()}" }
|
|
||||||
val accessor = enumValuesAccessors.getOrPut(enumClass) {
|
|
||||||
context.irFactory.buildFun {
|
|
||||||
name = InternalAbi.getEnumValuesAccessorName(enumClass)
|
|
||||||
returnType = context.ir.symbols.array.typeWith(enumClass.defaultType)
|
|
||||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
|
||||||
isExternal = true
|
|
||||||
}.also {
|
|
||||||
context.internalAbi.reference(it, enumClass.module)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return IrCallImpl(expression.startOffset, expression.endOffset, expression.type, accessor.symbol, accessor.typeParameters.size, accessor.valueParameters.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> expression
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
module.transformChildrenVoid(transformer)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
internal val bitcodePhase = NamedCompilerPhase(
|
internal val bitcodePhase = NamedCompilerPhase(
|
||||||
|
|||||||
+240
@@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.konan.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
|
import org.jetbrains.kotlin.backend.konan.InternalAbi
|
||||||
|
import org.jetbrains.kotlin.backend.konan.isObjCClass
|
||||||
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
|
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
||||||
|
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrGetField
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrGetObjectValue
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.types.typeWith
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
internal class ExportCachesAbiVisitor(val context: Context) : IrElementVisitorVoid {
|
||||||
|
override fun visitElement(element: IrElement) {
|
||||||
|
element.acceptChildrenVoid(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitClass(declaration: IrClass) {
|
||||||
|
declaration.acceptChildrenVoid(this)
|
||||||
|
|
||||||
|
if (declaration.isLocal) return
|
||||||
|
|
||||||
|
if (declaration.isCompanion) {
|
||||||
|
val function = context.irFactory.buildFun {
|
||||||
|
name = InternalAbi.getCompanionObjectAccessorName(declaration)
|
||||||
|
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||||
|
returnType = declaration.defaultType
|
||||||
|
}
|
||||||
|
context.createIrBuilder(function.symbol).apply {
|
||||||
|
function.body = irBlockBody {
|
||||||
|
+irReturn(irGetObjectValue(declaration.defaultType, declaration.symbol))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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]),
|
||||||
|
this@ExportCachesAbiVisitor.context.innerClassesSupport.getOuterThisField(declaration))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.internalAbi.declare(function, declaration.module)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (declaration.isEnumClass) {
|
||||||
|
val function = context.irFactory.buildFun {
|
||||||
|
name = InternalAbi.getEnumValuesAccessorName(declaration)
|
||||||
|
returnType = context.ir.symbols.array.typeWith(declaration.defaultType)
|
||||||
|
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||||
|
}
|
||||||
|
|
||||||
|
context.createIrBuilder(function.symbol).run {
|
||||||
|
function.body = irBlockBody {
|
||||||
|
+irReturn(with(this@ExportCachesAbiVisitor.context.enumsSupport) { irGetValuesField(declaration) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.internalAbi.declare(function, declaration.module)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitProperty(declaration: IrProperty) {
|
||||||
|
declaration.acceptChildrenVoid(this)
|
||||||
|
|
||||||
|
if (!declaration.isLateinit || declaration.isFakeOverride
|
||||||
|
|| DescriptorVisibilities.isPrivate(declaration.visibility) || declaration.isLocal)
|
||||||
|
return
|
||||||
|
|
||||||
|
val backingField = declaration.backingField ?: error("Lateinit property ${declaration.render()} should have a backing field")
|
||||||
|
val function = context.irFactory.buildFun {
|
||||||
|
name = InternalAbi.getLateinitPropertyFieldAccessorName(declaration)
|
||||||
|
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||||
|
returnType = backingField.type
|
||||||
|
}
|
||||||
|
val ownerClass = declaration.parentClassOrNull
|
||||||
|
if (ownerClass != null)
|
||||||
|
function.addValueParameter {
|
||||||
|
name = Name.identifier("owner")
|
||||||
|
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||||
|
type = ownerClass.defaultType
|
||||||
|
}
|
||||||
|
|
||||||
|
context.createIrBuilder(function.symbol).apply {
|
||||||
|
function.body = irBlockBody {
|
||||||
|
+irReturn(irGetField(ownerClass?.let { irGet(function.valueParameters[0]) }, backingField))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.internalAbi.declare(function, declaration.module)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ImportCachesAbiTransformer(val context: Context) : IrElementTransformerVoid() {
|
||||||
|
private val companionObjectAccessors = mutableMapOf<IrClass, IrSimpleFunction>()
|
||||||
|
private val outerThisAccessors = mutableMapOf<IrClass, IrSimpleFunction>()
|
||||||
|
private val lateinitPropertyAccessors = mutableMapOf<IrProperty, IrSimpleFunction>()
|
||||||
|
private val enumValuesAccessors = mutableMapOf<IrClass, IrSimpleFunction>()
|
||||||
|
|
||||||
|
override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression {
|
||||||
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
|
val irClass = expression.symbol.owner
|
||||||
|
if (!irClass.isCompanion || context.llvmModuleSpecification.containsDeclaration(irClass)) {
|
||||||
|
return expression
|
||||||
|
}
|
||||||
|
val parent = irClass.parentAsClass
|
||||||
|
if (parent.isObjCClass()) {
|
||||||
|
// Access to Obj-C metaclass is done via intrinsic.
|
||||||
|
return expression
|
||||||
|
}
|
||||||
|
val accessor = companionObjectAccessors.getOrPut(irClass) {
|
||||||
|
context.irFactory.buildFun {
|
||||||
|
name = InternalAbi.getCompanionObjectAccessorName(irClass)
|
||||||
|
returnType = irClass.defaultType
|
||||||
|
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||||
|
isExternal = true
|
||||||
|
}.also {
|
||||||
|
context.internalAbi.reference(it, irClass.module)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return IrCallImpl(expression.startOffset, expression.endOffset, expression.type, accessor.symbol, accessor.typeParameters.size, accessor.valueParameters.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitGetField(expression: IrGetField): IrExpression {
|
||||||
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
|
val field = expression.symbol.owner
|
||||||
|
val irClass = field.parentClassOrNull
|
||||||
|
val property = field.correspondingPropertySymbol?.owner
|
||||||
|
|
||||||
|
return when {
|
||||||
|
context.llvmModuleSpecification.containsDeclaration(field) -> expression
|
||||||
|
|
||||||
|
irClass?.isInner == true && context.innerClassesSupport.getOuterThisField(irClass) == field -> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
property?.isLateinit == true -> {
|
||||||
|
val accessor = lateinitPropertyAccessors.getOrPut(property) {
|
||||||
|
context.irFactory.buildFun {
|
||||||
|
name = InternalAbi.getLateinitPropertyFieldAccessorName(property)
|
||||||
|
returnType = field.type
|
||||||
|
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||||
|
isExternal = true
|
||||||
|
}.also { function ->
|
||||||
|
context.internalAbi.reference(function, property.module)
|
||||||
|
|
||||||
|
if (irClass != null)
|
||||||
|
function.addValueParameter {
|
||||||
|
name = Name.identifier("owner")
|
||||||
|
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 {
|
||||||
|
if (irClass != null)
|
||||||
|
putValueArgument(0, expression.receiver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
field.origin == DECLARATION_ORIGIN_ENUM -> {
|
||||||
|
val enumClass = irClass?.parentClassOrNull
|
||||||
|
require(enumClass != null) { "Unexpected usage of enum VALUES field" }
|
||||||
|
require(enumClass.isEnumClass) { "Expected a enum class: ${enumClass.render()}" }
|
||||||
|
val accessor = enumValuesAccessors.getOrPut(enumClass) {
|
||||||
|
context.irFactory.buildFun {
|
||||||
|
name = InternalAbi.getEnumValuesAccessorName(enumClass)
|
||||||
|
returnType = context.ir.symbols.array.typeWith(enumClass.defaultType)
|
||||||
|
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||||
|
isExternal = true
|
||||||
|
}.also {
|
||||||
|
context.internalAbi.reference(it, enumClass.module)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return IrCallImpl(expression.startOffset, expression.endOffset, expression.type, accessor.symbol, accessor.typeParameters.size, accessor.valueParameters.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> expression
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user