[JVM_IR] Give temporary variable loads meaningful offsets.

Temporary variable loads in when expressions had the offsets
of the variable declaration. That leads to hacks during codegen
for line number generation.

Instead of those hacks, give the variable loads the offsets of
the context in which they occur. That avoids the codegen hacks
and fixes stepping behavior for more when expressions.
This commit is contained in:
Mads Ager
2020-08-07 14:02:40 +02:00
committed by max-kammerer
parent 413d02621b
commit 2c6b5c8847
8 changed files with 102 additions and 13 deletions
@@ -532,10 +532,7 @@ class ExpressionCodegen(
} }
override fun visitGetValue(expression: IrGetValue, data: BlockInfo): PromisedValue { override fun visitGetValue(expression: IrGetValue, data: BlockInfo): PromisedValue {
// Do not generate line number information for loads from compiler-generated expression.markLineNumber(startOffset = true)
// temporary variables. They do not correspond to variable loads in user code.
if (expression.symbol.owner.origin != IrDeclarationOrigin.IR_TEMPORARY_VARIABLE)
expression.markLineNumber(startOffset = true)
val type = frameMap.typeOf(expression.symbol) val type = frameMap.typeOf(expression.symbol)
mv.load(findLocalIndex(expression.symbol), type) mv.load(findLocalIndex(expression.symbol), type)
return MaterialValue(this, type, expression.type) return MaterialValue(this, type, expression.type)
@@ -858,6 +855,7 @@ class ExpressionCodegen(
IrTypeOperator.INSTANCEOF -> { IrTypeOperator.INSTANCEOF -> {
expression.argument.accept(this, data).materializeAt(context.irBuiltIns.anyNType) expression.argument.accept(this, data).materializeAt(context.irBuiltIns.anyNType)
val type = typeMapper.boxType(typeOperand) val type = typeMapper.boxType(typeOperand)
if (typeOperand.isReifiedTypeParameter) { if (typeOperand.isReifiedTypeParameter) {
putReifiedOperationMarkerIfTypeIsReifiedParameter(typeOperand, ReifiedTypeInliner.OperationKind.IS) putReifiedOperationMarkerIfTypeIsReifiedParameter(typeOperand, ReifiedTypeInliner.OperationKind.IS)
v.instanceOf(type) v.instanceOf(type)
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
import org.jetbrains.kotlin.psi2ir.deparenthesize import org.jetbrains.kotlin.psi2ir.deparenthesize
import org.jetbrains.kotlin.psi2ir.intermediate.defaultLoad import org.jetbrains.kotlin.psi2ir.intermediate.loadAt
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartList
@@ -206,12 +206,14 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
private fun generateIsPatternCondition(irSubject: IrVariable, ktCondition: KtWhenConditionIsPattern): IrExpression { private fun generateIsPatternCondition(irSubject: IrVariable, ktCondition: KtWhenConditionIsPattern): IrExpression {
val typeOperand = getOrFail(BindingContext.TYPE, ktCondition.typeReference) val typeOperand = getOrFail(BindingContext.TYPE, ktCondition.typeReference)
val irTypeOperand = typeOperand.toIrType() val irTypeOperand = typeOperand.toIrType()
val startOffset = ktCondition.startOffsetSkippingComments
val endOffset = ktCondition.endOffset
val irInstanceOf = IrTypeOperatorCallImpl( val irInstanceOf = IrTypeOperatorCallImpl(
ktCondition.startOffsetSkippingComments, ktCondition.endOffset, startOffset, endOffset,
context.irBuiltIns.booleanType, context.irBuiltIns.booleanType,
IrTypeOperator.INSTANCEOF, IrTypeOperator.INSTANCEOF,
irTypeOperand, irTypeOperand,
irSubject.defaultLoad() irSubject.loadAt(startOffset, startOffset)
) )
return if (ktCondition.isNegated) return if (ktCondition.isNegated)
primitiveOp1( primitiveOp1(
@@ -227,7 +229,9 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
private fun generateInRangeCondition(irSubject: IrVariable, ktCondition: KtWhenConditionInRange): IrExpression { private fun generateInRangeCondition(irSubject: IrVariable, ktCondition: KtWhenConditionInRange): IrExpression {
val inCall = statementGenerator.pregenerateCall(getResolvedCall(ktCondition.operationReference)!!) val inCall = statementGenerator.pregenerateCall(getResolvedCall(ktCondition.operationReference)!!)
inCall.irValueArgumentsByIndex[0] = irSubject.defaultLoad() val startOffset = ktCondition.startOffsetSkippingComments
val endOffset = ktCondition.endOffset
inCall.irValueArgumentsByIndex[0] = irSubject.loadAt(startOffset, startOffset)
val inOperator = getInfixOperator(ktCondition.operationReference.getReferencedNameElementType()) val inOperator = getInfixOperator(ktCondition.operationReference.getReferencedNameElementType())
val irInCall = CallGenerator(statementGenerator).generateCall(ktCondition, inCall, inOperator) val irInCall = CallGenerator(statementGenerator).generateCall(ktCondition, inCall, inOperator)
return when (inOperator) { return when (inOperator) {
@@ -235,7 +239,7 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
irInCall irInCall
IrStatementOrigin.NOT_IN -> IrStatementOrigin.NOT_IN ->
primitiveOp1( primitiveOp1(
ktCondition.startOffsetSkippingComments, ktCondition.endOffset, startOffset, endOffset,
context.irBuiltIns.booleanNotSymbol, context.irBuiltIns.booleanNotSymbol,
context.irBuiltIns.booleanType, context.irBuiltIns.booleanType,
IrStatementOrigin.EXCL, IrStatementOrigin.EXCL,
@@ -248,9 +252,11 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
private fun generateEqualsCondition(irSubject: IrVariable, ktCondition: KtWhenConditionWithExpression): IrExpression { private fun generateEqualsCondition(irSubject: IrVariable, ktCondition: KtWhenConditionWithExpression): IrExpression {
val ktExpression = ktCondition.expression val ktExpression = ktCondition.expression
val irExpression = ktExpression!!.genExpr() val irExpression = ktExpression!!.genExpr()
val startOffset = ktCondition.startOffsetSkippingComments
val endOffset = ktCondition.endOffset
return OperatorExpressionGenerator(statementGenerator).generateEquality( return OperatorExpressionGenerator(statementGenerator).generateEquality(
ktCondition.startOffsetSkippingComments, ktCondition.endOffset, IrStatementOrigin.EQEQ, startOffset, endOffset, IrStatementOrigin.EQEQ,
irSubject.defaultLoad(), irExpression, irSubject.loadAt(startOffset, startOffset), irExpression,
context.bindingContext[BindingContext.PRIMITIVE_NUMERIC_COMPARISON_INFO, ktExpression] context.bindingContext[BindingContext.PRIMITIVE_NUMERIC_COMPARISON_INFO, ktExpression]
) )
} }
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
fun IrVariable.defaultLoad(): IrExpression = fun IrVariable.loadAt(startOffset: Int, endOffset: Int): IrExpression =
IrGetValueImpl(startOffset, endOffset, type, symbol) IrGetValueImpl(startOffset, endOffset, type, symbol)
fun CallReceiver.adjustForCallee(callee: CallableMemberDescriptor): CallReceiver = fun CallReceiver.adjustForCallee(callee: CallableMemberDescriptor): CallReceiver =
+38
View File
@@ -0,0 +1,38 @@
// FILE: test.kt
fun foo(x: Any) {
when (x) {
is Float ->
1
is Double ->
2
else ->
3
}
}
fun box() {
foo(1.2f)
foo(1.2)
foo(1)
}
// LINENUMBERS
// test.kt:15 box
// test.kt:4 foo
// test.kt:5 foo
// test.kt:6 foo
// test.kt:12 foo
// test.kt:16 box
// test.kt:4 foo
// test.kt:5 foo
// test.kt:7 foo
// test.kt:8 foo
// test.kt:12 foo
// test.kt:17 box
// test.kt:4 foo
// test.kt:5 foo
// test.kt:7 foo
// test.kt:10 foo
// test.kt:12 foo
// test.kt:18 box
+24
View File
@@ -0,0 +1,24 @@
// FILE: test.kt
fun box() {
val a: Int? = 0
when (a) {
1 -> {
1 + 1
}
2 -> {
2 + 1
}
else -> {
0 + 0
}
}
}
// LINENUMBERS
// test.kt:4 box
// test.kt:5 box
// test.kt:6 box
// test.kt:9 box
// test.kt:13 box
// test.kt:16 box
@@ -427,6 +427,12 @@ public class IrSteppingTestGenerated extends AbstractIrSteppingTest {
runTest("compiler/testData/debug/stepping/whenComplicatedSubject.kt"); runTest("compiler/testData/debug/stepping/whenComplicatedSubject.kt");
} }
@Test
@TestMetadata("whenIsChecks.kt")
public void testWhenIsChecks() throws Exception {
runTest("compiler/testData/debug/stepping/whenIsChecks.kt");
}
@Test @Test
@TestMetadata("whenMultiLine.kt") @TestMetadata("whenMultiLine.kt")
public void testWhenMultiLine() throws Exception { public void testWhenMultiLine() throws Exception {
@@ -439,6 +445,12 @@ public class IrSteppingTestGenerated extends AbstractIrSteppingTest {
runTest("compiler/testData/debug/stepping/whenMultiLineSubject.kt"); runTest("compiler/testData/debug/stepping/whenMultiLineSubject.kt");
} }
@Test
@TestMetadata("whenNullalbeSubject.kt")
public void testWhenNullalbeSubject() throws Exception {
runTest("compiler/testData/debug/stepping/whenNullalbeSubject.kt");
}
@Test @Test
@TestMetadata("whenSubject.kt") @TestMetadata("whenSubject.kt")
public void testWhenSubject() throws Exception { public void testWhenSubject() throws Exception {
@@ -427,6 +427,12 @@ public class SteppingTestGenerated extends AbstractSteppingTest {
runTest("compiler/testData/debug/stepping/whenComplicatedSubject.kt"); runTest("compiler/testData/debug/stepping/whenComplicatedSubject.kt");
} }
@Test
@TestMetadata("whenIsChecks.kt")
public void testWhenIsChecks() throws Exception {
runTest("compiler/testData/debug/stepping/whenIsChecks.kt");
}
@Test @Test
@TestMetadata("whenMultiLine.kt") @TestMetadata("whenMultiLine.kt")
public void testWhenMultiLine() throws Exception { public void testWhenMultiLine() throws Exception {
@@ -439,6 +445,12 @@ public class SteppingTestGenerated extends AbstractSteppingTest {
runTest("compiler/testData/debug/stepping/whenMultiLineSubject.kt"); runTest("compiler/testData/debug/stepping/whenMultiLineSubject.kt");
} }
@Test
@TestMetadata("whenNullalbeSubject.kt")
public void testWhenNullalbeSubject() throws Exception {
runTest("compiler/testData/debug/stepping/whenNullalbeSubject.kt");
}
@Test @Test
@TestMetadata("whenSubject.kt") @TestMetadata("whenSubject.kt")
public void testWhenSubject() throws Exception { public void testWhenSubject() throws Exception {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
LineBreakpoint created at whenExpr.kt:5 LineBreakpoint created at whenExpr.kt:5
Run Java Run Java
Connected to the target VM Connected to the target VM