Fixed SharedVariablesLowering

This commit is contained in:
Igor Chevdar
2018-05-07 14:45:56 +03:00
committed by Vasily Levchenko
parent 91f4606b99
commit aa3cae7a4e
2 changed files with 133 additions and 0 deletions
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.backend.konan.lower.DefaultParameterInjector
import org.jetbrains.kotlin.backend.konan.lower.InitializersLowering
import org.jetbrains.kotlin.backend.konan.lower.LateinitLowering
import org.jetbrains.kotlin.backend.konan.lower.LocalDeclarationsLowering
import org.jetbrains.kotlin.backend.konan.lower.SharedVariablesLowering
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.checkDeclarationParents
@@ -0,0 +1,132 @@
/*
* 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.backend.konan.lower
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ValueDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.expressions.IrSetVariable
import org.jetbrains.kotlin.ir.expressions.IrValueAccessExpression
import org.jetbrains.kotlin.ir.visitors.*
import java.util.*
// TODO: Fix .parent for variables and use from common backend.
class SharedVariablesLowering(val context: BackendContext) : FunctionLoweringPass {
override fun lower(irFunction: IrFunction) {
SharedVariablesTransformer(irFunction).lowerSharedVariables()
}
private inner class SharedVariablesTransformer(val irFunction: IrFunction) {
val sharedVariables = mutableSetOf<ValueDescriptor>()
fun lowerSharedVariables() {
collectSharedVariables()
if (sharedVariables.isEmpty()) return
rewriteSharedVariables()
}
private fun collectSharedVariables() {
irFunction.acceptVoid(object : IrElementVisitorVoid {
val relevantVars = mutableSetOf<VariableDescriptor>()
val functionsVariables = mutableListOf<MutableSet<VariableDescriptor>>()
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitFunction(declaration: IrFunction) {
functionsVariables.push(mutableSetOf())
declaration.acceptChildrenVoid(this)
functionsVariables.pop()
}
override fun visitVariable(declaration: IrVariable) {
declaration.acceptChildrenVoid(this)
val variableDescriptor = declaration.descriptor
if (variableDescriptor.isVar) {
relevantVars.add(variableDescriptor)
functionsVariables.peek()!!.add(variableDescriptor)
}
}
override fun visitVariableAccess(expression: IrValueAccessExpression) {
expression.acceptChildrenVoid(this)
val descriptor = expression.descriptor
//if (descriptor in relevantVars && descriptor.containingDeclaration != currentDeclaration) {
if (descriptor in relevantVars && !functionsVariables.peek()!!.contains(descriptor)) {
sharedVariables.add(descriptor)
}
}
})
}
private fun rewriteSharedVariables() {
val transformedDescriptors = HashMap<ValueDescriptor, VariableDescriptor>()
irFunction.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitVariable(declaration: IrVariable): IrStatement {
declaration.transformChildrenVoid(this)
val oldDescriptor = declaration.descriptor
if (oldDescriptor !in sharedVariables) return declaration
val newDescriptor = context.sharedVariablesManager.createSharedVariableDescriptor(oldDescriptor)
transformedDescriptors[oldDescriptor] = newDescriptor
return context.sharedVariablesManager.defineSharedValue(newDescriptor, declaration)
}
})
irFunction.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitGetValue(expression: IrGetValue): IrExpression {
expression.transformChildrenVoid(this)
val newDescriptor = getTransformedDescriptor(expression.descriptor) ?: return expression
return context.sharedVariablesManager.getSharedValue(newDescriptor, expression)
}
override fun visitSetVariable(expression: IrSetVariable): IrExpression {
expression.transformChildrenVoid(this)
val newDescriptor = getTransformedDescriptor(expression.descriptor) ?: return expression
return context.sharedVariablesManager.setSharedValue(newDescriptor, expression)
}
private fun getTransformedDescriptor(oldDescriptor: ValueDescriptor): VariableDescriptor? =
transformedDescriptors.getOrElse(oldDescriptor) {
assert(oldDescriptor !in sharedVariables) {
"Shared variable is not transformed: $oldDescriptor"
}
null
}
})
}
}
}