[JS IR BE] Support 1.3 coroutines in backend

This commit is contained in:
Roman Artemev
2018-09-13 20:39:18 +03:00
committed by romanart
parent c0ef1311ba
commit affc827998
7 changed files with 174 additions and 100 deletions
@@ -64,7 +64,7 @@ class InitializersLowering(
val irFieldInitializer = declaration.initializer?.expression ?: return val irFieldInitializer = declaration.initializer?.expression ?: return
val receiver = val receiver =
if (declaration.descriptor.dispatchReceiverParameter != null) // TODO isStaticField if (!declaration.isStatic) // TODO isStaticField
IrGetValueImpl( IrGetValueImpl(
irFieldInitializer.startOffset, irFieldInitializer.endOffset, irFieldInitializer.startOffset, irFieldInitializer.endOffset,
irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol
@@ -79,7 +79,7 @@ class InitializersLowering(
null, null null, null
) )
if (DescriptorUtils.isStaticDeclaration(declaration.descriptor)) { if (declaration.isStatic) {
staticInitializerStatements.add(irSetField) staticInitializerStatements.add(irSetField)
} else { } else {
instanceInitializerStatements.add(irSetField) instanceInitializerStatements.add(irSetField)
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.backend.common.ir.Symbols import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.js.JsDeclarationFactory import org.jetbrains.kotlin.backend.js.JsDeclarationFactory
import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
@@ -44,23 +45,34 @@ class JsIrBackendContext(
val module: ModuleDescriptor, val module: ModuleDescriptor,
override val irBuiltIns: IrBuiltIns, override val irBuiltIns: IrBuiltIns,
val symbolTable: SymbolTable, val symbolTable: SymbolTable,
irModuleFragment: IrModuleFragment irModuleFragment: IrModuleFragment,
val configuration: CompilerConfiguration
) : CommonBackendContext { ) : CommonBackendContext {
override val builtIns = module.builtIns override val builtIns = module.builtIns
val internalPackageFragmentDescriptor = KnownPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.js.internal")) val internalPackageFragmentDescriptor = KnownPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.js.internal"))
val implicitDeclarationFile = IrFileImpl(object : SourceManager.FileEntry { private val implicitDeclarationFile by lazy {
override val name = "<implicitDeclarations>" IrFileImpl(object : SourceManager.FileEntry {
override val maxOffset = UNDEFINED_OFFSET override val name = "<implicitDeclarations>"
override val maxOffset = UNDEFINED_OFFSET
override fun getSourceRangeInfo(beginOffset: Int, endOffset: Int) = override fun getSourceRangeInfo(beginOffset: Int, endOffset: Int) =
SourceRangeInfo("", UNDEFINED_OFFSET, UNDEFINED_OFFSET, UNDEFINED_OFFSET, UNDEFINED_OFFSET, UNDEFINED_OFFSET, UNDEFINED_OFFSET) SourceRangeInfo(
"",
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
UNDEFINED_OFFSET
)
override fun getLineNumber(offset: Int) = UNDEFINED_OFFSET override fun getLineNumber(offset: Int) = UNDEFINED_OFFSET
override fun getColumnNumber(offset: Int) = UNDEFINED_OFFSET override fun getColumnNumber(offset: Int) = UNDEFINED_OFFSET
}, internalPackageFragmentDescriptor).also { }, internalPackageFragmentDescriptor).also {
irModuleFragment.files += it irModuleFragment.files += it
}
} }
override val sharedVariablesManager = override val sharedVariablesManager =
@@ -68,31 +80,36 @@ class JsIrBackendContext(
override val declarationFactory = JsDeclarationFactory() override val declarationFactory = JsDeclarationFactory()
override val reflectionTypes: ReflectionTypes by lazy(LazyThreadSafetyMode.PUBLICATION) { override val reflectionTypes: ReflectionTypes by lazy(LazyThreadSafetyMode.PUBLICATION) {
// TODO // TODO
ReflectionTypes(module, FqName("kotlin.reflect")) ReflectionTypes(module, REFLECT_PACKAGE_FQNAME)
} }
private val internalPackageName = FqName("kotlin.js") companion object {
private val internalPackage = module.getPackage(internalPackageName) private val INTRINSICS_PACKAGE_NAME = Name.identifier("intrinsics")
private val COROUTINE_SUSPENDED_NAME = Name.identifier("COROUTINE_SUSPENDED")
private val COROUTINE_CONTEXT_NAME = Name.identifier("coroutineContext")
private val COROUTINE_IMPL_NAME = Name.identifier("CoroutineImpl")
private val CONTINUATION_NAME = Name.identifier("Continuation")
// TODO: what is more clear way reference this getter?
private val CONTINUATION_CONTEXT_GETTER_NAME = Name.special("<get-context>")
private val CONTINUATION_CONTEXT_PROPERTY_NAME = Name.identifier("context")
// TODO: replace it with appropriate package name once we migrate to 1.3 coroutines private val REFLECT_PACKAGE_FQNAME = FqName.fromSegments(listOf("kotlin", "reflect"))
private val coroutinePackageNameSrting_12 = "kotlin.coroutines.experimental" private val JS_PACKAGE_FQNAME = FqName.fromSegments(listOf("kotlin", "js"))
private val coroutinePackageNameSrting_13 = "kotlin.coroutines" private val JS_INTERNAL_PACKAGE_FQNAME = JS_PACKAGE_FQNAME.child(Name.identifier("internal"))
private val COROUTINE_PACKAGE_FQNAME_12 = FqName.fromSegments(listOf("kotlin", "coroutines", "experimental"))
private val COROUTINE_PACKAGE_FQNAME_13 = FqName.fromSegments(listOf("kotlin", "coroutines"))
private val COROUTINE_PACKAGE_FQNAME = COROUTINE_PACKAGE_FQNAME_13
private val COROUTINE_INTRINSICS_PACKAGE_FQNAME = COROUTINE_PACKAGE_FQNAME.child(INTRINSICS_PACKAGE_NAME)
private val INTRINSICS_PACKAGE_NAME = Name.identifier("intrinsics") // TODO: due to name clash those weird suffix is required, remove it once `NameGenerator` is implemented
private val COROUTINE_SUSPENDED_NAME = Name.identifier("COROUTINE_SUSPENDED") private val COROUTINE_SUSPEND_OR_RETURN_JS_NAME = "suspendCoroutineUninterceptedOrReturnJS"
private val COROUTINE_CONTEXT_NAME = Name.identifier("coroutineContext") private val GET_COROUTINE_CONTEXT_NAME = "getCoroutineContext"
private val COROUTINE_IMPL_NAME = Name.identifier("CoroutineImpl") }
private val CONTINUATION_NAME = Name.identifier("Continuation")
// TODO: what is more clear way reference this getter? private val internalPackage = module.getPackage(JS_PACKAGE_FQNAME)
private val CONTINUATION_CONTEXT_GETTER_NAME = Name.special("<get-context>")
private val CONTINUATION_CONTEXT_PROPERTY_NAME = Name.identifier("context")
private val coroutinePackageName = FqName(coroutinePackageNameSrting_12) private val coroutinePackage = module.getPackage(COROUTINE_PACKAGE_FQNAME)
private val coroutineIntrinsicsPackageName = coroutinePackageName.child(INTRINSICS_PACKAGE_NAME) private val coroutineIntrinsicsPackage = module.getPackage(COROUTINE_INTRINSICS_PACKAGE_FQNAME)
private val coroutinePackage = module.getPackage(coroutinePackageName)
private val coroutineIntrinsicsPackage = module.getPackage(coroutineIntrinsicsPackageName)
val enumEntryToGetInstanceFunction = mutableMapOf<IrEnumEntrySymbol, IrSimpleFunctionSymbol>() val enumEntryToGetInstanceFunction = mutableMapOf<IrEnumEntrySymbol, IrSimpleFunctionSymbol>()
@@ -106,19 +123,24 @@ class JsIrBackendContext(
) )
val contextGetter = val contextGetter =
continuation.owner.declarations.filterIsInstance<IrFunction>().atMostOne { it.descriptor.name == CONTINUATION_CONTEXT_GETTER_NAME } continuation.owner.declarations.filterIsInstance<IrFunction>().atMostOne { it.descriptor.name == CONTINUATION_CONTEXT_GETTER_NAME }
?: continuation.owner.declarations.filterIsInstance<IrProperty>().atMostOne { it.descriptor.name == CONTINUATION_CONTEXT_PROPERTY_NAME }?.getter!! ?: continuation.owner.declarations.filterIsInstance<IrProperty>().atMostOne { it.descriptor.name == CONTINUATION_CONTEXT_PROPERTY_NAME }?.getter!!
return contextGetter.symbol return contextGetter.symbol
} }
val coroutineGetContextJs = symbolTable.referenceSimpleFunction(getInternalFunctions(GET_COROUTINE_CONTEXT_NAME).single())
val coroutineContextProperty: PropertyDescriptor val coroutineContextProperty: PropertyDescriptor
get() { get() {
val vars = internalPackage.memberScope.getContributedVariables( val vars = coroutinePackage.memberScope.getContributedVariables(
COROUTINE_CONTEXT_NAME, COROUTINE_CONTEXT_NAME,
NoLookupLocation.FROM_BACKEND NoLookupLocation.FROM_BACKEND
) )
return vars.single() return vars.single()
} }
val coroutineSuspendOrReturn =
symbolTable.referenceSimpleFunction(getInternalFunctions(COROUTINE_SUSPEND_OR_RETURN_JS_NAME).single())
val intrinsics = JsIntrinsics(irBuiltIns, this) val intrinsics = JsIntrinsics(irBuiltIns, this)
private val operatorMap = referenceOperators() private val operatorMap = referenceOperators()
@@ -130,14 +152,11 @@ class JsIrBackendContext(
} }
val primitiveCompanionObjects = PrimitiveType.NUMBER_TYPES val primitiveCompanionObjects = PrimitiveType.NUMBER_TYPES
.asSequence()
.filter { it.name != "LONG" && it.name != "CHAR" } // skip due to they have own explicit companions .filter { it.name != "LONG" && it.name != "CHAR" } // skip due to they have own explicit companions
.map { .map {
it.typeName to symbolTable.lazyWrapper.referenceClass( it.typeName to symbolTable.lazyWrapper.referenceClass(
getClass( getClass(JS_INTERNAL_PACKAGE_FQNAME.child(Name.identifier("${it.typeName.identifier}CompanionObject")))
internalPackageName
.child(Name.identifier("internal"))
.child(Name.identifier("${it.typeName.identifier}CompanionObject"))
)
) )
}.toMap() }.toMap()
@@ -186,16 +205,19 @@ class JsIrBackendContext(
get() = TODO("not implemented") get() = TODO("not implemented")
override val copyRangeTo: Map<ClassDescriptor, IrSimpleFunctionSymbol> override val copyRangeTo: Map<ClassDescriptor, IrSimpleFunctionSymbol>
get() = TODO("not implemented") get() = TODO("not implemented")
override val coroutineImpl = symbolTable.referenceClass(getInternalClass(COROUTINE_IMPL_NAME.identifier)) override val coroutineImpl = symbolTable.referenceClass(findClass(coroutinePackage.memberScope, COROUTINE_IMPL_NAME.identifier))
override val coroutineSuspendedGetter = symbolTable.referenceSimpleFunction( override val coroutineSuspendedGetter = symbolTable.referenceSimpleFunction(
coroutineIntrinsicsPackage.memberScope.getContributedVariables(COROUTINE_SUSPENDED_NAME, NoLookupLocation.FROM_BACKEND).filterNot { it.isExpect }.single().getter!! coroutineIntrinsicsPackage.memberScope.getContributedVariables(
COROUTINE_SUSPENDED_NAME,
NoLookupLocation.FROM_BACKEND
).filterNot { it.isExpect }.single().getter!!
) )
} }
override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true
} }
val coroutineImplLabelProperty by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("label")!! } val coroutineImplLabelProperty by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("state")!! }
val coroutineImplResultSymbol by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("result")!! } val coroutineImplResultSymbol by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("result")!! }
val coroutineImplExceptionProperty by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("exception")!! } val coroutineImplExceptionProperty by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("exception")!! }
val coroutineImplExceptionStateProperty by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("exceptionState")!! } val coroutineImplExceptionStateProperty by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("exceptionState")!! }
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.backend.js.lower.* import org.jetbrains.kotlin.ir.backend.js.lower.*
import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.CoroutineIntrinsicLowering
import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.SuspendFunctionsLowering import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.SuspendFunctionsLowering
import org.jetbrains.kotlin.ir.backend.js.lower.inline.FunctionInlining import org.jetbrains.kotlin.ir.backend.js.lower.inline.FunctionInlining
import org.jetbrains.kotlin.ir.backend.js.lower.inline.RemoveInlineFunctionsWithReifiedTypeParametersLowering import org.jetbrains.kotlin.ir.backend.js.lower.inline.RemoveInlineFunctionsWithReifiedTypeParametersLowering
@@ -55,7 +56,8 @@ fun compile(
analysisResult.moduleDescriptor, analysisResult.moduleDescriptor,
psi2IrContext.irBuiltIns, psi2IrContext.irBuiltIns,
psi2IrContext.symbolTable, psi2IrContext.symbolTable,
moduleFragment moduleFragment,
configuration
) )
ExternalDependenciesGenerator(psi2IrContext.moduleDescriptor, psi2IrContext.symbolTable, psi2IrContext.irBuiltIns) ExternalDependenciesGenerator(psi2IrContext.moduleDescriptor, psi2IrContext.symbolTable, psi2IrContext.irBuiltIns)
@@ -68,6 +70,8 @@ fun compile(
MoveExternalDeclarationsToSeparatePlace().lower(moduleFragment.files) MoveExternalDeclarationsToSeparatePlace().lower(moduleFragment.files)
moduleFragment.files.forEach(CoroutineIntrinsicLowering(context)::lower)
context.performInlining(moduleFragment) context.performInlining(moduleFragment)
context.lower(moduleFragment) context.lower(moduleFragment)
@@ -266,4 +266,57 @@ fun IrClass.simpleFunctions(): List<IrSimpleFunction> = this.declarations.flatMa
} }
} }
// TODO extract to common place?
fun irCall(
call: IrCall,
newSymbol: IrFunctionSymbol,
dispatchReceiverAsFirstArgument: Boolean = false,
firstArgumentAsDispatchReceiver: Boolean = false
): IrCall =
call.run {
IrCallImpl(
startOffset,
endOffset,
type,
newSymbol,
newSymbol.descriptor,
typeArgumentsCount,
origin
).apply {
copyTypeAndValueArgumentsFrom(
call,
dispatchReceiverAsFirstArgument,
firstArgumentAsDispatchReceiver
)
}
}
// TODO extract to common place?
private fun IrCall.copyTypeAndValueArgumentsFrom(
call: IrCall,
dispatchReceiverAsFirstArgument: Boolean = false,
firstArgumentAsDispatchReceiver: Boolean = false
) {
copyTypeArgumentsFrom(call)
var toValueArgumentIndex = 0
var fromValueArgumentIndex = 0
when {
dispatchReceiverAsFirstArgument -> {
putValueArgument(toValueArgumentIndex++, call.dispatchReceiver)
}
firstArgumentAsDispatchReceiver -> {
dispatchReceiver = call.getValueArgument(fromValueArgumentIndex++)
}
else -> {
dispatchReceiver = call.dispatchReceiver
}
}
extensionReceiver = call.extensionReceiver
while (fromValueArgumentIndex < call.valueArgumentsCount) {
putValueArgument(toValueArgumentIndex++, call.getValueArgument(fromValueArgumentIndex++))
}
}
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.utils.isSubtypeOfClass
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.ir.irCall
import org.jetbrains.kotlin.ir.backend.js.utils.ConversionNames import org.jetbrains.kotlin.ir.backend.js.utils.ConversionNames
import org.jetbrains.kotlin.ir.backend.js.utils.Namer import org.jetbrains.kotlin.ir.backend.js.utils.Namer
import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
@@ -649,68 +650,10 @@ fun translateEqualsForNullableString(rhs: IrType): EqualityLoweringType = when {
else -> RuntimeFunctionCall else -> RuntimeFunctionCall
} }
private fun IrType.isNullableJsNumber(): Boolean = isNullablePrimitiveType() && !isNullableLong() && !isNullableChar() private fun IrType.isNullableJsNumber(): Boolean = isNullablePrimitiveType() && !isNullableLong() && !isNullableChar()
private fun IrType.isJsNumber(): Boolean = isPrimitiveType() && !isLong() && !isChar() private fun IrType.isJsNumber(): Boolean = isPrimitiveType() && !isLong() && !isChar()
// TODO extract to common place?
fun irCall(
call: IrCall,
newSymbol: IrFunctionSymbol,
dispatchReceiverAsFirstArgument: Boolean = false,
firstArgumentAsDispatchReceiver: Boolean = false
): IrCall =
call.run {
IrCallImpl(
startOffset,
endOffset,
type,
newSymbol,
newSymbol.descriptor,
typeArgumentsCount,
origin
).apply {
copyTypeAndValueArgumentsFrom(
call,
dispatchReceiverAsFirstArgument,
firstArgumentAsDispatchReceiver
)
}
}
// TODO extract to common place?
private fun IrCall.copyTypeAndValueArgumentsFrom(
call: IrCall,
dispatchReceiverAsFirstArgument: Boolean = false,
firstArgumentAsDispatchReceiver: Boolean = false
) {
copyTypeArgumentsFrom(call)
var toValueArgumentIndex = 0
var fromValueArgumentIndex = 0
when {
dispatchReceiverAsFirstArgument -> {
putValueArgument(toValueArgumentIndex++, call.dispatchReceiver)
}
firstArgumentAsDispatchReceiver -> {
dispatchReceiver = call.getValueArgument(fromValueArgumentIndex++)
}
else -> {
dispatchReceiver = call.dispatchReceiver
}
}
extensionReceiver = call.extensionReceiver
while (fromValueArgumentIndex < call.valueArgumentsCount) {
putValueArgument(toValueArgumentIndex++, call.getValueArgument(fromValueArgumentIndex++))
}
}
private fun MemberToTransformer.op(type: IrType, name: Name, v: IrSimpleFunctionSymbol) { private fun MemberToTransformer.op(type: IrType, name: Name, v: IrSimpleFunctionSymbol) {
op(type, name, v = { irCall(it, v, dispatchReceiverAsFirstArgument = true) }) op(type, name, v = { irCall(it, v, dispatchReceiverAsFirstArgument = true) })
} }
@@ -0,0 +1,38 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.backend.js.lower.coroutines
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.isBuiltInIntercepted
import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineUninterceptedOrReturn
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.irCall
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
class CoroutineIntrinsicLowering(val context: JsIrBackendContext): FileLoweringPass {
private val languageVersion = context.configuration.languageVersionSettings
override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitCall(expression: IrCall): IrExpression {
val call = super.visitCall(expression)
return when {
expression.descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersion) ->
irCall(expression, context.coroutineSuspendOrReturn)
expression.descriptor.isBuiltInIntercepted(languageVersion) ->
error("Intercepted should not be used with release coroutines")
expression.symbol.owner == context.intrinsics.jsCoroutineContext.owner ->
irCall(expression, context.coroutineGetContextJs)
else -> call
}
}
})
}
}
@@ -148,7 +148,20 @@ class SimpleNameGenerator : NameGenerator {
if (declaration.kind == ClassKind.OBJECT || declaration.name.isSpecial || declaration.visibility == Visibilities.LOCAL) { if (declaration.kind == ClassKind.OBJECT || declaration.name.isSpecial || declaration.visibility == Visibilities.LOCAL) {
nameDeclarator = context.staticContext.rootScope::declareFreshName nameDeclarator = context.staticContext.rootScope::declareFreshName
val parent = declaration.parent
when (parent) {
is IrDeclaration -> nameBuilder.append(getNameForDeclaration(parent, context))
is IrPackageFragment -> nameBuilder.append(parent.fqName.asString())
}
} }
// TODO: remove asap `NameGenerator` is implemented
(declaration.parent as? IrPackageFragment)?.let {
if (declaration.isInline && it.fqName.asString() != "kotlin") {
nameBuilder.append("_FIX")
}
}
} }
is IrConstructor -> { is IrConstructor -> {
nameBuilder.append(getNameForDeclaration(declaration.parent as IrClass, context)) nameBuilder.append(getNameForDeclaration(declaration.parent as IrClass, context))
@@ -158,6 +171,7 @@ class SimpleNameGenerator : NameGenerator {
nameDeclarator = context.currentScope::declareFreshName nameDeclarator = context.currentScope::declareFreshName
} }
is IrSimpleFunction -> { is IrSimpleFunction -> {
nameBuilder.append(declaration.name.asString()) nameBuilder.append(declaration.name.asString())
declaration.extensionReceiverParameter?.let { nameBuilder.append("_\$${it.type.render()}") } declaration.extensionReceiverParameter?.let { nameBuilder.append("_\$${it.type.render()}") }
declaration.typeParameters.forEach { nameBuilder.append("_${it.name.asString()}") } declaration.typeParameters.forEach { nameBuilder.append("_${it.name.asString()}") }