Fix statement order in LocalDeclarationsLowering

Previously, the order of IrSetField statements in this lowering was
non-deterministic. This broke the inliner in the JVM backend which
expects statements to be in argument order.
This commit is contained in:
Steven Schäfer
2019-07-23 13:59:56 +02:00
committed by max-kammerer
parent c38fb27676
commit 173f1fc7d1
@@ -87,7 +87,7 @@ class LocalDeclarationsLowering(
abstract val declaration: IrFunction
abstract val transformedDeclaration: IrFunction
val capturedValueToParameter: MutableMap<IrValueDeclaration, IrValueParameter> = HashMap()
val capturedValueToParameter: MutableMap<IrValueDeclaration, IrValueParameter> = mutableMapOf()
override fun irGet(startOffset: Int, endOffset: Int, valueDeclaration: IrValueDeclaration): IrExpression? {
val parameter = capturedValueToParameter[valueDeclaration] ?: return null
@@ -114,7 +114,9 @@ class LocalDeclarationsLowering(
private class LocalClassContext(val declaration: IrClass) : LocalContext() {
lateinit var closure: Closure
val capturedValueToField: MutableMap<IrValueDeclaration, IrField> = HashMap()
// NOTE: This map is iterated over in `rewriteClassMembers` and we're relying on
// the deterministic iteration order that `mutableMapOf` provides.
val capturedValueToField: MutableMap<IrValueDeclaration, IrField> = mutableMapOf()
override fun irGet(startOffset: Int, endOffset: Int, valueDeclaration: IrValueDeclaration): IrExpression? {
val field = capturedValueToField[valueDeclaration] ?: return null
@@ -380,26 +382,26 @@ class LocalDeclarationsLowering(
assert(constructorsCallingSuper.any()) { "Expected at least one constructor calling super; class: $irClass" }
localClassContext.capturedValueToField.forEach { (capturedValue, field) ->
val startOffset = irClass.startOffset
val endOffset = irClass.endOffset
irClass.declarations.add(field)
irClass.declarations += localClassContext.capturedValueToField.values
for (constructorContext in constructorsCallingSuper) {
val blockBody = constructorContext.declaration.body as? IrBlockBody
?: throw AssertionError("Unexpected constructor body: ${constructorContext.declaration.body}")
val capturedValueExpression = constructorContext.irGet(startOffset, endOffset, capturedValue)!!
blockBody.statements.add(
0,
for (constructorContext in constructorsCallingSuper) {
val blockBody = constructorContext.declaration.body as? IrBlockBody
?: throw AssertionError("Unexpected constructor body: ${constructorContext.declaration.body}")
// NOTE: It's important to set the fields for captured values in the same order as the arguments,
// since `AnonymousObjectTransformer` relies on this ordering.
blockBody.statements.addAll(
0,
localClassContext.capturedValueToField.map { (capturedValue, field) ->
IrSetFieldImpl(
startOffset, endOffset, field.symbol,
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol),
capturedValueExpression,
irClass.startOffset, irClass.endOffset, field.symbol,
IrGetValueImpl(irClass.startOffset, irClass.endOffset, irClass.thisReceiver!!.symbol),
constructorContext.irGet(irClass.startOffset, irClass.endOffset, capturedValue)!!,
context.irBuiltIns.unitType,
STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE
)
)
}
}
)
}
}