From 48fe46303d8cf7ea8308c1ccd1d03db59287969f Mon Sep 17 00:00:00 2001 From: Anton Bannykh Date: Wed, 2 Jun 2021 18:56:13 +0300 Subject: [PATCH] JS IR: declare intrinsics for lowerings in stdlib - simplifies lowered IR serialization - removes some hacks in jsOperators.kt - intrinsics can be directly invoked in stdlib --- .../org/jetbrains/kotlin/ir/backend/js/Dce.kt | 2 +- .../kotlin/ir/backend/js/JsIntrinsics.kt | 265 ++++-------------- .../ir/backend/js/JsSharedVariablesManager.kt | 6 +- .../js/lower/BlockDecomposerLowering.kt | 2 +- .../lower/JsDefaultArgumentStubGenerator.kt | 2 +- ...MoveBodilessDeclarationsToSeparatePlace.kt | 11 +- .../backend/js/lower/SecondaryCtorLowering.kt | 2 +- .../ir/backend/js/lower/ThrowableLowering.kt | 2 +- .../irToJs/IrModuleToJsTransformer.kt | 1 - .../irToJs/JsIntrinsicTransformers.kt | 4 + .../kotlin/ir/descriptors/IrBuiltIns.kt | 2 +- .../stdlib/js-ir/runtime/jsIntrinsics.kt | 207 ++++++++++++++ 12 files changed, 287 insertions(+), 219 deletions(-) create mode 100644 libraries/stdlib/js-ir/runtime/jsIntrinsics.kt diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/Dce.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/Dce.kt index 14197879a7b..aa2b39ea620 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/Dce.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/Dce.kt @@ -411,7 +411,7 @@ fun usefulDeclarations(roots: Iterable, context: JsIrBackendConte val ref = expression.getTypeArgument(0)?.classOrNull ?: context.irBuiltIns.anyClass referencedJsClassesFromExpressions += ref.owner } - context.intrinsics.jsObjectCreate.symbol -> { + context.intrinsics.jsObjectCreate -> { val classToCreate = expression.getTypeArgument(0)!!.classifierOrFail.owner as IrClass classToCreate.enqueue("intrinsic: jsObjectCreate") constructedClasses += classToCreate 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 caba6e281a5..5a617bc1116 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 @@ -34,69 +34,68 @@ import java.util.* class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendContext) { - val externalPackageFragment = IrExternalPackageFragmentImpl.createEmptyExternalPackageFragment( - context.builtIns.builtInsModule, FqName("kotlin.js.internal") - ) - // TODO: Should we drop operator intrinsics in favor of IrDynamicOperatorExpression? // Equality operations: - val jsEqeq = binOpBool("jsEqeq") - val jsNotEq = binOpBool("jsNotEq") - val jsEqeqeq = binOpBool("jsEqeqeq") - val jsNotEqeq = binOpBool("jsNotEqeq") + val jsEqeq = getInternalFunction("jsEqeq") + val jsNotEq = getInternalFunction("jsNotEq") + val jsEqeqeq = getInternalFunction("jsEqeqeq") + val jsNotEqeq = getInternalFunction("jsNotEqeq") - val jsGt = binOpBool("jsGt") - val jsGtEq = binOpBool("jsGtEq") - val jsLt = binOpBool("jsLt") - val jsLtEq = binOpBool("jsLtEq") + val jsGt = getInternalFunction("jsGt") + val jsGtEq = getInternalFunction("jsGtEq") + val jsLt = getInternalFunction("jsLt") + val jsLtEq = getInternalFunction("jsLtEq") // Unary operations: - val jsNot = unOpBool("jsNot") + val jsNot = getInternalFunction("jsNot") - val jsUnaryPlus = unOp("jsUnaryPlus") - val jsUnaryMinus = unOp("jsUnaryMinus") + val jsUnaryPlus = getInternalFunction("jsUnaryPlus") + val jsUnaryMinus = getInternalFunction("jsUnaryMinus") - val jsPrefixInc = unOp("jsPrefixInc") - val jsPostfixInc = unOp("jsPostfixInc") - val jsPrefixDec = unOp("jsPrefixDec") - val jsPostfixDec = unOp("jsPostfixDec") + val jsPrefixInc = getInternalFunction("jsPrefixInc") + val jsPostfixInc = getInternalFunction("jsPostfixInc") + val jsPrefixDec = getInternalFunction("jsPrefixDec") + val jsPostfixDec = getInternalFunction("jsPostfixDec") + + val jsDelete = getInternalFunction("jsDelete") // Binary operations: - val jsPlus = binOp("jsPlus") - val jsMinus = binOp("jsMinus") - val jsMult = binOp("jsMult") - val jsDiv = binOp("jsDiv") - val jsMod = binOp("jsMod") + val jsPlus = getInternalFunction("jsPlus") + val jsMinus = getInternalFunction("jsMinus") + val jsMult = getInternalFunction("jsMult") + val jsDiv = getInternalFunction("jsDiv") + val jsMod = getInternalFunction("jsMod") - val jsPlusAssign = binOp("jsPlusAssign") - val jsMinusAssign = binOp("jsMinusAssign") - val jsMultAssign = binOp("jsMultAssign") - val jsDivAssign = binOp("jsDivAssign") - val jsModAssign = binOp("jsModAssign") + val jsPlusAssign = getInternalFunction("jsPlusAssign") + val jsMinusAssign = getInternalFunction("jsMinusAssign") + val jsMultAssign = getInternalFunction("jsMultAssign") + val jsDivAssign = getInternalFunction("jsDivAssign") + val jsModAssign = getInternalFunction("jsModAssign") - val jsAnd = binOp("jsAnd") - val jsOr = binOp("jsOr") + val jsAnd = getInternalFunction("jsAnd") + val jsOr = getInternalFunction("jsOr") + val jsIn = getInternalFunction("jsInIntrinsic") // Bit operations: - val jsBitAnd = binOpInt("jsBitAnd") - val jsBitOr = binOpInt("jsBitOr") - val jsBitXor = binOpInt("jsBitXor") - val jsBitNot = unOpInt("jsBitNot") + val jsBitAnd = getInternalFunction("jsBitAnd") + val jsBitOr = getInternalFunction("jsBitOr") + val jsBitXor = getInternalFunction("jsBitXor") + val jsBitNot = getInternalFunction("jsBitNot") - val jsBitShiftR = binOpInt("jsBitShiftR") - val jsBitShiftRU = binOpInt("jsBitShiftRU") - val jsBitShiftL = binOpInt("jsBitShiftL") + val jsBitShiftR = getInternalFunction("jsBitShiftR") + val jsBitShiftRU = getInternalFunction("jsBitShiftRU") + val jsBitShiftL = getInternalFunction("jsBitShiftL") // Type checks: - val jsInstanceOf = binOpBool("jsInstanceOf") + val jsInstanceOf = getInternalFunction("jsInstanceOfIntrinsic") val jsTypeOf = getInternalFunction("jsTypeOf") // Number conversions: @@ -144,7 +143,7 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC // Other: - val jsObjectCreate = defineObjectCreateIntrinsic() // Object.create + val jsObjectCreate = getInternalFunction("objectCreate") // Object.create val jsCode = getInternalFunction("js") // js("") val jsHashCode = getInternalFunction("hashCode") val jsGetNumberHashCode = getInternalFunction("getNumberHashCode") @@ -155,10 +154,10 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC val jsCompareTo = getInternalFunction("compareTo") val jsEquals = getInternalFunction("equals") val jsConstruct = getInternalFunction("construct") - val jsNewTarget = unOp("jsNewTarget") - val jsEmptyObject = unOp("emptyObject") - val jsOpenInitializerBox = binOp("openInitializerBox") - val es6DefaultType = defineEs6DefaultTypeIntrinsic().symbol + val jsNewTarget = getInternalFunction("jsNewTarget") + val jsEmptyObject = getInternalFunction("emptyObject") + val jsOpenInitializerBox = getInternalFunction("openInitializerBox") + val es6DefaultType = getInternalFunction("DefaultType") val jsImul = getInternalFunction("imul") @@ -174,8 +173,7 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC val jsGetKClass = getInternalWithoutPackage("getKClass") val jsGetKClassFromExpression = getInternalWithoutPackage("getKClassFromExpression") - private val jsClassClassSymbol = getInternalClassWithoutPackage("kotlin.js.JsClass") - val jsClass = defineJsClassIntrinsic().symbol + val jsClass = getInternalFunction("jsClassIntrinsic") val jsNumberRangeToNumber = getInternalFunction("numberRangeToNumber") val jsNumberRangeToLong = getInternalFunction("numberRangeToLong") @@ -214,7 +212,7 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC val uIntClassSymbol by context.lazy2 { getInternalClassWithoutPackage("kotlin.UInt") } val uLongClassSymbol by context.lazy2 { getInternalClassWithoutPackage("kotlin.ULong") } - val unreachable = defineUnreachableIntrinsic() + val unreachable = getInternalFunction("unreachable") val returnIfSuspended = getInternalFunction("returnIfSuspended") val getContinuation = getInternalFunction("getContinuation") @@ -230,16 +228,16 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC val jsArray = getInternalFunction("arrayWithFun") val jsFillArray = getInternalFunction("fillArrayFun") - val jsArrayLength = unOp("jsArrayLength") - val jsArrayGet = binOp("jsArrayGet") - val jsArraySet = tripleOp("jsArraySet") + val jsArrayLength = getInternalFunction("jsArrayLength") + val jsArrayGet = getInternalFunction("jsArrayGet") + val jsArraySet = getInternalFunction("jsArraySet") val jsArrayIteratorFunction = getInternalFunction("arrayIterator") val jsPrimitiveArrayIteratorFunctions = PrimitiveType.values().associate { it to getInternalFunction("${it.typeName.asString().toLowerCaseAsciiOnly()}ArrayIterator") } - val arrayLiteral = unOp("arrayLiteral") + val arrayLiteral = getInternalFunction("arrayLiteral") val primitiveToTypedArrayMap = EnumMap( mapOf( @@ -262,14 +260,14 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC val primitiveToSizeConstructor = PrimitiveType.values().associate { type -> type to (primitiveToTypedArrayMap[type]?.let { - unOp("${it.toLowerCaseAsciiOnly()}Array") + getInternalFunction("${it.toLowerCaseAsciiOnly()}Array") } ?: getInternalFunction("${type.typeName.asString().toLowerCaseAsciiOnly()}Array")) } val primitiveToLiteralConstructor = PrimitiveType.values().associate { type -> type to (primitiveToTypedArrayMap[type]?.let { - unOp("${it.toLowerCaseAsciiOnly()}ArrayOf") + getInternalFunction("${it.toLowerCaseAsciiOnly()}ArrayOf") } ?: getInternalFunction("${type.typeName.asString().toLowerCaseAsciiOnly()}ArrayOf")) } @@ -278,9 +276,9 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC val primitiveArrayConcat = getInternalWithoutPackage("primitiveArrayConcat") val taggedArrayCopy = getInternalWithoutPackage("taggedArrayCopy") - val jsArraySlice = defineJsSliceIntrinsic().symbol + val jsArraySlice = getInternalFunction("slice") - val jsBind = defineJsBindIntrinsic() + val jsBind = getInternalFunction("jsBind") // TODO move to IntrinsifyCallsLowering val doNotIntrinsifyAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("DoNotIntrinsify")) @@ -311,15 +309,15 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC val captureStack = getInternalFunction("captureStack") - val createSharedBox = defineCreateSharedBox() - val readSharedBox = defineReadSharedBox() - val writeSharedBox = defineWriteSharedBox() + val createSharedBox = getInternalFunction("sharedBoxCreate") + val readSharedBox = getInternalFunction("sharedBoxRead") + val writeSharedBox = getInternalFunction("sharedBoxWrite") val safePropertyGet = getInternalFunction("safePropertyGet") val safePropertySet = getInternalFunction("safePropertySet") - val jsUndefined = defineJsUndefinedIntrinsic() + val jsUndefined = getInternalFunction("jsUndefined") // Helpers: @@ -339,153 +337,4 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC private fun getInternalClassWithoutPackage(fqName: String) = context.symbolTable.referenceClass(context.getClass(FqName(fqName))) - - private val irFactory: IrFactory get() = context.irFactory - - // TODO: unify how we create intrinsic symbols - private fun defineObjectCreateIntrinsic(): IrSimpleFunction { - return irFactory.addFunction(externalPackageFragment) { - name = Name.identifier("Object\$create") - origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB - }.apply { - returnType = addTypeParameter("T", irBuiltIns.anyType).defaultType - } - } - - private fun defineCreateSharedBox(): IrSimpleFunction { - return irFactory.addFunction(externalPackageFragment) { - name = Name.identifier("\$sharedBox\$create") - origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB - returnType = context.dynamicType - }.apply { - val tp = addTypeParameter("T", irBuiltIns.anyNType) - addValueParameter { - index = 0 - name = Name.identifier("v") - type = IrSimpleTypeBuilder().run { - classifier = tp.symbol - hasQuestionMark = true - buildSimpleType() - } - } - } - } - - private fun defineReadSharedBox(): IrSimpleFunction { - return irFactory.addFunction(externalPackageFragment) { - name = Name.identifier("\$sharedBox\$read") - origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB - }.apply { - val tp = addTypeParameter("T", irBuiltIns.anyNType) - returnType = IrSimpleTypeBuilder().run { - classifier = tp.symbol - hasQuestionMark = true - buildSimpleType() - } - addValueParameter { - index = 0 - name = Name.identifier("box") - type = context.dynamicType - } - } - } - - private fun defineWriteSharedBox(): IrSimpleFunction { - return irFactory.addFunction(externalPackageFragment) { - name = Name.identifier("\$sharedBox\$write") - origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB - returnType = irBuiltIns.unitType - }.apply { - val tp = addTypeParameter("T", irBuiltIns.anyNType) - addValueParameter { - index = 0 - name = Name.identifier("box") - type = context.dynamicType - } - addValueParameter { - index = 1 - name = Name.identifier("nv") - type = IrSimpleTypeBuilder().run { - classifier = tp.symbol - hasQuestionMark = true - buildSimpleType() - } - } - } - } - - private fun defineJsUndefinedIntrinsic(): IrSimpleFunction { - return irFactory.addFunction(externalPackageFragment) { - name = Name.identifier("\$undefined") - }.apply { - returnType = context.irBuiltIns.nothingNType - } - } - - private fun defineEs6DefaultTypeIntrinsic(): IrSimpleFunction { - return irFactory.addFunction(externalPackageFragment) { - name = Name.identifier("DefaultType") - }.apply { - returnType = addTypeParameter("T", irBuiltIns.anyType).defaultType - } - } - - private fun defineJsBindIntrinsic(): IrSimpleFunction { - return irFactory.addFunction(externalPackageFragment) { - name = Name.identifier("\$jsBind\$") - origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB - returnType = irBuiltIns.anyNType - }.apply { - listOf("receiver", "target").forEach { addValueParameter(it, irBuiltIns.anyType) } - } - } - - private fun defineJsSliceIntrinsic(): IrSimpleFunction { - return irFactory.addFunction(externalPackageFragment) { - name = Name.identifier("slice") - origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB - }.apply { - val aType = addTypeParameter("A", irBuiltIns.anyType).defaultType - returnType = aType - addValueParameter("a", aType) - } - } - - private fun defineUnreachableIntrinsic(): IrSimpleFunction { - return irFactory.addFunction(externalPackageFragment) { - name = Name.identifier(Namer.UNREACHABLE_NAME) - origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB - returnType = irBuiltIns.nothingType - } - } - - private fun defineJsClassIntrinsic(): IrSimpleFunction { - return irFactory.addFunction(externalPackageFragment) { - name = Name.identifier("jsClass") - origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB - isInline = true - }.apply { - val typeParameter = addTypeParameter { - name = Name.identifier("T") - isReified = true - superTypes += irBuiltIns.anyType - } - returnType = jsClassClassSymbol.typeWithParameters(listOf(typeParameter)) - } - } - - private fun unOp(name: String, returnType: IrType = irBuiltIns.anyNType) = - irBuiltIns.run { defineOperator(name, returnType, listOf(anyNType)) } - - private fun unOpBool(name: String) = unOp(name, irBuiltIns.booleanType) - private fun unOpInt(name: String) = unOp(name, irBuiltIns.intType) - - private fun binOp(name: String, returnType: IrType = irBuiltIns.anyNType) = - irBuiltIns.run { defineOperator(name, returnType, listOf(anyNType, anyNType)) } - - private fun tripleOp(name: String, returnType: IrType = irBuiltIns.anyNType) = - irBuiltIns.run { defineOperator(name, returnType, listOf(anyNType, anyNType, anyNType)) } - - private fun binOpBool(name: String) = binOp(name, irBuiltIns.booleanType) - private fun binOpInt(name: String) = binOp(name, irBuiltIns.intType) } 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 178d9b23ff1..fec2eac22d1 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 @@ -21,9 +21,9 @@ import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol class JsSharedVariablesManager(context: JsIrBackendContext) : SharedVariablesManager { private val builtIns: IrBuiltIns = context.irBuiltIns - private val createBox: IrSimpleFunctionSymbol = context.intrinsics.createSharedBox.symbol - private val readBox: IrSimpleFunctionSymbol = context.intrinsics.readSharedBox.symbol - private val writeBox: IrSimpleFunctionSymbol = context.intrinsics.writeSharedBox.symbol + private val createBox: IrSimpleFunctionSymbol = context.intrinsics.createSharedBox + private val readBox: IrSimpleFunctionSymbol = context.intrinsics.readSharedBox + private val writeBox: IrSimpleFunctionSymbol = context.intrinsics.writeSharedBox private val dynamicType = context.dynamicType override fun declareSharedVariable(originalDeclaration: IrVariable): IrVariable { 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 08dfdce5d4f..29330e540bf 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 @@ -32,7 +32,7 @@ import org.jetbrains.kotlin.utils.addIfNotNull class JsBlockDecomposerLowering(val context: JsIrBackendContext) : AbstractBlockDecomposerLowering(context) { override fun unreachableExpression(): IrExpression = - JsIrBuilder.buildCall(context.intrinsics.unreachable.symbol, context.irBuiltIns.nothingType) + JsIrBuilder.buildCall(context.intrinsics.unreachable, context.irBuiltIns.nothingType) } abstract class AbstractBlockDecomposerLowering( diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultArgumentStubGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultArgumentStubGenerator.kt index 4fb8a7189ff..9d1af0b0a5f 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultArgumentStubGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultArgumentStubGenerator.kt @@ -107,7 +107,7 @@ class JsDefaultCallbackGenerator(val context: JsIrBackendContext): BodyLoweringP startOffset, endOffset, context.irBuiltIns.anyType, - context.intrinsics.jsBind.symbol, + context.intrinsics.jsBind, valueArgumentsCount = 2, typeArgumentsCount = 0, origin = BIND_CALL, diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt index 19b5a475805..b72e04fc5b8 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.backend.js.utils.getJsQualifier import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl import org.jetbrains.kotlin.ir.symbols.impl.IrFileSymbolImpl +import org.jetbrains.kotlin.ir.util.constructedClass import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.isEffectivelyExternal import org.jetbrains.kotlin.ir.util.render @@ -46,6 +47,14 @@ private val BODILESS_BUILTIN_CLASSES = listOf( private fun isBuiltInClass(declaration: IrDeclaration): Boolean = declaration is IrClass && declaration.fqNameWhenAvailable in BODILESS_BUILTIN_CLASSES +private val JsPackage = FqName("kotlin.js") + +private val JsIntrinsicFqName = FqName("kotlin.js.JsIntrinsic") + +private fun isIntrinsic(declaration: IrDeclaration): Boolean = + declaration is IrSimpleFunction && (declaration.parent as? IrPackageFragment)?.fqName == JsPackage && + declaration.annotations.any { it.symbol.owner.constructedClass.fqNameWhenAvailable == JsIntrinsicFqName } + fun moveBodilessDeclarationsToSeparatePlace(context: JsIrBackendContext, moduleFragment: IrModuleFragment) { MoveBodilessDeclarationsToSeparatePlaceLowering(context).let { moveBodiless -> moduleFragment.files.forEach { @@ -80,7 +89,7 @@ class MoveBodilessDeclarationsToSeparatePlaceLowering(private val context: JsIrB } else { val d = declaration as? IrDeclarationWithName ?: return null - if (isBuiltInClass(d)) { + if (isBuiltInClass(d) || isIntrinsic(d)) { context.bodilessBuiltInsPackageFragment.addChild(d) d.collectAllExternalDeclarations() 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 82a21740879..2a2be12dfe3 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 @@ -86,7 +86,7 @@ class SecondaryConstructorLowering(val context: JsIrBackendContext) : Declaratio stub.body = context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) { val type = irClass.defaultType val createFunctionIntrinsic = context.intrinsics.jsObjectCreate - val irCreateCall = JsIrBuilder.buildCall(createFunctionIntrinsic.symbol, type, listOf(type)) + val irCreateCall = JsIrBuilder.buildCall(createFunctionIntrinsic, type, listOf(type)) val irDelegateCall = JsIrBuilder.buildCall(delegate.symbol, type).also { call -> for (i in 0 until stub.typeParameters.size) { call.putTypeArgument(i, stub.typeParameters[i].toIrType()) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ThrowableLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ThrowableLowering.kt index cf0a9a73618..189894afe56 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ThrowableLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ThrowableLowering.kt @@ -28,7 +28,7 @@ class ThrowableLowering( private val throwableConstructors = context.throwableConstructors private val newThrowableFunction = context.newThrowableSymbol - private val jsUndefined = context.intrinsics.jsUndefined.symbol + private val jsUndefined = context.intrinsics.jsUndefined fun nullValue(): IrExpression = IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, nothingNType) fun undefinedValue(): IrExpression = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, nothingNType, jsUndefined, 0, 0) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt index 44cfb3afd7e..90c465aef27 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt @@ -40,7 +40,6 @@ class IrModuleToJsTransformer( val additionalPackages = with(backendContext) { externalPackageFragment.values + listOf( bodilessBuiltInsPackageFragment, - intrinsics.externalPackageFragment ) + packageLevelJsModules } 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 0cca8e77a95..a728fe027d2 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 @@ -55,6 +55,8 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { prefixOp(intrinsics.jsPrefixDec, JsUnaryOperator.DEC) postfixOp(intrinsics.jsPostfixDec, JsUnaryOperator.DEC) + prefixOp(intrinsics.jsDelete, JsUnaryOperator.DELETE) + binOp(intrinsics.jsPlus, JsBinaryOperator.ADD) binOp(intrinsics.jsMinus, JsBinaryOperator.SUB) binOp(intrinsics.jsMult, JsBinaryOperator.MUL) @@ -78,6 +80,8 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { binOp(intrinsics.jsInstanceOf, JsBinaryOperator.INSTANCEOF) + binOp(intrinsics.jsIn, JsBinaryOperator.INOP) + prefixOp(intrinsics.jsTypeOf, JsUnaryOperator.TYPEOF) add(intrinsics.jsObjectCreate) { call, context -> diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt index a499065b010..0eca607339e 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt @@ -54,7 +54,7 @@ class IrBuiltIns( private fun ClassDescriptor.toIrSymbol() = symbolTable.referenceClass(this) private fun KotlinType.toIrType() = typeTranslator.translateType(this) - fun defineOperator(name: String, returnType: IrType, valueParameterTypes: List): IrSimpleFunctionSymbol { + private fun defineOperator(name: String, returnType: IrType, valueParameterTypes: List): IrSimpleFunctionSymbol { val operatorDescriptor = IrSimpleBuiltinOperatorDescriptorImpl(packageFragmentDescriptor, Name.identifier(name), returnType.originalKotlinType!!) diff --git a/libraries/stdlib/js-ir/runtime/jsIntrinsics.kt b/libraries/stdlib/js-ir/runtime/jsIntrinsics.kt new file mode 100644 index 00000000000..f9cd6eee603 --- /dev/null +++ b/libraries/stdlib/js-ir/runtime/jsIntrinsics.kt @@ -0,0 +1,207 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:Suppress("NON_MEMBER_FUNCTION_NO_BODY") + +package kotlin.js + +@RequiresOptIn(message = "Here be dragons! This is a compiler intrinsic, proceed with care!") +@Retention(AnnotationRetention.BINARY) +@Target(AnnotationTarget.FUNCTION) +internal annotation class JsIntrinsic + +@JsIntrinsic +internal fun jsEqeq(a: Any?, b: Any?): Boolean + +@JsIntrinsic +internal fun jsNotEq(a: Any?, b: Any?): Boolean + +@JsIntrinsic +internal fun jsEqeqeq(a: Any?, b: Any?): Boolean + +@JsIntrinsic +internal fun jsNotEqeq(a: Any?, b: Any?): Boolean + +@JsIntrinsic +internal fun jsGt(a: Any?, b: Any?): Boolean + +@JsIntrinsic +internal fun jsGtEq(a: Any?, b: Any?): Boolean + +@JsIntrinsic +internal fun jsLt(a: Any?, b: Any?): Boolean + +@JsIntrinsic +internal fun jsLtEq(a: Any?, b: Any?): Boolean + +@JsIntrinsic +internal fun jsNot(a: Any?): Boolean + +@JsIntrinsic +internal fun jsUnaryPlus(a: Any?): Any? + +@JsIntrinsic +internal fun jsUnaryMinus(a: Any?): Any? + +@JsIntrinsic +internal fun jsPrefixInc(a: Any?): Any? + +@JsIntrinsic +internal fun jsPostfixInc(a: Any?): Any? + +@JsIntrinsic +internal fun jsPrefixDec(a: Any?): Any? + +@JsIntrinsic +internal fun jsPostfixDec(a: Any?): Any? + +@JsIntrinsic +internal fun jsPlus(a: Any?, b: Any?): Any? + +@JsIntrinsic +internal fun jsMinus(a: Any?, b: Any?): Any? + +@JsIntrinsic +internal fun jsMult(a: Any?, b: Any?): Any? + +@JsIntrinsic +internal fun jsDiv(a: Any?, b: Any?): Any? + +@JsIntrinsic +internal fun jsMod(a: Any?, b: Any?): Any? + +@JsIntrinsic +internal fun jsPlusAssign(a: Any?, b: Any?): Any? + +@JsIntrinsic +internal fun jsMinusAssign(a: Any?, b: Any?): Any? + +@JsIntrinsic +internal fun jsMultAssign(a: Any?, b: Any?): Any? + +@JsIntrinsic +internal fun jsDivAssign(a: Any?, b: Any?): Any? + +@JsIntrinsic +internal fun jsModAssign(a: Any?, b: Any?): Any? + +@JsIntrinsic +internal fun jsAnd(a: Any?, b: Any?): Any? + +@JsIntrinsic +internal fun jsOr(a: Any?, b: Any?): Any? + +@JsIntrinsic +internal fun jsBitAnd(a: Any?, b: Any?): Int + +@JsIntrinsic +internal fun jsBitOr(a: Any?, b: Any?): Int + +@JsIntrinsic +internal fun jsBitXor(a: Any?, b: Any?): Int + +@JsIntrinsic +internal fun jsBitNot(a: Any?): Int + +@JsIntrinsic +internal fun jsBitShiftR(a: Any?, b: Any?): Int + +@JsIntrinsic +internal fun jsBitShiftRU(a: Any?, b: Any?): Int + +@JsIntrinsic +internal fun jsBitShiftL(a: Any?, b: Any?): Int + +@JsIntrinsic +internal fun jsInstanceOfIntrinsic(a: Any?, b: Any?): Boolean + +@JsIntrinsic +internal fun jsNewTarget(a: Any?): Any? + +@JsIntrinsic +internal fun emptyObject(a: Any?): Any? + +@JsIntrinsic +internal fun openInitializerBox(a: Any?, b: Any?): Any? + +@JsIntrinsic +internal fun jsArrayLength(a: Any?): Any? + +@JsIntrinsic +internal fun jsArrayGet(a: Any?, b: Any?): Any? + +@JsIntrinsic +internal fun jsArraySet(a: Any?, b: Any?, c: Any?): Any? + +@JsIntrinsic +internal fun arrayLiteral(a: Any?): Any? + +@JsIntrinsic +internal fun int8Array(a: Any?): Any? + +@JsIntrinsic +internal fun int16Array(a: Any?): Any? + +@JsIntrinsic +internal fun int32Array(a: Any?): Any? + +@JsIntrinsic +internal fun float32Array(a: Any?): Any? + +@JsIntrinsic +internal fun float64Array(a: Any?): Any? + +@JsIntrinsic +internal fun int8ArrayOf(a: Any?): Any? + +@JsIntrinsic +internal fun int16ArrayOf(a: Any?): Any? + +@JsIntrinsic +internal fun int32ArrayOf(a: Any?): Any? + +@JsIntrinsic +internal fun float32ArrayOf(a: Any?): Any? + +@JsIntrinsic +internal fun float64ArrayOf(a: Any?): Any? + +@JsIntrinsic +internal fun objectCreate(): T + +@JsIntrinsic +internal fun sharedBoxCreate(v: T?): dynamic + +@JsIntrinsic +internal fun sharedBoxRead(box: dynamic): T? + +@JsIntrinsic +internal fun sharedBoxWrite(box: dynamic, nv: T?) + +@JsIntrinsic +internal fun jsUndefined(): Nothing? + +@JsIntrinsic +internal fun DefaultType(): T + +@JsIntrinsic +internal fun jsBind(receiver: Any?, target: Any?): Any? + +@JsIntrinsic +internal fun slice(a: A): A + +@JsIntrinsic +internal fun unreachable(): Nothing + +@JsIntrinsic +@Suppress("REIFIED_TYPE_PARAMETER_NO_INLINE") // TODO: mark `inline` and skip in inliner +internal fun jsClassIntrinsic(): JsClass + +// Returns true if the specified property is in the specified object or its prototype chain. +@JsIntrinsic +internal fun jsInIntrinsic(lhs: Any?, rhs: Any): Boolean + +@JsIntrinsic +internal fun jsDelete(e: Any?) \ No newline at end of file