diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DataClassOperatorsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DataClassOperatorsLowering.kt index 0bc7e206c4d..a7811d311e3 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DataClassOperatorsLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DataClassOperatorsLowering.kt @@ -5,73 +5,76 @@ package org.jetbrains.kotlin.backend.konan.lower -import org.jetbrains.kotlin.backend.common.FunctionLoweringPass +import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlock import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark +import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.util.irCall -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid - -internal class DataClassOperatorsLowering(val context: Context): FunctionLoweringPass { +import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark +import org.jetbrains.kotlin.ir.visitors.IrElementTransformer +internal class DataClassOperatorsLowering(val context: Context) : FileLoweringPass, IrElementTransformer { private val irBuiltins = context.irModule!!.irBuiltins - override fun lower(irFunction: IrFunction) { - irFunction.transformChildrenVoid(object: IrElementTransformerVoid() { - override fun visitCall(expression: IrCall): IrExpression { - expression.transformChildrenVoid(this) + override fun lower(irFile: IrFile) { + irFile.transformChildren(this, null) + } - if (expression.symbol != irBuiltins.dataClassArrayMemberToStringSymbol - && expression.symbol != irBuiltins.dataClassArrayMemberHashCodeSymbol) - return expression + override fun visitFunction(declaration: IrFunction, data: IrFunction?): IrStatement = + super.visitFunction(declaration, declaration) - val argument = expression.getValueArgument(0)!! - val argumentClassifier = argument.type.classifierOrFail + override fun visitCall(expression: IrCall, data: IrFunction?): IrExpression { + expression.transformChildren(this, data) - val isToString = expression.symbol == irBuiltins.dataClassArrayMemberToStringSymbol - val newCalleeSymbol = if (isToString) - context.ir.symbols.arrayContentToString[argumentClassifier]!! - else - context.ir.symbols.arrayContentHashCode[argumentClassifier]!! + if (expression.symbol != irBuiltins.dataClassArrayMemberToStringSymbol + && expression.symbol != irBuiltins.dataClassArrayMemberHashCodeSymbol) + return expression - val newCallee = newCalleeSymbol.owner + val argument = expression.getValueArgument(0)!! + val argumentClassifier = argument.type.classifierOrFail - val startOffset = expression.startOffset - val endOffset = expression.endOffset - val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset) + val isToString = expression.symbol == irBuiltins.dataClassArrayMemberToStringSymbol + val newCalleeSymbol = if (isToString) + context.ir.symbols.arrayContentToString[argumentClassifier]!! + else + context.ir.symbols.arrayContentHashCode[argumentClassifier]!! - return irBuilder.run { - // TODO: use more precise type arguments. - val typeArguments = (0 until newCallee.typeParameters.size).map { irBuiltins.anyNType } + val newCallee = newCalleeSymbol.owner - if (!argument.type.isSimpleTypeWithQuestionMark) { - irCall(newCallee, typeArguments).apply { - extensionReceiver = argument - } - } else { - irBlock(argument) { - val tmp = irTemporary(argument) - val call = irCall(newCallee, typeArguments).apply { - extensionReceiver = irGet(tmp) - } - +irIfThenElse(call.type, - irEqeqeq(irGet(tmp), irNull()), - if (isToString) - irString("null") - else - irInt(0), - call) - } + val startOffset = expression.startOffset + val endOffset = expression.endOffset + val irBuilder = context.createIrBuilder(data!!.symbol, startOffset, endOffset) + + return irBuilder.run { + // TODO: use more precise type arguments. + val typeArguments = (0 until newCallee.typeParameters.size).map { irBuiltins.anyNType } + + if (!argument.type.isSimpleTypeWithQuestionMark) { + irCall(newCallee, typeArguments).apply { + extensionReceiver = argument + } + } else { + irBlock(argument) { + val tmp = irTemporary(argument) + val call = irCall(newCallee, typeArguments).apply { + extensionReceiver = irGet(tmp) } + +irIfThenElse(call.type, + irEqeqeq(irGet(tmp), irNull()), + if (isToString) + irString("null") + else + irInt(0), + call) } } - }) + } } -} \ No newline at end of file +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt index 9158df1b601..f33aad224d5 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt @@ -6,59 +6,34 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.CommonBackendContext -import org.jetbrains.kotlin.backend.common.FunctionLoweringPass -import org.jetbrains.kotlin.backend.common.lower.at -import org.jetbrains.kotlin.backend.common.lower.createIrBuilder -import org.jetbrains.kotlin.backend.common.lower.irBlock -import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.konan.ir.containsNull import org.jetbrains.kotlin.backend.konan.ir.isSubtypeOf -import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrTypeOperator import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall import org.jetbrains.kotlin.ir.symbols.IrClassSymbol -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.makeNotNull import org.jetbrains.kotlin.ir.types.makeNullable import org.jetbrains.kotlin.ir.util.irCall -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils -/** - * This lowering pass lowers some [IrTypeOperatorCall]s. - */ -internal class TypeOperatorLowering(val context: CommonBackendContext) : FunctionLoweringPass { - override fun lower(irFunction: IrFunction) { - val transformer = TypeOperatorTransformer(context, irFunction.symbol) - irFunction.transformChildrenVoid(transformer) - } -} - - -private class TypeOperatorTransformer(val context: CommonBackendContext, val function: IrFunctionSymbol) : IrElementTransformerVoid() { - - private val builder = context.createIrBuilder(function) - - val throwNullPointerException = context.ir.symbols.throwNullPointerException - - override fun visitFunction(declaration: IrFunction): IrStatement { - // ignore inner functions during this pass - return declaration +internal class TypeOperatorLowering(val context: CommonBackendContext) : FileLoweringPass, IrBuildingTransformer(context) { + override fun lower(irFile: IrFile) { + irFile.transformChildren(this, null) } private fun IrType.erasure(): IrType { if (this !is IrSimpleType) return this - val classifier = this.classifier - return when (classifier) { + return when (val classifier = classifier) { is IrClassSymbol -> this is IrTypeParameterSymbol -> { val upperBound = classifier.owner.superTypes.firstOrNull() ?: @@ -87,7 +62,7 @@ private class TypeOperatorTransformer(val context: CommonBackendContext, val fun expression.argument.type.isSubtypeOf(typeOperand) -> expression.argument expression.argument.type.containsNull() -> { - with (builder) { + with(builder) { irLetS(expression.argument) { argument -> irIfThenElse( type = expression.type, @@ -96,7 +71,7 @@ private class TypeOperatorTransformer(val context: CommonBackendContext, val fun thenPart = if (typeOperand.isSimpleTypeWithQuestionMark) irNull() else - irCall(throwNullPointerException.owner), + irCall(this@TypeOperatorLowering.context.ir.symbols.throwNullPointerException.owner), elsePart = irAs(irGet(argument.owner), typeOperand.makeNotNull()) ) @@ -112,8 +87,6 @@ private class TypeOperatorTransformer(val context: CommonBackendContext, val fun } } - private fun KotlinType.isNullable() = TypeUtils.isNullableType(this) - private fun lowerSafeCast(expression: IrTypeOperatorCall): IrExpression { val typeOperand = expression.typeOperand.erasure() @@ -136,4 +109,4 @@ private class TypeOperatorTransformer(val context: CommonBackendContext, val fun else -> expression } } -} \ No newline at end of file +}