JVM IR: move CollectionToArray creation to JvmSymbols

Also simplify it to use IR builder DSL
This commit is contained in:
Alexander Udalov
2019-05-16 17:21:37 +02:00
parent 15e0fd93bd
commit bd8c09bfb5
3 changed files with 45 additions and 112 deletions
@@ -274,7 +274,7 @@ class JvmSymbols(
val getOrCreateKotlinClasses: IrSimpleFunctionSymbol =
reflection.functions.single { it.owner.name.asString() == "getOrCreateKotlinClasses" }
val unsafeCoerceIntrinsic =
private val unsafeCoerceIntrinsic =
buildFun {
name = Name.special("<unsafe-coerce>")
origin = IrDeclarationOrigin.IR_BUILTINS_STUB
@@ -286,4 +286,25 @@ class JvmSymbols(
returnType = dst.defaultType
}
val unsafeCoerceIntrinsicSymbol = unsafeCoerceIntrinsic.symbol
private val collectionToArrayClass: IrClassSymbol = createClass(FqName("kotlin.jvm.internal.CollectionToArray")) { klass ->
klass.origin = JvmLoweredDeclarationOrigin.TO_ARRAY
val arrayType = irBuiltIns.arrayClass.typeWith(irBuiltIns.anyNType)
klass.addFunction("toArray", arrayType, isStatic = true).apply {
origin = JvmLoweredDeclarationOrigin.TO_ARRAY
addValueParameter("collection", irBuiltIns.collectionClass.owner.typeWith(), JvmLoweredDeclarationOrigin.TO_ARRAY)
}
klass.addFunction("toArray", arrayType, isStatic = true).apply {
origin = JvmLoweredDeclarationOrigin.TO_ARRAY
addValueParameter("collection", irBuiltIns.collectionClass.owner.typeWith(), JvmLoweredDeclarationOrigin.TO_ARRAY)
addValueParameter("array", arrayType, JvmLoweredDeclarationOrigin.TO_ARRAY)
}
}.symbol
val nonGenericToArray: IrSimpleFunctionSymbol =
collectionToArrayClass.functions.single { it.owner.name.asString() == "toArray" && it.owner.valueParameters.size == 1 }
val genericToArray: IrSimpleFunctionSymbol =
collectionToArrayClass.functions.single { it.owner.name.asString() == "toArray" && it.owner.valueParameters.size == 2 }
}
@@ -6,25 +6,34 @@
package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.descriptors.*
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedTypeParameterDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.irBlockBody
import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.irReturn
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.*
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.symbols.impl.*
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.isClass
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.DFS
@@ -36,11 +45,11 @@ internal val toArrayPhase = makeIrFilePhase(
)
private class ToArrayLowering(private val context: JvmBackendContext) : ClassLoweringPass {
override fun lower(irClass: IrClass) {
if (irClass.isJvmInterface || !irClass.isDirectCollectionSubClass()) return
val irBuiltIns = context.irBuiltIns
val symbols = context.ir.symbols
val toArrayName = Name.identifier("toArray")
val genericToArray = irClass.declarations.find { it.isGenericToArray() }
@@ -116,7 +125,7 @@ private class ToArrayLowering(private val context: JvmBackendContext) : ClassLow
irFunction.body = context.createIrBuilder(irFunction.symbol).irBlockBody {
+irReturn(
irCall(genericToArrayUtilFunction.symbol, genericToArrayUtilFunction.returnType).apply {
irCall(symbols.genericToArray, symbols.genericToArray.owner.returnType).apply {
putValueArgument(
0,
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.dispatchReceiverParameter!!.symbol)
@@ -165,7 +174,7 @@ private class ToArrayLowering(private val context: JvmBackendContext) : ClassLow
irFunction.body = context.createIrBuilder(irFunction.symbol).irBlockBody {
+irReturn(
irCall(nonGenericToArrayUtilFunction.symbol, nonGenericToArrayUtilFunction.returnType).apply {
irCall(symbols.nonGenericToArray, symbols.nonGenericToArray.owner.returnType).apply {
putValueArgument(
0,
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.dispatchReceiverParameter!!.symbol)
@@ -179,105 +188,6 @@ private class ToArrayLowering(private val context: JvmBackendContext) : ClassLow
}
}
private val kotlinJvmInternalPackageFragment: IrPackageFragment by lazy {
IrExternalPackageFragmentImpl(
IrExternalPackageFragmentSymbolImpl(
EmptyPackageFragmentDescriptor(
context.ir.irModule.descriptor,
FqName("kotlin.jvm.internal")
)
)
)
}
private val collectionUtilClass: IrClass by lazy {
val descriptor = WrappedClassDescriptor()
IrClassImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
JvmLoweredDeclarationOrigin.TO_ARRAY,
IrClassSymbolImpl(descriptor),
Name.identifier("CollectionToArray"),
ClassKind.CLASS,
Visibilities.PUBLIC,
Modality.FINAL,
isCompanion = false,
isInner = false,
isInline = false,
isData = false,
isExternal = false
).apply {
descriptor.bind(this)
parent = kotlinJvmInternalPackageFragment
superTypes.add(context.irBuiltIns.anyType)
kotlinJvmInternalPackageFragment.declarations.add(this)
}
}
private fun createToArrayUtilFunction(isGeneric: Boolean): IrSimpleFunction {
val irBuiltIns = context.irBuiltIns
val arrayType = irBuiltIns.arrayClass.typeWith(irBuiltIns.anyNType)
val utilFunctionDescriptor = WrappedSimpleFunctionDescriptor()
return IrFunctionImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
JvmLoweredDeclarationOrigin.TO_ARRAY,
IrSimpleFunctionSymbolImpl(utilFunctionDescriptor),
Name.identifier("toArray"),
Visibilities.PUBLIC,
Modality.FINAL,
returnType = arrayType,
isInline = false,
isExternal = false,
isTailrec = false,
isSuspend = false
).also { irFunction ->
utilFunctionDescriptor.bind(irFunction)
irFunction.parent = collectionUtilClass
val collectionParameterDescriptor = WrappedValueParameterDescriptor()
irFunction.valueParameters.add(
IrValueParameterImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
JvmLoweredDeclarationOrigin.TO_ARRAY,
IrValueParameterSymbolImpl(collectionParameterDescriptor),
Name.identifier("collection"),
0,
irBuiltIns.collectionClass.owner.defaultType,
varargElementType = null,
isCrossinline = false,
isNoinline = false
).apply {
collectionParameterDescriptor.bind(this)
parent = irFunction
}
)
if (isGeneric) {
val arrayParameterDescriptor = WrappedValueParameterDescriptor()
irFunction.valueParameters.add(
IrValueParameterImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
JvmLoweredDeclarationOrigin.TO_ARRAY,
IrValueParameterSymbolImpl(arrayParameterDescriptor),
Name.identifier("array"),
1,
arrayType,
varargElementType = null,
isCrossinline = false,
isNoinline = false
).apply {
arrayParameterDescriptor.bind(this)
parent = irFunction
}
)
}
collectionUtilClass.declarations.add(irFunction)
}
}
private val nonGenericToArrayUtilFunction: IrSimpleFunction by lazy { createToArrayUtilFunction(false) }
private val genericToArrayUtilFunction: IrSimpleFunction by lazy { createToArrayUtilFunction(true) }
private fun IrDeclaration.isGenericToArray(): Boolean {
if (this !is IrSimpleFunction) return false
val signature = context.state.typeMapper.mapAsmMethod(descriptor)
@@ -287,7 +197,7 @@ private class ToArrayLowering(private val context: JvmBackendContext) : ClassLow
private fun IrDeclaration.isNonGenericToArray(): Boolean {
if (this !is IrSimpleFunction) return false
if (this.name.asString() != "toArray") return false
if (!typeParameters.isEmpty() || !valueParameters.isEmpty()) return false
if (typeParameters.isNotEmpty() || valueParameters.isNotEmpty()) return false
if (!returnType.isArray()) return false
return true
@@ -115,3 +115,5 @@ fun IrClassifierSymbol.typeWith(arguments: List<IrType>): IrSimpleType =
)
fun IrClass.typeWith(arguments: List<IrType>) = this.symbol.typeWith(arguments)
fun IrClass.typeWith(vararg arguments: IrType) = this.symbol.typeWith(arguments.toList())