JVM_IR: refactor FunctionCodegen a bit

This commit is contained in:
pyos
2020-03-20 15:56:57 +01:00
committed by max-kammerer
parent df5c5b163e
commit f6e7d7f7f1
3 changed files with 75 additions and 109 deletions
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.codegen.coroutines.CoroutineTransformerMethodVisitor
import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_IMPL_NAME_SUFFIX import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_IMPL_NAME_SUFFIX
import org.jetbrains.kotlin.codegen.coroutines.reportSuspensionPointInsideMonitor import org.jetbrains.kotlin.codegen.coroutines.reportSuspensionPointInsideMonitor
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
import org.jetbrains.kotlin.config.isReleaseCoroutines import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
@@ -39,17 +40,20 @@ internal fun generateStateMachine(
methodVisitor: MethodVisitor, methodVisitor: MethodVisitor,
access: Int, access: Int,
signature: JvmMethodGenericSignature, signature: JvmMethodGenericSignature,
obtainContinuationClassBuilder: () -> ClassBuilder, obtainContinuationClassBuilder: () -> ClassBuilder
element: KtElement
): MethodVisitor { ): MethodVisitor {
val state = classCodegen.context.state val state = classCodegen.context.state
val languageVersionSettings = state.languageVersionSettings val languageVersionSettings = state.languageVersionSettings
assert(languageVersionSettings.isReleaseCoroutines()) { "Experimental coroutines are unsupported in JVM_IR backend" } assert(languageVersionSettings.isReleaseCoroutines()) { "Experimental coroutines are unsupported in JVM_IR backend" }
val element = if (irFunction.isSuspend)
irFunction.symbol.descriptor.psiElement ?: classCodegen.irClass.descriptor.psiElement
else
classCodegen.context.suspendLambdaToOriginalFunctionMap[classCodegen.irClass.attributeOwnerId]!!.symbol.descriptor.psiElement
return CoroutineTransformerMethodVisitor( return CoroutineTransformerMethodVisitor(
methodVisitor, access, signature.asmMethod.name, signature.asmMethod.descriptor, signature.genericsSignature, null, methodVisitor, access, signature.asmMethod.name, signature.asmMethod.descriptor, signature.genericsSignature, null,
obtainClassBuilderForCoroutineState = obtainContinuationClassBuilder, obtainClassBuilderForCoroutineState = obtainContinuationClassBuilder,
reportSuspensionPointInsideMonitor = { reportSuspensionPointInsideMonitor(element, state, it) }, reportSuspensionPointInsideMonitor = { reportSuspensionPointInsideMonitor(element as KtElement, state, it) },
lineNumber = CodegenUtil.getLineNumberForElement(element, false) ?: 0, lineNumber = element?.let { CodegenUtil.getLineNumberForElement(it, false) } ?: 0,
sourceFile = classCodegen.irClass.file.name, sourceFile = classCodegen.irClass.file.name,
languageVersionSettings = languageVersionSettings, languageVersionSettings = languageVersionSettings,
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization, shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
@@ -71,6 +75,26 @@ internal fun IrFunction.anyOfOverriddenFunctionsReturnsNonUnit(): Boolean {
} == true } == true
} }
internal fun IrFunction.suspendForInlineToOriginal(): IrSimpleFunction? {
if (origin != JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE &&
origin != JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE
) return null
return parentAsClass.declarations.find {
it is IrSimpleFunction && it.attributeOwnerId == (this as IrSimpleFunction).attributeOwnerId &&
it.name.asString() + FOR_INLINE_SUFFIX == name.asString()
} as IrSimpleFunction?
}
internal fun IrFunction.alwaysNeedsContinuation(): Boolean =
this is IrSimpleFunction && hasContinuation() && parentAsClass.declarations.any {
it is IrSimpleFunction && it.attributeOwnerId == attributeOwnerId &&
it.origin == JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE
}
internal fun IrFunction.continuationClass(): IrClass? =
(body as? IrBlockBody)?.statements?.find { it is IrClass && it.origin == JvmLoweredDeclarationOrigin.CONTINUATION_CLASS }
as IrClass?
internal fun IrFunction.continuationParameter(): IrValueParameter? = when { internal fun IrFunction.continuationParameter(): IrValueParameter? = when {
isInvokeSuspendOfLambda() || isInvokeSuspendForInlineOfLambda() -> dispatchReceiverParameter isInvokeSuspendOfLambda() || isInvokeSuspendForInlineOfLambda() -> dispatchReceiverParameter
else -> valueParameters.singleOrNull { it.origin == JvmLoweredDeclarationOrigin.CONTINUATION_CLASS } else -> valueParameters.singleOrNull { it.origin == JvmLoweredDeclarationOrigin.CONTINUATION_CLASS }
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.putNeedClassReificationMarker import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.putNeedClassReificationMarker
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.OperationKind.AS import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.OperationKind.AS
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.OperationKind.SAFE_AS import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.OperationKind.SAFE_AS
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics
import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysFalseIfeq import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysFalseIfeq
import org.jetbrains.kotlin.codegen.pseudoInsns.fixStackAndJump import org.jetbrains.kotlin.codegen.pseudoInsns.fixStackAndJump
@@ -52,7 +51,6 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
import org.jetbrains.kotlin.types.model.TypeParameterMarker import org.jetbrains.kotlin.types.model.TypeParameterMarker
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.kotlin.utils.keysToMap import org.jetbrains.kotlin.utils.keysToMap
@@ -222,10 +220,8 @@ class ExpressionCodegen(
private fun generateFakeContinuationConstructorIfNeeded() { private fun generateFakeContinuationConstructorIfNeeded() {
if (irFunction.origin != FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE) return if (irFunction.origin != FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE) return
val continuationClass = classCodegen.irClass.functions.find { val continuationClass = irFunction.suspendForInlineToOriginal()?.continuationClass()
it.attributeOwnerId == (irFunction as? IrSimpleFunction)?.attributeOwnerId && ?: error("could not find continuation for ${irFunction.render()}")
it.name.asString() == irFunction.name.asString().removeSuffix(FOR_INLINE_SUFFIX)
}?.body?.statements?.firstIsInstance<IrClass>() ?: error("could not find continuation for ${irFunction.render()}")
val continuationType = typeMapper.mapClass(continuationClass) val continuationType = typeMapper.mapClass(continuationClass)
val continuationIndex = frameMap.getIndex(irFunction.continuationParameter()!!.symbol) val continuationIndex = frameMap.getIndex(irFunction.continuationParameter()!!.symbol)
with(mv) { with(mv) {
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_SYNTHETIC_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_SYNTHETIC_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.annotations.STRICTFP_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.jvm.annotations.STRICTFP_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.annotations.SYNCHRONIZED_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.jvm.annotations.SYNCHRONIZED_ANNOTATION_FQ_NAME
@@ -43,10 +42,6 @@ open class FunctionCodegen(
) { ) {
private val context = classCodegen.context private val context = classCodegen.context
private val continuationClassCodegen = lazy {
classCodegen.createLocalClassCodegen(irFunction.continuationClass(), irFunction).also { it.generate() }
}
fun generate(smapOverride: DefaultSourceMapper? = null): JvmMethodGenericSignature = fun generate(smapOverride: DefaultSourceMapper? = null): JvmMethodGenericSignature =
try { try {
doGenerate(smapOverride) doGenerate(smapOverride)
@@ -56,8 +51,7 @@ open class FunctionCodegen(
private fun doGenerate(smapOverride: DefaultSourceMapper?): JvmMethodGenericSignature { private fun doGenerate(smapOverride: DefaultSourceMapper?): JvmMethodGenericSignature {
val signature = context.methodSignatureMapper.mapSignatureWithGeneric(irFunction) val signature = context.methodSignatureMapper.mapSignatureWithGeneric(irFunction)
val flags = irFunction.calculateMethodFlags()
val flags = calculateMethodFlags(irFunction.isStatic)
var methodVisitor = createMethod(flags, signature) var methodVisitor = createMethod(flags, signature)
if (context.state.generateParametersMetadata && flags.and(Opcodes.ACC_SYNTHETIC) == 0) { if (context.state.generateParametersMetadata && flags.and(Opcodes.ACC_SYNTHETIC) == 0) {
@@ -75,11 +69,7 @@ open class FunctionCodegen(
TypeReference.newTypeReference(TypeReference.METHOD_RETURN).value, path, descr, visible TypeReference.newTypeReference(TypeReference.METHOD_RETURN).value, path, descr, visible
) )
} }
}.genAnnotations( }.genAnnotations(irFunction, signature.asmMethod.returnType, irFunction.returnType)
irFunction,
signature.asmMethod.returnType,
irFunction.returnType
)
// Not generating parameter annotations for default stubs fixes KT-7892, though // Not generating parameter annotations for default stubs fixes KT-7892, though
// this certainly looks like a workaround for a javac bug. // this certainly looks like a workaround for a javac bug.
if (irFunction !is IrConstructor || !irFunction.parentAsClass.shouldNotGenerateConstructorParameterAnnotations()) { if (irFunction !is IrConstructor || !irFunction.parentAsClass.shouldNotGenerateConstructorParameterAnnotations()) {
@@ -87,29 +77,18 @@ open class FunctionCodegen(
} }
} }
val continuationClassCodegen = lazy {
classCodegen.createLocalClassCodegen(irFunction.continuationClass()!!, irFunction).also { it.generate() }
}
if (!context.state.classBuilderMode.generateBodies || flags.and(Opcodes.ACC_ABSTRACT) != 0 || irFunction.isExternal) { if (!context.state.classBuilderMode.generateBodies || flags.and(Opcodes.ACC_ABSTRACT) != 0 || irFunction.isExternal) {
generateAnnotationDefaultValueIfNeeded(methodVisitor) generateAnnotationDefaultValueIfNeeded(methodVisitor)
} else { } else {
val frameMap = createFrameMapWithReceivers() val frameMap = irFunction.createFrameMapWithReceivers()
if (irFunction.hasContinuation() || irFunction.isInvokeSuspendOfLambda()) { if (irFunction.hasContinuation() || irFunction.isInvokeSuspendOfLambda()) {
if (irFunction is IrSimpleFunction && irFunction.parentAsClass.declarations.any { methodVisitor = generateStateMachine(irFunction, classCodegen, methodVisitor, flags, signature) {
it is IrSimpleFunction && it.attributeOwnerId == irFunction.attributeOwnerId && // This has to be done lazily to avoid generating the class if tail call optimization makes it redundant.
it.origin == JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE if (irFunction.isSuspend) continuationClassCodegen.value.visitor else classCodegen.visitor
}
) {
// Force generation of fake continuation for inliner.
continuationClassCodegen.value
} }
// This has to be done lazily to avoid generating the class if tail call optimization makes it redundant.
val getContinuation = {
if (irFunction.isSuspend)
continuationClassCodegen.value.visitor
else
classCodegen.visitor
}
methodVisitor = generateStateMachine(
irFunction, classCodegen, methodVisitor, flags, signature, getContinuation, psiElement()
)
} }
context.state.globalInlineContext.enterDeclaration(irFunction.suspendFunctionOriginal().descriptor) context.state.globalInlineContext.enterDeclaration(irFunction.suspendFunctionOriginal().descriptor)
try { try {
@@ -121,10 +100,9 @@ open class FunctionCodegen(
methodVisitor.visitMaxs(-1, -1) methodVisitor.visitMaxs(-1, -1)
} }
methodVisitor.visitEnd() methodVisitor.visitEnd()
if (continuationClassCodegen.isInitialized()) { if (continuationClassCodegen.isInitialized() || irFunction.alwaysNeedsContinuation()) {
continuationClassCodegen.value.done() continuationClassCodegen.value.done()
} }
return signature return signature
} }
@@ -136,16 +114,6 @@ open class FunctionCodegen(
private fun IrClass.shouldNotGenerateConstructorParameterAnnotations() = private fun IrClass.shouldNotGenerateConstructorParameterAnnotations() =
isAnonymousObject || origin == JvmLoweredDeclarationOrigin.CONTINUATION_CLASS || origin == JvmLoweredDeclarationOrigin.SUSPEND_LAMBDA isAnonymousObject || origin == JvmLoweredDeclarationOrigin.CONTINUATION_CLASS || origin == JvmLoweredDeclarationOrigin.SUSPEND_LAMBDA
private fun psiElement(): KtElement =
(if (irFunction.isSuspend)
irFunction.symbol.descriptor.psiElement ?: irFunction.parentAsClass.descriptor.psiElement
else
context.suspendLambdaToOriginalFunctionMap[irFunction.parentAsClass.attributeOwnerId]!!.symbol.descriptor.psiElement)
as KtElement
private fun IrFunction.continuationClass(): IrClass =
(body as IrBlockBody).statements.first { it is IrClass && it.origin == JvmLoweredDeclarationOrigin.CONTINUATION_CLASS } as IrClass
private fun IrFunction.getVisibilityForDefaultArgumentStub(): Int = private fun IrFunction.getVisibilityForDefaultArgumentStub(): Int =
when (visibility) { when (visibility) {
Visibilities.PUBLIC -> Opcodes.ACC_PUBLIC Visibilities.PUBLIC -> Opcodes.ACC_PUBLIC
@@ -153,59 +121,48 @@ open class FunctionCodegen(
else -> throw IllegalStateException("Default argument stub should be either public or package private: ${ir2string(this)}") else -> throw IllegalStateException("Default argument stub should be either public or package private: ${ir2string(this)}")
} }
private fun calculateMethodFlags(isStatic: Boolean): Int { private fun IrFunction.calculateMethodFlags(): Int {
if (irFunction.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER) { if (origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER) {
return irFunction.getVisibilityForDefaultArgumentStub() or Opcodes.ACC_SYNTHETIC.let { return getVisibilityForDefaultArgumentStub() or Opcodes.ACC_SYNTHETIC.let {
if (irFunction is IrConstructor) it else it or Opcodes.ACC_STATIC if (this is IrConstructor) it else it or Opcodes.ACC_STATIC
} }
} }
val visibility = irFunction.getVisibilityAccessFlag() val isVararg = valueParameters.lastOrNull()?.varargElementType != null
val staticFlag = if (isStatic) Opcodes.ACC_STATIC else 0 val isBridge = origin == IrDeclarationOrigin.BRIDGE || origin == IrDeclarationOrigin.BRIDGE_SPECIAL
val varargFlag = if (irFunction.valueParameters.lastOrNull()?.varargElementType != null) Opcodes.ACC_VARARGS else 0 val modalityFlag = when ((this as? IrSimpleFunction)?.modality) {
val deprecation = irFunction.deprecationFlags
val bridgeFlag = if (
irFunction.origin == IrDeclarationOrigin.BRIDGE ||
irFunction.origin == IrDeclarationOrigin.BRIDGE_SPECIAL
) Opcodes.ACC_BRIDGE else 0
val modalityFlag = when ((irFunction as? IrSimpleFunction)?.modality) {
Modality.FINAL -> when { Modality.FINAL -> when {
irFunction.origin == JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER -> 0 origin == JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER -> 0
classCodegen.irClass.isInterface && irFunction.body != null -> 0 parentAsClass.isInterface && body != null -> 0
!classCodegen.irClass.isAnnotationClass || irFunction.isStatic -> Opcodes.ACC_FINAL parentAsClass.isAnnotationClass && !isStatic -> Opcodes.ACC_ABSTRACT
else -> Opcodes.ACC_ABSTRACT else -> Opcodes.ACC_FINAL
} }
Modality.ABSTRACT -> Opcodes.ACC_ABSTRACT Modality.ABSTRACT -> Opcodes.ACC_ABSTRACT
else -> if (classCodegen.irClass.isJvmInterface && irFunction.body == null) Opcodes.ACC_ABSTRACT else 0 //TODO transform interface modality on lowering to DefaultImpls // TODO transform interface modality on lowering to DefaultImpls
else -> if (parentAsClass.isJvmInterface && body == null) Opcodes.ACC_ABSTRACT else 0
} }
val nativeFlag = if (irFunction.isExternal) Opcodes.ACC_NATIVE else 0 val isSynthetic = origin.isSynthetic || hasAnnotation(JVM_SYNTHETIC_ANNOTATION_FQ_NAME) ||
val syntheticFlag = (isSuspend && Visibilities.isPrivate(visibility) && !isInline) || isReifiable()
if (irFunction.origin.isSynthetic || irFunction.hasAnnotation(JVM_SYNTHETIC_ANNOTATION_FQ_NAME) || val isStrict = hasAnnotation(STRICTFP_ANNOTATION_FQ_NAME)
(irFunction.isSuspend && Visibilities.isPrivate(irFunction.visibility) && !irFunction.isInline) || val isSynchronized = hasAnnotation(SYNCHRONIZED_ANNOTATION_FQ_NAME)
irFunction.isReifiable()
) Opcodes.ACC_SYNTHETIC
else 0
val strictFpFlag = if (irFunction.hasAnnotation(STRICTFP_ANNOTATION_FQ_NAME)) Opcodes.ACC_STRICT else 0
val synchronizedFlag = if (irFunction.hasAnnotation(SYNCHRONIZED_ANNOTATION_FQ_NAME)) Opcodes.ACC_SYNCHRONIZED else 0
return visibility or return getVisibilityAccessFlag() or modalityFlag or deprecationFlags or
modalityFlag or (if (isStatic) Opcodes.ACC_STATIC else 0) or
staticFlag or (if (isVararg) Opcodes.ACC_VARARGS else 0) or
varargFlag or (if (isExternal) Opcodes.ACC_NATIVE else 0) or
deprecation or (if (isBridge) Opcodes.ACC_BRIDGE else 0) or
nativeFlag or (if (isSynthetic) Opcodes.ACC_SYNTHETIC else 0) or
bridgeFlag or (if (isStrict) Opcodes.ACC_STRICT else 0) or
syntheticFlag or (if (isSynchronized) Opcodes.ACC_SYNCHRONIZED else 0)
strictFpFlag or
synchronizedFlag
} }
protected open fun createMethod(flags: Int, signature: JvmMethodGenericSignature): MethodVisitor = protected open fun createMethod(flags: Int, signature: JvmMethodGenericSignature): MethodVisitor =
classCodegen.visitor.newMethod( classCodegen.visitor.newMethod(
irFunction.OtherOrigin, irFunction.OtherOrigin,
flags, flags,
signature.asmMethod.name, signature.asmMethod.descriptor, signature.asmMethod.name,
if (flags.and(Opcodes.ACC_SYNTHETIC) != 0) null else signature.genericsSignature, signature.asmMethod.descriptor,
signature.genericsSignature.takeIf { flags.and(Opcodes.ACC_SYNTHETIC) == 0 },
getThrownExceptions(irFunction)?.toTypedArray() getThrownExceptions(irFunction)?.toTypedArray()
) )
@@ -223,10 +180,7 @@ open class FunctionCodegen(
private fun generateAnnotationDefaultValueIfNeeded(methodVisitor: MethodVisitor) { private fun generateAnnotationDefaultValueIfNeeded(methodVisitor: MethodVisitor) {
getAnnotationDefaultValueExpression()?.let { defaultValueExpression -> getAnnotationDefaultValueExpression()?.let { defaultValueExpression ->
val annotationCodegen = object: AnnotationCodegen( val annotationCodegen = object : AnnotationCodegen(classCodegen, context) {
classCodegen,
context
) {
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor { override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
return methodVisitor.visitAnnotationDefault() return methodVisitor.visitAnnotationDefault()
} }
@@ -249,26 +203,18 @@ open class FunctionCodegen(
?.expression ?.expression
} }
private fun IrFrameMap.enterDispatchReceiver(parameter: IrValueParameter) { private fun IrFunction.createFrameMapWithReceivers(): IrFrameMap {
val type = context.typeMapper.mapTypeAsDeclaration(parameter.type)
enter(parameter, type)
}
private fun createFrameMapWithReceivers(): IrFrameMap {
val frameMap = IrFrameMap() val frameMap = IrFrameMap()
val receiver = if (this is IrConstructor) parentAsClass.thisReceiver else dispatchReceiverParameter
if (irFunction is IrConstructor) { receiver?.let {
frameMap.enterDispatchReceiver(irFunction.constructedClass.thisReceiver!!) frameMap.enter(it, context.typeMapper.mapTypeAsDeclaration(it.type))
} else if (irFunction.dispatchReceiverParameter != null) {
frameMap.enterDispatchReceiver(irFunction.dispatchReceiverParameter!!)
} }
irFunction.extensionReceiverParameter?.let { extensionReceiverParameter?.let {
frameMap.enter(it, context.typeMapper.mapType(it)) frameMap.enter(it, context.typeMapper.mapType(it))
} }
for (parameter in irFunction.valueParameters) { for (parameter in valueParameters) {
frameMap.enter(parameter, context.typeMapper.mapType(parameter.type)) frameMap.enter(parameter, context.typeMapper.mapType(parameter.type))
} }
return frameMap return frameMap
} }
} }