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_OBJECT_INSTANCE : IrDeclarationOriginImpl("FIELD_FOR_OBJECT_INSTANCE")
|
||||||
object FIELD_FOR_OUTER_THIS : IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS")
|
object FIELD_FOR_OUTER_THIS : IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS")
|
||||||
object SYNTHETIC_ACCESSOR : IrDeclarationOriginImpl("SYNTHETIC_ACCESSOR")
|
object SYNTHETIC_ACCESSOR : IrDeclarationOriginImpl("SYNTHETIC_ACCESSOR")
|
||||||
|
object TO_ARRAY : IrDeclarationOriginImpl("TO_ARRAY")
|
||||||
}
|
}
|
||||||
|
|
||||||
interface JvmLoweredStatementOrigin : IrStatementOrigin {
|
interface JvmLoweredStatementOrigin : IrStatementOrigin {
|
||||||
object DEFAULT_IMPLS_DELEGATION : IrStatementOriginImpl("DEFAULT_IMPL_DELEGATION")
|
object DEFAULT_IMPLS_DELEGATION : IrStatementOriginImpl("DEFAULT_IMPL_DELEGATION")
|
||||||
object BRIDGE_DELEGATION : IrStatementOriginImpl("BRIDGE_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)
|
BridgeLowering(context).runOnFilePostfix(irFile)
|
||||||
|
|
||||||
TailrecLowering(context).runOnFilePostfix(irFile)
|
TailrecLowering(context).runOnFilePostfix(irFile)
|
||||||
|
ToArrayLowering(context).runOnFilePostfix(irFile)
|
||||||
|
|
||||||
irFile.acceptVoid(PatchDeclarationParentsVisitor())
|
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