Implement toArray lowering
This commit is contained in:
@@ -29,9 +29,11 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
|
||||
object FIELD_FOR_OBJECT_INSTANCE : IrDeclarationOriginImpl("FIELD_FOR_OBJECT_INSTANCE")
|
||||
object FIELD_FOR_OUTER_THIS : IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS")
|
||||
object SYNTHETIC_ACCESSOR : IrDeclarationOriginImpl("SYNTHETIC_ACCESSOR")
|
||||
object TO_ARRAY : IrDeclarationOriginImpl("TO_ARRAY")
|
||||
}
|
||||
|
||||
interface JvmLoweredStatementOrigin : IrStatementOrigin {
|
||||
object DEFAULT_IMPLS_DELEGATION : IrStatementOriginImpl("DEFAULT_IMPL_DELEGATION")
|
||||
object BRIDGE_DELEGATION : IrStatementOriginImpl("BRIDGE_DELEGATION")
|
||||
object TO_ARRAY : IrDeclarationOriginImpl("TO_ARRAY")
|
||||
}
|
||||
@@ -66,6 +66,7 @@ class JvmLower(val context: JvmBackendContext) {
|
||||
BridgeLowering(context).runOnFilePostfix(irFile)
|
||||
|
||||
TailrecLowering(context).runOnFilePostfix(irFile)
|
||||
ToArrayLowering(context).runOnFilePostfix(irFile)
|
||||
|
||||
irFile.acceptVoid(PatchDeclarationParentsVisitor())
|
||||
}
|
||||
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. 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.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.KnownClassDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.KnownPackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
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.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.codegen.isGenericToArray
|
||||
import org.jetbrains.kotlin.codegen.isNonGenericToArray
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
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.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isSubclass
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperclassesWithoutAny
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
class ToArrayLowering(private val context: JvmBackendContext) : ClassLoweringPass {
|
||||
|
||||
override fun lower(irClass: IrClass) {
|
||||
if (irClass.isJvmInterface) return
|
||||
|
||||
val descriptor = irClass.descriptor
|
||||
|
||||
val builtIns = descriptor.builtIns
|
||||
if (!isSubclass(descriptor, builtIns.collection)) return
|
||||
|
||||
if (descriptor.getAllSuperclassesWithoutAny().any { classDescriptor ->
|
||||
classDescriptor !is JavaClassDescriptor && isSubclass(
|
||||
classDescriptor,
|
||||
builtIns.collection
|
||||
)
|
||||
}) {
|
||||
return
|
||||
}
|
||||
|
||||
val toArrayName = Name.identifier("toArray")
|
||||
val functions = descriptor.defaultType.memberScope.getContributedFunctions(
|
||||
toArrayName, NoLookupLocation.FROM_BACKEND
|
||||
)
|
||||
|
||||
val genericToArray = functions.firstOrNull { it.isGenericToArray() }
|
||||
val nonGenericToArray = functions.firstOrNull { it.isNonGenericToArray() }
|
||||
val arrayType = builtIns.getArrayType(Variance.INVARIANT, builtIns.anyType)
|
||||
if (genericToArray == null) {
|
||||
val toArrayDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
irClass.descriptor, org.jetbrains.kotlin.descriptors.annotations.Annotations.EMPTY,
|
||||
toArrayName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE
|
||||
)
|
||||
toArrayDescriptor.initialize(
|
||||
null, irClass.descriptor.thisAsReceiverParameter, emptyList(), emptyList(),
|
||||
arrayType, Modality.OPEN, Visibilities.PUBLIC
|
||||
)
|
||||
|
||||
val toArrayUtilDescriptor = createToArrayUtilDescriptor(builtIns, false)
|
||||
|
||||
val irFunction = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.TO_ARRAY, toArrayDescriptor)
|
||||
irFunction.createParameterDeclarations()
|
||||
|
||||
irFunction.body = context.createIrBuilder(irFunction.symbol).irBlockBody {
|
||||
+irReturn(
|
||||
irCall(IrSimpleFunctionSymbolImpl(toArrayUtilDescriptor)).apply {
|
||||
putValueArgument(
|
||||
0,
|
||||
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.dispatchReceiverParameter!!.symbol)
|
||||
)
|
||||
})
|
||||
}
|
||||
irClass.declarations.add(irFunction)
|
||||
} else {
|
||||
//TODO patch visibility
|
||||
}
|
||||
|
||||
if (nonGenericToArray == null) {
|
||||
val toArrayDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
irClass.descriptor, org.jetbrains.kotlin.descriptors.annotations.Annotations.EMPTY,
|
||||
toArrayName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE
|
||||
)
|
||||
val createWithDefaultBound = TypeParameterDescriptorImpl.createWithDefaultBound(
|
||||
toArrayDescriptor,
|
||||
Annotations.EMPTY,
|
||||
false,
|
||||
Variance.INVARIANT,
|
||||
Name.identifier("T"),
|
||||
0
|
||||
)
|
||||
|
||||
val genericArrayType = builtIns.getArrayType(Variance.INVARIANT, createWithDefaultBound.defaultType)
|
||||
toArrayDescriptor.initialize(
|
||||
null,
|
||||
irClass.descriptor.thisAsReceiverParameter,
|
||||
listOf(createWithDefaultBound),
|
||||
listOf(
|
||||
ValueParameterDescriptorImpl(
|
||||
toArrayDescriptor,
|
||||
null,
|
||||
0,
|
||||
Annotations.EMPTY,
|
||||
Name.identifier("array"),
|
||||
genericArrayType,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
SourceElement.NO_SOURCE
|
||||
)
|
||||
),
|
||||
genericArrayType,
|
||||
Modality.OPEN,
|
||||
Visibilities.PUBLIC
|
||||
)
|
||||
|
||||
val toArrayUtilDescriptor = createToArrayUtilDescriptor(builtIns, true)
|
||||
|
||||
val irFunction = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.TO_ARRAY, toArrayDescriptor)
|
||||
irFunction.createParameterDeclarations()
|
||||
|
||||
irFunction.body = context.createIrBuilder(irFunction.symbol).irBlockBody {
|
||||
+irReturn(
|
||||
irCall(IrSimpleFunctionSymbolImpl(toArrayUtilDescriptor)).apply {
|
||||
putValueArgument(
|
||||
0,
|
||||
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.dispatchReceiverParameter!!.symbol)
|
||||
)
|
||||
putValueArgument(1, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.valueParameters[0].symbol))
|
||||
})
|
||||
}
|
||||
|
||||
irClass.declarations.add(irFunction)
|
||||
} else {
|
||||
//TODO patch visibility
|
||||
}
|
||||
}
|
||||
|
||||
private fun createToArrayUtilDescriptor(
|
||||
builtIns: KotlinBuiltIns,
|
||||
isGeneric: Boolean
|
||||
): SimpleFunctionDescriptorImpl {
|
||||
val kotlinJvmInternalPackage = KnownPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.jvm.internal"))
|
||||
|
||||
val toArrayUtil = SimpleFunctionDescriptorImpl.create(
|
||||
KnownClassDescriptor.createClass(Name.identifier("CollectionToArray"), kotlinJvmInternalPackage, listOf(builtIns.anyType)),
|
||||
Annotations.EMPTY,
|
||||
Name.identifier("toArray"),
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
SourceElement.NO_SOURCE
|
||||
)
|
||||
toArrayUtil.initialize(
|
||||
null,
|
||||
null,
|
||||
emptyList(),
|
||||
listOfNotNull(
|
||||
ValueParameterDescriptorImpl(
|
||||
toArrayUtil,
|
||||
null,
|
||||
0,
|
||||
Annotations.EMPTY,
|
||||
Name.identifier("collection"),
|
||||
builtIns.collection.defaultType,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
SourceElement.NO_SOURCE
|
||||
),
|
||||
if (isGeneric) ValueParameterDescriptorImpl(
|
||||
toArrayUtil,
|
||||
null,
|
||||
1,
|
||||
Annotations.EMPTY,
|
||||
Name.identifier("array"),
|
||||
builtIns.getArrayType(Variance.INVARIANT, builtIns.anyType),
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
SourceElement.NO_SOURCE
|
||||
) else null
|
||||
),
|
||||
builtIns.array.defaultType,
|
||||
Modality.OPEN,
|
||||
Visibilities.PUBLIC
|
||||
)
|
||||
return toArrayUtil
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user