[PSI2IR] Propagate smart cast information for variable loads.
This gives us more precise type information and can enable backend optimizations. This was motivated by when expressions not compiled to table switches in the JVM_IR backend. Fixed KT-36845.
This commit is contained in:
@@ -86,13 +86,14 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
endOffset: Int,
|
||||
descriptor: DeclarationDescriptor,
|
||||
resolvedCall: ResolvedCall<*>?,
|
||||
origin: IrStatementOrigin?
|
||||
origin: IrStatementOrigin?,
|
||||
irType: IrType? = null
|
||||
): IrExpression =
|
||||
when (descriptor) {
|
||||
is FakeCallableDescriptorForObject ->
|
||||
generateValueReference(startOffset, endOffset, descriptor.getReferencedDescriptor(), resolvedCall, origin)
|
||||
generateValueReference(startOffset, endOffset, descriptor.getReferencedDescriptor(), resolvedCall, origin, irType)
|
||||
is TypeAliasDescriptor ->
|
||||
generateValueReference(startOffset, endOffset, descriptor.classDescriptor!!, null, origin)
|
||||
generateValueReference(startOffset, endOffset, descriptor.classDescriptor!!, null, origin, irType)
|
||||
is ClassDescriptor -> {
|
||||
val classValueType = descriptor.classValueType!!
|
||||
statementGenerator.generateSingletonReference(descriptor, startOffset, endOffset, classValueType)
|
||||
@@ -107,7 +108,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
IrGetFieldImpl(startOffset, endOffset, field, fieldType, receiver?.load())
|
||||
}
|
||||
is VariableDescriptor ->
|
||||
generateGetVariable(startOffset, endOffset, descriptor, getTypeArguments(resolvedCall), origin)
|
||||
generateGetVariable(startOffset, endOffset, descriptor, getTypeArguments(resolvedCall), origin, irType)
|
||||
else ->
|
||||
TODO("Unexpected callable descriptor: $descriptor ${descriptor::class.java.simpleName}")
|
||||
}
|
||||
@@ -117,7 +118,8 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
endOffset: Int,
|
||||
descriptor: VariableDescriptor,
|
||||
typeArguments: Map<TypeParameterDescriptor, KotlinType>?,
|
||||
origin: IrStatementOrigin? = null
|
||||
origin: IrStatementOrigin? = null,
|
||||
irType: IrType? = null
|
||||
) =
|
||||
if (descriptor is LocalVariableDescriptor && descriptor.isDelegated) {
|
||||
val getterDescriptor = descriptor.getter!!
|
||||
@@ -128,8 +130,15 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
context.callToSubstitutedDescriptorMap[this] = getterDescriptor
|
||||
putTypeArguments(typeArguments) { it.toIrType() }
|
||||
}
|
||||
} else
|
||||
IrGetValueImpl(startOffset, endOffset, descriptor.type.toIrType(), context.symbolTable.referenceValue(descriptor), origin)
|
||||
} else {
|
||||
val getValue =
|
||||
IrGetValueImpl(startOffset, endOffset, descriptor.type.toIrType(), context.symbolTable.referenceValue(descriptor), origin)
|
||||
if (irType != null) {
|
||||
IrTypeOperatorCallImpl(startOffset, endOffset, irType, IrTypeOperator.IMPLICIT_CAST, irType, getValue)
|
||||
} else {
|
||||
getValue
|
||||
}
|
||||
}
|
||||
|
||||
fun generateDelegatingConstructorCall(startOffset: Int, endOffset: Int, call: CallBuilder): IrExpression =
|
||||
call.callReceiver.call { dispatchReceiver, extensionReceiver ->
|
||||
|
||||
+3
-1
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.psi2ir.intermediate.IntermediateValue
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.createTemporaryVariableInBlock
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.SMARTCAST
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
@@ -327,7 +328,8 @@ class StatementGenerator(
|
||||
): IrExpression =
|
||||
CallGenerator(this).generateValueReference(
|
||||
expression.startOffsetSkippingComments, expression.endOffset,
|
||||
descriptor, resolvedCall, null
|
||||
descriptor, resolvedCall, null,
|
||||
context.bindingContext.get(SMARTCAST, expression)?.defaultType?.toIrType()
|
||||
)
|
||||
|
||||
override fun visitCallExpression(expression: KtCallExpression, data: Nothing?): IrStatement {
|
||||
|
||||
Reference in New Issue
Block a user