[codegen] switch scopes for local variable initializers according to their locations provided by inliner.

This commit is contained in:
Vasily Levchenko
2019-08-02 18:04:01 +03:00
parent 52c5fd1fef
commit f50c3f0b22
@@ -9,6 +9,7 @@ import kotlinx.cinterop.*
import llvm.*
import org.jetbrains.kotlin.backend.common.descriptors.allParameters
import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.backend.common.lower.inline.InlinerExpressionLocationHint
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.descriptors.*
import org.jetbrains.kotlin.backend.konan.ir.*
@@ -22,6 +23,7 @@ import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
@@ -277,6 +279,40 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
}
}
private fun <T:IrElement> findCodeContext(entry: T, context:CodeContext?, predicate: CodeContext.(T) -> Boolean): CodeContext? {
if(context == null)
//TODO: replace `return null` with `throw NoContextFound()` ASAP.
return null
if (context.predicate(entry))
return context
return findCodeContext(entry, (context as? InnerScope)?.outerContext, predicate)
}
private inline fun <R> switchSymbolizationContextTo(symbol: IrFunctionSymbol, block: () -> R): R? {
val functionContext = findCodeContext(symbol.owner, currentCodeContext) {
val declaration = (this as? FunctionScope)?.declaration
val returnableBlock = (this as? ReturnableBlockScope)?.returnableBlock
val inlinedFunction = returnableBlock?.inlineFunctionSymbol?.owner
declaration == it || inlinedFunction == it
} ?: return null
/**
* We can't switch context safely, only for symbolzation needs: location, scope detection.
*/
using(object: InnerScopeImpl() {
override fun location(line: Int, column: Int): LocationInfo? {
return functionContext.location(line, column)
}
override fun scope(): DIScopeOpaqueRef? {
return functionContext.scope()
}
}) {
return block()
}
}
private fun appendCAdapters() {
context.cAdapterGenerator.generateBindings(codegen)
}
@@ -1198,7 +1234,15 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
private fun generateVariable(variable: IrVariable) {
context.log{"generateVariable : ${ir2string(variable)}"}
val value = variable.initializer?.let { evaluateExpression(it) }
val value = variable.initializer?.let {
val callSiteOrigin = (it as? IrBlock)?.origin as? InlinerExpressionLocationHint
val inlineAtFunctionSymbol = callSiteOrigin?.inlineAtSymbol as? IrFunctionSymbol
inlineAtFunctionSymbol?.run {
switchSymbolizationContextTo(inlineAtFunctionSymbol) {
evaluateExpression(it)
}
} ?: evaluateExpression(it)
}
currentCodeContext.genDeclareVariable(
variable, value, debugInfoIfNeeded(
(currentCodeContext.functionScope() as FunctionScope).declaration, variable))
@@ -2383,7 +2427,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
}
}
class NoContextFound : Throwable()
internal class LocationInfo(val scope: DIScopeOpaqueRef,
val line: Int,