[JS IR BE] Unit Materialization lowering
Fix unit-related things across backend
This commit is contained in:
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.backend.common.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
|
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.expressions.impl.IrCompositeImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||||
|
import org.jetbrains.kotlin.ir.types.isUnit
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
|
|
||||||
|
class UnitMaterializationLowering(context: BackendContext): FileLoweringPass {
|
||||||
|
|
||||||
|
private val unitType = context.irBuiltIns.unitType
|
||||||
|
private val unitValue = IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, unitType, unitType.classifierOrFail as IrClassSymbol)
|
||||||
|
|
||||||
|
override fun lower(irFile: IrFile) {
|
||||||
|
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||||
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
|
expression.transformChildrenVoid(this)
|
||||||
|
return if (expression.type.isUnit()) expression.let {
|
||||||
|
IrCompositeImpl(it.startOffset, it.endOffset, it.type, it.origin, listOf(it, unitValue))
|
||||||
|
}
|
||||||
|
else expression
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -22,15 +22,6 @@ import org.jetbrains.kotlin.ir.backend.js.lower.inline.RemoveInlineFunctionsWith
|
|||||||
import org.jetbrains.kotlin.ir.backend.js.lower.inline.ReturnableBlockLowering
|
import org.jetbrains.kotlin.ir.backend.js.lower.inline.ReturnableBlockLowering
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.inline.replaceUnboundSymbols
|
import org.jetbrains.kotlin.ir.backend.js.lower.inline.replaceUnboundSymbols
|
||||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
|
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrBlock
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.*
|
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
|
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
|
||||||
@@ -84,7 +75,6 @@ fun compile(
|
|||||||
|
|
||||||
MoveExternalDeclarationsToSeparatePlace().lower(moduleFragment.files)
|
MoveExternalDeclarationsToSeparatePlace().lower(moduleFragment.files)
|
||||||
|
|
||||||
|
|
||||||
moduleFragment.files.forEach(CoroutineIntrinsicLowering(context)::lower)
|
moduleFragment.files.forEach(CoroutineIntrinsicLowering(context)::lower)
|
||||||
moduleFragment.files.forEach { ArrayInlineConstructorLowering(context).lower(it) }
|
moduleFragment.files.forEach { ArrayInlineConstructorLowering(context).lower(it) }
|
||||||
|
|
||||||
@@ -111,6 +101,7 @@ private fun JsIrBackendContext.performInlining(moduleFragment: IrModuleFragment)
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun JsIrBackendContext.lower(moduleFragment: IrModuleFragment, dependencies: List<IrModuleFragment>) {
|
private fun JsIrBackendContext.lower(moduleFragment: IrModuleFragment, dependencies: List<IrModuleFragment>) {
|
||||||
|
moduleFragment.files.forEach(UnitMaterializationLowering(this)::lower)
|
||||||
moduleFragment.files.forEach(VarargLowering(this)::lower)
|
moduleFragment.files.forEach(VarargLowering(this)::lower)
|
||||||
moduleFragment.files.forEach(LateinitLowering(this, true)::lower)
|
moduleFragment.files.forEach(LateinitLowering(this, true)::lower)
|
||||||
moduleFragment.files.forEach(DefaultArgumentStubGenerator(this)::runOnFilePostfix)
|
moduleFragment.files.forEach(DefaultArgumentStubGenerator(this)::runOnFilePostfix)
|
||||||
|
|||||||
+1
-1
@@ -528,7 +528,7 @@ class BlockDecomposerTransformer(context: JsIrBackendContext) : IrElementTransfo
|
|||||||
|
|
||||||
override fun visitContainerExpression(expression: IrContainerExpression): IrExpression {
|
override fun visitContainerExpression(expression: IrContainerExpression): IrExpression {
|
||||||
|
|
||||||
expression.run { if (statements.isEmpty()) return IrCompositeImpl(startOffset, endOffset, type, origin, emptyList()) }
|
expression.run { if (statements.isEmpty()) return IrCompositeImpl(startOffset, endOffset, type, origin, listOf(unitValue)) }
|
||||||
|
|
||||||
val newStatements = mutableListOf<IrStatement>()
|
val newStatements = mutableListOf<IrStatement>()
|
||||||
|
|
||||||
|
|||||||
+16
-2
@@ -103,6 +103,8 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val unitValue = JsIrBuilder.buildGetObjectValue(context.irBuiltIns.unitType, context.irBuiltIns.unitClass)
|
||||||
|
|
||||||
// Ported from from jvm.lower.BridgeLowering
|
// Ported from from jvm.lower.BridgeLowering
|
||||||
private fun createBridge(
|
private fun createBridge(
|
||||||
function: IrSimpleFunction,
|
function: IrSimpleFunction,
|
||||||
@@ -146,7 +148,19 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
|
|||||||
irFunction.valueParameters.subList(0, toTake).mapIndexed { i, valueParameter ->
|
irFunction.valueParameters.subList(0, toTake).mapIndexed { i, valueParameter ->
|
||||||
call.putValueArgument(i, irCastIfNeeded(irGet(valueParameter), delegateTo.valueParameters[i].type))
|
call.putValueArgument(i, irCastIfNeeded(irGet(valueParameter), delegateTo.valueParameters[i].type))
|
||||||
}
|
}
|
||||||
+irReturn(call)
|
|
||||||
|
// This is required for Unit materialization
|
||||||
|
// TODO: generalize for boxed types and inline classes
|
||||||
|
// TODO: use return type in signature too
|
||||||
|
val returnValue = if (delegateTo.returnType.isUnit() && !function.returnType.isUnit()) {
|
||||||
|
irComposite(resultType = irFunction.returnType) {
|
||||||
|
+call
|
||||||
|
+unitValue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
call
|
||||||
|
}
|
||||||
|
+irReturn(returnValue)
|
||||||
}.apply {
|
}.apply {
|
||||||
irFunction.body = this
|
irFunction.body = this
|
||||||
}
|
}
|
||||||
@@ -156,7 +170,7 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
|
|||||||
|
|
||||||
// TODO: get rid of Unit check
|
// TODO: get rid of Unit check
|
||||||
private fun IrBlockBodyBuilder.irCastIfNeeded(argument: IrExpression, type: IrType): IrExpression =
|
private fun IrBlockBodyBuilder.irCastIfNeeded(argument: IrExpression, type: IrType): IrExpression =
|
||||||
if (argument.type.classifierOrNull == type.classifierOrNull || type.isUnit()) argument else irAs(argument, type)
|
if (argument.type.classifierOrNull == type.classifierOrNull) argument else irAs(argument, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle for common.bridges
|
// Handle for common.bridges
|
||||||
|
|||||||
+11
-2
@@ -18,7 +18,10 @@ import org.jetbrains.kotlin.ir.declarations.IrProperty
|
|||||||
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.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.*
|
import org.jetbrains.kotlin.ir.visitors.*
|
||||||
|
|
||||||
@@ -412,6 +415,12 @@ class StateMachineBuilder(
|
|||||||
transformLastExpression { expression.apply { value = it } }
|
transformLastExpression { expression.apply { value = it } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitTypeOperator(expression: IrTypeOperatorCall) {
|
||||||
|
if (expression !in suspendableNodes) return addStatement(expression)
|
||||||
|
expression.acceptChildrenVoid(this)
|
||||||
|
transformLastExpression { expression.apply { argument = it } }
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitVariable(declaration: IrVariable) {
|
override fun visitVariable(declaration: IrVariable) {
|
||||||
if (declaration !in suspendableNodes) return addStatement(declaration)
|
if (declaration !in suspendableNodes) return addStatement(declaration)
|
||||||
declaration.acceptChildrenVoid(this)
|
declaration.acceptChildrenVoid(this)
|
||||||
@@ -542,7 +551,7 @@ class StateMachineBuilder(
|
|||||||
currentState.successors += catchBlockStack.peek()!!
|
currentState.successors += catchBlockStack.peek()!!
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hasResultingValue(expression: IrExpression) = expression.type.run { !isUnit() && !isNothing() }
|
private fun hasResultingValue(expression: IrExpression) = !expression.type.isNothing()
|
||||||
|
|
||||||
override fun visitThrow(expression: IrThrow) {
|
override fun visitThrow(expression: IrThrow) {
|
||||||
expression.acceptChildrenVoid(this)
|
expression.acceptChildrenVoid(this)
|
||||||
|
|||||||
+3
-8
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
|||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.isUnit
|
|
||||||
import org.jetbrains.kotlin.ir.util.isFunctionTypeOrSubtype
|
import org.jetbrains.kotlin.ir.util.isFunctionTypeOrSubtype
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
@@ -70,13 +69,9 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
|||||||
|
|
||||||
override fun visitGetObjectValue(expression: IrGetObjectValue, context: JsGenerationContext) = when (expression.symbol.owner.kind) {
|
override fun visitGetObjectValue(expression: IrGetObjectValue, context: JsGenerationContext) = when (expression.symbol.owner.kind) {
|
||||||
ClassKind.OBJECT -> {
|
ClassKind.OBJECT -> {
|
||||||
// TODO: return unit instance instead of null
|
val className = context.getNameForSymbol(expression.symbol)
|
||||||
if (expression.type.isUnit()) JsNullLiteral()
|
val getInstanceName = className.ident + "_getInstance"
|
||||||
else {
|
JsInvocation(JsNameRef(getInstanceName))
|
||||||
val className = context.getNameForSymbol(expression.symbol)
|
|
||||||
val getInstanceName = className.ident + "_getInstance"
|
|
||||||
JsInvocation(JsNameRef(getInstanceName))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else -> TODO()
|
else -> TODO()
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.js.naming.isES5IdentifierPart
|
|||||||
import org.jetbrains.kotlin.js.naming.isES5IdentifierStart
|
import org.jetbrains.kotlin.js.naming.isES5IdentifierStart
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
|
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||||
|
|
||||||
// TODO: this class has to be reimplemented soon
|
// TODO: this class has to be reimplemented soon
|
||||||
class SimpleNameGenerator : NameGenerator {
|
class SimpleNameGenerator : NameGenerator {
|
||||||
@@ -147,7 +148,10 @@ 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
|
if (declaration.descriptor !is DeserializedClassDescriptor) {
|
||||||
|
// TODO: temporary workaround for Unit instance
|
||||||
|
nameDeclarator = context.staticContext.rootScope::declareFreshName
|
||||||
|
}
|
||||||
val parent = declaration.parent
|
val parent = declaration.parent
|
||||||
when (parent) {
|
when (parent) {
|
||||||
is IrDeclaration -> nameBuilder.append(getNameForDeclaration(parent, context))
|
is IrDeclaration -> nameBuilder.append(getNameForDeclaration(parent, context))
|
||||||
|
|||||||
Reference in New Issue
Block a user