backend: improve default arguments lowering:

use the same `$default`-descriptor in declaration and call.
This commit is contained in:
Svyatoslav Scherbina
2017-01-26 14:55:22 +07:00
committed by SvyatoslavScherbina
parent 6104648d5b
commit 36c90ac47d
2 changed files with 32 additions and 12 deletions
@@ -1,6 +1,8 @@
package org.jetbrains.kotlin.backend.konan.ir package org.jetbrains.kotlin.backend.konan.ir
import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.lower.DefaultParameterDescription
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
@@ -8,6 +10,8 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
internal class Ir(val context: Context, val irModule: IrModuleFragment) { internal class Ir(val context: Context, val irModule: IrModuleFragment) {
val propertiesWithBackingFields = mutableSetOf<PropertyDescriptor>() val propertiesWithBackingFields = mutableSetOf<PropertyDescriptor>()
val defaultParameterDescriptions = mutableMapOf<FunctionDescriptor, DefaultParameterDescription>()
val originalModuleIndex = ModuleIndex(irModule) val originalModuleIndex = ModuleIndex(irModule)
lateinit var moduleIndexForCodegen: ModuleIndex lateinit var moduleIndexForCodegen: ModuleIndex
@@ -69,7 +69,7 @@ class DefaultParameterStubGenerator internal constructor(val context: Context):
log("detected ${functionDescriptor.name.asString()} has got #${bodies.size} default expressions") log("detected ${functionDescriptor.name.asString()} has got #${bodies.size} default expressions")
functionDescriptor.overriddenDescriptors.forEach { context.log("DEFAULT-REPLACER: $it") } functionDescriptor.overriddenDescriptors.forEach { context.log("DEFAULT-REPLACER: $it") }
if (bodies.isNotEmpty()) { if (bodies.isNotEmpty()) {
val description = functionDescriptor.generateDefaultsDescription() val description = functionDescriptor.getOrCreateDefaultsDescription(context)
val builder = context.createFunctionIrBuilder(description.function) val builder = context.createFunctionIrBuilder(description.function)
val body = builder.irBlockBody(irFunction) { val body = builder.irBlockBody(irFunction) {
val params = mutableListOf<VariableDescriptor>() val params = mutableListOf<VariableDescriptor>()
@@ -228,7 +228,7 @@ class DefaultParameterInjector internal constructor(val context: Context): BodyL
var maskValue = 0 var maskValue = 0
val rawDescriptor = expression.descriptor as FunctionDescriptor val rawDescriptor = expression.descriptor as FunctionDescriptor
val descriptor = rawDescriptor.overriddenDescriptors.firstOrNull()?:rawDescriptor val descriptor = rawDescriptor.overriddenDescriptors.firstOrNull()?:rawDescriptor
val desc = descriptor.generateDefaultsDescription() val desc = descriptor.getOrCreateDefaultsDescription(context)
descriptor.valueParameters.forEach { descriptor.valueParameters.forEach {
log("descriptor::${descriptor.name.asString()}#${it.index}: ${it.name.asString()}") log("descriptor::${descriptor.name.asString()}#${it.index}: ${it.name.asString()}")
} }
@@ -276,13 +276,22 @@ val intAnd = DescriptorUtils.getFunctionByName(intDesctiptor.unsubstitutedMember
data class DefaultParameterDescription(val function: FunctionDescriptor, val mask:ValueParameterDescriptor, data class DefaultParameterDescription(val function: FunctionDescriptor, val mask:ValueParameterDescriptor,
val hasExtensionReceiver:Boolean, val hasDispatchReceiver: Boolean) val hasExtensionReceiver:Boolean, val hasDispatchReceiver: Boolean)
fun FunctionDescriptor.generateDefaultsDescription(): DefaultParameterDescription { private fun FunctionDescriptor.getOrCreateDefaultsDescription(context: Context): DefaultParameterDescription {
return context.ir.defaultParameterDescriptions.getOrPut(this) {
this.generateDefaultsDescription(context)
}
}
private fun FunctionDescriptor.generateDefaultsDescription(context: Context): DefaultParameterDescription {
val descriptor = when (this){ val descriptor = when (this){
is ConstructorDescriptor -> ClassConstructorDescriptorImpl.createSynthesized( is ConstructorDescriptor -> DefaultParameterClassConstructorDescriptor(
/* containingDeclaration = */ this.containingDeclaration as ClassDescriptor, containingDeclaration = this.containingDeclaration as ClassDescriptor,
/* annotations = */ annotations, annotations = annotations,
/* isPrimary = */ false, original = null,
/* source = */ SourceElement.NO_SOURCE) isPrimary = false,
source = SourceElement.NO_SOURCE,
kind = CallableMemberDescriptor.Kind.SYNTHESIZED)
is FunctionDescriptor -> SimpleFunctionDescriptorImpl.create( is FunctionDescriptor -> SimpleFunctionDescriptorImpl.create(
/* containingDeclaration = */ this.containingDeclaration, /* containingDeclaration = */ this.containingDeclaration,
/* annotations = */ Annotations.EMPTY, /* annotations = */ Annotations.EMPTY,
@@ -321,8 +330,7 @@ fun FunctionDescriptor.generateDefaultsDescription(): DefaultParameterDescriptio
/* modality = */ Modality.FINAL, /* modality = */ Modality.FINAL,
/* visibility = */ this.visibility) /* visibility = */ this.visibility)
return DefaultParameterDescription( return DefaultParameterDescription(
function = if (descriptor is ClassConstructorDescriptor) DefaultParameterClassConstructorDescriptor(descriptor) function = descriptor,
else descriptor,
mask = maskVariable, mask = maskVariable,
hasDispatchReceiver = (extensionReceiverParameter != null), hasDispatchReceiver = (extensionReceiverParameter != null),
hasExtensionReceiver = (dispatchReceiverParameter != null)) hasExtensionReceiver = (dispatchReceiverParameter != null))
@@ -347,8 +355,16 @@ private fun valueParameter(descriptor: FunctionDescriptor, index: Int, name: Str
/** /**
* This descriptor overrides name property, for class constructor : instead of <init> -> <init>$defeult symbol. * This descriptor overrides name property, for class constructor : instead of <init> -> <init>$defeult symbol.
*/ */
class DefaultParameterClassConstructorDescriptor(val descriptor: ClassConstructorDescriptor): ClassConstructorDescriptor by descriptor { class DefaultParameterClassConstructorDescriptor(
containingDeclaration: ClassDescriptor,
original: ConstructorDescriptor?,
annotations: Annotations,
isPrimary: Boolean,
kind: CallableMemberDescriptor.Kind,
source: SourceElement
) : ClassConstructorDescriptorImpl(containingDeclaration, original, annotations, isPrimary, kind, source) {
override fun getName(): Name { override fun getName(): Name {
return Name.identifier("${descriptor.name.asString()}\$default") return Name.identifier("${super.getName().asString()}\$default")
} }
} }