diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDescriptorsFactory.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDescriptorsFactory.kt index 3dfd81115c7..b741bbc1b9a 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDescriptorsFactory.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDescriptorsFactory.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. */ package org.jetbrains.kotlin.backend.js @@ -29,6 +18,7 @@ import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl +import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.name.Name @@ -64,7 +54,7 @@ class JsDescriptorsFactory : DescriptorsFactory { false ).apply { setType( - outerClass.defaultType, + outerClass.defaultType.toKotlinType(), emptyList(), innerClass.descriptor.thisAsReceiverParameter, null as? ReceiverParameterDescriptor diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt index de6f0f91ebc..ca22b538888 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt @@ -25,7 +25,7 @@ class JsIntrinsics( context: JsIrBackendContext ) { - private val stubBuilder = DeclarationStubGenerator(context.module, context.symbolTable, JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB) + private val stubBuilder = DeclarationStubGenerator(module, context.module, context.symbolTable, JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB) // Equality operations: diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt index 65b856c485e..dbfe28a8177 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt @@ -15,8 +15,8 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames import org.jetbrains.kotlin.ir.backend.js.lower.inline.ModuleIndex +import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment @@ -25,6 +25,8 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -59,7 +61,7 @@ class JsIrBackendContext( val secondaryConstructorsMap = mutableMapOf() - fun getOperatorByName(name: Name, type: KotlinType) = operatorMap[name]?.get(type) + fun getOperatorByName(name: Name, type: IrType) = operatorMap[name]?.get(type.toKotlinType()) val originalModuleIndex = ModuleIndex(irModuleFragment) @@ -109,6 +111,7 @@ class JsIrBackendContext( } private fun referenceOperators() = OperatorNames.ALL.map { name -> + // TODO to replace KotlinType with IrType we need right equals on IrType name to irBuiltIns.primitiveTypes.fold(mutableMapOf()) { m, t -> val function = t.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).singleOrNull() function?.let { m.put(t, symbolTable.referenceSimpleFunction(it)) } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsSharedVariablesManager.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsSharedVariablesManager.kt index 8beecdcf04b..bdb686138c9 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsSharedVariablesManager.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsSharedVariablesManager.kt @@ -40,24 +40,28 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack false, false, variableDescriptor.isLateInit, variableDescriptor.source ) - val valueType = originalDeclaration.descriptor.type + val valueType = originalDeclaration.type val boxConstructor = closureBoxConstructorTypeDescriptor val boxConstructorSymbol = closureBoxConstructorTypeSymbol - val constructorTypeParam = closureBoxConstructorTypeDescriptor.typeParameters[0] - val boxConstructorTypeArgument = mapOf(constructorTypeParam to valueType) val initializer = originalDeclaration.initializer ?: IrConstImpl.constNull( originalDeclaration.startOffset, originalDeclaration.endOffset, valueType ) + // TODO use buildCall? val constructorCall = IrCallImpl( originalDeclaration.startOffset, originalDeclaration.endOffset, + // TODO wrong type + originalDeclaration.type, boxConstructorSymbol, boxConstructor, - boxConstructorTypeArgument, + 1, JsLoweredDeclarationOrigin.JS_CLOSURE_BOX_CLASS - ).apply { putValueArgument(0, initializer) } + ).apply { + putTypeArgument(0, valueType) + putValueArgument(0, initializer) + } return IrVariableImpl( @@ -65,6 +69,8 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack originalDeclaration.endOffset, originalDeclaration.origin, sharedVariableDescriptor, + // TODO wrong type ? + originalDeclaration.type, constructorCall ) } @@ -75,9 +81,11 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack IrGetFieldImpl( originalGet.startOffset, originalGet.endOffset, closureBoxFieldSymbol, + originalGet.type, IrGetValueImpl( originalGet.startOffset, originalGet.endOffset, + originalGet.type, sharedVariableSymbol ), originalGet.origin @@ -90,9 +98,11 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack IrGetValueImpl( originalSet.startOffset, originalSet.endOffset, + originalSet.type, sharedVariableSymbol ), originalSet.value, + originalSet.type, originalSet.origin ) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt index b5e7409de99..69cde767cc9 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt @@ -45,7 +45,8 @@ fun compile( moduleFragment ) - ExternalDependenciesGenerator(psi2IrContext.symbolTable, psi2IrContext.irBuiltIns).generateUnboundSymbolsAsDependencies(moduleFragment) + ExternalDependenciesGenerator(psi2IrContext.moduleDescriptor, psi2IrContext.symbolTable, psi2IrContext.irBuiltIns) + .generateUnboundSymbolsAsDependencies(moduleFragment) context.performInlining(moduleFragment) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ir/IrArithBuilder.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ir/IrArithBuilder.kt index a153ab10c66..c289d7f1fc3 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ir/IrArithBuilder.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ir/IrArithBuilder.kt @@ -41,7 +41,7 @@ class JsIrArithBuilder(val context: JsIrBackendContext) { fun inv(v: IrExpression): IrExpression = buildUnaryOperator(OperatorNames.INV, v) fun andand(l: IrExpression, r: IrExpression) = // if (l) r else false - JsIrBuilder.buildIfElse(context.builtIns.booleanType, l, r, JsIrBuilder.buildBoolean(context.builtIns.booleanType, false)) + JsIrBuilder.buildIfElse(context.irBuiltIns.booleanType, l, r, JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, false)) fun oror(l: IrExpression, r: IrExpression) = // if (l) true else r - JsIrBuilder.buildIfElse(context.builtIns.booleanType, l, JsIrBuilder.buildBoolean(context.builtIns.booleanType, true), r) + JsIrBuilder.buildIfElse(context.irBuiltIns.booleanType, l, JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true), r) } \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ir/IrBuilder.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ir/IrBuilder.kt index caa1f0f2d00..782a4911de0 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ir/IrBuilder.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ir/IrBuilder.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.ir.backend.js.ir -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl @@ -15,76 +15,103 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.ir.types.IrType object JsIrBuilder { object SYNTHESIZED_STATEMENT : IrStatementOriginImpl("SYNTHESIZED_STATEMENT") object SYNTHESIZED_DECLARATION : IrDeclarationOriginImpl("SYNTHESIZED_DECLARATION") - fun buildCall(target: IrFunctionSymbol, type: KotlinType? = null, typeArguments: Map? = null) = + fun buildCall(target: IrFunctionSymbol, type: IrType? = null, typeArguments: List? = null): IrCall = IrCallImpl( UNDEFINED_OFFSET, UNDEFINED_OFFSET, - type ?: target.descriptor.returnType!!, + type ?: target.owner.returnType, target, target.descriptor, - typeArguments, + target.owner.typeParameters.size, SYNTHESIZED_STATEMENT - ) + ).apply { + typeArguments?.let { + assert(typeArguments.size == typeArgumentsCount) + it.withIndex().forEach { (i, t) -> putTypeArgument(i, t) } + } + } - fun buildReturn(targetSymbol: IrFunctionSymbol, value: IrExpression) = - IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, targetSymbol, value) + fun buildReturn(targetSymbol: IrFunctionSymbol, value: IrExpression, context: BackendContext) = + IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.nothingType, targetSymbol, value) - fun buildThrow(type: KotlinType, value: IrExpression) = IrThrowImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, value) + fun buildThrow(type: IrType, value: IrExpression) = IrThrowImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, value) - fun buildValueParameter(symbol: IrValueParameterSymbol) = - IrValueParameterImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol) + fun buildValueParameter(symbol: IrValueParameterSymbol, type: IrType? = null) = + IrValueParameterImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol, type ?: symbol.owner.type, null) - fun buildFunction(symbol: IrSimpleFunctionSymbol) = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol) + fun buildFunction(symbol: IrSimpleFunctionSymbol, returnType: IrType) = + IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol).apply { + this.returnType = returnType + } - fun buildGetObjectValue(type: KotlinType, classSymbol: IrClassSymbol) = + fun buildGetObjectValue(type: IrType, classSymbol: IrClassSymbol) = IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, classSymbol) - fun buildGetClass(expression: IrExpression, type: KotlinType) = IrGetClassImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, expression) + fun buildGetClass(expression: IrExpression, type: IrType) = IrGetClassImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, expression) - fun buildGetValue(symbol: IrValueSymbol) = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, SYNTHESIZED_STATEMENT) - fun buildSetVariable(symbol: IrVariableSymbol, value: IrExpression) = - IrSetVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, value, SYNTHESIZED_STATEMENT) + fun buildGetValue(symbol: IrValueSymbol) = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol.owner.type, symbol, SYNTHESIZED_STATEMENT) + fun buildSetVariable(symbol: IrVariableSymbol, value: IrExpression, type: IrType) = + IrSetVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, symbol, value, SYNTHESIZED_STATEMENT) fun buildGetField(symbol: IrFieldSymbol, receiver: IrExpression?, superQualifierSymbol: IrClassSymbol? = null) = - IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, receiver, SYNTHESIZED_STATEMENT, superQualifierSymbol) + IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, symbol.owner.type, receiver, SYNTHESIZED_STATEMENT, superQualifierSymbol) - fun buildSetField(symbol: IrFieldSymbol, receiver: IrExpression?, value: IrExpression, superQualifierSymbol: IrClassSymbol? = null) = - IrSetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, receiver, value, SYNTHESIZED_STATEMENT, superQualifierSymbol) + fun buildSetField(symbol: IrFieldSymbol, receiver: IrExpression?, value: IrExpression, type: IrType, superQualifierSymbol: IrClassSymbol? = null) = + IrSetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, receiver, value, type, SYNTHESIZED_STATEMENT, superQualifierSymbol) fun buildBlockBody(statements: List) = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, statements) - fun buildBlock(type: KotlinType) = IrBlockImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, SYNTHESIZED_STATEMENT) - fun buildBlock(type: KotlinType, statements: List) = + fun buildBlock(type: IrType) = IrBlockImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, SYNTHESIZED_STATEMENT) + fun buildBlock(type: IrType, statements: List) = IrBlockImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, SYNTHESIZED_STATEMENT, statements) - fun buildFunctionReference(type: KotlinType, symbol: IrFunctionSymbol) = - IrFunctionReferenceImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, symbol, symbol.descriptor) + fun buildFunctionReference(type: IrType, symbol: IrFunctionSymbol) = + IrFunctionReferenceImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, symbol, symbol.descriptor, 0, null) - fun buildVar(symbol: IrVariableSymbol, initializer: IrExpression? = null) = - IrVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol).apply { this.initializer = initializer } + fun buildVar(symbol: IrVariableSymbol, initializer: IrExpression? = null, type: IrType?) = + IrVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol, type ?: symbol.owner.type).apply { this.initializer = initializer } - fun buildBreak(type: KotlinType, loop: IrLoop) = IrBreakImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, loop) - fun buildContinue(type: KotlinType, loop: IrLoop) = IrContinueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, loop) + fun buildBreak(type: IrType, loop: IrLoop) = IrBreakImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, loop) + fun buildContinue(type: IrType, loop: IrLoop) = IrContinueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, loop) - fun buildIfElse(type: KotlinType, cond: IrExpression, thenBranch: IrExpression, elseBranch: IrExpression? = null) = IrIfThenElseImpl( + fun buildIfElse(type: IrType, cond: IrExpression, thenBranch: IrExpression, elseBranch: IrExpression? = null): IrWhen = buildIfElse( UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, cond, thenBranch, elseBranch, SYNTHESIZED_STATEMENT ) - fun buildWhen(type: KotlinType, branches: List) = + fun buildIfElse( + startOffset: Int, + endOffset: Int, + type: IrType, + cond: IrExpression, + thenBranch: IrExpression, + elseBranch: IrExpression? = null, + origin: IrStatementOrigin? = null + ): IrWhen { + val element = IrIfThenElseImpl(startOffset, endOffset, type, origin) + element.branches.add(IrBranchImpl(cond, thenBranch)) + if (elseBranch != null) { + val irTrue = IrConstImpl.boolean(UNDEFINED_OFFSET, UNDEFINED_OFFSET, cond.type, true) + element.branches.add(IrElseBranchImpl(irTrue, elseBranch)) + } + + return element + } + + fun buildWhen(type: IrType, branches: List) = IrWhenImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, SYNTHESIZED_STATEMENT, branches) - fun buildTypeOperator(type: KotlinType, operator: IrTypeOperator, argument: IrExpression, toType: KotlinType, symbol: IrClassifierSymbol) = - IrTypeOperatorCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, operator, toType, argument, symbol) + fun buildTypeOperator(type: IrType, operator: IrTypeOperator, argument: IrExpression, toType: IrType, symbol: IrClassifierSymbol) = + IrTypeOperatorCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, operator, toType, symbol, argument) - fun buildNull(type: KotlinType) = IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type) - fun buildBoolean(type: KotlinType, v: Boolean) = IrConstImpl.boolean(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, v) - fun buildInt(type: KotlinType, v: Int) = IrConstImpl.int(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, v) - fun buildString(type: KotlinType, s: String) = IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, s) -} \ No newline at end of file + fun buildNull(type: IrType) = IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type) + fun buildBoolean(type: IrType, v: Boolean) = IrConstImpl.boolean(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, v) + fun buildInt(type: IrType, v: Int) = IrConstImpl.int(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, v) + fun buildString(type: IrType, s: String) = IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, s) +} diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt index 7773639d1f5..6fbb052fce2 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass -import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext @@ -17,9 +16,11 @@ import org.jetbrains.kotlin.ir.backend.js.utils.Namer import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.ir.util.transformFlat -import org.jetbrains.kotlin.ir.visitors.* -import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.ir.visitors.IrElementTransformer +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor private typealias VisitData = Nothing? @@ -30,15 +31,20 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont private val statementVisitor = StatementVisitor() private val expressionVisitor = ExpressionVisitor() - private val constTrue = JsIrBuilder.buildBoolean(context.builtIns.booleanType, true) - private val constFalse = JsIrBuilder.buildBoolean(context.builtIns.booleanType, false) - private val nothingType = context.builtIns.nullableNothingType + private val constTrue = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true) + private val constFalse = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, false) + private val nothingType get() = context.irBuiltIns.nothingType + private val unitType get() = context.irBuiltIns.unitType - private val unitType = context.builtIns.unitType private val unitValue = JsIrBuilder.buildGetObjectValue(unitType, context.symbolTable.referenceClass(context.builtIns.unit)) - private val unreachableFunction = - JsSymbolBuilder.buildSimpleFunction(context.module, Namer.UNREACHABLE_NAME).initialize(type = nothingType) + private val unreachableFunction = JsIrBuilder.buildFunction( + JsSymbolBuilder.buildSimpleFunction( + context.module, + Namer.UNREACHABLE_NAME + ).initialize(returnType = nothingType), + nothingType + ) override fun lower(irDeclarationContainer: IrDeclarationContainer) { irDeclarationContainer.declarations.transformFlat { declaration -> @@ -61,17 +67,18 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont fun lower(irField: IrField, container: IrDeclarationContainer): List { irField.initializer?.apply { + val returnType = expression.type val initFnSymbol = JsSymbolBuilder.buildSimpleFunction( (container as IrSymbolOwner).symbol.descriptor, irField.name.asString() + "\$init\$" - ).initialize(type = expression.type) + ).initialize(returnType = returnType) val newBody = IrBlockBodyImpl(expression.startOffset, expression.endOffset).apply { - statements += JsIrBuilder.buildReturn(initFnSymbol, expression) + statements += JsIrBuilder.buildReturn(initFnSymbol, expression, context) } - val initFn = JsIrBuilder.buildFunction(initFnSymbol).apply { + val initFn = JsIrBuilder.buildFunction(initFnSymbol, returnType).apply { body = newBody } @@ -314,15 +321,15 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont expression.type, expression.operator, expression.typeOperand, - resultValue, - expression.typeOperandClassifier + expression.typeOperandClassifier, + resultValue ) val resValue: IrExpression - if (!KotlinBuiltIns.isUnit(expression.type)) { + if (!expression.type.isUnit()) { val resVar = makeTempVar(expression.type) - statements += JsIrBuilder.buildVar(resVar, newOperator) + statements += JsIrBuilder.buildVar(resVar, newOperator, type = expression.type) resValue = JsIrBuilder.buildGetValue(resVar) } else { statements += newOperator @@ -364,7 +371,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont } if (needNew) { - newStatements += JsIrBuilder.buildSetField(expression.symbol, newReceiver, newValue, expression.superQualifierSymbol) + newStatements += JsIrBuilder.buildSetField(expression.symbol, newReceiver, newValue, unitType, expression.superQualifierSymbol) return DecomposedResult(newStatements, unitValue) } @@ -375,7 +382,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont val valueResult = expression.value.accept(expressionVisitor, data) return valueResult.runIfChanged { - statements += JsIrBuilder.buildSetVariable(expression.symbol, resultValue) + statements += JsIrBuilder.buildSetVariable(expression.symbol, resultValue, unitType) DecomposedResult(statements, unitValue) } } @@ -400,7 +407,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont // val x = x_tmp override fun visitContainerExpression(expression: IrContainerExpression, data: VisitData): VisitResult { val variable = makeTempVar(expression.type) - val varDeclaration = JsIrBuilder.buildVar(variable) + val varDeclaration = JsIrBuilder.buildVar(variable, type = expression.type) val blockStatements = expression.statements val lastStatement: IrStatement? = blockStatements.lastOrNull() @@ -434,7 +441,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont collectingList += statements resultValue } - collectingList += JsIrBuilder.buildSetVariable(variable, result) + collectingList += JsIrBuilder.buildSetVariable(variable, result, unitType) if (body is IrComposite) { DecomposedResult(mutableListOf(varDeclaration, *collectingList.toTypedArray()) , JsIrBuilder.buildGetValue(variable)) } else { @@ -463,7 +470,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont private fun prepareArgument(arg: IrExpression, needWrap: Boolean, statements: MutableList): IrExpression { return if (needWrap) { val wrapVar = makeTempVar(arg.type) - statements += JsIrBuilder.buildVar(wrapVar, arg) + statements += JsIrBuilder.buildVar(wrapVar, arg, type = arg.type) JsIrBuilder.buildGetValue(wrapVar) } else arg } @@ -543,21 +550,21 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont val resultVar = makeTempVar(expression.type) // TODO: get rid of temporary variable - newStatements += JsIrBuilder.buildVar(resultVar, expression) + newStatements += JsIrBuilder.buildVar(resultVar, expression, type = expression.type) return DecomposedResult(newStatements, JsIrBuilder.buildGetValue(resultVar)) } override fun visitWhen(expression: IrWhen, data: VisitData): VisitResult { val collectiveVar = makeTempVar(expression.type) - val varDeclaration = JsIrBuilder.buildVar(collectiveVar) + val varDeclaration = JsIrBuilder.buildVar(collectiveVar, type = expression.type) val newWhen = processWhen(expression, data, this, this) { visitResult, original -> val resultList = mutableListOf() val newResult = visitResult.runIfChangedOrDefault(original as IrExpression) { resultList += statements resultValue } - resultList.apply { add(JsIrBuilder.buildSetVariable(collectiveVar, newResult)) } + resultList.apply { add(JsIrBuilder.buildSetVariable(collectiveVar, newResult, unitType)) } } if (newWhen != expression) { @@ -587,7 +594,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont resultValue } val wrapVar = makeTempVar(expression.varargElementType) - newStatements += JsIrBuilder.buildVar(wrapVar).apply { initializer = newExpression } + newStatements += JsIrBuilder.buildVar(wrapVar, type = expression.type).apply { initializer = newExpression } val newValue = JsIrBuilder.buildGetValue(wrapVar) if (original is IrSpreadElement) { IrSpreadElementImpl(original.startOffset, original.endOffset, newValue) @@ -641,7 +648,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont newStatements += instantiater(returnValue) - return TerminatedResult(newStatements, JsIrBuilder.buildCall(unreachableFunction)) + return TerminatedResult(newStatements, JsIrBuilder.buildCall(unreachableFunction.symbol)) } @@ -658,7 +665,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont ) override fun visitBreakContinue(jump: IrBreakContinue, data: VisitData): VisitResult { - return DecomposedResult(jump, JsIrBuilder.buildCall(unreachableFunction)) + return DecomposedResult(jump, JsIrBuilder.buildCall(unreachableFunction.symbol)) } override fun visitTry(aTry: IrTry, data: VisitData): VisitResult { @@ -669,10 +676,10 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont finallyResult?.run { assert(status == VisitStatus.KEPT) } val resultSymbol = makeTempVar(aTry.type) - val resultDeclaration = JsIrBuilder.buildVar(resultSymbol) + val resultDeclaration = JsIrBuilder.buildVar(resultSymbol, type = aTry.type) val newTryValue = tryResult.runIfChangedOrDefault(aTry.tryResult) { resultValue } - val trySetResult = JsIrBuilder.buildSetVariable(resultSymbol, newTryValue) as IrStatement + val trySetResult = JsIrBuilder.buildSetVariable(resultSymbol, newTryValue, unitType) as IrStatement val tryBlock = IrBlockImpl(aTry.tryResult.startOffset, aTry.tryResult.endOffset, unitType).apply { statements += tryResult.runIfChangedOrDefault(listOf(trySetResult)) { statements + trySetResult } @@ -680,7 +687,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont val catchBlocks = catchResults.map { (original, result) -> val newCatchResult = result.runIfChangedOrDefault(original.result) { resultValue } - val catchSetResult = JsIrBuilder.buildSetVariable(resultSymbol, newCatchResult) as IrStatement + val catchSetResult = JsIrBuilder.buildSetVariable(resultSymbol, newCatchResult, unitType) as IrStatement val catchBlock = IrBlockImpl(original.result.startOffset, original.result.endOffset, unitType) catchBlock.statements += result.runIfChangedOrDefault(listOf(catchSetResult)) { statements + catchSetResult } IrCatchImpl(original.startOffset, original.endOffset, original.catchParameter, catchBlock) @@ -713,7 +720,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont } } - fun makeTempVar(type: KotlinType) = + fun makeTempVar(type: IrType) = JsSymbolBuilder.buildTempVar(function.symbol, type, "tmp\$dcms\$${tmpVarCounter++}", true) fun makeLoopLabel() = "\$l\$${tmpVarCounter++}" @@ -782,7 +789,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont JsIrBuilder.buildBlock(unitType).also { val elseBlock = if (originalBranch is IrElseBranch) null else it - val ifElseNode = IrIfThenElseImpl( + val ifElseNode = JsIrBuilder.buildIfElse( originalBranch.startOffset, originalBranch.endOffset, unitType, diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/CallableReferenceLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/CallableReferenceLowering.kt index e099fa69e00..17b2daa34cb 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/CallableReferenceLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/CallableReferenceLowering.kt @@ -24,6 +24,8 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrValueSymbol +import org.jetbrains.kotlin.ir.types.IrSimpleType +import org.jetbrains.kotlin.ir.types.toIrType import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe @@ -39,9 +41,9 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP private val callableToGetterFunction = mutableMapOf() private val collectedReferenceMap = mutableMapOf() - private val callableNameConst = JsIrBuilder.buildString(context.irBuiltIns.string, Namer.KCALLABLE_NAME) - private val getterConst = JsIrBuilder.buildString(context.irBuiltIns.string, Namer.KPROPERTY_GET) - private val setterConst = JsIrBuilder.buildString(context.irBuiltIns.string, Namer.KPROPERTY_SET) + private val callableNameConst = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KCALLABLE_NAME) + private val getterConst = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KPROPERTY_GET) + private val setterConst = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KPROPERTY_SET) private val newDeclarations = mutableListOf() @@ -97,7 +99,13 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP } private fun redirectToFunction(callable: IrCallableReference, newTarget: IrFunction) = - IrCallImpl(callable.startOffset, callable.endOffset, newTarget.symbol, callable.origin).apply { + IrCallImpl( + callable.startOffset, callable.endOffset, + newTarget.symbol.owner.returnType, + newTarget.symbol, + newTarget.symbol.descriptor, + callable.origin + ).apply { copyTypeArgumentsFrom(callable) var index = 0 callable.dispatchReceiver?.let { putValueArgument(index++, it) } @@ -156,13 +164,13 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP val additionalDeclarations = generateGetterBodyWithGuard(refGetFunction) { val irClosureReference = JsIrBuilder.buildFunctionReference(functionReference.type, refClosureFunction.symbol) val irVarSymbol = JsSymbolBuilder.buildTempVar(refGetFunction.symbol, irClosureReference.type) - val irVar = JsIrBuilder.buildVar(irVarSymbol, irClosureReference) + val irVar = JsIrBuilder.buildVar(irVarSymbol, irClosureReference, type = irClosureReference.type) // TODO: fill other fields of callable reference (returnType, parameters, isFinal, etc.) val irSetName = JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply { putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol)) putValueArgument(1, callableNameConst) - putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.string, getReferenceName(declaration.descriptor))) + putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.stringType, getReferenceName(declaration.descriptor))) } Pair(listOf(irVar, irSetName), irVarSymbol) } @@ -203,10 +211,11 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP val statements = mutableListOf() val getterFunctionType = context.builtIns.getFunction(getterFunction.valueParameters.size + 1) - val irGetReference = JsIrBuilder.buildFunctionReference(getterFunctionType.defaultType, getterFunction.symbol) - val irVarSymbol = JsSymbolBuilder.buildTempVar(refGetFunction.symbol, getterFunctionType.defaultType) + val type = getterFunctionType.toIrType() + val irGetReference = JsIrBuilder.buildFunctionReference(type, getterFunction.symbol) + val irVarSymbol = JsSymbolBuilder.buildTempVar(refGetFunction.symbol, type) - statements += JsIrBuilder.buildVar(irVarSymbol, irGetReference) + statements += JsIrBuilder.buildVar(irVarSymbol, irGetReference, type = type) statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply { putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol)) @@ -216,7 +225,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP if (setterFunction != null) { val setterFunctionType = context.builtIns.getFunction(setterFunction.valueParameters.size + 1) - val irSetReference = JsIrBuilder.buildFunctionReference(setterFunctionType.defaultType, setterFunction.symbol) + val irSetReference = JsIrBuilder.buildFunctionReference(setterFunctionType.toIrType(), setterFunction.symbol) statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply { putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol)) putValueArgument(1, setterConst) @@ -228,7 +237,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply { putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol)) putValueArgument(1, callableNameConst) - putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.string, getReferenceName(propertyReference.descriptor))) + putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.stringType, getReferenceName(propertyReference.descriptor))) } Pair(statements, irVarSymbol) @@ -255,22 +264,23 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP // } // val cacheName = "${getterFunction.name}_${Namer.KCALLABLE_CACHE_SUFFIX}" + val type = getterFunction.returnType val cacheVarSymbol = - JsSymbolBuilder.buildVar(getterFunction.descriptor.containingDeclaration, getterFunction.returnType, cacheName, true) - val irNull = JsIrBuilder.buildNull(cacheVarSymbol.descriptor.type) - val irCacheDeclaration = JsIrBuilder.buildVar(cacheVarSymbol) + JsSymbolBuilder.buildVar(getterFunction.descriptor.containingDeclaration, type, cacheName, true) + val irNull = JsIrBuilder.buildNull(context.irBuiltIns.nothingNType) + val irCacheDeclaration = JsIrBuilder.buildVar(cacheVarSymbol, irNull, type = type) val irCacheValue = JsIrBuilder.buildGetValue(cacheVarSymbol) val irIfCondition = JsIrBuilder.buildCall(context.irBuiltIns.eqeqSymbol).apply { putValueArgument(0, irCacheValue) putValueArgument(1, irNull) } - val irSetCache = JsIrBuilder.buildSetVariable(cacheVarSymbol, JsIrBuilder.buildGetValue(varSymbol)) + val irSetCache = JsIrBuilder.buildSetVariable(cacheVarSymbol, JsIrBuilder.buildGetValue(varSymbol), context.irBuiltIns.unitType) val thenStatements = mutableListOf().apply { addAll(bodyStatements) add(irSetCache) } - val irThenBranch = JsIrBuilder.buildBlock(context.irBuiltIns.unit, thenStatements) - val irIfNode = JsIrBuilder.buildIfElse(context.irBuiltIns.unit, irIfCondition, irThenBranch) + val irThenBranch = JsIrBuilder.buildBlock(context.irBuiltIns.unitType, thenStatements) + val irIfNode = JsIrBuilder.buildIfElse(context.irBuiltIns.unitType, irIfCondition, irThenBranch) statements += irIfNode returnValue = irCacheValue returnStatements = listOf(irCacheDeclaration) @@ -280,7 +290,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP returnStatements = emptyList() } - statements += JsIrBuilder.buildReturn(getterFunction.symbol, returnValue) + statements += JsIrBuilder.buildReturn(getterFunction.symbol, returnValue, context) getterFunction.body = JsIrBuilder.buildBlockBody(statements) return returnStatements @@ -314,8 +324,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP private fun buildGetFunction(declaration: IrFunction, reference: IrCallableReference, getterName: String): IrSimpleFunction { val callableType = reference.type - val closureParams = callableType.arguments.dropLast(1) // drop return type - var kFunctionValueParamsCount = closureParams.size + var kFunctionValueParamsCount = (callableType as? IrSimpleType)?.arguments?.size?.minus(1) ?: 0 if (declaration.dispatchReceiverParameter != null && reference.dispatchReceiver == null) { kFunctionValueParamsCount-- @@ -342,14 +351,22 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP val refGetSymbol = JsSymbolBuilder.buildSimpleFunction(declaration.descriptor.containingDeclaration, getterName).apply { initialize( valueParameters = getterValueParameters.mapIndexed { i, p -> p.descriptor.copyAsValueParameter(descriptor, i) }, - type = callableType + returnType = callableType ) } - return JsIrBuilder.buildFunction(refGetSymbol).apply { + return JsIrBuilder.buildFunction(refGetSymbol, callableType).apply { for (i in 0 until getterValueParameters.size) { val p = getterValueParameters[i] - valueParameters += IrValueParameterImpl(p.startOffset, p.endOffset, p.origin, refGetSymbol.descriptor.valueParameters[i]) + valueParameters += + IrValueParameterImpl( + p.startOffset, + p.endOffset, + p.origin, + refGetSymbol.descriptor.valueParameters[i], + p.type, + p.varargElementType + ) } } } @@ -366,15 +383,18 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP val closureParamSymbols = generateSignatureForClosure(declaration, refGetFunction, refClosureSymbol, reference) val closureParamDescriptors = closureParamSymbols.map { it.descriptor as ValueParameterDescriptor } - refClosureSymbol.initialize(valueParameters = closureParamDescriptors, type = declaration.returnType) + val returnType = declaration.returnType + refClosureSymbol.initialize(valueParameters = closureParamDescriptors, returnType = returnType) - val closureFunction = JsIrBuilder.buildFunction(refClosureSymbol) + val closureFunction = JsIrBuilder.buildFunction(refClosureSymbol, returnType) - for (it in closureParamSymbols) { - closureFunction.valueParameters += JsIrBuilder.buildValueParameter(it) + for (param in closureParamSymbols) { + // TODO always take type from param + val type = if (param.isBound) param.owner.type else context.irBuiltIns.anyType + closureFunction.valueParameters += JsIrBuilder.buildValueParameter(param, type) } - val irCall = JsIrBuilder.buildCall(declaration.symbol) + val irCall = JsIrBuilder.buildCall(declaration.symbol, type = returnType) var cp = 0 var gp = 0 @@ -401,7 +421,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP irCall.putValueArgument(j++, JsIrBuilder.buildGetValue(closureParamSymbols[i])) } - val irClosureReturn = JsIrBuilder.buildReturn(closureFunction.symbol, irCall) + val irClosureReturn = JsIrBuilder.buildReturn(closureFunction.symbol, irCall, context) closureFunction.body = JsIrBuilder.buildBlockBody(listOf(irClosureReturn)) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/IntrinsicifyCallsLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/IntrinsicifyCallsLowering.kt index 5896b04bc4e..b19a112ea67 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/IntrinsicifyCallsLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/IntrinsicifyCallsLowering.kt @@ -6,7 +6,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass -import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.backend.common.utils.isSubtypeOfClass import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.utils.Namer @@ -19,10 +19,10 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.impl.originalKotlinType import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.SimpleType class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileLoweringPass { @@ -33,16 +33,13 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL private val symbolToIrFunction: Map private val nameToIrTransformer: Map IrCall> - val kCallable = context.builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.kCallable.toSafe()) - val kProperty = context.builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.kProperty.asSingleFqName()) - init { memberToIrFunction = mutableMapOf() symbolToIrFunction = mutableMapOf() memberToTransformer = mutableMapOf() nameToIrTransformer = mutableMapOf() - val primitiveNumbers = context.irBuiltIns.run { listOf(int, short, byte, float, double) } + val primitiveNumbers = context.irBuiltIns.run { listOf(intType, shortType, byteType, floatType, doubleType) } memberToIrFunction.run { for (type in primitiveNumbers) { @@ -57,11 +54,11 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL op(type, OperatorNames.REM, context.intrinsics.jsMod) } - context.irBuiltIns.string.let { + context.irBuiltIns.stringType.let { op(it, OperatorNames.ADD, context.intrinsics.jsPlus) } - context.irBuiltIns.int.let { + context.irBuiltIns.intType.let { op(it, OperatorNames.SHL, context.intrinsics.jsBitShiftL) op(it, OperatorNames.SHR, context.intrinsics.jsBitShiftR) op(it, OperatorNames.SHRU, context.intrinsics.jsBitShiftRU) @@ -71,7 +68,7 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL op(it, OperatorNames.INV, context.intrinsics.jsBitNot) } - context.irBuiltIns.bool.let { + context.irBuiltIns.booleanType.let { op(it, OperatorNames.AND, context.intrinsics.jsBitAnd) op(it, OperatorNames.OR, context.intrinsics.jsBitOr) op(it, OperatorNames.NOT, context.intrinsics.jsNot) @@ -99,12 +96,12 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL // TODO: use increment and decrement when it's possible op(type, OperatorNames.INC) { irCall(it, context.intrinsics.jsPlus.symbol, dispatchReceiverAsFirstArgument = true).apply { - putValueArgument(1, JsIrBuilder.buildInt(context.irBuiltIns.int, 1)) + putValueArgument(1, JsIrBuilder.buildInt(context.irBuiltIns.intType, 1)) } } op(type, OperatorNames.DEC) { irCall(it, context.intrinsics.jsMinus.symbol, dispatchReceiverAsFirstArgument = true).apply { - putValueArgument(1, JsIrBuilder.buildInt(context.irBuiltIns.int, 1)) + putValueArgument(1, JsIrBuilder.buildInt(context.irBuiltIns.intType, 1)) } } } @@ -113,18 +110,18 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL nameToIrTransformer.run { addWithPredicate( Name.special(Namer.KCALLABLE_GET_NAME), - { call -> call.symbol.owner.dispatchReceiverParameter?.run { DescriptorUtils.isSubtypeOfClass(type, kCallable) } ?: false }, + { call -> call.symbol.owner.dispatchReceiverParameter?.run { type.isSubtypeOfClass(context.irBuiltIns.kCallableClass) } ?: false }, { call -> irCall(call, context.intrinsics.jsName.symbol, dispatchReceiverAsFirstArgument = true) }) addWithPredicate( Name.identifier(Namer.KPROPERTY_GET), - { call -> call.symbol.owner.dispatchReceiverParameter?.run { DescriptorUtils.isSubtypeOfClass(type, kProperty) } ?: false }, + { call -> call.symbol.owner.dispatchReceiverParameter?.run { type.isSubtypeOfClass(context.irBuiltIns.kPropertyClass) } ?: false }, { call -> irCall(call, context.intrinsics.jsPropertyGet.symbol, dispatchReceiverAsFirstArgument = true)} ) addWithPredicate( Name.identifier(Namer.KPROPERTY_SET), - { call -> call.symbol.owner.dispatchReceiverParameter?.run { DescriptorUtils.isSubtypeOfClass(type, kProperty) } ?: false}, + { call -> call.symbol.owner.dispatchReceiverParameter?.run { type.isSubtypeOfClass(context.irBuiltIns.kPropertyClass) } ?: false}, { call -> irCall(call, context.intrinsics.jsPropertySet.symbol, dispatchReceiverAsFirstArgument = true)} ) } @@ -207,12 +204,11 @@ private fun IrCall.copyTypeAndValueArgumentsFrom(call: IrCall, dispatchReceiverA } } -private fun MutableMap.op(type: KotlinType, name: Name, v: V) { +private fun MutableMap.op(type: IrType, name: Name, v: V) { put(SimpleMemberKey(type, name), v) } -// TODO issue: marked as unused, but used; rename works wrongly. -private fun MutableMap.op(type: KotlinType, name: String, v: V) { +private fun MutableMap.op(type: IrType, name: String, v: V) { put(SimpleMemberKey(type, Name.identifier(name)), v) } @@ -232,4 +228,23 @@ private fun MutableMap IrCall>.addWithPredicate(from: K, pred private inline fun select(crossinline predicate: () -> Boolean, crossinline ifTrue: () -> T, crossinline ifFalse: () -> T): T = if (predicate()) ifTrue() else ifFalse() -private data class SimpleMemberKey(val klass: KotlinType, val name: Name) +private class SimpleMemberKey(val klass: IrType, val name: Name) { + // TODO drop custom equals and hashCode when IrTypes will have right equals + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as SimpleMemberKey + + if (name != other.name) return false + if (klass.originalKotlinType != other.klass.originalKotlinType) return false + + return true + } + + override fun hashCode(): Int { + var result = klass.originalKotlinType?.hashCode() ?: 0 + result = 31 * result + name.hashCode() + return result + } +} diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MultipleCatchesLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MultipleCatchesLowering.kt index 3fde18cf9fb..6c22c74451c 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MultipleCatchesLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MultipleCatchesLowering.kt @@ -6,6 +6,8 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.utils.commonSupertype +import org.jetbrains.kotlin.backend.common.utils.isSubtypeOf import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder @@ -18,11 +20,10 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCatchImpl import org.jetbrains.kotlin.ir.expressions.impl.IrElseBranchImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTryImpl import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol +import org.jetbrains.kotlin.ir.types.IrDynamicType +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.visitors.IrElementTransformer -import org.jetbrains.kotlin.types.CommonSupertypes -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.isDynamic -import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf /** * Since JS does not support multiple catch blocks by default we should replace them with similar `when` statement, so @@ -49,9 +50,9 @@ import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf */ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPass { - val litTrue = JsIrBuilder.buildBoolean(context.irBuiltIns.bool, true) - val unitType = context.irBuiltIns.unit - val nothingType = context.irBuiltIns.nothing + val litTrue = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true) + val unitType = context.irBuiltIns.unitType + val nothingType = context.irBuiltIns.nothingType override fun lower(irFile: IrFile) { irFile.transformChildren(object : IrElementTransformer { @@ -67,7 +68,7 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas val commonType = mergeTypes(aTry.catches.map { it.catchParameter.type }) val pendingExceptionSymbol = JsSymbolBuilder.buildVar(data!!.descriptor, commonType, "\$pending\$", false) - val pendingExceptionDeclaration = JsIrBuilder.buildVar(pendingExceptionSymbol) + val pendingExceptionDeclaration = JsIrBuilder.buildVar(pendingExceptionSymbol, type = commonType) val pendingException = JsIrBuilder.buildGetValue(pendingExceptionSymbol) val branches = mutableListOf() @@ -75,24 +76,27 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas for (catch in aTry.catches) { assert(!catch.catchParameter.isVar) { "caught exception parameter has to immutable" } val type = catch.catchParameter.type - val typeSymbol = context.symbolTable.referenceClassifier(type.constructor.declarationDescriptor!!) - val castedPendingException = buildImplicitCast(pendingException, type, typeSymbol) + val typeSymbol = type.classifierOrNull val catchBody = catch.result.transform(object : IrElementTransformer { override fun visitGetValue(expression: IrGetValue, data: VariableDescriptor) = - if (expression.descriptor == data) castedPendingException else expression + if (typeSymbol != null && expression.descriptor == data) + // TODO how is it good to generate implicit cast for each access? + buildImplicitCast(pendingException, type, typeSymbol) + else + expression }, catch.parameter) - if (type.isDynamic()) { + if (type is IrDynamicType) { branches += IrElseBranchImpl(catch.startOffset, catch.endOffset, litTrue, catchBody) break } else { - val typeCheck = buildIsCheck(pendingException, type, typeSymbol) + val typeCheck = buildIsCheck(pendingException, type, typeSymbol!!) branches += IrBranchImpl(catch.startOffset, catch.endOffset, typeCheck, catchBody) } } - if (!commonType.isDynamic()) { + if (commonType !is IrDynamicType) { val throwStatement = JsIrBuilder.buildThrow(nothingType, pendingException) branches += IrElseBranchImpl(litTrue, JsIrBuilder.buildBlock(nothingType, listOf(throwStatement))) } @@ -106,14 +110,14 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas return aTry.run { IrTryImpl(startOffset, endOffset, type, tryResult, listOf(newCatch), finallyExpression) } } - private fun buildIsCheck(value: IrExpression, toType: KotlinType, toTypeSymbol: IrClassifierSymbol) = - JsIrBuilder.buildTypeOperator(context.irBuiltIns.bool, IrTypeOperator.INSTANCEOF, value, toType, toTypeSymbol) + private fun buildIsCheck(value: IrExpression, toType: IrType, toTypeSymbol: IrClassifierSymbol) = + JsIrBuilder.buildTypeOperator(context.irBuiltIns.booleanType, IrTypeOperator.INSTANCEOF, value, toType, toTypeSymbol) - private fun buildImplicitCast(value: IrExpression, toType: KotlinType, toTypeSymbol: IrClassifierSymbol) = + private fun buildImplicitCast(value: IrExpression, toType: IrType, toTypeSymbol: IrClassifierSymbol) = JsIrBuilder.buildTypeOperator(toType, IrTypeOperator.IMPLICIT_CAST, value, toType, toTypeSymbol) - private fun mergeTypes(types: List) = CommonSupertypes.commonSupertype(types).also { - assert(it.isSubtypeOf(context.builtIns.throwable.defaultType) || it.isDynamic()) + private fun mergeTypes(types: List) = types.commonSupertype().also { + assert(it.isSubtypeOf(context.irBuiltIns.throwableType) || it is IrDynamicType) } }, null) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt index 5451e9f6476..6e5236c94d9 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt @@ -26,6 +26,8 @@ import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid @@ -72,8 +74,9 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor // val t = Object.create(Foo.prototype); // return Foo_init_$Init$(..., t) // } - val newInitConstructor = createInitConstructor(declaration, constructorName) - val newCreateConstructor = createCreateConstructor(declaration, newInitConstructor, constructorName) + + val newInitConstructor = createInitConstructor(declaration, constructorName, irClass.defaultType) + val newCreateConstructor = createCreateConstructor(declaration, newInitConstructor, constructorName, irClass.defaultType) oldCtorToNewMap[declaration.symbol] = JsIrBackendContext.SecondaryCtorPair(newInitConstructor.symbol, newCreateConstructor.symbol) @@ -95,14 +98,16 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor override fun visitReturn(expression: IrReturn): IrExpression = IrReturnImpl( expression.startOffset, expression.endOffset, + expression.type, function, - IrGetValueImpl(expression.startOffset, expression.endOffset, thisSymbol) + IrGetValueImpl(expression.startOffset, expression.endOffset, thisSymbol.owner.type, thisSymbol) ) override fun visitGetValue(expression: IrGetValue): IrExpression = if (expression.descriptor.name.isSpecial && expression.descriptor.name.asString() == Namer.THIS_SPECIAL_NAME) IrGetValueImpl( expression.startOffset, expression.endOffset, + expression.type, thisSymbol, expression.origin ) else { @@ -110,28 +115,32 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor } } - private fun createInitConstructor(declaration: IrConstructor, name: String): IrSimpleFunction = + private fun createInitConstructor( + declaration: IrConstructor, + name: String, + type: IrType + ): IrSimpleFunction = JsSymbolBuilder.copyFunctionSymbol(declaration.symbol, "${name}_\$Init\$").let { val thisSymbol = - JsSymbolBuilder.buildValueParameter(it, declaration.valueParameters.size, declaration.returnType, "\$this") + JsSymbolBuilder.buildValueParameter(it, declaration.valueParameters.size, type, "\$this") it.initialize( dispatchParameterDescriptor = declaration.descriptor.dispatchReceiverParameter, typeParameters = declaration.descriptor.typeParameters, valueParameters = declaration.descriptor.valueParameters + thisSymbol.descriptor as ValueParameterDescriptor, - type = declaration.descriptor.returnType, + returnType = type, modality = declaration.descriptor.modality, visibility = declaration.descriptor.visibility ) - val thisParam = JsIrBuilder.buildValueParameter(thisSymbol) + val thisParam = JsIrBuilder.buildValueParameter(thisSymbol, type) return IrFunctionImpl( declaration.startOffset, declaration.endOffset, declaration.origin, it ).apply { - val retStmt = JsIrBuilder.buildReturn(it, JsIrBuilder.buildGetValue(thisSymbol)) + val retStmt = JsIrBuilder.buildReturn(it, JsIrBuilder.buildGetValue(thisSymbol), context) val statements = (declaration.body as IrStatementContainer).statements valueParameters += (declaration.valueParameters + thisParam) @@ -145,13 +154,13 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor } - private fun createCreateConstructor(ctorOrig: IrConstructor, ctorImpl: IrSimpleFunction, name: String): IrSimpleFunction = + private fun createCreateConstructor(ctorOrig: IrConstructor, ctorImpl: IrSimpleFunction, name: String, type: IrType): IrSimpleFunction = JsSymbolBuilder.copyFunctionSymbol(ctorOrig.symbol, "${name}_\$Create\$").let { it.initialize( dispatchParameterDescriptor = ctorOrig.descriptor.dispatchReceiverParameter, typeParameters = ctorOrig.descriptor.typeParameters, valueParameters = ctorOrig.descriptor.valueParameters, - type = ctorOrig.returnType, + returnType = type, modality = ctorOrig.descriptor.modality, visibility = ctorOrig.visibility ) @@ -165,14 +174,14 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor typeParameters += ctorOrig.typeParameters // parent = ctorOrig.parent - val returnType = ctorOrig.returnType + val returnType = type val createFunctionIntrinsic = context.intrinsics.jsObjectCreate val irCreateCall = JsIrBuilder.buildCall( createFunctionIntrinsic.symbol, returnType, - mapOf(createFunctionIntrinsic.typeParameters[0].descriptor to returnType) + listOf(returnType) ) - val irDelegateCall = JsIrBuilder.buildCall(ctorImpl.symbol).also { + val irDelegateCall = JsIrBuilder.buildCall(ctorImpl.symbol, type).also { for (i in 0 until valueParameters.size) { it.putValueArgument(i, JsIrBuilder.buildGetValue(valueParameters[i].symbol)) } @@ -181,7 +190,7 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor // typeParameters.mapIndexed { i, t -> ctorImpl.typeParameters[i].descriptor -> } } - val irReturn = JsIrBuilder.buildReturn(it, irDelegateCall) + val irReturn = JsIrBuilder.buildReturn(it, irDelegateCall, context) body = JsIrBuilder.buildBlockBody(listOf(irReturn)) @@ -233,10 +242,11 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor IrGetValueImpl( expression.startOffset, expression.endOffset, + expression.type, IrValueParameterSymbolImpl(LazyClassReceiverParameterDescriptor(target.descriptor.containingDeclaration)) ) } else { - IrGetValueImpl(expression.startOffset, expression.endOffset, ownerFunc.valueParameters.last().symbol) + IrGetValueImpl(expression.startOffset, expression.endOffset, expression.type, ownerFunc.valueParameters.last().symbol) } newCall.putValueArgument(expression.valueArgumentsCount, readThis) @@ -247,7 +257,7 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor private fun redirectCall( call: IrFunctionAccessExpression, newTarget: IrSimpleFunctionSymbol - ) = IrCallImpl(call.startOffset, call.endOffset, newTarget).apply { + ) = IrCallImpl(call.startOffset, call.endOffset, call.type, newTarget).apply { copyTypeArgumentsFrom(call) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt index a47af1dea50..749855010c1 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt @@ -6,35 +6,34 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass -import org.jetbrains.kotlin.backend.common.descriptors.isFunctionOrKFunctionType -import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.backend.common.utils.* import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrArithBuilder import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.symbols.JsSymbolBuilder +import org.jetbrains.kotlin.ir.backend.js.utils.isReified import org.jetbrains.kotlin.ir.declarations.IrDeclaration 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.expressions.impl.IrCompositeImpl +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformer -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.isNullable -import org.jetbrains.kotlin.types.typeUtil.* class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { - private val unit = context.builtIns.unit - private val unitValue = JsIrBuilder.buildGetObjectValue(unit.defaultType, context.symbolTable.referenceClass(unit)) + private val unit = context.irBuiltIns.unitType + private val unitValue = JsIrBuilder.buildGetObjectValue(unit, unit.classifierOrFail as IrClassSymbol) - private val lit24 = JsIrBuilder.buildInt(context.builtIns.intType, 24) - private val lit16 = JsIrBuilder.buildInt(context.builtIns.intType, 16) + private val lit24 = JsIrBuilder.buildInt(context.irBuiltIns.intType, 24) + private val lit16 = JsIrBuilder.buildInt(context.irBuiltIns.intType, 16) - private val byteMask = JsIrBuilder.buildInt(context.builtIns.intType, 0xFF) - private val shortMask = JsIrBuilder.buildInt(context.builtIns.intType, 0xFFFF) + private val byteMask = JsIrBuilder.buildInt(context.irBuiltIns.intType, 0xFF) + private val shortMask = JsIrBuilder.buildInt(context.irBuiltIns.intType, 0xFFFF) private val calculator = JsIrArithBuilder(context) @@ -53,13 +52,13 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { private val typeOfIntrinsicSymbol = context.intrinsics.jsTypeOf.symbol private val toJSTypeIntrinsicSymbol = context.intrinsics.jsToJsType.symbol - private val stringMarker = JsIrBuilder.buildString(context.irBuiltIns.string, "string") - private val booleanMarker = JsIrBuilder.buildString(context.irBuiltIns.string, "boolean") - private val functionMarker = JsIrBuilder.buildString(context.irBuiltIns.string, "function") - private val numberMarker = JsIrBuilder.buildString(context.irBuiltIns.string, "number") + private val stringMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "string") + private val booleanMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "boolean") + private val functionMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "function") + private val numberMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "number") - private val litTrue: IrExpression = JsIrBuilder.buildBoolean(context.irBuiltIns.bool, true) - private val litNull: IrExpression = JsIrBuilder.buildNull(context.builtIns.nullableNothingType) + private val litTrue: IrExpression = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true) + private val litNull: IrExpression = JsIrBuilder.buildNull(context.irBuiltIns.nothingNType) private fun getInternalFunction(name: String) = context.symbolTable.referenceSimpleFunction(context.getInternalFunctions(name).single()) @@ -126,16 +125,21 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { } // Note: native `instanceOf` is not used which is important because of null-behaviour - private fun advancedCheckRequired(type: KotlinType) = type.isInterface() || - KotlinBuiltIns.isArray(type) || - KotlinBuiltIns.isPrimitiveArray(type) || + private fun advancedCheckRequired(type: IrType) = type.isInterface() || + type.isArray() || + type.isPrimitiveArray() || isTypeOfCheckingType(type) - private fun isTypeOfCheckingType(type: KotlinType) = - ((type.isPrimitiveNumberType() || KotlinBuiltIns.isNumber(type)) && !type.isLong() && !type.isChar()) || + private fun isTypeOfCheckingType(type: IrType) = + type.isByte() || + type.isShort() || + type.isInt() || + type.isFloat() || + type.isDouble() || + type.isNumber() || type.isBoolean() || - type.isFunctionOrKFunctionType || - KotlinBuiltIns.isString(type) + type.isFunctionOrKFunction() || + type.isString() fun lowerInstanceOf( expression: IrTypeOperatorCall, @@ -146,7 +150,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { assert((expression.operator == IrTypeOperator.NOT_INSTANCEOF) == inverted) val toType = expression.typeOperand - val isCopyRequired = expression.argument.type.isNullable() && advancedCheckRequired(toType.makeNotNullable()) + val isCopyRequired = expression.argument.type.isNullable() && advancedCheckRequired(toType.makeNotNull()) val newStatements = mutableListOf() val argument = @@ -167,12 +171,12 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { private fun cacheValue(value: IrExpression, newStatements: MutableList, cd: DeclarationDescriptor): IrExpression { val varSymbol = JsSymbolBuilder.buildTempVar(cd, value.type, mutable = false) - newStatements += JsIrBuilder.buildVar(varSymbol, value) + newStatements += JsIrBuilder.buildVar(varSymbol, value, value.type) return JsIrBuilder.buildGetValue(varSymbol) } - private fun generateTypeCheck(argument: IrExpression, toType: KotlinType): IrExpression { - val toNotNullable = toType.makeNotNullable() + private fun generateTypeCheck(argument: IrExpression, toType: IrType): IrExpression { + val toNotNullable = toType.makeNotNull() val instanceCheck = generateTypeCheckNonNull(argument, toNotNullable) val isFromNullable = argument.type.isNullable() val isToNullable = toType.isNullable() @@ -190,14 +194,14 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { } } - private fun generateTypeCheckNonNull(argument: IrExpression, toType: KotlinType): IrExpression { - assert(!toType.isMarkedNullable) + private fun generateTypeCheckNonNull(argument: IrExpression, toType: IrType): IrExpression { + assert(!toType.isMarkedNullable()) return when { - KotlinBuiltIns.isAny(toType) -> generateIsObjectCheck(argument) + toType.isAny() -> generateIsObjectCheck(argument) isTypeOfCheckingType(toType) -> generateTypeOfCheck(argument, toType) toType.isChar() -> generateCheckForChar(argument) - KotlinBuiltIns.isArray(toType) -> generateGenericArrayCheck(argument) - KotlinBuiltIns.isPrimitiveArray(toType) -> generatePrimitiveArrayTypeCheck(argument, toType) + toType.isArray() -> generateGenericArrayCheck(argument) + toType.isPrimitiveArray() -> generatePrimitiveArrayTypeCheck(argument, toType) toType.isTypeParameter() -> generateTypeCheckWithTypeParameter(argument, toType) toType.isInterface() -> generateInterfaceCheck(argument, toType) else -> generateNativeInstanceOf(argument, toType) @@ -208,12 +212,14 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { putValueArgument(0, argument) } - private fun generateTypeCheckWithTypeParameter(argument: IrExpression, toType: KotlinType): IrExpression { - val typeParameterDescriptor = toType.constructor.declarationDescriptor as TypeParameterDescriptor - assert(!typeParameterDescriptor.isReified) { "reified parameters have to be lowered before" } + private fun generateTypeCheckWithTypeParameter(argument: IrExpression, toType: IrType): IrExpression { + val typeParameter = + (toType.classifierOrNull as? IrTypeParameterSymbol)?.owner ?: error("expected type parameter, but $toType") - return typeParameterDescriptor.upperBounds.fold(litTrue) { r, t -> - val check = generateTypeCheckNonNull(argument, t.makeNotNullable()) + assert(!typeParameter.isReified) { "reified parameters have to be lowered before" } + + return typeParameter.superTypes.fold(litTrue) { r, t -> + val check = generateTypeCheckNonNull(argument, t.makeNotNull()) calculator.and(r, check) } } @@ -221,11 +227,11 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { private fun generateCheckForChar(argument: IrExpression) = JsIrBuilder.buildCall(isCharSymbol).apply { dispatchReceiver = argument } - private fun generateTypeOfCheck(argument: IrExpression, toType: KotlinType): IrExpression { + private fun generateTypeOfCheck(argument: IrExpression, toType: IrType): IrExpression { val marker = when { - toType.isFunctionOrKFunctionType -> functionMarker + toType.isFunctionOrKFunction() -> functionMarker toType.isBoolean() -> booleanMarker - KotlinBuiltIns.isString(toType) -> stringMarker + toType.isString() -> stringMarker else -> numberMarker } @@ -236,17 +242,17 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { } } - private fun wrapTypeReference(toType: KotlinType) = + private fun wrapTypeReference(toType: IrType) = JsIrBuilder.buildCall(toJSTypeIntrinsicSymbol).apply { putTypeArgument(0, toType) } private fun generateGenericArrayCheck(argument: IrExpression) = JsIrBuilder.buildCall(isArraySymbol).apply { putValueArgument(0, argument) } - private fun generatePrimitiveArrayTypeCheck(argument: IrExpression, toType: KotlinType): IrExpression { + private fun generatePrimitiveArrayTypeCheck(argument: IrExpression, toType: IrType): IrExpression { TODO("Implement Typed Array check") } - private fun generateInterfaceCheck(argument: IrExpression, toType: KotlinType): IrExpression { + private fun generateInterfaceCheck(argument: IrExpression, toType: IrType): IrExpression { val irType = wrapTypeReference(toType) return JsIrBuilder.buildCall(isInterfaceSymbol).apply { putValueArgument(0, argument) @@ -254,7 +260,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { } } - private fun generateNativeInstanceOf(argument: IrExpression, toType: KotlinType): IrExpression { + private fun generateNativeInstanceOf(argument: IrExpression, toType: IrType): IrExpression { val irType = wrapTypeReference(toType) return JsIrBuilder.buildCall(instanceOfIntrinsicSymbol).apply { putValueArgument(0, argument) @@ -264,12 +270,12 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { private fun lowerCoercionToUnit(expression: IrTypeOperatorCall): IrExpression { assert(expression.operator === IrTypeOperator.IMPLICIT_COERCION_TO_UNIT) - return expression.run { IrCompositeImpl(startOffset, endOffset, unit.defaultType, null, listOf(argument, unitValue)) } + return expression.run { IrCompositeImpl(startOffset, endOffset, unit, null, listOf(argument, unitValue)) } } private fun lowerIntegerCoercion(expression: IrTypeOperatorCall, containingDeclaration: DeclarationDescriptor): IrExpression { assert(expression.operator === IrTypeOperator.IMPLICIT_INTEGER_COERCION) - assert(KotlinBuiltIns.isInt(expression.argument.type)) + assert(expression.argument.type.isInt()) val isNullable = expression.argument.type.isNullable() val toType = expression.typeOperand @@ -284,9 +290,9 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { if (isNullable) cacheValue(expression.argument, newStatements, containingDeclaration) else expression.argument val casted = when { - KotlinBuiltIns.isByte(toType) -> maskOp(argument, byteMask, lit24) - KotlinBuiltIns.isShort(toType) -> maskOp(argument, shortMask, lit16) - KotlinBuiltIns.isLong(toType) -> TODO("Long coercion") + toType.isByte() -> maskOp(argument, byteMask, lit24) + toType.isShort() -> maskOp(argument, shortMask, lit16) + toType.isLong() -> TODO("Long coercion") else -> error("Unreachable execution (coercion to non-Integer type") } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/DeepCopyIrTreeWithDescriptors.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/DeepCopyIrTreeWithDescriptors.kt index cde7546716d..f5d3488194f 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/DeepCopyIrTreeWithDescriptors.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/DeepCopyIrTreeWithDescriptors.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.impl.createClassSymbolOrNull import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol +import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.DeepCopyIrTree import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid @@ -34,7 +35,6 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.Variance -import org.jetbrains.kotlin.types.typeUtil.makeNullable // backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DeepCopyIrTreeWithDescriptors.kt @@ -479,7 +479,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr return IrCallImpl( startOffset = expression.startOffset, endOffset = expression.endOffset, - type = newDescriptor.returnType!!, + type = newDescriptor.returnType?.toIrType()!!, descriptor = newDescriptor, typeArgumentsCount = expression.typeArgumentsCount, origin = expression.origin, @@ -517,7 +517,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr //---------------------------------------------------------------------// - fun getTypeOperatorReturnType(operator: IrTypeOperator, type: KotlinType) : KotlinType { + fun getTypeOperatorReturnType(operator: IrTypeOperator, type: IrType) : IrType { return when (operator) { IrTypeOperator.CAST, IrTypeOperator.IMPLICIT_CAST, @@ -526,7 +526,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr IrTypeOperator.IMPLICIT_INTEGER_COERCION -> type IrTypeOperator.SAFE_CAST -> type.makeNullable() IrTypeOperator.INSTANCEOF, - IrTypeOperator.NOT_INSTANCEOF -> context.builtIns.booleanType + IrTypeOperator.NOT_INSTANCEOF -> context.irBuiltIns.booleanType } } @@ -541,7 +541,8 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr type = returnType, operator = expression.operator, typeOperand = typeOperand, - argument = expression.argument.transform(this, null) + argument = expression.argument.transform(this, null), + typeOperandClassifier = typeOperand.classifierOrFail ) } @@ -610,6 +611,8 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr //-------------------------------------------------------------------------// + private fun substituteType(oldType: IrType?): IrType? = substituteType(oldType?.toKotlinType())?.toIrType() + private fun substituteType(oldType: KotlinType?): KotlinType? { if (typeSubstitutor == null) return oldType if (oldType == null) return oldType @@ -699,7 +702,8 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap< endOffset = declaration.endOffset, origin = declaration.origin, descriptor = newDescriptor, - initializer = declaration.initializer + initializer = declaration.initializer, + type = declaration.type ) } @@ -715,7 +719,8 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap< startOffset = expression.startOffset, endOffset = expression.endOffset, origin = expression.origin, - symbol = createValueSymbol(newDescriptor) + symbol = createValueSymbol(newDescriptor), + type = expression.type ) } @@ -732,7 +737,7 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap< return IrCallImpl( startOffset = oldExpression.startOffset, endOffset = oldExpression.endOffset, - type = newDescriptor.returnType!!, + type = oldExpression.type, symbol = createFunctionSymbol(newDescriptor), descriptor = newDescriptor, typeArgumentsCount = oldExpression.typeArgumentsCount, @@ -763,4 +768,3 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap< return oldExpression.shallowCopy(oldExpression.origin, createFunctionSymbol(newDescriptor), oldExpression.superQualifierSymbol) } } - diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/FunctionInlining.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/FunctionInlining.kt index 6f4382f4bda..478527f4f85 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/FunctionInlining.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/FunctionInlining.kt @@ -23,14 +23,16 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.getDefault import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl -import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol +import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.types.TypeProjection @@ -149,8 +151,8 @@ private class Inliner(val globalSubstituteMap: MutableMap() for (index in 0 until irCall.typeArgumentsCount) { val typeArgument = irCall.getTypeArgument(index) ?: continue - substitutionContext[typeParameters[index].typeConstructor] = TypeProjectionImpl(typeArgument) + substitutionContext[typeParameters[index].typeConstructor] = TypeProjectionImpl(typeArgument.toKotlinType()) } return TypeSubstitutor.create(substitutionContext) } @@ -309,7 +311,8 @@ private class Inliner(val globalSubstituteMap: MutableMap() - functionDescriptor.valueParameters.forEach { parameterDescriptor -> // Iterate value parameter descriptors. + irFunction.valueParameters.forEach { parameter -> // Iterate value parameter descriptors. + val parameterDescriptor = parameter.descriptor as ValueParameterDescriptor val argument = valueArguments[parameterDescriptor.index] // Get appropriate argument from call site. when { argument != null -> { // Argument is good enough. @@ -331,8 +334,8 @@ private class Inliner(val globalSubstituteMap: MutableMap - val newSymbol = symbol.replace(SymbolTable::referenceClass) - if (newSymbol != null) { - declaration.superClasses[index] = newSymbol - } - } withLocal(declaration.thisReceiver?.symbol) { return super.visitClass(declaration) } @@ -227,7 +226,7 @@ private class IrUnboundSymbolReplacer( expression.transformChildrenVoid(this) return with(expression) { - IrGetFieldImpl(startOffset, endOffset, symbol, receiver, origin, superQualifierSymbol) + IrGetFieldImpl(startOffset, endOffset, symbol, type, receiver, origin, superQualifierSymbol) } } @@ -242,11 +241,13 @@ private class IrUnboundSymbolReplacer( expression.transformChildrenVoid(this) return with(expression) { - IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value, origin, superQualifierSymbol) + IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value, type /*wrong*/, origin, superQualifierSymbol) } } override fun visitCall(expression: IrCall): IrExpression { + expression.replaceTypeArguments() + val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?: expression.symbol val superQualifierSymbol = expression.superQualifierSymbol?.replaceOrSame(SymbolTable::referenceClass) @@ -257,17 +258,21 @@ private class IrUnboundSymbolReplacer( expression.transformChildrenVoid() return with(expression) { - IrCallImpl(startOffset, endOffset, symbol, descriptor, - getTypeArgumentsMap(), - origin, superQualifierSymbol).also { + IrCallImpl(startOffset, endOffset, type, symbol, descriptor, + typeArgumentsCount, + origin, superQualifierSymbol).also { it.copyArgumentsFrom(this) + it.copyTypeArgumentsFrom(this) } } } - private fun IrMemberAccessExpression.getTypeArgumentsMap() = - descriptor.original.typeParameters.associate { it to getTypeArgumentOrDefault(it) } + private fun IrMemberAccessExpression.replaceTypeArguments() { + repeat(typeArgumentsCount) { + putTypeArgument(it, getTypeArgument(it)/*?.toKotlinType()?.let { context.ir.translateErased(it) }*/) + } + } private fun IrMemberAccessExpressionBase.copyArgumentsFrom(original: IrMemberAccessExpression) { dispatchReceiver = original.dispatchReceiver @@ -279,40 +284,48 @@ private class IrUnboundSymbolReplacer( override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression { val symbol = expression.symbol.replace(SymbolTable::referenceConstructor) ?: - return super.visitEnumConstructorCall(expression) + return super.visitEnumConstructorCall(expression) return with(expression) { - IrEnumConstructorCallImpl(startOffset, endOffset, symbol, null).also { + IrEnumConstructorCallImpl(startOffset, endOffset, expression.type, symbol, 0).also { it.copyArgumentsFrom(this) } } } override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { + expression.replaceTypeArguments() + val symbol = expression.symbol.replace(SymbolTable::referenceConstructor) ?: - return super.visitDelegatingConstructorCall(expression) + return super.visitDelegatingConstructorCall(expression) expression.transformChildrenVoid() return with(expression) { - IrDelegatingConstructorCallImpl(startOffset, endOffset, symbol, descriptor, getTypeArgumentsMap()).also { + IrDelegatingConstructorCallImpl(startOffset, endOffset, type, symbol, descriptor, typeArgumentsCount).also { it.copyArgumentsFrom(this) + it.copyTypeArgumentsFrom(this) } } } override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { + expression.replaceTypeArguments() + val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?: - return super.visitFunctionReference(expression) + return super.visitFunctionReference(expression) expression.transformChildrenVoid(this) return with(expression) { - IrFunctionReferenceImpl(startOffset, endOffset, type, symbol, descriptor, getTypeArgumentsMap()).also { + IrFunctionReferenceImpl(startOffset, endOffset, type, symbol, descriptor, 0).also { it.copyArgumentsFrom(this) + it.copyTypeArgumentsFrom(this) } } } override fun visitPropertyReference(expression: IrPropertyReference): IrExpression { + expression.replaceTypeArguments() + val field = expression.field?.replaceOrSame(SymbolTable::referenceField) val getter = expression.getter?.replace(SymbolTable::referenceFunction) ?: expression.getter val setter = expression.setter?.replace(SymbolTable::referenceFunction) ?: expression.setter @@ -323,13 +336,14 @@ private class IrUnboundSymbolReplacer( expression.transformChildrenVoid(this) return with(expression) { - IrPropertyReferenceImpl(startOffset, endOffset, type, descriptor, - field, - getter, - setter, - getTypeArgumentsMap(), origin).also { + IrPropertyReferenceImpl(startOffset, endOffset, type, descriptor, 0, + field, + getter, + setter, + origin).also { it.copyArgumentsFrom(this) + it.copyTypeArgumentsFrom(this) } } } @@ -346,7 +360,7 @@ private class IrUnboundSymbolReplacer( expression.transformChildrenVoid(this) return with(expression) { IrLocalDelegatedPropertyReferenceImpl(startOffset, endOffset, type, descriptor, - delegate, getter, setter, origin).also { + delegate, getter, setter, origin).also { it.copyArgumentsFrom(this) } @@ -406,12 +420,24 @@ private class IrUnboundSymbolReplacer( override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression { val classSymbol = expression.classSymbol.replace(SymbolTable::referenceClass) ?: - return super.visitInstanceInitializerCall(expression) + return super.visitInstanceInitializerCall(expression) expression.transformChildrenVoid(this) return with(expression) { - IrInstanceInitializerCallImpl(startOffset, endOffset, classSymbol) + IrInstanceInitializerCallImpl(startOffset, endOffset, classSymbol, type) + } + } + + override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression { + expression.transformChildrenVoid(this) + + return with(expression) { + val newTypeOperand = typeOperand /*context.ir.translateErased(typeOperand.toKotlinType())*/ + IrTypeOperatorCallImpl(startOffset, endOffset, type, operator, newTypeOperand).also { + it.argument = argument + it.typeOperandClassifier = newTypeOperand.classifierOrFail + } } } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/IrUtils2.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/IrUtils2.kt index 99575377221..93c97f26fee 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/IrUtils2.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/IrUtils2.kt @@ -5,10 +5,11 @@ package org.jetbrains.kotlin.ir.backend.js.lower.inline -import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer +import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.visitors.IrElementVisitor @@ -19,21 +20,6 @@ fun IrSimpleFunction.setOverrides(symbolTable: SymbolTable) { this.descriptor.overriddenDescriptors.mapTo(this.overriddenSymbols) { symbolTable.referenceSimpleFunction(it.original) } - - this.typeParameters.forEach { it.setSupers(symbolTable) } -} - -fun IrTypeParameter.setSupers(symbolTable: SymbolTable) { - assert(this.superClassifiers.isEmpty()) - this.descriptor.upperBounds.mapNotNullTo(this.superClassifiers) { - it.constructor.declarationDescriptor?.let { - if (it is TypeParameterDescriptor) { - IrTypeParameterSymbolImpl(it) // Workaround for deserialized inline functions - } else { - symbolTable.referenceClassifier(it) - } - } - } } fun IrDeclarationContainer.addChildren(declarations: List) { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/NewIrUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/NewIrUtils.kt index 5f7782cb545..47d9c7ed2ad 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/NewIrUtils.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/NewIrUtils.kt @@ -13,6 +13,8 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.getTypeArgumentOrDefault +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid @@ -43,6 +45,10 @@ fun IrModuleFragment.referenceAllTypeExternalClassifiers(symbolTable: SymbolTabl } } + fun IrType.referenceAllClassifiers() { + this.toKotlinType().referenceAllClassifiers() + } + val visitor = object : IrElementVisitorVoid { override fun visitElement(element: IrElement) { element.acceptChildrenVoid(this) @@ -125,4 +131,4 @@ fun IrModuleFragment.referenceAllTypeExternalClassifiers(symbolTable: SymbolTabl it.acceptVoid(visitor) } } -} \ No newline at end of file +} diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/ReturnableBlockLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/ReturnableBlockLowering.kt index c3305bf1053..a9b421865a9 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/ReturnableBlockLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/inline/ReturnableBlockLowering.kt @@ -10,14 +10,18 @@ import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.symbols.JsSymbolBuilder -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner +import org.jetbrains.kotlin.ir.expressions.IrContainerExpression +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrReturn +import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl import org.jetbrains.kotlin.ir.expressions.impl.IrDoWhileLoopImpl import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol import org.jetbrains.kotlin.ir.visitors.IrElementTransformer -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid /** * Replaces returnable blocks and `return`'s with loops and `break`'s correspondingly. @@ -93,7 +97,7 @@ private class ReturnableBlockTransformer( return super.visitDeclaration(declaration, data) } - private val constFalse = JsIrBuilder.buildBoolean(context.builtIns.booleanType, false) + private val constFalse = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, false) override fun visitContainerExpression(expression: IrContainerExpression, data: ReturnableBlockLoweringContext): IrExpression { if (expression !is IrReturnableBlock) return super.visitContainerExpression(expression, data) @@ -111,7 +115,7 @@ private class ReturnableBlockTransformer( IrDoWhileLoopImpl( expression.startOffset, expression.endOffset, - context.builtIns.unitType, + context.irBuiltIns.unitType, expression.origin ).apply { label = "l\$ret\$${data.labelCnt++}" @@ -127,10 +131,10 @@ private class ReturnableBlockTransformer( IrCompositeImpl( returnExpression.startOffset, returnExpression.endOffset, - context.builtIns.unitType + context.irBuiltIns.unitType ).apply { - statements += JsIrBuilder.buildSetVariable(variable, returnExpression.value) - statements += JsIrBuilder.buildBreak(context.builtIns.unitType, loop) + statements += JsIrBuilder.buildSetVariable(variable, returnExpression.value, context.irBuiltIns.unitType) + statements += JsIrBuilder.buildBreak(context.irBuiltIns.unitType, loop) } } @@ -138,7 +142,7 @@ private class ReturnableBlockTransformer( if (i == expression.statements.lastIndex && s is IrReturn && s.returnTargetSymbol == expression.symbol) { s.transformChildren(this, data) if (!hasReturned) s.value else { - JsIrBuilder.buildSetVariable(variable, s.value) + JsIrBuilder.buildSetVariable(variable, s.value, context.irBuiltIns.unitType) } } else { s.transform(this, data) @@ -159,7 +163,7 @@ private class ReturnableBlockTransformer( loop.body = IrBlockImpl( expression.startOffset, expression.endOffset, - context.builtIns.unitType, + context.irBuiltIns.unitType, expression.origin, newStatements ) @@ -170,7 +174,7 @@ private class ReturnableBlockTransformer( expression.type, expression.origin ).apply { - statements += JsIrBuilder.buildVar(variable) + statements += JsIrBuilder.buildVar(variable, type = expression.type) statements += loop statements += JsIrBuilder.buildGetValue(variable) } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/symbols/SymbolBuilder.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/symbols/SymbolBuilder.kt index aacccde4b88..a4e340da162 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/symbols/SymbolBuilder.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/symbols/SymbolBuilder.kt @@ -18,12 +18,13 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.types.KotlinType object JsSymbolBuilder { - fun buildValueParameter(containingSymbol: IrSimpleFunctionSymbol, index: Int, type: KotlinType, name: String? = null) = - IrValueParameterSymbolImpl(createValueParameter(containingSymbol.descriptor, index, name ?: "param$index", type)) + fun buildValueParameter(containingSymbol: IrSimpleFunctionSymbol, index: Int, type: IrType, name: String? = null) = + IrValueParameterSymbolImpl(createValueParameter(containingSymbol.descriptor, index, name ?: "param$index", type.toKotlinType())) fun buildSimpleFunction( containingDeclaration: DeclarationDescriptor, @@ -53,7 +54,7 @@ object JsSymbolBuilder { fun buildVar( containingDeclaration: DeclarationDescriptor, - type: KotlinType, + type: IrType, name: String, mutable: Boolean = false ) = IrVariableSymbolImpl( @@ -61,42 +62,42 @@ object JsSymbolBuilder { containingDeclaration, Annotations.EMPTY, Name.identifier(name), - type, + type.toKotlinType(), mutable, false, SourceElement.NO_SOURCE ) ) - fun buildTempVar(containingSymbol: IrSymbol, type: KotlinType, name: String? = null, mutable: Boolean = false) = + fun buildTempVar(containingSymbol: IrSymbol, type: IrType, name: String? = null, mutable: Boolean = false) = buildTempVar(containingSymbol.descriptor, type, name, mutable) - fun buildTempVar(containingDeclaration: DeclarationDescriptor, type: KotlinType, name: String? = null, mutable: Boolean = false) = + fun buildTempVar(containingDeclaration: DeclarationDescriptor, type: IrType, name: String? = null, mutable: Boolean = false) = IrVariableSymbolImpl( IrTemporaryVariableDescriptorImpl( containingDeclaration, Name.identifier(name ?: "tmp"), - type, mutable + type.toKotlinType(), mutable ) ) } fun IrSimpleFunctionSymbol.initialize( - receiverParameterType: KotlinType? = null, + receiverParameterType: IrType? = null, dispatchParameterDescriptor: ReceiverParameterDescriptor? = null, typeParameters: List = emptyList(), valueParameters: List = emptyList(), - type: KotlinType? = null, + returnType: IrType? = null, modality: Modality = Modality.FINAL, visibility: Visibility = Visibilities.LOCAL ) = this.apply { (descriptor as FunctionDescriptorImpl).initialize( - receiverParameterType, + receiverParameterType?.toKotlinType(), dispatchParameterDescriptor, typeParameters, valueParameters, - type, + returnType?.toKotlinType(), modality, visibility ) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt index ddb44782fd0..a1e27e9c25f 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt @@ -5,15 +5,15 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs -import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype +import org.jetbrains.kotlin.backend.common.utils.isFunctionTypeOrSubtype import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext import org.jetbrains.kotlin.ir.backend.js.utils.Namer import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.js.backend.ast.* -import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.util.OperatorNameConventions class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer { @@ -158,7 +158,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer { - if (baseClass == null || baseClass.isAny) { + if (baseClass == null || baseClass.isAny()) { return emptyList() } @@ -158,7 +160,13 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo private fun generateSuperClasses(): JsPropertyInitializer = JsPropertyInitializer( JsNameRef(Namer.METADATA_INTERFACES), - JsArrayLiteral(irClass.superClasses.filter { it.owner.isInterface }.map { JsNameRef(context.getNameForSymbol(it.owner.symbol)) }) + JsArrayLiteral( + irClass.superTypes.mapNotNull { + val symbol = it.classifierOrFail + if (symbol.isInterface) JsNameRef(context.getNameForSymbol(symbol)) else null + } + ) ) - } + +private val IrClassifierSymbol.isInterface get() = (owner as? IrClass)?.isInterface == true \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt index 1e9f94cf591..d6fae12ea3a 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt @@ -5,14 +5,13 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs -import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext import org.jetbrains.kotlin.ir.backend.js.utils.Namer import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl +import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.js.backend.ast.* typealias IrCallTransformer = (IrCall, context: JsGenerationContext) -> JsExpression @@ -69,7 +68,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { add(intrinsics.jsObjectCreate) { call, context -> val classToCreate = call.getTypeArgument(0)!! - val className = context.getNameForSymbol(IrClassSymbolImpl(classToCreate.constructor.declarationDescriptor as ClassDescriptor)) + val className = context.getNameForSymbol(classToCreate.classifierOrFail) val prototype = prototypeOf(className.makeRef()) JsInvocation(Namer.JS_OBJECT_CREATE_FUNCTION, prototype) } @@ -86,8 +85,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { } add(intrinsics.jsToJsType) { call, context -> - val typeParameter = call.getTypeArgument(0)!! - val typeName = context.getNameForSymbol(IrClassSymbolImpl(typeParameter.constructor.declarationDescriptor as ClassDescriptor)) + val typeName = context.getNameForSymbol(call.getTypeArgument(0)!!.classifierOrFail) typeName.makeRef() }