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
This commit is contained in:
committed by
teamcityserver
parent
94384ce2ca
commit
48fe46303d
@@ -411,7 +411,7 @@ fun usefulDeclarations(roots: Iterable<IrDeclaration>, 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
|
||||
|
||||
@@ -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("<code>")
|
||||
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)
|
||||
}
|
||||
|
||||
+3
-3
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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(
|
||||
|
||||
+1
-1
@@ -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,
|
||||
|
||||
+10
-1
@@ -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()
|
||||
|
||||
|
||||
+1
-1
@@ -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())
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
-1
@@ -40,7 +40,6 @@ class IrModuleToJsTransformer(
|
||||
val additionalPackages = with(backendContext) {
|
||||
externalPackageFragment.values + listOf(
|
||||
bodilessBuiltInsPackageFragment,
|
||||
intrinsics.externalPackageFragment
|
||||
) + packageLevelJsModules
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -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 ->
|
||||
|
||||
@@ -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<IrType>): IrSimpleFunctionSymbol {
|
||||
private fun defineOperator(name: String, returnType: IrType, valueParameterTypes: List<IrType>): IrSimpleFunctionSymbol {
|
||||
val operatorDescriptor =
|
||||
IrSimpleBuiltinOperatorDescriptorImpl(packageFragmentDescriptor, Name.identifier(name), returnType.originalKotlinType!!)
|
||||
|
||||
|
||||
@@ -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 <T> objectCreate(): T
|
||||
|
||||
@JsIntrinsic
|
||||
internal fun <T> sharedBoxCreate(v: T?): dynamic
|
||||
|
||||
@JsIntrinsic
|
||||
internal fun <T> sharedBoxRead(box: dynamic): T?
|
||||
|
||||
@JsIntrinsic
|
||||
internal fun <T> sharedBoxWrite(box: dynamic, nv: T?)
|
||||
|
||||
@JsIntrinsic
|
||||
internal fun jsUndefined(): Nothing?
|
||||
|
||||
@JsIntrinsic
|
||||
internal fun <T> DefaultType(): T
|
||||
|
||||
@JsIntrinsic
|
||||
internal fun jsBind(receiver: Any?, target: Any?): Any?
|
||||
|
||||
@JsIntrinsic
|
||||
internal fun <A> 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 <reified T : Any> jsClassIntrinsic(): JsClass<T>
|
||||
|
||||
// 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?)
|
||||
Reference in New Issue
Block a user