IrTypes in psi2ir: generators (seem to be) complete

This commit is contained in:
Dmitry Petrov
2018-05-14 15:07:38 +03:00
parent 5f4f6ef863
commit 54e9a2bb7b
21 changed files with 190 additions and 100 deletions
@@ -92,7 +92,9 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
irBlock(ktExpression.startOffset, ktExpression.endOffset, origin, irLValue.type) { irBlock(ktExpression.startOffset, ktExpression.endOffset, origin, irLValue.type) {
val temporary = irTemporary(irLValue.load()) val temporary = irTemporary(irLValue.load())
val opCall = statementGenerator.pregenerateCall(opResolvedCall) val opCall = statementGenerator.pregenerateCall(opResolvedCall)
opCall.setExplicitReceiverValue(VariableLValue(startOffset, endOffset, temporary.symbol)) opCall.setExplicitReceiverValue(
VariableLValue(context, startOffset, endOffset, temporary.symbol, temporary.type)
)
val irOpCall = CallGenerator(statementGenerator).generateCall(ktExpression, opCall, origin) val irOpCall = CallGenerator(statementGenerator).generateCall(ktExpression, opCall, origin)
+irLValue.store(irOpCall) +irLValue.store(irOpCall)
+irGet(temporary.type, temporary.symbol) +irGet(temporary.type, temporary.symbol)
@@ -118,31 +120,37 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
if (descriptor.isDelegated) if (descriptor.isDelegated)
DelegatedLocalPropertyLValue( DelegatedLocalPropertyLValue(
context,
ktLeft.startOffset, ktLeft.endOffset, ktLeft.startOffset, ktLeft.endOffset,
descriptor.type, descriptor.type.toIrType(),
descriptor.getter?.let { context.symbolTable.referenceDeclaredFunction(it) }, descriptor.getter?.let { context.symbolTable.referenceDeclaredFunction(it) },
descriptor.setter?.let { context.symbolTable.referenceDeclaredFunction(it) }, descriptor.setter?.let { context.symbolTable.referenceDeclaredFunction(it) },
origin origin
) )
else else
VariableLValue( createVariableValue(ktLeft, descriptor, origin)
ktLeft.startOffset, ktLeft.endOffset,
context.symbolTable.referenceVariable(descriptor),
origin
)
is PropertyDescriptor -> is PropertyDescriptor ->
generateAssignmentReceiverForProperty(descriptor, origin, ktLeft, resolvedCall) generateAssignmentReceiverForProperty(descriptor, origin, ktLeft, resolvedCall)
is ValueDescriptor -> is ValueDescriptor ->
VariableLValue( createVariableValue(ktLeft, descriptor, origin)
ktLeft.startOffset, ktLeft.endOffset,
context.symbolTable.referenceValue(descriptor),
origin
)
else -> else ->
OnceExpressionValue(ktLeft.genExpr()) OnceExpressionValue(ktLeft.genExpr())
} }
} }
private fun createVariableValue(
ktExpression: KtExpression,
descriptor: ValueDescriptor,
origin: IrStatementOrigin
) =
VariableLValue(
context,
ktExpression.startOffset, ktExpression.endOffset,
context.symbolTable.referenceValue(descriptor),
descriptor.type.toIrType(),
origin
)
private fun createBackingFieldLValue( private fun createBackingFieldLValue(
ktExpression: KtExpression, ktExpression: KtExpression,
descriptor: PropertyDescriptor, descriptor: PropertyDescriptor,
@@ -150,8 +158,9 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
origin: IrStatementOrigin? origin: IrStatementOrigin?
): BackingFieldLValue = ): BackingFieldLValue =
BackingFieldLValue( BackingFieldLValue(
context,
ktExpression.startOffset, ktExpression.endOffset, ktExpression.startOffset, ktExpression.endOffset,
descriptor.type, descriptor.type.toIrType(),
context.symbolTable.referenceField(descriptor), context.symbolTable.referenceField(descriptor),
receiverValue, origin receiverValue, origin
) )
@@ -189,7 +198,7 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
ktExpression: KtExpression, ktExpression: KtExpression,
descriptor: PropertyDescriptor, descriptor: PropertyDescriptor,
propertyReceiver: CallReceiver, propertyReceiver: CallReceiver,
typeArguments: Map<TypeParameterDescriptor, KotlinType>?, typeArgumentsMap: Map<TypeParameterDescriptor, KotlinType>?,
origin: IrStatementOrigin?, origin: IrStatementOrigin?,
superQualifier: ClassDescriptor? superQualifier: ClassDescriptor?
): PropertyLValueBase { ): PropertyLValueBase {
@@ -201,24 +210,32 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
val setterDescriptor = descriptor.setter val setterDescriptor = descriptor.setter
val setterSymbol = setterDescriptor?.let { context.symbolTable.referenceFunction(it.original) } val setterSymbol = setterDescriptor?.let { context.symbolTable.referenceFunction(it.original) }
val propertyIrType = descriptor.type.toIrType()
return if (getterSymbol != null || setterSymbol != null) { return if (getterSymbol != null || setterSymbol != null) {
val typeArgumentsList =
typeArgumentsMap?.let { typeArguments ->
descriptor.typeParameters.map { typeArguments[it]!!.toIrType() }
}
AccessorPropertyLValue( AccessorPropertyLValue(
context,
scope, scope,
ktExpression.startOffset, ktExpression.endOffset, origin, ktExpression.startOffset, ktExpression.endOffset, origin,
descriptor.type, propertyIrType,
getterSymbol, getterSymbol,
getterDescriptor, getterDescriptor,
setterSymbol, setterSymbol,
setterDescriptor, setterDescriptor,
typeArguments, typeArgumentsList,
propertyReceiver, propertyReceiver,
superQualifierSymbol superQualifierSymbol
) )
} else } else
FieldPropertyLValue( FieldPropertyLValue(
context,
scope, scope,
ktExpression.startOffset, ktExpression.endOffset, origin, ktExpression.startOffset, ktExpression.endOffset, origin,
context.symbolTable.referenceField(descriptor), context.symbolTable.referenceField(descriptor),
propertyIrType,
propertyReceiver, propertyReceiver,
superQualifierSymbol superQualifierSymbol
) )
@@ -72,8 +72,10 @@ class BodyGenerator(
val ktDestructuringDeclaration = ktParameter.destructuringDeclaration ?: continue val ktDestructuringDeclaration = ktParameter.destructuringDeclaration ?: continue
val valueParameter = getOrFail(BindingContext.VALUE_PARAMETER, ktParameter) val valueParameter = getOrFail(BindingContext.VALUE_PARAMETER, ktParameter)
val parameterValue = VariableLValue( val parameterValue = VariableLValue(
context,
ktDestructuringDeclaration.startOffset, ktDestructuringDeclaration.endOffset, ktDestructuringDeclaration.startOffset, ktDestructuringDeclaration.endOffset,
context.symbolTable.referenceValue(valueParameter), context.symbolTable.referenceValue(valueParameter),
valueParameter.type.toIrType(),
IrStatementOrigin.DESTRUCTURING_DECLARATION IrStatementOrigin.DESTRUCTURING_DECLARATION
) )
statementGenerator.declareComponentVariablesInBlock(ktDestructuringDeclaration, irBlockBody, parameterValue) statementGenerator.declareComponentVariablesInBlock(ktDestructuringDeclaration, irBlockBody, parameterValue)
@@ -164,8 +164,9 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
): IntermediateValue { ): IntermediateValue {
val thisValue = createThisValueForDelegate(thisClass, ktDelegate) val thisValue = createThisValueForDelegate(thisClass, ktDelegate)
return BackingFieldLValue( return BackingFieldLValue(
context,
ktDelegate.startOffset, ktDelegate.endOffset, ktDelegate.startOffset, ktDelegate.endOffset,
irDelegateField.descriptor.type, irDelegateField.descriptor.type.toIrType(),
irDelegateField, irDelegateField,
thisValue, thisValue,
null null
@@ -327,7 +328,7 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
} }
private fun createVariableValueForDelegate(irDelegate: IrVariableSymbol, ktDelegate: KtPropertyDelegate) = private fun createVariableValueForDelegate(irDelegate: IrVariableSymbol, ktDelegate: KtPropertyDelegate) =
VariableLValue(ktDelegate.startOffset, ktDelegate.endOffset, irDelegate) VariableLValue(context, ktDelegate.startOffset, ktDelegate.endOffset, irDelegate, irDelegate.descriptor.type.toIrType())
private inline fun createLocalPropertyAccessor( private inline fun createLocalPropertyAccessor(
getterDescriptor: VariableAccessorDescriptor, getterDescriptor: VariableAccessorDescriptor,
@@ -162,7 +162,7 @@ class LoopExpressionGenerator(statementGenerator: StatementGenerator) : Statemen
val iteratorCall = statementGenerator.pregenerateCall(iteratorResolvedCall) val iteratorCall = statementGenerator.pregenerateCall(iteratorResolvedCall)
val irIteratorCall = callGenerator.generateCall(ktLoopRange, iteratorCall, IrStatementOrigin.FOR_LOOP_ITERATOR) val irIteratorCall = callGenerator.generateCall(ktLoopRange, iteratorCall, IrStatementOrigin.FOR_LOOP_ITERATOR)
val irIterator = scope.createTemporaryVariable(irIteratorCall, "iterator", origin = IrDeclarationOrigin.FOR_LOOP_ITERATOR) val irIterator = scope.createTemporaryVariable(irIteratorCall, "iterator", origin = IrDeclarationOrigin.FOR_LOOP_ITERATOR)
val iteratorValue = VariableLValue(irIterator) val iteratorValue = VariableLValue(context, irIterator)
irForBlock.statements.add(irIterator) irForBlock.statements.add(irIterator)
val irInnerWhile = IrWhileLoopImpl(startOffset, endOffset, context.irBuiltIns.unitType, IrStatementOrigin.FOR_LOOP_INNER_WHILE) val irInnerWhile = IrWhileLoopImpl(startOffset, endOffset, context.irBuiltIns.unitType, IrStatementOrigin.FOR_LOOP_INNER_WHILE)
@@ -196,7 +196,7 @@ class LoopExpressionGenerator(statementGenerator: StatementGenerator) : Statemen
statementGenerator.declareComponentVariablesInBlock( statementGenerator.declareComponentVariablesInBlock(
ktLoopDestructuringDeclaration, ktLoopDestructuringDeclaration,
irInnerBody, irInnerBody,
VariableLValue(irLoopParameter) VariableLValue(context, irLoopParameter)
) )
} }
@@ -44,16 +44,19 @@ class PropertyGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
fun generatePropertyForPrimaryConstructorParameter(ktParameter: KtParameter, irValueParameter: IrValueParameter): IrDeclaration { fun generatePropertyForPrimaryConstructorParameter(ktParameter: KtParameter, irValueParameter: IrValueParameter): IrDeclaration {
val propertyDescriptor = getOrFail(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, ktParameter) val propertyDescriptor = getOrFail(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, ktParameter)
val irPropertyType = propertyDescriptor.type.toIrType()
return IrPropertyImpl( return IrPropertyImpl(
ktParameter.startOffset, ktParameter.endOffset, ktParameter.startOffset, ktParameter.endOffset,
IrDeclarationOrigin.DEFINED, false, IrDeclarationOrigin.DEFINED, false,
propertyDescriptor propertyDescriptor,
irPropertyType
).also { irProperty -> ).also { irProperty ->
irProperty.backingField = irProperty.backingField =
generatePropertyBackingField(ktParameter, propertyDescriptor) { generatePropertyBackingField(ktParameter, propertyDescriptor) {
IrExpressionBodyImpl( IrExpressionBodyImpl(
IrGetValueImpl( IrGetValueImpl(
ktParameter.startOffset, ktParameter.endOffset, ktParameter.startOffset, ktParameter.endOffset,
irPropertyType,
irValueParameter.symbol, irValueParameter.symbol,
IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER
) )
@@ -99,8 +102,10 @@ class PropertyGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
private fun generateSimpleProperty(ktProperty: KtProperty, propertyDescriptor: PropertyDescriptor): IrProperty = private fun generateSimpleProperty(ktProperty: KtProperty, propertyDescriptor: PropertyDescriptor): IrProperty =
IrPropertyImpl( IrPropertyImpl(
ktProperty.startOffset, ktProperty.endOffset, ktProperty.startOffset, ktProperty.endOffset,
IrDeclarationOrigin.DEFINED, false, IrDeclarationOrigin.DEFINED,
propertyDescriptor false,
propertyDescriptor,
propertyDescriptor.type.toIrType()
).buildWithScope { irProperty -> ).buildWithScope { irProperty ->
irProperty.backingField = irProperty.backingField =
if (propertyDescriptor.hasBackingField()) if (propertyDescriptor.hasBackingField())
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) { class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) {
fun generateClassLiteral(ktClassLiteral: KtClassLiteralExpression): IrExpression { fun generateClassLiteral(ktClassLiteral: KtClassLiteralExpression): IrExpression {
val ktArgument = ktClassLiteral.receiverExpression!! val ktArgument = ktClassLiteral.receiverExpression!!
val lhs = getOrFail(BindingContext.DOUBLE_COLON_LHS, ktArgument) val lhs = getOrFail(BindingContext.DOUBLE_COLON_LHS, ktArgument)
@@ -409,4 +409,5 @@ abstract class StatementGeneratorExtension(val statementGenerator: StatementGene
fun KtExpression.genExpr() = statementGenerator.generateExpression(this) fun KtExpression.genExpr() = statementGenerator.generateExpression(this)
fun KtExpression.genStmt() = statementGenerator.generateStatement(this) fun KtExpression.genStmt() = statementGenerator.generateStatement(this)
fun KotlinType.toIrType() = with(statementGenerator) { toIrType() } fun KotlinType.toIrType() = with(statementGenerator) { toIrType() }
fun translateType(kotlinType: KotlinType) = kotlinType.toIrType()
} }
@@ -26,23 +26,25 @@ import org.jetbrains.kotlin.types.KotlinType
import java.lang.AssertionError import java.lang.AssertionError
class ArrayAccessAssignmentReceiver( class ArrayAccessAssignmentReceiver(
val irArray: IrExpression, private val irArray: IrExpression,
val irIndices: List<IrExpression>, private val irIndices: List<IrExpression>,
val indexedGetCall: CallBuilder?, private val indexedGetCall: CallBuilder?,
val indexedSetCall: CallBuilder?, private val indexedSetCall: CallBuilder?,
val callGenerator: CallGenerator, private val callGenerator: CallGenerator,
val startOffset: Int, private val startOffset: Int,
val endOffset: Int, private val endOffset: Int,
val origin: IrStatementOrigin private val origin: IrStatementOrigin
) : AssignmentReceiver { ) : AssignmentReceiver {
private val type: KotlinType =
private val kotlinType: KotlinType =
indexedGetCall?.run { descriptor.returnType!! } ?: indexedSetCall?.run { descriptor.valueParameters.last().type } indexedGetCall?.run { descriptor.returnType!! } ?: indexedSetCall?.run { descriptor.valueParameters.last().type }
?: throw AssertionError("Array access should have either indexed-get call or indexed-set call") ?: throw AssertionError("Array access should have either indexed-get call or indexed-set call")
override fun assign(withLValue: (LValue) -> IrExpression): IrExpression { override fun assign(withLValue: (LValue) -> IrExpression): IrExpression {
val hasResult = origin.isAssignmentOperatorWithResult() val hasResult = origin.isAssignmentOperatorWithResult()
val resultType = if (hasResult) type else callGenerator.context.builtIns.unitType val resultType = if (hasResult) kotlinType else callGenerator.context.builtIns.unitType
val irBlock = IrBlockImpl(startOffset, endOffset, resultType, origin) val irResultType = callGenerator.translateType(resultType)
val irBlock = IrBlockImpl(startOffset, endOffset, irResultType, origin)
val irArrayValue = callGenerator.scope.createTemporaryVariableInBlock(irArray, irBlock, "array") val irArrayValue = callGenerator.scope.createTemporaryVariableInBlock(irArray, irBlock, "array")
@@ -52,7 +54,12 @@ class ArrayAccessAssignmentReceiver(
indexedGetCall?.fillArrayAndIndexArguments(irArrayValue, irIndexValues) indexedGetCall?.fillArrayAndIndexArguments(irArrayValue, irIndexValues)
indexedSetCall?.fillArrayAndIndexArguments(irArrayValue, irIndexValues) indexedSetCall?.fillArrayAndIndexArguments(irArrayValue, irIndexValues)
val irLValue = LValueWithGetterAndSetterCalls(callGenerator, indexedGetCall, indexedSetCall, type, startOffset, endOffset, origin) val irLValue = LValueWithGetterAndSetterCalls(
callGenerator,
indexedGetCall, indexedSetCall,
callGenerator.translateType(kotlinType),
startOffset, endOffset, origin
)
irBlock.inlineStatement(withLValue(irLValue)) irBlock.inlineStatement(withLValue(irLValue))
return irBlock return irBlock
@@ -16,26 +16,30 @@
package org.jetbrains.kotlin.psi2ir.intermediate package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.builders.IrGeneratorContext
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
class BackingFieldLValue( class BackingFieldLValue(
val startOffset: Int, private val context: IrGeneratorContext,
val endOffset: Int, private val startOffset: Int,
override val type: KotlinType, private val endOffset: Int,
val symbol: IrFieldSymbol, override val type: IrType,
val receiver: IntermediateValue?, private val symbol: IrFieldSymbol,
val origin: IrStatementOrigin? private val receiver: IntermediateValue?,
private val origin: IrStatementOrigin?
) : LValue, AssignmentReceiver { ) : LValue, AssignmentReceiver {
override fun store(irExpression: IrExpression): IrExpression = override fun store(irExpression: IrExpression): IrExpression =
IrSetFieldImpl(startOffset, endOffset, symbol, receiver?.load(), irExpression, origin) IrSetFieldImpl(startOffset, endOffset, symbol, receiver?.load(), irExpression, context.irBuiltIns.unitType, origin)
override fun load(): IrExpression = override fun load(): IrExpression =
IrGetFieldImpl(startOffset, endOffset, symbol, receiver?.load(), origin) IrGetFieldImpl(startOffset, endOffset, symbol, type, receiver?.load(), origin)
override fun assign(withLValue: (LValue) -> IrExpression): IrExpression = override fun assign(withLValue: (LValue) -> IrExpression): IrExpression =
withLValue(this) withLValue(this)
@@ -16,25 +16,31 @@
package org.jetbrains.kotlin.psi2ir.intermediate package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.builders.IrGeneratorContext
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
class DelegatedLocalPropertyLValue( class DelegatedLocalPropertyLValue(
private val context: IrGeneratorContext,
val startOffset: Int, val startOffset: Int,
val endOffset: Int, val endOffset: Int,
override val type: KotlinType, override val type: IrType,
val getterSymbol: IrSimpleFunctionSymbol?, private val getterSymbol: IrSimpleFunctionSymbol?,
val setterSymbol: IrSimpleFunctionSymbol?, private val setterSymbol: IrSimpleFunctionSymbol?,
val origin: IrStatementOrigin? = null val origin: IrStatementOrigin? = null
) : LValue, AssignmentReceiver { ) :
LValue,
AssignmentReceiver {
override fun load(): IrExpression = override fun load(): IrExpression =
IrCallImpl(startOffset, endOffset, type, getterSymbol!!, getterSymbol.descriptor, null, origin) IrCallImpl(startOffset, endOffset, type, getterSymbol!!, getterSymbol.descriptor, origin)
override fun store(irExpression: IrExpression): IrExpression = override fun store(irExpression: IrExpression): IrExpression =
IrCallImpl(startOffset, endOffset, type, setterSymbol!!, setterSymbol.descriptor, null, origin).apply { IrCallImpl(startOffset, endOffset, context.irBuiltIns.unitType, setterSymbol!!, setterSymbol.descriptor, origin).apply {
putValueArgument(0, irExpression) putValueArgument(0, irExpression)
} }
@@ -19,10 +19,11 @@ package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
class ExtensionInvokeCallReceiver( class ExtensionInvokeCallReceiver(
val callBuilder: CallBuilder, private val callBuilder: CallBuilder,
val functionReceiver: IntermediateValue, private val functionReceiver: IntermediateValue,
val extensionInvokeReceiver: IntermediateValue private val extensionInvokeReceiver: IntermediateValue
) : CallReceiver { ) : CallReceiver {
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression { override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
// extensionInvokeReceiver is actually a first argument: // extensionInvokeReceiver is actually a first argument:
// receiver.extFun(p1, ..., pN) // receiver.extFun(p1, ..., pN)
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.psi2ir.generators.CallGenerator import org.jetbrains.kotlin.psi2ir.generators.CallGenerator
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -26,11 +27,12 @@ class LValueWithGetterAndSetterCalls(
val callGenerator: CallGenerator, val callGenerator: CallGenerator,
val getterCall: CallBuilder?, val getterCall: CallBuilder?,
val setterCall: CallBuilder?, val setterCall: CallBuilder?,
override val type: KotlinType, override val type: IrType,
val startOffset: Int, val startOffset: Int,
val endOffset: Int, val endOffset: Int,
val origin: IrStatementOrigin? = null val origin: IrStatementOrigin? = null
) : LValue { ) : LValue {
private val descriptor: CallableDescriptor = private val descriptor: CallableDescriptor =
getterCall?.descriptor ?: setterCall?.descriptor getterCall?.descriptor ?: setterCall?.descriptor
?: throw AssertionError("Call-based LValue should have either a getter or a setter call") ?: throw AssertionError("Call-based LValue should have either a getter or a setter call")
@@ -17,22 +17,24 @@
package org.jetbrains.kotlin.psi2ir.intermediate package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.ir.builders.IrGeneratorContext
import org.jetbrains.kotlin.ir.builders.Scope import org.jetbrains.kotlin.ir.builders.Scope
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.ir.types.IrType
abstract class PropertyLValueBase( abstract class PropertyLValueBase(
protected val context: IrGeneratorContext,
val scope: Scope, val scope: Scope,
val startOffset: Int, val startOffset: Int,
val endOffset: Int, val endOffset: Int,
val origin: IrStatementOrigin?, val origin: IrStatementOrigin?,
override val type: KotlinType, override val type: IrType,
val callReceiver: CallReceiver, val callReceiver: CallReceiver,
val superQualifier: IrClassSymbol? val superQualifier: IrClassSymbol?
) : LValue, AssignmentReceiver { ) : LValue, AssignmentReceiver {
@@ -64,20 +66,25 @@ abstract class PropertyLValueBase(
} }
class FieldPropertyLValue( class FieldPropertyLValue(
context: IrGeneratorContext,
scope: Scope, scope: Scope,
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
origin: IrStatementOrigin?, origin: IrStatementOrigin?,
val field: IrFieldSymbol, val field: IrFieldSymbol,
type: IrType,
callReceiver: CallReceiver, callReceiver: CallReceiver,
superQualifier: IrClassSymbol? superQualifier: IrClassSymbol?
) : PropertyLValueBase(scope, startOffset, endOffset, origin, field.descriptor.type, callReceiver, superQualifier) { ) :
PropertyLValueBase(context, scope, startOffset, endOffset, origin, type, callReceiver, superQualifier) {
override fun load(): IrExpression = override fun load(): IrExpression =
callReceiver.call { dispatchReceiverValue, extensionReceiverValue -> callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
assert(extensionReceiverValue == null) { "Field can't have an extension receiver: ${field.descriptor}" } assert(extensionReceiverValue == null) { "Field can't have an extension receiver: ${field.descriptor}" }
IrGetFieldImpl( IrGetFieldImpl(
startOffset, endOffset, startOffset, endOffset,
field, field,
type,
dispatchReceiverValue?.load(), dispatchReceiverValue?.load(),
origin, origin,
superQualifier superQualifier
@@ -92,6 +99,7 @@ class FieldPropertyLValue(
field, field,
dispatchReceiverValue?.load(), dispatchReceiverValue?.load(),
irExpression, irExpression,
context.irBuiltIns.unitType,
origin, origin,
superQualifier superQualifier
) )
@@ -99,57 +107,76 @@ class FieldPropertyLValue(
override fun withReceiver(dispatchReceiver: VariableLValue?, extensionReceiver: VariableLValue?): PropertyLValueBase = override fun withReceiver(dispatchReceiver: VariableLValue?, extensionReceiver: VariableLValue?): PropertyLValueBase =
FieldPropertyLValue( FieldPropertyLValue(
context,
scope, startOffset, endOffset, origin, scope, startOffset, endOffset, origin,
field, field,
type,
SimpleCallReceiver(dispatchReceiver, extensionReceiver), SimpleCallReceiver(dispatchReceiver, extensionReceiver),
superQualifier superQualifier
) )
} }
class AccessorPropertyLValue( class AccessorPropertyLValue(
context: IrGeneratorContext,
scope: Scope, scope: Scope,
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
origin: IrStatementOrigin?, origin: IrStatementOrigin?,
type: KotlinType, type: IrType,
val getter: IrFunctionSymbol?, val getter: IrFunctionSymbol?,
val getterDescriptor: FunctionDescriptor?, val getterDescriptor: FunctionDescriptor?,
val setter: IrFunctionSymbol?, val setter: IrFunctionSymbol?,
val setterDescriptor: FunctionDescriptor?, val setterDescriptor: FunctionDescriptor?,
val typeArguments: Map<TypeParameterDescriptor, KotlinType>?, val typeArguments: List<IrType>?,
callReceiver: CallReceiver, callReceiver: CallReceiver,
superQualifier: IrClassSymbol? superQualifier: IrClassSymbol?
) : PropertyLValueBase(scope, startOffset, endOffset, origin, type, callReceiver, superQualifier) { ) : PropertyLValueBase(context, scope, startOffset, endOffset, origin, type, callReceiver, superQualifier) {
private val typeArgumentsCount = typeArguments?.size ?: 0
private fun IrMemberAccessExpression.putTypeArguments() {
typeArguments?.forEachIndexed { index, irType ->
putTypeArgument(index, irType)
}
}
override fun load(): IrExpression = override fun load(): IrExpression =
callReceiver.call { dispatchReceiverValue, extensionReceiverValue -> callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
IrGetterCallImpl( IrGetterCallImpl(
startOffset, endOffset, startOffset, endOffset,
type,
getter!!, getterDescriptor!!, getter!!, getterDescriptor!!,
typeArguments, typeArgumentsCount,
dispatchReceiverValue?.load(), dispatchReceiverValue?.load(),
extensionReceiverValue?.load(), extensionReceiverValue?.load(),
origin, origin,
superQualifier superQualifier
) ).apply {
putTypeArguments()
}
} }
override fun store(irExpression: IrExpression) = override fun store(irExpression: IrExpression) =
callReceiver.call { dispatchReceiverValue, extensionReceiverValue -> callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
IrSetterCallImpl( IrSetterCallImpl(
startOffset, endOffset, startOffset, endOffset,
context.irBuiltIns.unitType,
setter!!, setterDescriptor!!, setter!!, setterDescriptor!!,
typeArguments, typeArgumentsCount,
dispatchReceiverValue?.load(), dispatchReceiverValue?.load(),
extensionReceiverValue?.load(), extensionReceiverValue?.load(),
irExpression, irExpression,
origin, origin,
superQualifier superQualifier
) ).apply {
putTypeArguments()
}
} }
override fun withReceiver(dispatchReceiver: VariableLValue?, extensionReceiver: VariableLValue?): PropertyLValueBase = override fun withReceiver(dispatchReceiver: VariableLValue?, extensionReceiver: VariableLValue?): PropertyLValueBase =
AccessorPropertyLValue( AccessorPropertyLValue(
scope, startOffset, endOffset, origin, context, scope,
startOffset, endOffset, origin,
type, getter, getterDescriptor, setter, setterDescriptor, type, getter, getterDescriptor, setter, setterDescriptor,
typeArguments, typeArguments,
SimpleCallReceiver(dispatchReceiver, extensionReceiver), SimpleCallReceiver(dispatchReceiver, extensionReceiver),
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
class RematerializableValue(val irExpression: IrExpressionWithCopy) : IntermediateValue { class RematerializableValue(val irExpression: IrExpressionWithCopy) : IntermediateValue {
override val type: IrType get() = irExpression.type override val type: IrType get() = irExpression.type
override fun load(): IrExpression = irExpression.copy() override fun load(): IrExpression = irExpression.copy()
@@ -16,12 +16,12 @@
package org.jetbrains.kotlin.psi2ir.intermediate package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.builders.constNull import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.equalsNull
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrIfThenElseImpl import org.jetbrains.kotlin.ir.expressions.impl.IrIfThenElseImpl
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.psi2ir.generators.GeneratorWithScope import org.jetbrains.kotlin.psi2ir.generators.GeneratorWithScope
import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.types.typeUtil.makeNullable import org.jetbrains.kotlin.types.typeUtil.makeNullable
@@ -35,6 +35,7 @@ class SafeCallReceiver(
val dispatchReceiver: IntermediateValue?, val dispatchReceiver: IntermediateValue?,
val isAssignmentReceiver: Boolean val isAssignmentReceiver: Boolean
) : CallReceiver { ) : CallReceiver {
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression { override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
val irTmp = generator.scope.createTemporaryVariable(extensionReceiver?.load() ?: dispatchReceiver!!.load(), "safe_receiver") val irTmp = generator.scope.createTemporaryVariable(extensionReceiver?.load() ?: dispatchReceiver!!.load(), "safe_receiver")
val safeReceiverValue = VariableLValue(irTmp) val safeReceiverValue = VariableLValue(irTmp)
@@ -50,19 +51,17 @@ class SafeCallReceiver(
} }
val irResult = withDispatchAndExtensionReceivers(dispatchReceiverValue, extensionReceiverValue) val irResult = withDispatchAndExtensionReceivers(dispatchReceiverValue, extensionReceiverValue)
val resultType = if (isAssignmentReceiver) irResult.type.builtIns.unitType else irResult.type.makeNullable()
val resultType = if (isAssignmentReceiver) generator.context.irBuiltIns.unitType else irResult.type.makeNullable()
val irBlock = IrBlockImpl(startOffset, endOffset, resultType, IrStatementOrigin.SAFE_CALL) val irBlock = IrBlockImpl(startOffset, endOffset, resultType, IrStatementOrigin.SAFE_CALL)
irBlock.statements.add(irTmp) irBlock.statements.add(irTmp)
val irIfThenElse = IrIfThenElseImpl( val irIfThenElse =
startOffset, endOffset, resultType, generator.buildStatement(startOffset, endOffset, IrStatementOrigin.SAFE_CALL) {
generator.context.equalsNull(startOffset, endOffset, safeReceiverValue.load()), irIfNull(resultType, safeReceiverValue.load(), irNull(), irResult)
generator.context.constNull(startOffset, endOffset), }
irResult,
IrStatementOrigin.SAFE_CALL
)
irBlock.statements.add(irIfThenElse) irBlock.statements.add(irIfThenElse)
return irBlock return irBlock
@@ -16,14 +16,13 @@
package org.jetbrains.kotlin.psi2ir.intermediate package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.builders.constNull import org.jetbrains.kotlin.ir.builders.irBlock
import org.jetbrains.kotlin.ir.builders.equalsNull import org.jetbrains.kotlin.ir.builders.irIfNull
import org.jetbrains.kotlin.ir.builders.irNull
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.expressions.impl.IrIfThenElseImpl
import org.jetbrains.kotlin.psi2ir.generators.GeneratorWithScope import org.jetbrains.kotlin.psi2ir.generators.GeneratorWithScope
import org.jetbrains.kotlin.types.typeUtil.makeNullable
class SafeExtensionInvokeCallReceiver( class SafeExtensionInvokeCallReceiver(
val generator: GeneratorWithScope, val generator: GeneratorWithScope,
@@ -33,6 +32,7 @@ class SafeExtensionInvokeCallReceiver(
val functionReceiver: IntermediateValue, val functionReceiver: IntermediateValue,
val extensionInvokeReceiver: IntermediateValue val extensionInvokeReceiver: IntermediateValue
) : CallReceiver { ) : CallReceiver {
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression { override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
// extensionInvokeReceiver is actually a first argument: // extensionInvokeReceiver is actually a first argument:
// receiver?.extFun(p1, ..., pN) // receiver?.extFun(p1, ..., pN)
@@ -53,19 +53,14 @@ class SafeExtensionInvokeCallReceiver(
val resultType = irResult.type.makeNullable() val resultType = irResult.type.makeNullable()
return IrBlockImpl( return generator.irBlock(startOffset, endOffset, IrStatementOrigin.SAFE_CALL, resultType) {
startOffset, endOffset, resultType, IrStatementOrigin.SAFE_CALL, +irTmp
arrayListOf( +irIfNull(
irTmp, resultType,
IrIfThenElseImpl( safeReceiverValue.load(), irNull(),
startOffset, endOffset, resultType, irResult
generator.context.equalsNull(startOffset, endOffset, safeReceiverValue.load()),
generator.context.constNull(startOffset, endOffset),
irResult,
IrStatementOrigin.SAFE_CALL
)
) )
) }
} }
} }
@@ -19,9 +19,10 @@ package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
class SimpleCallReceiver( class SimpleCallReceiver(
val dispatchReceiverValue: IntermediateValue?, private val dispatchReceiverValue: IntermediateValue?,
val extensionReceiverValue: IntermediateValue? private val extensionReceiverValue: IntermediateValue?
) : CallReceiver { ) : CallReceiver {
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression { override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
return withDispatchAndExtensionReceivers(dispatchReceiverValue, extensionReceiverValue) return withDispatchAndExtensionReceivers(dispatchReceiverValue, extensionReceiverValue)
} }
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
class TransientReceiverValue(override val type: IrType) : IntermediateValue { class TransientReceiverValue(override val type: IrType) : IntermediateValue {
override fun load(): IrExpression { override fun load(): IrExpression {
throw AssertionError("Transient receiver should not be instantiated") throw AssertionError("Transient receiver should not be instantiated")
} }
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.psi2ir.intermediate package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.builders.IrGeneratorContext
import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
@@ -23,27 +24,31 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrSetVariableImpl import org.jetbrains.kotlin.ir.expressions.impl.IrSetVariableImpl
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
class VariableLValue( class VariableLValue(
private val context: IrGeneratorContext,
val startOffset: Int, val startOffset: Int,
val endOffset: Int, val endOffset: Int,
val symbol: IrValueSymbol, val symbol: IrValueSymbol,
override val type: IrType,
val origin: IrStatementOrigin? = null val origin: IrStatementOrigin? = null
) : LValue, AssignmentReceiver { ) :
constructor(irVariable: IrVariable, origin: IrStatementOrigin? = null) : this( LValue,
irVariable.startOffset, irVariable.endOffset, irVariable.symbol, origin AssignmentReceiver {
)
override val type: KotlinType get() = symbol.descriptor.type constructor(context: IrGeneratorContext, irVariable: IrVariable, origin: IrStatementOrigin? = null) :
this(context, irVariable.startOffset, irVariable.endOffset, irVariable.symbol, irVariable.type, origin)
override fun load(): IrExpression = override fun load(): IrExpression =
IrGetValueImpl(startOffset, endOffset, symbol, origin) IrGetValueImpl(startOffset, endOffset, type, symbol, origin)
override fun store(irExpression: IrExpression): IrExpression = override fun store(irExpression: IrExpression): IrExpression =
IrSetVariableImpl( IrSetVariableImpl(
startOffset, endOffset, startOffset, endOffset,
context.irBuiltIns.unitType,
symbol.assertedCast<IrVariableSymbol> { "Not a variable: ${symbol.descriptor}" }, symbol.assertedCast<IrVariableSymbol> { "Not a variable: ${symbol.descriptor}" },
irExpression, origin irExpression, origin
) )
@@ -22,6 +22,8 @@ import org.jetbrains.kotlin.ir.expressions.IrWhen
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
// TODO rewrite using IR Builders
fun primitiveOp1( fun primitiveOp1(
startOffset: Int, endOffset: Int, startOffset: Int, endOffset: Int,
primitiveOpSymbol: IrSimpleFunctionSymbol, primitiveOpSymbol: IrSimpleFunctionSymbol,
@@ -38,3 +38,15 @@ fun IrType.makeNotNull() =
) )
else else
this this
fun IrType.makeNullable() =
if (this is IrSimpleType && !this.hasQuestionMark)
IrSimpleTypeImpl(
classifier,
true,
arguments,
annotations,
Variance.INVARIANT
)
else
this