[IR] Refactored Kotlin Mangler API
- Implement abstract Ir-based, Descriptor-based mangler computers and export checkers and corresponding platform specializations - Add runtime verifier which check whether all types of mangler produces the same type of data Note: code migration is not finished yet
This commit is contained in:
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
|
||||
import org.jetbrains.kotlin.backend.common.ir.isTopLevel
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerForBE
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
||||
|
||||
fun <T> mapToKey(declaration: T): String {
|
||||
return with(JsManglerForBE) {
|
||||
return with(JsManglerIr) {
|
||||
if (declaration is IrDeclaration && isPublic(declaration)) {
|
||||
declaration.hashedMangle.toString()
|
||||
} else if (declaration is Signature) {
|
||||
@@ -32,7 +32,7 @@ fun <T> mapToKey(declaration: T): String {
|
||||
}
|
||||
}
|
||||
|
||||
fun JsManglerForBE.isPublic(declaration: IrDeclaration) =
|
||||
fun JsManglerIr.isPublic(declaration: IrDeclaration) =
|
||||
declaration.isExported() && declaration !is IrScript && declaration !is IrVariable && declaration !is IrValueParameter
|
||||
|
||||
class NameTable<T>(
|
||||
|
||||
@@ -5,22 +5,35 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.util
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
interface KotlinMangler {
|
||||
interface KotlinMangler<D : Any> {
|
||||
|
||||
val String.hashMangle: Long
|
||||
val IrDeclaration.hashedMangle: Long
|
||||
fun IrDeclaration.isExported(): Boolean
|
||||
val IrFunction.functionName: String
|
||||
val IrType.isInlined: Boolean
|
||||
val Long.isSpecial: Boolean
|
||||
|
||||
companion object {
|
||||
private val FUNCTION_PREFIX = "<BUILT-IN-FUNCTION>"
|
||||
fun functionClassSymbolName(name: Name) = "ktype:$FUNCTION_PREFIX$name"
|
||||
fun functionInvokeSymbolName(name: Name) = "kfun:$FUNCTION_PREFIX$name.invoke"
|
||||
fun D.isExported(): Boolean
|
||||
val D.mangleString: String
|
||||
|
||||
val D.hashedMangle: Long get() = mangleString.hashMangle
|
||||
|
||||
val manglerName: String
|
||||
|
||||
interface DescriptorMangler : KotlinMangler<DeclarationDescriptor> {
|
||||
override val manglerName: String
|
||||
get() = "Descriptor"
|
||||
|
||||
fun ClassDescriptor.isExportEnumEntry(): Boolean
|
||||
fun ClassDescriptor.mangleEnumEntryString(): String
|
||||
|
||||
fun PropertyDescriptor.isExportField(): Boolean
|
||||
fun PropertyDescriptor.mangleFieldString(): String
|
||||
}
|
||||
|
||||
interface IrMangler : KotlinMangler<IrDeclaration> {
|
||||
override val manglerName: String
|
||||
get() = "Ir"
|
||||
}
|
||||
}
|
||||
|
||||
-362
@@ -1,362 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.isExpect
|
||||
import org.jetbrains.kotlin.backend.common.ir.isProperExpect
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
private const val PUBLIC_MANGLE_FLAG = 1L shl 63
|
||||
|
||||
abstract class KotlinManglerImpl : KotlinMangler {
|
||||
|
||||
override val String.hashMangle get() = (this.cityHash64() % PUBLIC_MANGLE_FLAG) or PUBLIC_MANGLE_FLAG
|
||||
|
||||
private fun hashedMangleImpl(declaration: IrDeclaration): Long {
|
||||
return declaration.uniqSymbolName().hashMangle
|
||||
}
|
||||
|
||||
override val IrDeclaration.hashedMangle: Long
|
||||
get() = hashedMangleImpl(this)
|
||||
|
||||
|
||||
// We can't call "with (super) { this.isExported() }" in children.
|
||||
// So provide a hook.
|
||||
protected open fun IrDeclaration.isPlatformSpecificExported(): Boolean = false
|
||||
|
||||
override fun IrDeclaration.isExported(): Boolean = isExportedImpl(this)
|
||||
|
||||
/**
|
||||
* Defines whether the declaration is exported, i.e. visible from other modules.
|
||||
*
|
||||
* Exported declarations must have predictable and stable ABI
|
||||
* that doesn't depend on any internal transformations (e.g. IR lowering),
|
||||
* and so should be computable from the descriptor itself without checking a backend state.
|
||||
*/
|
||||
private tailrec fun isExportedImpl(declaration: IrDeclaration): Boolean {
|
||||
// TODO: revise
|
||||
val descriptorAnnotations = declaration.descriptor.annotations
|
||||
|
||||
if (declaration.isPlatformSpecificExported()) return true
|
||||
|
||||
if (declaration is IrTypeAlias && declaration.parent is IrPackageFragment) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (descriptorAnnotations.hasAnnotation(publishedApiAnnotation)) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (declaration.isAnonymousObject)
|
||||
return false
|
||||
|
||||
if (declaration is IrConstructor && declaration.constructedClass.kind.isSingleton) {
|
||||
// Currently code generator can access the constructor of the singleton,
|
||||
// so ignore visibility of the constructor itself.
|
||||
return isExportedImpl(declaration.constructedClass)
|
||||
}
|
||||
|
||||
if (declaration is IrFunction) {
|
||||
val descriptor = declaration.descriptor
|
||||
// TODO: this code is required because accessor doesn't have a reference to property.
|
||||
if (descriptor is PropertyAccessorDescriptor) {
|
||||
val property = descriptor.correspondingProperty
|
||||
if (property.annotations.hasAnnotation(publishedApiAnnotation)) return true
|
||||
}
|
||||
}
|
||||
|
||||
val visibility = when (declaration) {
|
||||
is IrClass -> declaration.visibility
|
||||
is IrFunction -> declaration.visibility
|
||||
is IrProperty -> declaration.visibility
|
||||
is IrField -> declaration.visibility
|
||||
is IrTypeAlias -> declaration.visibility
|
||||
else -> null
|
||||
}
|
||||
|
||||
/**
|
||||
* note: about INTERNAL - with support of friend modules we let frontend to deal with internal declarations.
|
||||
*/
|
||||
if (visibility != null && !visibility.isPublicAPI && visibility != Visibilities.INTERNAL) {
|
||||
// If the declaration is explicitly marked as non-public,
|
||||
// then it must not be accessible from other modules.
|
||||
return false
|
||||
}
|
||||
|
||||
val parent = declaration.parent
|
||||
if (parent is IrDeclaration) {
|
||||
return isExportedImpl(parent)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun IrTypeParameter.effectiveParent(): IrDeclaration = when (val irParent = parent) {
|
||||
is IrClass -> irParent
|
||||
is IrConstructor -> irParent
|
||||
is IrSimpleFunction -> irParent.correspondingPropertySymbol?.owner ?: irParent
|
||||
else -> error("Unexpected type parameter container")
|
||||
}
|
||||
|
||||
private fun collectTypeParameterContainers(element: IrElement): List<IrDeclaration> {
|
||||
val result = mutableListOf<IrDeclaration>()
|
||||
|
||||
tailrec fun collectTypeParameterContainersImpl(element: IrElement) {
|
||||
when (element) {
|
||||
is IrConstructor -> result += element
|
||||
is IrSimpleFunction -> result.add(element.correspondingPropertySymbol?.owner ?: element)
|
||||
is IrProperty -> result += element
|
||||
is IrClass -> result += element
|
||||
else -> return
|
||||
}
|
||||
|
||||
collectTypeParameterContainersImpl((element as IrDeclaration).parent)
|
||||
}
|
||||
|
||||
collectTypeParameterContainersImpl(element)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun mapTypeParameterContainers(element: IrElement): Map<IrDeclaration, Int> {
|
||||
return collectTypeParameterContainers(element).mapIndexed { i, d -> d to i }.toMap()
|
||||
}
|
||||
|
||||
private val publishedApiAnnotation = FqName("kotlin.PublishedApi")
|
||||
|
||||
protected open fun mangleTypeParameter(typeParameter: IrTypeParameter, typeParameterNamer: (IrTypeParameter) -> String): String {
|
||||
return typeParameterNamer(typeParameter)
|
||||
}
|
||||
|
||||
protected fun acyclicTypeMangler(type: IrType, typeParameterNamer: (IrTypeParameter) -> String): String {
|
||||
|
||||
var hashString = type.classifierOrNull?.let {
|
||||
when (it) {
|
||||
is IrClassSymbol -> it.owner.fqNameForIrSerialization.asString()
|
||||
is IrTypeParameterSymbol -> mangleTypeParameter(it.owner, typeParameterNamer)
|
||||
else -> error("Unexpected type constructor")
|
||||
}
|
||||
} ?: "<dynamic>"
|
||||
|
||||
when (type) {
|
||||
is IrSimpleType -> {
|
||||
if (!type.arguments.isEmpty()) {
|
||||
hashString += "<${type.arguments.map {
|
||||
when (it) {
|
||||
is IrStarProjection -> "#STAR"
|
||||
is IrTypeProjection -> {
|
||||
val variance = it.variance.label
|
||||
val projection = if (variance == "") "" else "${variance}_"
|
||||
projection + acyclicTypeMangler(it.type, typeParameterNamer)
|
||||
}
|
||||
else -> error(it)
|
||||
}
|
||||
}.joinToString(",")}>"
|
||||
}
|
||||
|
||||
if (type.hasQuestionMark) hashString += "?"
|
||||
}
|
||||
!is IrDynamicType -> {
|
||||
error(type)
|
||||
}
|
||||
}
|
||||
return hashString
|
||||
}
|
||||
|
||||
protected fun typeToHashString(type: IrType, typeParameterNamer: (IrTypeParameter) -> String) =
|
||||
acyclicTypeMangler(type, typeParameterNamer)
|
||||
|
||||
fun IrValueParameter.extensionReceiverNamePart(typeParameterNamer: (IrTypeParameter) -> String): String =
|
||||
"@${typeToHashString(this.type, typeParameterNamer)}."
|
||||
|
||||
open fun IrFunction.valueParamsPart(typeParameterNamer: (IrTypeParameter) -> String): String {
|
||||
return this.valueParameters.map {
|
||||
"${typeToHashString(it.type, typeParameterNamer)}${if (it.isVararg) "_VarArg" else ""}"
|
||||
}.joinToString(";")
|
||||
}
|
||||
|
||||
open fun IrFunction.typeParamsPart(typeParameters: List<IrTypeParameter>, typeParameterNamer: (IrTypeParameter) -> String): String {
|
||||
if (typeParameters.isEmpty()) return ""
|
||||
|
||||
fun mangleTypeParameter(index: Int, typeParameter: IrTypeParameter): String {
|
||||
// We use type parameter index instead of name since changing name is not a binary-incompatible change
|
||||
return typeParameter.superTypes.joinToString("&", "$index<", ">") {
|
||||
acyclicTypeMangler(it, typeParameterNamer)
|
||||
}
|
||||
}
|
||||
|
||||
return typeParameters.withIndex().joinToString(";", "{", "}") { (i, tp) ->
|
||||
mangleTypeParameter(i, tp)
|
||||
}
|
||||
}
|
||||
|
||||
open fun IrFunction.signature(typeParameterNamer: (IrTypeParameter) -> String): String {
|
||||
val extensionReceiverPart = this.extensionReceiverParameter?.extensionReceiverNamePart(typeParameterNamer) ?: ""
|
||||
val valueParamsPart = this.valueParamsPart(typeParameterNamer)
|
||||
// Distinguish value types and references - it's needed for calling virtual methods through bridges.
|
||||
// Also is function has type arguments - frontend allows exactly matching overrides.
|
||||
val signatureSuffix =
|
||||
when {
|
||||
this.typeParameters.isNotEmpty() -> "Generic"
|
||||
!returnType.isUnitOrNullableUnit() -> typeToHashString(returnType, typeParameterNamer)
|
||||
else -> ""
|
||||
}
|
||||
|
||||
val typesParamsPart = this.typeParamsPart(typeParameters, typeParameterNamer)
|
||||
|
||||
return "$extensionReceiverPart($valueParamsPart)$typesParamsPart$signatureSuffix"
|
||||
}
|
||||
|
||||
open val IrFunction.platformSpecificFunctionName: String? get() = null
|
||||
|
||||
// TODO: rename to indicate that it has signature included
|
||||
override val IrFunction.functionName: String
|
||||
get() {
|
||||
// TODO: Again. We can't call super in children, so provide a hook for now.
|
||||
this.platformSpecificFunctionName?.let { return it }
|
||||
|
||||
val typeContainerMap = mapTypeParameterContainers(this)
|
||||
val typeParameterNamer: (IrTypeParameter) -> String = {
|
||||
val eParent = it.effectiveParent()
|
||||
"${typeContainerMap[eParent] ?: error("No parent for ${it.render()}")}:${it.index}"
|
||||
}
|
||||
|
||||
val name = this.name.mangleIfInternal(this.module, this.visibility)
|
||||
return "$name${signature(typeParameterNamer)}"
|
||||
}
|
||||
|
||||
override val Long.isSpecial: Boolean
|
||||
get() = specialHashes.contains(this)
|
||||
|
||||
fun Name.mangleIfInternal(moduleDescriptor: ModuleDescriptor, visibility: Visibility): String =
|
||||
if (visibility != Visibilities.INTERNAL) {
|
||||
this.asString()
|
||||
} else {
|
||||
val moduleName = moduleDescriptor.name.asString()
|
||||
.let { it.substring(1, it.lastIndex) } // Remove < and >.
|
||||
|
||||
"$this\$$moduleName"
|
||||
}
|
||||
|
||||
val IrField.symbolName: String
|
||||
get() {
|
||||
val containingDeclarationPart = parent.fqNameForIrSerialization.let {
|
||||
if (it.isRoot) "" else "$it."
|
||||
}
|
||||
return "kfield:$containingDeclarationPart$name"
|
||||
|
||||
}
|
||||
|
||||
val IrClass.typeInfoSymbolName: String
|
||||
get() {
|
||||
assert(isExportedImpl(this))
|
||||
if (isBuiltInFunction(this))
|
||||
return KotlinMangler.functionClassSymbolName(name)
|
||||
return "ktype:" + this.fqNameForIrSerialization.toString()
|
||||
}
|
||||
|
||||
val IrTypeParameter.symbolName: String
|
||||
get() {
|
||||
|
||||
val parentDeclaration = (parent as? IrSimpleFunction)?.correspondingPropertySymbol?.owner ?: parent
|
||||
val containingDeclarationPart = when (parentDeclaration) {
|
||||
is IrDeclaration -> parentDeclaration.uniqSymbolName()
|
||||
else -> error("Unexpected type parameter parent")
|
||||
}
|
||||
return "ktypeparam:$containingDeclarationPart$name@$index"
|
||||
}
|
||||
|
||||
val IrTypeAlias.symbolName: String
|
||||
get() {
|
||||
val containingDeclarationPart = parent.fqNameForIrSerialization.let {
|
||||
if (it.isRoot) "" else "$it."
|
||||
}
|
||||
return "ktypealias:$containingDeclarationPart$name"
|
||||
}
|
||||
|
||||
// This is a little extension over what's used in real mangling
|
||||
// since some declarations never appear in the bitcode symbols.
|
||||
|
||||
internal fun IrDeclaration.uniqSymbolName(): String = when (this) {
|
||||
is IrFunction -> this.uniqFunctionName
|
||||
is IrProperty -> this.symbolName
|
||||
is IrClass -> this.typeInfoSymbolName
|
||||
is IrField -> this.symbolName
|
||||
is IrEnumEntry -> this.symbolName
|
||||
is IrTypeParameter -> this.symbolName
|
||||
is IrTypeAlias -> this.symbolName
|
||||
else -> error("Unexpected exported declaration: $this")
|
||||
} + expectPart
|
||||
|
||||
// TODO: need to figure out the proper OptionalExpectation behavior
|
||||
private val IrDeclaration.expectPart get() = if (this.isProperExpect) "#expect" else ""
|
||||
|
||||
private val IrDeclarationParent.fqNameUnique: FqName
|
||||
get() = when (this) {
|
||||
is IrPackageFragment -> this.fqName
|
||||
is IrDeclaration -> this.parent.fqNameUnique.child(this.uniqName)
|
||||
else -> error(this)
|
||||
}
|
||||
|
||||
private val IrDeclaration.uniqName: Name
|
||||
get() = when (this) {
|
||||
is IrSimpleFunction -> Name.special("<${this.uniqFunctionName}>")
|
||||
else -> this.nameForIrSerialization
|
||||
}
|
||||
|
||||
private val IrProperty.symbolName: String
|
||||
get() {
|
||||
val typeContainerMap = mapTypeParameterContainers(this)
|
||||
val typeParameterNamer: (IrTypeParameter) -> String = {
|
||||
val eParent = it.effectiveParent()
|
||||
"${typeContainerMap[eParent] ?: error("No parent for ${it.render()}")}:${it.index}"
|
||||
}
|
||||
|
||||
val extensionReceiver: String = getter?.extensionReceiverParameter?.extensionReceiverNamePart(typeParameterNamer) ?: ""
|
||||
|
||||
val containingDeclarationPart = parent.fqNameForIrSerialization.let {
|
||||
if (it.isRoot) "" else "$it."
|
||||
}
|
||||
return "kprop:$containingDeclarationPart$extensionReceiver$name"
|
||||
}
|
||||
|
||||
private val IrEnumEntry.symbolName: String
|
||||
get() {
|
||||
val containingDeclarationPart = parent.fqNameForIrSerialization.let {
|
||||
if (it.isRoot) "" else "$it."
|
||||
}
|
||||
return "kenumentry:$containingDeclarationPart$name"
|
||||
}
|
||||
|
||||
// This is basicly the same as .symbolName, but disambiguates external functions with the same C name.
|
||||
// In addition functions appearing in fq sequence appear as <full signature>.
|
||||
private val IrFunction.uniqFunctionName: String
|
||||
get() {
|
||||
if (isBuiltInFunction(this))
|
||||
return KotlinMangler.functionInvokeSymbolName(parentAsClass.name)
|
||||
val parent = this.parent
|
||||
|
||||
val containingDeclarationPart = parent.fqNameUnique.let {
|
||||
if (it.isRoot) "" else "$it."
|
||||
}
|
||||
|
||||
return "kfun:$containingDeclarationPart#$functionName"
|
||||
}
|
||||
|
||||
private val specialHashes = listOf("Function", "KFunction", "SuspendFunction", "KSuspendFunction")
|
||||
.flatMap { name ->
|
||||
(0..255).map { KotlinMangler.functionClassSymbolName(Name.identifier(name + it)) }
|
||||
}.map { it.hashMangle }
|
||||
.toSet()
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.backend.common.serialization.cityHash64
|
||||
import org.jetbrains.kotlin.ir.util.KotlinMangler
|
||||
|
||||
abstract class AbstractKotlinMangler<D : Any> : KotlinMangler<D> {
|
||||
override val String.hashMangle get() = cityHash64()
|
||||
|
||||
protected abstract fun getExportChecker(): KotlinExportChecker<D>
|
||||
protected abstract fun getMangleComputer(prefix: String): KotlinMangleComputer<D>
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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
|
||||
|
||||
interface KotlinExportChecker<D : Any> {
|
||||
fun check(declaration: D, type: SpecialDeclarationType): Boolean
|
||||
|
||||
fun D.isPlatformSpecificExported(): Boolean
|
||||
}
|
||||
+4
-6
@@ -3,10 +3,8 @@
|
||||
* 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.ir.backend.js.lower.serialization.metadata
|
||||
package org.jetbrains.kotlin.backend.common.serialization.mangle
|
||||
|
||||
class JsKlibMetadataModuleDescriptor<out T>(
|
||||
val name: String,
|
||||
val imported: List<String>,
|
||||
val data: T
|
||||
)
|
||||
interface KotlinMangleComputer<D : Any> {
|
||||
fun computeMangle(declaration: D): String
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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
|
||||
|
||||
enum class MangleConstant(val prefix: Char, val separator: Char, val suffix: Char) {
|
||||
VALUE_PARAMETERS('(', ';', ')'),
|
||||
TYPE_PARAMETERS('{', ';', '}'),
|
||||
UPPER_BOUNDS('<', '&', '>'),
|
||||
TYPE_ARGUMENTS('<', ',', '>'),
|
||||
FLEXIBLE_TYPE('[', '~', ']');
|
||||
|
||||
companion object {
|
||||
const val VAR_ARG_MARK = "..."
|
||||
const val STAR_MARK = '*'
|
||||
const val Q_MARK = '?'
|
||||
const val EXPECT_MARK = "#expect"
|
||||
const val UNKNOWN_MARK = "<unknown>"
|
||||
const val DYNAMIC_MARK = "<dynamic>"
|
||||
|
||||
const val VARIANCE_SEPARATOR = '|'
|
||||
const val UPPER_BOUND_SEPARATOR = '§'
|
||||
const val PREFIX_SEPARATOR = ':'
|
||||
const val MODULE_SEPARATOR = '$'
|
||||
const val FQN_SEPARATOR = '.'
|
||||
const val INDEX_SEPARATOR = ':'
|
||||
|
||||
const val PLATFORM_FUNCTION_MARKER = '%'
|
||||
|
||||
const val EXTENSION_RECEIVER_PREFIX = '@'
|
||||
const val FUNCTION_NAME_PREFIX = '#'
|
||||
const val TYPE_PARAM_INDEX_PREFIX = '@'
|
||||
|
||||
const val EMPTY_PREFIX = ""
|
||||
|
||||
const val FUN_PREFIX = "kfun"
|
||||
const val CLASS_PREFIX = "kclass"
|
||||
const val PROPERTY_PREFIX = "kprop"
|
||||
const val FIELD_PREFIX = "kfield"
|
||||
const val ENUM_ENTRY_PREFIX = "kenumentry"
|
||||
const val TYPE_ALIAS_PREFIX = "ktypealias"
|
||||
const val TYPE_PARAM_PREFIX = "ktypeparam"
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.util.KotlinMangler
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
|
||||
class ManglerChecker(vararg _manglers: KotlinMangler<IrDeclaration>) : IrElementVisitorVoid {
|
||||
|
||||
private val manglers = _manglers.toList()
|
||||
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
private fun KotlinMangler<IrDeclaration>.isExportCheck(declaration: IrDeclaration) = declaration.isExported()
|
||||
private fun KotlinMangler<IrDeclaration>.stringMangle(declaration: IrDeclaration) = declaration.mangleString
|
||||
|
||||
private fun <T : Any, R> Iterable<T>.checkAllEqual(init: R, op: T.() -> R, onError: (T, R, T, R) -> Unit): R {
|
||||
var prev: T? = null
|
||||
|
||||
var r = init
|
||||
|
||||
for (it in this) {
|
||||
if (prev == null) {
|
||||
r = it.op()
|
||||
prev = it
|
||||
} else {
|
||||
val tmp = it.op()
|
||||
if (r != tmp) {
|
||||
onError(prev, r, it, tmp)
|
||||
}
|
||||
prev = it
|
||||
r = tmp
|
||||
}
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
override fun visitDeclaration(declaration: IrDeclaration) {
|
||||
|
||||
val exported = manglers.checkAllEqual(false, { isExportCheck(declaration) }) { m1, r1, m2, r2 ->
|
||||
println("${declaration.render()}\n ${m1.manglerName}: $r1\n ${m2.manglerName}: $r2\n")
|
||||
error("${declaration.render()}\n ${m1.manglerName}: $r1\n ${m2.manglerName}: $r2\n")
|
||||
}
|
||||
|
||||
if (!exported) return
|
||||
|
||||
manglers.checkAllEqual("", { stringMangle(declaration) }) { m1, r1, m2, r2 ->
|
||||
println("${declaration.render()}\n ${m1.manglerName}: $r1\n ${m2.manglerName}: $r2\n")
|
||||
error("${declaration.render()}\n ${m1.manglerName}: $r1\n ${m2.manglerName}: $r2\n")
|
||||
}
|
||||
|
||||
declaration.acceptChildrenVoid(this)
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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
|
||||
|
||||
enum class SpecialDeclarationType {
|
||||
REGULAR,
|
||||
ANON_INIT,
|
||||
BACKING_FIELD,
|
||||
ENUM_ENTRY;
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.descriptor
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.AbstractKotlinMangler
|
||||
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.SpecialDeclarationType
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrAnonymousInitializer
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrEnumEntry
|
||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||
import org.jetbrains.kotlin.ir.util.KotlinMangler
|
||||
|
||||
abstract class DescriptorBasedKotlinManglerImpl : AbstractKotlinMangler<DeclarationDescriptor>(), KotlinMangler.DescriptorMangler {
|
||||
private fun withPrefix(prefix: String, descriptor: DeclarationDescriptor): String =
|
||||
getMangleComputer(prefix).computeMangle(descriptor)
|
||||
|
||||
override fun ClassDescriptor.mangleEnumEntryString(): String = withPrefix(MangleConstant.ENUM_ENTRY_PREFIX, this)
|
||||
|
||||
override fun ClassDescriptor.isExportEnumEntry(): Boolean =
|
||||
getExportChecker().check(this, SpecialDeclarationType.ENUM_ENTRY)
|
||||
|
||||
override fun PropertyDescriptor.isExportField(): Boolean = false
|
||||
|
||||
override fun PropertyDescriptor.mangleFieldString(): String = error("Fields supposed to be non-exporting")
|
||||
|
||||
override val DeclarationDescriptor.mangleString: String
|
||||
get() = withPrefix(MangleConstant.EMPTY_PREFIX, this)
|
||||
|
||||
override fun DeclarationDescriptor.isExported(): Boolean = getExportChecker().check(this, SpecialDeclarationType.REGULAR)
|
||||
}
|
||||
|
||||
class Ir2DescriptorManglerAdapter(private val delegate: DescriptorBasedKotlinManglerImpl) : AbstractKotlinMangler<IrDeclaration>(),
|
||||
KotlinMangler.IrMangler {
|
||||
override val manglerName: String
|
||||
get() = delegate.manglerName
|
||||
|
||||
override fun IrDeclaration.isExported(): Boolean {
|
||||
return when (this) {
|
||||
is IrAnonymousInitializer -> false
|
||||
is IrEnumEntry -> delegate.run { descriptor.isExportEnumEntry() }
|
||||
is IrField -> delegate.run { descriptor.isExportField() }
|
||||
else -> delegate.run { descriptor.isExported() }
|
||||
}
|
||||
}
|
||||
|
||||
override val IrDeclaration.mangleString: String
|
||||
get() {
|
||||
return when (this) {
|
||||
is IrEnumEntry -> delegate.run { descriptor.mangleEnumEntryString() }
|
||||
is IrField -> delegate.run { descriptor.mangleFieldString() }
|
||||
else -> delegate.run { descriptor.mangleString }
|
||||
}
|
||||
}
|
||||
|
||||
override fun getExportChecker() = error("Should not have been reached")
|
||||
|
||||
override fun getMangleComputer(prefix: String): KotlinMangleComputer<IrDeclaration> = error("Should not have been reached")
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.descriptor
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinExportChecker
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.SpecialDeclarationType
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.publishedApiAnnotation
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
|
||||
abstract class DescriptorExportCheckerVisitor : DeclarationDescriptorVisitor<Boolean, SpecialDeclarationType>,
|
||||
KotlinExportChecker<DeclarationDescriptor> {
|
||||
|
||||
override fun check(declaration: DeclarationDescriptor, type: SpecialDeclarationType): Boolean {
|
||||
return declaration.accept(this, type)
|
||||
}
|
||||
|
||||
private fun reportUnexpectedDescriptor(descriptor: DeclarationDescriptor): Nothing {
|
||||
error("unexpected descriptor $descriptor")
|
||||
}
|
||||
|
||||
private fun Visibility.isPubliclyVisible(): Boolean = isPublicAPI || this === Visibilities.INTERNAL
|
||||
|
||||
private fun DeclarationDescriptorNonRoot.isExported(annotations: Annotations, visibility: Visibility?): Boolean {
|
||||
if (annotations.hasAnnotation(publishedApiAnnotation)) return true
|
||||
if (visibility != null && !visibility.isPubliclyVisible()) return false
|
||||
|
||||
return containingDeclaration.accept(this@DescriptorExportCheckerVisitor, SpecialDeclarationType.REGULAR) ?: false
|
||||
}
|
||||
|
||||
override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor, data: SpecialDeclarationType) = true
|
||||
|
||||
override fun visitPackageViewDescriptor(descriptor: PackageViewDescriptor, data: SpecialDeclarationType) = true
|
||||
|
||||
override fun visitVariableDescriptor(descriptor: VariableDescriptor, data: SpecialDeclarationType) = false
|
||||
|
||||
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: SpecialDeclarationType): Boolean {
|
||||
return descriptor.run { isExported(annotations, visibility) }
|
||||
}
|
||||
|
||||
override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor, data: SpecialDeclarationType): Boolean = false
|
||||
|
||||
override fun visitClassDescriptor(descriptor: ClassDescriptor, data: SpecialDeclarationType): Boolean {
|
||||
if (data == SpecialDeclarationType.ANON_INIT) return false
|
||||
if (descriptor.name == SpecialNames.NO_NAME_PROVIDED) return false
|
||||
if (descriptor.kind == ClassKind.ENUM_ENTRY && data == SpecialDeclarationType.REGULAR) return false
|
||||
return descriptor.run { isExported(annotations, visibility) }
|
||||
}
|
||||
|
||||
override fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, data: SpecialDeclarationType) =
|
||||
if (descriptor.containingDeclaration is PackageFragmentDescriptor) true
|
||||
else descriptor.run { isExported(annotations, visibility) }
|
||||
|
||||
override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: SpecialDeclarationType): Boolean {
|
||||
reportUnexpectedDescriptor(descriptor)
|
||||
}
|
||||
|
||||
override fun visitConstructorDescriptor(constructorDescriptor: ConstructorDescriptor, data: SpecialDeclarationType): Boolean {
|
||||
val klass = constructorDescriptor.constructedClass
|
||||
return if (klass.kind.isSingleton)
|
||||
klass.accept(this, SpecialDeclarationType.REGULAR)
|
||||
else constructorDescriptor.run { isExported(annotations, visibility) }
|
||||
}
|
||||
|
||||
override fun visitScriptDescriptor(scriptDescriptor: ScriptDescriptor, data: SpecialDeclarationType): Boolean {
|
||||
reportUnexpectedDescriptor(scriptDescriptor)
|
||||
}
|
||||
|
||||
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: SpecialDeclarationType): Boolean {
|
||||
val visibility = if (data == SpecialDeclarationType.BACKING_FIELD) {
|
||||
return false
|
||||
} else descriptor.visibility
|
||||
|
||||
return descriptor.run { isExported(annotations, visibility) }
|
||||
}
|
||||
|
||||
override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor, data: SpecialDeclarationType): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun visitPropertyGetterDescriptor(descriptor: PropertyGetterDescriptor, data: SpecialDeclarationType): Boolean {
|
||||
return descriptor.run { isExported(correspondingProperty.annotations, visibility) }
|
||||
}
|
||||
|
||||
override fun visitPropertySetterDescriptor(descriptor: PropertySetterDescriptor, data: SpecialDeclarationType): Boolean {
|
||||
return descriptor.run { isExported(correspondingProperty.annotations, visibility) }
|
||||
}
|
||||
|
||||
override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor, data: SpecialDeclarationType) = false
|
||||
|
||||
}
|
||||
+255
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.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.collect
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
||||
|
||||
abstract class DescriptorMangleComputer(protected val builder: StringBuilder, protected val specialPrefix: String) :
|
||||
DeclarationDescriptorVisitor<Unit, Boolean>, KotlinMangleComputer<DeclarationDescriptor> {
|
||||
|
||||
override fun computeMangle(declaration: DeclarationDescriptor): String {
|
||||
declaration.accept(this, true)
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
protected abstract fun copy(): DescriptorMangleComputer
|
||||
|
||||
private val typeParameterContainer = ArrayList<DeclarationDescriptor>(4)
|
||||
|
||||
private var isRealExpect = false
|
||||
|
||||
private fun addPrefix(prefix: String, addPrefix: Boolean): Int {
|
||||
if (addPrefix) {
|
||||
builder.append(prefix)
|
||||
builder.append(MangleConstant.PREFIX_SEPARATOR)
|
||||
}
|
||||
return builder.length
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.mangleSimpleDeclaration(prefix: String, addPrefix: Boolean, name: String) {
|
||||
val prefixLength = addPrefix(prefix, addPrefix)
|
||||
containingDeclaration?.accept(this@DescriptorMangleComputer, false)
|
||||
|
||||
if (prefixLength != builder.length) builder.append(MangleConstant.FQN_SEPARATOR)
|
||||
|
||||
builder.append(name)
|
||||
}
|
||||
|
||||
open val FunctionDescriptor.platformSpecificFunctionName: String? get() = null
|
||||
|
||||
private fun reportUnexpectedDescriptor(descriptor: DeclarationDescriptor) {
|
||||
error("unexpected descriptor $descriptor")
|
||||
}
|
||||
|
||||
open fun FunctionDescriptor.platformSpecificSuffix(): String? = null
|
||||
|
||||
private fun FunctionDescriptor.mangleFunction(isCtor: Boolean, prefix: Boolean, container: CallableDescriptor) {
|
||||
|
||||
isRealExpect = isRealExpect or isExpect
|
||||
|
||||
val prefixLength = addPrefix(MangleConstant.FUN_PREFIX, prefix)
|
||||
|
||||
typeParameterContainer.add(container)
|
||||
container.containingDeclaration.accept(this@DescriptorMangleComputer, false)
|
||||
|
||||
if (prefixLength != builder.length) builder.append(MangleConstant.FQN_SEPARATOR)
|
||||
|
||||
builder.append(MangleConstant.FUNCTION_NAME_PREFIX)
|
||||
|
||||
if (visibility != Visibilities.INTERNAL) builder.append(name)
|
||||
else {
|
||||
builder.append(name)
|
||||
builder.append(MangleConstant.MODULE_SEPARATOR)
|
||||
builder.append(module.name.asString().run { substring(1, lastIndex) })
|
||||
}
|
||||
|
||||
mangleSignature(isCtor, container)
|
||||
|
||||
platformSpecificSuffix()?.let {
|
||||
builder.append(MangleConstant.PLATFORM_FUNCTION_MARKER)
|
||||
builder.append(it)
|
||||
}
|
||||
|
||||
if (prefix && isRealExpect) builder.append(MangleConstant.EXPECT_MARK)
|
||||
}
|
||||
|
||||
private fun FunctionDescriptor.mangleSignature(isCtor: Boolean, realTypeParameterContainer: CallableDescriptor) {
|
||||
|
||||
extensionReceiverParameter?.let {
|
||||
builder.append(MangleConstant.EXTENSION_RECEIVER_PREFIX)
|
||||
mangleExtensionReceiverParameter(builder, it)
|
||||
}
|
||||
|
||||
valueParameters.collect(builder, MangleConstant.VALUE_PARAMETERS) { mangleValueParameter(this, it) }
|
||||
realTypeParameterContainer.typeParameters.filter { it.containingDeclaration == realTypeParameterContainer }
|
||||
.collect(builder, MangleConstant.TYPE_PARAMETERS) { mangleTypeParameter(this, it) }
|
||||
|
||||
returnType?.run {
|
||||
if (!isCtor && !isUnit()) {
|
||||
mangleType(builder, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun mangleExtensionReceiverParameter(vpBuilder: StringBuilder, param: ReceiverParameterDescriptor) {
|
||||
mangleType(vpBuilder, param.type)
|
||||
}
|
||||
|
||||
private fun mangleValueParameter(vpBuilder: StringBuilder, param: ValueParameterDescriptor) {
|
||||
mangleType(vpBuilder, param.type)
|
||||
|
||||
if (param.varargElementType != null) vpBuilder.append(MangleConstant.VAR_ARG_MARK)
|
||||
}
|
||||
|
||||
private fun mangleTypeParameter(tpBuilder: StringBuilder, param: TypeParameterDescriptor) {
|
||||
tpBuilder.append(param.index)
|
||||
tpBuilder.append(MangleConstant.UPPER_BOUND_SEPARATOR)
|
||||
|
||||
param.upperBounds.collect(tpBuilder, MangleConstant.UPPER_BOUNDS) { mangleType(this, it) }
|
||||
}
|
||||
|
||||
private fun mangleType(tBuilder: StringBuilder, wtype: KotlinType) {
|
||||
when (val type = wtype.unwrap()) {
|
||||
is SimpleType -> {
|
||||
when (val classifier = type.constructor.declarationDescriptor) {
|
||||
is ClassDescriptor -> classifier.accept(copy(), false)
|
||||
is TypeParameterDescriptor -> tBuilder.mangleTypeParameterReference(classifier)
|
||||
else -> error("Unexpected classifier: $classifier")
|
||||
}
|
||||
|
||||
type.arguments.ifNotEmpty {
|
||||
collect(tBuilder, MangleConstant.TYPE_ARGUMENTS) { arg ->
|
||||
if (arg.isStarProjection) {
|
||||
append(MangleConstant.STAR_MARK)
|
||||
} else {
|
||||
if (arg.projectionKind != Variance.INVARIANT) {
|
||||
append(arg.projectionKind.label)
|
||||
append(MangleConstant.VARIANCE_SEPARATOR)
|
||||
}
|
||||
|
||||
mangleType(this, arg.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type.isMarkedNullable) tBuilder.append(MangleConstant.Q_MARK)
|
||||
}
|
||||
is DynamicType -> tBuilder.append(MangleConstant.DYNAMIC_MARK)
|
||||
is FlexibleType -> {
|
||||
// TODO: is that correct way to mangle flexible type?
|
||||
with(MangleConstant.FLEXIBLE_TYPE) {
|
||||
tBuilder.append(prefix)
|
||||
mangleType(tBuilder, type.lowerBound)
|
||||
tBuilder.append(separator)
|
||||
mangleType(tBuilder, type.upperBound)
|
||||
tBuilder.append(suffix)
|
||||
}
|
||||
}
|
||||
else -> error("Unexpected type $wtype")
|
||||
}
|
||||
}
|
||||
|
||||
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()}" }
|
||||
append(ci)
|
||||
append(MangleConstant.INDEX_SEPARATOR)
|
||||
append(typeParameter.index)
|
||||
}
|
||||
|
||||
override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor, data: Boolean) {
|
||||
descriptor.fqName.let { if (!it.isRoot) builder.append(it.asString()) }
|
||||
}
|
||||
|
||||
override fun visitPackageViewDescriptor(descriptor: PackageViewDescriptor, data: Boolean) = reportUnexpectedDescriptor(descriptor)
|
||||
|
||||
override fun visitVariableDescriptor(descriptor: VariableDescriptor, data: Boolean) = reportUnexpectedDescriptor(descriptor)
|
||||
|
||||
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Boolean) {
|
||||
descriptor.platformSpecificFunctionName?.let {
|
||||
builder.append(it)
|
||||
return
|
||||
}
|
||||
|
||||
descriptor.mangleFunction(false, data, descriptor)
|
||||
}
|
||||
|
||||
override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor, data: Boolean) {
|
||||
addPrefix(MangleConstant.TYPE_PARAM_PREFIX, data)
|
||||
descriptor.containingDeclaration.accept(this, data)
|
||||
|
||||
builder.append(MangleConstant.TYPE_PARAM_INDEX_PREFIX)
|
||||
builder.append(descriptor.index)
|
||||
}
|
||||
|
||||
override fun visitClassDescriptor(descriptor: ClassDescriptor, data: Boolean) {
|
||||
isRealExpect = isRealExpect or descriptor.isExpect
|
||||
typeParameterContainer.add(descriptor)
|
||||
val prefix = if (specialPrefix == MangleConstant.ENUM_ENTRY_PREFIX) specialPrefix else MangleConstant.CLASS_PREFIX
|
||||
descriptor.mangleSimpleDeclaration(prefix, data, descriptor.name.asString())
|
||||
|
||||
if (data && isRealExpect) builder.append(MangleConstant.EXPECT_MARK)
|
||||
}
|
||||
|
||||
override fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, data: Boolean) {
|
||||
descriptor.mangleSimpleDeclaration(MangleConstant.TYPE_ALIAS_PREFIX, data, descriptor.name.asString())
|
||||
}
|
||||
|
||||
override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: Boolean) = reportUnexpectedDescriptor(descriptor)
|
||||
|
||||
override fun visitConstructorDescriptor(constructorDescriptor: ConstructorDescriptor, data: Boolean) {
|
||||
constructorDescriptor.mangleFunction(true, data, constructorDescriptor)
|
||||
}
|
||||
|
||||
override fun visitScriptDescriptor(scriptDescriptor: ScriptDescriptor, data: Boolean) = reportUnexpectedDescriptor(scriptDescriptor)
|
||||
|
||||
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Boolean) {
|
||||
val extensionReceiver = descriptor.extensionReceiverParameter
|
||||
|
||||
val prefix = if (specialPrefix == MangleConstant.FIELD_PREFIX) specialPrefix else MangleConstant.PROPERTY_PREFIX
|
||||
val prefixLength = addPrefix(prefix, data)
|
||||
|
||||
isRealExpect = isRealExpect or descriptor.isExpect
|
||||
typeParameterContainer.add(descriptor)
|
||||
descriptor.containingDeclaration.accept(this, false)
|
||||
|
||||
if (prefixLength != builder.length) builder.append(MangleConstant.FQN_SEPARATOR)
|
||||
|
||||
if (extensionReceiver != null) {
|
||||
builder.append(MangleConstant.EXTENSION_RECEIVER_PREFIX)
|
||||
mangleExtensionReceiverParameter(builder, extensionReceiver)
|
||||
}
|
||||
|
||||
builder.append(descriptor.name)
|
||||
if (data && isRealExpect) builder.append(MangleConstant.EXPECT_MARK)
|
||||
}
|
||||
|
||||
override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor, data: Boolean) = reportUnexpectedDescriptor(descriptor)
|
||||
|
||||
private fun manglePropertyAccessor(accessor: PropertyAccessorDescriptor, data: Boolean) {
|
||||
accessor.mangleFunction(false, data, accessor.correspondingProperty)
|
||||
}
|
||||
|
||||
override fun visitPropertyGetterDescriptor(descriptor: PropertyGetterDescriptor, data: Boolean) {
|
||||
manglePropertyAccessor(descriptor, data)
|
||||
}
|
||||
|
||||
override fun visitPropertySetterDescriptor(descriptor: PropertySetterDescriptor, data: Boolean) {
|
||||
manglePropertyAccessor(descriptor, data)
|
||||
}
|
||||
|
||||
override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor, data: Boolean) =
|
||||
reportUnexpectedDescriptor(descriptor)
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.AbstractKotlinMangler
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.SpecialDeclarationType
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.util.KotlinMangler
|
||||
|
||||
abstract class IrBasedKotlinManglerImpl : AbstractKotlinMangler<IrDeclaration>(), KotlinMangler.IrMangler {
|
||||
override val IrDeclaration.mangleString: String
|
||||
get() = getMangleComputer("").computeMangle(this)
|
||||
|
||||
override fun IrDeclaration.isExported(): Boolean = getExportChecker().check(this, SpecialDeclarationType.REGULAR)
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinExportChecker
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.SpecialDeclarationType
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.publishedApiAnnotation
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
import org.jetbrains.kotlin.ir.util.constructedClass
|
||||
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
|
||||
abstract class IrExportCheckerVisitor : IrElementVisitor<Boolean, Nothing?>, KotlinExportChecker<IrDeclaration> {
|
||||
|
||||
override fun check(declaration: IrDeclaration, type: SpecialDeclarationType): Boolean {
|
||||
return declaration.accept(this, null)
|
||||
}
|
||||
|
||||
abstract override fun IrDeclaration.isPlatformSpecificExported(): Boolean
|
||||
|
||||
private fun IrDeclaration.isExported(annotations: List<IrConstructorCall>, visibility: Visibility?): Boolean {
|
||||
if (annotations.hasAnnotation(publishedApiAnnotation)) return true
|
||||
if (visibility != null && !visibility.isPubliclyVisible()) return false
|
||||
|
||||
return parent.accept(this@IrExportCheckerVisitor, null)
|
||||
}
|
||||
|
||||
private fun Visibility.isPubliclyVisible(): Boolean = isPublicAPI || this === Visibilities.INTERNAL
|
||||
|
||||
override fun visitElement(element: IrElement, data: Nothing?): Boolean = error("Should bot reach here ${element.render()}")
|
||||
|
||||
override fun visitDeclaration(declaration: IrDeclaration, data: Nothing?) = declaration.run { isExported(annotations, null) }
|
||||
|
||||
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer, data: Nothing?) = false
|
||||
override fun visitValueParameter(declaration: IrValueParameter, data: Nothing?) = false
|
||||
override fun visitVariable(declaration: IrVariable, data: Nothing?) = false
|
||||
override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty, data: Nothing?) = false
|
||||
|
||||
override fun visitTypeParameter(declaration: IrTypeParameter, data: Nothing?) = false
|
||||
|
||||
override fun visitField(declaration: IrField, data: Nothing?) = false
|
||||
|
||||
override fun visitProperty(declaration: IrProperty, data: Nothing?): Boolean {
|
||||
return declaration.run { isExported(annotations, visibility) }
|
||||
}
|
||||
|
||||
override fun visitPackageFragment(declaration: IrPackageFragment, data: Nothing?): Boolean = true
|
||||
|
||||
override fun visitTypeAlias(declaration: IrTypeAlias, data: Nothing?): Boolean =
|
||||
if (declaration.parent is IrPackageFragment) true
|
||||
else declaration.run { isExported(annotations, visibility) }
|
||||
|
||||
override fun visitClass(declaration: IrClass, data: Nothing?): Boolean {
|
||||
if (declaration.name == SpecialNames.NO_NAME_PROVIDED) return false
|
||||
return declaration.run { isExported(annotations, visibility) }
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor, data: Nothing?): Boolean {
|
||||
val klass = declaration.constructedClass
|
||||
return if (klass.kind.isSingleton) klass.accept(this, null) else declaration.run { isExported(annotations, visibility) }
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(declaration: IrSimpleFunction, data: Nothing?): Boolean {
|
||||
val annotations = declaration.run { correspondingPropertySymbol?.owner?.annotations ?: annotations }
|
||||
return declaration.run { isExported(annotations, visibility) }
|
||||
}
|
||||
}
|
||||
+230
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.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.collect
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.isVararg
|
||||
import org.jetbrains.kotlin.ir.util.module
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
||||
|
||||
abstract class IrMangleComputer(protected val builder: StringBuilder) : IrElementVisitor<Unit, Boolean>,
|
||||
KotlinMangleComputer<IrDeclaration> {
|
||||
|
||||
private val typeParameterContainer = ArrayList<IrDeclaration>(4)
|
||||
|
||||
private var isRealExpect = false
|
||||
|
||||
open val IrFunction.platformSpecificFunctionName: String? get() = null
|
||||
|
||||
protected abstract fun copy(): IrMangleComputer
|
||||
|
||||
override fun computeMangle(declaration: IrDeclaration): String {
|
||||
declaration.accept(this, true)
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
private fun addPrefix(prefix: String, addPrefix: Boolean): Int {
|
||||
if (addPrefix) {
|
||||
builder.append(prefix)
|
||||
builder.append(MangleConstant.PREFIX_SEPARATOR)
|
||||
}
|
||||
return builder.length
|
||||
}
|
||||
|
||||
private fun IrDeclaration.mangleSimpleDeclaration(prefix: String, addPrefix: Boolean, name: String) {
|
||||
val prefixLength = addPrefix(prefix, addPrefix)
|
||||
parent.accept(this@IrMangleComputer, false)
|
||||
|
||||
if (prefixLength != builder.length) builder.append(MangleConstant.FQN_SEPARATOR)
|
||||
|
||||
builder.append(name)
|
||||
}
|
||||
|
||||
private fun IrFunction.mangleFunction(isCtor: Boolean, prefix: Boolean, container: IrDeclaration) {
|
||||
|
||||
isRealExpect = isRealExpect or isExpect
|
||||
|
||||
val prefixLength = addPrefix(MangleConstant.FUN_PREFIX, prefix)
|
||||
|
||||
typeParameterContainer.add(container)
|
||||
container.parent.accept(this@IrMangleComputer, false)
|
||||
|
||||
if (prefixLength != builder.length) builder.append(MangleConstant.FQN_SEPARATOR)
|
||||
|
||||
builder.append(MangleConstant.FUNCTION_NAME_PREFIX)
|
||||
|
||||
if (visibility != Visibilities.INTERNAL) builder.append(name)
|
||||
else {
|
||||
builder.append(name)
|
||||
builder.append(MangleConstant.MODULE_SEPARATOR)
|
||||
val moduleName = try {
|
||||
module.name.asString().run { substring(1, lastIndex) }
|
||||
} catch (e: Throwable) {
|
||||
MangleConstant.UNKNOWN_MARK
|
||||
}
|
||||
builder.append(moduleName)
|
||||
}
|
||||
|
||||
mangleSignature(isCtor)
|
||||
|
||||
if (prefix && isRealExpect) builder.append(MangleConstant.EXPECT_MARK)
|
||||
}
|
||||
|
||||
private fun IrFunction.mangleSignature(isCtor: Boolean) {
|
||||
|
||||
extensionReceiverParameter?.let {
|
||||
builder.append(MangleConstant.EXTENSION_RECEIVER_PREFIX)
|
||||
mangleValueParameter(builder, it)
|
||||
}
|
||||
|
||||
valueParameters.collect(builder, MangleConstant.VALUE_PARAMETERS) { mangleValueParameter(this, it) }
|
||||
typeParameters.collect(builder, MangleConstant.TYPE_PARAMETERS) { mangleTypeParameter(this, it) }
|
||||
|
||||
if (!isCtor && !returnType.isUnit()) {
|
||||
mangleType(builder, returnType)
|
||||
}
|
||||
}
|
||||
|
||||
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()}")
|
||||
}
|
||||
|
||||
private fun mangleValueParameter(vpBuilder: StringBuilder, param: IrValueParameter) {
|
||||
mangleType(vpBuilder, param.type)
|
||||
|
||||
if (param.isVararg) vpBuilder.append(MangleConstant.VAR_ARG_MARK)
|
||||
}
|
||||
|
||||
private fun mangleTypeParameter(tpBuilder: StringBuilder, param: IrTypeParameter) {
|
||||
tpBuilder.append(param.index)
|
||||
tpBuilder.append(MangleConstant.UPPER_BOUND_SEPARATOR)
|
||||
|
||||
param.superTypes.collect(tpBuilder, MangleConstant.UPPER_BOUNDS) { mangleType(this, it) }
|
||||
}
|
||||
|
||||
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()}" }
|
||||
append(ci)
|
||||
append(MangleConstant.INDEX_SEPARATOR)
|
||||
append(typeParameter.index)
|
||||
}
|
||||
|
||||
private fun mangleType(tBuilder: StringBuilder, type: IrType) {
|
||||
when (type) {
|
||||
is IrSimpleType -> {
|
||||
when (val classifier = type.classifier) {
|
||||
is IrClassSymbol -> classifier.owner.accept(copy(), false)
|
||||
is IrTypeParameterSymbol -> tBuilder.mangleTypeParameterReference(classifier.owner)
|
||||
}
|
||||
|
||||
type.arguments.ifNotEmpty {
|
||||
collect(tBuilder, MangleConstant.TYPE_ARGUMENTS) { arg ->
|
||||
when (arg) {
|
||||
is IrStarProjection -> append(MangleConstant.STAR_MARK)
|
||||
is IrTypeProjection -> {
|
||||
if (arg.variance != Variance.INVARIANT) {
|
||||
append(arg.variance.label)
|
||||
append(MangleConstant.VARIANCE_SEPARATOR)
|
||||
}
|
||||
|
||||
mangleType(this, arg.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type.hasQuestionMark) tBuilder.append(MangleConstant.Q_MARK)
|
||||
}
|
||||
is IrDynamicType -> tBuilder.append(MangleConstant.DYNAMIC_MARK)
|
||||
else -> error("Unexpected type $type")
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitElement(element: IrElement, data: Boolean) = error("unexpected element ${element.render()}")
|
||||
|
||||
override fun visitClass(declaration: IrClass, data: Boolean) {
|
||||
isRealExpect = isRealExpect or declaration.isExpect
|
||||
typeParameterContainer.add(declaration)
|
||||
declaration.mangleSimpleDeclaration(MangleConstant.CLASS_PREFIX, data, declaration.name.asString())
|
||||
|
||||
if (data && isRealExpect) builder.append(MangleConstant.EXPECT_MARK)
|
||||
}
|
||||
|
||||
override fun visitPackageFragment(declaration: IrPackageFragment, data: Boolean) {
|
||||
declaration.fqName.let { if (!it.isRoot) builder.append(it.asString()) }
|
||||
}
|
||||
|
||||
override fun visitProperty(declaration: IrProperty, data: Boolean) {
|
||||
val extensionReceiver = declaration.run { (getter ?: setter)?.extensionReceiverParameter }
|
||||
|
||||
val prefixLength = addPrefix(MangleConstant.PROPERTY_PREFIX, data)
|
||||
|
||||
isRealExpect = isRealExpect or declaration.isExpect
|
||||
typeParameterContainer.add(declaration)
|
||||
declaration.parent.accept(this, false)
|
||||
|
||||
if (prefixLength != builder.length) builder.append(MangleConstant.FQN_SEPARATOR)
|
||||
|
||||
if (extensionReceiver != null) {
|
||||
builder.append(MangleConstant.EXTENSION_RECEIVER_PREFIX)
|
||||
mangleValueParameter(builder, extensionReceiver)
|
||||
}
|
||||
|
||||
builder.append(declaration.name)
|
||||
if (data && isRealExpect) builder.append(MangleConstant.EXPECT_MARK)
|
||||
}
|
||||
|
||||
override fun visitField(declaration: IrField, data: Boolean) =
|
||||
declaration.mangleSimpleDeclaration(MangleConstant.FIELD_PREFIX, data, declaration.name.asString())
|
||||
|
||||
override fun visitEnumEntry(declaration: IrEnumEntry, data: Boolean) {
|
||||
declaration.mangleSimpleDeclaration(MangleConstant.ENUM_ENTRY_PREFIX, data, declaration.name.asString())
|
||||
if (data && isRealExpect) builder.append(MangleConstant.EXPECT_MARK)
|
||||
}
|
||||
|
||||
override fun visitTypeAlias(declaration: IrTypeAlias, data: Boolean) =
|
||||
declaration.mangleSimpleDeclaration(MangleConstant.TYPE_ALIAS_PREFIX, data, declaration.name.asString())
|
||||
|
||||
override fun visitTypeParameter(declaration: IrTypeParameter, data: Boolean) {
|
||||
addPrefix(MangleConstant.TYPE_PARAM_PREFIX, data)
|
||||
declaration.effectiveParent().accept(this, data)
|
||||
|
||||
builder.append(MangleConstant.TYPE_PARAM_INDEX_PREFIX)
|
||||
builder.append(declaration.index)
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(declaration: IrSimpleFunction, data: Boolean) {
|
||||
|
||||
isRealExpect = isRealExpect or declaration.isExpect
|
||||
|
||||
declaration.platformSpecificFunctionName?.let {
|
||||
builder.append(it)
|
||||
return
|
||||
}
|
||||
|
||||
val container = declaration.correspondingPropertySymbol?.owner ?: declaration
|
||||
|
||||
declaration.mangleFunction(false, data, container)
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor, data: Boolean) = declaration.mangleFunction(true, data, declaration)
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.name.FqName
|
||||
|
||||
internal fun <T> Collection<T>.collect(builder: StringBuilder, params: MangleConstant, collect: StringBuilder.(T) -> Unit) {
|
||||
var first = true
|
||||
|
||||
builder.append(params.prefix)
|
||||
|
||||
for (e in this) {
|
||||
if (first) {
|
||||
first = false
|
||||
} else {
|
||||
builder.append(params.separator)
|
||||
}
|
||||
|
||||
builder.collect(e)
|
||||
}
|
||||
|
||||
builder.append(params.suffix)
|
||||
}
|
||||
|
||||
internal val publishedApiAnnotation = FqName("kotlin.PublishedApi")
|
||||
+55
-17
@@ -5,25 +5,63 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.KotlinManglerImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.isInlined
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinExportChecker
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinMangleComputer
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.classic.ClassicExportChecker
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.classic.ClassicKotlinManglerImpl
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.classic.ClassicMangleComputer
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.DescriptorBasedKotlinManglerImpl
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.DescriptorExportCheckerVisitor
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.DescriptorMangleComputer
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.ir.IrBasedKotlinManglerImpl
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.ir.IrExportCheckerVisitor
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.ir.IrMangleComputer
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
|
||||
abstract class AbstractJsMangler : KotlinManglerImpl() {
|
||||
override val IrType.isInlined: Boolean
|
||||
get() = this.isInlined()
|
||||
abstract class AbstractJsManglerIr : IrBasedKotlinManglerImpl() {
|
||||
|
||||
companion object {
|
||||
private val exportChecker = JsIrExportChecker()
|
||||
}
|
||||
|
||||
private class JsIrExportChecker : IrExportCheckerVisitor() {
|
||||
override fun IrDeclaration.isPlatformSpecificExported() = false
|
||||
}
|
||||
|
||||
private class JsIrManglerComputer(builder: StringBuilder) : IrMangleComputer(builder) {
|
||||
override fun copy(): IrMangleComputer = JsIrManglerComputer(builder)
|
||||
}
|
||||
|
||||
override fun getExportChecker(): KotlinExportChecker<IrDeclaration> = exportChecker
|
||||
|
||||
override fun getMangleComputer(prefix: String): KotlinMangleComputer<IrDeclaration> {
|
||||
return JsIrManglerComputer(StringBuilder(256))
|
||||
}
|
||||
}
|
||||
|
||||
object JsMangler : AbstractJsMangler()
|
||||
object JsManglerIr : AbstractJsManglerIr()
|
||||
|
||||
abstract class AbstractJsDescriptorMangler : DescriptorBasedKotlinManglerImpl() {
|
||||
|
||||
companion object {
|
||||
private val exportChecker = JsDescriptorExportChecker()
|
||||
}
|
||||
|
||||
private class JsDescriptorExportChecker : DescriptorExportCheckerVisitor() {
|
||||
override fun DeclarationDescriptor.isPlatformSpecificExported() = false
|
||||
}
|
||||
|
||||
private class JsDescriptorManglerComputer(builder: StringBuilder, prefix: String) : DescriptorMangleComputer(builder, prefix) {
|
||||
override fun copy(): DescriptorMangleComputer = JsDescriptorManglerComputer(builder, specialPrefix)
|
||||
}
|
||||
|
||||
override fun getExportChecker(): KotlinExportChecker<DeclarationDescriptor> = exportChecker
|
||||
|
||||
override fun getMangleComputer(prefix: String): KotlinMangleComputer<DeclarationDescriptor> {
|
||||
return JsDescriptorManglerComputer(StringBuilder(256), prefix)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* JsManglerForBE is a special verison of kotlin mangler used in case when IR is not completely correct from Type Parameter perspective.
|
||||
* I.e. usage of TypeParameter is not in TP's container. It's acceptable if only required to distinguish declaration somehow.
|
||||
*/
|
||||
object JsManglerForBE : AbstractJsMangler() {
|
||||
|
||||
override fun mangleTypeParameter(typeParameter: IrTypeParameter, typeParameterNamer: (IrTypeParameter) -> String): String =
|
||||
typeParameter.name.asString()
|
||||
}
|
||||
object JsManglerDesc : AbstractJsDescriptorMangler()
|
||||
|
||||
+68
-7
@@ -5,13 +5,74 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.jvm.serialization
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.KotlinManglerImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.isInlined
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinExportChecker
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinMangleComputer
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.classic.ClassicExportChecker
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.classic.ClassicKotlinManglerImpl
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.classic.ClassicMangleComputer
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.DescriptorBasedKotlinManglerImpl
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.DescriptorExportCheckerVisitor
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.DescriptorMangleComputer
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.ir.IrBasedKotlinManglerImpl
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.ir.IrExportCheckerVisitor
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.ir.IrMangleComputer
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.isJavaField
|
||||
|
||||
// Copied from JsMangler for now
|
||||
object JvmMangler : KotlinManglerImpl() {
|
||||
abstract class AbstractJvmManglerIr : IrBasedKotlinManglerImpl() {
|
||||
|
||||
override val IrType.isInlined: Boolean
|
||||
get() = this.isInlined()
|
||||
companion object {
|
||||
private val exportChecker = JvmIrExportChecker()
|
||||
}
|
||||
|
||||
private class JvmIrExportChecker : IrExportCheckerVisitor() {
|
||||
override fun IrDeclaration.isPlatformSpecificExported() = false
|
||||
}
|
||||
|
||||
private class JvmIrManglerComputer(builder: StringBuilder) : IrMangleComputer(builder) {
|
||||
override fun copy(): IrMangleComputer = JvmIrManglerComputer(builder)
|
||||
}
|
||||
|
||||
override fun getExportChecker(): KotlinExportChecker<IrDeclaration> = exportChecker
|
||||
|
||||
override fun getMangleComputer(prefix: String): KotlinMangleComputer<IrDeclaration> {
|
||||
return JvmIrManglerComputer(StringBuilder(256))
|
||||
}
|
||||
}
|
||||
|
||||
object JvmManglerIr : AbstractJvmManglerIr()
|
||||
|
||||
abstract class AbstractJvmDescriptorMangler(private val mainDetector: MainFunctionDetector?) : DescriptorBasedKotlinManglerImpl() {
|
||||
|
||||
companion object {
|
||||
private val exportChecker = JvmDescriptorExportChecker()
|
||||
}
|
||||
|
||||
private class JvmDescriptorExportChecker : DescriptorExportCheckerVisitor() {
|
||||
override fun DeclarationDescriptor.isPlatformSpecificExported() = false
|
||||
}
|
||||
|
||||
private class JvmDescriptorManglerComputer(builder: StringBuilder, prefix: String, private val mainDetector: MainFunctionDetector?) :
|
||||
DescriptorMangleComputer(builder, prefix) {
|
||||
override fun copy(): DescriptorMangleComputer = JvmDescriptorManglerComputer(builder, specialPrefix, mainDetector)
|
||||
|
||||
private fun isMainFunction(descriptor: FunctionDescriptor): Boolean = mainDetector?.isMain(descriptor) ?: false
|
||||
|
||||
override fun FunctionDescriptor.platformSpecificSuffix(): String? {
|
||||
return if (isMainFunction(this)) {
|
||||
return source.containingFile.name
|
||||
} else null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getExportChecker(): KotlinExportChecker<DeclarationDescriptor> = exportChecker
|
||||
|
||||
override fun getMangleComputer(prefix: String): KotlinMangleComputer<DeclarationDescriptor> {
|
||||
return JvmDescriptorManglerComputer(StringBuilder(256), prefix, mainDetector)
|
||||
}
|
||||
}
|
||||
|
||||
class JvmManglerDesc(mainDetector: MainFunctionDetector? = null) : AbstractJvmDescriptorMangler(mainDetector)
|
||||
Reference in New Issue
Block a user