Rematerialize simple expressions (local variables, literals, $this, $receiver) when generating calls.
This commit is contained in:
committed by
Dmitry Petrov
parent
c1583c4368
commit
287d804131
+28
-9
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.psi2ir.generators.values.IrTemporaryVariableValue
|
||||
import org.jetbrains.kotlin.psi2ir.generators.values.IrValue
|
||||
import org.jetbrains.kotlin.psi2ir.generators.values.createRematerializableValue
|
||||
import org.jetbrains.kotlin.psi2ir.toExpectedType
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
@@ -42,12 +43,30 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
||||
private val receiverValues = HashMap<ReceiverValue, IrValue>()
|
||||
private val valueArgumentValues = HashMap<ValueParameterDescriptor, IrValue>()
|
||||
|
||||
fun createTemporary(ktExpression: KtExpression, irExpression: IrExpression, nameHint: String? = null): IrVariable {
|
||||
fun introduceTemporary(ktExpression: KtExpression, irExpression: IrExpression, nameHint: String? = null): IrVariable? {
|
||||
val rematerializable = createRematerializableValue(irExpression)
|
||||
if (rematerializable != null) {
|
||||
putValue(ktExpression, rematerializable)
|
||||
return null
|
||||
}
|
||||
|
||||
val irTmpVar = temporaryVariableFactory.createTemporaryVariable(irExpression, nameHint)
|
||||
putValue(ktExpression, IrTemporaryVariableValue(irTmpVar))
|
||||
return irTmpVar
|
||||
}
|
||||
|
||||
fun introduceTemporary(valueParameterDescriptor: ValueParameterDescriptor, irExpression: IrExpression): IrVariable? {
|
||||
val rematerializable = createRematerializableValue(irExpression)
|
||||
if (rematerializable != null) {
|
||||
putValue(valueParameterDescriptor, rematerializable)
|
||||
return null
|
||||
}
|
||||
|
||||
val irTmpVar = temporaryVariableFactory.createTemporaryVariable(irExpression, valueParameterDescriptor.name.asString())
|
||||
putValue(valueParameterDescriptor, IrTemporaryVariableValue(irTmpVar))
|
||||
return irTmpVar
|
||||
}
|
||||
|
||||
fun putValue(ktExpression: KtExpression, irValue: IrValue) {
|
||||
expressionValues[ktExpression] = irValue
|
||||
}
|
||||
@@ -140,30 +159,30 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
||||
// TODO use IrLetExpression?
|
||||
|
||||
val valueArgumentsInEvaluationOrder = resolvedCall.valueArguments.values
|
||||
val valueParameters = resolvedCall.resultingDescriptor.valueParameters
|
||||
|
||||
val irBlock = IrBlockExpressionImpl(ktExpression.startOffset, ktExpression.endOffset, resultType,
|
||||
hasResult = isUsedAsExpression(ktExpression),
|
||||
isDesugared = true)
|
||||
|
||||
|
||||
|
||||
val valueArgumentsToValueParameters = HashMap<ResolvedValueArgument, ValueParameterDescriptor>()
|
||||
for ((index, valueArgument) in resolvedCall.valueArgumentsByIndex!!.withIndex()) {
|
||||
val valueParameter = resolvedCall.resultingDescriptor.valueParameters[index]
|
||||
val valueParameter = valueParameters[index]
|
||||
valueArgumentsToValueParameters[valueArgument] = valueParameter
|
||||
}
|
||||
|
||||
val temporariesForValueArguments = HashMap<ResolvedValueArgument, Pair<VariableDescriptor, IrExpression>>()
|
||||
for (valueArgument in valueArgumentsInEvaluationOrder) {
|
||||
val valueParameter = valueArgumentsToValueParameters[valueArgument]!!
|
||||
val irArgument = generateValueArgument(valueArgument, valueParameter) ?: continue
|
||||
val irTemporary = temporaryVariableFactory.createTemporaryVariable(irArgument, valueParameter.name.asString())
|
||||
temporariesForValueArguments[valueArgument] = Pair(irTemporary.descriptor, irArgument)
|
||||
irBlock.addStatement(irTemporary)
|
||||
val irTmpArg = introduceTemporary(valueParameter, irArgument)
|
||||
irBlock.addIfNotNull(irTmpArg)
|
||||
}
|
||||
|
||||
for ((index, valueArgument) in resolvedCall.valueArgumentsByIndex!!.withIndex()) {
|
||||
val (temporaryDescriptor, irArgument) = temporariesForValueArguments[valueArgument]!!
|
||||
val valueParameter = resolvedCall.resultingDescriptor.valueParameters[index]
|
||||
val irGetTemporary = IrGetVariableExpressionImpl(irArgument.startOffset, irArgument.endOffset, temporaryDescriptor)
|
||||
val valueParameter = valueParameters[index]
|
||||
val irGetTemporary = valueArgumentValues[valueParameter]!!.load()
|
||||
irCall.putArgument(index, irGetTemporary.toExpectedType(valueParameter.type))
|
||||
}
|
||||
|
||||
|
||||
+11
-2
@@ -28,15 +28,24 @@ import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi2ir.generators.values.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
|
||||
val KT_OPERATOR_TO_IR_OPERATOR = hashMapOf(
|
||||
KtTokens.PLUSEQ to IrOperator.PLUSEQ,
|
||||
KtTokens.MINUSEQ to IrOperator.MINUSEQ,
|
||||
KtTokens.MULTEQ to IrOperator.MULTEQ,
|
||||
KtTokens.DIVEQ to IrOperator.DIVEQ,
|
||||
KtTokens.PERCEQ to IrOperator.PERCEQ
|
||||
KtTokens.PERCEQ to IrOperator.PERCEQ,
|
||||
|
||||
KtTokens.PLUS to IrOperator.PLUS,
|
||||
KtTokens.MINUS to IrOperator.MINUS,
|
||||
KtTokens.MUL to IrOperator.MUL,
|
||||
KtTokens.DIV to IrOperator.DIV
|
||||
)
|
||||
|
||||
val AUGMENTED_ASSIGNMENTS = KtTokens.AUGMENTED_ASSIGNMENTS
|
||||
val BINARY_OPERATORS_WITH_CALLS = OperatorConventions.BINARY_OPERATION_NAMES.keys
|
||||
|
||||
class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerator): IrGenerator {
|
||||
override val context: IrGeneratorContext get() = irStatementGenerator.context
|
||||
|
||||
@@ -45,7 +54,7 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
||||
|
||||
return when (ktOperator) {
|
||||
KtTokens.EQ -> generateAssignment(expression)
|
||||
in KtTokens.AUGMENTED_ASSIGNMENTS -> generateAugmentedAssignment(expression, ktOperator)
|
||||
in AUGMENTED_ASSIGNMENTS -> generateAugmentedAssignment(expression, ktOperator)
|
||||
else -> createDummyExpression(expression, ktOperator.toString())
|
||||
}
|
||||
}
|
||||
|
||||
+3
-6
@@ -16,10 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.psi2ir.generators.values
|
||||
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBlockExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBlockExpressionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrOperator
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
@@ -98,11 +95,11 @@ class IrIndexedLValue(
|
||||
}
|
||||
|
||||
private fun defineContextVariables(irBlock: IrBlockExpression, callGenerator: IrCallGenerator) {
|
||||
irBlock.addStatement(callGenerator.createTemporary(ktArrayAccessExpression.arrayExpression!!, irArray, "array"))
|
||||
irBlock.addIfNotNull(callGenerator.introduceTemporary(ktArrayAccessExpression.arrayExpression!!, irArray, "array"))
|
||||
|
||||
var index = 0
|
||||
for ((ktIndexExpression, irIndexValue) in indexValues) {
|
||||
irBlock.addStatement(callGenerator.createTemporary(ktIndexExpression, irIndexValue, "index${index++}"))
|
||||
irBlock.addIfNotNull(callGenerator.introduceTemporary(ktIndexExpression, irIndexValue, "index${index++}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.psi2ir.generators.values
|
||||
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
|
||||
interface IrRematerializableValue : IrValue
|
||||
|
||||
fun createRematerializableValue(irExpression: IrExpression): IrRematerializableValue? =
|
||||
when (irExpression) {
|
||||
is IrLiteralExpression<*> -> IrRematerializableLiteralValue(irExpression)
|
||||
is IrGetVariableExpression -> IrRematerializableVariableValue(irExpression)
|
||||
is IrGetExtensionReceiverExpression -> IrRematerializableExtensionReceiverValue(irExpression)
|
||||
is IrThisExpression -> IrRematerializableThisValue(irExpression)
|
||||
else -> null
|
||||
}
|
||||
|
||||
class IrRematerializableLiteralValue(val irExpression: IrLiteralExpression<*>): IrRematerializableValue {
|
||||
override fun load(): IrExpression =
|
||||
IrLiteralExpressionImpl(irExpression.startOffset, irExpression.endOffset, irExpression.type,
|
||||
irExpression.kind, irExpression.kind.valueOf(irExpression))
|
||||
}
|
||||
|
||||
class IrRematerializableVariableValue(val irExpression: IrGetVariableExpression) : IrRematerializableValue {
|
||||
override fun load(): IrExpression =
|
||||
IrGetVariableExpressionImpl(irExpression.startOffset, irExpression.endOffset, irExpression.descriptor)
|
||||
}
|
||||
|
||||
class IrRematerializableExtensionReceiverValue(val irExpression: IrGetExtensionReceiverExpression) : IrRematerializableValue {
|
||||
override fun load(): IrExpression =
|
||||
IrGetExtensionReceiverExpressionImpl(irExpression.startOffset, irExpression.endOffset, irExpression.type, irExpression.descriptor)
|
||||
}
|
||||
|
||||
class IrRematerializableThisValue(val irExpression: IrThisExpression): IrRematerializableValue {
|
||||
override fun load(): IrExpression =
|
||||
IrThisExpressionImpl(irExpression.startOffset, irExpression.endOffset, irExpression.type, irExpression.classDescriptor)
|
||||
}
|
||||
@@ -33,6 +33,10 @@ interface IrBlockExpression : IrExpression {
|
||||
fun addStatement(statement: IrStatement)
|
||||
}
|
||||
|
||||
fun IrBlockExpression.addIfNotNull(statement: IrStatement?) {
|
||||
if (statement != null) addStatement(statement)
|
||||
}
|
||||
|
||||
class IrBlockExpressionImpl(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
|
||||
Reference in New Issue
Block a user