IC mangling: Generalize mangling algorithm between two backends
This commit is contained in:
+76
-65
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.codegen.state
|
||||
|
||||
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
|
||||
@@ -23,6 +24,62 @@ const val NOT_INLINE_CLASS_PARAMETER_PLACEHOLDER = "_"
|
||||
|
||||
private fun FunctionDescriptor.isFunctionFromStdlib(): Boolean = fqNameSafe.startsWith(Name.identifier("kotlin"))
|
||||
|
||||
class InfoForMangling(
|
||||
val fqName: FqNameUnsafe,
|
||||
val isInline: Boolean,
|
||||
val isNullable: Boolean
|
||||
)
|
||||
|
||||
fun collectFunctionSignatureForManglingSuffix(
|
||||
useOldManglingRules: Boolean,
|
||||
requiresFunctionNameManglingForParameterTypes: Boolean,
|
||||
fqNamesForMangling: List<InfoForMangling?>,
|
||||
returnTypeInfo: InfoForMangling?,
|
||||
): String? {
|
||||
fun getSignatureElementForMangling(info: InfoForMangling?): String = buildString {
|
||||
if (info == null) return ""
|
||||
if (useOldManglingRules || info.isInline) {
|
||||
append('L')
|
||||
append(info.fqName)
|
||||
if (info.isNullable) append('?')
|
||||
append(';')
|
||||
} else {
|
||||
append(NOT_INLINE_CLASS_PARAMETER_PLACEHOLDER)
|
||||
}
|
||||
}
|
||||
|
||||
fun collectSignatureForMangling(): String =
|
||||
fqNamesForMangling.joinToString(separator = if (useOldManglingRules) ", " else "") {
|
||||
getSignatureElementForMangling(it)
|
||||
}
|
||||
|
||||
if (useOldManglingRules) {
|
||||
if (requiresFunctionNameManglingForParameterTypes) {
|
||||
return collectSignatureForMangling()
|
||||
}
|
||||
|
||||
// If a class member function returns inline class value, mangle its name.
|
||||
// NB here function can be a suspend function JVM view with return type replaced with 'Any',
|
||||
// should unwrap it and take original return type instead.
|
||||
if (returnTypeInfo != null) {
|
||||
return ":" + getSignatureElementForMangling(returnTypeInfo)
|
||||
}
|
||||
} else {
|
||||
// If a function accepts inline class parameters, mangle its name.
|
||||
if (requiresFunctionNameManglingForParameterTypes || returnTypeInfo != null) {
|
||||
// If a class member function returns inline class value, mangle its name.
|
||||
// NB here function can be a suspend function JVM view with return type replaced with 'Any',
|
||||
// should unwrap it and take original return type instead.
|
||||
val signature = collectSignatureForMangling() +
|
||||
if (returnTypeInfo != null)
|
||||
":" + getSignatureElementForMangling(returnTypeInfo)
|
||||
else ""
|
||||
return signature
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun getManglingSuffixBasedOnKotlinSignature(
|
||||
descriptor: CallableMemberDescriptor,
|
||||
shouldMangleByReturnType: Boolean,
|
||||
@@ -38,77 +95,31 @@ fun getManglingSuffixBasedOnKotlinSignature(
|
||||
|
||||
val unwrappedDescriptor = descriptor.unwrapInitialDescriptorForSuspendFunction()
|
||||
|
||||
if (useOldManglingRules || descriptor.isFunctionFromStdlib()) {
|
||||
if (requiresFunctionNameManglingForParameterTypes(descriptor)) {
|
||||
return "-" + md5base64(collectSignatureForMangling(descriptor, true))
|
||||
}
|
||||
val resultNew = collectFunctionSignatureForManglingSuffix(
|
||||
useOldManglingRules = useOldManglingRules || descriptor.isFunctionFromStdlib(),
|
||||
requiresFunctionNameManglingForParameterTypes = requiresFunctionNameManglingForParameterTypes(descriptor),
|
||||
fqNamesForMangling =
|
||||
(listOfNotNull(descriptor.extensionReceiverParameter?.type) + descriptor.valueParameters.map { it.type })
|
||||
.map { getInfoForMangling(it) },
|
||||
returnTypeInfo =
|
||||
if (shouldMangleByReturnType && requiresFunctionNameManglingForReturnType(unwrappedDescriptor))
|
||||
getInfoForMangling(unwrappedDescriptor.returnType!!)
|
||||
else null
|
||||
)
|
||||
|
||||
// If a class member function returns inline class value, mangle its name.
|
||||
// NB here function can be a suspend function JVM view with return type replaced with 'Any',
|
||||
// should unwrap it and take original return type instead.
|
||||
if (shouldMangleByReturnType) {
|
||||
if (requiresFunctionNameManglingForReturnType(unwrappedDescriptor)) {
|
||||
return "-" + md5base64(
|
||||
":" + getSignatureElementForMangling(
|
||||
unwrappedDescriptor.returnType!!, true
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If a function accepts inline class parameters, mangle its name.
|
||||
if (requiresFunctionNameManglingForParameterTypes(descriptor) ||
|
||||
(shouldMangleByReturnType && requiresFunctionNameManglingForReturnType(unwrappedDescriptor))
|
||||
) {
|
||||
// If a class member function returns inline class value, mangle its name.
|
||||
// NB here function can be a suspend function JVM view with return type replaced with 'Any',
|
||||
// should unwrap it and take original return type instead.
|
||||
val signature = collectSignatureForMangling(descriptor, false) +
|
||||
if (shouldMangleByReturnType && requiresFunctionNameManglingForReturnType(unwrappedDescriptor))
|
||||
":" + getSignatureElementForMangling(unwrappedDescriptor.returnType!!, false)
|
||||
else ""
|
||||
return "-" + md5base64(signature)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
return resultNew?.let { "-" + md5base64(it) }
|
||||
}
|
||||
|
||||
private fun collectSignatureForMangling(descriptor: CallableMemberDescriptor, useOldManglingRules: Boolean): String {
|
||||
val types = listOfNotNull(descriptor.extensionReceiverParameter?.type) + descriptor.valueParameters.map { it.type }
|
||||
return types.joinToString(separator = if (useOldManglingRules) ", " else "") { getSignatureElementForMangling(it, useOldManglingRules) }
|
||||
}
|
||||
private fun getInfoForMangling(type: KotlinType): InfoForMangling? {
|
||||
val descriptor = type.constructor.declarationDescriptor ?: return null
|
||||
return when (descriptor) {
|
||||
is ClassDescriptor -> InfoForMangling(descriptor.fqNameUnsafe, descriptor.isInline, type.isMarkedNullable)
|
||||
|
||||
private fun getSignatureElementForMangling(type: KotlinType, useOldManglingRules: Boolean): String = buildString {
|
||||
val descriptor = type.constructor.declarationDescriptor ?: return ""
|
||||
if (useOldManglingRules) {
|
||||
when (descriptor) {
|
||||
is ClassDescriptor -> {
|
||||
append('L')
|
||||
append(descriptor.fqNameUnsafe)
|
||||
if (type.isMarkedNullable) append('?')
|
||||
append(';')
|
||||
}
|
||||
|
||||
is TypeParameterDescriptor -> {
|
||||
append(getSignatureElementForMangling(descriptor.representativeUpperBound, useOldManglingRules))
|
||||
}
|
||||
is TypeParameterDescriptor -> {
|
||||
getInfoForMangling(descriptor.representativeUpperBound)
|
||||
}
|
||||
} else {
|
||||
when (descriptor) {
|
||||
is ClassDescriptor -> if (descriptor.isInline) {
|
||||
append('L')
|
||||
append(descriptor.fqNameUnsafe)
|
||||
if (type.isMarkedNullable) append('?')
|
||||
append(';')
|
||||
} else {
|
||||
append(NOT_INLINE_CLASS_PARAMETER_PLACEHOLDER)
|
||||
}
|
||||
|
||||
is TypeParameterDescriptor -> {
|
||||
append(getSignatureElementForMangling(descriptor.representativeUpperBound, useOldManglingRules))
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user