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 d8d6e984f93..eb25690bac9 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 @@ -8,14 +8,16 @@ package org.jetbrains.kotlin.ir.backend.js import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.utils.Namer +import org.jetbrains.kotlin.ir.builders.declarations.addFunction +import org.jetbrains.kotlin.ir.builders.declarations.addTypeParameter +import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl -import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeBuilder -import org.jetbrains.kotlin.ir.types.impl.buildSimpleType +import org.jetbrains.kotlin.ir.types.defaultType import org.jetbrains.kotlin.ir.types.isLong import org.jetbrains.kotlin.ir.util.constructors import org.jetbrains.kotlin.ir.util.findDeclaration @@ -86,14 +88,6 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC val jsBitShiftRU = binOpInt("jsBitShiftRU") val jsBitShiftL = binOpInt("jsBitShiftL") - - // KFunction operations: - - val jsName = unOp("kCallableName", irBuiltIns.string) - val jsPropertyGet = binOp("kPropertyGet") - val jsPropertySet = tripleOp("kPropertySet", irBuiltIns.unit) - - // Type checks: val jsInstanceOf = binOpBool("jsInstanceOf") @@ -145,8 +139,6 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC // Other: val jsObjectCreate = defineObjectCreateIntrinsic() // Object.create - val jsGetJSField = defineGetJSPropertyIntrinsic() // TODO: Replace with dynamic operators - val jsSetJSField = defineSetJSPropertyIntrinsic() // TODO: Replace with dynamic operators val jsCode = getInternalFunction("js") // js("") val jsHashCode = getInternalFunction("hashCode") val jsGetObjectHashCode = getInternalFunction("getObjectHashCode") @@ -295,90 +287,42 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC // TODO: unify how we create intrinsic symbols private fun defineObjectCreateIntrinsic(): IrSimpleFunction { - return JsIrBuilder.buildFunction( - "Object\$create", - returnType = irBuiltIns.anyType, - parent = externalPackageFragment, - isInline = true, + return externalPackageFragment.addFunction { + name = Name.identifier("Object\$create") origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB - ).also { - val typeParameter = JsIrBuilder.buildTypeParameter(Name.identifier("T"), 0, true) - typeParameter.parent = it - typeParameter.superTypes += irBuiltIns.anyType - it.typeParameters += typeParameter - externalPackageFragment.declarations += it + }.apply { + returnType = addTypeParameter("T", irBuiltIns.anyType).defaultType } } - private fun defineGetJSPropertyIntrinsic() = - JsIrBuilder.buildFunction( - "\$getJSProperty\$", - returnType = irBuiltIns.anyNType, - parent = externalPackageFragment, + private fun defineJsBindIntrinsic(): IrSimpleFunction { + return externalPackageFragment.addFunction { + name = Name.identifier("\$jsBind\$") origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB - ).also { - listOf("receiver", "fieldName").mapIndexedTo(it.valueParameters) { i, p -> - JsIrBuilder.buildValueParameter(p, i, irBuiltIns.anyType).also { v -> v.parent = it } - } - externalPackageFragment.declarations += it - } - - private fun defineJsBindIntrinsic() = - JsIrBuilder.buildFunction( - "\$jsBind\$", - returnType = irBuiltIns.anyNType, - parent = externalPackageFragment, - origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB - ).also { - listOf("receiver", "target").mapIndexedTo(it.valueParameters) { i, p -> - JsIrBuilder.buildValueParameter(p, i, irBuiltIns.anyType).also { v -> v.parent = it } - } - externalPackageFragment.declarations += it + returnType = irBuiltIns.anyNType + }.apply { + listOf("receiver", "target").forEach { addValueParameter(it, irBuiltIns.anyType) } } + } private fun defineJsSliceIntrinsic(): IrSimpleFunction { - val typeParameter = JsIrBuilder.buildTypeParameter(Name.identifier("A"), 0, true).apply { - superTypes += irBuiltIns.anyType - } - val type = IrSimpleTypeBuilder().run { - classifier = typeParameter.symbol - buildSimpleType() - } - - return JsIrBuilder.buildFunction( - "slice", - returnType = type, - parent = externalPackageFragment, + return externalPackageFragment.addFunction { + name = Name.identifier("slice") origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB - ).also { - it.typeParameters += typeParameter.also { t -> t.parent = it } - it.valueParameters += JsIrBuilder.buildValueParameter("a", 0, type).also { v -> v.parent = it } - externalPackageFragment.declarations += it + }.apply { + val aType = addTypeParameter("A", irBuiltIns.anyType).defaultType + returnType = aType + addValueParameter("a", aType) } } - private fun defineSetJSPropertyIntrinsic() = - JsIrBuilder.buildFunction( - "\$setJSProperty\$", - returnType = irBuiltIns.unitType, - parent = externalPackageFragment, + private fun defineUnreachableIntrinsic(): IrSimpleFunction { + return externalPackageFragment.addFunction { + name = Name.identifier(Namer.UNREACHABLE_NAME) origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB - ).also { - listOf("receiver", "fieldName", "fieldValue").mapIndexedTo(it.valueParameters) { i, p -> - JsIrBuilder.buildValueParameter(p, i, irBuiltIns.anyType).also { v -> v.parent = it } - } - externalPackageFragment.declarations += it - } - - private fun defineUnreachableIntrinsic() = - JsIrBuilder.buildFunction( - Namer.UNREACHABLE_NAME, - returnType = irBuiltIns.nothingType, - parent = externalPackageFragment, - origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB - ).also { - externalPackageFragment.declarations += it + returnType = irBuiltIns.nothingType } + } private fun unOp(name: String, returnType: KotlinType = irBuiltIns.anyN) = irBuiltIns.run { defineOperator(name, returnType, listOf(anyN)) } 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 344b09fca64..f9534cafbbf 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 @@ -20,9 +20,7 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl +import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl @@ -45,11 +43,7 @@ data class CallableReferenceKey( // TODO: generate $metadata$ property and fill it with corresponding KFunction/KProperty interface class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringPass { - private val callableNameConst get() = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KCALLABLE_NAME) - private val getterConst get() = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KPROPERTY_GET) - private val setterConst get() = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KPROPERTY_SET) private val callableToFactoryFunction = context.callableReferencesCache - private val newDeclarations = mutableListOf() private val implicitDeclarationFile = context.implicitDeclarationFile @@ -170,11 +164,10 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP val irVar = JsIrBuilder.buildVar(irClosureReference.type, factoryFunction, initializer = irClosureReference) // TODO: fill other fields of callable reference (returnType, parameters, isFinal, etc.) - val irSetName = JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply { - putValueArgument(0, JsIrBuilder.buildGetValue(irVar.symbol)) - putValueArgument(1, callableNameConst) - putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.stringType, getReferenceName(declaration))) + val irSetName = setDynamicProperty(irVar.symbol, Namer.KCALLABLE_NAME) { + JsIrBuilder.buildString(context.irBuiltIns.stringType, getReferenceName(declaration)) } + Pair(listOf(closureFunction, irVar, irSetName), irVar.symbol) } @@ -221,10 +214,8 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP statements += irVar - statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply { - putValueArgument(0, JsIrBuilder.buildGetValue(irVar.symbol)) - putValueArgument(1, getterConst) - putValueArgument(2, JsIrBuilder.buildGetValue(irVar.symbol)) + statements += setDynamicProperty(irVar.symbol, Namer.KPROPERTY_GET) { + JsIrBuilder.buildGetValue(irVar.symbol) } if (setterFunction != null) { @@ -232,22 +223,14 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP val setterFunctionTypeSymbol = context.ir.symbols.functionN(setterFunction.valueParameters.size + 1) val setterFunctionIrType = IrSimpleTypeImpl(setterFunctionTypeSymbol, false, emptyList(), emptyList()) val irSetReference = JsIrBuilder.buildFunctionReference(setterFunctionIrType, setterFunction.symbol) - statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply { - putValueArgument(0, JsIrBuilder.buildGetValue(irVar.symbol)) - putValueArgument(1, setterConst) - putValueArgument(2, irSetReference) - } + statements += setDynamicProperty(irVar.symbol, Namer.KPROPERTY_SET) { irSetReference } } // TODO: fill other fields of callable reference (returnType, parameters, isFinal, etc.) - statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply { - putValueArgument(0, JsIrBuilder.buildGetValue(irVar.symbol)) - putValueArgument(1, callableNameConst) - putValueArgument( - 2, JsIrBuilder.buildString( - context.irBuiltIns.stringType, - getReferenceName(getterDeclaration.correspondingPropertySymbol!!.owner) - ) + statements += setDynamicProperty(irVar.symbol, Namer.KCALLABLE_NAME) { + JsIrBuilder.buildString( + context.irBuiltIns.stringType, + getReferenceName(getterDeclaration.correspondingPropertySymbol!!.owner) ) } @@ -291,16 +274,12 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP statements += irVar - statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply { - putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol)) - putValueArgument(1, getterConst) - putValueArgument(2, JsIrBuilder.buildGetValue(irVarSymbol)) + statements += setDynamicProperty(irVarSymbol, Namer.KPROPERTY_GET) { + JsIrBuilder.buildGetValue(irVarSymbol) } - statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply { - putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol)) - putValueArgument(1, callableNameConst) - putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.stringType, getReferenceName(declaration))) + statements += setDynamicProperty(irVarSymbol, Namer.KCALLABLE_NAME) { + JsIrBuilder.buildString(context.irBuiltIns.stringType, getReferenceName(declaration)) } Pair(statements, irVarSymbol) @@ -572,4 +551,11 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP return closureFunction } + + private inline fun setDynamicProperty(r: IrValueSymbol, property: String, value: () -> IrExpression): IrStatement { + return IrDynamicOperatorExpressionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.unitType, IrDynamicOperator.EQ).apply { + receiver = IrDynamicMemberExpressionImpl(startOffset, endOffset, context.dynamicType, property, JsIrBuilder.buildGetValue(r)) + arguments += value() + } + } } 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 a547ba31874..2532087d218 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 @@ -45,7 +45,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { private val isInterfaceSymbol get() = context.intrinsics.isInterfaceSymbol private val isArraySymbol get() = context.intrinsics.isArraySymbol - private val isSuspenfFunctionSymbol = context.intrinsics.isSuspendFunctionSymbol + private val isSuspendFunctionSymbol = context.intrinsics.isSuspendFunctionSymbol // private val isCharSymbol get() = context.intrinsics.isCharSymbol private val isObjectSymbol get() = context.intrinsics.isObjectSymbol @@ -188,14 +188,6 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { } private fun generateTypeCheck(argument: () -> IrExpressionWithCopy, toType: IrType): IrExpression { - - // TODO: Fix unbound symbols (in inline) - toType.classifierOrNull?.apply { - if (!isBound) { - return argument() - } - } - val toNotNullable = toType.makeNotNull() val argumentInstance = argument() val instanceCheck = generateTypeCheckNonNull(argumentInstance, toNotNullable) @@ -248,11 +240,6 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { val typeParameterSymbol = (toType.classifierOrNull as? IrTypeParameterSymbol) ?: error("expected type parameter, but $toType") - // TODO: Stop creating unbound symbols inline: - // DeepCopyIrTreeWithDescriptors.copy() -> ... -> ClassifierDescriptor.getSymbol() - if (!typeParameterSymbol.isBound) { - return argument - } val typeParameter = typeParameterSymbol.owner // TODO either remove functions with reified type parameters or support this case @@ -270,7 +257,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { val arity = (toType.classifierOrFail.owner as IrClass).typeParameters.size - 1 // drop return type val irBuiltIns = context.irBuiltIns - return JsIrBuilder.buildCall(isSuspenfFunctionSymbol, irBuiltIns.booleanType).apply { + return JsIrBuilder.buildCall(isSuspendFunctionSymbol, irBuiltIns.booleanType).apply { putValueArgument(0, argument) putValueArgument(1, JsIrBuilder.buildInt(irBuiltIns.intType, arity)) } 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 fc11f18048c..3e506f32906 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 @@ -87,27 +87,6 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { JsInvocation(Namer.JS_OBJECT_CREATE_FUNCTION, prototype) } - add(intrinsics.jsGetJSField) { call, context -> - val args = translateCallArguments(call, context) - val receiver = args[0] - val fieldName = args[1] as JsStringLiteral - - val fieldNameLiteral = fieldName.value!! - - JsNameRef(fieldNameLiteral, receiver) - } - - add(intrinsics.jsSetJSField) { call, context -> - val args = translateCallArguments(call, context) - val receiver = args[0] - val fieldName = args[1] as JsStringLiteral - val fieldValue = args[2] - - val fieldNameLiteral = fieldName.value!! - - jsAssignment(JsNameRef(fieldNameLiteral, receiver), fieldValue) - } - add(intrinsics.jsClass) { call, context -> val classifier: IrClassifierSymbol = call.getTypeArgument(0)!!.classifierOrFail val owner = classifier.owner @@ -126,32 +105,11 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { when (jsCode) { is JsExpression -> jsCode - // TODO don't generate function for this case + // TODO don't generate function for this case else -> JsInvocation(JsFunction(emptyScope, jsCode as? JsBlock ?: JsBlock(jsCode as JsStatement), "")) } } - add(intrinsics.jsName) { call, context -> - val args = translateCallArguments(call, context) - val receiver = args[0] - JsNameRef(Namer.KCALLABLE_NAME, receiver) - } - - add(intrinsics.jsPropertyGet) { call, context -> - val args = translateCallArguments(call, context) - val reference = args[0] - val receiver = args[1] - JsInvocation(JsNameRef(Namer.KPROPERTY_GET, reference), listOf(receiver)) - } - - add(intrinsics.jsPropertySet) { call, context -> - val args = translateCallArguments(call, context) - val reference = args[0] - val receiver = args[1] - val value = args[2] - JsInvocation(JsNameRef(Namer.KPROPERTY_SET, reference), listOf(receiver, value)) - } - add(intrinsics.jsGetContinuation) { _, context: JsGenerationContext -> context.continuation }