[Native] Move proto utils from KonanIrLinker into separate utils file

This commit is contained in:
Ivan Kylchik
2023-08-15 14:15:27 +02:00
committed by Space Team
parent 66b9c2f260
commit 70697af6b9
2 changed files with 122 additions and 103 deletions
@@ -20,17 +20,18 @@ import org.jetbrains.kotlin.backend.common.linkage.issues.UserVisibleIrModulesSu
import org.jetbrains.kotlin.backend.common.linkage.partial.PartialLinkageSupportForLinker
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideClassFilter
import org.jetbrains.kotlin.backend.common.serialization.*
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinaryNameAndType
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
import org.jetbrains.kotlin.backend.common.serialization.encodings.FunctionFlags
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.common.serialization.DeserializationStrategy
import org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker
import org.jetbrains.kotlin.backend.konan.CacheDeserializationStrategy
import org.jetbrains.kotlin.backend.konan.CachedLibraries
import org.jetbrains.kotlin.backend.konan.InlineFunctionOriginInfo
import org.jetbrains.kotlin.backend.konan.PartialCacheInfo
import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary
import org.jetbrains.kotlin.backend.konan.descriptors.isInteropLibrary
import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs
import org.jetbrains.kotlin.backend.konan.ir.konanLibrary
import org.jetbrains.kotlin.backend.konan.ir.isFromInteropLibraryByDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.backend.konan.ir.konanLibrary
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
import org.jetbrains.kotlin.ir.IrBuiltIns
@@ -40,15 +41,12 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrPublicSymbolBase
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.metadata.impl.KlibResolvedModuleDescriptorsFactoryImpl.Companion.FORWARD_DECLARATIONS_MODULE_NAME
import sun.misc.Unsafe
import org.jetbrains.kotlin.backend.common.serialization.proto.IrClass as ProtoClass
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclaration as ProtoDeclaration
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFunction as ProtoFunction
import org.jetbrains.kotlin.backend.common.serialization.proto.IrProperty as ProtoProperty
private val unsafe = with(Unsafe::class.java.getDeclaredField("theUnsafe")) {
isAccessible = true
@@ -317,97 +315,6 @@ internal object EagerInitializedPropertySerializer {
}
}
internal fun ProtoClass.findClass(irClass: IrClass, fileReader: IrLibraryFile, symbolDeserializer: IrSymbolDeserializer): ProtoClass {
val signature = irClass.symbol.signature ?: error("No signature for ${irClass.render()}")
var result: ProtoClass? = null
for (i in 0 until this.declarationCount) {
val child = this.getDeclaration(i)
val childClass = when {
child.declaratorCase == ProtoDeclaration.DeclaratorCase.IR_CLASS -> child.irClass
child.declaratorCase == ProtoDeclaration.DeclaratorCase.IR_ENUM_ENTRY
&& child.irEnumEntry.hasCorrespondingClass() -> child.irEnumEntry.correspondingClass
else -> continue
}
val name = fileReader.string(childClass.name)
if (name == irClass.name.asString()) {
if (result == null)
result = childClass
else {
val resultIdSignature = symbolDeserializer.deserializeIdSignature(BinarySymbolData.decode(result.base.symbol).signatureId)
if (resultIdSignature == signature)
return result
result = childClass
}
}
}
return result ?: error("Class ${irClass.render()} is not found")
}
internal fun ProtoClass.findProperty(irProperty: IrProperty, fileReader: IrLibraryFile, symbolDeserializer: IrSymbolDeserializer): ProtoProperty {
val signature = irProperty.symbol.signature ?: error("No signature for ${irProperty.render()}")
var result: ProtoProperty? = null
for (i in 0 until this.declarationCount) {
val child = this.getDeclaration(i)
if (child.declaratorCase != ProtoDeclaration.DeclaratorCase.IR_PROPERTY) continue
val childProperty = child.irProperty
val name = fileReader.string(child.irProperty.name)
if (name == irProperty.name.asString()) {
if (result == null)
result = childProperty
else {
val resultIdSignature = symbolDeserializer.deserializeIdSignature(BinarySymbolData.decode(result.base.symbol).signatureId)
if (resultIdSignature == signature)
return result
result = childProperty
}
}
}
return result ?: error("Property ${irProperty.render()} is not found")
}
internal fun ProtoProperty.findAccessor(irProperty: IrProperty, irFunction: IrSimpleFunction): ProtoFunction {
if (irFunction == irProperty.getter)
return getter
require(irFunction == irProperty.setter) { "Accessor should be either a getter or a setter. ${irFunction.render()}" }
return setter
}
internal fun ProtoClass.findInlineFunction(irFunction: IrFunction, fileReader: IrLibraryFile, symbolDeserializer: IrSymbolDeserializer): ProtoFunction {
(irFunction as? IrSimpleFunction)?.correspondingPropertySymbol?.owner?.let { irProperty ->
return findProperty(irProperty, fileReader, symbolDeserializer).findAccessor(irProperty, irFunction)
}
val signature = irFunction.symbol.signature ?: error("No signature for ${irFunction.render()}")
var result: ProtoFunction? = null
for (i in 0 until this.declarationCount) {
val child = this.getDeclaration(i)
if (child.declaratorCase != ProtoDeclaration.DeclaratorCase.IR_FUNCTION) continue
val childFunction = child.irFunction
if (childFunction.base.valueParameterCount != irFunction.valueParameters.size) continue
if (childFunction.base.hasExtensionReceiver() xor (irFunction.extensionReceiverParameter != null)) continue
if (childFunction.base.hasDispatchReceiver() xor (irFunction.dispatchReceiverParameter != null)) continue
if (!FunctionFlags.decode(childFunction.base.base.flags).isInline) continue
val nameAndType = BinaryNameAndType.decode(childFunction.base.nameType)
val name = fileReader.string(nameAndType.nameIndex)
if (name == irFunction.name.asString()) {
if (result == null)
result = childFunction
else {
val resultIdSignature = symbolDeserializer.deserializeIdSignature(BinarySymbolData.decode(result.base.base.symbol).signatureId)
if (resultIdSignature == signature)
return result
result = childFunction
}
}
}
return result ?: error("Function ${irFunction.render()} is not found")
}
object KonanFakeOverrideClassFilter : FakeOverrideClassFilter {
private fun IdSignature.isInteropSignature(): Boolean = with(this) {
IdSignature.Flags.IS_NATIVE_INTEROP_LIBRARY.test()
@@ -0,0 +1,112 @@
/*
* Copyright 2010-2023 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.serialization
import org.jetbrains.kotlin.backend.common.serialization.IrLibraryFile
import org.jetbrains.kotlin.backend.common.serialization.IrSymbolDeserializer
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinaryNameAndType
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
import org.jetbrains.kotlin.backend.common.serialization.encodings.FunctionFlags
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.backend.common.serialization.proto.IrClass as ProtoClass
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclaration as ProtoDeclaration
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFunction as ProtoFunction
import org.jetbrains.kotlin.backend.common.serialization.proto.IrProperty as ProtoProperty
internal fun ProtoClass.findClass(irClass: IrClass, fileReader: IrLibraryFile, symbolDeserializer: IrSymbolDeserializer): ProtoClass {
val signature = irClass.symbol.signature ?: error("No signature for ${irClass.render()}")
var result: ProtoClass? = null
for (i in 0 until this.declarationCount) {
val child = this.getDeclaration(i)
val childClass = when {
child.declaratorCase == ProtoDeclaration.DeclaratorCase.IR_CLASS -> child.irClass
child.declaratorCase == ProtoDeclaration.DeclaratorCase.IR_ENUM_ENTRY
&& child.irEnumEntry.hasCorrespondingClass() -> child.irEnumEntry.correspondingClass
else -> continue
}
val name = fileReader.string(childClass.name)
if (name == irClass.name.asString()) {
if (result == null)
result = childClass
else {
val resultIdSignature = symbolDeserializer.deserializeIdSignature(BinarySymbolData.decode(result.base.symbol).signatureId)
if (resultIdSignature == signature)
return result
result = childClass
}
}
}
return result ?: error("Class ${irClass.render()} is not found")
}
internal fun ProtoClass.findProperty(irProperty: IrProperty, fileReader: IrLibraryFile, symbolDeserializer: IrSymbolDeserializer): ProtoProperty {
val signature = irProperty.symbol.signature ?: error("No signature for ${irProperty.render()}")
var result: ProtoProperty? = null
for (i in 0 until this.declarationCount) {
val child = this.getDeclaration(i)
if (child.declaratorCase != ProtoDeclaration.DeclaratorCase.IR_PROPERTY) continue
val childProperty = child.irProperty
val name = fileReader.string(child.irProperty.name)
if (name == irProperty.name.asString()) {
if (result == null)
result = childProperty
else {
val resultIdSignature = symbolDeserializer.deserializeIdSignature(BinarySymbolData.decode(result.base.symbol).signatureId)
if (resultIdSignature == signature)
return result
result = childProperty
}
}
}
return result ?: error("Property ${irProperty.render()} is not found")
}
internal fun ProtoProperty.findAccessor(irProperty: IrProperty, irFunction: IrSimpleFunction): ProtoFunction {
if (irFunction == irProperty.getter)
return getter
require(irFunction == irProperty.setter) { "Accessor should be either a getter or a setter. ${irFunction.render()}" }
return setter
}
internal fun ProtoClass.findInlineFunction(irFunction: IrFunction, fileReader: IrLibraryFile, symbolDeserializer: IrSymbolDeserializer): ProtoFunction {
(irFunction as? IrSimpleFunction)?.correspondingPropertySymbol?.owner?.let { irProperty ->
return findProperty(irProperty, fileReader, symbolDeserializer).findAccessor(irProperty, irFunction)
}
val signature = irFunction.symbol.signature ?: error("No signature for ${irFunction.render()}")
var result: ProtoFunction? = null
for (i in 0 until this.declarationCount) {
val child = this.getDeclaration(i)
if (child.declaratorCase != ProtoDeclaration.DeclaratorCase.IR_FUNCTION) continue
val childFunction = child.irFunction
if (childFunction.base.valueParameterCount != irFunction.valueParameters.size) continue
if (childFunction.base.hasExtensionReceiver() xor (irFunction.extensionReceiverParameter != null)) continue
if (childFunction.base.hasDispatchReceiver() xor (irFunction.dispatchReceiverParameter != null)) continue
if (!FunctionFlags.decode(childFunction.base.base.flags).isInline) continue
val nameAndType = BinaryNameAndType.decode(childFunction.base.nameType)
val name = fileReader.string(nameAndType.nameIndex)
if (name == irFunction.name.asString()) {
if (result == null)
result = childFunction
else {
val resultIdSignature = symbolDeserializer.deserializeIdSignature(BinarySymbolData.decode(result.base.base.symbol).signatureId)
if (resultIdSignature == signature)
return result
result = childFunction
}
}
}
return result ?: error("Function ${irFunction.render()} is not found")
}