From 5f4f6ef8639fb447a9c4a97ba0b8127cdeea8c32 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Mon, 14 May 2018 12:40:56 +0300 Subject: [PATCH] IrTypes in psi2ir (work in progress) --- .../psi2ir/generators/AssignmentGenerator.kt | 1 + .../BranchingExpressionGenerator.kt | 12 +-- .../generators/DataClassMembersGenerator.kt | 71 ++++++++++++---- .../generators/DelegatedPropertyGenerator.kt | 33 +++++--- .../psi2ir/generators/FunctionGenerator.kt | 27 ++++-- .../generators/OperatorExpressionGenerator.kt | 82 +++++++++++++------ .../kotlin/ir/builders/ExpressionHelpers.kt | 33 ++++++-- .../jetbrains/kotlin/ir/builders/IrBuilder.kt | 28 +++++++ .../expressions/IrMemberAccessExpression.kt | 27 +++--- .../ir/expressions/impl/IrIfThenElseImpl.kt | 15 ---- .../kotlin/ir/expressions/impl/IrWhenImpl.kt | 7 +- .../org/jetbrains/kotlin/ir/types/irTypes.kt | 13 +++ 12 files changed, 250 insertions(+), 99 deletions(-) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt index 73757c7f3dc..735d4c4ad3f 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ThisClassReceiver import org.jetbrains.kotlin.types.KotlinType class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) { + fun generateAssignment(ktExpression: KtBinaryExpression): IrExpression { val ktLeft = ktExpression.left!! val irRhs = ktExpression.right!!.genExpr() diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt index 0607719cf81..c7c246bd01c 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt @@ -18,6 +18,8 @@ package org.jetbrains.kotlin.psi2ir.generators import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.builders.buildStatement +import org.jetbrains.kotlin.ir.builders.irIfThenMaybeElse import org.jetbrains.kotlin.ir.builders.whenComma import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.* @@ -27,13 +29,13 @@ import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset -import org.jetbrains.kotlin.psi2ir.intermediate.defaultLoad import org.jetbrains.kotlin.psi2ir.deparenthesize import org.jetbrains.kotlin.psi2ir.intermediate.defaultLoad import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.utils.SmartList class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) { + fun generateIfExpression(expression: KtIfExpression): IrExpression { val resultType = getInferredTypeWithImplicitCastsOrFail(expression).toIrType() @@ -68,10 +70,10 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta resultType: IrType ): IrWhen { if (irBranches.size == 1) { - return IrIfThenElseImpl( - ktIf.startOffset, ktIf.endOffset, resultType, - irBranches[0].condition, irBranches[0].result, irElseResult - ) + val irBranch0 = irBranches[0] + return buildStatement(ktIf.startOffset, ktIf.endOffset) { + irIfThenMaybeElse(resultType, irBranch0.condition, irBranch0.result, irElseResult) + } } val irWhen = IrWhenImpl(ktIf.startOffset, ktIf.endOffset, resultType, IrStatementOrigin.WHEN) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DataClassMembersGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DataClassMembersGenerator.kt index edd6ed458dd..fa08e1a98d9 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DataClassMembersGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DataClassMembersGenerator.kt @@ -28,6 +28,8 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.putDefault import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl +import org.jetbrains.kotlin.ir.expressions.mapTypeParameters +import org.jetbrains.kotlin.ir.expressions.mapValueParameters import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.util.declareSimpleFunctionWithOverrides import org.jetbrains.kotlin.psi.KtClassOrObject @@ -143,24 +145,29 @@ class DataClassMembersGenerator( +irReturn( irCall( constructorSymbol, - dataClassConstructor.returnType.toIrType(), - dataClassConstructor.typeParameters.associate { it to it.defaultType } + dataClassConstructor.returnType.toIrType() ).apply { + mapTypeParameters { it.defaultType.toIrType() } mapValueParameters { - irGet(irFunction.valueParameters[it.index].symbol) + val irValueParameter = irFunction.valueParameters[it.index] + irGet(irValueParameter.type, irValueParameter.symbol) } } + ) } } override fun generateEqualsMethod(function: FunctionDescriptor, properties: List) { buildMember(function, declaration) { + val irType = classDescriptor.defaultType.toIrType() + +irIfThenReturnTrue(irEqeqeq(irThis(), irOther())) - +irIfThenReturnFalse(irNotIs(irOther(), classDescriptor.defaultType, irClass.symbol)) - val otherWithCast = irTemporary(irImplicitCast(irOther(), classDescriptor.defaultType, irClass.symbol), "other_with_cast") + +irIfThenReturnFalse(irNotIs(irOther(), irType)) + val otherWithCast = irTemporary(irAs(irOther(), irType), "other_with_cast") for (property in properties) { - val arg1 = irGet(irThis(), getPropertyGetterSymbol(property)) - val arg2 = irGet(irGet(otherWithCast.symbol), getPropertyGetterSymbol(property)) + val irPropertyType = property.type.toIrType() + val arg1 = irGet(irPropertyType, irThis(), getPropertyGetterSymbol(property)) + val arg2 = irGet(irPropertyType, irGet(irPropertyType, otherWithCast.symbol), getPropertyGetterSymbol(property)) +irIfThenReturnFalse(irNotEquals(arg1, arg2)) } +irReturnTrue() @@ -199,34 +206,58 @@ class DataClassMembersGenerator( override fun generateHashCodeMethod(function: FunctionDescriptor, properties: List) { buildMember(function, declaration) { + val irIntType = context.irBuiltIns.intType val result = irTemporaryVar(irInt(0), "result").symbol var first = true for (property in properties) { val hashCodeOfProperty = getHashCodeOfProperty(irThis(), property) val irNewValue = if (first) hashCodeOfProperty - else irCallOp(intPlus, irCallOp(intTimes, irGet(result), irInt(31)), hashCodeOfProperty) + else + irCallOp( + intPlus, + irIntType, + irCallOp( + intTimes, irIntType, irGet(irIntType, result), irInt(31) + ), + hashCodeOfProperty + ) +irSetVar(result, irNewValue) first = false } - +irReturn(irGet(result)) + +irReturn(irGet(irIntType, result)) } } private fun MemberFunctionBuilder.getHashCodeOfProperty(receiver: IrExpression, property: PropertyDescriptor): IrExpression { val getterSymbol = getPropertyGetterSymbol(property) + val propertyType = property.type + val irPropertyType = propertyType.toIrType() return when { - property.type.containsNull() -> - irLetS(irGet(receiver, getterSymbol)) { variable -> - irIfNull(context.builtIns.intType, irGet(variable), irInt(0), getHashCodeOf(irGet(variable))) + propertyType.containsNull() -> + irLetS( + irGet(irPropertyType, receiver, getterSymbol) + ) { variable -> + irIfNull( + context.irBuiltIns.intType, + irGet(irPropertyType, variable), + irInt(0), + getHashCodeOf( + propertyType, + irGet(irPropertyType, variable) + ) + ) } else -> - getHashCodeOf(irGet(receiver, getterSymbol)) + getHashCodeOf( + propertyType, + irGet(irPropertyType, receiver, getterSymbol) + ) } } - private fun MemberFunctionBuilder.getHashCodeOf(irValue: IrExpression): IrExpression { - val hashCodeFunctionDescriptor = getHashCodeFunction(irValue.type) + private fun MemberFunctionBuilder.getHashCodeOf(kotlinType: KotlinType, irValue: IrExpression): IrExpression { + val hashCodeFunctionDescriptor = getHashCodeFunction(kotlinType) val hashCodeFunctionSymbol = declarationGenerator.context.symbolTable.referenceFunction(hashCodeFunctionDescriptor.original) return irCall(hashCodeFunctionSymbol, hashCodeFunctionDescriptor).apply { if (descriptor.dispatchReceiverParameter != null) { @@ -243,19 +274,25 @@ class DataClassMembersGenerator( irConcat.addArgument(irString(classDescriptor.name.asString() + "(")) var first = true for (property in properties) { + val irPropertyType = property.type.toIrType() + if (!first) irConcat.addArgument(irString(", ")) + irConcat.addArgument(irString(property.name.asString() + "=")) - val irPropertyValue = irGet(irThis(), getPropertyGetterSymbol(property)) + + val irPropertyValue = irGet(irPropertyType, irThis(), getPropertyGetterSymbol(property)) + val typeConstructorDescriptor = property.type.constructor.declarationDescriptor val irPropertyStringValue = if (typeConstructorDescriptor is ClassDescriptor && KotlinBuiltIns.isArrayOrPrimitiveArray(typeConstructorDescriptor) ) - irCall(context.irBuiltIns.dataClassArrayMemberToStringSymbol).apply { + irCall(context.irBuiltIns.dataClassArrayMemberToStringSymbol, context.irBuiltIns.stringType).apply { putValueArgument(0, irPropertyValue) } else irPropertyValue + irConcat.addArgument(irPropertyStringValue) first = false } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt index 22bc30e1588..21ab3274d12 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.psi2ir.generators import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.ir.builders.irBlockBody import org.jetbrains.kotlin.ir.builders.irGet import org.jetbrains.kotlin.ir.builders.irReturn import org.jetbrains.kotlin.ir.declarations.* @@ -55,8 +56,10 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D val kPropertyType = getKPropertyTypeForDelegatedProperty(propertyDescriptor) val irProperty = IrPropertyImpl( - ktProperty.startOffset, ktProperty.endOffset, IrDeclarationOrigin.DEFINED, true, - propertyDescriptor + ktProperty.startOffset, ktProperty.endOffset, IrDeclarationOrigin.DEFINED, + isDelegated = true, + descriptor = propertyDescriptor, + type = propertyDescriptor.type.toIrType() ).apply { backingField = generateDelegateFieldForProperty(propertyDescriptor, kPropertyType, ktDelegate) } @@ -171,10 +174,12 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D private fun createThisValueForDelegate(thisClass: ClassDescriptor?, ktDelegate: KtPropertyDelegate): IntermediateValue? = thisClass?.let { - generateExpressionValue(it.thisAsReceiverParameter.type) { + generateExpressionValue(it.thisAsReceiverParameter.type.toIrType()) { + val thisAsReceiverParameter = thisClass.thisAsReceiverParameter IrGetValueImpl( ktDelegate.startOffset, ktDelegate.endOffset, - context.symbolTable.referenceValueParameter(thisClass.thisAsReceiverParameter) + thisAsReceiverParameter.type.toIrType(), + context.symbolTable.referenceValueParameter(thisAsReceiverParameter) ) } } @@ -225,7 +230,8 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D val irLocalDelegatedProperty = IrLocalDelegatedPropertyImpl( ktProperty.startOffset, ktProperty.endOffset, IrDeclarationOrigin.DEFINED, - variableDescriptor + variableDescriptor, + variableDescriptor.type.toIrType() ).apply { delegate = generateDelegateVariableForLocalDelegatedProperty(ktDelegate, variableDescriptor, kPropertyType, scopeOwnerSymbol) } @@ -363,7 +369,9 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D irPropertyReference: IrCallableReference ): IrBody = with(createBodyGenerator(irGetter.symbol)) { - irBlockBody(ktDelegate) { + val startOffset = ktDelegate.startOffset + val endOffset = ktDelegate.endOffset + irBlockBody(startOffset, endOffset) { val statementGenerator = createStatementGenerator() val conventionMethodResolvedCall = getOrFail(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor) val conventionMethodCall = statementGenerator.pregenerateCall(conventionMethodResolvedCall) @@ -371,8 +379,8 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D conventionMethodCall.irValueArgumentsByIndex[1] = irPropertyReference +irReturn( CallGenerator(statementGenerator).generateCall( - ktDelegate.startOffset, - ktDelegate.endOffset, + startOffset, + endOffset, conventionMethodCall ) ) @@ -386,14 +394,17 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D delegateReceiverValue: IntermediateValue, irPropertyReference: IrCallableReference ): IrBody = with(createBodyGenerator(irSetter.symbol)) { - irBlockBody(ktDelegate) { + val startOffset = ktDelegate.startOffset + val endOffset = ktDelegate.endOffset + irBlockBody(startOffset, endOffset) { val statementGenerator = createStatementGenerator() val conventionMethodResolvedCall = getOrFail(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, setterDescriptor) val conventionMethodCall = statementGenerator.pregenerateCall(conventionMethodResolvedCall) conventionMethodCall.setExplicitReceiverValue(delegateReceiverValue) conventionMethodCall.irValueArgumentsByIndex[1] = irPropertyReference - conventionMethodCall.irValueArgumentsByIndex[2] = irGet(irSetter.valueParameters[0].symbol) - +irReturn(CallGenerator(statementGenerator).generateCall(ktDelegate.startOffset, ktDelegate.endOffset, conventionMethodCall)) + val irSetterParameter = irSetter.valueParameters[0] + conventionMethodCall.irValueArgumentsByIndex[2] = irGet(irSetterParameter.type, irSetterParameter.symbol) + +irReturn(CallGenerator(statementGenerator).generateCall(startOffset, endOffset, conventionMethodCall)) } } } \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt index b51e13fba28..c49db1794a4 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt @@ -142,17 +142,20 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio ): IrBlockBody { val property = getter.correspondingProperty - val irBody = IrBlockBodyImpl(ktProperty.startOffset, ktProperty.endOffset) + val startOffset = ktProperty.startOffset + val endOffset = ktProperty.endOffset + val irBody = IrBlockBodyImpl(startOffset, endOffset) val receiver = generateReceiverExpressionForDefaultPropertyAccessor(ktProperty, property) irBody.statements.add( IrReturnImpl( - ktProperty.startOffset, ktProperty.endOffset, context.builtIns.nothingType, + startOffset, endOffset, context.irBuiltIns.nothingType, irAccessor.symbol, IrGetFieldImpl( - ktProperty.startOffset, ktProperty.endOffset, + startOffset, endOffset, context.symbolTable.referenceField(property), + property.type.toIrType(), receiver ) ) @@ -167,17 +170,20 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio ): IrBlockBody { val property = setter.correspondingProperty - val irBody = IrBlockBodyImpl(ktProperty.startOffset, ktProperty.endOffset) + val startOffset = ktProperty.startOffset + val endOffset = ktProperty.endOffset + val irBody = IrBlockBodyImpl(startOffset, endOffset) val receiver = generateReceiverExpressionForDefaultPropertyAccessor(ktProperty, property) - val setterParameter = irAccessor.valueParameters.single().symbol + val irValueParameter = irAccessor.valueParameters.single() irBody.statements.add( IrSetFieldImpl( - ktProperty.startOffset, ktProperty.endOffset, + startOffset, endOffset, context.symbolTable.referenceField(property), receiver, - IrGetValueImpl(ktProperty.startOffset, ktProperty.endOffset, setterParameter) + IrGetValueImpl(startOffset, endOffset, irValueParameter.type, irValueParameter.symbol), + context.irBuiltIns.unitType ) ) return irBody @@ -186,11 +192,14 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio private fun generateReceiverExpressionForDefaultPropertyAccessor(ktProperty: KtElement, property: PropertyDescriptor): IrExpression? { val containingDeclaration = property.containingDeclaration return when (containingDeclaration) { - is ClassDescriptor -> + is ClassDescriptor -> { + val thisAsReceiverParameter = containingDeclaration.thisAsReceiverParameter IrGetValueImpl( ktProperty.startOffset, ktProperty.endOffset, - context.symbolTable.referenceValue(containingDeclaration.thisAsReceiverParameter) + thisAsReceiverParameter.type.toIrType(), + context.symbolTable.referenceValue(thisAsReceiverParameter) ) + } else -> null } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt index 2987dbe9fa5..7a5bc764132 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.IrTypeOperator import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.makeNotNull import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* @@ -46,6 +47,14 @@ import java.lang.AssertionError class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) { + private fun createErrorExpression(ktExpression: KtExpression, text: String) = + IrErrorExpressionImpl( + ktExpression.startOffset, + ktExpression.endOffset, + context.irBuiltIns.nothingType, + text + ) + fun generatePrefixExpression(expression: KtPrefixExpression): IrExpression { val ktOperator = expression.operationReference.getReferencedNameElementType() val irOperator = getPrefixOperator(ktOperator) @@ -57,7 +66,7 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat irOperator ) in OPERATORS_DESUGARED_TO_CALLS -> generatePrefixOperatorAsCall(expression, irOperator) - else -> createDummyExpression(expression, ktOperator.toString()) + else -> createErrorExpression(expression, ktOperator.toString()) } } @@ -72,7 +81,7 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat irOperator ) IrStatementOrigin.EXCLEXCL -> generateExclExclOperator(expression, irOperator) - else -> createDummyExpression(expression, ktOperator.toString()) + else -> createErrorExpression(expression, ktOperator.toString()) } } @@ -91,7 +100,7 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat } return IrTypeOperatorCallImpl( - expression.startOffset, expression.endOffset, resultType, irOperator, rhsType, + expression.startOffset, expression.endOffset, resultType.toIrType(), irOperator, rhsType.toIrType(), context.symbolTable.referenceClassifier(rhsType.constructor.declarationDescriptor!!), expression.left.genExpr() ) @@ -103,8 +112,9 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat val againstType = getOrFail(BindingContext.TYPE, expression.typeReference) return IrTypeOperatorCallImpl( - expression.startOffset, expression.endOffset, context.builtIns.booleanType, irOperator, - againstType, context.symbolTable.referenceClassifier(againstType.constructor.declarationDescriptor!!), + expression.startOffset, expression.endOffset, context.irBuiltIns.booleanType, irOperator, + againstType.toIrType(), + context.symbolTable.referenceClassifier(againstType.constructor.declarationDescriptor!!), expression.leftHandSide.genExpr() ) } @@ -128,19 +138,24 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat in IDENTITY_OPERATORS -> generateIdentityOperator(expression, irOperator) in IN_OPERATORS -> generateInOperator(expression, irOperator) in BINARY_BOOLEAN_OPERATORS -> generateBinaryBooleanOperator(expression, irOperator) - else -> createDummyExpression(expression, ktOperator.toString()) + else -> createErrorExpression(expression, ktOperator.toString()) } } private fun generateElvis(expression: KtBinaryExpression): IrExpression { val specialCallForElvis = getResolvedCall(expression)!! - val resultType = specialCallForElvis.resultingDescriptor.returnType!! + val resultType = specialCallForElvis.resultingDescriptor.returnType!!.toIrType() val irArgument0 = expression.left!!.genExpr() val irArgument1 = expression.right!!.genExpr() - return irBlock(expression, IrStatementOrigin.ELVIS, resultType) { + return irBlock(expression.startOffset, expression.endOffset, IrStatementOrigin.ELVIS, resultType) { val temporary = irTemporary(irArgument0, "elvis_lhs") - +irIfNull(resultType, irGet(temporary.symbol), irArgument1, irGet(temporary.symbol)) + +irIfNull( + resultType, + irGet(temporary.type, temporary.symbol), + irArgument1, + irGet(temporary.type, temporary.symbol) + ) } } @@ -167,7 +182,9 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat irContainsCall IrStatementOrigin.NOT_IN -> IrUnaryPrimitiveImpl( - expression.startOffset, expression.endOffset, IrStatementOrigin.NOT_IN, + expression.startOffset, expression.endOffset, + context.irBuiltIns.booleanType, + IrStatementOrigin.NOT_IN, context.irBuiltIns.booleanNotSymbol, irContainsCall ) @@ -182,7 +199,9 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat val irArgument1 = expression.right!!.genExpr() val irIdentityEquals = IrBinaryPrimitiveImpl( - expression.startOffset, expression.endOffset, irOperator, + expression.startOffset, expression.endOffset, + context.irBuiltIns.booleanType, + irOperator, context.irBuiltIns.eqeqeqSymbol, irArgument0, irArgument1 ) @@ -192,7 +211,9 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat irIdentityEquals IrStatementOrigin.EXCLEQEQ -> IrUnaryPrimitiveImpl( - expression.startOffset, expression.endOffset, IrStatementOrigin.EXCLEQEQ, + expression.startOffset, expression.endOffset, + context.irBuiltIns.booleanType, + IrStatementOrigin.EXCLEQEQ, context.irBuiltIns.booleanNotSymbol, irIdentityEquals ) @@ -218,6 +239,7 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat val irEquals = IrBinaryPrimitiveImpl( expression.startOffset, expression.endOffset, + context.irBuiltIns.booleanType, irOperator, eqeqSymbol, expression.left!!.generateAsPrimitiveNumericComparisonOperand(comparisonInfo?.leftType, comparisonType), @@ -230,6 +252,7 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat IrStatementOrigin.EXCLEQ -> IrUnaryPrimitiveImpl( expression.startOffset, expression.endOffset, + context.irBuiltIns.booleanType, IrStatementOrigin.EXCLEQ, context.irBuiltIns.booleanNotSymbol, irEquals @@ -253,14 +276,18 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat context.irBuiltIns.ieee754equalsFunByOperandType[comparisonType]?.symbol ?: context.irBuiltIns.eqeqSymbol IrBinaryPrimitiveImpl( - startOffset, endOffset, irOperator, + startOffset, endOffset, + context.irBuiltIns.booleanType, + irOperator, eqeqSymbol, arg1.promoteToPrimitiveNumericType(comparisonInfo.leftType, comparisonType), arg2.promoteToPrimitiveNumericType(comparisonInfo.rightType, comparisonType) ) } else { IrBinaryPrimitiveImpl( - startOffset, endOffset, irOperator, + startOffset, endOffset, + context.irBuiltIns.booleanType, + irOperator, context.irBuiltIns.eqeqSymbol, arg1, arg2 ) @@ -281,7 +308,8 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat operandType == targetType || operandNNType == targetType -> this - type.containsNull() -> + // TODO operandType may have inaccurate nullability + operandType.containsNull() -> safeCallOnDispatchReceiver(this@OperatorExpressionGenerator, startOffset, endOffset) { dispatchReceiver -> invokeConversionFunction( startOffset, endOffset, @@ -308,10 +336,9 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat IrCallImpl( startOffset, endOffset, - functionDescriptor.returnType!!, + functionDescriptor.returnType!!.toIrType(), context.symbolTable.referenceFunction(functionDescriptor.original), functionDescriptor, - typeArguments = null, origin = null, // TODO origin for widening conversions? superQualifierSymbol = null ).apply { @@ -331,17 +358,21 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat return if (comparisonInfo != null) { IrBinaryPrimitiveImpl( - startOffset, endOffset, origin, + startOffset, endOffset, + context.irBuiltIns.booleanType, + origin, getComparisonOperatorSymbol(origin, comparisonInfo.comparisonType), expression.left!!.generateAsPrimitiveNumericComparisonOperand(comparisonInfo.leftType, comparisonInfo.comparisonType), expression.right!!.generateAsPrimitiveNumericComparisonOperand(comparisonInfo.rightType, comparisonInfo.comparisonType) ) } else { IrBinaryPrimitiveImpl( - startOffset, endOffset, origin, + startOffset, endOffset, + context.irBuiltIns.booleanType, + origin, getComparisonOperatorSymbol(origin, context.irBuiltIns.int), generateCall(getResolvedCall(expression)!!, expression, origin), - IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, 0) + IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, 0) ) } } @@ -367,11 +398,16 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat val irArgument = ktArgument.genExpr() val ktOperator = expression.operationReference - val resultType = irArgument.type.makeNotNullable() + val resultType = irArgument.type.makeNotNull() - return irBlock(ktOperator, origin, resultType) { + return irBlock(ktOperator.startOffset, ktOperator.endOffset, origin, resultType) { val temporary = irTemporary(irArgument, "notnull") - +irIfNull(resultType, irGet(temporary.symbol), irThrowNpe(origin), irGet(temporary.symbol)) + +irIfNull( + resultType, + irGet(temporary.type, temporary.symbol), + irThrowNpe(origin), + irGet(temporary.type, temporary.symbol) + ) } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/ExpressionHelpers.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/ExpressionHelpers.kt index ef93fe745ee..7ba0f0d1d26 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/ExpressionHelpers.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/ExpressionHelpers.kt @@ -85,14 +85,33 @@ fun IrBuilderWithScope.irReturn(value: IrExpression) = value ) -fun IrBuilderWithScope.irReturnTrue() = - irReturn(IrConstImpl(startOffset, endOffset, context.irBuiltIns.booleanType, IrConstKind.Boolean, true)) +fun IrBuilderWithScope.irBoolean(value: Boolean) = + IrConstImpl(startOffset, endOffset, context.irBuiltIns.booleanType, IrConstKind.Boolean, value) -fun IrBuilderWithScope.irReturnFalse() = - irReturn(IrConstImpl(startOffset, endOffset, context.irBuiltIns.booleanType, IrConstKind.Boolean, false)) +fun IrBuilderWithScope.irTrue() = irBoolean(true) +fun IrBuilderWithScope.irFalse() = irBoolean(false) +fun IrBuilderWithScope.irReturnTrue() = irReturn(irTrue()) +fun IrBuilderWithScope.irReturnFalse() = irReturn(irFalse()) + +fun IrBuilderWithScope.irElseBranch(expression: IrExpression) = + IrElseBranchImpl(startOffset, endOffset, irTrue(), expression) + +fun IrBuilderWithScope.irIfThen(type: IrType, condition: IrExpression, thenPart: IrExpression) = + IrIfThenElseImpl(startOffset, endOffset, type).apply { + branches.add(IrBranchImpl(startOffset, endOffset, condition, thenPart)) + } fun IrBuilderWithScope.irIfThenElse(type: IrType, condition: IrExpression, thenPart: IrExpression, elsePart: IrExpression) = - IrIfThenElseImpl(startOffset, endOffset, type, condition, thenPart, elsePart) + IrIfThenElseImpl(startOffset, endOffset, type).apply { + branches.add(IrBranchImpl(startOffset, endOffset, condition, thenPart)) + branches.add(irElseBranch(elsePart)) + } + +fun IrBuilderWithScope.irIfThenMaybeElse(type: IrType, condition: IrExpression, thenPart: IrExpression, elsePart: IrExpression?) = + if (elsePart != null) + irIfThenElse(type, condition, thenPart, elsePart) + else + irIfThen(type, condition, thenPart) fun IrBuilderWithScope.irIfNull(type: IrType, subject: IrExpression, thenPart: IrExpression, elsePart: IrExpression) = irIfThenElse(type, irEqualsNull(subject), thenPart, elsePart) @@ -101,10 +120,10 @@ fun IrBuilderWithScope.irThrowNpe(origin: IrStatementOrigin) = IrNullaryPrimitiveImpl(startOffset, endOffset, context.irBuiltIns.nothingType, origin, context.irBuiltIns.throwNpeSymbol) fun IrBuilderWithScope.irIfThenReturnTrue(condition: IrExpression) = - IrIfThenElseImpl(startOffset, endOffset, context.irBuiltIns.unitType, condition, irReturnTrue()) + irIfThen(context.irBuiltIns.unitType, condition, irReturnTrue()) fun IrBuilderWithScope.irIfThenReturnFalse(condition: IrExpression) = - IrIfThenElseImpl(startOffset, endOffset, context.irBuiltIns.unitType, condition, irReturnFalse()) + irIfThen(context.irBuiltIns.unitType, condition, irReturnFalse()) fun IrBuilderWithScope.irGet(type: IrType, variable: IrValueSymbol) = IrGetValueImpl(startOffset, endOffset, type, variable) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/IrBuilder.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/IrBuilder.kt index ab07d371e34..f89b1dbcad7 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/IrBuilder.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/IrBuilder.kt @@ -86,6 +86,7 @@ class IrBlockBuilder( val origin: IrStatementOrigin? = null, var resultType: IrType? = null ) : IrStatementsBuilder(context, scope, startOffset, endOffset) { + private val statements = ArrayList() inline fun block(body: IrBlockBuilder.() -> Unit): IrBlock { @@ -107,6 +108,33 @@ class IrBlockBuilder( } } +class IrSingleStatementBuilder( + context: IrGeneratorContext, + scope: Scope, + startOffset: Int, + endOffset: Int, + val origin: IrStatementOrigin? = null +) : IrBuilderWithScope(context, scope, startOffset, endOffset) { + + inline fun build(statementBuilder: IrSingleStatementBuilder.() -> T): T = + statementBuilder() +} + +inline fun IrGeneratorWithScope.buildStatement( + startOffset: Int, + endOffset: Int, + origin: IrStatementOrigin?, + builder: IrSingleStatementBuilder.() -> T +) = + IrSingleStatementBuilder(context, scope, startOffset, endOffset, origin).builder() + +inline fun IrGeneratorWithScope.buildStatement( + startOffset: Int, + endOffset: Int, + builder: IrSingleStatementBuilder.() -> T +) = + IrSingleStatementBuilder(context, scope, startOffset, endOffset).builder() + fun T.at(startOffset: Int, endOffset: Int) = apply { this.startOffset = startOffset this.endOffset = endOffset diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrMemberAccessExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrMemberAccessExpression.kt index a9d16c865bc..1fd0379f950 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrMemberAccessExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrMemberAccessExpression.kt @@ -86,17 +86,24 @@ fun IrMemberAccessExpression.removeValueArgument(valueParameterDescriptor: Value removeValueArgument(valueParameterDescriptor.index) } -inline fun T.mapValueParameters(transform: (ValueParameterDescriptor) -> IrExpression?): T { - descriptor.valueParameters.forEach { - putValueArgument(it.index, transform(it)) +inline fun T.mapTypeParameters(transform: (TypeParameterDescriptor) -> IrType) : T = + apply { + descriptor.typeParameters.forEach { + putTypeArgument(it.index, transform(it)) + } } - return this -} -inline fun T.mapValueParametersIndexed(transform: (Int, ValueParameterDescriptor) -> IrExpression?): T { - descriptor.valueParameters.forEach { - putValueArgument(it.index, transform(it.index, it)) +inline fun T.mapValueParameters(transform: (ValueParameterDescriptor) -> IrExpression?): T = + apply { + descriptor.valueParameters.forEach { + putValueArgument(it.index, transform(it)) + } + } + +inline fun T.mapValueParametersIndexed(transform: (Int, ValueParameterDescriptor) -> IrExpression?): T = + apply { + descriptor.valueParameters.forEach { + putValueArgument(it.index, transform(it.index, it)) + } } - return this -} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrIfThenElseImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrIfThenElseImpl.kt index 8e63388462e..68e76443d3d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrIfThenElseImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrIfThenElseImpl.kt @@ -31,19 +31,4 @@ class IrIfThenElseImpl( IrWhenBase(startOffset, endOffset, type) { override val branches: MutableList = SmartList() - - constructor( - startOffset: Int, - endOffset: Int, - type: IrType, - condition: IrExpression, - thenBranch: IrExpression, - elseBranch: IrExpression? = null, - origin: IrStatementOrigin? = null - ) : this(startOffset, endOffset, type, origin) { - branches.add(IrBranchImpl(startOffset, endOffset, condition, thenBranch)) - if (elseBranch != null) { - branches.add(IrBranchImpl.elseBranch(elseBranch)) - } - } } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrWhenImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrWhenImpl.kt index 5fd4c8fa5a2..9a779ecad34 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrWhenImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrWhenImpl.kt @@ -51,7 +51,8 @@ class IrWhenImpl( endOffset: Int, type: IrType, override val origin: IrStatementOrigin? = null -) : IrWhenBase(startOffset, endOffset, type) { +) : + IrWhenBase(startOffset, endOffset, type) { constructor( startOffset: Int, @@ -71,7 +72,9 @@ open class IrBranchImpl( endOffset: Int, override var condition: IrExpression, override var result: IrExpression -) : IrElementBase(startOffset, endOffset), IrBranch { +) : + IrElementBase(startOffset, endOffset), + IrBranch { constructor(condition: IrExpression, result: IrExpression) : this(condition.startOffset, condition.endOffset, condition, result) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt index 91e36a2a530..ea2c4db52f1 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.types import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl +import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -25,3 +26,15 @@ val IrType.classifierOrFail: IrClassifierSymbol val IrType.classifierOrNull: IrClassifierSymbol? get() = safeAs()?.classifier + +fun IrType.makeNotNull() = + if (this is IrSimpleType && this.hasQuestionMark) + IrSimpleTypeImpl( + classifier, + false, + arguments, + annotations, + Variance.INVARIANT + ) + else + this \ No newline at end of file