[JS IR BE] Reorder phases in order to extract a common prefix
This commit is contained in:
+15
-13
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
|||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
||||||
import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat
|
import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat
|
||||||
import org.jetbrains.kotlin.ir.visitors.*
|
import org.jetbrains.kotlin.ir.visitors.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -42,25 +43,26 @@ class PropertiesLowering(
|
|||||||
override fun visitClass(declaration: IrClass): IrStatement {
|
override fun visitClass(declaration: IrClass): IrStatement {
|
||||||
declaration.transformChildrenVoid(this)
|
declaration.transformChildrenVoid(this)
|
||||||
declaration.transformDeclarationsFlat { lowerProperty(it, declaration.kind) }
|
declaration.transformDeclarationsFlat { lowerProperty(it, declaration.kind) }
|
||||||
declaration.declarations.removeAll { it is IrProperty }
|
|
||||||
return declaration
|
return declaration
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun lowerProperty(declaration: IrDeclaration, kind: ClassKind): List<IrDeclaration>? =
|
private fun lowerProperty(declaration: IrDeclaration, kind: ClassKind): List<IrDeclaration>? =
|
||||||
if (declaration is IrProperty)
|
if (declaration is IrProperty)
|
||||||
ArrayList<IrDeclaration>(4).apply {
|
if (declaration.isEffectivelyExternal()) listOf(declaration) else {
|
||||||
// JvmFields in a companion object refer to companion's owners and should not be generated within companion.
|
ArrayList<IrDeclaration>(4).apply {
|
||||||
if (kind != ClassKind.ANNOTATION_CLASS && declaration.backingField?.parent == declaration.parent) {
|
// JvmFields in a companion object refer to companion's owners and should not be generated within companion.
|
||||||
addIfNotNull(declaration.backingField)
|
if (kind != ClassKind.ANNOTATION_CLASS && declaration.backingField?.parent == declaration.parent) {
|
||||||
}
|
addIfNotNull(declaration.backingField)
|
||||||
addIfNotNull(declaration.getter)
|
}
|
||||||
addIfNotNull(declaration.setter)
|
addIfNotNull(declaration.getter)
|
||||||
|
addIfNotNull(declaration.setter)
|
||||||
|
|
||||||
if (declaration.annotations.isNotEmpty() && originOfSyntheticMethodForAnnotations != null
|
if (declaration.annotations.isNotEmpty() && originOfSyntheticMethodForAnnotations != null
|
||||||
&& computeSyntheticMethodName != null
|
&& computeSyntheticMethodName != null
|
||||||
) {
|
) {
|
||||||
val methodName = computeSyntheticMethodName.invoke(declaration.name) // Workaround KT-4113
|
val methodName = computeSyntheticMethodName.invoke(declaration.name) // Workaround KT-4113
|
||||||
add(createSyntheticMethodForAnnotations(declaration, originOfSyntheticMethodForAnnotations, methodName))
|
add(createSyntheticMethodForAnnotations(declaration, originOfSyntheticMethodForAnnotations, methodName))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -18,20 +18,24 @@ package org.jetbrains.kotlin.ir.util
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.atMostOne
|
import org.jetbrains.kotlin.backend.common.atMostOne
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
fun IrClassSymbol.getPropertyDeclaration(name: String) =
|
fun IrClassSymbol.getPropertyDeclaration(name: String) =
|
||||||
this.owner.declarations.filterIsInstance<IrProperty>()
|
this.owner.declarations.filterIsInstance<IrProperty>()
|
||||||
.atMostOne { it.descriptor.name == Name.identifier(name) }
|
.atMostOne { it.descriptor.name == Name.identifier(name) }
|
||||||
|
|
||||||
fun IrClassSymbol.getPropertyGetter(name: String): IrFunctionSymbol? =
|
fun IrClassSymbol.getSimpleFunction(name: String): IrSimpleFunctionSymbol? =
|
||||||
this.getPropertyDeclaration(name)?.getter?.symbol
|
owner.findDeclaration<IrSimpleFunction> { it.name.asString() == name }?.symbol
|
||||||
|
|
||||||
fun IrClassSymbol.getPropertySetter(name: String): IrFunctionSymbol? =
|
fun IrClassSymbol.getPropertyGetter(name: String): IrSimpleFunctionSymbol? =
|
||||||
this.getPropertyDeclaration(name)?.setter?.symbol
|
this.getPropertyDeclaration(name)?.getter?.symbol ?: this.getSimpleFunction("<get-$name>")
|
||||||
|
|
||||||
|
fun IrClassSymbol.getPropertySetter(name: String): IrSimpleFunctionSymbol? =
|
||||||
|
this.getPropertyDeclaration(name)?.setter?.symbol ?: this.getSimpleFunction("<set-$name>")
|
||||||
|
|
||||||
fun IrClassSymbol.getPropertyField(name: String): IrFieldSymbol? =
|
fun IrClassSymbol.getPropertyField(name: String): IrFieldSymbol? =
|
||||||
this.getPropertyDeclaration(name)?.backingField?.symbol
|
this.getPropertyDeclaration(name)?.backingField?.symbol
|
||||||
|
|||||||
@@ -31,9 +31,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
|
|||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
import org.jetbrains.kotlin.ir.types.impl.IrDynamicTypeImpl
|
import org.jetbrains.kotlin.ir.types.impl.IrDynamicTypeImpl
|
||||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.util.getPropertyDeclaration
|
|
||||||
import org.jetbrains.kotlin.ir.util.kotlinPackageFqn
|
|
||||||
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.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
@@ -257,10 +255,14 @@ class JsIrBackendContext(
|
|||||||
val throwNWBESymbol = ir.symbols.ThrowNoWhenBranchMatchedException
|
val throwNWBESymbol = ir.symbols.ThrowNoWhenBranchMatchedException
|
||||||
val throwUPAESymbol = ir.symbols.ThrowUninitializedPropertyAccessException
|
val throwUPAESymbol = ir.symbols.ThrowUninitializedPropertyAccessException
|
||||||
|
|
||||||
val coroutineImplLabelProperty by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("state")!! }
|
val coroutineImplLabelPropertyGetter by lazy { ir.symbols.coroutineImpl.getPropertyGetter("state")!!.owner }
|
||||||
val coroutineImplResultSymbol by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("result")!! }
|
val coroutineImplLabelPropertySetter by lazy { ir.symbols.coroutineImpl.getPropertySetter("state")!!.owner }
|
||||||
val coroutineImplExceptionProperty by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("exception")!! }
|
val coroutineImplResultSymbolGetter by lazy { ir.symbols.coroutineImpl.getPropertyGetter("result")!!.owner }
|
||||||
val coroutineImplExceptionStateProperty by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("exceptionState")!! }
|
val coroutineImplResultSymbolSetter by lazy { ir.symbols.coroutineImpl.getPropertySetter("result")!!.owner }
|
||||||
|
val coroutineImplExceptionPropertyGetter by lazy { ir.symbols.coroutineImpl.getPropertyGetter("exception")!!.owner }
|
||||||
|
val coroutineImplExceptionPropertySetter by lazy { ir.symbols.coroutineImpl.getPropertySetter("exception")!!.owner }
|
||||||
|
val coroutineImplExceptionStatePropertyGetter by lazy { ir.symbols.coroutineImpl.getPropertyGetter("exceptionState")!!.owner }
|
||||||
|
val coroutineImplExceptionStatePropertySetter by lazy { ir.symbols.coroutineImpl.getPropertySetter("exceptionState")!!.owner }
|
||||||
|
|
||||||
val primitiveClassProperties by lazy {
|
val primitiveClassProperties by lazy {
|
||||||
primitiveClassesObject.owner.declarations.filterIsInstance<IrProperty>()
|
primitiveClassesObject.owner.declarations.filterIsInstance<IrProperty>()
|
||||||
|
|||||||
@@ -81,18 +81,6 @@ private val expectDeclarationsRemovingPhase = makeJsModulePhase(
|
|||||||
description = "Remove expect declaration from module fragment"
|
description = "Remove expect declaration from module fragment"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val coroutineIntrinsicLoweringPhase = makeJsModulePhase(
|
|
||||||
::CoroutineIntrinsicLowering,
|
|
||||||
name = "CoroutineIntrinsicLowering",
|
|
||||||
description = "Replace common coroutine intrinsics with platform specific ones"
|
|
||||||
)
|
|
||||||
|
|
||||||
private val arrayInlineConstructorLoweringPhase = makeJsModulePhase(
|
|
||||||
::ArrayInlineConstructorLowering,
|
|
||||||
name = "ArrayInlineConstructorLowering",
|
|
||||||
description = "Replace array constructor with platform specific factory functions"
|
|
||||||
)
|
|
||||||
|
|
||||||
private val lateinitLoweringPhase = makeJsModulePhase(
|
private val lateinitLoweringPhase = makeJsModulePhase(
|
||||||
::LateinitLowering,
|
::LateinitLowering,
|
||||||
name = "LateinitLowering",
|
name = "LateinitLowering",
|
||||||
@@ -107,7 +95,7 @@ private val functionInliningPhase = makeCustomJsModulePhase(
|
|||||||
},
|
},
|
||||||
name = "FunctionInliningPhase",
|
name = "FunctionInliningPhase",
|
||||||
description = "Perform function inlining",
|
description = "Perform function inlining",
|
||||||
prerequisite = setOf(lateinitLoweringPhase, arrayInlineConstructorLoweringPhase, coroutineIntrinsicLoweringPhase)
|
prerequisite = setOf(expectDeclarationsRemovingPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val removeInlineFunctionsWithReifiedTypeParametersLoweringPhase = makeJsModulePhase(
|
private val removeInlineFunctionsWithReifiedTypeParametersLoweringPhase = makeJsModulePhase(
|
||||||
@@ -136,16 +124,24 @@ private val unitMaterializationLoweringPhase = makeJsModulePhase(
|
|||||||
prerequisite = setOf(tailrecLoweringPhase)
|
prerequisite = setOf(tailrecLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val enumClassConstructorLoweringPhase = makeJsModulePhase(
|
||||||
|
::EnumClassConstructorLowering,
|
||||||
|
name = "EnumClassConstructorLowering",
|
||||||
|
description = "Transform Enum Class into regular Class"
|
||||||
|
)
|
||||||
|
|
||||||
private val enumClassLoweringPhase = makeJsModulePhase(
|
private val enumClassLoweringPhase = makeJsModulePhase(
|
||||||
::EnumClassLowering,
|
::EnumClassLowering,
|
||||||
name = "EnumClassLowering",
|
name = "EnumClassLowering",
|
||||||
description = "Transform Enum Class into regular Class"
|
description = "Transform Enum Class into regular Class",
|
||||||
|
prerequisite = setOf(enumClassConstructorLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val enumUsageLoweringPhase = makeJsModulePhase(
|
private val enumUsageLoweringPhase = makeJsModulePhase(
|
||||||
::EnumUsageLowering,
|
::EnumUsageLowering,
|
||||||
name = "EnumUsageLowering",
|
name = "EnumUsageLowering",
|
||||||
description = "Replace enum access with invocation of corresponding function"
|
description = "Replace enum access with invocation of corresponding function",
|
||||||
|
prerequisite = setOf(enumClassLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val sharedVariablesLoweringPhase = makeJsModulePhase(
|
private val sharedVariablesLoweringPhase = makeJsModulePhase(
|
||||||
@@ -171,7 +167,7 @@ private val localDeclarationsLoweringPhase = makeJsModulePhase(
|
|||||||
::LocalDeclarationsLowering,
|
::LocalDeclarationsLowering,
|
||||||
name = "LocalDeclarationsLowering",
|
name = "LocalDeclarationsLowering",
|
||||||
description = "Move local declarations into nearest declaration container",
|
description = "Move local declarations into nearest declaration container",
|
||||||
prerequisite = setOf(sharedVariablesLoweringPhase)
|
prerequisite = setOf(sharedVariablesLoweringPhase, localDelegatedPropertiesLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val innerClassesLoweringPhase = makeJsModulePhase(
|
private val innerClassesLoweringPhase = makeJsModulePhase(
|
||||||
@@ -190,7 +186,7 @@ private val suspendFunctionsLoweringPhase = makeJsModulePhase(
|
|||||||
::SuspendFunctionsLowering,
|
::SuspendFunctionsLowering,
|
||||||
name = "SuspendFunctionsLowering",
|
name = "SuspendFunctionsLowering",
|
||||||
description = "Transform suspend functions into CoroutineImpl instance and build state machine",
|
description = "Transform suspend functions into CoroutineImpl instance and build state machine",
|
||||||
prerequisite = setOf(unitMaterializationLoweringPhase, coroutineIntrinsicLoweringPhase)
|
prerequisite = setOf(unitMaterializationLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val privateMembersLoweringPhase = makeJsModulePhase(
|
private val privateMembersLoweringPhase = makeJsModulePhase(
|
||||||
@@ -253,7 +249,7 @@ private val initializersLoweringPhase = makeCustomJsModulePhase(
|
|||||||
{ context, module -> InitializersLowering(context, JsLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, false).lower(module) },
|
{ context, module -> InitializersLowering(context, JsLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, false).lower(module) },
|
||||||
name = "InitializersLowering",
|
name = "InitializersLowering",
|
||||||
description = "Merge init block and field initializers into [primary] constructor",
|
description = "Merge init block and field initializers into [primary] constructor",
|
||||||
prerequisite = setOf(enumClassLoweringPhase)
|
prerequisite = setOf(enumClassConstructorLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val multipleCatchesLoweringPhase = makeJsModulePhase(
|
private val multipleCatchesLoweringPhase = makeJsModulePhase(
|
||||||
@@ -344,24 +340,24 @@ private val callsLoweringPhase = makeJsModulePhase(
|
|||||||
val jsPhases = namedIrModulePhase(
|
val jsPhases = namedIrModulePhase(
|
||||||
name = "IrModuleLowering",
|
name = "IrModuleLowering",
|
||||||
description = "IR module lowering",
|
description = "IR module lowering",
|
||||||
lower = moveBodilessDeclarationsToSeparatePlacePhase then
|
lower = expectDeclarationsRemovingPhase then
|
||||||
expectDeclarationsRemovingPhase then
|
|
||||||
coroutineIntrinsicLoweringPhase then
|
|
||||||
arrayInlineConstructorLoweringPhase then
|
|
||||||
lateinitLoweringPhase then
|
|
||||||
functionInliningPhase then
|
functionInliningPhase then
|
||||||
removeInlineFunctionsWithReifiedTypeParametersLoweringPhase then
|
lateinitLoweringPhase then
|
||||||
throwableSuccessorsLoweringPhase then
|
|
||||||
tailrecLoweringPhase then
|
tailrecLoweringPhase then
|
||||||
unitMaterializationLoweringPhase then
|
enumClassConstructorLoweringPhase then
|
||||||
enumClassLoweringPhase then
|
|
||||||
enumUsageLoweringPhase then
|
|
||||||
sharedVariablesLoweringPhase then
|
sharedVariablesLoweringPhase then
|
||||||
returnableBlockLoweringPhase then
|
|
||||||
localDelegatedPropertiesLoweringPhase then
|
localDelegatedPropertiesLoweringPhase then
|
||||||
localDeclarationsLoweringPhase then
|
localDeclarationsLoweringPhase then
|
||||||
innerClassesLoweringPhase then
|
innerClassesLoweringPhase then
|
||||||
innerClassConstructorCallsLoweringPhase then
|
innerClassConstructorCallsLoweringPhase then
|
||||||
|
propertiesLoweringPhase then
|
||||||
|
initializersLoweringPhase then
|
||||||
|
// Common prefix ends
|
||||||
|
moveBodilessDeclarationsToSeparatePlacePhase then
|
||||||
|
enumClassLoweringPhase then
|
||||||
|
enumUsageLoweringPhase then
|
||||||
|
returnableBlockLoweringPhase then
|
||||||
|
unitMaterializationLoweringPhase then
|
||||||
suspendFunctionsLoweringPhase then
|
suspendFunctionsLoweringPhase then
|
||||||
privateMembersLoweringPhase then
|
privateMembersLoweringPhase then
|
||||||
callableReferenceLoweringPhase then
|
callableReferenceLoweringPhase then
|
||||||
@@ -369,9 +365,9 @@ val jsPhases = namedIrModulePhase(
|
|||||||
defaultParameterInjectorPhase then
|
defaultParameterInjectorPhase then
|
||||||
defaultParameterCleanerPhase then
|
defaultParameterCleanerPhase then
|
||||||
jsDefaultCallbackGeneratorPhase then
|
jsDefaultCallbackGeneratorPhase then
|
||||||
|
removeInlineFunctionsWithReifiedTypeParametersLoweringPhase then
|
||||||
|
throwableSuccessorsLoweringPhase then
|
||||||
varargLoweringPhase then
|
varargLoweringPhase then
|
||||||
propertiesLoweringPhase then
|
|
||||||
initializersLoweringPhase then
|
|
||||||
multipleCatchesLoweringPhase then
|
multipleCatchesLoweringPhase then
|
||||||
bridgesConstructionPhase then
|
bridgesConstructionPhase then
|
||||||
typeOperatorLoweringPhase then
|
typeOperatorLoweringPhase then
|
||||||
|
|||||||
+3
-18
@@ -5,40 +5,25 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.lower
|
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
|
||||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.irCall
|
import org.jetbrains.kotlin.ir.util.irCall
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
|
||||||
|
|
||||||
// Replace array inline constructors with stdlib function invocations
|
// Replace array inline constructors with stdlib function invocations
|
||||||
// Should be performed before inliner
|
class ArrayConstructorTransformer(
|
||||||
class ArrayInlineConstructorLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
|
||||||
override fun lower(irFile: IrFile) {
|
|
||||||
irFile.transformChildrenVoid(ArrayConstructorTransformer(context))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ArrayConstructorTransformer(
|
|
||||||
val context: JsIrBackendContext
|
val context: JsIrBackendContext
|
||||||
) : IrElementTransformerVoid() {
|
) {
|
||||||
|
|
||||||
// Inline constructor for CharArray is implemented in runtime
|
// Inline constructor for CharArray is implemented in runtime
|
||||||
private val primitiveArrayInlineToSizeConstructorMap =
|
private val primitiveArrayInlineToSizeConstructorMap =
|
||||||
context.intrinsics.primitiveArrays.filter { it.value != PrimitiveType.CHAR }.keys.associate {
|
context.intrinsics.primitiveArrays.filter { it.value != PrimitiveType.CHAR }.keys.associate {
|
||||||
it.inlineConstructor to it.sizeConstructor
|
it.inlineConstructor to it.sizeConstructor
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
fun transformCall(expression: IrCall): IrCall {
|
||||||
expression.transformChildrenVoid(this)
|
|
||||||
|
|
||||||
if (expression.symbol == context.intrinsics.array.inlineConstructor) {
|
if (expression.symbol == context.intrinsics.array.inlineConstructor) {
|
||||||
return irCall(expression, context.intrinsics.jsArray)
|
return irCall(expression, context.intrinsics.jsArray)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+194
-152
@@ -85,15 +85,11 @@ class EnumUsageLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
|||||||
class EnumClassLowering(val context: JsIrBackendContext) : DeclarationContainerLoweringPass {
|
class EnumClassLowering(val context: JsIrBackendContext) : DeclarationContainerLoweringPass {
|
||||||
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
||||||
irDeclarationContainer.transformDeclarationsFlat { declaration ->
|
irDeclarationContainer.transformDeclarationsFlat { declaration ->
|
||||||
if (declaration is IrClass && declaration.isEnumClass) {
|
if (declaration is IrClass && declaration.isEnumClass &&
|
||||||
if (declaration.descriptor.isExpect) {
|
!declaration.descriptor.isExpect && !declaration.isEffectivelyExternal()
|
||||||
emptyList()
|
) {
|
||||||
} else {
|
EnumClassTransformer(context, declaration).transform()
|
||||||
EnumClassTransformer(context, declaration).transform()
|
} else null
|
||||||
}
|
|
||||||
} else {
|
|
||||||
listOf(declaration)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,12 +100,22 @@ private fun createEntryAccessorName(enumName: String, enumEntry: IrEnumEntry) =
|
|||||||
|
|
||||||
private fun IrEnumEntry.getType(irClass: IrClass) = (correspondingClass ?: irClass).defaultType
|
private fun IrEnumEntry.getType(irClass: IrClass) = (correspondingClass ?: irClass).defaultType
|
||||||
|
|
||||||
class EnumClassTransformer(val context: JsIrBackendContext, private val irClass: IrClass) {
|
class EnumClassConstructorLowering(val context: JsIrBackendContext) : DeclarationContainerLoweringPass {
|
||||||
|
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
||||||
|
irDeclarationContainer.transformDeclarationsFlat { declaration ->
|
||||||
|
if (declaration is IrClass && declaration.isEnumClass &&
|
||||||
|
!declaration.descriptor.isExpect && !declaration.isEffectivelyExternal()
|
||||||
|
) {
|
||||||
|
EnumClassConstructorTransformer(context, declaration).transform()
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EnumClassConstructorTransformer(val context: JsIrBackendContext, private val irClass: IrClass) {
|
||||||
private val builder = context.createIrBuilder(irClass.symbol)
|
private val builder = context.createIrBuilder(irClass.symbol)
|
||||||
private val enumEntries = irClass.declarations.filterIsInstance<IrEnumEntry>()
|
private val enumEntries = irClass.declarations.filterIsInstance<IrEnumEntry>()
|
||||||
private val loweredEnumConstructors = HashMap<IrConstructorSymbol, IrConstructor>()
|
private val loweredEnumConstructors = HashMap<IrConstructorSymbol, IrConstructor>()
|
||||||
private val enumName = irClass.name.identifier
|
|
||||||
private val throwISESymbol = context.throwISEymbol
|
|
||||||
|
|
||||||
fun transform(): List<IrDeclaration> {
|
fun transform(): List<IrDeclaration> {
|
||||||
// Make sure InstanceInitializer exists
|
// Make sure InstanceInitializer exists
|
||||||
@@ -124,35 +130,16 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
|
|||||||
// The first step creates a new `IrConstructor` with new `IrValueParameter`s so references to old `IrValueParameter`s must be replaced with new ones.
|
// The first step creates a new `IrConstructor` with new `IrValueParameter`s so references to old `IrValueParameter`s must be replaced with new ones.
|
||||||
fixReferencesToConstructorParameters()
|
fixReferencesToConstructorParameters()
|
||||||
|
|
||||||
// Create instance variable for each enum entry initialized with `null`
|
|
||||||
val entryInstances = createEnumEntryInstanceVariables()
|
|
||||||
|
|
||||||
// Lower `IrEnumConstructorCall`s inside of enum entry class constructors to corresponding `IrDelegatingConstructorCall`s.
|
// Lower `IrEnumConstructorCall`s inside of enum entry class constructors to corresponding `IrDelegatingConstructorCall`s.
|
||||||
// Add `name` and `ordinal` parameters.
|
// Add `name` and `ordinal` parameters.
|
||||||
lowerEnumEntryClassConstructors(entryInstances)
|
lowerEnumEntryClassConstructors()
|
||||||
|
|
||||||
// Lower `IrEnumConstructorCall`s to corresponding `IrCall`s.
|
// Lower `IrEnumConstructorCall`s to corresponding `IrCall`s.
|
||||||
// Add `name` and `ordinal` constant parameters only for calls to the "enum class" constructors ("enum entry class" constructors
|
// Add `name` and `ordinal` constant parameters only for calls to the "enum class" constructors ("enum entry class" constructors
|
||||||
// already delegate these parameters)
|
// already delegate these parameters)
|
||||||
lowerEnumEntryInitializerExpression()
|
lowerEnumEntryInitializerExpression()
|
||||||
|
|
||||||
// Create boolean flag that indicates if entry instances were initialized.
|
return listOf(irClass)
|
||||||
val entryInstancesInitializedVar = createEntryInstancesInitializedVar()
|
|
||||||
|
|
||||||
// Create function that initializes all enum entry instances using `IrEnumEntry.initializationExpression`.
|
|
||||||
// It should be called on the first `IrGetEnumValue`, consecutive calls to this function will do nothing.
|
|
||||||
val initEntryInstancesFun = createInitEntryInstancesFun(entryInstancesInitializedVar, entryInstances)
|
|
||||||
|
|
||||||
// Create entry instance getters. These are used to lower `IrGetEnumValue`.
|
|
||||||
val entryGetInstanceFuns = createGetEntryInstanceFuns(initEntryInstancesFun, entryInstances)
|
|
||||||
|
|
||||||
// Create body for `values` and `valueOf` functions
|
|
||||||
lowerSyntheticFunctions()
|
|
||||||
|
|
||||||
// Remove IrEnumEntry nodes from class declarations. Replace them with corresponding class declarations (if they have them).
|
|
||||||
replaceIrEntriesWithCorrespondingClasses()
|
|
||||||
|
|
||||||
return listOf(irClass) + entryInstances + listOf(entryInstancesInitializedVar, initEntryInstancesFun) + entryGetInstanceFuns
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun insertInstanceInitializer() {
|
private fun insertInstanceInitializer() {
|
||||||
@@ -182,6 +169,82 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun lowerEnumConstructorsSignature() {
|
||||||
|
irClass.declarations.transform { declaration ->
|
||||||
|
if (declaration is IrConstructor) {
|
||||||
|
transformEnumConstructor(declaration, irClass)
|
||||||
|
} else
|
||||||
|
declaration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun transformEnumConstructor(enumConstructor: IrConstructor, enumClass: IrClass): IrConstructor {
|
||||||
|
val loweredConstructorDescriptor = WrappedClassConstructorDescriptor()
|
||||||
|
val loweredConstructorSymbol = IrConstructorSymbolImpl(loweredConstructorDescriptor)
|
||||||
|
|
||||||
|
return IrConstructorImpl(
|
||||||
|
enumConstructor.startOffset,
|
||||||
|
enumConstructor.endOffset,
|
||||||
|
enumConstructor.origin,
|
||||||
|
loweredConstructorSymbol,
|
||||||
|
enumConstructor.name,
|
||||||
|
enumConstructor.visibility,
|
||||||
|
enumConstructor.returnType,
|
||||||
|
enumConstructor.isInline,
|
||||||
|
enumConstructor.isExternal,
|
||||||
|
enumConstructor.isPrimary
|
||||||
|
).apply {
|
||||||
|
loweredConstructorDescriptor.bind(this)
|
||||||
|
parent = enumClass
|
||||||
|
valueParameters += JsIrBuilder.buildValueParameter("name", 0, context.irBuiltIns.stringType).also { it.parent = this }
|
||||||
|
valueParameters += JsIrBuilder.buildValueParameter("ordinal", 1, context.irBuiltIns.intType).also { it.parent = this }
|
||||||
|
copyParameterDeclarationsFrom(enumConstructor)
|
||||||
|
body = enumConstructor.body
|
||||||
|
loweredEnumConstructors[enumConstructor.symbol] = this
|
||||||
|
|
||||||
|
this.acceptVoid(PatchDeclarationParentsVisitor(enumClass))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun lowerEnumConstructorsBody() {
|
||||||
|
irClass.declarations.filterIsInstance<IrConstructor>().forEach {
|
||||||
|
IrEnumClassConstructorTransformer(it).transformBody()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class IrEnumClassConstructorTransformer(val constructor: IrConstructor) : IrElementTransformerVoid() {
|
||||||
|
val builder = context.createIrBuilder(constructor.symbol)
|
||||||
|
|
||||||
|
fun transformBody() {
|
||||||
|
constructor.body?.transformChildrenVoid(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall) =
|
||||||
|
builder.irDelegatingConstructorCall(expression.symbol.owner).apply {
|
||||||
|
for (i in 0..1) {
|
||||||
|
putValueArgument(i, builder.irGet(constructor.valueParameters[i]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
||||||
|
var delegatingConstructor = expression.symbol.owner
|
||||||
|
val constructorWasTransformed = delegatingConstructor.symbol in loweredEnumConstructors
|
||||||
|
|
||||||
|
if (constructorWasTransformed)
|
||||||
|
delegatingConstructor = loweredEnumConstructors[delegatingConstructor.symbol]!!
|
||||||
|
|
||||||
|
return builder.irDelegatingConstructorCall(delegatingConstructor).apply {
|
||||||
|
var valueArgIdx = 0
|
||||||
|
for (i in 0..1) {
|
||||||
|
putValueArgument(valueArgIdx++, builder.irGet(constructor.valueParameters[i]))
|
||||||
|
}
|
||||||
|
for (i in 0 until expression.valueArgumentsCount) {
|
||||||
|
putValueArgument(valueArgIdx++, expression.getValueArgument(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun fixReferencesToConstructorParameters() {
|
private fun fixReferencesToConstructorParameters() {
|
||||||
val fromOldToNewParameter = mutableMapOf<IrValueParameterSymbol, IrValueParameter>()
|
val fromOldToNewParameter = mutableMapOf<IrValueParameterSymbol, IrValueParameter>()
|
||||||
|
|
||||||
@@ -205,6 +268,92 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun lowerEnumEntryClassConstructors() {
|
||||||
|
for (entry in enumEntries) {
|
||||||
|
entry.correspondingClass?.constructors?.forEach {
|
||||||
|
it.transformChildrenVoid(IrEnumEntryClassConstructorTransformer(entry, true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class IrEnumEntryClassConstructorTransformer(val entry: IrEnumEntry, val isInsideConstructor: Boolean) :
|
||||||
|
IrElementTransformerVoid() {
|
||||||
|
|
||||||
|
private fun buildConstructorCall(constructor: IrConstructor) =
|
||||||
|
if (isInsideConstructor)
|
||||||
|
builder.irDelegatingConstructorCall(constructor)
|
||||||
|
else
|
||||||
|
builder.irCall(constructor)
|
||||||
|
|
||||||
|
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression {
|
||||||
|
var constructor = expression.symbol.owner
|
||||||
|
val constructorWasTransformed = constructor.symbol in loweredEnumConstructors
|
||||||
|
|
||||||
|
// Enum entry class constructors are not transformed
|
||||||
|
if (constructorWasTransformed)
|
||||||
|
constructor = loweredEnumConstructors[constructor.symbol]!!
|
||||||
|
|
||||||
|
return buildConstructorCall(constructor).apply {
|
||||||
|
var valueArgIdx = 0
|
||||||
|
|
||||||
|
// Enum entry class constructors already delegate name and ordinal parameters in their body
|
||||||
|
if (constructorWasTransformed) {
|
||||||
|
putValueArgument(valueArgIdx++, entry.getNameExpression())
|
||||||
|
putValueArgument(valueArgIdx++, entry.getOrdinalExpression())
|
||||||
|
}
|
||||||
|
for (i in 0 until expression.valueArgumentsCount) {
|
||||||
|
putValueArgument(valueArgIdx++, expression.getValueArgument(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun lowerEnumEntryInitializerExpression() {
|
||||||
|
for (entry in enumEntries) {
|
||||||
|
entry.initializerExpression =
|
||||||
|
entry.initializerExpression?.transform(IrEnumEntryClassConstructorTransformer(entry, false), null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrEnumEntry.getNameExpression() = builder.irString(this.name.identifier)
|
||||||
|
private fun IrEnumEntry.getOrdinalExpression() = builder.irInt(enumEntries.indexOf(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class EnumClassTransformer(val context: JsIrBackendContext, private val irClass: IrClass) {
|
||||||
|
private val builder = context.createIrBuilder(irClass.symbol)
|
||||||
|
private val enumEntries = irClass.declarations.filterIsInstance<IrEnumEntry>()
|
||||||
|
private val enumName = irClass.name.identifier
|
||||||
|
private val throwISESymbol = context.throwISEymbol
|
||||||
|
|
||||||
|
fun transform(): List<IrDeclaration> {
|
||||||
|
|
||||||
|
// Create instance variable for each enum entry initialized with `null`
|
||||||
|
val entryInstances = createEnumEntryInstanceVariables()
|
||||||
|
|
||||||
|
// Create boolean flag that indicates if entry instances were initialized.
|
||||||
|
val entryInstancesInitializedVar = createEntryInstancesInitializedVar()
|
||||||
|
|
||||||
|
// Create function that initializes all enum entry instances using `IrEnumEntry.initializationExpression`.
|
||||||
|
// It should be called on the first `IrGetEnumValue`, consecutive calls to this function will do nothing.
|
||||||
|
val initEntryInstancesFun = createInitEntryInstancesFun(entryInstancesInitializedVar, entryInstances)
|
||||||
|
|
||||||
|
// Create entry instance getters. These are used to lower `IrGetEnumValue`.
|
||||||
|
val entryGetInstanceFuns = createGetEntryInstanceFuns(initEntryInstancesFun, entryInstances)
|
||||||
|
|
||||||
|
// Create body for `values` and `valueOf` functions
|
||||||
|
lowerSyntheticFunctions()
|
||||||
|
|
||||||
|
// Remove IrEnumEntry nodes from class declarations. Replace them with corresponding class declarations (if they have them).
|
||||||
|
replaceIrEntriesWithCorrespondingClasses()
|
||||||
|
|
||||||
|
return listOf(irClass) + entryInstances + listOf(entryInstancesInitializedVar, initEntryInstancesFun) + entryGetInstanceFuns
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun createEnumValueOfBody(): IrBody {
|
private fun createEnumValueOfBody(): IrBody {
|
||||||
val valueOfFun = findFunctionDescriptorForMemberWithSyntheticBodyKind(IrSyntheticBodyKind.ENUM_VALUEOF)
|
val valueOfFun = findFunctionDescriptorForMemberWithSyntheticBodyKind(IrSyntheticBodyKind.ENUM_VALUEOF)
|
||||||
val nameParameter = valueOfFun.valueParameters[0]
|
val nameParameter = valueOfFun.valueParameters[0]
|
||||||
@@ -249,25 +398,9 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun lowerEnumConstructorsSignature() {
|
|
||||||
irClass.declarations.transform { declaration ->
|
|
||||||
if (declaration is IrConstructor) {
|
|
||||||
transformEnumConstructor(declaration, irClass)
|
|
||||||
} else
|
|
||||||
declaration
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun lowerEnumConstructorsBody() {
|
|
||||||
irClass.declarations.filterIsInstance<IrConstructor>().forEach {
|
|
||||||
IrEnumClassConstructorTransformer(it).transformBody()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun lowerEnumEntryClassConstructors(entryInstances: List<IrVariable>) {
|
private fun lowerEnumEntryClassConstructors(entryInstances: List<IrVariable>) {
|
||||||
for ((entry, instance) in enumEntries.zip(entryInstances)) {
|
for ((entry, instance) in enumEntries.zip(entryInstances)) {
|
||||||
entry.correspondingClass?.constructors?.forEach {
|
entry.correspondingClass?.constructors?.forEach {
|
||||||
it.transformChildrenVoid(IrEnumEntryClassConstructorTransformer(entry, true))
|
|
||||||
|
|
||||||
// Initialize entry instance at the beginning of constructor so it can be used inside constructor body
|
// Initialize entry instance at the beginning of constructor so it can be used inside constructor body
|
||||||
(it.body as? IrBlockBody)?.apply {
|
(it.body as? IrBlockBody)?.apply {
|
||||||
@@ -279,19 +412,23 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun lowerEnumEntryInitializerExpression() {
|
|
||||||
for (entry in enumEntries) {
|
|
||||||
entry.initializerExpression =
|
|
||||||
entry.initializerExpression?.transform(IrEnumEntryClassConstructorTransformer(entry, false), null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createEnumEntryInstanceVariables() = enumEntries.map { enumEntry ->
|
private fun createEnumEntryInstanceVariables() = enumEntries.map { enumEntry ->
|
||||||
val type = enumEntry.getType(irClass).makeNullable(false)
|
val type = enumEntry.getType(irClass).makeNullable(false)
|
||||||
val name = "${enumName}_${enumEntry.name.identifier}_instance"
|
val name = "${enumName}_${enumEntry.name.identifier}_instance"
|
||||||
builder.run {
|
val result = builder.run {
|
||||||
scope.createTmpVariable(irImplicitCast(irNull(), type), name)
|
scope.createTmpVariable(irImplicitCast(irNull(), type), name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enumEntry.correspondingClass?.constructors?.forEach {
|
||||||
|
// Initialize entry instance at the beginning of constructor so it can be used inside constructor body
|
||||||
|
(it.body as? IrBlockBody)?.apply {
|
||||||
|
statements.add(0, context.createIrBuilder(it.symbol).run {
|
||||||
|
irSetVar(result.symbol, irGet(enumEntry.correspondingClass!!.thisReceiver!!))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun replaceIrEntriesWithCorrespondingClasses() {
|
private fun replaceIrEntriesWithCorrespondingClasses() {
|
||||||
@@ -346,98 +483,6 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class IrEnumClassConstructorTransformer(val constructor: IrConstructor) : IrElementTransformerVoid() {
|
|
||||||
val builder = context.createIrBuilder(constructor.symbol)
|
|
||||||
|
|
||||||
fun transformBody() {
|
|
||||||
constructor.body?.transformChildrenVoid(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall) =
|
|
||||||
builder.irDelegatingConstructorCall(expression.symbol.owner).apply {
|
|
||||||
for (i in 0..1) {
|
|
||||||
putValueArgument(i, builder.irGet(constructor.valueParameters[i]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
|
||||||
var delegatingConstructor = expression.symbol.owner
|
|
||||||
val constructorWasTransformed = delegatingConstructor.symbol in loweredEnumConstructors
|
|
||||||
|
|
||||||
if (constructorWasTransformed)
|
|
||||||
delegatingConstructor = loweredEnumConstructors[delegatingConstructor.symbol]!!
|
|
||||||
|
|
||||||
return builder.irDelegatingConstructorCall(delegatingConstructor).apply {
|
|
||||||
var valueArgIdx = 0
|
|
||||||
for (i in 0..1) {
|
|
||||||
putValueArgument(valueArgIdx++, builder.irGet(constructor.valueParameters[i]))
|
|
||||||
}
|
|
||||||
for (i in 0 until expression.valueArgumentsCount) {
|
|
||||||
putValueArgument(valueArgIdx++, expression.getValueArgument(i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private inner class IrEnumEntryClassConstructorTransformer(val entry: IrEnumEntry, val isInsideConstructor: Boolean) :
|
|
||||||
IrElementTransformerVoid() {
|
|
||||||
|
|
||||||
private fun buildConstructorCall(constructor: IrConstructor) =
|
|
||||||
if (isInsideConstructor)
|
|
||||||
builder.irDelegatingConstructorCall(constructor)
|
|
||||||
else
|
|
||||||
builder.irCall(constructor)
|
|
||||||
|
|
||||||
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression {
|
|
||||||
var constructor = expression.symbol.owner
|
|
||||||
val constructorWasTransformed = constructor.symbol in loweredEnumConstructors
|
|
||||||
|
|
||||||
// Enum entry class constructors are not transformed
|
|
||||||
if (constructorWasTransformed)
|
|
||||||
constructor = loweredEnumConstructors[constructor.symbol]!!
|
|
||||||
|
|
||||||
return buildConstructorCall(constructor).apply {
|
|
||||||
var valueArgIdx = 0
|
|
||||||
|
|
||||||
// Enum entry class constructors already delegate name and ordinal parameters in their body
|
|
||||||
if (constructorWasTransformed) {
|
|
||||||
putValueArgument(valueArgIdx++, entry.getNameExpression())
|
|
||||||
putValueArgument(valueArgIdx++, entry.getOrdinalExpression())
|
|
||||||
}
|
|
||||||
for (i in 0 until expression.valueArgumentsCount) {
|
|
||||||
putValueArgument(valueArgIdx++, expression.getValueArgument(i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun transformEnumConstructor(enumConstructor: IrConstructor, enumClass: IrClass): IrConstructor {
|
|
||||||
val loweredConstructorDescriptor = WrappedClassConstructorDescriptor()
|
|
||||||
val loweredConstructorSymbol = IrConstructorSymbolImpl(loweredConstructorDescriptor)
|
|
||||||
|
|
||||||
return IrConstructorImpl(
|
|
||||||
enumConstructor.startOffset,
|
|
||||||
enumConstructor.endOffset,
|
|
||||||
enumConstructor.origin,
|
|
||||||
loweredConstructorSymbol,
|
|
||||||
enumConstructor.name,
|
|
||||||
enumConstructor.visibility,
|
|
||||||
enumConstructor.returnType,
|
|
||||||
enumConstructor.isInline,
|
|
||||||
enumConstructor.isExternal,
|
|
||||||
enumConstructor.isPrimary
|
|
||||||
).apply {
|
|
||||||
loweredConstructorDescriptor.bind(this)
|
|
||||||
parent = enumClass
|
|
||||||
valueParameters += JsIrBuilder.buildValueParameter("name", 0, context.irBuiltIns.stringType).also { it.parent = this }
|
|
||||||
valueParameters += JsIrBuilder.buildValueParameter("ordinal", 1, context.irBuiltIns.intType).also { it.parent = this }
|
|
||||||
copyParameterDeclarationsFrom(enumConstructor)
|
|
||||||
body = enumConstructor.body
|
|
||||||
loweredEnumConstructors[enumConstructor.symbol] = this
|
|
||||||
|
|
||||||
this.acceptVoid(PatchDeclarationParentsVisitor(enumClass))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findFunctionDescriptorForMemberWithSyntheticBodyKind(kind: IrSyntheticBodyKind): IrFunction =
|
private fun findFunctionDescriptorForMemberWithSyntheticBodyKind(kind: IrSyntheticBodyKind): IrFunction =
|
||||||
irClass.declarations.asSequence().filterIsInstance<IrFunction>()
|
irClass.declarations.asSequence().filterIsInstance<IrFunction>()
|
||||||
@@ -459,7 +504,4 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
|
|||||||
) = JsIrBuilder.buildFunction(name, returnType, irClass).also {
|
) = JsIrBuilder.buildFunction(name, returnType, irClass).also {
|
||||||
it.body = context.createIrBuilder(it.symbol).irBlockBody(it, bodyBuilder)
|
it.body = context.createIrBuilder(it.symbol).irBlockBody(it, bodyBuilder)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrEnumEntry.getNameExpression() = builder.irString(this.name.identifier)
|
|
||||||
private fun IrEnumEntry.getOrdinalExpression() = builder.irInt(enumEntries.indexOf(this))
|
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-5
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.ir.types.makeNullable
|
|||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
import org.jetbrains.kotlin.ir.util.isThrowable
|
import org.jetbrains.kotlin.ir.util.isThrowable
|
||||||
import org.jetbrains.kotlin.ir.util.isThrowableTypeOrSubtype
|
import org.jetbrains.kotlin.ir.util.isThrowableTypeOrSubtype
|
||||||
|
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||||
import org.jetbrains.kotlin.ir.visitors.*
|
import org.jetbrains.kotlin.ir.visitors.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
@@ -147,12 +148,25 @@ class ThrowableSuccessorsLowering(val context: JsIrBackendContext) : FileLowerin
|
|||||||
if (isDirectChildOfThrowable(declaration)) {
|
if (isDirectChildOfThrowable(declaration)) {
|
||||||
val messageField = createBackingField(declaration, messagePropertyName, stringType)
|
val messageField = createBackingField(declaration, messagePropertyName, stringType)
|
||||||
val causeField = createBackingField(declaration, causePropertyName, throwableType)
|
val causeField = createBackingField(declaration, causePropertyName, throwableType)
|
||||||
|
|
||||||
val existedMessageAccessor = ownPropertyAccessor(declaration, messageGetter)
|
val existedMessageAccessor = ownPropertyAccessor(declaration, messageGetter)
|
||||||
if (existedMessageAccessor.origin == IrDeclarationOrigin.FAKE_OVERRIDE)
|
val newMessageAccessor = if (existedMessageAccessor.origin == IrDeclarationOrigin.FAKE_OVERRIDE) {
|
||||||
createPropertyAccessor(existedMessageAccessor, messageField)
|
createPropertyAccessor(existedMessageAccessor, messageField)
|
||||||
|
} else existedMessageAccessor
|
||||||
|
|
||||||
val existedCauseAccessor = ownPropertyAccessor(declaration, causeGetter)
|
val existedCauseAccessor = ownPropertyAccessor(declaration, causeGetter)
|
||||||
if (existedCauseAccessor.origin == IrDeclarationOrigin.FAKE_OVERRIDE)
|
val newCauseAccessor = if (existedCauseAccessor.origin == IrDeclarationOrigin.FAKE_OVERRIDE) {
|
||||||
createPropertyAccessor(existedCauseAccessor, causeField)
|
createPropertyAccessor(existedCauseAccessor, causeField)
|
||||||
|
} else existedCauseAccessor
|
||||||
|
|
||||||
|
|
||||||
|
declaration.declarations.transformFlat {
|
||||||
|
when (it) {
|
||||||
|
existedMessageAccessor -> listOf(newMessageAccessor)
|
||||||
|
existedCauseAccessor -> listOf(newCauseAccessor)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pendingSuperUsages += DirectThrowableSuccessors(declaration, messageField, causeField)
|
pendingSuperUsages += DirectThrowableSuccessors(declaration, messageField, causeField)
|
||||||
}
|
}
|
||||||
@@ -181,7 +195,7 @@ class ThrowableSuccessorsLowering(val context: JsIrBackendContext) : FileLowerin
|
|||||||
return fieldDeclaration
|
return fieldDeclaration
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createPropertyAccessor(fakeAccessor: IrSimpleFunction, field: IrField) {
|
private fun createPropertyAccessor(fakeAccessor: IrSimpleFunction, field: IrField): IrSimpleFunction {
|
||||||
val name = fakeAccessor.name
|
val name = fakeAccessor.name
|
||||||
val function = JsIrBuilder.buildFunction(name, fakeAccessor.returnType, fakeAccessor.parent).apply {
|
val function = JsIrBuilder.buildFunction(name, fakeAccessor.returnType, fakeAccessor.parent).apply {
|
||||||
overriddenSymbols += fakeAccessor.overriddenSymbols
|
overriddenSymbols += fakeAccessor.overriddenSymbols
|
||||||
@@ -194,7 +208,7 @@ class ThrowableSuccessorsLowering(val context: JsIrBackendContext) : FileLowerin
|
|||||||
val returnStatement = JsIrBuilder.buildReturn(function.symbol, returnValue, nothingType)
|
val returnStatement = JsIrBuilder.buildReturn(function.symbol, returnValue, nothingType)
|
||||||
function.body = JsIrBuilder.buildBlockBody(listOf(returnStatement))
|
function.body = JsIrBuilder.buildBlockBody(listOf(returnStatement))
|
||||||
|
|
||||||
fakeAccessor.correspondingProperty?.getter = function
|
return function
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,7 +329,8 @@ class ThrowableSuccessorsLowering(val context: JsIrBackendContext) : FileLowerin
|
|||||||
private fun isDirectChildOfThrowable(irClass: IrClass) = irClass.superTypes.any { it.isThrowable() }
|
private fun isDirectChildOfThrowable(irClass: IrClass) = irClass.superTypes.any { it.isThrowable() }
|
||||||
private fun ownPropertyAccessor(irClass: IrClass, irBase: IrFunctionSymbol) =
|
private fun ownPropertyAccessor(irClass: IrClass, irBase: IrFunctionSymbol) =
|
||||||
irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }
|
irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }
|
||||||
.single { it.overriddenSymbols.any { s -> s == irBase } }
|
.singleOrNull { it.overriddenSymbols.any { s -> s == irBase } }
|
||||||
|
?: irClass.declarations.filterIsInstance<IrSimpleFunction>().single { it.overriddenSymbols.any { s -> s == irBase } }
|
||||||
|
|
||||||
inner class ThrowablePropertiesUsageTransformer : IrElementTransformerVoid() {
|
inner class ThrowablePropertiesUsageTransformer : IrElementTransformerVoid() {
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
|
|||||||
+2
-1
@@ -244,7 +244,8 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
|||||||
}
|
}
|
||||||
val typeParameter = typeParameterSymbol.owner
|
val typeParameter = typeParameterSymbol.owner
|
||||||
|
|
||||||
assert(!typeParameter.isReified) { "reified parameters have to be lowered before" }
|
// TODO either remove functions with reified type parameters or support this case
|
||||||
|
// assert(!typeParameter.isReified) { "reified parameters have to be lowered before" }
|
||||||
return typeParameter.superTypes.fold(litTrue) { r, t ->
|
return typeParameter.superTypes.fold(litTrue) { r, t ->
|
||||||
val check = generateTypeCheckNonNull(argument.copy(), t.makeNotNull(false))
|
val check = generateTypeCheckNonNull(argument.copy(), t.makeNotNull(false))
|
||||||
calculator.and(r, check)
|
calculator.and(r, check)
|
||||||
|
|||||||
+8
-8
@@ -7,12 +7,12 @@ package org.jetbrains.kotlin.ir.backend.js.lower.calls
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
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.IrProperty
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.util.getSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
||||||
|
|
||||||
class PrimitiveContainerMemberCallTransformer(private val context: JsIrBackendContext) : CallsTransformer {
|
class PrimitiveContainerMemberCallTransformer(private val context: JsIrBackendContext) : CallsTransformer {
|
||||||
private val intrinsics = context.intrinsics
|
private val intrinsics = context.intrinsics
|
||||||
@@ -65,22 +65,22 @@ class PrimitiveContainerMemberCallTransformer(private val context: JsIrBackendCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val IrClassSymbol.sizeProperty
|
private val IrClassSymbol.sizeProperty
|
||||||
get() = owner.declarations.filterIsInstance<IrProperty>().first { it.name.asString() == "size" }.getter!!.symbol
|
get() = getPropertyGetter("size")!!
|
||||||
|
|
||||||
private val IrClassSymbol.getFunction
|
private val IrClassSymbol.getFunction
|
||||||
get() = owner.declarations.filterIsInstance<IrFunction>().first { it.name.asString() == "get" }.symbol
|
get() = getSimpleFunction("get")!!
|
||||||
|
|
||||||
private val IrClassSymbol.setFunction
|
private val IrClassSymbol.setFunction
|
||||||
get() = owner.declarations.filterIsInstance<IrFunction>().first { it.name.asString() == "set" }.symbol
|
get() = getSimpleFunction("set")!!
|
||||||
|
|
||||||
private val IrClassSymbol.iterator
|
private val IrClassSymbol.iterator
|
||||||
get() = owner.declarations.filterIsInstance<IrFunction>().first { it.name.asString() == "iterator" }.symbol
|
get() = getSimpleFunction("iterator")!!
|
||||||
|
|
||||||
private val IrClassSymbol.sizeConstructor
|
private val IrClassSymbol.sizeConstructor
|
||||||
get() = owner.declarations.filterIsInstance<IrConstructor>().first { it.valueParameters.size == 1 }.symbol
|
get() = owner.declarations.filterIsInstance<IrConstructor>().first { it.valueParameters.size == 1 }.symbol
|
||||||
|
|
||||||
private val IrClassSymbol.lengthProperty
|
private val IrClassSymbol.lengthProperty
|
||||||
get() = owner.declarations.filterIsInstance<IrProperty>().first { it.name.asString() == "length" }.getter!!.symbol
|
get() = getPropertyGetter("length")!!
|
||||||
|
|
||||||
private val IrClassSymbol.subSequence
|
private val IrClassSymbol.subSequence
|
||||||
get() = owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "subSequence" }.symbol
|
get() = getSimpleFunction("subSequence")!!
|
||||||
|
|||||||
+15
-12
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
|||||||
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.declarations.IrProperty
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
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.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
@@ -64,9 +65,11 @@ class StateMachineBuilder(
|
|||||||
val context: JsIrBackendContext,
|
val context: JsIrBackendContext,
|
||||||
val function: IrFunctionSymbol,
|
val function: IrFunctionSymbol,
|
||||||
private val rootLoop: IrLoop,
|
private val rootLoop: IrLoop,
|
||||||
private val exceptionSymbol: IrProperty,
|
private val exceptionSymbolGetter: IrSimpleFunction,
|
||||||
private val exStateSymbol: IrProperty,
|
private val exceptionSymbolSetter: IrSimpleFunction,
|
||||||
private val stateSymbol: IrProperty,
|
private val exStateSymbolGetter: IrSimpleFunction,
|
||||||
|
private val exStateSymbolSetter: IrSimpleFunction,
|
||||||
|
private val stateSymbolSetter: IrSimpleFunction,
|
||||||
private val thisSymbol: IrValueParameterSymbol,
|
private val thisSymbol: IrValueParameterSymbol,
|
||||||
private val suspendResult: IrVariableSymbol
|
private val suspendResult: IrVariableSymbol
|
||||||
) : IrElementVisitorVoid {
|
) : IrElementVisitorVoid {
|
||||||
@@ -84,7 +87,7 @@ class StateMachineBuilder(
|
|||||||
|
|
||||||
val entryState = SuspendState(unit)
|
val entryState = SuspendState(unit)
|
||||||
val rootExceptionTrap = buildExceptionTrapState()
|
val rootExceptionTrap = buildExceptionTrapState()
|
||||||
private val globalExceptionVar = JsIrBuilder.buildVar(exceptionSymbol.getter!!.returnType, function.owner, "e")
|
private val globalExceptionVar = JsIrBuilder.buildVar(exceptionSymbolGetter.returnType, function.owner, "e")
|
||||||
lateinit var globalCatch: IrCatch
|
lateinit var globalCatch: IrCatch
|
||||||
|
|
||||||
fun finalizeStateMachine() {
|
fun finalizeStateMachine() {
|
||||||
@@ -118,11 +121,11 @@ class StateMachineBuilder(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// TODO: exception table
|
// TODO: exception table
|
||||||
elseBlock.statements += JsIrBuilder.buildCall(stateSymbol.setter!!.symbol, unit).apply {
|
elseBlock.statements += JsIrBuilder.buildCall(stateSymbolSetter.symbol, unit).apply {
|
||||||
dispatchReceiver = thisReceiver
|
dispatchReceiver = thisReceiver
|
||||||
putValueArgument(0, exceptionState())
|
putValueArgument(0, exceptionState())
|
||||||
}
|
}
|
||||||
elseBlock.statements += JsIrBuilder.buildCall(exceptionSymbol.setter!!.symbol, unit).apply {
|
elseBlock.statements += JsIrBuilder.buildCall(exceptionSymbolSetter.symbol, unit).apply {
|
||||||
dispatchReceiver = thisReceiver
|
dispatchReceiver = thisReceiver
|
||||||
putValueArgument(0, JsIrBuilder.buildGetValue(globalExceptionSymbol))
|
putValueArgument(0, JsIrBuilder.buildGetValue(globalExceptionSymbol))
|
||||||
}
|
}
|
||||||
@@ -180,7 +183,7 @@ class StateMachineBuilder(
|
|||||||
private fun doDispatchImpl(target: SuspendState, block: IrContainerExpression, andContinue: Boolean) {
|
private fun doDispatchImpl(target: SuspendState, block: IrContainerExpression, andContinue: Boolean) {
|
||||||
val irDispatch = IrDispatchPoint(target)
|
val irDispatch = IrDispatchPoint(target)
|
||||||
currentState.successors.add(target)
|
currentState.successors.add(target)
|
||||||
block.addStatement(JsIrBuilder.buildCall(stateSymbol.setter!!.symbol, unit).apply {
|
block.addStatement(JsIrBuilder.buildCall(stateSymbolSetter.symbol, unit).apply {
|
||||||
dispatchReceiver = thisReceiver
|
dispatchReceiver = thisReceiver
|
||||||
putValueArgument(0, irDispatch)
|
putValueArgument(0, irDispatch)
|
||||||
})
|
})
|
||||||
@@ -297,7 +300,7 @@ class StateMachineBuilder(
|
|||||||
currentState.successors += continueState
|
currentState.successors += continueState
|
||||||
|
|
||||||
transformLastExpression {
|
transformLastExpression {
|
||||||
JsIrBuilder.buildCall(stateSymbol.setter!!.symbol, unit).apply {
|
JsIrBuilder.buildCall(stateSymbolSetter.symbol, unit).apply {
|
||||||
dispatchReceiver = thisReceiver
|
dispatchReceiver = thisReceiver
|
||||||
putValueArgument(0, dispatch)
|
putValueArgument(0, dispatch)
|
||||||
}
|
}
|
||||||
@@ -686,7 +689,7 @@ class StateMachineBuilder(
|
|||||||
aTry.finallyExpression?.acceptVoid(this)
|
aTry.finallyExpression?.acceptVoid(this)
|
||||||
currentState.successors += listOf(throwExitState, exitState)
|
currentState.successors += listOf(throwExitState, exitState)
|
||||||
addStatement(
|
addStatement(
|
||||||
JsIrBuilder.buildCall(stateSymbol.setter!!.symbol, unit).also {
|
JsIrBuilder.buildCall(stateSymbolSetter.symbol, unit).also {
|
||||||
it.dispatchReceiver = thisReceiver
|
it.dispatchReceiver = thisReceiver
|
||||||
it.putValueArgument(0, JsIrBuilder.buildGetValue(finallyStateVar.symbol))
|
it.putValueArgument(0, JsIrBuilder.buildGetValue(finallyStateVar.symbol))
|
||||||
}
|
}
|
||||||
@@ -706,15 +709,15 @@ class StateMachineBuilder(
|
|||||||
|
|
||||||
private fun setupExceptionState(target: SuspendState) {
|
private fun setupExceptionState(target: SuspendState) {
|
||||||
addStatement(
|
addStatement(
|
||||||
JsIrBuilder.buildCall(exStateSymbol.setter!!.symbol, unit).apply {
|
JsIrBuilder.buildCall(exStateSymbolSetter.symbol, unit).apply {
|
||||||
dispatchReceiver = thisReceiver
|
dispatchReceiver = thisReceiver
|
||||||
putValueArgument(0, IrDispatchPoint(target))
|
putValueArgument(0, IrDispatchPoint(target))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun exceptionState() = JsIrBuilder.buildCall(exStateSymbol.getter!!.symbol).also { it.dispatchReceiver = thisReceiver }
|
private fun exceptionState() = JsIrBuilder.buildCall(exStateSymbolGetter.symbol).also { it.dispatchReceiver = thisReceiver }
|
||||||
private fun pendingException() = JsIrBuilder.buildCall(exceptionSymbol.getter!!.symbol).also { it.dispatchReceiver = thisReceiver }
|
private fun pendingException() = JsIrBuilder.buildCall(exceptionSymbolGetter.symbol).also { it.dispatchReceiver = thisReceiver }
|
||||||
|
|
||||||
private fun buildTryState(aTry: IrTry) =
|
private fun buildTryState(aTry: IrTry) =
|
||||||
TryState(
|
TryState(
|
||||||
|
|||||||
+20
-15
@@ -228,8 +228,8 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
|
|||||||
builtCoroutines[irFunction] = coroutine
|
builtCoroutines[irFunction] = coroutine
|
||||||
|
|
||||||
if (functionReference == null) {
|
if (functionReference == null) {
|
||||||
val resultSetter = context.coroutineImplResultSymbol.setter!!
|
val resultSetter = context.coroutineImplResultSymbolSetter
|
||||||
val exceptionSetter = context.coroutineImplExceptionProperty.setter!!
|
val exceptionSetter = context.coroutineImplExceptionPropertySetter
|
||||||
// It is not a lambda - replace original function with a call to constructor of the built coroutine.
|
// It is not a lambda - replace original function with a call to constructor of the built coroutine.
|
||||||
val irBuilder = context.createIrBuilder(irFunction.symbol, irFunction.startOffset, irFunction.endOffset)
|
val irBuilder = context.createIrBuilder(irFunction.symbol, irFunction.startOffset, irFunction.endOffset)
|
||||||
irFunction.body = irBuilder.irBlockBody(irFunction) {
|
irFunction.body = irBuilder.irBlockBody(irFunction) {
|
||||||
@@ -290,10 +290,13 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
|
|||||||
|
|
||||||
private val create1CompletionParameter = create1Function.valueParameters[0]
|
private val create1CompletionParameter = create1Function.valueParameters[0]
|
||||||
|
|
||||||
private val coroutineImplLabelProperty = context.coroutineImplLabelProperty
|
private val coroutineImplLabelPropertyGetter = context.coroutineImplLabelPropertyGetter
|
||||||
private val coroutineImplResultSymbol = context.coroutineImplResultSymbol
|
private val coroutineImplLabelPropertySetter = context.coroutineImplLabelPropertySetter
|
||||||
private val coroutineImplExceptionProperty = context.coroutineImplExceptionProperty
|
private val coroutineImplResultSymbolGetter = context.coroutineImplResultSymbolGetter
|
||||||
private val coroutineImplExceptionStateProperty = context.coroutineImplExceptionStateProperty
|
private val coroutineImplExceptionPropertyGetter = context.coroutineImplExceptionPropertyGetter
|
||||||
|
private val coroutineImplExceptionPropertySetter = context.coroutineImplExceptionPropertySetter
|
||||||
|
private val coroutineImplExceptionStatePropertyGetter = context.coroutineImplExceptionStatePropertyGetter
|
||||||
|
private val coroutineImplExceptionStatePropertySetter = context.coroutineImplExceptionStatePropertySetter
|
||||||
|
|
||||||
private val coroutineConstructors = mutableListOf<IrConstructor>()
|
private val coroutineConstructors = mutableListOf<IrConstructor>()
|
||||||
private var exceptionTrapId = -1
|
private var exceptionTrapId = -1
|
||||||
@@ -727,8 +730,8 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
|
|||||||
JsIrBuilder.buildValueParameter(p.name, p.index, p.type, p.origin).also { it.parent = declaration }
|
JsIrBuilder.buildValueParameter(p.name, p.index, p.type, p.origin).also { it.parent = declaration }
|
||||||
}
|
}
|
||||||
|
|
||||||
val resultSetter = context.coroutineImplResultSymbol.setter!!
|
val resultSetter = context.coroutineImplResultSymbolSetter
|
||||||
val exceptionSetter = context.coroutineImplExceptionProperty.setter!!
|
val exceptionSetter = context.coroutineImplExceptionPropertySetter
|
||||||
|
|
||||||
val thisReceiver = declaration.dispatchReceiverParameter!!
|
val thisReceiver = declaration.dispatchReceiverParameter!!
|
||||||
val irBuilder = context.createIrBuilder(symbol, irFunction.startOffset, irFunction.endOffset)
|
val irBuilder = context.createIrBuilder(symbol, irFunction.startOffset, irFunction.endOffset)
|
||||||
@@ -821,10 +824,10 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
|
|||||||
function,
|
function,
|
||||||
"suspendResult",
|
"suspendResult",
|
||||||
true,
|
true,
|
||||||
initializer = JsIrBuilder.buildCall(coroutineImplResultSymbol.getter!!.symbol).apply { dispatchReceiver = thisReceiver }
|
initializer = JsIrBuilder.buildCall(coroutineImplResultSymbolGetter.symbol).apply { dispatchReceiver = thisReceiver }
|
||||||
)
|
)
|
||||||
|
|
||||||
suspendState = JsIrBuilder.buildVar(coroutineImplLabelProperty.getter!!.returnType, function, "suspendState", true)
|
suspendState = JsIrBuilder.buildVar(coroutineImplLabelPropertyGetter.returnType, function, "suspendState", true)
|
||||||
|
|
||||||
val body =
|
val body =
|
||||||
(originalBody as IrBlockBody).run {
|
(originalBody as IrBlockBody).run {
|
||||||
@@ -848,7 +851,7 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
|
|||||||
(it.body as? IrBlockBody)?.run {
|
(it.body as? IrBlockBody)?.run {
|
||||||
val receiver = JsIrBuilder.buildGetValue(coroutineClassThis.symbol)
|
val receiver = JsIrBuilder.buildGetValue(coroutineClassThis.symbol)
|
||||||
val id = JsIrBuilder.buildInt(context.irBuiltIns.intType, exceptionTrapId)
|
val id = JsIrBuilder.buildInt(context.irBuiltIns.intType, exceptionTrapId)
|
||||||
statements += JsIrBuilder.buildCall(coroutineImplExceptionStateProperty.setter!!.symbol).also { call ->
|
statements += JsIrBuilder.buildCall(coroutineImplExceptionStatePropertySetter.symbol).also { call ->
|
||||||
call.dispatchReceiver = receiver
|
call.dispatchReceiver = receiver
|
||||||
call.putValueArgument(0, id)
|
call.putValueArgument(0, id)
|
||||||
}
|
}
|
||||||
@@ -880,9 +883,11 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
|
|||||||
context,
|
context,
|
||||||
function.symbol,
|
function.symbol,
|
||||||
rootLoop,
|
rootLoop,
|
||||||
coroutineImplExceptionProperty,
|
coroutineImplExceptionPropertyGetter,
|
||||||
coroutineImplExceptionStateProperty,
|
coroutineImplExceptionPropertySetter,
|
||||||
coroutineImplLabelProperty,
|
coroutineImplExceptionStatePropertyGetter,
|
||||||
|
coroutineImplExceptionStatePropertySetter,
|
||||||
|
coroutineImplLabelPropertySetter,
|
||||||
thisReceiver,
|
thisReceiver,
|
||||||
suspendResult.symbol
|
suspendResult.symbol
|
||||||
)
|
)
|
||||||
@@ -907,7 +912,7 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
|
|||||||
|
|
||||||
for (state in sortedStates) {
|
for (state in sortedStates) {
|
||||||
val condition = JsIrBuilder.buildCall(eqeqeqInt).apply {
|
val condition = JsIrBuilder.buildCall(eqeqeqInt).apply {
|
||||||
putValueArgument(0, JsIrBuilder.buildCall(coroutineImplLabelProperty.getter!!.symbol).also {
|
putValueArgument(0, JsIrBuilder.buildCall(coroutineImplLabelPropertyGetter.symbol).also {
|
||||||
it.dispatchReceiver = JsIrBuilder.buildGetValue(thisReceiver)
|
it.dispatchReceiver = JsIrBuilder.buildGetValue(thisReceiver)
|
||||||
})
|
})
|
||||||
putValueArgument(1, JsIrBuilder.buildInt(context.irBuiltIns.intType, state.id))
|
putValueArgument(1, JsIrBuilder.buildInt(context.irBuiltIns.intType, state.id))
|
||||||
|
|||||||
+22
-10
@@ -7,8 +7,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.lower.inline
|
package org.jetbrains.kotlin.ir.backend.js.lower.inline
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
import org.jetbrains.kotlin.backend.common.*
|
||||||
import org.jetbrains.kotlin.backend.common.ScopeWithIr
|
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
|
import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
@@ -19,6 +18,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities
|
|||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.lower.ArrayConstructorTransformer
|
||||||
import org.jetbrains.kotlin.ir.builders.irCall
|
import org.jetbrains.kotlin.ir.builders.irCall
|
||||||
import org.jetbrains.kotlin.ir.builders.irGet
|
import org.jetbrains.kotlin.ir.builders.irGet
|
||||||
import org.jetbrains.kotlin.ir.builders.irReturn
|
import org.jetbrains.kotlin.ir.builders.irReturn
|
||||||
@@ -31,11 +31,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
|||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.types.irTypeKotlinBuiltIns
|
import org.jetbrains.kotlin.ir.types.irTypeKotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.util.file
|
|
||||||
import org.jetbrains.kotlin.ir.util.getArguments
|
|
||||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
|
||||||
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -53,11 +49,27 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
|||||||
return irModule.accept(this, data = null)
|
return irModule.accept(this, data = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val arrayConstructorTransformer = ArrayConstructorTransformer(context)
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
val callSite = super.visitCall(expression) as IrCall
|
val callSite = arrayConstructorTransformer.transformCall(super.visitCall(expression) as IrCall)
|
||||||
val functionDescriptor = callSite.descriptor
|
val functionDescriptor = callSite.descriptor
|
||||||
if (!functionDescriptor.needsInlining)
|
|
||||||
return callSite // This call does not need inlining.
|
if (!functionDescriptor.needsInlining) return callSite // This call does not need inlining.
|
||||||
|
|
||||||
|
val languageVersionSettings = context.configuration.languageVersionSettings
|
||||||
|
when {
|
||||||
|
callSite.symbol == context.ir.symbols.lateinitIsInitializedPropertyGetter ->
|
||||||
|
return callSite
|
||||||
|
// Handle coroutine intrinsics
|
||||||
|
// TODO These should actually be inlined.
|
||||||
|
callSite.descriptor.isBuiltInIntercepted(languageVersionSettings) ->
|
||||||
|
error("Continuation.intercepted is not available with release coroutines")
|
||||||
|
callSite.symbol.descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings) ->
|
||||||
|
return irCall(callSite, context.coroutineSuspendOrReturn)
|
||||||
|
callSite.symbol == context.intrinsics.jsCoroutineContext ->
|
||||||
|
return irCall(callSite, context.coroutineGetContextJs)
|
||||||
|
}
|
||||||
|
|
||||||
val callee = getFunctionDeclaration(callSite.symbol) // Get declaration of the function to be inlined.
|
val callee = getFunctionDeclaration(callSite.symbol) // Get declaration of the function to be inlined.
|
||||||
callee.transformChildrenVoid(this) // Process recursive inline.
|
callee.transformChildrenVoid(this) // Process recursive inline.
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
|||||||
|
|
||||||
override fun visitFunction(declaration: IrFunction, data: JsGenerationContext) = JsEmpty.also {
|
override fun visitFunction(declaration: IrFunction, data: JsGenerationContext) = JsEmpty.also {
|
||||||
assert(declaration.origin == JsIrBackendContext.callableClosureOrigin) {
|
assert(declaration.origin == JsIrBackendContext.callableClosureOrigin) {
|
||||||
"The only possible Function Declarartion is one composed in Callable Reference Lowering"
|
"The only possible Function Declaration is one composed in Callable Reference Lowering"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user