diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt index 5e51ad249e1..770cec83a4d 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt @@ -180,7 +180,8 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration configuration.get(BinaryOptions.appStateTracking) ?: AppStateTracking.DISABLED } - val mimallocUseDefaultOptions by lazy { + + val mimallocUseDefaultOptions: Boolean by lazy { configuration.get(BinaryOptions.mimallocUseDefaultOptions) ?: false } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt index a5a8053901a..b83c01f8397 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.backend.konan.descriptors import llvm.LLVMStoreSizeOfType +import org.jetbrains.kotlin.backend.common.lower.coroutines.getOrCreateFunctionWithContinuationStub import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.ir.* import org.jetbrains.kotlin.backend.konan.llvm.computeFunctionName @@ -507,8 +508,10 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context) { /** * Normally, function should be already replaced. But if the function come from LazyIr, it can be not replaced. */ - fun IrSimpleFunction.getLoweredVersion() = context.mapping.suspendFunctionsToFunctionWithContinuations[this] ?: this - + fun IrSimpleFunction.getLoweredVersion() = when { + isSuspend -> this.getOrCreateFunctionWithContinuationStub(context) + else -> this + } private val overridableOrOverridingMethods: List get() = irClass.simpleFunctions() .map {it.getLoweredVersion() } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt index 8aa0cfa685a..0fb580bd177 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt @@ -105,8 +105,6 @@ internal interface IntrinsicGeneratorEnvironment { val functionGenerationContext: FunctionGenerationContext - val continuation: LLVMValueRef - val exceptionHandler: ExceptionHandler val stackLocalsManager: StackLocalsManager @@ -156,10 +154,10 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv /** * Some intrinsics have to be processed before evaluation of their arguments. * So this method looks at [callSite] and if it is call to "special" intrinsic - * processes it. Otherwise it returns null. + * processes it. Otherwise, it returns null. */ + @Suppress("UNUSED_PARAMETER") fun tryEvaluateSpecialCall(callSite: IrFunctionAccessExpression, resultSlot: LLVMValueRef?): LLVMValueRef? { - resultSlot.let{} val function = callSite.symbol.owner if (!function.isTypedIntrinsic) { return null @@ -241,9 +239,9 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv IntrinsicType.INTEROP_NATIVE_PTR_PLUS_LONG -> emitNativePtrPlusLong(args) IntrinsicType.INTEROP_GET_NATIVE_NULL_PTR -> emitGetNativeNullPtr() IntrinsicType.IDENTITY -> emitIdentity(args) - IntrinsicType.GET_CONTINUATION -> emitGetContinuation() IntrinsicType.INTEROP_MEMORY_COPY -> emitMemoryCopy(callSite, args) IntrinsicType.IS_EXPERIMENTAL_MM -> emitIsExperimentalMM() + IntrinsicType.GET_CONTINUATION, IntrinsicType.RETURN_IF_SUSPENDED, IntrinsicType.INTEROP_BITS_TO_FLOAT, IntrinsicType.INTEROP_BITS_TO_DOUBLE, @@ -286,8 +284,6 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv private fun reportNonLoweredIntrinsic(intrinsicType: ConstantConstructorIntrinsicType): Nothing = context.reportCompilationError("Constant constructor intrinsic of type $intrinsicType should be handled by previous lowering phase") - private fun FunctionGenerationContext.emitGetContinuation(): LLVMValueRef = - environment.continuation private fun FunctionGenerationContext.emitIdentity(args: List): LLVMValueRef = args.single() diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index fe4a0669423..40650b9a0f0 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.konan.llvm import kotlinx.cinterop.* import llvm.* +import org.jetbrains.kotlin.backend.common.lower.coroutines.getOrCreateFunctionWithContinuationStub import org.jetbrains.kotlin.backend.common.lower.inline.InlinerExpressionLocationHint import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.cgen.CBridgeOrigin @@ -224,9 +225,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map null + // TODO: May be tie up inline lambdas to their outer function? + codegen.isExternal(this) && !KonanBinaryInterface.isExported(this) -> null + this is IrSimpleFunction && isSuspend -> this.getOrCreateFunctionWithContinuationStub(context).let { codegen.llvmFunctionOrNull(it)?.llvmValue } + else -> codegen.llvmFunctionOrNull(this)?.llvmValue + } + return if (functionLlvmValue != null) { debugInfo.subprograms.getOrPut(functionLlvmValue) { memScoped { val subroutineType = subroutineType(context, codegen.llvmTargetData) - val llvmFunction = codegen.llvmFunction(this@scope).llvmValue - diFunctionScope(name.asString(), llvmFunction.name!!, startLine, subroutineType).also { + diFunctionScope(name.asString(), functionLlvmValue.name!!, startLine, subroutineType).also { if (!this@scope.isInline) - DIFunctionAddSubprogram(llvmFunction, it) + DIFunctionAddSubprogram(functionLlvmValue, it) } } } as DIScopeOpaqueRef @@ -2291,19 +2290,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map, resultLifetime: Lifetime, resultSlot: LLVMValueRef?): LLVMValueRef { val function = callee.symbol.owner + require(!function.isSuspend) { "Suspend functions should be lowered out at this point"} - val argsWithContinuationIfNeeded = if (function.isSuspend) - args + getContinuation() - else args return when { function.isTypedIntrinsic -> intrinsicGenerator.evaluateCall(callee, args, resultSlot) - function.isBuiltInOperator -> evaluateOperatorCall(callee, argsWithContinuationIfNeeded) + function.isBuiltInOperator -> evaluateOperatorCall(callee, args) function.origin == DECLARATION_ORIGIN_FILE_GLOBAL_INITIALIZER -> evaluateFileGlobalInitializerCall(function) function.origin == DECLARATION_ORIGIN_FILE_THREAD_LOCAL_INITIALIZER -> evaluateFileThreadLocalInitializerCall(function) function.origin == DECLARATION_ORIGIN_FILE_STANDALONE_THREAD_LOCAL_INITIALIZER -> evaluateFileStandaloneThreadLocalInitializerCall(function) - else -> evaluateSimpleFunctionCall(function, argsWithContinuationIfNeeded, resultLifetime, callee.superQualifierSymbol?.owner, resultSlot) + else -> evaluateSimpleFunctionCall(function, args, resultLifetime, callee.superQualifierSymbol?.owner, resultSlot) } } @@ -2681,11 +2669,9 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map - functionGenerationContext.unreachable() - needsNativeThreadState -> - functionGenerationContext.switchThreadState(ThreadState.Runnable) + when { + function.returnType.isNothing() -> functionGenerationContext.unreachable() + needsNativeThreadState -> functionGenerationContext.switchThreadState(ThreadState.Runnable) } if (llvmCallable.returnType == voidType) { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmAttributes.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmAttributes.kt index 16f023680b5..6a7f53572b2 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmAttributes.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmAttributes.kt @@ -7,11 +7,6 @@ package org.jetbrains.kotlin.backend.konan.llvm import llvm.* import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.ir.declarations.IrConstructor -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.types.isNothing -import org.jetbrains.kotlin.ir.util.isSuspend -import org.jetbrains.kotlin.ir.util.isThrowable import org.jetbrains.kotlin.konan.target.Architecture import org.jetbrains.kotlin.konan.target.Family import org.jetbrains.kotlin.konan.target.KonanTarget diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmFunctionPrototype.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmFunctionPrototype.kt index d571206d515..398378faf5a 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmFunctionPrototype.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmFunctionPrototype.kt @@ -193,8 +193,8 @@ private fun mustNotInline(context: Context, irFunction: IrFunction): Boolean { private fun inferFunctionAttributes(contextUtils: ContextUtils, irFunction: IrFunction): List = mutableListOf().apply { - // suspend function can return value in case of COROUTINE_SUSPENDED. - if (irFunction.returnType.isNothing() && !irFunction.isSuspend) { + if (irFunction.returnType.isNothing()) { + require(!irFunction.isSuspend) { "Suspend functions should be lowered out at this point"} add(LlvmFunctionAttribute.NoReturn) } if (mustNotInline(contextUtils.context, irFunction)) { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmParamType.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmParamType.kt index cbe6c83a794..ea4fd37b3bd 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmParamType.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmParamType.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.util.allParameters import org.jetbrains.kotlin.ir.util.isSuspend +import org.jetbrains.kotlin.ir.util.render /** * LLVM function's parameter type with its attributes. @@ -26,8 +27,7 @@ internal fun ContextUtils.getLlvmFunctionParameterTypes(function: IrFunction): L val paramTypes = ArrayList(function.allParameters.map { LlvmParamType(getLLVMType(it.type), argumentAbiInfo.defaultParameterAttributesForIrType(it.type)) }) - if (function.isSuspend) - paramTypes.add(LlvmParamType(kObjHeaderPtr)) // Suspend functions have implicit parameter of type Continuation<>. + require(!function.isSuspend) { "Suspend functions should be lowered out at this point"} if (isObjectType(returnType)) paramTypes.add(LlvmParamType(kObjHeaderPtrPtr)) @@ -37,7 +37,7 @@ internal fun ContextUtils.getLlvmFunctionParameterTypes(function: IrFunction): L internal fun ContextUtils.getLlvmFunctionReturnType(function: IrFunction): LlvmRetType { val returnType = when { function is IrConstructor -> LlvmParamType(voidType) - function.isSuspend -> LlvmParamType(kObjHeaderPtr) // Suspend functions return Any?. + function.isSuspend -> error("Suspend functions should be lowered out at this point, but ${function.render()} is still here") else -> LlvmParamType( getLLVMReturnType(function.returnType), argumentAbiInfo.defaultParameterAttributesForIrType(function.returnType) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt index 92e0723390d..cfde0e13135 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt @@ -76,11 +76,7 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr } override fun IrExpression.useAsReturnValue(returnTarget: IrReturnTargetSymbol): IrExpression = when (returnTarget) { - is IrSimpleFunctionSymbol -> if (returnTarget.owner.isSuspend && returnTarget == currentFunction?.symbol) { - this.useAs(irBuiltIns.anyNType) - } else { - this.useAs(returnTarget.owner.returnType) - } + is IrSimpleFunctionSymbol -> this.useAs(returnTarget.owner.returnType) is IrConstructorSymbol -> this.useAs(irBuiltIns.unitType) is IrReturnableBlockSymbol -> this.useAs(returnTarget.owner.type) else -> error(returnTarget) @@ -89,8 +85,7 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr override fun IrExpression.useAs(type: IrType): IrExpression { val actualType = when (this) { is IrCall -> { - if (this.symbol.owner.isSuspend) irBuiltIns.anyNType - else if (this.symbol == symbols.reinterpret) this.getTypeArgument(1)!! + if (this.symbol == symbols.reinterpret) this.getTypeArgument(1)!! else this.callTarget.returnType } is IrGetField -> this.symbol.owner.type diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionReferenceLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionReferenceLowering.kt index 5ffcaf6c9f7..daad9aa5fa6 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionReferenceLowering.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionReferenceLowering.kt @@ -481,9 +481,6 @@ internal class FunctionReferenceLowering(val context: Context) : FileLoweringPas if (parameter == referencedFunction.extensionReceiverParameter && extensionReceiverParameter != null) irGet(extensionReceiverParameter!!) - else if (function.isSuspend && unboundIndex == valueParameters.size) - // For suspend functions the last argument is continuation and it is implicit. - irCall(getContinuationSymbol.owner, listOf(returnType)) else irGet(valueParameters[unboundIndex++]) } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt index d4b75108dee..a9110a5d654 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt @@ -445,8 +445,6 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag symbols.baseContinuationImpl.owner.declarations .filterIsInstance().single { it.name.asString() == "invokeSuspend" }.symbol - private val getContinuationSymbol = symbols.getContinuation - private val arrayGetSymbols = symbols.arrayGet.values private val arraySetSymbols = symbols.arraySet.values private val createUninitializedInstanceSymbol = symbols.createUninitializedInstance @@ -485,27 +483,12 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag { Scoped(DataFlowIR.Node.Parameter(it.index), rootScope) } ) - private val continuationParameter = when { - declaration !is IrSimpleFunction -> null - - declaration.isSuspend -> Scoped(DataFlowIR.Node.Parameter(allParameters.size), rootScope) - - declaration.overrides(invokeSuspendFunctionSymbol.owner) -> // is a ContinuationImpl inheritor. - templateParameters[declaration.dispatchReceiverParameter!!] // It is its own continuation. - - else -> null - } - - private fun getContinuation() = continuationParameter - ?: error("Function ${declaration.descriptor} has no continuation parameter") private val nodes = mutableMapOf>() private val variables = mutableMapOf>() private val expressionsScopes = mutableMapOf() fun build(): DataFlowIR.Function { - val isSuspend = declaration is IrSimpleFunction && declaration.isSuspend - val scopes = mutableMapOf() fun transformLoop(loop: IrLoop, parentLoop: IrLoop?): DataFlowIR.Node.Scope { scopes[loop]?.let { return it } @@ -566,8 +549,6 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag rootScope.nodes += templateParameters.values.map { it.value } rootScope.nodes += returnsNode rootScope.nodes += throwsNode - if (isSuspend) - rootScope.nodes += continuationParameter!!.value return DataFlowIR.Function( symbol = symbolTable.mapFunction(declaration), @@ -610,7 +591,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag private fun mapReturnType(actualType: IrType, returnType: IrType) = mapWrappedType(actualType, returnType) - private fun getNode(expression: IrExpression, continuationOverride: DataFlowIR.Node? = null): Scoped { + private fun getNode(expression: IrExpression): Scoped { if (expression is IrGetValue) { val valueDeclaration = expression.symbol.owner if (valueDeclaration is IrValueParameter) @@ -712,8 +693,6 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag } is IrCall -> when (value.symbol) { - getContinuationSymbol -> continuationOverride ?: getContinuation().value - in arrayGetSymbols -> { val actualCallee = value.actualCallee @@ -760,12 +739,6 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag val callee = value.symbol.owner val arguments = value.getArguments() .map { expressionToEdge(it.second) } - .let { - if (callee.isSuspend) - it + DataFlowIR.Edge(continuationOverride ?: getContinuation().value, null) - else - it - } if (value.isVirtualCall) { val owner = callee.parentAsClass diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt index ee0f6056fda..4ba7e1a9f87 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt @@ -595,8 +595,8 @@ internal object DataFlowIR { } val name = "kfun:$containingDeclarationPart${it.computeFunctionName()}" - val returnsUnit = it is IrConstructor || (!it.isSuspend && it.returnType.isUnit()) - val returnsNothing = !it.isSuspend && it.returnType.isNothing() + val returnsUnit = it is IrConstructor || it.returnType.isUnit() + val returnsNothing = it.returnType.isNothing() var attributes = 0 if (returnsUnit) attributes = attributes or FunctionAttributes.RETURNS_UNIT @@ -648,14 +648,10 @@ internal object DataFlowIR { } functionMap[it] = symbol - symbol.parameters = - (function.allParameters.map { it.type } + (if (function.isSuspend) listOf(continuationType) else emptyList())) + symbol.parameters = function.allParameters.map { it.type } .map { mapTypeToFunctionParameter(it) } .toTypedArray() - symbol.returnParameter = mapTypeToFunctionParameter(if (function.isSuspend) - context.irBuiltIns.anyType - else - function.returnType) + symbol.returnParameter = mapTypeToFunctionParameter(function.returnType) return symbol } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DevirtualizationAnalysis.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DevirtualizationAnalysis.kt index a5744b22b97..96bef0db86c 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DevirtualizationAnalysis.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DevirtualizationAnalysis.kt @@ -1446,9 +1446,7 @@ internal object DevirtualizationAnalysis { val startOffset = expression.startOffset val endOffset = expression.endOffset val function = expression.symbol.owner - val type = if (callee.isSuspend) - context.irBuiltIns.anyNType - else function.returnType + val type = function.returnType val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset) irBuilder.run { val dispatchReceiver = expression.dispatchReceiver!!