Skip to content

Commit

Permalink
[K/N] New parameter API: BridgesBuilding ^KT-73361
Browse files Browse the repository at this point in the history
Merge-request: KT-MR-20156
Merged-by: Alexey Glushko <aleksei.glushko@jetbrains.com>
  • Loading branch information
Aleksei.Glushko authored and Space Team committed Feb 13, 2025
1 parent 70cc08b commit e701e27
Show file tree
Hide file tree
Showing 8 changed files with 34 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,7 @@ private fun IrFunction.typeWithKindAt(index: ParameterIndex) = when (index) {
returnType.isVoidAsReturnType() -> TypeWithKind(returnType, TypeKind.VOID)
else -> TypeWithKind.fromType(returnType)
}
ParameterIndex.DISPATCH_RECEIVER_INDEX -> TypeWithKind.fromType(dispatchReceiverParameter?.type)
ParameterIndex.EXTENSION_RECEIVER_INDEX -> TypeWithKind.fromType(extensionReceiverParameter?.type)
else -> TypeWithKind.fromType(this.valueParameters[index.unmap()].type)
else -> TypeWithKind.fromType(this.parameters[index.unmap()].type)
}

private fun IrFunction.needBridgeToAt(target: IrFunction, index: ParameterIndex, policy: BridgesPolicy) =
Expand All @@ -109,18 +107,16 @@ private fun IrFunction.needBridgeToAt(target: IrFunction, index: ParameterIndex,
private value class ParameterIndex(val index: Int) {
companion object {
val RETURN_INDEX = ParameterIndex(0)
val DISPATCH_RECEIVER_INDEX = ParameterIndex(1)
val EXTENSION_RECEIVER_INDEX = ParameterIndex(2)

fun map(index: Int) = ParameterIndex(index + 3)
fun map(index: Int) = ParameterIndex(index + 1)

fun allParametersCount(irFunction: IrFunction) = irFunction.valueParameters.size + 3
fun allParametersCount(irFunction: IrFunction) = irFunction.parameters.size + 1

inline fun forEachIndex(irFunction: IrFunction, block: (ParameterIndex) -> Unit) =
(0 until allParametersCount(irFunction)).forEach { block(ParameterIndex(it)) }
}

fun unmap() = index - 3
fun unmap() = index - 1
}

internal fun IrFunction.needBridgeTo(target: IrFunction, policy: BridgesPolicy): Boolean {
Expand Down Expand Up @@ -226,8 +222,6 @@ internal class BridgeDirections(private val array: Array<BridgeDirection>) {
private fun getDirectionAt(index: ParameterIndex) = array[index.index]

val returnDirection get() = getDirectionAt(ParameterIndex.RETURN_INDEX)
val dispatchReceiverDirection get() = getDirectionAt(ParameterIndex.DISPATCH_RECEIVER_INDEX)
val extensionReceiverDirection get() = getDirectionAt(ParameterIndex.EXTENSION_RECEIVER_INDEX)
fun parameterDirectionAt(index: Int) = getDirectionAt(ParameterIndex.map(index))

override fun toString(): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrRawFunctionReferenceImpl
import org.jetbrains.kotlin.ir.expressions.impl.fromSymbolOwner
import org.jetbrains.kotlin.ir.irAttribute
Expand Down Expand Up @@ -85,14 +84,8 @@ internal class BridgesSupport(val irBuiltIns: IrBuiltIns, val irFactory: IrFacto
parent = function.parent
val bridge = this

dispatchReceiverParameter = target.dispatchReceiverParameter?.let {
it.copyTo(bridge, type = bridgeDirections.dispatchReceiverDirection.type() ?: it.type)
}
extensionReceiverParameter = target.extensionReceiverParameter?.let {
it.copyTo(bridge, type = bridgeDirections.extensionReceiverDirection.type() ?: it.type)
}
valueParameters = target.valueParameters.map {
it.copyTo(bridge, type = bridgeDirections.parameterDirectionAt(it.indexInOldValueParameters).type() ?: it.type)
parameters = target.parameters.map {
it.copyTo(bridge, type = bridgeDirections.parameterDirectionAt(it.indexInParameters).type() ?: it.type)
}

typeParameters = function.typeParameters.map { parameter ->
Expand Down Expand Up @@ -130,11 +123,11 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain
if (expression.symbol != symbols.executeImpl)
return expression

val job = expression.getValueArgument(3) as IrRawFunctionReference
val job = expression.arguments[3] as IrRawFunctionReference
val jobFunction = (job.symbol as IrSimpleFunctionSymbol).owner

if (!::runtimeJobFunction.isInitialized) {
val arg = jobFunction.valueParameters[0]
val arg = jobFunction.parameters[0]
val startOffset = jobFunction.startOffset
val endOffset = jobFunction.endOffset
runtimeJobFunction =
Expand All @@ -155,11 +148,12 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain
isInfix = false,
)

runtimeJobFunction.valueParameters +=
runtimeJobFunction.parameters +=
context.irFactory.createValueParameter(
startOffset = startOffset,
endOffset = endOffset,
origin = IrDeclarationOrigin.DEFINED,
kind = IrParameterKind.Regular,
name = arg.name,
type = context.irBuiltIns.anyNType,
isAssignable = arg.isAssignable,
Expand All @@ -179,12 +173,12 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain
overriddenFunction = overriddenJobDescriptor,
targetSymbol = jobFunction.symbol)
bridges += bridge
expression.putValueArgument(3, IrRawFunctionReferenceImpl(
expression.arguments[3] = IrRawFunctionReferenceImpl(
startOffset = job.startOffset,
endOffset = job.endOffset,
type = job.type,
symbol = bridge.symbol
))
)
return expression
}
})
Expand Down Expand Up @@ -273,23 +267,23 @@ private fun IrBuilderWithScope.irConst(value: Any?) = when (value) {
private fun IrBlockBodyBuilder.buildTypeSafeBarrier(function: IrFunction,
originalFunction: IrFunction,
typeSafeBarrierDescription: SpecialGenericSignatures.TypeSafeBarrierDescription) {
val valueParameters = function.valueParameters
val originalValueParameters = originalFunction.valueParameters
for (i in valueParameters.indices) {
val parameters = function.nonDispatchParameters
val originalParameters = originalFunction.nonDispatchParameters
for (i in parameters.indices) {
if (!typeSafeBarrierDescription.checkParameter(i))
continue

val type = originalValueParameters[i].type.eraseTypeParameters()
val type = originalParameters[i].type.eraseTypeParameters()
// Note: erasing to single type is not entirely correct if type parameter has multiple upper bounds.
// In this case the compiler could generate multiple type checks, one for each upper bound.
// But let's keep it simple here for now; JVM backend doesn't do this anyway.

if (!type.isNullableAny()) {
// Here, we can't trust value parameter type until we check it, because of @UnsafeVariance
// So we add implicit cast to avoid type check optimization
+returnIfBadType(irImplicitCast(irGet(valueParameters[i]), context.irBuiltIns.anyNType), type,
+returnIfBadType(irImplicitCast(irGet(parameters[i]), context.irBuiltIns.anyNType), type,
if (typeSafeBarrierDescription == SpecialGenericSignatures.TypeSafeBarrierDescription.MAP_GET_OR_DEFAULT)
irGet(valueParameters[1])
irGet(parameters[1])
else irConst(typeSafeBarrierDescription.defaultValue)
)
}
Expand Down Expand Up @@ -318,9 +312,7 @@ private fun Context.buildBridge(startOffset: Int, endOffset: Int,
target.symbol,
superQualifierSymbol = superQualifierSymbol /* Call non-virtually */
).apply {
bridge.dispatchReceiverParameter?.let { dispatchReceiver = irGet(it) }
bridge.extensionReceiverParameter?.let { extensionReceiver = irGet(it) }
bridge.valueParameters.forEachIndexed { index, parameter -> putValueArgument(index, irGet(parameter)) }
bridge.parameters.forEachIndexed { index, parameter -> arguments[index] = irGet(parameter) }
}

+irReturn(delegatingCall)
Expand Down
6 changes: 3 additions & 3 deletions native/native.tests/testData/codegen/fileCheck/bridges.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ interface I1 {
class C1 : I1 {
override fun foo(): Nothing = TODO()
}
// CHECK-LABEL: define i32 @"kfun:C1#$<bridge-DNN>foo(){}kotlin.Nothing(){}kotlin.Int
// CHECK-LABEL: define i32 @"kfun:C1#$<bridge-DN>foo(){}kotlin.Nothing(){}kotlin.Int
// CHECK-LABEL: epilogue:

open class Foo2<T>(val x: T)
Expand All @@ -19,7 +19,7 @@ interface I2 {
}

class Bar2 : Foo2<Unit>(Unit), I2
// CHECK-LABEL: define void @"kfun:Bar2#$<bridge-DNN><get-x>(){}(){}
// CHECK-LABEL: define void @"kfun:Bar2#$<bridge-DN><get-x>(){}(){}
// CHECK-LABEL: epilogue:

fun getX2(i: I2) = i.x
Expand All @@ -33,7 +33,7 @@ open class Foo3<T : Int> {
}

class Bar3 : Foo3<Nothing>(), I3
// CHECK-LABEL: define void @"kfun:Bar3#$<bridge-DNN>foo(){}kotlin.Nothing(){}kotlin.Nothing
// CHECK-LABEL: define void @"kfun:Bar3#$<bridge-DN>foo(){}kotlin.Nothing(){}kotlin.Nothing
// CHECK-LABEL: epilogue:

// CHECK-LABEL: define ptr @"kfun:#box(){}kotlin.String"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ fun box(): String {
// CHECK-SAME: (ptr {{%[0-9]+}}, ptr {{%[0-9]+}})


// CHECK-LABEL: define internal ptr @"kfun:stringifyArray$1.$<bridge-UNNN>invoke(kotlin.Array<-1:0>){}kotlin.Int#internal"
// CHECK-LABEL: define internal ptr @"kfun:stringifyArray$1.$<bridge-UNN>invoke(kotlin.Array<-1:0>){}kotlin.Int#internal"
// CHECK-SAME: (ptr [[this:%[0-9]+]], ptr [[array:%[0-9]+]], ptr {{%[0-9]+}})
// CHECK-OPT: call i32 @"kfun:stringifyArray$1.invoke#internal"(ptr [[this]], ptr {{%[0-9]+}})
// CHECK-DEBUG: call i32 @"kfun:stringifyArray$1.invoke#internal"(ptr {{%[0-9]+}}, ptr {{%[0-9]+}})
Expand All @@ -80,7 +80,7 @@ fun box(): String {
// CHECK-OPT: call ptr @Kotlin_Array_get(ptr [[array]], i32 [[index]], ptr [[ret]])
// CHECK-DEBUG: call ptr @Kotlin_Array_get(ptr {{%[0-9]+}}, i32 {{%[0-9]+}}, ptr {{%[0-9]+}})

// CHECK-LABEL: define internal ptr @"kfun:stringifyArray$$FUNCTION_REFERENCE_FOR$get$0.$<bridge-NNNNU>invoke(kotlin.Array<*>;kotlin.Int){}kotlin.Any?#internal"
// CHECK-LABEL: define internal ptr @"kfun:stringifyArray$$FUNCTION_REFERENCE_FOR$get$0.$<bridge-NNNU>invoke(kotlin.Array<*>;kotlin.Int){}kotlin.Any?#internal"
// CHECK-SAME: (ptr [[this:%[0-9]+]], ptr [[array:%[0-9]+]], ptr [[boxedIndex:%[0-9]+]], ptr [[ret:%[0-9]+]])
// CHECK-OPT: call ptr @"kfun:stringifyArray$$FUNCTION_REFERENCE_FOR$get$0.invoke#internal"(ptr [[this]], ptr {{%[0-9]+}}, i32 {{%[0-9]+}}, ptr [[ret]])
// CHECK-DEBUG: call ptr @"kfun:stringifyArray$$FUNCTION_REFERENCE_FOR$get$0.invoke#internal"(ptr {{%[0-9]+}}, ptr {{%[0-9]+}}, i32 {{%[0-9]+}}, ptr {{%[0-9]+}})
Expand All @@ -91,7 +91,7 @@ fun box(): String {
// CHECK-LABEL: define internal i32 @"kfun:stringifyIntArray$1.invoke#internal"
// CHECK-SAME: (ptr {{%[0-9]+}}, ptr {{%[0-9]+}})

// CHECK-LABEL: define internal ptr @"kfun:stringifyIntArray$1.$<bridge-UNNN>invoke(kotlin.Array<kotlin.Int>){}kotlin.Int#internal"
// CHECK-LABEL: define internal ptr @"kfun:stringifyIntArray$1.$<bridge-UNN>invoke(kotlin.Array<kotlin.Int>){}kotlin.Int#internal"
// CHECK-SAME: (ptr [[this:%[0-9]+]], ptr [[array:%[0-9]+]], ptr {{%[0-9]+}})
// CHECK-OPT: call i32 @"kfun:stringifyIntArray$1.invoke#internal"(ptr [[this]], ptr {{%[0-9]+}})
// CHECK-DEBUG: call i32 @"kfun:stringifyIntArray$1.invoke#internal"(ptr {{%[0-9]+}}, ptr {{%[0-9]+}})
Expand All @@ -103,7 +103,7 @@ fun box(): String {
// CHECK-SAME: (ptr {{%[0-9]+}}, ptr {{%[0-9]+}}, i32 {{%[0-9]+}})


// CHECK-LABEL: define internal ptr @"kfun:stringifyIntArray$$FUNCTION_REFERENCE_FOR$get$1.$<bridge-UNNNU>invoke(kotlin.Array<kotlin.Int>;kotlin.Int){}kotlin.Int#internal"
// CHECK-LABEL: define internal ptr @"kfun:stringifyIntArray$$FUNCTION_REFERENCE_FOR$get$1.$<bridge-UNNU>invoke(kotlin.Array<kotlin.Int>;kotlin.Int){}kotlin.Int#internal"
// CHECK-SAME: (ptr [[this:%[0-9]+]], ptr [[array:%[0-9]+]], ptr {{%[0-9]+}}, ptr {{%[0-9]+}})
// CHECK-OPT: call i32 @"kfun:stringifyIntArray$$FUNCTION_REFERENCE_FOR$get$1.invoke#internal"(ptr [[this]], ptr {{%[0-9]+}}, i32 {{%[0-9]+}})
// CHECK-DEBUG: call i32 @"kfun:stringifyIntArray$$FUNCTION_REFERENCE_FOR$get$1.invoke#internal"(ptr {{%[0-9]+}}, ptr {{%[0-9]+}}, i32 {{%[0-9]+}})
Expand All @@ -117,7 +117,7 @@ fun box(): String {
// CHECK-DEBUG: call void @"kfun:#foo(0:0;0:1){0\C2\A7<kotlin.Any?>;1\C2\A7<kotlin.Any?>}"(ptr {{%[0-9]+}}, ptr {{%[0-9]+}})


// CHECK-LABEL: define internal ptr @"kfun:bar$ref$$FUNCTION_REFERENCE_FOR$foo$2.$<bridge-DNNNN>invoke(-1:0;-1:0){}#internal"
// CHECK-LABEL: define internal ptr @"kfun:bar$ref$$FUNCTION_REFERENCE_FOR$foo$2.$<bridge-DNNN>invoke(-1:0;-1:0){}#internal"
// CHECK-SAME: (ptr [[this:%[0-9]+]], ptr [[p1:%[0-9]+]], ptr [[p2:%[0-9]+]], ptr {{%[0-9]+}})
// CHECK-OPT: call void @"kfun:bar$ref$$FUNCTION_REFERENCE_FOR$foo$2.invoke#internal"(ptr [[this]], ptr [[p1]], ptr [[p2]])
// CHECK-DEBUG: call void @"kfun:bar$ref$$FUNCTION_REFERENCE_FOR$foo$2.invoke#internal"(ptr {{%[0-9]+}}, ptr {{%[0-9]+}}, ptr {{%[0-9]+}})
Expand All @@ -129,7 +129,7 @@ fun box(): String {
// CHECK-SAME: (ptr {{%[0-9]+}}, i32 {{%[0-9]+}}, i32 {{%[0-9]+}})
// CHECK: call void @"kfun:#foo(0:0;0:1){0\C2\A7<kotlin.Any?>;1\C2\A7<kotlin.Any?>}"(ptr {{%[0-9]+}}, ptr {{%[0-9]+}})

// CHECK-LABEL: define internal ptr @"kfun:box$ref$$FUNCTION_REFERENCE_FOR$foo$3.$<bridge-DNNUU>invoke(kotlin.Int;kotlin.Int){}#internal"
// CHECK-LABEL: define internal ptr @"kfun:box$ref$$FUNCTION_REFERENCE_FOR$foo$3.$<bridge-DNUU>invoke(kotlin.Int;kotlin.Int){}#internal"
// CHECK-SAME: (ptr [[this:%[0-9]+]], ptr {{%[0-9]+}}, ptr {{%[0-9]+}}, ptr {{%[0-9]+}})
// CHECK-OPT: call void @"kfun:box$ref$$FUNCTION_REFERENCE_FOR$foo$3.invoke#internal"(ptr [[this]], i32 {{%[0-9]+}}, i32 {{%[0-9]+}})
// CHECK-DEBUG: call void @"kfun:box$ref$$FUNCTION_REFERENCE_FOR$foo$3.invoke#internal"(ptr {{%[0-9]+}}, i32 {{%[0-9]+}}, i32 {{%[0-9]+}})
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// FREE_COMPILER_ARGS: -Xbinary=genericSafeCasts=true

value class Foo(val value: Int)
// CHECK-LABEL: define ptr @"kfun:Foo#$<bridge-NUN>toString(){}kotlin.String(){}kotlin.String
// CHECK-LABEL: define ptr @"kfun:Foo#$<bridge-NU>toString(){}kotlin.String(){}kotlin.String
// CHECK-DEBUG-NOT: {{call|call zeroext}} i1 @IsSubtype
// CHECK-OPT-NOT: {{call|call zeroext}} i1 @IsSubclassFast
// CHECK-LABEL: call ptr @"kfun:Foo#toString(){}kotlin.String
Expand Down
2 changes: 1 addition & 1 deletion native/native.tests/testData/lldb/kt42208.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* thread #1, [..] stop reason = breakpoint 1.1
* frame #0: [..]`ThrowException
frame #1: [..]`kfun:[..]main$$inlined$foo[..]invoke[..](_this=[..])[..] at kt42208-2.kt:10:11
frame #2: [..]`kfun:[..]main$$inlined$foo[..]$<bridge-DNN>invoke(_this=[..]){}kotlin.Nothing[..] at kt42208-2.kt:9:20
frame #2: [..]`kfun:[..]main$$inlined$foo[..]$<bridge-DN>invoke(_this=[..]){}kotlin.Nothing[..] at kt42208-2.kt:9:20
frame #3: [..]`kfun:kotlin.Function0#invoke(){}1:0-trampoline at [K][Suspend]Functions:1:1
frame #4: [..]`kfun:#main(){} at kt42208-1.kt:5:5
frame #5: [..]`Konan_start(args=[..]) at [..]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
> bt
* thread #1, [..] stop reason = breakpoint 1.1
* frame #0: [..]`kfun:[..]main$$inlined$foo[..]invoke[..](_this=[..])[..] at kt42208-2.kt:13:5
frame #1: [..]`kfun:[..]main$$inlined$foo[..]$<bridge-UNN>invoke(_this=[..]){}kotlin.Boolean[..] at kt42208-2.kt:12:20
frame #1: [..]`kfun:[..]main$$inlined$foo[..]$<bridge-UN>invoke(_this=[..]){}kotlin.Boolean[..] at kt42208-2.kt:12:20
frame #2: [..]`kfun:kotlin.Function0#invoke(){}1:0-trampoline at [K][Suspend]Functions:1:1
frame #3: [..]`kfun:#bar(v=[..]){} at kt42208-3.kt:17:5
frame #4: [..]`kfun:#main(){} at kt42208-1.kt:6:5
Expand Down
6 changes: 3 additions & 3 deletions native/native.tests/testData/lldb/kt42208WithVariable.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
> bt
* thread #1, [..] stop reason = breakpoint 1.1
* frame #0: [..]`kfun:[..]main$$inlined$foo[..]invoke[..](_this=[..])[..] at kt42208-2.kt:15:5
frame #1: [..]`kfun:[..]main$$inlined$foo[..]$<bridge-UNN>invoke(_this=[..]){}kotlin.Boolean[..] at kt42208-2.kt:14:20
frame #1: [..]`kfun:[..]main$$inlined$foo[..]$<bridge-UN>invoke(_this=[..]){}kotlin.Boolean[..] at kt42208-2.kt:14:20
frame #2: [..]`kfun:kotlin.Function0#invoke(){}1:0-trampoline at [K][Suspend]Functions:1:1
frame #3: [..]`kfun:#main(){} at kt42208-1.kt:6:5
frame #4: [..]`Konan_start(args=[..]) at [..]
Expand All @@ -12,15 +12,15 @@
> bt
* thread #1, [..] stop reason = breakpoint 1.1
* frame #0: [..]`kfun:[..]main$$inlined$foo[..]invoke[..](_this=[..])[..] at kt42208-2.kt:15:5
frame #1: [..]`kfun:[..]main$$inlined$foo[..]$<bridge-UNN>invoke(_this=[..]){}kotlin.Boolean[..] at kt42208-2.kt:14:20
frame #1: [..]`kfun:[..]main$$inlined$foo[..]$<bridge-UN>invoke(_this=[..]){}kotlin.Boolean[..] at kt42208-2.kt:14:20
frame #2: [..]`kfun:kotlin.Function0#invoke(){}1:0-trampoline at [K][Suspend]Functions:1:1
frame #3: [..]`kfun:#main(){} at kt42208-1.kt:7:5
frame #4: [..]`Konan_start(args=[..]) at [..]
> c
> bt
* thread #1, [..] stop reason = breakpoint 1.1
* frame #0: [..]`kfun:[..]main$$inlined$foo[..]invoke[..](_this=[..])[..] at kt42208-2.kt:15:5
frame #1: [..]`kfun:[..]main$$inlined$foo[..]$<bridge-UNN>invoke(_this=[..]){}kotlin.Boolean[..] at kt42208-2.kt:14:20
frame #1: [..]`kfun:[..]main$$inlined$foo[..]$<bridge-UN>invoke(_this=[..]){}kotlin.Boolean[..] at kt42208-2.kt:14:20
frame #2: [..]`kfun:kotlin.Function0#invoke(){}1:0-trampoline at [K][Suspend]Functions:1:1
frame #3: [..]`kfun:#main(){} at kt42208-1.kt:8:5
frame #4: [..]`Konan_start(args=[..]) at [..]
Expand Down

0 comments on commit e701e27

Please sign in to comment.