[JS IR BE] Covert Char into inline class
This commit is contained in:
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
|
||||
private fun FileLoweringPass.lower(moduleFragment: IrModuleFragment) = moduleFragment.files.forEach { lower(it) }
|
||||
|
||||
@@ -371,13 +370,13 @@ val jsPhases = listOf(
|
||||
TypeOperatorLoweringPhase,
|
||||
SecondaryConstructorLoweringPhase,
|
||||
SecondaryFactoryInjectorLoweringPhase,
|
||||
ClassReferenceLoweringPhase,
|
||||
InlineClassLoweringPhase,
|
||||
AutoboxingTransformerPhase,
|
||||
BlockDecomposerLoweringPhase,
|
||||
ClassReferenceLoweringPhase,
|
||||
PrimitiveCompanionLoweringPhase,
|
||||
ConstLoweringPhase,
|
||||
CallsLoweringPhase,
|
||||
IrModuleEndPhase,
|
||||
IrToJsPhase
|
||||
)
|
||||
)
|
||||
|
||||
+7
-4
@@ -6,14 +6,15 @@
|
||||
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.util.irCall
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.util.irCall
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
@@ -29,9 +30,11 @@ private class ArrayConstructorTransformer(
|
||||
val context: JsIrBackendContext
|
||||
) : IrElementTransformerVoid() {
|
||||
|
||||
private val primitiveArrayInlineToSizeConstructorMap = context.intrinsics.primitiveArrays.keys.associate {
|
||||
it.inlineConstructor to it.sizeConstructor
|
||||
}
|
||||
// Inline constructor for CharArray is implemented in runtime
|
||||
private val primitiveArrayInlineToSizeConstructorMap =
|
||||
context.intrinsics.primitiveArrays.filter { it.value != PrimitiveType.CHAR }.keys.associate {
|
||||
it.inlineConstructor to it.sizeConstructor
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
+2
-1
@@ -151,7 +151,8 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag
|
||||
|
||||
override fun IrExpression.useAsVarargElement(expression: IrVararg): IrExpression {
|
||||
return this.useAs(
|
||||
if (this.type.isInlined())
|
||||
// Do not box primitive inline classes
|
||||
if (this.type.isInlined() && !expression.type.isInlined() && !expression.type.isPrimitiveArray())
|
||||
irBuiltIns.anyNType
|
||||
else
|
||||
expression.varargElementType
|
||||
|
||||
+68
-14
@@ -8,13 +8,22 @@ package org.jetbrains.kotlin.ir.backend.js.lower
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrSpreadElement
|
||||
import org.jetbrains.kotlin.ir.expressions.IrVararg
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.getInlineClassBackingField
|
||||
import org.jetbrains.kotlin.ir.util.getInlinedClass
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
@@ -44,32 +53,64 @@ private class VarargTransformer(
|
||||
}
|
||||
}
|
||||
|
||||
fun IrExpression.unboxInlineClassIfNeeded(): IrExpression {
|
||||
val inlinedClass = type.getInlinedClass() ?: return this
|
||||
val field = getInlineClassBackingField(inlinedClass)
|
||||
return IrGetFieldImpl(startOffset, endOffset, field.symbol, inlinedClass.defaultType, this)
|
||||
}
|
||||
|
||||
fun IrExpression.boxInlineClassIfNeeded(inlineClass: IrClass?) =
|
||||
if (inlineClass == null)
|
||||
this
|
||||
else
|
||||
IrCallImpl(startOffset, endOffset, inlineClass.defaultType, inlineClass.constructors.single { it.isPrimary }.symbol).also {
|
||||
it.putValueArgument(0, this)
|
||||
}
|
||||
|
||||
override fun visitVararg(expression: IrVararg): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
val currentList = mutableListOf<IrExpression>()
|
||||
val segments = mutableListOf<IrExpression>()
|
||||
|
||||
val elementType = expression.varargElementType
|
||||
val primitiveElementType: IrType
|
||||
val primitiveExpressionType: IrType
|
||||
val needUnboxing: Boolean
|
||||
val arrayInlineClass = expression.type.getInlinedClass()
|
||||
if (arrayInlineClass != null) {
|
||||
primitiveElementType = getInlineClassBackingField(elementType.getInlinedClass()!!).type
|
||||
primitiveExpressionType = getInlineClassBackingField(arrayInlineClass).type
|
||||
needUnboxing = true
|
||||
} else {
|
||||
primitiveElementType = elementType
|
||||
primitiveExpressionType = expression.type
|
||||
needUnboxing = false
|
||||
}
|
||||
|
||||
for (e in expression.elements) {
|
||||
if (e is IrSpreadElement) {
|
||||
if (!currentList.isEmpty()) {
|
||||
segments.add(currentList.toArrayLiteral(expression.type, expression.varargElementType))
|
||||
currentList.clear()
|
||||
when (e) {
|
||||
is IrSpreadElement -> {
|
||||
if (!currentList.isEmpty()) {
|
||||
segments.add(currentList.toArrayLiteral(primitiveExpressionType, primitiveElementType))
|
||||
currentList.clear()
|
||||
}
|
||||
segments.add(if (needUnboxing) e.expression.unboxInlineClassIfNeeded() else e.expression)
|
||||
}
|
||||
|
||||
is IrExpression -> {
|
||||
currentList.add(if (needUnboxing) e.unboxInlineClassIfNeeded() else e)
|
||||
}
|
||||
segments.add(e.expression)
|
||||
} else {
|
||||
// IrVarargElement is either IrSpreadElement or IrExpression
|
||||
currentList.add(e as IrExpression)
|
||||
}
|
||||
}
|
||||
if (!currentList.isEmpty()) {
|
||||
segments.add(currentList.toArrayLiteral(expression.type, expression.varargElementType))
|
||||
segments.add(currentList.toArrayLiteral(primitiveExpressionType, primitiveElementType))
|
||||
currentList.clear()
|
||||
}
|
||||
|
||||
// empty vararg => empty array literal
|
||||
if (segments.isEmpty()) {
|
||||
return emptyList().toArrayLiteral(expression.type, expression.varargElementType)
|
||||
return emptyList().toArrayLiteral(primitiveExpressionType, primitiveElementType)
|
||||
}
|
||||
|
||||
// vararg with a single segment => no need to concatenate
|
||||
@@ -85,11 +126,19 @@ private class VarargTransformer(
|
||||
putValueArgument(0, segments.first())
|
||||
}
|
||||
} else {
|
||||
segments.first()
|
||||
val res = segments.first()
|
||||
return if (needUnboxing)
|
||||
res.boxInlineClassIfNeeded(arrayInlineClass!!)
|
||||
else
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
val arrayLiteral = segments.toArrayLiteral(IrSimpleTypeImpl(context.intrinsics.array, false, emptyList(), emptyList()), context.irBuiltIns.anyType)
|
||||
val arrayLiteral =
|
||||
segments.toArrayLiteral(
|
||||
IrSimpleTypeImpl(context.intrinsics.array, false, emptyList(), emptyList()),
|
||||
context.irBuiltIns.anyType
|
||||
)
|
||||
|
||||
val concatFun = if (expression.type.classifierOrNull in context.intrinsics.primitiveArrays.keys) {
|
||||
context.intrinsics.primitiveArrayConcat
|
||||
@@ -97,7 +146,7 @@ private class VarargTransformer(
|
||||
context.intrinsics.arrayConcat
|
||||
}
|
||||
|
||||
return IrCallImpl(
|
||||
val res = IrCallImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
expression.type,
|
||||
@@ -105,6 +154,11 @@ private class VarargTransformer(
|
||||
).apply {
|
||||
putValueArgument(0, arrayLiteral)
|
||||
}
|
||||
|
||||
return if (needUnboxing)
|
||||
res.boxInlineClassIfNeeded(arrayInlineClass!!)
|
||||
else
|
||||
res
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
|
||||
+1
-3
@@ -66,14 +66,12 @@ class NumberConversionCallsTransformer(context: JsIrBackendContext) : CallsTrans
|
||||
}
|
||||
|
||||
for (type in arrayOf(irBuiltIns.byteType, irBuiltIns.shortType, irBuiltIns.intType)) {
|
||||
add(type, ConversionNames.TO_CHAR, intrinsics.charConstructor)
|
||||
add(type, ConversionNames.TO_CHAR, intrinsics.jsNumberToChar)
|
||||
}
|
||||
|
||||
for (type in arrayOf(irBuiltIns.floatType, irBuiltIns.doubleType, irBuiltIns.numberType)) {
|
||||
add(type, ConversionNames.TO_CHAR, intrinsics.jsNumberToChar)
|
||||
}
|
||||
|
||||
add(irBuiltIns.charType, ConversionNames.TO_CHAR, ::useDispatchReceiver)
|
||||
}
|
||||
|
||||
override fun transformCall(call: IrCall): IrExpression {
|
||||
|
||||
+1
@@ -1,4 +1,5 @@
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
|
||||
Reference in New Issue
Block a user