[IR] Rewrite generator for interpreter map
1. Reuse `DisabledIdSignatureDescriptor` to create `IrBuiltIns` 2. Provide FQ names for types to ensure method find correctness
This commit is contained in:
+3
-3
@@ -155,7 +155,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
|
||||
}
|
||||
|
||||
val receiverType = irFunction.dispatchReceiverParameter?.type ?: irFunction.extensionReceiverParameter?.type
|
||||
val argsType = (listOfNotNull(receiverType) + irFunction.valueParameters.map { it.type }).map { it.getOnlyName() }
|
||||
val argsType = (listOfNotNull(receiverType) + irFunction.valueParameters.map { it.type }).map { it.fqNameWithNullability() }
|
||||
val argsValues = args.wrap(this, irFunction)
|
||||
|
||||
withExceptionHandler(environment) {
|
||||
@@ -170,8 +170,8 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
|
||||
if (environment.configuration.platform.isJs()) {
|
||||
if (signature.name == "toString") return signature.args[0].value.specialToStringForJs()
|
||||
if (signature.name == "toFloat") signature.name = "toDouble"
|
||||
signature.args.filter { it.type == "Float" }.forEach {
|
||||
it.type = "Double"
|
||||
signature.args.filter { it.type == "kotlin.Float" }.forEach {
|
||||
it.type = "kotlin.Double"
|
||||
it.value = it.value.toString().toDouble()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,6 +204,14 @@ internal fun IrFunction.getArgsForMethodInvocation(
|
||||
return argsValues
|
||||
}
|
||||
|
||||
internal fun IrType.fqNameWithNullability(): String {
|
||||
val fqName = classFqName?.toString()
|
||||
?: (this.classifierOrNull?.owner as? IrDeclarationWithName)?.name?.asString()
|
||||
?: render()
|
||||
val nullability = if (this is IrSimpleType && this.nullability == SimpleTypeNullability.MARKED_NULLABLE) "?" else ""
|
||||
return fqName + nullability
|
||||
}
|
||||
|
||||
internal fun IrType.getOnlyName(): String {
|
||||
if (this !is IrSimpleType) return this.render()
|
||||
return (this.classifierOrFail.owner as IrDeclarationWithName).name.asString() + when (nullability) {
|
||||
|
||||
+539
-563
File diff suppressed because it is too large
Load Diff
@@ -45,6 +45,7 @@ dependencies {
|
||||
wasmApi(kotlinStdlib())
|
||||
interpreterApi(project(":compiler:ir.tree"))
|
||||
interpreterApi(project(":compiler:ir.psi2ir"))
|
||||
interpreterApi(project(":compiler:ir.serialization.jvm"))
|
||||
protobufApi(kotlinStdlib())
|
||||
protobufCompareApi(projectTests(":kotlin-build-common"))
|
||||
nativeInteropRuntimeApi(kotlinStdlib())
|
||||
|
||||
@@ -5,11 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.generators.interpreter
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.serialization.DisabledIdSignatureDescriptor
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.config.ApiVersion
|
||||
import org.jetbrains.kotlin.config.LanguageVersion
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
@@ -19,10 +18,7 @@ import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.ir.util.IdSignatureComposer
|
||||
import org.jetbrains.kotlin.ir.util.KotlinMangler
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi2ir.descriptors.IrBuiltInsOverDescriptors
|
||||
import org.jetbrains.kotlin.psi2ir.generators.TypeTranslatorImpl
|
||||
@@ -39,6 +35,30 @@ fun main() {
|
||||
fun generateMap(): String {
|
||||
val sb = StringBuilder()
|
||||
val p = Printer(sb)
|
||||
printPreamble(p)
|
||||
|
||||
val irBuiltIns = getIrBuiltIns()
|
||||
|
||||
val unaryOperations = getOperationMap(1).apply {
|
||||
this += Operation(BuiltInOperatorNames.CHECK_NOT_NULL, listOf("T0?"), customExpression = "a!!")
|
||||
this += Operation("toString", listOf("Any?"), customExpression = "a?.toString() ?: \"null\"")
|
||||
this += Operation("code", listOf("Char"), customExpression = "(a as Char).code")
|
||||
// TODO next operation can be dropped after serialization introduction
|
||||
this += Operation("toString", listOf("Unit"), customExpression = "Unit.toString()")
|
||||
}
|
||||
|
||||
val binaryOperations = getOperationMap(2) + getBinaryIrOperationMap(irBuiltIns) + getExtensionOperationMap()
|
||||
|
||||
val ternaryOperations = getOperationMap(3)
|
||||
|
||||
generateInterpretUnaryFunction(p, unaryOperations)
|
||||
generateInterpretBinaryFunction(p, binaryOperations)
|
||||
generateInterpretTernaryFunction(p, ternaryOperations)
|
||||
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
private fun printPreamble(p: Printer) {
|
||||
p.println(File("license/COPYRIGHT_HEADER.txt").readText())
|
||||
p.println()
|
||||
p.println("@file:Suppress(\"DEPRECATION\", \"DEPRECATION_ERROR\", \"UNCHECKED_CAST\")")
|
||||
@@ -50,26 +70,6 @@ fun generateMap(): String {
|
||||
p.println()
|
||||
p.println("/** This file is generated by `./gradlew generateInterpreterMap`. DO NOT MODIFY MANUALLY */")
|
||||
p.println()
|
||||
|
||||
val irBuiltIns = getIrBuiltIns()
|
||||
|
||||
generateInterpretUnaryFunction(p, getOperationMap(1).apply {
|
||||
val irNullCheck = irBuiltIns.checkNotNullSymbol.owner
|
||||
this += Operation(irNullCheck.name.asString(), listOf("T0?"), customExpression = "a!!")
|
||||
this += Operation("toString", listOf("Any?"), customExpression = "a?.toString() ?: \"null\"")
|
||||
this += Operation("code", listOf("Char"), customExpression = "(a as Char).code")
|
||||
// TODO next operation can be dropped after serialization introduction
|
||||
this += Operation("toString", listOf("Unit"), customExpression = "Unit.toString()")
|
||||
})
|
||||
|
||||
generateInterpretBinaryFunction(
|
||||
p,
|
||||
getOperationMap(2) + getBinaryIrOperationMap(irBuiltIns) + getExtensionOperationMap() + getAdditionalEqualsOperationMap()
|
||||
)
|
||||
|
||||
generateInterpretTernaryFunction(p, getOperationMap(3))
|
||||
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
private fun generateInterpretUnaryFunction(p: Printer, unaryOperations: List<Operation>) {
|
||||
@@ -138,9 +138,8 @@ private fun generateInterpretTernaryFunction(p: Printer, ternaryOperations: List
|
||||
for ((name, operations) in ternaryOperations.groupBy(Operation::name)) {
|
||||
p.println("\"$name\" -> when (typeA) {")
|
||||
p.pushIndent()
|
||||
for (operation in operations) {
|
||||
val (typeA, typeB, typeC) = operation.parameterTypes
|
||||
p.println("\"$typeA\" -> if (typeB == \"$typeB\" && typeC == \"$typeC\") return ${operation.expressionString}")
|
||||
for (op in operations) {
|
||||
p.println("\"${op.typeA}\" -> if (typeB == \"${op.typeB}\" && typeC == \"${op.typeC}\") return ${op.expressionString}")
|
||||
}
|
||||
p.popIndent()
|
||||
p.println("}")
|
||||
@@ -163,18 +162,22 @@ private fun castValue(name: String, type: String): String = when (type) {
|
||||
private fun castValueParenthesized(name: String, type: String): String =
|
||||
if (type == "Any?") name else "(${castValue(name, type)})"
|
||||
|
||||
private fun String.addKotlinPackage(): String =
|
||||
if (this == "T" || this == "T0?") this else "kotlin.$this"
|
||||
|
||||
private data class Operation(
|
||||
val name: String,
|
||||
val parameterTypes: List<String>,
|
||||
private val parameterTypes: List<String>,
|
||||
val isFunction: Boolean = true,
|
||||
val customExpression: String? = null,
|
||||
) {
|
||||
val typeA: String get() = parameterTypes[0]
|
||||
val typeB: String get() = parameterTypes[1]
|
||||
val typeA: String get() = parameterTypes[0].addKotlinPackage()
|
||||
val typeB: String get() = parameterTypes[1].addKotlinPackage()
|
||||
val typeC: String get() = parameterTypes[2].addKotlinPackage()
|
||||
|
||||
val expressionString: String
|
||||
get() {
|
||||
val receiver = castValueParenthesized("a", typeA)
|
||||
val receiver = castValueParenthesized("a", parameterTypes[0])
|
||||
return when {
|
||||
name == BuiltInOperatorNames.EQEQEQ && parameterTypes.all { it == "Any?" } ->
|
||||
"if (a is Proxy && b is Proxy) a.state === b.state else a === b"
|
||||
@@ -217,13 +220,9 @@ private fun getOperationMap(argumentsCount: Int): MutableList<Operation> {
|
||||
.filter { it.name !in excludedBinaryOperations }
|
||||
|
||||
for (function in compileTimeFunctions) {
|
||||
operationMap.add(
|
||||
Operation(
|
||||
function.name.asString(),
|
||||
listOf(classDescriptor.defaultType.constructor.toString()) + function.valueParameters.map { it.type.toString() },
|
||||
function is FunctionDescriptor
|
||||
)
|
||||
)
|
||||
val parameterTypes = listOf(classDescriptor.defaultType.constructor.toString()) +
|
||||
function.valueParameters.map { it.type.toString() }
|
||||
operationMap.add(Operation(function.name.asString(), parameterTypes, function is FunctionDescriptor))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,16 +277,6 @@ private fun getExtensionOperationMap(): List<Operation> {
|
||||
return operationMap
|
||||
}
|
||||
|
||||
// We need this additional list to properly interpret functions like `Boolean.equals(Boolean) in Native`
|
||||
// Probably can be dropped after KT-57344 fix
|
||||
private fun getAdditionalEqualsOperationMap(): List<Operation> {
|
||||
val builtIns = DefaultBuiltIns.Instance
|
||||
return PrimitiveType.values().map { builtIns.getBuiltInClassByFqName(it.typeFqName) }.map {
|
||||
val type = it.defaultType.constructor.toString()
|
||||
Operation("equals", listOf(type, type), isFunction = true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getIrMethodSymbolByName(methodName: String): String {
|
||||
return when (methodName) {
|
||||
BuiltInOperatorNames.LESS -> "<"
|
||||
@@ -305,26 +294,8 @@ private fun getIrMethodSymbolByName(methodName: String): String {
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
private fun getIrBuiltIns(): IrBuiltIns {
|
||||
val languageSettings = LanguageVersionSettingsImpl(LanguageVersion.KOTLIN_1_3, ApiVersion.KOTLIN_1_3)
|
||||
|
||||
val moduleDescriptor = ModuleDescriptorImpl(Name.special("<test-module>"), LockBasedStorageManager(""), DefaultBuiltIns.Instance)
|
||||
val signaturer = object : IdSignatureComposer {
|
||||
override fun composeSignature(descriptor: DeclarationDescriptor): IdSignature? = null
|
||||
|
||||
override fun composeEnumEntrySignature(descriptor: ClassDescriptor): IdSignature? = null
|
||||
|
||||
override fun composeAnonInitSignature(descriptor: ClassDescriptor): IdSignature? = null
|
||||
|
||||
override fun composeFieldSignature(descriptor: PropertyDescriptor): IdSignature? = null
|
||||
|
||||
override fun withFileSignature(fileSignature: IdSignature.FileSignature, body: () -> Unit) {
|
||||
body()
|
||||
}
|
||||
|
||||
override val mangler: KotlinMangler.DescriptorMangler
|
||||
get() = throw UnsupportedOperationException("Mangler is unavailable")
|
||||
}
|
||||
val symbolTable = SymbolTable(signaturer, IrFactoryImpl)
|
||||
val typeTranslator = TypeTranslatorImpl(symbolTable, languageSettings, moduleDescriptor)
|
||||
val symbolTable = SymbolTable(DisabledIdSignatureDescriptor, IrFactoryImpl)
|
||||
val typeTranslator = TypeTranslatorImpl(symbolTable, LanguageVersionSettingsImpl.DEFAULT, moduleDescriptor)
|
||||
return IrBuiltInsOverDescriptors(moduleDescriptor.builtIns, typeTranslator, symbolTable)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user