[IR] Factor out duplicated code in KotlinMangleComputer into base class

This commit is contained in:
Sergej Jaskiewicz
2022-12-13 19:49:24 +01:00
committed by Space Team
parent de5b475f7a
commit c447b91101
6 changed files with 572 additions and 568 deletions
@@ -5,10 +5,7 @@
package org.jetbrains.kotlin.fir.backend.jvm
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinMangleComputer
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleConstant
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleMode
import org.jetbrains.kotlin.backend.common.serialization.mangle.collectForMangler
import org.jetbrains.kotlin.backend.common.serialization.mangle.*
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
@@ -21,68 +18,42 @@ import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.signaturer.irName
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
open class FirJvmMangleComputer(
private val builder: StringBuilder,
private val mode: MangleMode
) : FirVisitor<Unit, Boolean>(), KotlinMangleComputer<FirDeclaration> {
class FirJvmMangleComputer(
builder: StringBuilder,
mode: MangleMode,
) : BaseKotlinMangleComputer<
/*Declaration=*/FirDeclaration,
/*Type=*/ConeKotlinType,
/*TypeParameter=*/ConeTypeParameterLookupTag,
/*ValueParameter=*/FirValueParameter,
/*TypeParameterContainer=*/FirMemberDeclaration,
/*FunctionDeclaration=*/FirFunction,
/*Session=*/FirSession,
>(builder, mode) {
private val typeParameterContainer = ArrayList<FirMemberDeclaration>(4)
override fun getTypeSystemContext(session: FirSession) = object : ConeInferenceContext {
override val session: FirSession
get() = session
}
private var isRealExpect = false
open fun FirFunction.platformSpecificFunctionName(): String? = null
open fun FirFunction.platformSpecificSuffix(): String? =
override fun FirFunction.platformSpecificSuffix(): String? =
if (this is FirSimpleFunction && name.asString() == "main")
this.moduleData.session.firProvider.getFirCallableContainerFile(symbol)?.name
else null
open fun FirFunction.specialValueParamPrefix(param: FirValueParameter): String = ""
private fun addReturnType(): Boolean = true
override fun addReturnType(): Boolean = true
override fun copy(newMode: MangleMode): FirJvmMangleComputer =
FirJvmMangleComputer(builder, newMode)
private fun StringBuilder.appendName(s: String) {
if (mode.fqn) {
append(s)
}
}
private fun StringBuilder.appendName(c: Char) {
if (mode.fqn) {
append(c)
}
}
private fun StringBuilder.appendSignature(s: String) {
if (mode.signature) {
append(s)
}
}
private fun StringBuilder.appendSignature(c: Char) {
if (mode.signature) {
append(c)
}
}
private fun StringBuilder.appendSignature(i: Int) {
if (mode.signature) {
append(i)
}
}
private fun FirDeclaration.visitParent() {
override fun FirDeclaration.visitParent() {
val (parentPackageFqName, parentClassId) = when (this) {
is FirCallableDeclaration -> this.containingClassLookupTag()?.classId?.let { it.packageFqName to it } ?: return
is FirClassLikeDeclaration -> this.symbol.classId.let { it.packageFqName to it.outerClassId }
@@ -92,7 +63,7 @@ open class FirJvmMangleComputer(
val parentClassLike = this.moduleData.session.symbolProvider.getClassLikeSymbolByClassId(parentClassId)?.fir
?: error("Attempt to find parent ($parentClassId) for probably-local declaration!")
if (parentClassLike is FirRegularClass || parentClassLike is FirTypeAlias) {
parentClassLike.accept(this@FirJvmMangleComputer, false)
parentClassLike.visit()
} else {
error("Strange class-like declaration: ${parentClassLike.render()}")
}
@@ -101,15 +72,8 @@ open class FirJvmMangleComputer(
}
}
private fun FirDeclaration.mangleSimpleDeclaration(name: String) {
val l = builder.length
visitParent()
if (builder.length != l) {
builder.appendName(MangleConstant.FQN_SEPARATOR)
}
builder.appendName(name)
override fun FirDeclaration.visit() {
accept(Visitor(), null)
}
private fun FirFunction.mangleFunction(isCtor: Boolean, isStatic: Boolean, container: FirDeclaration) {
@@ -117,7 +81,7 @@ open class FirJvmMangleComputer(
isRealExpect = isRealExpect || (this as? FirMemberDeclaration)?.isExpect == true
if (container is FirMemberDeclaration) {
typeParameterContainer.add(container)
typeParameterContainers.add(container)
}
visitParent()
@@ -161,11 +125,11 @@ open class FirJvmMangleComputer(
valueParameters.collectForMangler(builder, MangleConstant.VALUE_PARAMETERS) {
appendSignature(specialValueParamPrefix(it))
mangleValueParameter(this, it)
mangleValueParameter(this, it, moduleData.session)
}
(container as? FirTypeParametersOwner)?.typeParameters?.withIndex()?.toList().orEmpty()
.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { (index, typeParameter) ->
mangleTypeParameter(this, typeParameter, index)
mangleTypeParameter(this, typeParameter.symbol.toLookupTag(), index, moduleData.session)
}
if (!isCtor && !returnTypeRef.isUnit && addReturnType()) {
@@ -173,8 +137,8 @@ open class FirJvmMangleComputer(
}
}
private fun FirTypeParameter.effectiveParent(): FirMemberDeclaration {
for (parent in typeParameterContainer) {
override fun getEffectiveParent(typeParameter: ConeTypeParameterLookupTag): FirMemberDeclaration = typeParameter.symbol.fir.run {
for (parent in typeParameterContainers) {
if (this in parent.typeParameters) {
return parent
}
@@ -188,33 +152,18 @@ open class FirJvmMangleComputer(
throw IllegalStateException("Should not be here!")
}
private fun mangleValueParameter(vpBuilder: StringBuilder, param: FirValueParameter) {
mangleType(vpBuilder, param.returnTypeRef.coneType, param.moduleData.session)
override fun renderDeclaration(declaration: FirDeclaration) = declaration.render()
if (param.isVararg) {
vpBuilder.appendSignature(MangleConstant.VAR_ARG_MARK)
}
}
override fun getTypeParameterName(typeParameter: ConeTypeParameterLookupTag) = typeParameter.name.asString()
private fun mangleTypeParameter(tpBuilder: StringBuilder, param: FirTypeParameter, index: Int) {
tpBuilder.appendSignature(index)
tpBuilder.appendSignature(MangleConstant.UPPER_BOUND_SEPARATOR)
override fun isVararg(valueParameter: FirValueParameter) = valueParameter.isVararg
param.bounds.map { it.coneType }.collectForMangler(tpBuilder, MangleConstant.UPPER_BOUNDS) {
mangleType(this, it, param.moduleData.session)
}
}
override fun getValueParameterType(valueParameter: FirValueParameter) = valueParameter.returnTypeRef.coneType
private fun StringBuilder.mangleTypeParameterReference(typeParameter: FirTypeParameter) {
val parent = typeParameter.effectiveParent()
val ci = typeParameterContainer.indexOf(parent)
require(ci >= 0) { "No type container found for ${typeParameter.render()}" }
appendSignature(ci)
appendSignature(MangleConstant.INDEX_SEPARATOR)
appendSignature(parent.typeParameters.indexOf(typeParameter))
}
override fun getIndexOfTypeParameter(typeParameter: ConeTypeParameterLookupTag, container: FirMemberDeclaration) =
container.typeParameters.indexOf(typeParameter.symbol.fir)
private fun mangleType(tBuilder: StringBuilder, type: ConeKotlinType, declarationSiteSession: FirSession) {
override fun mangleType(tBuilder: StringBuilder, type: ConeKotlinType, declarationSiteSession: FirSession) {
when (type) {
is ConeLookupTagBasedType -> {
when (val symbol = type.lookupTag.toSymbol(declarationSiteSession)) {
@@ -223,29 +172,15 @@ open class FirJvmMangleComputer(
return
}
is FirClassSymbol -> symbol.fir.accept(copy(MangleMode.FQNAME), false)
is FirTypeParameterSymbol -> tBuilder.mangleTypeParameterReference(symbol.fir)
is FirClassSymbol -> with(copy(MangleMode.FQNAME)) { symbol.fir.visit() }
is FirTypeParameterSymbol -> tBuilder.mangleTypeParameterReference(symbol.toLookupTag())
// This is performed for a case with invisible class-like symbol in fake override
null -> (type.lookupTag as? ConeClassLikeLookupTag)?.let {
tBuilder.append(it.classId)
}
}
type.typeArguments.asList().ifNotEmpty {
collectForMangler(tBuilder, MangleConstant.TYPE_ARGUMENTS) { arg ->
when (arg) {
is ConeStarProjection -> appendSignature(MangleConstant.STAR_MARK)
is ConeKotlinTypeProjection -> {
if (arg.kind != ProjectionKind.INVARIANT) {
appendSignature(arg.kind.name.toLowerCaseAsciiOnly())
appendSignature(MangleConstant.VARIANCE_SEPARATOR)
}
mangleType(this, arg.type, declarationSiteSession)
}
}
}
}
mangleTypeArguments(tBuilder, type, declarationSiteSession)
if (type.isMarkedNullable) {
tBuilder.appendSignature(MangleConstant.Q_MARK)
@@ -294,79 +229,78 @@ open class FirJvmMangleComputer(
}
}
override fun visitElement(element: FirElement, data: Boolean) = error("unexpected element ${element.render()}")
private inner class Visitor : FirVisitorVoid() {
override fun visitRegularClass(regularClass: FirRegularClass, data: Boolean) {
isRealExpect = isRealExpect or regularClass.isExpect
typeParameterContainer.add(regularClass)
regularClass.mangleSimpleDeclaration(regularClass.name.asString())
}
override fun visitElement(element: FirElement) = error("unexpected element ${element.render()}")
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: Boolean) {
anonymousObject.mangleSimpleDeclaration("<anonymous>")
}
override fun visitVariable(variable: FirVariable, data: Boolean) {
isRealExpect = isRealExpect or variable.isExpect
typeParameterContainer.add(variable)
variable.visitParent()
val isStaticProperty = variable.isStatic
if (isStaticProperty) {
builder.appendSignature(MangleConstant.STATIC_MEMBER_MARK)
override fun visitRegularClass(regularClass: FirRegularClass) {
isRealExpect = isRealExpect or regularClass.isExpect
typeParameterContainers.add(regularClass)
regularClass.mangleSimpleDeclaration(regularClass.name.asString())
}
variable.receiverParameter?.typeRef?.let {
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
mangleType(builder, it.coneType, variable.moduleData.session)
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject) {
anonymousObject.mangleSimpleDeclaration("<anonymous>")
}
variable.typeParameters.withIndex().toList().collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { (index, typeParameter) ->
mangleTypeParameter(this, typeParameter.symbol.fir, index)
override fun visitVariable(variable: FirVariable) {
isRealExpect = isRealExpect or variable.isExpect
typeParameterContainers.add(variable)
variable.visitParent()
val isStaticProperty = variable.isStatic
if (isStaticProperty) {
builder.appendSignature(MangleConstant.STATIC_MEMBER_MARK)
}
variable.receiverParameter?.typeRef?.let {
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
mangleType(builder, it.coneType, variable.moduleData.session)
}
variable.typeParameters.withIndex().toList()
.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { (index, typeParameter) ->
mangleTypeParameter(this, typeParameter.symbol.toLookupTag(), index, variable.moduleData.session)
}
builder.append(variable.name.asString())
}
builder.append(variable.name.asString())
}
override fun visitProperty(property: FirProperty, data: Boolean) {
visitVariable(property, data)
}
override fun visitField(field: FirField, data: Boolean) {
if (field is FirJavaField) {
field.mangleSimpleDeclaration(field.name.asString())
} else {
visitVariable(field, data)
override fun visitProperty(property: FirProperty) {
visitVariable(property)
}
}
override fun visitEnumEntry(enumEntry: FirEnumEntry, data: Boolean) {
enumEntry.mangleSimpleDeclaration(enumEntry.name.asString())
}
override fun visitTypeAlias(typeAlias: FirTypeAlias, data: Boolean) =
typeAlias.mangleSimpleDeclaration(typeAlias.name.asString())
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: Boolean) {
isRealExpect = isRealExpect || simpleFunction.isExpect
val isStatic = simpleFunction.isStatic
simpleFunction.mangleFunction(false, isStatic, simpleFunction)
}
override fun visitConstructor(constructor: FirConstructor, data: Boolean) =
constructor.mangleFunction(isCtor = true, isStatic = false, constructor)
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: Boolean) {
if (propertyAccessor is FirSyntheticPropertyAccessor) {
// No need to distinguish between the accessor and its delegate.
visitSimpleFunction(propertyAccessor.delegate, data)
} else {
propertyAccessor.mangleFunction(isCtor = false, propertyAccessor.isStatic, propertyAccessor.propertySymbol.fir)
override fun visitField(field: FirField) {
if (field is FirJavaField) {
field.mangleSimpleDeclaration(field.name.asString())
} else {
visitVariable(field)
}
}
}
override fun computeMangle(declaration: FirDeclaration): String {
declaration.accept(this, true)
return builder.toString()
override fun visitEnumEntry(enumEntry: FirEnumEntry) {
enumEntry.mangleSimpleDeclaration(enumEntry.name.asString())
}
override fun visitTypeAlias(typeAlias: FirTypeAlias) =
typeAlias.mangleSimpleDeclaration(typeAlias.name.asString())
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) {
isRealExpect = isRealExpect || simpleFunction.isExpect
val isStatic = simpleFunction.isStatic
simpleFunction.mangleFunction(false, isStatic, simpleFunction)
}
override fun visitConstructor(constructor: FirConstructor) =
constructor.mangleFunction(isCtor = true, isStatic = false, constructor)
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor) {
if (propertyAccessor is FirSyntheticPropertyAccessor) {
// No need to distinguish between the accessor and its delegate.
visitSimpleFunction(propertyAccessor.delegate)
} else {
propertyAccessor.mangleFunction(isCtor = false, propertyAccessor.isStatic, propertyAccessor.propertySymbol.fir)
}
}
}
}
@@ -0,0 +1,181 @@
/*
* 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.common.serialization.mangle
import org.jetbrains.kotlin.types.model.*
/**
* A base implementation of the [KotlinMangleComputer] interface containing routines that are common for all frontends and backends.
*
* @param Declaration A class representing a Kotlin declaration.
* @param Type A class representing a Kotlin type.
* @param TypeParameter A class representing a type parameter of a Kotlin class or function.
* @param ValueParameter A class representing a value parameter declaration of a Kotlin function.
* @param TypeParameterContainer A class representing something that can have type parameters, like a Kotlin function or class declaration.
* @param FunctionDeclaration A class representing a Kotlin function declaration.
* @param Session An additional context used for type computations.
* @property builder A string builder to write the mangled name into.
* @property mode The mangle mode.
*/
abstract class BaseKotlinMangleComputer<Declaration, Type, TypeParameter, ValueParameter, TypeParameterContainer, FunctionDeclaration, Session>(
protected val builder: StringBuilder,
protected val mode: MangleMode
) : KotlinMangleComputer<Declaration>
where Declaration : Any,
Type : KotlinTypeMarker,
TypeParameter : TypeParameterMarker,
ValueParameter : Declaration,
TypeParameterContainer : Declaration,
FunctionDeclaration : Declaration {
/**
* The type system to use to query properties of types, type parameters and type arguments.
*/
protected abstract fun getTypeSystemContext(session: Session): TypeSystemContext
protected val typeParameterContainers = ArrayList<TypeParameterContainer>(4)
protected var isRealExpect = false
protected open fun FunctionDeclaration.platformSpecificFunctionName(): String? = null
protected open fun FunctionDeclaration.platformSpecificSuffix(): String? = null
protected open fun FunctionDeclaration.specialValueParamPrefix(param: ValueParameter): String = ""
protected open fun addReturnType(): Boolean = false
protected open fun addReturnTypeSpecialCase(function: FunctionDeclaration): Boolean = false
protected fun StringBuilder.appendName(s: String) {
if (mode.fqn) {
append(s)
}
}
protected fun StringBuilder.appendName(c: Char) {
if (mode.fqn) {
append(c)
}
}
protected fun StringBuilder.appendSignature(s: String) {
if (mode.signature) {
append(s)
}
}
protected fun StringBuilder.appendSignature(c: Char) {
if (mode.signature) {
append(c)
}
}
protected fun StringBuilder.appendSignature(i: Int) {
if (mode.signature) {
append(i)
}
}
protected abstract fun Declaration.visitParent()
protected abstract fun Declaration.visit()
final override fun computeMangle(declaration: Declaration): String {
declaration.visit()
return builder.toString()
}
protected fun Declaration.mangleSimpleDeclaration(name: String) {
val l = builder.length
visitParent()
if (builder.length != l) {
builder.appendName(MangleConstant.FQN_SEPARATOR)
}
builder.appendName(name)
}
protected abstract fun mangleType(tBuilder: StringBuilder, type: Type, declarationSiteSession: Session)
protected open fun mangleTypePlatformSpecific(type: Type, tBuilder: StringBuilder) {}
protected abstract fun isVararg(valueParameter: ValueParameter): Boolean
protected abstract fun getValueParameterType(valueParameter: ValueParameter): Type
protected abstract fun getIndexOfTypeParameter(typeParameter: TypeParameter, container: TypeParameterContainer): Int
/**
* Used to show a meaningful exception message.
*/
protected abstract fun renderDeclaration(declaration: Declaration): String
protected abstract fun getTypeParameterName(typeParameter: TypeParameter): String
protected fun StringBuilder.mangleTypeParameterReference(typeParameter: TypeParameter) {
val parent = getEffectiveParent(typeParameter)
val containerIndex = typeParameterContainers.indexOf(parent)
require(containerIndex >= 0) {
"No container found for type parameter '${getTypeParameterName(typeParameter)}' of '${renderDeclaration(parent)}'"
}
appendSignature(containerIndex)
appendSignature(MangleConstant.INDEX_SEPARATOR)
appendSignature(getIndexOfTypeParameter(typeParameter, parent))
}
protected fun mangleTypeParameter(
tpBuilder: StringBuilder,
param: TypeParameter,
index: Int,
declarationSiteSession: Session
) = with(getTypeSystemContext(declarationSiteSession)) {
tpBuilder.appendSignature(index)
tpBuilder.appendSignature(MangleConstant.UPPER_BOUND_SEPARATOR)
param.getUpperBounds().collectForMangler(tpBuilder, MangleConstant.UPPER_BOUNDS) {
@Suppress("UNCHECKED_CAST")
mangleType(this, it as Type, declarationSiteSession)
}
}
protected abstract fun getEffectiveParent(typeParameter: TypeParameter): TypeParameterContainer
protected fun mangleValueParameter(vpBuilder: StringBuilder, param: ValueParameter, declarationSiteSession: Session) {
mangleType(vpBuilder, getValueParameterType(param), declarationSiteSession)
if (isVararg(param)) {
vpBuilder.appendSignature(MangleConstant.VAR_ARG_MARK)
}
}
protected fun mangleTypeArguments(tBuilder: StringBuilder, type: Type, declarationSiteSession: Session) =
with(getTypeSystemContext(declarationSiteSession)) {
val typeArguments = type.getArguments().zip(type.typeConstructor().getParameters())
if (typeArguments.isEmpty()) return
@Suppress("UNUSED_DESTRUCTURED_PARAMETER_ENTRY")
typeArguments.collectForMangler(tBuilder, MangleConstant.TYPE_ARGUMENTS) { (typeArgument, typeParameter) ->
when {
typeArgument.isStarProjection() -> appendSignature(MangleConstant.STAR_MARK)
else -> {
// FIXME: Use effective variance here according to the klib spec: `org.jetbrains.kotlin.types.AbstractTypeChecker.effectiveVariance(typeParameter.getVariance(), typeArgument.getVariance())`
// NOTE: If we start using effective variance instead of declared variance, we must take into account
// binary compatibility implications.
val variance = typeArgument.getVariance()
if (variance != TypeVariance.INV) {
appendSignature(variance.presentation)
appendSignature(MangleConstant.VARIANCE_SEPARATOR)
}
@Suppress("UNCHECKED_CAST")
mangleType(this, typeArgument.getType() as Type, declarationSiteSession)
}
}
}
}
}
@@ -5,86 +5,44 @@
package org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinMangleComputer
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleConstant
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleMode
import org.jetbrains.kotlin.backend.common.serialization.mangle.collectForMangler
import org.jetbrains.kotlin.backend.common.serialization.mangle.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.descriptors.IrImplementingDelegateDescriptor
import org.jetbrains.kotlin.ir.descriptors.IrPropertyDelegateDescriptor
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext
import org.jetbrains.kotlin.types.model.TypeSystemContext
import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsByExistingArgumentsWith
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
abstract class DescriptorMangleComputer(protected val builder: StringBuilder, private val mode: MangleMode) :
DeclarationDescriptorVisitor<Unit, Nothing?>, KotlinMangleComputer<DeclarationDescriptor> {
override fun computeMangle(declaration: DeclarationDescriptor): String {
declaration.accept(this, null)
return builder.toString()
}
abstract class DescriptorMangleComputer(builder: StringBuilder, mode: MangleMode) :
BaseKotlinMangleComputer<
/*Declaration=*/DeclarationDescriptor,
/*Type=*/KotlinType,
/*TypeParameter=*/TypeParameterDescriptor,
/*ValueParameter=*/ValueParameterDescriptor,
/*TypeParameterContainer=*/DeclarationDescriptor,
/*FunctionDeclaration=*/FunctionDescriptor,
/*Session=*/Nothing?,
>(builder, mode) {
final override fun getTypeSystemContext(session: Nothing?): TypeSystemContext = SimpleClassicTypeSystemContext
abstract override fun copy(newMode: MangleMode): DescriptorMangleComputer
private fun StringBuilder.appendName(s: String) {
if (mode.fqn) {
append(s)
}
final override fun DeclarationDescriptor.visitParent() {
containingDeclaration?.visit()
}
private fun StringBuilder.appendName(c: Char) {
if (mode.fqn) {
append(c)
}
final override fun DeclarationDescriptor.visit() {
accept(Visitor(), null)
}
protected fun StringBuilder.appendSignature(s: String) {
if (mode.signature) {
append(s)
}
}
private fun StringBuilder.appendSignature(c: Char) {
if (mode.signature) {
append(c)
}
}
private fun StringBuilder.appendSignature(i: Int) {
if (mode.signature) {
append(i)
}
}
private val typeParameterContainer = ArrayList<DeclarationDescriptor>(4)
private var isRealExpect = false
private fun DeclarationDescriptor.mangleSimpleDeclaration(name: String) {
val l = builder.length
containingDeclaration?.accept(this@DescriptorMangleComputer, null)
if (builder.length != l) builder.appendName(MangleConstant.FQN_SEPARATOR)
builder.appendName(name)
}
open fun FunctionDescriptor.platformSpecificFunctionName(): String? = null
private fun reportUnexpectedDescriptor(descriptor: DeclarationDescriptor) {
error("unexpected descriptor $descriptor")
}
open fun FunctionDescriptor.platformSpecificSuffix(): String? = null
open fun PropertyDescriptor.platformSpecificSuffix(): String? = null
protected open fun addReturnType(): Boolean = false
protected open fun addReturnTypeSpecialCase(functionDescriptor: FunctionDescriptor): Boolean = false
open fun FunctionDescriptor.specialValueParamPrefix(param: ValueParameterDescriptor): String = ""
private val CallableDescriptor.isRealStatic: Boolean
get() = dispatchReceiverParameter == null && containingDeclaration !is PackageFragmentDescriptor
@@ -92,8 +50,8 @@ abstract class DescriptorMangleComputer(protected val builder: StringBuilder, pr
isRealExpect = isRealExpect or isExpect
typeParameterContainer.add(container)
container.containingDeclaration.accept(this@DescriptorMangleComputer, null)
typeParameterContainers.add(container)
container.containingDeclaration.visit()
builder.appendName(MangleConstant.FUNCTION_NAME_PREFIX)
@@ -127,14 +85,14 @@ abstract class DescriptorMangleComputer(protected val builder: StringBuilder, pr
valueParameters.collectForMangler(builder, MangleConstant.VALUE_PARAMETERS) {
appendSignature(specialValueParamPrefix(it))
mangleValueParameter(this, it)
mangleValueParameter(this, it, null)
}
realTypeParameterContainer.typeParameters.filter { it.containingDeclaration == realTypeParameterContainer }
.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { mangleTypeParameter(this, it) }
.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { mangleTypeParameter(this, it, it.index, null) }
returnType?.run {
if (!isCtor && !isUnit() && (addReturnType() || addReturnTypeSpecialCase(this@mangleSignature))) {
mangleType(builder, this)
mangleType(builder, this, null)
}
}
@@ -145,28 +103,20 @@ abstract class DescriptorMangleComputer(protected val builder: StringBuilder, pr
}
private fun mangleContextReceiverParameter(vpBuilder: StringBuilder, param: ReceiverParameterDescriptor) {
mangleType(vpBuilder, param.type)
mangleType(vpBuilder, param.type, null)
}
private fun mangleExtensionReceiverParameter(vpBuilder: StringBuilder, param: ReceiverParameterDescriptor) {
mangleType(vpBuilder, param.type)
mangleType(vpBuilder, param.type, null)
}
private fun mangleValueParameter(vpBuilder: StringBuilder, param: ValueParameterDescriptor) {
mangleType(vpBuilder, param.type)
final override fun isVararg(valueParameter: ValueParameterDescriptor) = valueParameter.varargElementType != null
if (param.varargElementType != null) vpBuilder.appendSignature(MangleConstant.VAR_ARG_MARK)
}
final override fun getValueParameterType(valueParameter: ValueParameterDescriptor) = valueParameter.type
private fun mangleTypeParameter(tpBuilder: StringBuilder, param: TypeParameterDescriptor) {
tpBuilder.appendSignature(param.index)
tpBuilder.appendSignature(MangleConstant.UPPER_BOUND_SEPARATOR)
param.upperBounds.collectForMangler(tpBuilder, MangleConstant.UPPER_BOUNDS) { mangleType(this, it) }
}
private fun mangleType(tBuilder: StringBuilder, wtype: KotlinType) {
when (val type = wtype.unwrap()) {
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
final override fun mangleType(tBuilder: StringBuilder, wrappedType: KotlinType, declarationSiteSession: Nothing?) {
when (val type = wrappedType.unwrap()) {
is SimpleType -> {
if (type is SupposititiousSimpleType) {
@@ -180,26 +130,13 @@ abstract class DescriptorMangleComputer(protected val builder: StringBuilder, pr
}
} else {
when (val classifier = type.constructor.declarationDescriptor) {
is ClassDescriptor -> classifier.accept(copy(MangleMode.FQNAME), null)
is ClassDescriptor -> with(copy(MangleMode.FQNAME)) { classifier.visit() }
is TypeParameterDescriptor -> tBuilder.mangleTypeParameterReference(classifier)
else -> error("Unexpected classifier: $classifier")
}
}
type.arguments.ifNotEmpty {
collectForMangler(tBuilder, MangleConstant.TYPE_ARGUMENTS) { arg ->
if (arg.isStarProjection) {
appendSignature(MangleConstant.STAR_MARK)
} else {
if (arg.projectionKind != Variance.INVARIANT) {
appendSignature(arg.projectionKind.label)
appendSignature(MangleConstant.VARIANCE_SEPARATOR)
}
mangleType(this, arg.type)
}
}
}
mangleTypeArguments(tBuilder, type, null)
if (type.isMarkedNullable) tBuilder.appendSignature(MangleConstant.Q_MARK)
@@ -219,113 +156,119 @@ abstract class DescriptorMangleComputer(protected val builder: StringBuilder, pr
lower.replace(newArguments = upper.arguments)
} else lower
val mixed = intermediate.makeNullableAsSpecified(upper.isMarkedNullable)
mangleType(tBuilder, mixed)
} else mangleType(tBuilder, upper)
mangleType(tBuilder, mixed, null)
} else mangleType(tBuilder, upper, null)
}
else -> error("Unexpected type $wtype")
else -> error("Unexpected type $wrappedType")
}
}
protected open fun mangleTypePlatformSpecific(type: UnwrappedType, tBuilder: StringBuilder) {}
final override fun getEffectiveParent(typeParameter: TypeParameterDescriptor) = typeParameter.containingDeclaration
private fun StringBuilder.mangleTypeParameterReference(typeParameter: TypeParameterDescriptor) {
val parent = typeParameter.containingDeclaration
val ci = typeParameterContainer.indexOf(parent)
// TODO: what should we do in this case?
// require(ci >= 0) { "No type container found for ${typeParameter.render()}" }
appendSignature(ci)
appendSignature(MangleConstant.INDEX_SEPARATOR)
appendSignature(typeParameter.index)
}
override fun renderDeclaration(declaration: DeclarationDescriptor) = DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(declaration)
override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor, data: Nothing?) {
descriptor.fqName.let { if (!it.isRoot) builder.appendName(it.asString()) }
}
override fun getTypeParameterName(typeParameter: TypeParameterDescriptor) = typeParameter.name.asString()
override fun visitPackageViewDescriptor(descriptor: PackageViewDescriptor, data: Nothing?) = reportUnexpectedDescriptor(descriptor)
override fun visitVariableDescriptor(descriptor: VariableDescriptor, data: Nothing?) = reportUnexpectedDescriptor(descriptor)
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Nothing?) {
descriptor.mangleFunction(false, descriptor)
}
override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor, data: Nothing?) {
descriptor.containingDeclaration.accept(this, data)
builder.appendSignature(MangleConstant.TYPE_PARAM_INDEX_PREFIX)
builder.appendSignature(descriptor.index)
}
override fun visitClassDescriptor(descriptor: ClassDescriptor, data: Nothing?) {
isRealExpect = isRealExpect or descriptor.isExpect
typeParameterContainer.add(descriptor)
descriptor.mangleSimpleDeclaration(descriptor.name.asString())
}
override fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, data: Nothing?) {
descriptor.mangleSimpleDeclaration(descriptor.name.asString())
}
override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: Nothing?) = reportUnexpectedDescriptor(descriptor)
override fun visitConstructorDescriptor(constructorDescriptor: ConstructorDescriptor, data: Nothing?) {
constructorDescriptor.mangleFunction(isCtor = true, container = constructorDescriptor)
}
override fun visitScriptDescriptor(scriptDescriptor: ScriptDescriptor, data: Nothing?) =
visitClassDescriptor(scriptDescriptor, data)
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Nothing?) {
if (descriptor is IrImplementingDelegateDescriptor) {
descriptor.mangleSimpleDeclaration(descriptor.name.asString())
} else {
val actualDescriptor = (descriptor as? IrPropertyDelegateDescriptor)?.correspondingProperty ?: descriptor
val extensionReceiver = actualDescriptor.extensionReceiverParameter
isRealExpect = isRealExpect or actualDescriptor.isExpect
typeParameterContainer.add(actualDescriptor)
actualDescriptor.containingDeclaration.accept(this, data)
if (actualDescriptor.isRealStatic) {
builder.appendSignature(MangleConstant.STATIC_MEMBER_MARK)
}
if (extensionReceiver != null) {
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
mangleExtensionReceiverParameter(builder, extensionReceiver)
}
actualDescriptor.typeParameters.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { mangleTypeParameter(this, it) }
builder.append(actualDescriptor.name.asString())
actualDescriptor.platformSpecificSuffix()?.let {
builder.appendSignature(it)
}
}
}
override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor, data: Nothing?) =
reportUnexpectedDescriptor(descriptor)
final override fun getIndexOfTypeParameter(typeParameter: TypeParameterDescriptor, container: DeclarationDescriptor) =
typeParameter.index
private fun manglePropertyAccessor(accessor: PropertyAccessorDescriptor) {
val property = accessor.correspondingProperty
accessor.mangleFunction(false, property)
}
override fun visitPropertyGetterDescriptor(descriptor: PropertyGetterDescriptor, data: Nothing?) {
manglePropertyAccessor(descriptor)
}
protected open fun visitModuleDeclaration(descriptor: ModuleDescriptor) = reportUnexpectedDescriptor(descriptor)
override fun visitPropertySetterDescriptor(descriptor: PropertySetterDescriptor, data: Nothing?) {
manglePropertyAccessor(descriptor)
}
private inner class Visitor : DeclarationDescriptorVisitor<Unit, Nothing?> {
override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor, data: Nothing?) =
reportUnexpectedDescriptor(descriptor)
override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor, data: Nothing?) {
descriptor.fqName.let { if (!it.isRoot) builder.appendName(it.asString()) }
}
override fun visitPackageViewDescriptor(descriptor: PackageViewDescriptor, data: Nothing?) = reportUnexpectedDescriptor(descriptor)
override fun visitVariableDescriptor(descriptor: VariableDescriptor, data: Nothing?) = reportUnexpectedDescriptor(descriptor)
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Nothing?) {
descriptor.mangleFunction(false, descriptor)
}
override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor, data: Nothing?) {
descriptor.containingDeclaration.visit()
builder.appendSignature(MangleConstant.TYPE_PARAM_INDEX_PREFIX)
builder.appendSignature(descriptor.index)
}
override fun visitClassDescriptor(descriptor: ClassDescriptor, data: Nothing?) {
isRealExpect = isRealExpect or descriptor.isExpect
typeParameterContainers.add(descriptor)
descriptor.mangleSimpleDeclaration(descriptor.name.asString())
}
override fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, data: Nothing?) {
descriptor.mangleSimpleDeclaration(descriptor.name.asString())
}
override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: Nothing?) {
visitModuleDeclaration(descriptor)
}
override fun visitConstructorDescriptor(constructorDescriptor: ConstructorDescriptor, data: Nothing?) {
constructorDescriptor.mangleFunction(isCtor = true, container = constructorDescriptor)
}
override fun visitScriptDescriptor(scriptDescriptor: ScriptDescriptor, data: Nothing?) =
visitClassDescriptor(scriptDescriptor, data)
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Nothing?) {
if (descriptor is IrImplementingDelegateDescriptor) {
descriptor.mangleSimpleDeclaration(descriptor.name.asString())
} else {
val actualDescriptor = (descriptor as? IrPropertyDelegateDescriptor)?.correspondingProperty ?: descriptor
val extensionReceiver = actualDescriptor.extensionReceiverParameter
isRealExpect = isRealExpect or actualDescriptor.isExpect
typeParameterContainers.add(actualDescriptor)
actualDescriptor.containingDeclaration.visit()
if (actualDescriptor.isRealStatic) {
builder.appendSignature(MangleConstant.STATIC_MEMBER_MARK)
}
if (extensionReceiver != null) {
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
mangleExtensionReceiverParameter(builder, extensionReceiver)
}
actualDescriptor.typeParameters.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) {
mangleTypeParameter(this, it, it.index, null)
}
builder.append(actualDescriptor.name.asString())
actualDescriptor.platformSpecificSuffix()?.let {
builder.appendSignature(it)
}
}
}
override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor, data: Nothing?) =
reportUnexpectedDescriptor(descriptor)
override fun visitPropertyGetterDescriptor(descriptor: PropertyGetterDescriptor, data: Nothing?) {
manglePropertyAccessor(descriptor)
}
override fun visitPropertySetterDescriptor(descriptor: PropertySetterDescriptor, data: Nothing?) {
manglePropertyAccessor(descriptor)
}
override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor, data: Nothing?) =
reportUnexpectedDescriptor(descriptor)
}
}
@@ -5,10 +5,8 @@
package org.jetbrains.kotlin.backend.common.serialization.mangle.ir
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinMangleComputer
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleConstant
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleMode
import org.jetbrains.kotlin.backend.common.serialization.mangle.collectForMangler
import org.jetbrains.kotlin.backend.common.serialization.mangle.*
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
@@ -17,80 +15,47 @@ import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
abstract class IrMangleComputer(protected val builder: StringBuilder, private val mode: MangleMode, protected val compatibleMode: Boolean) :
IrElementVisitorVoid, KotlinMangleComputer<IrDeclaration> {
abstract class IrMangleComputer(
builder: StringBuilder,
mode: MangleMode,
protected val compatibleMode: Boolean
) : BaseKotlinMangleComputer<
/*Declaration=*/IrDeclaration,
/*Type=*/IrType,
/*TypeParameter=*/IrTypeParameterSymbol,
/*ValueParameter=*/IrValueParameter,
/*TypeParameterContainer=*/IrDeclaration,
/*FunctionDeclaration=*/IrFunction,
/*Session=*/Nothing?,
>(builder, mode) {
private val typeParameterContainer = ArrayList<IrDeclaration>(4)
final override fun getTypeSystemContext(session: Nothing?) = object : IrTypeSystemContext {
override val irBuiltIns: IrBuiltIns
get() = throw UnsupportedOperationException("Builtins are unavailable")
}
private var isRealExpect = false
open fun IrFunction.platformSpecificFunctionName(): String? = null
open fun IrFunction.platformSpecificFunctionMarks(): List<String> = emptyList()
open fun IrFunction.specialValueParamPrefix(param: IrValueParameter): String = ""
open fun addReturnType(): Boolean = false
protected open fun addReturnTypeSpecialCase(irFunction: IrFunction): Boolean = false
abstract override fun copy(newMode: MangleMode): IrMangleComputer
private fun StringBuilder.appendName(s: String) {
if (mode.fqn) {
append(s)
}
final override fun IrDeclaration.visitParent() {
parent.acceptVoid(Visitor())
}
private fun StringBuilder.appendName(c: Char) {
if (mode.fqn) {
append(c)
}
}
private fun StringBuilder.appendSignature(s: String) {
if (mode.signature) {
append(s)
}
}
private fun StringBuilder.appendSignature(c: Char) {
if (mode.signature) {
append(c)
}
}
private fun StringBuilder.appendSignature(i: Int) {
if (mode.signature) {
append(i)
}
}
override fun computeMangle(declaration: IrDeclaration): String {
declaration.acceptVoid(this)
return builder.toString()
}
private fun IrDeclaration.mangleSimpleDeclaration(name: String) {
val l = builder.length
parent.acceptVoid(this@IrMangleComputer)
if (builder.length != l) builder.appendName(MangleConstant.FQN_SEPARATOR)
builder.appendName(name)
final override fun IrDeclaration.visit() {
acceptVoid(Visitor())
}
private fun IrFunction.mangleFunction(isCtor: Boolean, isStatic: Boolean, container: IrDeclaration) {
isRealExpect = isRealExpect or isExpect
typeParameterContainer.add(container)
typeParameterContainers.add(container)
val containerParent = container.parent
val realParent =
if (containerParent is IrField && containerParent.origin == IrDeclarationOrigin.DELEGATE) containerParent.parent else containerParent
realParent.acceptVoid(this@IrMangleComputer)
realParent.acceptVoid(Visitor())
builder.appendName(MangleConstant.FUNCTION_NAME_PREFIX)
@@ -120,76 +85,53 @@ abstract class IrMangleComputer(protected val builder: StringBuilder, private va
extensionReceiverParameter?.let {
if (!it.isHidden) {
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
mangleValueParameter(builder, it)
mangleValueParameter(builder, it, null)
}
}
valueParameters.collectForMangler(builder, MangleConstant.VALUE_PARAMETERS) {
if (!it.isHidden) {
appendSignature(specialValueParamPrefix(it))
mangleValueParameter(this, it)
mangleValueParameter(this, it, null)
}
}
typeParameters.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { mangleTypeParameter(this, it) }
typeParameters.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) {
mangleTypeParameter(this, it.symbol, it.index, null)
}
if (!isCtor && !returnType.isUnit() && (addReturnType() || addReturnTypeSpecialCase(this))) {
mangleType(builder, returnType)
mangleType(builder, returnType, null)
}
}
private fun IrTypeParameter.effectiveParent(): IrDeclaration = when (val irParent = parent) {
is IrSimpleFunction -> irParent.correspondingPropertySymbol?.owner ?: irParent
is IrTypeParametersContainer -> irParent
else -> error("Unexpected type parameter container ${irParent.render()} for TP ${render()}")
final override fun getEffectiveParent(typeParameter: IrTypeParameterSymbol): IrDeclaration = typeParameter.owner.run {
when (val irParent = parent) {
is IrSimpleFunction -> irParent.correspondingPropertySymbol?.owner ?: irParent
is IrTypeParametersContainer -> irParent
else -> error("Unexpected type parameter container ${irParent.render()} for TP ${render()}")
}
}
private fun mangleValueParameter(vpBuilder: StringBuilder, param: IrValueParameter) {
mangleType(vpBuilder, param.type)
override fun renderDeclaration(declaration: IrDeclaration) = declaration.render()
if (param.isVararg) vpBuilder.appendSignature(MangleConstant.VAR_ARG_MARK)
}
override fun getTypeParameterName(typeParameter: IrTypeParameterSymbol) = typeParameter.owner.name.asString()
private fun mangleTypeParameter(tpBuilder: StringBuilder, param: IrTypeParameter) {
tpBuilder.appendSignature(param.index)
tpBuilder.appendSignature(MangleConstant.UPPER_BOUND_SEPARATOR)
final override fun isVararg(valueParameter: IrValueParameter) = valueParameter.varargElementType != null
param.superTypes.collectForMangler(tpBuilder, MangleConstant.UPPER_BOUNDS) { mangleType(this, it) }
}
final override fun getValueParameterType(valueParameter: IrValueParameter) = valueParameter.type
private fun StringBuilder.mangleTypeParameterReference(typeParameter: IrTypeParameter) {
val parent = typeParameter.effectiveParent()
val ci = typeParameterContainer.indexOf(parent)
// TODO: what should we do in this case?
// require(ci >= 0) { "No type container found for ${typeParameter.render()}" }
appendSignature(ci)
appendSignature(MangleConstant.INDEX_SEPARATOR)
appendSignature(typeParameter.index)
}
final override fun getIndexOfTypeParameter(typeParameter: IrTypeParameterSymbol, container: IrDeclaration) = typeParameter.owner.index
private fun mangleType(tBuilder: StringBuilder, type: IrType) {
final override fun mangleType(tBuilder: StringBuilder, type: IrType, declarationSiteSession: Nothing?) {
when (type) {
is IrSimpleType -> {
when (val classifier = type.classifier) {
is IrClassSymbol -> classifier.owner.acceptVoid(copy(MangleMode.FQNAME))
is IrTypeParameterSymbol -> tBuilder.mangleTypeParameterReference(classifier.owner)
is IrClassSymbol -> with(copy(MangleMode.FQNAME)) { classifier.owner.visit() }
is IrTypeParameterSymbol -> tBuilder.mangleTypeParameterReference(classifier)
}
type.arguments.ifNotEmpty {
collectForMangler(tBuilder, MangleConstant.TYPE_ARGUMENTS) { arg ->
when (arg) {
is IrStarProjection -> appendSignature(MangleConstant.STAR_MARK)
is IrTypeProjection -> {
if (arg.variance != Variance.INVARIANT) {
appendSignature(arg.variance.label)
appendSignature(MangleConstant.VARIANCE_SEPARATOR)
}
mangleType(this, arg.type)
}
}
}
}
mangleTypeArguments(tBuilder, type, null)
//TODO
if (type.isMarkedNullable()) tBuilder.appendSignature(MangleConstant.Q_MARK)
@@ -202,124 +144,127 @@ abstract class IrMangleComputer(protected val builder: StringBuilder, private va
}
}
protected open fun mangleTypePlatformSpecific(type: IrType, tBuilder: StringBuilder) {}
private inner class Visitor : IrElementVisitorVoid {
override fun visitElement(element: IrElement) =
error("unexpected element ${element.render()}")
override fun visitElement(element: IrElement) =
error("unexpected element ${element.render()}")
override fun visitScript(declaration: IrScript) {
declaration.parent.acceptVoid(this)
}
override fun visitErrorDeclaration(declaration: IrErrorDeclaration) {
declaration.mangleSimpleDeclaration(MangleConstant.ERROR_DECLARATION)
}
override fun visitClass(declaration: IrClass) {
isRealExpect = isRealExpect or declaration.isExpect
typeParameterContainer.add(declaration)
val className = declaration.name.asString()
declaration.mangleSimpleDeclaration(className)
}
override fun visitPackageFragment(declaration: IrPackageFragment) {
declaration.fqName.let { if (!it.isRoot) builder.appendName(it.asString()) }
}
override fun visitProperty(declaration: IrProperty) {
val accessor = declaration.run { getter ?: setter }
require(accessor != null || declaration.backingField != null) {
"Expected at least one accessor or backing field for property ${declaration.render()}"
override fun visitScript(declaration: IrScript) {
declaration.visitParent()
}
isRealExpect = isRealExpect or declaration.isExpect
typeParameterContainer.add(declaration)
declaration.parent.acceptVoid(this)
override fun visitErrorDeclaration(declaration: IrErrorDeclaration) {
declaration.mangleSimpleDeclaration(MangleConstant.ERROR_DECLARATION)
}
val isStaticProperty = if (accessor != null)
accessor.let {
it.dispatchReceiverParameter == null && declaration.parent !is IrPackageFragment && !declaration.parent.isFacadeClass
override fun visitClass(declaration: IrClass) {
isRealExpect = isRealExpect or declaration.isExpect
typeParameterContainers.add(declaration)
val className = declaration.name.asString()
declaration.mangleSimpleDeclaration(className)
}
override fun visitPackageFragment(declaration: IrPackageFragment) {
declaration.fqName.let { if (!it.isRoot) builder.appendName(it.asString()) }
}
override fun visitProperty(declaration: IrProperty) {
val accessor = declaration.run { getter ?: setter }
require(accessor != null || declaration.backingField != null) {
"Expected at least one accessor or backing field for property ${declaration.render()}"
}
isRealExpect = isRealExpect or declaration.isExpect
typeParameterContainers.add(declaration)
declaration.visitParent()
val isStaticProperty = if (accessor != null)
accessor.let {
it.dispatchReceiverParameter == null && declaration.parent !is IrPackageFragment && !declaration.parent.isFacadeClass
}
else {
// Fake override for a Java field
val backingField = declaration.resolveFakeOverride()?.backingField
?: error("Expected at least one accessor or a backing field for property ${declaration.render()}")
backingField.isStatic
}
if (isStaticProperty) {
builder.appendSignature(MangleConstant.STATIC_MEMBER_MARK)
}
accessor?.extensionReceiverParameter?.let {
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
mangleValueParameter(builder, it, null)
}
val typeParameters = accessor?.typeParameters ?: emptyList()
typeParameters.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) {
mangleTypeParameter(this, it.symbol, it.index, null)
}
builder.append(declaration.name.asString())
if (declaration.isSyntheticForJavaField) {
builder.append(MangleConstant.JAVA_FIELD_SUFFIX)
}
else {
// Fake override for a Java field
val backingField = declaration.resolveFakeOverride()?.backingField
?: error("Expected at least one accessor or a backing field for property ${declaration.render()}")
backingField.isStatic
}
if (isStaticProperty) {
builder.appendSignature(MangleConstant.STATIC_MEMBER_MARK)
private val IrProperty.isSyntheticForJavaField: Boolean
get() = origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && getter == null && setter == null
override fun visitField(declaration: IrField) {
val prop = declaration.correspondingPropertySymbol
if (compatibleMode || prop == null) { // act as used to be (KT-48912)
// test compiler/testData/codegen/box/ir/serializationRegressions/anonFakeOverride.kt
declaration.mangleSimpleDeclaration(declaration.name.asString())
} else {
visitProperty(prop.owner)
}
}
accessor?.extensionReceiverParameter?.let {
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
mangleValueParameter(builder, it)
}
val typeParameters = accessor?.typeParameters ?: emptyList()
typeParameters.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { mangleTypeParameter(this, it) }
builder.append(declaration.name.asString())
if (declaration.isSyntheticForJavaField) {
builder.append(MangleConstant.JAVA_FIELD_SUFFIX)
}
}
private val IrProperty.isSyntheticForJavaField: Boolean
get() = origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && getter == null && setter == null
override fun visitField(declaration: IrField) {
val prop = declaration.correspondingPropertySymbol
if (compatibleMode || prop == null) { // act as used to be (KT-48912)
// test compiler/testData/codegen/box/ir/serializationRegressions/anonFakeOverride.kt
override fun visitEnumEntry(declaration: IrEnumEntry) {
declaration.mangleSimpleDeclaration(declaration.name.asString())
} else {
visitProperty(prop.owner)
}
}
override fun visitEnumEntry(declaration: IrEnumEntry) {
declaration.mangleSimpleDeclaration(declaration.name.asString())
}
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer) {
val klass = declaration.parentAsClass
val anonInitializers = klass.declarations.filterIsInstance<IrAnonymousInitializer>()
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer) {
val klass = declaration.parentAsClass
val anonInitializers = klass.declarations.filterIsInstance<IrAnonymousInitializer>()
val anonName = buildString {
append(MangleConstant.ANON_INIT_NAME_PREFIX)
if (anonInitializers.size > 1) {
append(MangleConstant.LOCAL_DECLARATION_INDEX_PREFIX)
append(anonInitializers.indexOf(declaration))
val anonName = buildString {
append(MangleConstant.ANON_INIT_NAME_PREFIX)
if (anonInitializers.size > 1) {
append(MangleConstant.LOCAL_DECLARATION_INDEX_PREFIX)
append(anonInitializers.indexOf(declaration))
}
}
declaration.mangleSimpleDeclaration(anonName)
}
declaration.mangleSimpleDeclaration(anonName)
override fun visitTypeAlias(declaration: IrTypeAlias) =
declaration.mangleSimpleDeclaration(declaration.name.asString())
override fun visitTypeParameter(declaration: IrTypeParameter) {
getEffectiveParent(declaration.symbol).visit()
builder.appendSignature(MangleConstant.TYPE_PARAM_INDEX_PREFIX)
builder.appendSignature(declaration.index)
}
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
isRealExpect = isRealExpect or declaration.isExpect
val container = declaration.correspondingPropertySymbol?.owner ?: declaration
val isStatic = declaration.dispatchReceiverParameter == null &&
(container.parent !is IrPackageFragment && !container.parent.isFacadeClass)
declaration.mangleFunction(false, isStatic, container)
}
override fun visitConstructor(declaration: IrConstructor) =
declaration.mangleFunction(isCtor = true, isStatic = false, declaration)
}
override fun visitTypeAlias(declaration: IrTypeAlias) =
declaration.mangleSimpleDeclaration(declaration.name.asString())
override fun visitTypeParameter(declaration: IrTypeParameter) {
declaration.effectiveParent().acceptVoid(this)
builder.appendSignature(MangleConstant.TYPE_PARAM_INDEX_PREFIX)
builder.appendSignature(declaration.index)
}
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
isRealExpect = isRealExpect or declaration.isExpect
val container = declaration.correspondingPropertySymbol?.owner ?: declaration
val isStatic = declaration.dispatchReceiverParameter == null &&
(container.parent !is IrPackageFragment && !container.parent.isFacadeClass)
declaration.mangleFunction(false, isStatic, container)
}
override fun visitConstructor(declaration: IrConstructor) =
declaration.mangleFunction(isCtor = true, isStatic = false, declaration)
}
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.backend.common.serialization.mangle
import org.jetbrains.kotlin.name.FqName
fun <T> Collection<T>.collectForMangler(builder: StringBuilder, params: MangleConstant, collect: StringBuilder.(T) -> Unit) {
fun <T> Iterable<T>.collectForMangler(builder: StringBuilder, params: MangleConstant, collect: StringBuilder.(T) -> Unit) {
var first = true
builder.append(params.prefix)
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.java.lazy.descriptors.isJavaField
import org.jetbrains.kotlin.load.java.typeEnhancement.hasEnhancedNullability
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext
@@ -36,7 +37,7 @@ object JvmIrMangler : IrBasedKotlinManglerImpl() {
override fun copy(newMode: MangleMode): IrMangleComputer =
JvmIrManglerComputer(builder, newMode, compatibleMode)
override fun addReturnTypeSpecialCase(irFunction: IrFunction): Boolean = true
override fun addReturnTypeSpecialCase(function: IrFunction): Boolean = true
override fun mangleTypePlatformSpecific(type: IrType, tBuilder: StringBuilder) {
if (type.hasAnnotation(JvmAnnotationNames.ENHANCED_NULLABILITY_ANNOTATION)) {
@@ -61,7 +62,7 @@ class JvmDescriptorMangler(private val mainDetector: MainFunctionDetector?) : De
private val mainDetector: MainFunctionDetector?,
mode: MangleMode
) : DescriptorMangleComputer(builder, mode) {
override fun addReturnTypeSpecialCase(functionDescriptor: FunctionDescriptor): Boolean = true
override fun addReturnTypeSpecialCase(function: FunctionDescriptor): Boolean = true
override fun copy(newMode: MangleMode): DescriptorMangleComputer = JvmDescriptorManglerComputer(builder, mainDetector, newMode)
@@ -78,13 +79,13 @@ class JvmDescriptorMangler(private val mainDetector: MainFunctionDetector?) : De
return if (isJavaField) MangleConstant.JAVA_FIELD_SUFFIX else null
}
override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: Nothing?) {
override fun visitModuleDeclaration(descriptor: ModuleDescriptor) {
// In general, having module descriptor as `containingDeclaration` for regular declaration is considered an error (in JS/Native)
// because there should be `PackageFragmentDescriptor` in between
// but on JVM there is `SyntheticJavaPropertyDescriptor` whose parent is a module. So let just skip it.
}
override fun mangleTypePlatformSpecific(type: UnwrappedType, tBuilder: StringBuilder) {
override fun mangleTypePlatformSpecific(type: KotlinType, tBuilder: StringBuilder) {
// Disambiguate between 'double' and '@NotNull java.lang.Double' types in mixed Java/Kotlin class hierarchies
if (SimpleClassicTypeSystemContext.hasEnhancedNullability(type)) {
tBuilder.appendSignature(MangleConstant.ENHANCED_NULLABILITY_MARK)