[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.replaceUnboundSymbols
|
||||
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.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
|
||||
@@ -84,7 +75,6 @@ fun compile(
|
||||
|
||||
MoveExternalDeclarationsToSeparatePlace().lower(moduleFragment.files)
|
||||
|
||||
|
||||
moduleFragment.files.forEach(CoroutineIntrinsicLowering(context)::lower)
|
||||
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>) {
|
||||
moduleFragment.files.forEach(UnitMaterializationLowering(this)::lower)
|
||||
moduleFragment.files.forEach(VarargLowering(this)::lower)
|
||||
moduleFragment.files.forEach(LateinitLowering(this, true)::lower)
|
||||
moduleFragment.files.forEach(DefaultArgumentStubGenerator(this)::runOnFilePostfix)
|
||||
|
||||
+1
-1
@@ -528,7 +528,7 @@ class BlockDecomposerTransformer(context: JsIrBackendContext) : IrElementTransfo
|
||||
|
||||
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>()
|
||||
|
||||
|
||||
+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
|
||||
private fun createBridge(
|
||||
function: IrSimpleFunction,
|
||||
@@ -146,7 +148,19 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
|
||||
irFunction.valueParameters.subList(0, toTake).mapIndexed { i, valueParameter ->
|
||||
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 {
|
||||
irFunction.body = this
|
||||
}
|
||||
@@ -156,7 +170,7 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
|
||||
|
||||
// TODO: get rid of Unit check
|
||||
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
|
||||
|
||||
+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.expressions.*
|
||||
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.visitors.*
|
||||
|
||||
@@ -412,6 +415,12 @@ class StateMachineBuilder(
|
||||
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) {
|
||||
if (declaration !in suspendableNodes) return addStatement(declaration)
|
||||
declaration.acceptChildrenVoid(this)
|
||||
@@ -542,7 +551,7 @@ class StateMachineBuilder(
|
||||
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) {
|
||||
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.expressions.*
|
||||
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.js.backend.ast.*
|
||||
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) {
|
||||
ClassKind.OBJECT -> {
|
||||
// TODO: return unit instance instead of null
|
||||
if (expression.type.isUnit()) JsNullLiteral()
|
||||
else {
|
||||
val className = context.getNameForSymbol(expression.symbol)
|
||||
val getInstanceName = className.ident + "_getInstance"
|
||||
JsInvocation(JsNameRef(getInstanceName))
|
||||
}
|
||||
val className = context.getNameForSymbol(expression.symbol)
|
||||
val getInstanceName = className.ident + "_getInstance"
|
||||
JsInvocation(JsNameRef(getInstanceName))
|
||||
}
|
||||
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.resolve.calls.tasks.isDynamic
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||
|
||||
// TODO: this class has to be reimplemented soon
|
||||
class SimpleNameGenerator : NameGenerator {
|
||||
@@ -147,7 +148,10 @@ class SimpleNameGenerator : NameGenerator {
|
||||
|
||||
|
||||
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
|
||||
when (parent) {
|
||||
is IrDeclaration -> nameBuilder.append(getNameForDeclaration(parent, context))
|
||||
|
||||
Reference in New Issue
Block a user