IrTypes in psi2ir (work in progress)

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