Factor out duplicated mangling logic for functions into the base class

^KT-57777 Fixed
^KT-57818 Fixed
This commit is contained in:
Sergej Jaskiewicz
2023-04-13 11:35:30 +02:00
committed by Space Team
parent 8ae196d4fc
commit 02180e8685
77 changed files with 366 additions and 424 deletions
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.backend.common.serialization.mangle
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.model.*
/**
@@ -41,8 +42,6 @@ abstract class BaseKotlinMangleComputer<Declaration, Type, TypeParameter, ValueP
protected val typeParameterContainers = ArrayList<TypeParameterContainer>(4)
protected var isRealExpect = false
protected open fun FunctionDeclaration.platformSpecificFunctionName(): String? = null
protected open fun FunctionDeclaration.platformSpecificSuffix(): String? = null
@@ -85,6 +84,13 @@ abstract class BaseKotlinMangleComputer<Declaration, Type, TypeParameter, ValueP
protected abstract fun Declaration.visitParent()
/**
* Like [visitParent], but may have some logic that makes it suitable specifically for mangling function names.
*/
protected open fun Declaration.visitParentForFunctionMangling() {
visitParent()
}
protected abstract fun Declaration.visit()
final override fun computeMangle(declaration: Declaration): String {
@@ -103,6 +109,97 @@ abstract class BaseKotlinMangleComputer<Declaration, Type, TypeParameter, ValueP
builder.appendName(name)
}
protected abstract fun getContextReceiverTypes(function: FunctionDeclaration): List<Type>
protected abstract fun getExtensionReceiverParameterType(function: FunctionDeclaration): Type?
protected abstract fun getValueParameters(function: FunctionDeclaration): List<ValueParameter>
protected abstract fun getReturnType(function: FunctionDeclaration): Type?
protected abstract fun isUnit(type: Type): Boolean
protected abstract fun getTypeParametersWithIndices(
function: FunctionDeclaration,
container: Declaration,
): Iterable<IndexedValue<TypeParameter>>
protected open fun FunctionDeclaration.platformSpecificFunctionMarks(): List<String> = emptyList()
/**
* Simply attempts to cast [Declaration] to [TypeParameterContainer].
*/
protected abstract fun Declaration.asTypeParameterContainer(): TypeParameterContainer?
protected fun FunctionDeclaration.mangleFunction(
name: Name,
isConstructor: Boolean,
isStatic: Boolean,
container: Declaration,
session: Session
) {
container.asTypeParameterContainer()?.let(typeParameterContainers::add)
container.visitParentForFunctionMangling()
builder.appendName(MangleConstant.FUNCTION_NAME_PREFIX)
platformSpecificFunctionName()?.let {
builder.append(it)
return
}
builder.append(name.asString())
mangleSignature(isConstructor, isStatic, container, session)
}
private fun FunctionDeclaration.mangleSignature(
isConstructor: Boolean,
isStatic: Boolean,
typeParameterContainer: Declaration,
session: Session
) {
if (!mode.signature) return
if (!isConstructor && isStatic) {
builder.appendSignature(MangleConstant.STATIC_MEMBER_MARK)
}
platformSpecificFunctionMarks().forEach { builder.appendSignature(it) }
getContextReceiverTypes(this).forEach {
builder.appendSignature(MangleConstant.CONTEXT_RECEIVER_PREFIX)
mangleType(builder, it, session)
}
getExtensionReceiverParameterType(this)?.let {
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
mangleType(builder, it, session)
}
getValueParameters(this).collectForMangler(builder, MangleConstant.VALUE_PARAMETERS) {
appendSignature(specialValueParamPrefix(it))
mangleValueParameter(this, it, session)
}
getTypeParametersWithIndices(this, typeParameterContainer).collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) {
mangleTypeParameter(this, it.value, it.index, session)
}
getReturnType(this)?.let {
if (!isConstructor && !isUnit(it) && (addReturnType() || addReturnTypeSpecialCase(this@mangleSignature))) {
mangleType(builder, it, session)
}
}
platformSpecificSuffix()?.let {
builder.appendSignature(MangleConstant.PLATFORM_FUNCTION_MARKER)
builder.appendSignature(it)
}
}
protected abstract fun mangleType(tBuilder: StringBuilder, type: Type, declarationSiteSession: Session)
protected open fun mangleTypePlatformSpecific(type: Type, tBuilder: StringBuilder) {}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor
import org.jetbrains.kotlin.backend.common.serialization.isExpectMember
import org.jetbrains.kotlin.backend.common.serialization.mangle.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.descriptors.IrImplementingDelegateDescriptor
@@ -24,7 +25,7 @@ open class DescriptorMangleComputer(builder: StringBuilder, mode: MangleMode) :
/*Type=*/KotlinType,
/*TypeParameter=*/TypeParameterDescriptor,
/*ValueParameter=*/ValueParameterDescriptor,
/*TypeParameterContainer=*/DeclarationDescriptor,
/*TypeParameterContainer=*/DeclarationDescriptor, // CallableDescriptor or ClassDescriptor
/*FunctionDeclaration=*/FunctionDescriptor,
/*Session=*/Nothing?,
>(builder, mode) {
@@ -49,61 +50,32 @@ open class DescriptorMangleComputer(builder: StringBuilder, mode: MangleMode) :
private val CallableDescriptor.isRealStatic: Boolean
get() = dispatchReceiverParameter == null && containingDeclaration !is PackageFragmentDescriptor
private fun FunctionDescriptor.mangleFunction(isCtor: Boolean, container: CallableDescriptor) {
override fun DeclarationDescriptor.asTypeParameterContainer(): DeclarationDescriptor =
this
isRealExpect = isRealExpect or isExpect
override fun getContextReceiverTypes(function: FunctionDescriptor): List<KotlinType> =
function.contextReceiverParameters.map { it.type }
typeParameterContainers.add(container)
container.containingDeclaration.visit()
override fun getExtensionReceiverParameterType(function: FunctionDescriptor): KotlinType? =
function.extensionReceiverParameter?.type
builder.appendName(MangleConstant.FUNCTION_NAME_PREFIX)
override fun getValueParameters(function: FunctionDescriptor): List<ValueParameterDescriptor> =
function.valueParameters
platformSpecificFunctionName()?.let {
builder.append(it)
return
}
override fun getReturnType(function: FunctionDescriptor): KotlinType? =
function.returnType
builder.append(name.asString())
override fun getTypeParametersWithIndices(
function: FunctionDescriptor,
container: DeclarationDescriptor,
): List<IndexedValue<TypeParameterDescriptor>> =
(container as? CallableDescriptor)
?.typeParameters
.orEmpty()
.filter { it.containingDeclaration == container }
.map { IndexedValue(it.index, it) }
mangleSignature(isCtor, container)
}
private fun FunctionDescriptor.mangleSignature(isCtor: Boolean, realTypeParameterContainer: CallableDescriptor) {
if (!mode.signature) return
if (!isCtor && realTypeParameterContainer.isRealStatic) {
builder.appendSignature(MangleConstant.STATIC_MEMBER_MARK)
}
contextReceiverParameters.forEach {
builder.appendSignature(MangleConstant.CONTEXT_RECEIVER_PREFIX)
mangleType(builder, it.type, null)
}
extensionReceiverParameter?.let {
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
mangleExtensionReceiverParameter(builder, it)
}
valueParameters.collectForMangler(builder, MangleConstant.VALUE_PARAMETERS) {
appendSignature(specialValueParamPrefix(it))
mangleValueParameter(this, it, null)
}
realTypeParameterContainer.typeParameters.filter { it.containingDeclaration == realTypeParameterContainer }
.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { mangleTypeParameter(this, it, it.index, null) }
returnType?.run {
if (!isCtor && !isUnit() && (addReturnType() || addReturnTypeSpecialCase(this@mangleSignature))) {
mangleType(builder, this, null)
}
}
platformSpecificSuffix()?.let {
builder.appendSignature(MangleConstant.PLATFORM_FUNCTION_MARKER)
builder.appendSignature(it)
}
}
override fun isUnit(type: KotlinType) = type.isUnit()
private fun mangleExtensionReceiverParameter(vpBuilder: StringBuilder, param: ReceiverParameterDescriptor) {
mangleType(vpBuilder, param.type, null)
@@ -111,7 +83,8 @@ open class DescriptorMangleComputer(builder: StringBuilder, mode: MangleMode) :
final override fun isVararg(valueParameter: ValueParameterDescriptor) = valueParameter.varargElementType != null
final override fun getValueParameterType(valueParameter: ValueParameterDescriptor) = valueParameter.type
final override fun getValueParameterType(valueParameter: ValueParameterDescriptor): KotlinType =
valueParameter.type
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
final override fun mangleType(tBuilder: StringBuilder, wrappedType: KotlinType, declarationSiteSession: Nothing?) {
@@ -173,7 +146,13 @@ open class DescriptorMangleComputer(builder: StringBuilder, mode: MangleMode) :
private fun manglePropertyAccessor(accessor: PropertyAccessorDescriptor) {
val property = accessor.correspondingProperty
accessor.mangleFunction(false, property)
accessor.mangleFunction(
name = accessor.name,
isConstructor = false,
isStatic = property.isRealStatic,
container = property,
session = null
)
}
protected open fun visitModuleDeclaration(descriptor: ModuleDescriptor) = reportUnexpectedDescriptor(descriptor)
@@ -189,7 +168,13 @@ open class DescriptorMangleComputer(builder: StringBuilder, mode: MangleMode) :
override fun visitVariableDescriptor(descriptor: VariableDescriptor, data: Nothing?) = reportUnexpectedDescriptor(descriptor)
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Nothing?) {
descriptor.mangleFunction(false, descriptor)
descriptor.mangleFunction(
name = descriptor.name,
isConstructor = false,
isStatic = descriptor.isRealStatic,
container = descriptor,
session = null
)
}
override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor, data: Nothing?) {
@@ -200,7 +185,6 @@ open class DescriptorMangleComputer(builder: StringBuilder, mode: MangleMode) :
}
override fun visitClassDescriptor(descriptor: ClassDescriptor, data: Nothing?) {
isRealExpect = isRealExpect or descriptor.isExpect
typeParameterContainers.add(descriptor)
descriptor.mangleSimpleDeclaration(descriptor.name.asString())
}
@@ -214,7 +198,13 @@ open class DescriptorMangleComputer(builder: StringBuilder, mode: MangleMode) :
}
override fun visitConstructorDescriptor(constructorDescriptor: ConstructorDescriptor, data: Nothing?) {
constructorDescriptor.mangleFunction(isCtor = true, container = constructorDescriptor)
constructorDescriptor.mangleFunction(
name = constructorDescriptor.name,
isConstructor = true,
isStatic = constructorDescriptor.isRealStatic,
container = constructorDescriptor,
session = null
)
}
override fun visitScriptDescriptor(scriptDescriptor: ScriptDescriptor, data: Nothing?) =
@@ -230,8 +220,6 @@ open class DescriptorMangleComputer(builder: StringBuilder, mode: MangleMode) :
val extensionReceiver = actualDescriptor.extensionReceiverParameter
isRealExpect = isRealExpect or actualDescriptor.isExpect
typeParameterContainers.add(actualDescriptor)
actualDescriptor.containingDeclaration.visit()
@@ -40,8 +40,6 @@ open class IrMangleComputer(
get() = throw UnsupportedOperationException("Builtins are unavailable")
}
open fun IrFunction.platformSpecificFunctionMarks(): List<String> = emptyList()
override fun copy(newMode: MangleMode) = IrMangleComputer(builder, newMode, compatibleMode)
final override fun IrDeclaration.visitParent() {
@@ -52,70 +50,47 @@ open class IrMangleComputer(
acceptVoid(Visitor())
}
private fun IrFunction.mangleFunction(isCtor: Boolean, isStatic: Boolean, container: IrDeclaration) {
override fun IrDeclaration.asTypeParameterContainer(): IrDeclaration =
this
isRealExpect = isRealExpect or isExpect
typeParameterContainers.add(container)
val containerParent = container.parent
val realParent =
if (containerParent is IrField && containerParent.origin == IrDeclarationOrigin.DELEGATE) containerParent.parent else containerParent
override fun IrDeclaration.visitParentForFunctionMangling() {
val declarationParent = parent
val realParent = if (declarationParent is IrField && declarationParent.origin == IrDeclarationOrigin.DELEGATE)
declarationParent.parent
else
declarationParent
realParent.acceptVoid(Visitor())
builder.appendName(MangleConstant.FUNCTION_NAME_PREFIX)
platformSpecificFunctionName()?.let {
builder.append(it)
return
}
val funName = name.asString()
builder.append(funName)
mangleSignature(isCtor, isStatic)
}
private fun IrFunction.mangleSignature(isCtor: Boolean, isStatic: Boolean) {
if (!mode.signature) return
override fun getContextReceiverTypes(function: IrFunction): List<IrType> =
function
.valueParameters
.asSequence()
.take(function.contextReceiverParametersCount)
.filterNot { it.isHidden }
.map { it.type }
.toList()
if (isStatic) {
builder.appendSignature(MangleConstant.STATIC_MEMBER_MARK)
}
override fun getExtensionReceiverParameterType(function: IrFunction) =
function
.extensionReceiverParameter
?.takeUnless { it.isHidden }
?.type
platformSpecificFunctionMarks().forEach {
builder.appendSignature(it)
}
override fun getValueParameters(function: IrFunction): List<IrValueParameter> =
function
.valueParameters
.asSequence()
.drop(function.contextReceiverParametersCount)
.filterNot { it.isHidden }
.toList()
valueParameters.take(contextReceiverParametersCount).forEach {
if (!it.isHidden) {
builder.appendSignature(MangleConstant.CONTEXT_RECEIVER_PREFIX)
mangleType(builder, it.type, null)
}
}
override fun getReturnType(function: IrFunction) = function.returnType
extensionReceiverParameter?.let {
if (!it.isHidden) {
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
mangleValueParameter(builder, it, null)
}
}
override fun getTypeParametersWithIndices(function: IrFunction, container: IrDeclaration): List<IndexedValue<IrTypeParameterSymbol>> =
function.typeParameters.map { IndexedValue(it.index, it.symbol) }
valueParameters.drop(contextReceiverParametersCount).collectForMangler(builder, MangleConstant.VALUE_PARAMETERS) {
if (!it.isHidden) {
appendSignature(specialValueParamPrefix(it))
mangleValueParameter(this, it, null)
}
}
typeParameters.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) {
mangleTypeParameter(this, it.symbol, it.index, null)
}
if (!isCtor && !returnType.isUnit() && (addReturnType() || addReturnTypeSpecialCase(this))) {
mangleType(builder, returnType, null)
}
}
override fun isUnit(type: IrType) = type.isUnit()
final override fun getEffectiveParent(typeParameter: IrTypeParameterSymbol): IrDeclaration = typeParameter.owner.run {
when (val irParent = parent) {
@@ -171,7 +146,6 @@ open class IrMangleComputer(
}
override fun visitClass(declaration: IrClass) {
isRealExpect = isRealExpect or declaration.isExpect
typeParameterContainers.add(declaration)
val className = declaration.name.asString()
@@ -188,7 +162,6 @@ open class IrMangleComputer(
"Expected at least one accessor or backing field for property ${declaration.render()}"
}
isRealExpect = isRealExpect or declaration.isExpect
typeParameterContainers.add(declaration)
declaration.visitParent()
@@ -268,16 +241,26 @@ open class IrMangleComputer(
}
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)
declaration.mangleFunction(
name = declaration.name,
isConstructor = false,
isStatic = isStatic,
container = container,
session = null
)
}
override fun visitConstructor(declaration: IrConstructor) =
declaration.mangleFunction(isCtor = true, isStatic = false, declaration)
override fun visitConstructor(declaration: IrConstructor) {
declaration.mangleFunction(
name = declaration.name,
isConstructor = true,
isStatic = false,
container = declaration,
session = null
)
}
}
}