Use symbols to find local declarations in codegen

This commit is contained in:
Mikhael Bogdanov
2018-05-03 11:03:06 +02:00
parent f0e4420259
commit eefc49a617
3 changed files with 57 additions and 40 deletions
@@ -27,6 +27,8 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrTypeAlias import org.jetbrains.kotlin.ir.declarations.IrTypeAlias
import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -86,12 +88,12 @@ class BlockInfo private constructor(val parent: BlockInfo?) {
} }
} }
class VariableInfo(val descriptor: VariableDescriptor, val index: Int, val type: Type, val startLabel: Label) class VariableInfo(val declaration: IrVariable, val index: Int, val type: Type, val startLabel: Label)
@Suppress("IMPLICIT_CAST_TO_ANY") @Suppress("IMPLICIT_CAST_TO_ANY")
class ExpressionCodegen( class ExpressionCodegen(
val irFunction: IrFunction, val irFunction: IrFunction,
val frame: FrameMap, val frame: IrFrameMap,
val mv: InstructionAdapter, val mv: InstructionAdapter,
val classCodegen: ClassCodegen val classCodegen: ClassCodegen
) : IrElementVisitor<StackValue, BlockInfo>, BaseExpressionCodegen { ) : IrElementVisitor<StackValue, BlockInfo>, BaseExpressionCodegen {
@@ -148,11 +150,11 @@ class ExpressionCodegen(
private fun writeLocalVariablesInTable(info: BlockInfo) { private fun writeLocalVariablesInTable(info: BlockInfo) {
val endLabel = markNewLabel() val endLabel = markNewLabel()
info.variables.forEach { info.variables.forEach {
mv.visitLocalVariable(it.descriptor.name.asString(), it.type.descriptor, null, it.startLabel, endLabel, it.index) mv.visitLocalVariable(it.declaration.name.asString(), it.type.descriptor, null, it.startLabel, endLabel, it.index)
} }
info.variables.reversed().forEach { info.variables.reversed().forEach {
frame.leave(it.descriptor) frame.leave(it.declaration.symbol)
} }
} }
@@ -293,14 +295,14 @@ class ExpressionCodegen(
override fun visitVariable(declaration: IrVariable, data: BlockInfo): StackValue { override fun visitVariable(declaration: IrVariable, data: BlockInfo): StackValue {
val varType = typeMapper.mapType(declaration.descriptor) val varType = typeMapper.mapType(declaration.descriptor)
val index = frame.enter(declaration.descriptor, varType) val index = frame.enter(declaration.symbol, varType)
declaration.initializer?.apply { declaration.initializer?.apply {
StackValue.local(index, varType).store(gen(this, varType, data), mv) StackValue.local(index, varType).store(gen(this, varType, data), mv)
} }
val info = VariableInfo( val info = VariableInfo(
declaration.descriptor, declaration,
index, index,
varType, varType,
markNewLabel() markNewLabel()
@@ -320,7 +322,7 @@ class ExpressionCodegen(
} }
override fun visitGetValue(expression: IrGetValue, data: BlockInfo): StackValue { override fun visitGetValue(expression: IrGetValue, data: BlockInfo): StackValue {
return generateLocal(expression.descriptor, expression.asmType) return generateLocal(expression.symbol, expression.asmType)
} }
private fun generateFieldValue(expression: IrFieldAccessExpression, data: BlockInfo): StackValue { private fun generateFieldValue(expression: IrFieldAccessExpression, data: BlockInfo): StackValue {
@@ -349,15 +351,23 @@ class ExpressionCodegen(
return none() return none()
} }
private fun generateLocal(descriptor: CallableDescriptor, type: Type): StackValue { private fun generateLocal(symbol: IrSymbol, type: Type): StackValue {
val index = findLocalIndex(descriptor) val index = findLocalIndex(symbol)
StackValue.local(index, type).put(type, mv) StackValue.local(index, type).put(type, mv)
return onStack(type) return onStack(type)
} }
private fun findLocalIndex(descriptor: CallableDescriptor): Int { private fun findLocalIndex(irSymbol: IrSymbol): Int {
return frame.getIndex(descriptor).apply { return frame.getIndex(irSymbol).apply {
if (this < 0) throw AssertionError("Non-mapped local variable descriptor: $descriptor") if (this < 0) {
if (irFunction.dispatchReceiverParameter != null) {
(irFunction.parent as? IrClass)?.takeIf { it.thisReceiver?.symbol == irSymbol }?.let { return 0 }
}
throw AssertionError(
"Non-mapped local declaration: " +
"${if (irSymbol.isBound) irSymbol.owner.dump() else irSymbol.descriptor} \n in ${irFunction.dump()}"
)
}
} }
} }
@@ -371,7 +381,7 @@ class ExpressionCodegen(
override fun visitSetVariable(expression: IrSetVariable, data: BlockInfo): StackValue { override fun visitSetVariable(expression: IrSetVariable, data: BlockInfo): StackValue {
val value = expression.value.accept(this, data) val value = expression.value.accept(this, data)
StackValue.local(findLocalIndex(expression.descriptor), expression.descriptor.asmType).store(value, mv) StackValue.local(findLocalIndex(expression.symbol), expression.descriptor.asmType).store(value, mv)
return none() return none()
} }
@@ -729,13 +739,13 @@ class ExpressionCodegen(
val clauseStart = markNewLabel() val clauseStart = markNewLabel()
val descriptor = clause.parameter val descriptor = clause.parameter
val descriptorType = descriptor.asmType val descriptorType = descriptor.asmType
val index = frame.enter(descriptor, descriptorType) val index = frame.enter(clause.catchParameter, descriptorType)
mv.store(index, descriptorType) mv.store(index, descriptorType)
val catchBody = clause.result val catchBody = clause.result
gen(catchBody, catchBody.asmType, data) gen(catchBody, catchBody.asmType, data)
frame.leave(descriptor) frame.leave(clause.catchParameter)
val clauseEnd = markNewLabel() val clauseEnd = markNewLabel()
@@ -1014,7 +1024,7 @@ class ExpressionCodegen(
return getOrCreateCallGenerator(descriptor, memberAccessExpression, mappings, false) return getOrCreateCallGenerator(descriptor, memberAccessExpression, mappings, false)
} }
override val frameMap: FrameMap override val frameMap: IrFrameMap
get() = frame get() = frame
override val visitor: InstructionAdapter override val visitor: InstructionAdapter
get() = mv get() = mv
@@ -22,8 +22,7 @@ import org.jetbrains.kotlin.backend.common.lower.InitializersLowering
import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.FunctionCodegen import org.jetbrains.kotlin.codegen.FunctionCodegen
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.util.dump
@@ -55,8 +54,7 @@ open class FunctionCodegen(private val irFunction: IrFunction, private val class
private fun doGenerate() { private fun doGenerate() {
val signature = classCodegen.typeMapper.mapSignatureWithGeneric(descriptor, OwnerKind.IMPLEMENTATION) val signature = classCodegen.typeMapper.mapSignatureWithGeneric(descriptor, OwnerKind.IMPLEMENTATION)
val isStatic = irFunction.isStatic val isStatic = irFunction.isStatic
val frameMap = createFrameMapWithReceivers(classCodegen.state, descriptor, signature, isStatic) val frameMap = createFrameMapWithReceivers(classCodegen.state, irFunction, signature)
val flags = calculateMethodFlags(isStatic) val flags = calculateMethodFlags(isStatic)
val methodVisitor = createMethod(flags, signature) val methodVisitor = createMethod(flags, signature)
@@ -90,7 +88,7 @@ open class FunctionCodegen(private val irFunction: IrFunction, private val class
return flags return flags
} }
open protected fun createMethod(flags: Int, signature: JvmMethodGenericSignature): MethodVisitor { protected open fun createMethod(flags: Int, signature: JvmMethodGenericSignature): MethodVisitor {
return classCodegen.visitor.newMethod( return classCodegen.visitor.newMethod(
irFunction.OtherOrigin, irFunction.OtherOrigin,
flags, flags,
@@ -120,26 +118,21 @@ open class FunctionCodegen(private val irFunction: IrFunction, private val class
fun createFrameMapWithReceivers( fun createFrameMapWithReceivers(
state: GenerationState, state: GenerationState,
function: FunctionDescriptor, irFunction: IrFunction,
signature: JvmMethodSignature, signature: JvmMethodSignature
isStatic: Boolean ): IrFrameMap {
): FrameMap { val frameMap = IrFrameMap()
val frameMap = FrameMap() if (irFunction is IrConstructor) {
if (!isStatic) { frameMap.enter((irFunction.parent as IrClass).thisReceiver!!, AsmTypes.OBJECT_TYPE)
val descriptorForThis = } else if (irFunction.dispatchReceiverParameter != null) {
if (function is ClassConstructorDescriptor) frameMap.enter(irFunction.dispatchReceiverParameter!!, AsmTypes.OBJECT_TYPE)
function.containingDeclaration.thisAsReceiverParameter
else
function.dispatchReceiverParameter
frameMap.enter(descriptorForThis, AsmTypes.OBJECT_TYPE)
} }
for (parameter in signature.valueParameters) { for (parameter in signature.valueParameters) {
if (parameter.kind == JvmMethodParameterKind.RECEIVER) { if (parameter.kind == JvmMethodParameterKind.RECEIVER) {
val receiverParameter = function.extensionReceiverParameter val receiverParameter = irFunction.extensionReceiverParameter
if (receiverParameter != null) { if (receiverParameter?.descriptor != null) {
frameMap.enter(receiverParameter, state.typeMapper.mapType(receiverParameter)) frameMap.enter(receiverParameter, state.typeMapper.mapType(receiverParameter.descriptor))
} else { } else {
frameMap.enterTemp(parameter.asmType) frameMap.enterTemp(parameter.asmType)
} }
@@ -148,8 +141,8 @@ fun createFrameMapWithReceivers(
} }
} }
for (parameter in function.valueParameters) { for (parameter in irFunction.valueParameters) {
frameMap.enter(parameter, state.typeMapper.mapType(parameter)) frameMap.enter(parameter, state.typeMapper.mapType(parameter.type))
} }
return frameMap return frameMap
@@ -5,8 +5,22 @@
package org.jetbrains.kotlin.backend.jvm.codegen package org.jetbrains.kotlin.backend.jvm.codegen
import org.jetbrains.kotlin.codegen.FrameMapBase
import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.org.objectweb.asm.Type
class IrFrameMap : FrameMapBase<IrSymbol>()
internal val IrFunction.isStatic internal val IrFunction.isStatic
get() = this.dispatchReceiverParameter == null && this !is IrConstructor get() = this.dispatchReceiverParameter == null && this !is IrConstructor
fun IrFrameMap.enter(irDeclaration: IrSymbolOwner, type: Type): Int {
return enter(irDeclaration.symbol, type)
}
fun IrFrameMap.leave(irDeclaration: IrSymbolOwner): Int {
return leave(irDeclaration.symbol)
}