JVM_IR move 'arrayOf' handling to JvmBuiltInsLowering

FunctionReferenceLowering creates calls to 'arrayOf' functions that
should be processed later.
This commit is contained in:
Dmitry Petrov
2021-10-12 16:33:11 +03:00
committed by TeamCityServer
parent 27e5655480
commit b946a284b0
3 changed files with 37 additions and 31 deletions
@@ -349,7 +349,7 @@ private val jvmFilePhases = listOf(
remapObjectFieldAccesses, remapObjectFieldAccesses,
anonymousObjectSuperConstructorPhase, anonymousObjectSuperConstructorPhase,
jvmStandardLibraryBuiltInsPhase, jvmBuiltInsPhase,
rangeContainsLoweringPhase, rangeContainsLoweringPhase,
forLoopsPhase, forLoopsPhase,
@@ -6,8 +6,11 @@
package org.jetbrains.kotlin.backend.jvm.lower package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder
import org.jetbrains.kotlin.backend.jvm.ir.irArrayOf
import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
@@ -15,32 +18,45 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
internal val jvmStandardLibraryBuiltInsPhase = makeIrFilePhase( internal val jvmBuiltInsPhase = makeIrFilePhase(
::JvmStandardLibraryBuiltInsLowering, ::JvmBuiltInsLowering,
name = "JvmStandardLibraryBuiltInsLowering", name = "JvmBuiltInsLowering",
description = "Use Java Standard Library implementations of built-ins" description = "JVM-specific implementations of some built-ins"
) )
class JvmStandardLibraryBuiltInsLowering(val context: JvmBackendContext) : FileLoweringPass { class JvmBuiltInsLowering(val context: JvmBackendContext) : FileLoweringPass {
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
if (context.state.target < JvmTarget.JVM_1_8) return val transformer = object : IrElementTransformerVoidWithContext() {
val transformer = object : IrElementTransformerVoid() {
override fun visitCall(expression: IrCall): IrExpression { override fun visitCall(expression: IrCall): IrExpression {
expression.transformChildren(this, null) expression.transformChildren(this, null)
val parentClass = expression.symbol.owner.parent.fqNameForIrSerialization.asString() val callee = expression.symbol.owner
val functionName = expression.symbol.owner.name.asString()
jvm8builtInReplacements[parentClass to functionName]?.let { replacement -> if (context.state.target >= JvmTarget.JVM_1_8) {
return expression.replaceWithCallTo(replacement) val parentClassName = callee.parent.fqNameForIrSerialization.asString()
val functionName = callee.name.asString()
val jvm8Replacement = jvm8builtInReplacements[parentClassName to functionName]
if (jvm8Replacement != null) {
return expression.replaceWithCallTo(jvm8Replacement)
}
} }
return expression return when {
callee.isArrayOf() ->
expression.getValueArgument(0)
?: throw AssertionError("Argument #0 expected: ${expression.dump()}")
callee.isEmptyArray() ->
context.createJvmIrBuilder(currentScope!!, expression).irArrayOf(expression.type)
else ->
expression
}
} }
} }
@@ -13,8 +13,8 @@ import org.jetbrains.kotlin.backend.jvm.ir.IrArrayBuilder
import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder
import org.jetbrains.kotlin.backend.jvm.ir.irArray import org.jetbrains.kotlin.backend.jvm.ir.irArray
import org.jetbrains.kotlin.backend.jvm.ir.irArrayOf import org.jetbrains.kotlin.backend.jvm.ir.irArrayOf
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.UnsignedType import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.makeNotNull import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
@@ -62,16 +61,7 @@ internal class VarargLowering(val context: JvmBackendContext) : FileLoweringPass
} }
} }
return when { return expression
// Lower `arrayOf` calls. When `isArrayOf` returns true we know that the function has exactly one
// vararg parameter. Meanwhile, the code above ensures that the corresponding argument is not null.
function.owner.isArrayOf() ->
expression.getValueArgument(0)!!
function.isEmptyArray ->
createBuilder(expression.startOffset, expression.endOffset).irArrayOf(expression.type)
else ->
expression
}
} }
override fun visitVararg(expression: IrVararg): IrExpression = override fun visitVararg(expression: IrVararg): IrExpression =
@@ -99,11 +89,8 @@ internal class VarargLowering(val context: JvmBackendContext) : FileLoweringPass
} }
private fun createBuilder(startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET) = private fun createBuilder(startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET) =
context.createJvmIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset) context.createJvmIrBuilder(currentScope!!, startOffset, endOffset)
private val IrFunctionSymbol.isEmptyArray: Boolean
get() = owner.name.asString() == "emptyArray" &&
(owner.parent as? IrPackageFragment)?.fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME
} }
internal val PRIMITIVE_ARRAY_OF_NAMES: Set<String> = internal val PRIMITIVE_ARRAY_OF_NAMES: Set<String> =
@@ -126,3 +113,6 @@ internal fun IrFunction.isArrayOf(): Boolean {
valueParameters[0].isVararg valueParameters[0].isVararg
} }
internal fun IrFunction.isEmptyArray(): Boolean =
name.asString() == "emptyArray" &&
(parent as? IrPackageFragment)?.fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME