[JS IR BE] Support bridges for special methods

Mostly reused from JVM IR lowering.
Shared logic moved to common backend module.
This commit is contained in:
Svyatoslav Kuzmich
2019-05-05 23:42:51 +03:00
parent ec6904afd1
commit 17178628fb
4 changed files with 125 additions and 63 deletions
@@ -7,14 +7,15 @@ package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.bridges.FunctionHandle
import org.jetbrains.kotlin.backend.common.bridges.findInterfaceImplementation
import org.jetbrains.kotlin.backend.common.bridges.generateBridges
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
import org.jetbrains.kotlin.backend.common.ir.isSuspend
import org.jetbrains.kotlin.backend.common.lower.SpecialBridgeMethods
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
import org.jetbrains.kotlin.backend.common.lower.irNot
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
@@ -29,7 +30,6 @@ import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.isUnit
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.resolve.DescriptorUtils
// Constructs bridges for inherited generic functions
//
@@ -52,6 +52,8 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
//
class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
private val specialBridgeMethods = SpecialBridgeMethods(context)
override fun lower(irClass: IrClass) {
irClass.declarations
.asSequence()
@@ -66,6 +68,11 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
if (function.isMethodOfAny())
return
val (specialOverride: IrSimpleFunction?, specialOverrideValueGenerator) =
specialBridgeMethods.findSpecialWithOverride(function) ?: Pair(null, null)
val specialOverrideSignature = specialOverride?.let { FunctionAndSignature(it) }
val bridgesToGenerate = generateBridges(
function = IrBasedFunctionHandle(function),
signature = { FunctionAndSignature(it.function) }
@@ -85,7 +92,16 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
continue
}
irClass.declarations.add(createBridge(function, from.function, to.function))
val bridge: IrDeclaration = when {
specialOverrideSignature == from ->
createBridge(function, from.function, to.function, specialOverrideValueGenerator)
else ->
createBridge(function, from.function, to.function, null)
}
irClass.declarations.add(bridge)
}
}
@@ -95,7 +111,8 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
private fun createBridge(
function: IrSimpleFunction,
bridge: IrSimpleFunction,
delegateTo: IrSimpleFunction
delegateTo: IrSimpleFunction,
defaultValueGenerator: ((IrSimpleFunction) -> IrExpression)?
): IrFunction {
val origin =
@@ -130,6 +147,16 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
}
context.createIrBuilder(irFunction.symbol).irBlockBody(irFunction) {
if (defaultValueGenerator != null) {
irFunction.valueParameters.forEach {
+irIfThen(
context.irBuiltIns.unitType,
irNot(irIs(irGet(it), delegateTo.valueParameters[it.index].type)),
irReturn(defaultValueGenerator(irFunction))
)
}
}
val call = irCall(delegateTo.symbol)
call.dispatchReceiver = irGet(irFunction.dispatchReceiverParameter!!)
irFunction.extensionReceiverParameter?.let {