Introduce name hints for temporary variables.

Split IrValue.kt into a subpackage.
This commit is contained in:
Dmitry Petrov
2016-08-17 11:38:24 +03:00
committed by Dmitry Petrov
parent 177acaabf5
commit 888b1685ed
11 changed files with 179 additions and 100 deletions
@@ -22,6 +22,8 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi.KtExpression
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.toExpectedType
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
import org.jetbrains.kotlin.resolve.calls.model.*
@@ -151,8 +153,9 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
val temporariesForValueArguments = HashMap<ResolvedValueArgument, Pair<VariableDescriptor, IrExpression>>()
for (valueArgument in valueArgumentsInEvaluationOrder) {
val irArgument = generateValueArgument(valueArgument, valueArgumentsToValueParameters[valueArgument]!!) ?: continue
val irTemporary = temporaryVariableFactory.createTemporaryVariable(irArgument)
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)
}
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtBinaryExpression
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
@@ -96,7 +97,7 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
val indexedGetCall = get(BindingContext.INDEXED_LVALUE_GET, ktLeft)
val indexedSetCall = get(BindingContext.INDEXED_LVALUE_SET, ktLeft)
return IrIndexedLValue(irStatementGenerator, ktLeft, irOperator,
irArrayValue, indexExpressions, indexedGetCall, indexedSetCall)
irArrayValue, indexExpressions, indexedGetCall, indexedSetCall)
}
val resolvedCall = getResolvedCall(ktLeft) ?: TODO("no resolved call for LHS")
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.deparenthesize
import org.jetbrains.kotlin.psi2ir.generators.values.IrTemporaryVariableValue
import org.jetbrains.kotlin.psi2ir.toExpectedType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContextUtils
@@ -35,7 +35,7 @@ class IrTemporaryVariableFactory(val scopeOwner: DeclarationDescriptor) {
scopeOwner,
Name.identifier(
if (nameHint != null)
"tmp${nextTemporaryIndex()}\$$nameHint"
"tmp${nextTemporaryIndex()}_$nameHint"
else
"tmp${nextTemporaryIndex()}"
),
@@ -14,87 +14,20 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir.generators
package org.jetbrains.kotlin.psi2ir.generators.values
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.*
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.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.createDefaultGetExpression
import org.jetbrains.kotlin.psi2ir.toExpectedType
import org.jetbrains.kotlin.psi2ir.generators.IrCallGenerator
import org.jetbrains.kotlin.psi2ir.generators.IrStatementGenerator
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
interface IrValue {
fun load(): IrExpression
}
class IrTemporaryVariableValue(val irVariable: IrVariable) : IrValue {
override fun load(): IrExpression =
irVariable.createDefaultGetExpression()
}
class IrSingleExpressionValue(val irExpression: IrExpression) : IrValue {
override fun load() = irExpression
}
interface IrLValue : IrValue {
fun store(irExpression: IrExpression): IrExpression
}
interface IrLValueWithAugmentedStore : IrLValue {
fun augmentedStore(operatorCall: ResolvedCall<*>, irRhs: IrExpression): IrExpression
}
class IrVariableLValueValue(
val ktElement: KtElement,
val irOperator: IrOperator?,
val descriptor: VariableDescriptor
) : IrLValue {
override fun load(): IrExpression =
IrGetVariableExpressionImpl(
ktElement.startOffset, ktElement.endOffset,
descriptor, irOperator
)
override fun store(irExpression: IrExpression): IrExpression =
IrSetVariableExpressionImpl(
ktElement.startOffset, ktElement.endOffset,
descriptor, irExpression.toExpectedType(descriptor.type), irOperator
)
}
class IrPropertyLValueValue(
val ktElement: KtElement,
val irOperator: IrOperator?,
val descriptor: PropertyDescriptor,
val dispatchReceiver: IrExpression?,
val extensionReceiver: IrExpression?,
val isSafe: Boolean
) : IrLValue {
private fun IrPropertyAccessExpression.setReceivers() =
apply {
dispatchReceiver = this@IrPropertyLValueValue.dispatchReceiver
extensionReceiver = this@IrPropertyLValueValue.extensionReceiver
}
override fun load(): IrExpression =
IrGetPropertyExpressionImpl(
ktElement.startOffset, ktElement.endOffset,
descriptor.type, isSafe, descriptor, irOperator
).setReceivers()
override fun store(irExpression: IrExpression): IrExpression =
IrSetPropertyExpressionImpl(
ktElement.startOffset, ktElement.endOffset,
isSafe, descriptor, irExpression.toExpectedType(descriptor.type), irOperator
).setReceivers()
}
class IrIndexedLValue(
var irStatementGenerator: IrStatementGenerator,
val ktArrayAccessExpression: KtArrayAccessExpression,
@@ -165,10 +98,11 @@ class IrIndexedLValue(
}
private fun defineContextVariables(irBlock: IrBlockExpression, callGenerator: IrCallGenerator) {
irBlock.addStatement(callGenerator.createTemporary(ktArrayAccessExpression.arrayExpression!!, arrayValue.load()))
irBlock.addStatement(callGenerator.createTemporary(ktArrayAccessExpression.arrayExpression!!, arrayValue.load(), "array"))
var index = 0
for ((ktIndexExpression, irIndexValue) in indexValues) {
irBlock.addStatement(callGenerator.createTemporary(ktIndexExpression, irIndexValue.load()))
irBlock.addStatement(callGenerator.createTemporary(ktIndexExpression, irIndexValue.load(), "index${index++}"))
}
}
}
@@ -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.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.toExpectedType
class IrPropertyLValueValue(
val ktElement: KtElement,
val irOperator: IrOperator?,
val descriptor: PropertyDescriptor,
val dispatchReceiver: IrExpression?,
val extensionReceiver: IrExpression?,
val isSafe: Boolean
) : IrLValue {
private fun IrPropertyAccessExpression.setReceivers() =
apply {
dispatchReceiver = this@IrPropertyLValueValue.dispatchReceiver
extensionReceiver = this@IrPropertyLValueValue.extensionReceiver
}
override fun load(): IrExpression =
IrGetPropertyExpressionImpl(
ktElement.startOffset, ktElement.endOffset,
descriptor.type, isSafe, descriptor, irOperator
).setReceivers()
override fun store(irExpression: IrExpression): IrExpression =
IrSetPropertyExpressionImpl(
ktElement.startOffset, ktElement.endOffset,
isSafe, descriptor, irExpression.toExpectedType(descriptor.type), irOperator
).setReceivers()
}
@@ -0,0 +1,44 @@
/*
* 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.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.psi2ir.createDefaultGetExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
interface IrValue {
fun load(): IrExpression
}
class IrTemporaryVariableValue(val irVariable: IrVariable) : IrValue {
override fun load(): IrExpression =
irVariable.createDefaultGetExpression()
}
class IrSingleExpressionValue(val irExpression: IrExpression) : IrValue {
override fun load() = irExpression
}
interface IrLValue : IrValue {
fun store(irExpression: IrExpression): IrExpression
}
interface IrLValueWithAugmentedStore : IrLValue {
fun augmentedStore(operatorCall: ResolvedCall<*>, irRhs: IrExpression): IrExpression
}
@@ -0,0 +1,45 @@
/*
* 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.descriptors.VariableDescriptor
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetVariableExpressionImpl
import org.jetbrains.kotlin.ir.expressions.IrOperator
import org.jetbrains.kotlin.ir.expressions.IrSetVariableExpressionImpl
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.toExpectedType
class IrVariableLValueValue(
val ktElement: KtElement,
val irOperator: IrOperator?,
val descriptor: VariableDescriptor
) : IrLValue {
override fun load(): IrExpression =
IrGetVariableExpressionImpl(
ktElement.startOffset, ktElement.endOffset,
descriptor, irOperator
)
override fun store(irExpression: IrExpression): IrExpression =
IrSetVariableExpressionImpl(
ktElement.startOffset, ktElement.endOffset,
descriptor, irExpression.toExpectedType(descriptor.type), irOperator
)
}
+4 -4
View File
@@ -5,11 +5,11 @@ IrFile /arrayAssignment.kt
VAR val x: kotlin.IntArray
CALL .intArrayOf type=kotlin.IntArray operator=
elements: DUMMY vararg type=kotlin.Int
VAR val tmp0: kotlin.IntArray
VAR val tmp0_array: kotlin.IntArray
GET_VAR x type=kotlin.IntArray
VAR val tmp1: kotlin.Int
VAR val tmp1_index0: kotlin.Int
LITERAL Int type=kotlin.Int value='1'
CALL .set type=kotlin.Unit operator=EQ
$this: GET_VAR tmp0 type=kotlin.IntArray
index: GET_VAR tmp1 type=kotlin.Int
$this: GET_VAR tmp0_array type=kotlin.IntArray
index: GET_VAR tmp1_index0 type=kotlin.Int
value: LITERAL Int type=kotlin.Int value='0'
+12 -12
View File
@@ -10,27 +10,27 @@ IrFile /augmentedAssignmentArray.kt
BLOCK type=<no-type> hasResult=false isDesugared=false
VAR var x: kotlin.IntArray
CALL .foo type=kotlin.IntArray operator=
VAR val tmp0: kotlin.IntArray
VAR val tmp0_array: kotlin.IntArray
GET_VAR x type=kotlin.IntArray
VAR val tmp1: kotlin.Int
VAR val tmp1_index0: kotlin.Int
LITERAL Int type=kotlin.Int value='0'
CALL .set type=kotlin.Unit operator=PLUSEQ
$this: GET_VAR tmp0 type=kotlin.IntArray
index: GET_VAR tmp1 type=kotlin.Int
$this: GET_VAR tmp0_array type=kotlin.IntArray
index: GET_VAR tmp1_index0 type=kotlin.Int
value: CALL .plus type=kotlin.Int operator=PLUSEQ
$this: CALL .get type=kotlin.Int operator=PLUSEQ
$this: GET_VAR tmp0 type=kotlin.IntArray
index: GET_VAR tmp1 type=kotlin.Int
$this: GET_VAR tmp0_array type=kotlin.IntArray
index: GET_VAR tmp1_index0 type=kotlin.Int
other: LITERAL Int type=kotlin.Int value='1'
VAR val tmp2: kotlin.IntArray
VAR val tmp2_array: kotlin.IntArray
CALL .foo type=kotlin.IntArray operator=
VAR val tmp3: kotlin.Int
VAR val tmp3_index0: kotlin.Int
LITERAL Int type=kotlin.Int value='0'
CALL .set type=kotlin.Unit operator=MULTEQ
$this: GET_VAR tmp2 type=kotlin.IntArray
index: GET_VAR tmp3 type=kotlin.Int
$this: GET_VAR tmp2_array type=kotlin.IntArray
index: GET_VAR tmp3_index0 type=kotlin.Int
value: CALL .times type=kotlin.Int operator=MULTEQ
$this: CALL .get type=kotlin.Int operator=MULTEQ
$this: GET_VAR tmp2 type=kotlin.IntArray
index: GET_VAR tmp3 type=kotlin.Int
$this: GET_VAR tmp2_array type=kotlin.IntArray
index: GET_VAR tmp3_index0 type=kotlin.Int
other: LITERAL Int type=kotlin.Int value='2'
+4 -4
View File
@@ -28,10 +28,10 @@ IrFile /callWithReorderedArguments.kt
CALL .foo type=kotlin.Unit operator=
a: CALL .noReorder1 type=kotlin.Int operator=
b: CALL .noReorder2 type=kotlin.Int operator=
VAR val tmp0: kotlin.Int
VAR val tmp0_b: kotlin.Int
CALL .reordered1 type=kotlin.Int operator=
VAR val tmp1: kotlin.Int
VAR val tmp1_a: kotlin.Int
CALL .reordered2 type=kotlin.Int operator=
CALL .foo type=kotlin.Unit operator=
a: GET_VAR tmp1 type=kotlin.Int
b: GET_VAR tmp0 type=kotlin.Int
a: GET_VAR tmp1_a type=kotlin.Int
b: GET_VAR tmp0_b type=kotlin.Int