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,
anonymousObjectSuperConstructorPhase,
jvmStandardLibraryBuiltInsPhase,
jvmBuiltInsPhase,
rangeContainsLoweringPhase,
forLoopsPhase,
@@ -6,8 +6,11 @@
package org.jetbrains.kotlin.backend.jvm.lower
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.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.ir.declarations.IrFile
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.symbols.IrSimpleFunctionSymbol
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.render
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
internal val jvmStandardLibraryBuiltInsPhase = makeIrFilePhase(
::JvmStandardLibraryBuiltInsLowering,
name = "JvmStandardLibraryBuiltInsLowering",
description = "Use Java Standard Library implementations of built-ins"
internal val jvmBuiltInsPhase = makeIrFilePhase(
::JvmBuiltInsLowering,
name = "JvmBuiltInsLowering",
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) {
if (context.state.target < JvmTarget.JVM_1_8) return
val transformer = object : IrElementTransformerVoid() {
val transformer = object : IrElementTransformerVoidWithContext() {
override fun visitCall(expression: IrCall): IrExpression {
expression.transformChildren(this, null)
val parentClass = expression.symbol.owner.parent.fqNameForIrSerialization.asString()
val functionName = expression.symbol.owner.name.asString()
jvm8builtInReplacements[parentClass to functionName]?.let { replacement ->
return expression.replaceWithCallTo(replacement)
val callee = expression.symbol.owner
if (context.state.target >= JvmTarget.JVM_1_8) {
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.irArray
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.StandardNames
import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
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.IrPackageFragment
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.util.*
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
@@ -62,16 +61,7 @@ internal class VarargLowering(val context: JvmBackendContext) : FileLoweringPass
}
}
return when {
// 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
}
return expression
}
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) =
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> =
@@ -126,3 +113,6 @@ internal fun IrFunction.isArrayOf(): Boolean {
valueParameters[0].isVararg
}
internal fun IrFunction.isEmptyArray(): Boolean =
name.asString() == "emptyArray" &&
(parent as? IrPackageFragment)?.fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME