BridgesConstruction
This commit is contained in:
committed by
Anton Bannykh
parent
4142031fe7
commit
d9646a5361
+38
-33
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.lower
|
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
|
||||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
|
||||||
import org.jetbrains.kotlin.backend.common.bridges.FunctionHandle
|
import org.jetbrains.kotlin.backend.common.bridges.FunctionHandle
|
||||||
import org.jetbrains.kotlin.backend.common.bridges.generateBridges
|
import org.jetbrains.kotlin.backend.common.bridges.generateBridges
|
||||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||||
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
|
|||||||
import org.jetbrains.kotlin.backend.common.ir.isSuspend
|
import org.jetbrains.kotlin.backend.common.ir.isSuspend
|
||||||
import org.jetbrains.kotlin.backend.common.lower.*
|
import org.jetbrains.kotlin.backend.common.lower.*
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.functionSignature
|
import org.jetbrains.kotlin.ir.backend.js.utils.functionSignature
|
||||||
@@ -23,6 +24,7 @@ import org.jetbrains.kotlin.ir.builders.*
|
|||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
@@ -46,23 +48,20 @@ import org.jetbrains.kotlin.ir.util.*
|
|||||||
// fun foo(t: Any?) = foo(t as Int) // Constructed bridge
|
// fun foo(t: Any?) = foo(t as Int) // Constructed bridge
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
class BridgesConstruction(val context: CommonBackendContext) : ClassLoweringPass {
|
class BridgesConstruction(val context: CommonBackendContext) : DeclarationTransformer {
|
||||||
|
|
||||||
private val specialBridgeMethods = SpecialBridgeMethods(context)
|
private val specialBridgeMethods = SpecialBridgeMethods(context)
|
||||||
|
|
||||||
override fun lower(irClass: IrClass) {
|
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
|
||||||
irClass.declarations
|
if (declaration !is IrSimpleFunction || declaration.isStaticMethodOfClass || declaration.parent !is IrClass) return null
|
||||||
.asSequence()
|
|
||||||
.filterIsInstance<IrSimpleFunction>()
|
return generateBridges(declaration)?.let { listOf(declaration) + it }
|
||||||
.filter { !it.isStaticMethodOfClass }
|
|
||||||
.toList()
|
|
||||||
.forEach { generateBridges(it, irClass) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateBridges(function: IrSimpleFunction, irClass: IrClass) {
|
private fun generateBridges(function: IrSimpleFunction): List<IrDeclaration>? {
|
||||||
// equals(Any?), hashCode(), toString() never need bridges
|
// equals(Any?), hashCode(), toString() never need bridges
|
||||||
if (function.isMethodOfAny())
|
if (function.isMethodOfAny())
|
||||||
return
|
return null
|
||||||
|
|
||||||
val (specialOverride: IrSimpleFunction?, specialOverrideInfo) =
|
val (specialOverride: IrSimpleFunction?, specialOverrideInfo) =
|
||||||
specialBridgeMethods.findSpecialWithOverride(function) ?: Pair(null, null)
|
specialBridgeMethods.findSpecialWithOverride(function) ?: Pair(null, null)
|
||||||
@@ -74,6 +73,10 @@ class BridgesConstruction(val context: CommonBackendContext) : ClassLoweringPass
|
|||||||
signature = { FunctionAndSignature(it.function) }
|
signature = { FunctionAndSignature(it.function) }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (bridgesToGenerate.isEmpty()) return null
|
||||||
|
|
||||||
|
val result = mutableListOf<IrDeclaration>()
|
||||||
|
|
||||||
for ((from, to) in bridgesToGenerate) {
|
for ((from, to) in bridgesToGenerate) {
|
||||||
if (!from.function.parentAsClass.isInterface &&
|
if (!from.function.parentAsClass.isInterface &&
|
||||||
from.function.isReal &&
|
from.function.isReal &&
|
||||||
@@ -97,8 +100,10 @@ class BridgesConstruction(val context: CommonBackendContext) : ClassLoweringPass
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
irClass.declarations.add(bridge)
|
result += bridge
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ported from from jvm.lower.BridgeLowering
|
// Ported from from jvm.lower.BridgeLowering
|
||||||
@@ -141,32 +146,32 @@ class BridgesConstruction(val context: CommonBackendContext) : ClassLoweringPass
|
|||||||
overriddenSymbols += bridge.symbol
|
overriddenSymbols += bridge.symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
context.createIrBuilder(irFunction.symbol).irBlockBody(irFunction) {
|
irFunction.body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
|
||||||
if (specialMethodInfo != null) {
|
statements += context.createIrBuilder(irFunction.symbol).irBlockBody(irFunction) {
|
||||||
irFunction.valueParameters.take(specialMethodInfo.argumentsToCheck).forEach {
|
if (specialMethodInfo != null) {
|
||||||
+irIfThen(
|
irFunction.valueParameters.take(specialMethodInfo.argumentsToCheck).forEach {
|
||||||
context.irBuiltIns.unitType,
|
+irIfThen(
|
||||||
irNot(irIs(irGet(it), delegateTo.valueParameters[it.index].type)),
|
context.irBuiltIns.unitType,
|
||||||
irReturn(specialMethodInfo.defaultValueGenerator(irFunction))
|
irNot(irIs(irGet(it), delegateTo.valueParameters[it.index].type)),
|
||||||
)
|
irReturn(specialMethodInfo.defaultValueGenerator(irFunction))
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val call = irCall(delegateTo.symbol)
|
val call = irCall(delegateTo.symbol)
|
||||||
call.dispatchReceiver = irGet(irFunction.dispatchReceiverParameter!!)
|
call.dispatchReceiver = irGet(irFunction.dispatchReceiverParameter!!)
|
||||||
irFunction.extensionReceiverParameter?.let {
|
irFunction.extensionReceiverParameter?.let {
|
||||||
call.extensionReceiver = irCastIfNeeded(irGet(it), delegateTo.extensionReceiverParameter!!.type)
|
call.extensionReceiver = irCastIfNeeded(irGet(it), delegateTo.extensionReceiverParameter!!.type)
|
||||||
}
|
}
|
||||||
|
|
||||||
val toTake = irFunction.valueParameters.size - if (call.isSuspend xor irFunction.isSuspend) 1 else 0
|
val toTake = irFunction.valueParameters.size - if (call.isSuspend xor irFunction.isSuspend) 1 else 0
|
||||||
|
|
||||||
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)
|
+irReturn(call)
|
||||||
}.apply {
|
}.statements
|
||||||
irFunction.body = this
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return irFunction
|
return irFunction
|
||||||
|
|||||||
Reference in New Issue
Block a user