1) Move IrClassReference and IrGetClass processing from PreInlineLowering to PostInlineLowering
2) Move immutableBinaryBlobOf processing from PreInlineLowering to PostInlineLowering 3) Support IrClassReference and IrGetClass elements in DeepCopyIrTreeWithDescriptors
This commit is contained in:
committed by
KonstantinAnisimov
parent
4a0be88d47
commit
783a18fad2
+4
@@ -57,6 +57,10 @@ internal class KonanLower(val context: Context) {
|
|||||||
FunctionInlining(context).inline(irModule)
|
FunctionInlining(context).inline(irModule)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
phaser.phase(KonanPhase.LOWER_AFTER_INLINE) {
|
||||||
|
irModule.files.forEach(PostInlineLowering(context)::lower)
|
||||||
|
}
|
||||||
|
|
||||||
phaser.phase(KonanPhase.LOWER_INTEROP_PART1) {
|
phaser.phase(KonanPhase.LOWER_INTEROP_PART1) {
|
||||||
irModule.files.forEach(InteropLoweringPart1(context)::lower)
|
irModule.files.forEach(InteropLoweringPart1(context)::lower)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -32,6 +32,7 @@ enum class KonanPhase(val description: String,
|
|||||||
/* ... ... */ LOWER_BEFORE_INLINE("Special operations processing before inlining"),
|
/* ... ... */ LOWER_BEFORE_INLINE("Special operations processing before inlining"),
|
||||||
/* ... ... */ LOWER_INLINE_CONSTRUCTORS("Inline constructors transformation", LOWER_BEFORE_INLINE),
|
/* ... ... */ LOWER_INLINE_CONSTRUCTORS("Inline constructors transformation", LOWER_BEFORE_INLINE),
|
||||||
/* ... ... */ LOWER_INLINE("Functions inlining", LOWER_INLINE_CONSTRUCTORS, LOWER_BEFORE_INLINE),
|
/* ... ... */ LOWER_INLINE("Functions inlining", LOWER_INLINE_CONSTRUCTORS, LOWER_BEFORE_INLINE),
|
||||||
|
/* ... ... */ LOWER_AFTER_INLINE("Special operations processing after inlining"),
|
||||||
/* ... ... ... */ DESERIALIZER("Deserialize inline bodies"),
|
/* ... ... ... */ DESERIALIZER("Deserialize inline bodies"),
|
||||||
/* ... ... */ LOWER_INTEROP_PART1("Interop lowering, part 1", LOWER_INLINE),
|
/* ... ... */ LOWER_INTEROP_PART1("Interop lowering, part 1", LOWER_INLINE),
|
||||||
/* ... ... */ LOWER_FOR_LOOPS("For loops lowering"),
|
/* ... ... */ LOWER_FOR_LOOPS("For loops lowering"),
|
||||||
|
|||||||
+653
@@ -0,0 +1,653 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.konan.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
|
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.util.DeepCopyIrTree
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
|
|
||||||
|
class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescriptor,
|
||||||
|
context: CommonBackendContext) {
|
||||||
|
|
||||||
|
private val descriptorSubstituteMap: MutableMap<DeclarationDescriptor, DeclarationDescriptor> = mutableMapOf()
|
||||||
|
private var typeSubstitutor: TypeSubstitutor? = null
|
||||||
|
private var nameIndex = 0
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
fun copy(irElement: IrElement, typeSubstitutor: TypeSubstitutor?): IrElement {
|
||||||
|
this.typeSubstitutor = typeSubstitutor
|
||||||
|
irElement.acceptChildrenVoid(DescriptorCollector())
|
||||||
|
return irElement.accept(InlineCopyIr(), null)
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
inner class DescriptorCollector: IrElementVisitorVoid {
|
||||||
|
|
||||||
|
override fun visitElement(element: IrElement) {
|
||||||
|
element.acceptChildren(this, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun visitClass(declaration: IrClass) {
|
||||||
|
|
||||||
|
val oldDescriptor = declaration.descriptor
|
||||||
|
val newDescriptor = copyClassDescriptor(oldDescriptor)
|
||||||
|
descriptorSubstituteMap[oldDescriptor] = newDescriptor
|
||||||
|
descriptorSubstituteMap[oldDescriptor.thisAsReceiverParameter] = newDescriptor.thisAsReceiverParameter
|
||||||
|
|
||||||
|
super.visitClass(declaration)
|
||||||
|
|
||||||
|
val constructors = oldDescriptor.constructors.map { oldConstructorDescriptor ->
|
||||||
|
descriptorSubstituteMap[oldConstructorDescriptor] as ClassConstructorDescriptor
|
||||||
|
}.toSet()
|
||||||
|
|
||||||
|
val oldPrimaryConstructor = oldDescriptor.unsubstitutedPrimaryConstructor
|
||||||
|
val primaryConstructor = oldPrimaryConstructor?.let { descriptorSubstituteMap[it] as ClassConstructorDescriptor }
|
||||||
|
|
||||||
|
val contributedDescriptors = oldDescriptor.unsubstitutedMemberScope
|
||||||
|
.getContributedDescriptors()
|
||||||
|
.map {
|
||||||
|
descriptorSubstituteMap[it]!!
|
||||||
|
}
|
||||||
|
newDescriptor.initialize(
|
||||||
|
SimpleMemberScope(contributedDescriptors),
|
||||||
|
constructors,
|
||||||
|
primaryConstructor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun visitProperty(declaration: IrProperty) {
|
||||||
|
|
||||||
|
copyPropertyOrField(declaration.descriptor)
|
||||||
|
super.visitProperty(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun visitField(declaration: IrField) {
|
||||||
|
|
||||||
|
val oldDescriptor = declaration.descriptor
|
||||||
|
if (descriptorSubstituteMap[oldDescriptor] == null) {
|
||||||
|
copyPropertyOrField(oldDescriptor) // A field without a property or a field of a delegated property.
|
||||||
|
}
|
||||||
|
super.visitField(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun visitFunction(declaration: IrFunction) {
|
||||||
|
|
||||||
|
val oldDescriptor = declaration.descriptor
|
||||||
|
if (oldDescriptor !is PropertyAccessorDescriptor) { // Property accessors are copied along with their property.
|
||||||
|
val newDescriptor = copyFunctionDescriptor(oldDescriptor)
|
||||||
|
descriptorSubstituteMap[oldDescriptor] = newDescriptor
|
||||||
|
oldDescriptor.extensionReceiverParameter?.let{
|
||||||
|
descriptorSubstituteMap[it] = newDescriptor.extensionReceiverParameter!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.visitFunction(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun visitVariable(declaration: IrVariable) {
|
||||||
|
|
||||||
|
val oldDescriptor = declaration.descriptor
|
||||||
|
val oldContainingDeclaration = oldDescriptor.containingDeclaration
|
||||||
|
val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration)
|
||||||
|
val newDescriptor = IrTemporaryVariableDescriptorImpl(
|
||||||
|
containingDeclaration = newContainingDeclaration,
|
||||||
|
name = generateCopyName(oldDescriptor.name),
|
||||||
|
outType = substituteType(oldDescriptor.type)!!,
|
||||||
|
isMutable = oldDescriptor.isVar)
|
||||||
|
descriptorSubstituteMap[oldDescriptor] = newDescriptor
|
||||||
|
|
||||||
|
super.visitVariable(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun visitCatch(aCatch: IrCatch) {
|
||||||
|
val oldDescriptor = aCatch.parameter
|
||||||
|
val oldContainingDeclaration = oldDescriptor.containingDeclaration
|
||||||
|
val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration)
|
||||||
|
val newDescriptor = IrTemporaryVariableDescriptorImpl(
|
||||||
|
containingDeclaration = newContainingDeclaration,
|
||||||
|
name = generateCopyName(oldDescriptor.name),
|
||||||
|
outType = substituteType(oldDescriptor.type)!!,
|
||||||
|
isMutable = oldDescriptor.isVar)
|
||||||
|
descriptorSubstituteMap[oldDescriptor] = newDescriptor
|
||||||
|
|
||||||
|
super.visitCatch(aCatch)
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- Copy descriptors ------------------------------------------------//
|
||||||
|
|
||||||
|
private fun generateCopyName(name: Name): Name {
|
||||||
|
|
||||||
|
val declarationName = name.toString() // Name of declaration
|
||||||
|
val indexStr = (nameIndex++).toString() // Unique for inline target index
|
||||||
|
return Name.identifier(declarationName + "_" + indexStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
private fun copyFunctionDescriptor(oldDescriptor: CallableDescriptor): CallableDescriptor {
|
||||||
|
|
||||||
|
return when (oldDescriptor) {
|
||||||
|
is ConstructorDescriptor -> copyConstructorDescriptor(oldDescriptor)
|
||||||
|
is SimpleFunctionDescriptor -> copySimpleFunctionDescriptor(oldDescriptor)
|
||||||
|
else -> TODO("Unsupported FunctionDescriptor subtype: $oldDescriptor")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
private fun copySimpleFunctionDescriptor(oldDescriptor: SimpleFunctionDescriptor) : FunctionDescriptor {
|
||||||
|
|
||||||
|
val oldContainingDeclaration = oldDescriptor.containingDeclaration
|
||||||
|
val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration)
|
||||||
|
return SimpleFunctionDescriptorImpl.create(
|
||||||
|
/* containingDeclaration = */ newContainingDeclaration,
|
||||||
|
/* annotations = */ oldDescriptor.annotations,
|
||||||
|
/* name = */ generateCopyName(oldDescriptor.name),
|
||||||
|
/* kind = */ oldDescriptor.kind,
|
||||||
|
/* source = */ oldDescriptor.source
|
||||||
|
).apply {
|
||||||
|
|
||||||
|
val oldDispatchReceiverParameter = oldDescriptor.dispatchReceiverParameter
|
||||||
|
val newDispatchReceiverParameter = oldDispatchReceiverParameter?.let { descriptorSubstituteMap.getOrDefault(it, it) as ReceiverParameterDescriptor }
|
||||||
|
val newTypeParameters = oldDescriptor.typeParameters // TODO substitute types
|
||||||
|
val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, this)
|
||||||
|
val newReceiverParameterType = substituteType(oldDescriptor.extensionReceiverParameter?.type)
|
||||||
|
val newReturnType = substituteType(oldDescriptor.returnType)
|
||||||
|
|
||||||
|
initialize(
|
||||||
|
/* receiverParameterType = */ newReceiverParameterType,
|
||||||
|
/* dispatchReceiverParameter = */ newDispatchReceiverParameter,
|
||||||
|
/* typeParameters = */ newTypeParameters,
|
||||||
|
/* unsubstitutedValueParameters = */ newValueParameters,
|
||||||
|
/* unsubstitutedReturnType = */ newReturnType,
|
||||||
|
/* modality = */ oldDescriptor.modality,
|
||||||
|
/* visibility = */ oldDescriptor.visibility
|
||||||
|
)
|
||||||
|
isTailrec = oldDescriptor.isTailrec
|
||||||
|
isSuspend = oldDescriptor.isSuspend
|
||||||
|
overriddenDescriptors += oldDescriptor.overriddenDescriptors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
private fun copyConstructorDescriptor(oldDescriptor: ConstructorDescriptor) : FunctionDescriptor {
|
||||||
|
|
||||||
|
val oldContainingDeclaration = oldDescriptor.containingDeclaration
|
||||||
|
val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration)
|
||||||
|
return ClassConstructorDescriptorImpl.create(
|
||||||
|
/* containingDeclaration = */ newContainingDeclaration as ClassDescriptor,
|
||||||
|
/* annotations = */ oldDescriptor.annotations,
|
||||||
|
/* isPrimary = */ oldDescriptor.isPrimary,
|
||||||
|
/* source = */ oldDescriptor.source
|
||||||
|
).apply {
|
||||||
|
|
||||||
|
val newTypeParameters = oldDescriptor.typeParameters
|
||||||
|
val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, this)
|
||||||
|
val receiverParameterType = substituteType(oldDescriptor.dispatchReceiverParameter?.type)
|
||||||
|
val returnType = substituteType(oldDescriptor.returnType)
|
||||||
|
|
||||||
|
initialize(
|
||||||
|
/* receiverParameterType = */ receiverParameterType,
|
||||||
|
/* dispatchReceiverParameter = */ null, // For constructor there is no explicit dispatch receiver.
|
||||||
|
/* typeParameters = */ newTypeParameters,
|
||||||
|
/* unsubstitutedValueParameters = */ newValueParameters,
|
||||||
|
/* unsubstitutedReturnType = */ returnType,
|
||||||
|
/* modality = */ oldDescriptor.modality,
|
||||||
|
/* visibility = */ oldDescriptor.visibility
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
private fun copyPropertyOrField(oldDescriptor: PropertyDescriptor) {
|
||||||
|
|
||||||
|
val newDescriptor = copyPropertyDescriptor(oldDescriptor)
|
||||||
|
descriptorSubstituteMap[oldDescriptor] = newDescriptor
|
||||||
|
oldDescriptor.getter?.let {
|
||||||
|
descriptorSubstituteMap[it] = newDescriptor.getter!!
|
||||||
|
}
|
||||||
|
oldDescriptor.setter?.let {
|
||||||
|
descriptorSubstituteMap[it] = newDescriptor.setter!!
|
||||||
|
}
|
||||||
|
oldDescriptor.extensionReceiverParameter?.let{
|
||||||
|
descriptorSubstituteMap[it] = newDescriptor.extensionReceiverParameter!!
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
private fun copyPropertyDescriptor(oldDescriptor: PropertyDescriptor): PropertyDescriptor {
|
||||||
|
|
||||||
|
val oldContainingDeclaration = oldDescriptor.containingDeclaration
|
||||||
|
val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration) as ClassDescriptor
|
||||||
|
return PropertyDescriptorImpl.create(
|
||||||
|
/* containingDeclaration = */ newContainingDeclaration,
|
||||||
|
/* annotations = */ oldDescriptor.annotations,
|
||||||
|
/* modality = */ oldDescriptor.modality,
|
||||||
|
/* visibility = */ oldDescriptor.visibility,
|
||||||
|
/* isVar = */ oldDescriptor.isVar,
|
||||||
|
/* name = */ oldDescriptor.name,
|
||||||
|
/* kind = */ oldDescriptor.kind,
|
||||||
|
/* source = */ oldDescriptor.source,
|
||||||
|
/* lateInit = */ oldDescriptor.isLateInit,
|
||||||
|
/* isConst = */ oldDescriptor.isConst,
|
||||||
|
/* isExpect = */ oldDescriptor.isExpect,
|
||||||
|
/* isActual = */ oldDescriptor.isActual,
|
||||||
|
/* isExternal = */ oldDescriptor.isExternal,
|
||||||
|
/* isDelegated = */ oldDescriptor.isDelegated
|
||||||
|
).apply {
|
||||||
|
|
||||||
|
setType(
|
||||||
|
/* outType = */ oldDescriptor.type,
|
||||||
|
/* typeParameters = */ oldDescriptor.typeParameters,
|
||||||
|
/* dispatchReceiverParameter = */ newContainingDeclaration.thisAsReceiverParameter,
|
||||||
|
/* receiverType = */ oldDescriptor.extensionReceiverParameter?.type)
|
||||||
|
|
||||||
|
initialize(
|
||||||
|
/* getter = */ oldDescriptor.getter?.let { copyPropertyGetterDescriptor(it, this) },
|
||||||
|
/* setter = */ oldDescriptor.setter?.let { copyPropertySetterDescriptor(it, this) })
|
||||||
|
|
||||||
|
overriddenDescriptors += oldDescriptor.overriddenDescriptors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
private fun copyPropertyGetterDescriptor(oldDescriptor: PropertyGetterDescriptor, newPropertyDescriptor: PropertyDescriptor)
|
||||||
|
: PropertyGetterDescriptorImpl {
|
||||||
|
|
||||||
|
return PropertyGetterDescriptorImpl(
|
||||||
|
/* correspondingProperty = */ newPropertyDescriptor,
|
||||||
|
/* annotations = */ oldDescriptor.annotations,
|
||||||
|
/* modality = */ oldDescriptor.modality,
|
||||||
|
/* visibility = */ oldDescriptor.visibility,
|
||||||
|
/* isDefault = */ oldDescriptor.isDefault,
|
||||||
|
/* isExternal = */ oldDescriptor.isExternal,
|
||||||
|
/* isInline = */ oldDescriptor.isInline,
|
||||||
|
/* kind = */ oldDescriptor.kind,
|
||||||
|
/* original = */ null,
|
||||||
|
/* source = */ oldDescriptor.source).apply {
|
||||||
|
initialize(oldDescriptor.returnType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
private fun copyPropertySetterDescriptor(oldDescriptor: PropertySetterDescriptor, newPropertyDescriptor: PropertyDescriptor)
|
||||||
|
: PropertySetterDescriptorImpl {
|
||||||
|
|
||||||
|
return PropertySetterDescriptorImpl(
|
||||||
|
/* correspondingProperty = */ newPropertyDescriptor,
|
||||||
|
/* annotations = */ oldDescriptor.annotations,
|
||||||
|
/* modality = */ oldDescriptor.modality,
|
||||||
|
/* visibility = */ oldDescriptor.visibility,
|
||||||
|
/* isDefault = */ oldDescriptor.isDefault,
|
||||||
|
/* isExternal = */ oldDescriptor.isExternal,
|
||||||
|
/* isInline = */ oldDescriptor.isInline,
|
||||||
|
/* kind = */ oldDescriptor.kind,
|
||||||
|
/* original = */ null,
|
||||||
|
/* source = */ oldDescriptor.source).apply {
|
||||||
|
initialize(copyValueParameters(oldDescriptor.valueParameters, this).single())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
private fun copyClassDescriptor(oldDescriptor: ClassDescriptor): ClassDescriptorImpl {
|
||||||
|
|
||||||
|
val oldSuperClass = oldDescriptor.getSuperClassOrAny()
|
||||||
|
val newSuperClass = descriptorSubstituteMap.getOrDefault(oldSuperClass, oldSuperClass) as ClassDescriptor
|
||||||
|
val oldContainingDeclaration = oldDescriptor.containingDeclaration
|
||||||
|
val newContainingDeclaration = descriptorSubstituteMap.getOrDefault(oldContainingDeclaration, oldContainingDeclaration)
|
||||||
|
val newName = if (DescriptorUtils.isAnonymousObject(oldDescriptor)) // Anonymous objects are identified by their name.
|
||||||
|
oldDescriptor.name // We need to preserve it for LocalDeclarationsLowering.
|
||||||
|
else
|
||||||
|
generateCopyName(oldDescriptor.name)
|
||||||
|
return ClassDescriptorImpl(
|
||||||
|
/* containingDeclaration = */ newContainingDeclaration,
|
||||||
|
/* name = */ newName,
|
||||||
|
/* modality = */ oldDescriptor.modality,
|
||||||
|
/* kind = */ oldDescriptor.kind,
|
||||||
|
/* supertypes = */ listOf(newSuperClass.defaultType),
|
||||||
|
/* source = */ oldDescriptor.source,
|
||||||
|
/* isExternal = */ oldDescriptor.isExternal
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
inner class InlineCopyIr : DeepCopyIrTree() {
|
||||||
|
|
||||||
|
override fun mapClassDeclaration (descriptor: ClassDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassDescriptor
|
||||||
|
override fun mapTypeAliasDeclaration (descriptor: TypeAliasDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as TypeAliasDescriptor
|
||||||
|
override fun mapFunctionDeclaration (descriptor: FunctionDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as FunctionDescriptor
|
||||||
|
override fun mapConstructorDeclaration (descriptor: ClassConstructorDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassConstructorDescriptor
|
||||||
|
override fun mapPropertyDeclaration (descriptor: PropertyDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as PropertyDescriptor
|
||||||
|
override fun mapLocalPropertyDeclaration (descriptor: VariableDescriptorWithAccessors) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as VariableDescriptorWithAccessors
|
||||||
|
override fun mapEnumEntryDeclaration (descriptor: ClassDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassDescriptor
|
||||||
|
override fun mapVariableDeclaration (descriptor: VariableDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as VariableDescriptor
|
||||||
|
override fun mapErrorDeclaration (descriptor: DeclarationDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor)
|
||||||
|
|
||||||
|
override fun mapClassReference (descriptor: ClassDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassDescriptor
|
||||||
|
override fun mapValueReference (descriptor: ValueDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ValueDescriptor
|
||||||
|
override fun mapVariableReference (descriptor: VariableDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as VariableDescriptor
|
||||||
|
override fun mapPropertyReference (descriptor: PropertyDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as PropertyDescriptor
|
||||||
|
override fun mapCallee (descriptor: FunctionDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as FunctionDescriptor
|
||||||
|
override fun mapDelegatedConstructorCallee (descriptor: ClassConstructorDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassConstructorDescriptor
|
||||||
|
override fun mapEnumConstructorCallee (descriptor: ClassConstructorDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassConstructorDescriptor
|
||||||
|
override fun mapLocalPropertyReference (descriptor: VariableDescriptorWithAccessors) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as VariableDescriptorWithAccessors
|
||||||
|
override fun mapClassifierReference (descriptor: ClassifierDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as ClassifierDescriptor
|
||||||
|
override fun mapReturnTarget (descriptor: FunctionDescriptor) = descriptorSubstituteMap.getOrDefault(descriptor, descriptor) as FunctionDescriptor
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun mapSuperQualifier(qualifier: ClassDescriptor?): ClassDescriptor? {
|
||||||
|
if (qualifier == null) return null
|
||||||
|
return descriptorSubstituteMap.getOrDefault(qualifier, qualifier) as ClassDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- Visits ----------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun visitCall(expression: IrCall): IrCall {
|
||||||
|
if (expression !is IrCallImpl) return super.visitCall(expression)
|
||||||
|
val newDescriptor = mapCallee(expression.descriptor)
|
||||||
|
return IrCallImpl(
|
||||||
|
startOffset = expression.startOffset,
|
||||||
|
endOffset = expression.endOffset,
|
||||||
|
type = newDescriptor.returnType!!,
|
||||||
|
calleeDescriptor = newDescriptor,
|
||||||
|
typeArguments = substituteTypeArguments(expression.transformTypeArguments(newDescriptor)),
|
||||||
|
origin = expression.origin,
|
||||||
|
superQualifierDescriptor = mapSuperQualifier(expression.superQualifier)
|
||||||
|
).transformValueArguments(expression)
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun visitFunction(declaration: IrFunction): IrFunction =
|
||||||
|
IrFunctionImpl(
|
||||||
|
startOffset = declaration.startOffset,
|
||||||
|
endOffset = declaration.endOffset,
|
||||||
|
origin = mapDeclarationOrigin(declaration.origin),
|
||||||
|
descriptor = mapFunctionDeclaration(declaration.descriptor),
|
||||||
|
body = declaration.body?.transform(this, null)
|
||||||
|
).transformParameters(declaration)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
private fun <T : IrFunction> T.transformDefaults(original: T): T {
|
||||||
|
for (originalValueParameter in original.descriptor.valueParameters) {
|
||||||
|
val valueParameter = descriptor.valueParameters[originalValueParameter.index]
|
||||||
|
original.getDefault(originalValueParameter)?.let { irDefaultParameterValue ->
|
||||||
|
putDefault(valueParameter, irDefaultParameterValue.transform(this@InlineCopyIr, null))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
fun getTypeOperatorReturnType(operator: IrTypeOperator, type: KotlinType) : KotlinType {
|
||||||
|
return when (operator) {
|
||||||
|
IrTypeOperator.CAST,
|
||||||
|
IrTypeOperator.IMPLICIT_CAST,
|
||||||
|
IrTypeOperator.IMPLICIT_NOTNULL,
|
||||||
|
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
|
||||||
|
IrTypeOperator.IMPLICIT_INTEGER_COERCION -> type
|
||||||
|
IrTypeOperator.SAFE_CAST -> type.makeNullable()
|
||||||
|
IrTypeOperator.INSTANCEOF,
|
||||||
|
IrTypeOperator.NOT_INSTANCEOF -> context.builtIns.booleanType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrTypeOperatorCall {
|
||||||
|
val typeOperand = substituteType(expression.typeOperand)!!
|
||||||
|
val returnType = getTypeOperatorReturnType(expression.operator, typeOperand)
|
||||||
|
return IrTypeOperatorCallImpl(
|
||||||
|
startOffset = expression.startOffset,
|
||||||
|
endOffset = expression.endOffset,
|
||||||
|
type = returnType,
|
||||||
|
operator = expression.operator,
|
||||||
|
typeOperand = typeOperand,
|
||||||
|
argument = expression.argument.transform(this, null)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun visitReturn(expression: IrReturn): IrReturn =
|
||||||
|
IrReturnImpl(
|
||||||
|
startOffset = expression.startOffset,
|
||||||
|
endOffset = expression.endOffset,
|
||||||
|
type = substituteType(expression.type)!!,
|
||||||
|
returnTargetDescriptor = mapReturnTarget(expression.returnTarget),
|
||||||
|
value = expression.value.transform(this, null)
|
||||||
|
)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun visitBlock(expression: IrBlock): IrBlock {
|
||||||
|
return if (expression is IrReturnableBlock) {
|
||||||
|
IrReturnableBlockImpl(
|
||||||
|
startOffset = expression.startOffset,
|
||||||
|
endOffset = expression.endOffset,
|
||||||
|
type = expression.type,
|
||||||
|
descriptor = expression.descriptor,
|
||||||
|
origin = mapStatementOrigin(expression.origin),
|
||||||
|
statements = expression.statements.map { it.transform(this, null) },
|
||||||
|
sourceFileName = expression.sourceFileName
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
super.visitBlock(expression)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun visitClassReference(expression: IrClassReference): IrClassReference {
|
||||||
|
val newExpressionType = substituteType(expression.type)!! // Substituted expression type.
|
||||||
|
val newDescriptorType = substituteType(expression.descriptor.defaultType)!! // Substituted type of referenced class.
|
||||||
|
val classDescriptor = newDescriptorType.constructor.declarationDescriptor!! // Get ClassifierDescriptor of the referenced class.
|
||||||
|
return IrClassReferenceImpl(
|
||||||
|
startOffset = expression.startOffset,
|
||||||
|
endOffset = expression.endOffset,
|
||||||
|
type = newExpressionType,
|
||||||
|
descriptor = classDescriptor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun visitGetClass(expression: IrGetClass): IrGetClass {
|
||||||
|
val type = substituteType(expression.type)!!
|
||||||
|
if (type == expression.type) return expression
|
||||||
|
return IrGetClassImpl(
|
||||||
|
startOffset = expression.startOffset,
|
||||||
|
endOffset = expression.endOffset,
|
||||||
|
type = type,
|
||||||
|
argument = expression.argument.transform(this, null)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop {
|
||||||
|
return irLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
private fun copyValueParameters(oldValueParameters: List <ValueParameterDescriptor>, containingDeclaration: CallableDescriptor): List <ValueParameterDescriptor> {
|
||||||
|
|
||||||
|
return oldValueParameters.map { oldDescriptor ->
|
||||||
|
val newDescriptor = ValueParameterDescriptorImpl(
|
||||||
|
containingDeclaration = containingDeclaration,
|
||||||
|
original = oldDescriptor.original,
|
||||||
|
index = oldDescriptor.index,
|
||||||
|
annotations = oldDescriptor.annotations,
|
||||||
|
name = oldDescriptor.name,
|
||||||
|
outType = substituteType(oldDescriptor.type)!!,
|
||||||
|
declaresDefaultValue = oldDescriptor.declaresDefaultValue(),
|
||||||
|
isCrossinline = oldDescriptor.isCrossinline,
|
||||||
|
isNoinline = oldDescriptor.isNoinline,
|
||||||
|
varargElementType = substituteType(oldDescriptor.varargElementType),
|
||||||
|
source = oldDescriptor.source
|
||||||
|
)
|
||||||
|
descriptorSubstituteMap[oldDescriptor] = newDescriptor
|
||||||
|
newDescriptor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
private fun substituteType(oldType: KotlinType?): KotlinType? {
|
||||||
|
if (typeSubstitutor == null) return oldType
|
||||||
|
if (oldType == null) return oldType
|
||||||
|
return typeSubstitutor!!.substitute(oldType, Variance.INVARIANT) ?: oldType
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
private fun substituteTypeArguments(oldTypeArguments: Map <TypeParameterDescriptor, KotlinType>?): Map <TypeParameterDescriptor, KotlinType>? {
|
||||||
|
|
||||||
|
if (oldTypeArguments == null) return null
|
||||||
|
if (typeSubstitutor == null) return oldTypeArguments
|
||||||
|
|
||||||
|
val newTypeArguments = oldTypeArguments.entries.associate {
|
||||||
|
val typeParameterDescriptor = it.key
|
||||||
|
val oldTypeArgument = it.value
|
||||||
|
val newTypeArgument = substituteType(oldTypeArgument)!!
|
||||||
|
typeParameterDescriptor to newTypeArgument
|
||||||
|
}
|
||||||
|
return newTypeArguments
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
fun addCurrentSubstituteMap(globalSubstituteMap: MutableMap<DeclarationDescriptor, SubstitutedDescriptor>) {
|
||||||
|
descriptorSubstituteMap.forEach { t, u ->
|
||||||
|
globalSubstituteMap.put(t, SubstitutedDescriptor(targetDescriptor, u))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val context = context
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class SubstitutedDescriptor(val inlinedFunction: FunctionDescriptor, val descriptor: DeclarationDescriptor)
|
||||||
|
|
||||||
|
class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap<DeclarationDescriptor, SubstitutedDescriptor>)
|
||||||
|
: IrElementTransformerVoidWithContext() {
|
||||||
|
|
||||||
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
|
val oldExpression = super.visitCall(expression) as IrCall
|
||||||
|
|
||||||
|
val substitutedDescriptor = globalSubstituteMap[expression.descriptor.original]
|
||||||
|
?: return oldExpression
|
||||||
|
if (allScopes.any { it.scope.scopeOwner == substitutedDescriptor.inlinedFunction })
|
||||||
|
return oldExpression
|
||||||
|
return when (oldExpression) {
|
||||||
|
is IrCallImpl -> copyIrCallImpl(oldExpression, substitutedDescriptor)
|
||||||
|
is IrCallWithShallowCopy -> copyIrCallWithShallowCopy(oldExpression, substitutedDescriptor)
|
||||||
|
else -> oldExpression
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
private fun copyIrCallImpl(oldExpression: IrCallImpl, substitutedDescriptor: SubstitutedDescriptor): IrCallImpl {
|
||||||
|
|
||||||
|
val oldDescriptor = oldExpression.descriptor
|
||||||
|
val newDescriptor = substitutedDescriptor.descriptor as FunctionDescriptor
|
||||||
|
|
||||||
|
if (newDescriptor == oldDescriptor)
|
||||||
|
return oldExpression
|
||||||
|
|
||||||
|
val newExpression = IrCallImpl(
|
||||||
|
startOffset = oldExpression.startOffset,
|
||||||
|
endOffset = oldExpression.endOffset,
|
||||||
|
type = oldExpression.type,
|
||||||
|
calleeDescriptor = newDescriptor,
|
||||||
|
typeArguments = oldExpression.typeArguments,
|
||||||
|
origin = oldExpression.origin,
|
||||||
|
superQualifierDescriptor = oldExpression.superQualifier
|
||||||
|
).apply {
|
||||||
|
oldExpression.descriptor.valueParameters.forEach {
|
||||||
|
val valueArgument = oldExpression.getValueArgument(it)
|
||||||
|
putValueArgument(it.index, valueArgument)
|
||||||
|
}
|
||||||
|
extensionReceiver = oldExpression.extensionReceiver
|
||||||
|
dispatchReceiver = oldExpression.dispatchReceiver
|
||||||
|
}
|
||||||
|
|
||||||
|
return newExpression
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
private fun copyIrCallWithShallowCopy(oldExpression: IrCallWithShallowCopy, substitutedDescriptor: SubstitutedDescriptor): IrCall {
|
||||||
|
|
||||||
|
val oldDescriptor = oldExpression.descriptor
|
||||||
|
val newDescriptor = substitutedDescriptor.descriptor as FunctionDescriptor
|
||||||
|
|
||||||
|
if (newDescriptor == oldDescriptor)
|
||||||
|
return oldExpression
|
||||||
|
|
||||||
|
return oldExpression.shallowCopy(oldExpression.origin, newDescriptor, oldExpression.superQualifier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+3
-1
@@ -18,7 +18,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.konan.lower
|
package org.jetbrains.kotlin.backend.konan.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.*
|
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||||
|
import org.jetbrains.kotlin.backend.common.ScopeWithIr
|
||||||
|
import org.jetbrains.kotlin.backend.common.reportWarning
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke
|
import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.needsInlining
|
import org.jetbrains.kotlin.backend.konan.descriptors.needsInlining
|
||||||
|
|||||||
+106
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.konan.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.at
|
||||||
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
|
import org.jetbrains.kotlin.backend.konan.reportCompilationError
|
||||||
|
import org.jetbrains.kotlin.ir.builders.irCall
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This pass runs after inlining and performs the following additional transformations over some operations:
|
||||||
|
* - Convert immutableBinaryBlobOf() arguments to special IrConst.
|
||||||
|
* - Convert `obj::class` and `Class::class` to calls.
|
||||||
|
*/
|
||||||
|
internal class PostInlineLowering(val context: Context) : FileLoweringPass {
|
||||||
|
|
||||||
|
private val symbols get() = context.ir.symbols
|
||||||
|
|
||||||
|
override fun lower(irFile: IrFile) {
|
||||||
|
irFile.transformChildrenVoid(object : IrBuildingTransformer(context) {
|
||||||
|
|
||||||
|
override fun visitClassReference(expression: IrClassReference): IrExpression {
|
||||||
|
expression.transformChildrenVoid()
|
||||||
|
builder.at(expression)
|
||||||
|
|
||||||
|
val typeArgument = expression.descriptor.defaultType
|
||||||
|
|
||||||
|
return builder.irCall(symbols.kClassImplConstructor, listOf(typeArgument)).apply {
|
||||||
|
putValueArgument(0, builder.irCall(symbols.getClassTypeInfo, listOf(typeArgument)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitGetClass(expression: IrGetClass): IrExpression {
|
||||||
|
expression.transformChildrenVoid()
|
||||||
|
builder.at(expression)
|
||||||
|
|
||||||
|
val typeArgument = expression.type.arguments.single().type
|
||||||
|
return builder.irCall(symbols.kClassImplConstructor, listOf(typeArgument)).apply {
|
||||||
|
val typeInfo = builder.irCall(symbols.getObjectTypeInfo).apply {
|
||||||
|
putValueArgument(0, expression.argument)
|
||||||
|
}
|
||||||
|
|
||||||
|
putValueArgument(0, typeInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
|
if (expression.symbol == context.ir.symbols.immutableBinaryBlobOf) {
|
||||||
|
// Convert arguments of the binary blob to special IrConst<String> structure, so that
|
||||||
|
// vararg lowering will not affect it.
|
||||||
|
val args = expression.getValueArgument(0) as? IrVararg
|
||||||
|
if (args == null) throw Error("varargs shall not be lowered yet")
|
||||||
|
if (args.elements.any { it is IrSpreadElement }) {
|
||||||
|
context.reportCompilationError("no spread elements allowed here", irFile, args)
|
||||||
|
}
|
||||||
|
val builder = StringBuilder()
|
||||||
|
args.elements.forEach {
|
||||||
|
if (it !is IrConst<*>) {
|
||||||
|
context.reportCompilationError(
|
||||||
|
"all elements of binary blob must be constants", irFile, it)
|
||||||
|
}
|
||||||
|
val value = when (it.kind) {
|
||||||
|
IrConstKind.Short -> (it.value as Short).toInt()
|
||||||
|
else ->
|
||||||
|
context.reportCompilationError("incorrect value for binary data: $it.value", irFile, it)
|
||||||
|
}
|
||||||
|
if (value < 0 || value > 0xff)
|
||||||
|
context.reportCompilationError("incorrect value for binary data: $value", irFile, it)
|
||||||
|
// Luckily, all values in range 0x00 .. 0xff represent valid UTF-16 symbols,
|
||||||
|
// block 0 (Basic Latin) and block 1 (Latin-1 Supplement) in
|
||||||
|
// Basic Multilingual Plane, so we could just append data "as is".
|
||||||
|
builder.append(value.toChar())
|
||||||
|
}
|
||||||
|
expression.putValueArgument(0, IrConstImpl<String>(
|
||||||
|
expression.startOffset, expression.endOffset,
|
||||||
|
context.ir.symbols.immutableBinaryBlob.descriptor.defaultType,
|
||||||
|
IrConstKind.String, builder.toString()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return expression
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-64
@@ -18,22 +18,18 @@ package org.jetbrains.kotlin.backend.konan.lower
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer
|
import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer
|
||||||
import org.jetbrains.kotlin.backend.common.lower.at
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.*
|
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
||||||
import org.jetbrains.kotlin.ir.builders.irCall
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This pass runs before inlining and performs the following additional transformations over some operations:
|
* This pass runs before inlining and performs the following additional transformations over some operations:
|
||||||
* - Assertion call removal.
|
* - Assertion call removal.
|
||||||
* - Convert immutableBinaryBlobOf() arguments to special IrConst.
|
|
||||||
* - Convert `obj::class` and `Class::class` to calls.
|
|
||||||
*/
|
*/
|
||||||
internal class PreInlineLowering(val context: Context) : FileLoweringPass {
|
internal class PreInlineLowering(val context: Context) : FileLoweringPass {
|
||||||
|
|
||||||
@@ -45,31 +41,6 @@ internal class PreInlineLowering(val context: Context) : FileLoweringPass {
|
|||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
irFile.transformChildrenVoid(object : IrBuildingTransformer(context) {
|
irFile.transformChildrenVoid(object : IrBuildingTransformer(context) {
|
||||||
|
|
||||||
override fun visitClassReference(expression: IrClassReference): IrExpression {
|
|
||||||
expression.transformChildrenVoid()
|
|
||||||
builder.at(expression)
|
|
||||||
|
|
||||||
val typeArgument = expression.descriptor.defaultType
|
|
||||||
|
|
||||||
return builder.irCall(symbols.kClassImplConstructor, listOf(typeArgument)).apply {
|
|
||||||
putValueArgument(0, builder.irCall(symbols.getClassTypeInfo, listOf(typeArgument)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitGetClass(expression: IrGetClass): IrExpression {
|
|
||||||
expression.transformChildrenVoid()
|
|
||||||
builder.at(expression)
|
|
||||||
|
|
||||||
val typeArgument = expression.type.arguments.single().type
|
|
||||||
return builder.irCall(symbols.kClassImplConstructor, listOf(typeArgument)).apply {
|
|
||||||
val typeInfo = builder.irCall(symbols.getObjectTypeInfo).apply {
|
|
||||||
putValueArgument(0, expression.argument)
|
|
||||||
}
|
|
||||||
|
|
||||||
putValueArgument(0, typeInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
@@ -79,38 +50,6 @@ internal class PreInlineLowering(val context: Context) : FileLoweringPass {
|
|||||||
return IrCompositeImpl(expression.startOffset, expression.endOffset, expression.type)
|
return IrCompositeImpl(expression.startOffset, expression.endOffset, expression.type)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expression.symbol == context.ir.symbols.immutableBinaryBlobOf) {
|
|
||||||
// Convert arguments of the binary blob to special IrConst<String> structure, so that
|
|
||||||
// vararg lowering will not affect it.
|
|
||||||
val args = expression.getValueArgument(0) as? IrVararg
|
|
||||||
if (args == null) throw Error("varargs shall not be lowered yet")
|
|
||||||
if (args.elements.any { it is IrSpreadElement }) {
|
|
||||||
context.reportCompilationError("no spread elements allowed here", irFile, args)
|
|
||||||
}
|
|
||||||
val builder = StringBuilder()
|
|
||||||
args.elements.forEach {
|
|
||||||
if (it !is IrConst<*>) {
|
|
||||||
context.reportCompilationError(
|
|
||||||
"all elements of binary blob must be constants", irFile, it)
|
|
||||||
}
|
|
||||||
val value = when (it.kind) {
|
|
||||||
IrConstKind.Short -> (it.value as Short).toInt()
|
|
||||||
else ->
|
|
||||||
context.reportCompilationError("incorrect value for binary data: $it.value", irFile, it)
|
|
||||||
}
|
|
||||||
if (value < 0 || value > 0xff)
|
|
||||||
context.reportCompilationError("incorrect value for binary data: $value", irFile, it)
|
|
||||||
// Luckily, all values in range 0x00 .. 0xff represent valid UTF-16 symbols,
|
|
||||||
// block 0 (Basic Latin) and block 1 (Latin-1 Supplement) in
|
|
||||||
// Basic Multilingual Plane, so we could just append data "as is".
|
|
||||||
builder.append(value.toChar())
|
|
||||||
}
|
|
||||||
expression.putValueArgument(0, IrConstImpl<String>(
|
|
||||||
expression.startOffset, expression.endOffset,
|
|
||||||
context.ir.symbols.immutableBinaryBlob.descriptor.defaultType,
|
|
||||||
IrConstKind.String, builder.toString()))
|
|
||||||
}
|
|
||||||
|
|
||||||
return expression
|
return expression
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
+1
-1
@@ -251,7 +251,7 @@ message IrOperation {
|
|||||||
IrBreak break = 2;
|
IrBreak break = 2;
|
||||||
IrCall call = 3;
|
IrCall call = 3;
|
||||||
IrCallableReference callable_reference = 4;
|
IrCallableReference callable_reference = 4;
|
||||||
IrClassReference class_reference = 25;
|
IrClassReference class_reference = 27;
|
||||||
IrConst const = 5;
|
IrConst const = 5;
|
||||||
IrComposite composite = 26;
|
IrComposite composite = 26;
|
||||||
IrContinue continue = 6;
|
IrContinue continue = 6;
|
||||||
|
|||||||
Reference in New Issue
Block a user