[K/N][Tests] Move filecheck and cinterop tests to /native/

^KT-61259
This commit is contained in:
Vladimir Sukharev
2024-02-14 13:07:40 +01:00
committed by Space Team
parent 05cbe66ee0
commit bf0150108d
144 changed files with 1683 additions and 5542 deletions
@@ -0,0 +1,18 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
inline fun foo(x: () -> Unit): String {
x()
return "OK"
}
fun String.id(s: String = this, vararg xs: Int): String = s
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
// CHECK-LABEL: entry
// CHECK-NOT: call %struct.ObjHeader* @AllocInstance
// CHECK-NOT: alloca
return foo("Fail"::id)
// CHECK-LABEL: epilogue:
}
@@ -0,0 +1,372 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlin.concurrent.*
// CHECK-AAPCS-LABEL: define i8 @"kfun:#<get-byteGlobal>(){}kotlin.Byte"()
// CHECK-DEFAULTABI-LABEL: define signext i8 @"kfun:#<get-byteGlobal>(){}kotlin.Byte"()
// CHECK-WINDOWSX64-LABEL: define i8 @"kfun:#<get-byteGlobal>(){}kotlin.Byte"()
// CHECK: load atomic i8, i8* @"kvar:byteGlobal#internal" seq_cst
// CHECK-LABEL: define void @"kfun:#<set-byteGlobal>(kotlin.Byte){}"(i8
// CHECK: store atomic i8 %{{[0-9]+}}, i8* @"kvar:byteGlobal#internal" seq_cst
@Volatile var byteGlobal: Byte = 42
// CHECK-AAPCS-LABEL: define i16 @"kfun:#<get-shortGlobal>(){}kotlin.Short"()
// CHECK-DEFAULTABI-LABEL: define signext i16 @"kfun:#<get-shortGlobal>(){}kotlin.Short"()
// CHECK-WINDOWSX64-LABEL: define i16 @"kfun:#<get-shortGlobal>(){}kotlin.Short"()
// CHECK: load atomic i16, i16* @"kvar:shortGlobal#internal" seq_cst
// CHECK-LABEL: define void @"kfun:#<set-shortGlobal>(kotlin.Short){}"(i16
// CHECK: store atomic i16 %{{[0-9]+}}, i16* @"kvar:shortGlobal#internal" seq_cst
@Volatile var shortGlobal: Short = 42
// CHECK-LABEL: define i32 @"kfun:#<get-intGlobal>(){}kotlin.Int"()
// CHECK: load atomic i32, i32* @"kvar:intGlobal#internal" seq_cst
// CHECK-LABEL: define void @"kfun:#<set-intGlobal>(kotlin.Int){}"(i32
// CHECK: store atomic i32 %{{[0-9]+}}, i32* @"kvar:intGlobal#internal" seq_cst
@Volatile var intGlobal: Int = 42
// CHECK-LABEL: define i64 @"kfun:#<get-longGlobal>(){}kotlin.Long"()
// CHECK: load atomic i64, i64* @"kvar:longGlobal#internal" seq_cst
// CHECK-LABEL: define void @"kfun:#<set-longGlobal>(kotlin.Long){}"(i64
// CHECK: store atomic i64 %{{[0-9]+}}, i64* @"kvar:longGlobal#internal" seq_cst
@Volatile var longGlobal: Long = 42
// CHECK-AAPCS-LABEL: define i1 @"kfun:#<get-booleanGlobal>(){}kotlin.Boolean"()
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#<get-booleanGlobal>(){}kotlin.Boolean"()
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#<get-booleanGlobal>(){}kotlin.Boolean"()
// CHECK: load atomic i8, i8* @"kvar:booleanGlobal#internal" seq_cst
// CHECK-LABEL: define void @"kfun:#<set-booleanGlobal>(kotlin.Boolean){}"(i1
// CHECK: store atomic i8 %{{[0-9]+}}, i8* @"kvar:booleanGlobal#internal" seq_cst
@Volatile var booleanGlobal: Boolean = true
// Byte
fun byteGlobal_getField() = byteGlobal
fun byteGlobal_setField() { byteGlobal = 0 }
// CHECK-AAPCS-LABEL: define i8 @"kfun:#byteGlobal_getAndSetField(){}kotlin.Byte"()
// CHECK-DEFAULTABI-LABEL: define signext i8 @"kfun:#byteGlobal_getAndSetField(){}kotlin.Byte"()
// CHECK-WINDOWSX64-LABEL: define i8 @"kfun:#byteGlobal_getAndSetField(){}kotlin.Byte"()
// CHECK: atomicrmw xchg i8* @"kvar:byteGlobal#internal", i8 0 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun byteGlobal_getAndSetField() = ::byteGlobal.getAndSetField(0.toByte())
// CHECK-AAPCS-LABEL: define i8 @"kfun:#byteGlobal_getAndAddField(){}kotlin.Byte"()
// CHECK-DEFAULTABI-LABEL: define signext i8 @"kfun:#byteGlobal_getAndAddField(){}kotlin.Byte"()
// CHECK-WINDOWSX64-LABEL: define i8 @"kfun:#byteGlobal_getAndAddField(){}kotlin.Byte"()
// CHECK: atomicrmw add i8* @"kvar:byteGlobal#internal", i8 0 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun byteGlobal_getAndAddField() = ::byteGlobal.getAndAddField(0.toByte())
// CHECK-AAPCS-LABEL: define i1 @"kfun:#byteGlobal_compareAndSetField(){}kotlin.Boolean"()
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#byteGlobal_compareAndSetField(){}kotlin.Boolean"()
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#byteGlobal_compareAndSetField(){}kotlin.Boolean"()
// CHECK: cmpxchg i8* @"kvar:byteGlobal#internal", i8 0, i8 1 seq_cst seq_cst
// CHECK: extractvalue { i8, i1 } %{{[0-9]+}}, 1
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun byteGlobal_compareAndSetField() = ::byteGlobal.compareAndSetField(0.toByte(), 1.toByte())
// CHECK-AAPCS-LABEL: define i8 @"kfun:#byteGlobal_compareAndExchangeField(){}kotlin.Byte"()
// CHECK-DEFAULTABI-LABEL: define signext i8 @"kfun:#byteGlobal_compareAndExchangeField(){}kotlin.Byte"()
// CHECK-WINDOWSX64-LABEL: define i8 @"kfun:#byteGlobal_compareAndExchangeField(){}kotlin.Byte"()
// CHECK: cmpxchg i8* @"kvar:byteGlobal#internal", i8 0, i8 1 seq_cst seq_cst
// CHECK: extractvalue { i8, i1 } %{{[0-9]+}}, 0
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun byteGlobal_compareAndExchangeField() = ::byteGlobal.compareAndExchangeField(0.toByte(), 1.toByte())
// Short
fun shortGlobal_getField() = shortGlobal
fun shortGlobal_setField() { shortGlobal = 0 }
// CHECK-AAPCS-LABEL: define i16 @"kfun:#shortGlobal_getAndSetField(){}
// CHECK-DEFAULTABI-LABEL: define signext i16 @"kfun:#shortGlobal_getAndSetField(){}
// CHECK-WINDOWSX64-LABEL: define i16 @"kfun:#shortGlobal_getAndSetField(){}
// CHECK: atomicrmw xchg i16* @"kvar:shortGlobal#internal", i16 0 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun shortGlobal_getAndSetField() = ::shortGlobal.getAndSetField(0.toShort())
// CHECK-AAPCS-LABEL: define i16 @"kfun:#shortGlobal_getAndAddField(){}
// CHECK-DEFAULTABI-LABEL: define signext i16 @"kfun:#shortGlobal_getAndAddField(){}
// CHECK-WINDOWSX64-LABEL: define i16 @"kfun:#shortGlobal_getAndAddField(){}
// CHECK: atomicrmw add i16* @"kvar:shortGlobal#internal", i16 0 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun shortGlobal_getAndAddField() = ::shortGlobal.getAndAddField(0.toShort())
// CHECK-AAPCS-LABEL: define i1 @"kfun:#shortGlobal_compareAndSetField(){}
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#shortGlobal_compareAndSetField(){}
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#shortGlobal_compareAndSetField(){}
// CHECK: cmpxchg i16* @"kvar:shortGlobal#internal", i16 0, i16 1 seq_cst seq_cst
// CHECK: extractvalue { i16, i1 } %{{[0-9]+}}, 1
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun shortGlobal_compareAndSetField() = ::shortGlobal.compareAndSetField(0.toShort(), 1.toShort())
// CHECK-AAPCS-LABEL: define i16 @"kfun:#shortGlobal_compareAndExchangeField(){}
// CHECK-DEFAULTABI-LABEL: define signext i16 @"kfun:#shortGlobal_compareAndExchangeField(){}
// CHECK-WINDOWSX64-LABEL: define i16 @"kfun:#shortGlobal_compareAndExchangeField(){}
// CHECK: cmpxchg i16* @"kvar:shortGlobal#internal", i16 0, i16 1 seq_cst seq_cst
// CHECK: extractvalue { i16, i1 } %{{[0-9]+}}, 0
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun shortGlobal_compareAndExchangeField() = ::shortGlobal.compareAndExchangeField(0.toShort(), 1.toShort())
// Int
fun intGlobal_getField() = intGlobal
fun intGlobal_setField() { intGlobal = 0 }
// CHECK-LABEL: define i32 @"kfun:#intGlobal_getAndSetField(){}
// CHECK: atomicrmw xchg i32* @"kvar:intGlobal#internal", i32 0 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intGlobal_getAndSetField() = ::intGlobal.getAndSetField(0)
// CHECK-LABEL: define i32 @"kfun:#intGlobal_getAndAddField(){}
// CHECK: atomicrmw add i32* @"kvar:intGlobal#internal", i32 0 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intGlobal_getAndAddField() = ::intGlobal.getAndAddField(0)
// CHECK-AAPCS-LABEL: define i1 @"kfun:#intGlobal_compareAndSetField(){}
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#intGlobal_compareAndSetField(){}
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#intGlobal_compareAndSetField(){}
// CHECK: cmpxchg i32* @"kvar:intGlobal#internal", i32 0, i32 1 seq_cst seq_cst
// CHECK: extractvalue { i32, i1 } %{{[0-9]+}}, 1
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intGlobal_compareAndSetField() = ::intGlobal.compareAndSetField(0, 1)
// CHECK-LABEL: define i32 @"kfun:#intGlobal_compareAndExchangeField(){}
// CHECK: cmpxchg i32* @"kvar:intGlobal#internal", i32 0, i32 1 seq_cst seq_cst
// CHECK: extractvalue { i32, i1 } %{{[0-9]+}}, 0
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intGlobal_compareAndExchangeField() = ::intGlobal.compareAndExchangeField(0, 1)
// Long
fun longGlobal_getField() = longGlobal
fun longGlobal_setField() { longGlobal = 0 }
// CHECK-LABEL: define i64 @"kfun:#longGlobal_getAndSetField(){}
// CHECK: atomicrmw xchg i64* @"kvar:longGlobal#internal", i64 0 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longGlobal_getAndSetField() = ::longGlobal.getAndSetField(0L)
// CHECK-LABEL: define i64 @"kfun:#longGlobal_getAndAddField(){}
// CHECK: atomicrmw add i64* @"kvar:longGlobal#internal", i64 0 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longGlobal_getAndAddField() = ::longGlobal.getAndAddField(0L)
// CHECK-AAPCS-LABEL: define i1 @"kfun:#longGlobal_compareAndSetField(){}
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#longGlobal_compareAndSetField(){}
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#longGlobal_compareAndSetField(){}
// CHECK: cmpxchg i64* @"kvar:longGlobal#internal", i64 0, i64 1 seq_cst seq_cst
// CHECK: extractvalue { i64, i1 } %{{[0-9]+}}, 1
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longGlobal_compareAndSetField() = ::longGlobal.compareAndSetField(0L, 1L)
// CHECK-LABEL: define i64 @"kfun:#longGlobal_compareAndExchangeField(){}
// CHECK: cmpxchg i64* @"kvar:longGlobal#internal", i64 0, i64 1 seq_cst seq_cst
// CHECK: extractvalue { i64, i1 } %{{[0-9]+}}, 0
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longGlobal_compareAndExchangeField() = ::longGlobal.compareAndExchangeField(0L, 1L)
// Boolean
fun booleanGlobal_getField() = booleanGlobal
fun booleanGlobal_setField() { booleanGlobal = false }
// CHECK-AAPCS-LABEL: define i1 @"kfun:#booleanGlobal_getAndSetField(){}kotlin.Boolean"
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#booleanGlobal_getAndSetField(){}kotlin.Boolean"
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#booleanGlobal_getAndSetField(){}kotlin.Boolean"
// CHECK: atomicrmw xchg i8* @"kvar:booleanGlobal#internal", i8 %{{[0-9]+}} seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun booleanGlobal_getAndSetField() = ::booleanGlobal.getAndSetField(false)
// CHECK-AAPCS-LABEL: define i1 @"kfun:#booleanGlobal_compareAndSetField(){}
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#booleanGlobal_compareAndSetField(){}
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#booleanGlobal_compareAndSetField(){}
// CHECK: cmpxchg i8* @"kvar:booleanGlobal#internal", i8 %{{[0-9]+}}, i8 %{{[0-9]+}} seq_cst seq_cst
// CHECK: extractvalue { i8, i1 } %{{[0-9]+}}, 1
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun booleanGlobal_compareAndSetField() = ::booleanGlobal.compareAndSetField(false, true)
// CHECK-AAPCS-LABEL: define i1 @"kfun:#booleanGlobal_compareAndExchangeField(){}
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#booleanGlobal_compareAndExchangeField(){}
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#booleanGlobal_compareAndExchangeField(){}
// CHECK: cmpxchg i8* @"kvar:booleanGlobal#internal", i8 %{{[0-9]+}}, i8 %{{[0-9]+}} seq_cst seq_cst
// CHECK: extractvalue { i8, i1 } %{{[0-9]+}}, 0
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun booleanGlobal_compareAndExchangeField() = ::booleanGlobal.compareAndExchangeField(false, true)
// IntArray
val intArr = IntArray(2)
// CHECK-LABEL: define i32 @"kfun:#intArr_atomicGet(){}kotlin.Int"()
// CHECK: call i32* @Kotlin_intArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: load atomic i32, i32* %{{[0-9]+}} seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intArr_atomicGet() = intArr.atomicGet(0)
// CHECK-LABEL: define void @"kfun:#intArr_atomicSet(){}"()
// CHECK: call i32* @Kotlin_intArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: store atomic i32 1, i32* %{{[0-9]+}} seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intArr_atomicSet() = intArr.atomicSet(0, 1)
// CHECK-LABEL: define i32 @"kfun:#intArr_getAndSet(){}kotlin.Int"()
// CHECK: call i32* @Kotlin_intArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: atomicrmw xchg i32* %{{[0-9]+}}, i32 1 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intArr_getAndSet() = intArr.getAndSet(0, 1)
// CHECK-LABEL: define i32 @"kfun:#intArr_getAndAdd(){}kotlin.Int"()
// CHECK: call i32* @Kotlin_intArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: atomicrmw add i32* %{{[0-9]+}}, i32 1 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intArr_getAndAdd() = intArr.getAndAdd(0, 1)
// CHECK-LABEL: define i32 @"kfun:#intArr_compareAndExchange(){}kotlin.Int"()
// CHECK: call i32* @Kotlin_intArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: cmpxchg i32* %{{[0-9]+}}, i32 1, i32 2 seq_cst seq_cst
// CHECK: extractvalue { i32, i1 } %{{[0-9]+}}, 0
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intArr_compareAndExchange() = intArr.compareAndExchange(0, 1, 2)
// CHECK-AAPCS-LABEL: define i1 @"kfun:#intArr_compareAndSet(){}kotlin.Boolean"()
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#intArr_compareAndSet(){}kotlin.Boolean"()
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#intArr_compareAndSet(){}kotlin.Boolean"()
// CHECK: call i32* @Kotlin_intArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: cmpxchg i32* %{{[0-9]+}}, i32 1, i32 2 seq_cst seq_cst
// CHECK: extractvalue { i32, i1 } %{{[0-9]+}}, 1
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intArr_compareAndSet() = intArr.compareAndSet(0, 1, 2)
// LongArray
val longArr = LongArray(2)
// CHECK-LABEL: define i64 @"kfun:#longArr_atomicGet(){}kotlin.Long"()
// CHECK: call i64* @Kotlin_longArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: load atomic i64, i64* %{{[0-9]+}} seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longArr_atomicGet() = longArr.atomicGet(0)
// CHECK-LABEL: define void @"kfun:#longArr_atomicSet(){}"()
// CHECK: call i64* @Kotlin_longArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: store atomic i64 1, i64* %{{[0-9]+}} seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longArr_atomicSet() = longArr.atomicSet(0, 1L)
// CHECK-LABEL: define i64 @"kfun:#longArr_getAndSet(){}kotlin.Long"()
// CHECK: call i64* @Kotlin_longArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: atomicrmw xchg i64* %{{[0-9]+}}, i64 1 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longArr_getAndSet() = longArr.getAndSet(0, 1L)
// CHECK-LABEL: define i64 @"kfun:#longArr_getAndAdd(){}kotlin.Long"()
// CHECK: call i64* @Kotlin_longArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: atomicrmw add i64* %{{[0-9]+}}, i64 1 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longArr_getAndAdd() = longArr.getAndAdd(0, 1L)
// CHECK-LABEL: define i64 @"kfun:#longArr_compareAndExchange(){}kotlin.Long"()
// CHECK: call i64* @Kotlin_longArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: cmpxchg i64* %{{[0-9]+}}, i64 1, i64 2 seq_cst seq_cst
// CHECK: extractvalue { i64, i1 } %{{[0-9]+}}, 0
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longArr_compareAndExchange() = longArr.compareAndExchange(0, 1L, 2L)
// CHECK-AAPCS-LABEL: define i1 @"kfun:#longArr_compareAndSet(){}kotlin.Boolean"()
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#longArr_compareAndSet(){}kotlin.Boolean"()
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#longArr_compareAndSet(){}kotlin.Boolean"()
// CHECK: call i64* @Kotlin_longArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: cmpxchg i64* %{{[0-9]+}}, i64 1, i64 2 seq_cst seq_cst
// CHECK: extractvalue { i64, i1 } %{{[0-9]+}}, 1
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longArr_compareAndSet() = longArr.compareAndSet(0, 1L, 2L)
// Array<T>
val refArr = arrayOfNulls<String?>(2)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#refArr_atomicGet(){}kotlin.String?"
// CHECK: call %struct.ObjHeader** @Kotlin_arrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: load atomic %struct.ObjHeader*, %struct.ObjHeader** %{{[0-9]+}} seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun refArr_atomicGet() = refArr.atomicGet(0)
// CHECK-LABEL: define void @"kfun:#refArr_atomicSet(){}"()
// CHECK: call %struct.ObjHeader** @Kotlin_arrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: call void @UpdateVolatileHeapRef(%struct.ObjHeader** %{{[0-9]+}}, %struct.ObjHeader* null)
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun refArr_atomicSet() = refArr.atomicSet(0, null)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#refArr_getAndSet(){}kotlin.String?"
// CHECK: call %struct.ObjHeader** @Kotlin_arrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: call %struct.ObjHeader* @GetAndSetVolatileHeapRef(%struct.ObjHeader** %{{[0-9]+}}, %struct.ObjHeader* null, %struct.ObjHeader** %{{[0-9]+}})
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun refArr_getAndSet() = refArr.getAndSet(0, null)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#refArr_compareAndExchange(){}kotlin.String?"
// CHECK: call %struct.ObjHeader** @Kotlin_arrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: call %struct.ObjHeader* @CompareAndSwapVolatileHeapRef(%struct.ObjHeader** %{{[0-9]+}}, %struct.ObjHeader* null, %struct.ObjHeader* null, %struct.ObjHeader** %{{[0-9]+}})
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun refArr_compareAndExchange() = refArr.compareAndExchange(0, null, null)
// CHECK-AAPCS-LABEL: define i1 @"kfun:#refArr_compareAndSet(){}kotlin.Boolean"()
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#refArr_compareAndSet(){}kotlin.Boolean"()
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#refArr_compareAndSet(){}kotlin.Boolean"()
// CHECK: call %struct.ObjHeader** @Kotlin_arrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK-AAPCS: call i1 @CompareAndSetVolatileHeapRef(%struct.ObjHeader** %{{[0-9]+}}, %struct.ObjHeader* null, %struct.ObjHeader* null)
// CHECK-DEFAULTABI: call zeroext i1 @CompareAndSetVolatileHeapRef(%struct.ObjHeader** %{{[0-9]+}}, %struct.ObjHeader* null, %struct.ObjHeader* null)
// CHECK-WINDOWSX64: call zeroext i1 @CompareAndSetVolatileHeapRef(%struct.ObjHeader** %{{[0-9]+}}, %struct.ObjHeader* null, %struct.ObjHeader* null)
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun refArr_compareAndSet() = refArr.compareAndSet(0, null, null)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
byteGlobal_getField()
byteGlobal_setField()
byteGlobal_getAndSetField()
byteGlobal_getAndAddField()
byteGlobal_compareAndSetField()
byteGlobal_compareAndExchangeField()
shortGlobal_getField()
shortGlobal_setField()
shortGlobal_getAndSetField()
shortGlobal_getAndAddField()
shortGlobal_compareAndSetField()
shortGlobal_compareAndExchangeField()
intGlobal_getField()
intGlobal_setField()
intGlobal_getAndSetField()
intGlobal_getAndAddField()
intGlobal_compareAndSetField()
intGlobal_compareAndExchangeField()
longGlobal_getField()
longGlobal_setField()
longGlobal_getAndSetField()
longGlobal_getAndAddField()
longGlobal_compareAndSetField()
longGlobal_compareAndExchangeField()
booleanGlobal_getField()
booleanGlobal_setField()
booleanGlobal_getAndSetField()
booleanGlobal_compareAndSetField()
booleanGlobal_compareAndExchangeField()
intArr_atomicGet()
intArr_atomicSet()
intArr_getAndSet()
intArr_getAndAdd()
intArr_compareAndSet()
intArr_compareAndExchange()
longArr_atomicGet()
longArr_atomicSet()
longArr_getAndSet()
longArr_getAndAdd()
longArr_compareAndSet()
longArr_compareAndExchange()
refArr_atomicGet()
refArr_atomicSet()
refArr_getAndSet()
refArr_compareAndSet()
refArr_compareAndExchange()
return "OK"
}
+338
View File
@@ -0,0 +1,338 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// CHECK-LABEL: define void @"kfun:#forEachIndicies(){}"()
fun forEachIndicies() {
val array = Array(10) { 0 }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in array.indices) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forUntilSize(){}"()
fun forUntilSize() {
val array = Array(10) { 0L }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0 until array.size) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forRangeUntilSize(){}"()
@ExperimentalStdlibApi
fun forRangeUntilSize() {
val array = Array(10) { 0L }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0..<array.size) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forDownToSize(){}"()
fun forDownToSize() {
val array = Array(10) { 0L }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in array.size - 1 downTo 0) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
// CHECK: {{^}}do_while_loop{{.*}}:
for (j in array.size - 3 downTo 0) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[j] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forRangeToSize(){}"()
fun forRangeToSize() {
val array = Array(10) { 0L }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0..array.size - 1) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
val length = array.size - 1
// CHECK: {{^}}do_while_loop{{.*}}:
for (j in 0..length) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[j] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forRangeToWithStep(){}"()
fun forRangeToWithStep() {
val array = Array(10) { 0L }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0..array.size - 1 step 2) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forUntilWithStep(){}"()
fun forUntilWithStep() {
val array = CharArray(10) { '0' }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0 until array.size step 2) {
// CHECK: {{call|invoke}} void @Kotlin_CharArray_set_without_BoundCheck
array[i] = '6'
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forRangeUntilWithStep(){}"()
@ExperimentalStdlibApi
fun forRangeUntilWithStep() {
val array = CharArray(10) { '0' }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0..<array.size step 2) {
// CHECK: {{call|invoke}} void @Kotlin_CharArray_set_without_BoundCheck
array[i] = '6'
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forDownToWithStep(){}"()
fun forDownToWithStep() {
val array = UIntArray(10) { 0U }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in array.size - 1 downTo 0 step 2) {
// CHECK: {{call|invoke}} void @Kotlin_IntArray_set_without_BoundCheck
array[i] = 6U
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forIndiciesWithStep(){}"()
fun forIndiciesWithStep() {
val array = Array(10) { 0L }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in array.indices step 2) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forWithIndex(){}"()
fun forWithIndex() {
val array = Array(10) { 100 }
// CHECK: {{^}}while_loop{{.*}}:
for ((index, value) in array.withIndex()) {
// CHECK: {{call|invoke}} %struct.ObjHeader* @Kotlin_Array_get_without_BoundCheck
array[index] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forReversed(){}"()
fun forReversed() {
val array = Array(10) { 100 }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in (0..array.size-1).reversed()) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forRangeUntilReversed(){}"()
@ExperimentalStdlibApi
fun forRangeUntilReversed() {
val array = Array(10) { 100 }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in (0..<array.size).reversed()) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
fun foo(a: Int, b : Int): Int = a + b * 2
// CHECK-LABEL: define void @"kfun:#forEachCall(){}"()
fun forEachCall() {
val array = Array(10) { 100 }
var sum = 0
// CHECK: {{^}}while_loop{{.*}}:
array.forEach {
// CHECK: {{call|invoke}} %struct.ObjHeader* @Kotlin_Array_get_without_BoundCheck
sum += it
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forLoop(){}"()
fun forLoop() {
val array = Array(10) { 100 }
var sum = 0
// CHECK: {{^}}while_loop{{.*}}:
for (it in array) {
// CHECK: {{call|invoke}} %struct.ObjHeader* @Kotlin_Array_get_without_BoundCheck
sum += it
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#innerLoop(){}"()
fun innerLoop() {
val array = Array(10) { 100 }
val array1 = Array(3) { 0 }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0 until array.size) {
// CHECK-DAG: {{call|invoke}} %struct.ObjHeader* @Kotlin_Array_get_without_BoundCheck
array[i] = 7
// CHECK-DAG: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
// CHECK-DAG: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
for (j in 0 until array1.size) {
array1[j] = array[i]
}
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#argsInFunctionCall(){}"()
fun argsInFunctionCall() {
val array = Array(10) { 100 }
val size = array.size - 1
val size1 = size
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0..size1) {
// CHECK: {{call|invoke}} %struct.ObjHeader* @Kotlin_Array_get_without_BoundCheck
// CHECK: {{call|invoke}} %struct.ObjHeader* @Kotlin_Array_get_without_BoundCheck
// CHECK: {{call|invoke}} i32 @"kfun:#foo(kotlin.Int;kotlin.Int){}kotlin.Int"
foo(array[i], array[i])
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#smallLoop(){}"()
fun smallLoop() {
val array = Array(10) { 100 }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0..array.size - 2) {
// CHECK: {{call|invoke}} %struct.ObjHeader* @Kotlin_Array_get_without_BoundCheck
array[i+1] = array[i]
}
}
// CHECK-LABEL: {{^}}epilogue:
object TopLevelObject {
val array = Array(10) { 100 }
}
// CHECK-LABEL: define void @"kfun:#topLevelObject(){}"()
fun topLevelObject() {
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0 until TopLevelObject.array.size) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
TopLevelObject.array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
val array = Array(10) { 100 }
// CHECK-LABEL: define void @"kfun:#topLevelProperty(){}"()
fun topLevelProperty() {
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0..array.size - 2) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
open class Base() {
open val array = Array(10) { 100 }
}
class Child() : Base()
// CHECK-LABEL: define void @"kfun:#childClassWithFakeOverride(){}"()
fun childClassWithFakeOverride() {
val child = Child()
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0..child.array.size - 1) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
child.array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
class First {
val child = Child()
}
class Second{
val first = First()
}
class Third {
val second = Second()
}
// CHECK-LABEL: define void @"kfun:#chainedReceivers(){}"()
fun chainedReceivers() {
val obj = Third()
val obj1 = obj
val obj2 = obj1
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0 until obj1.second.first.child.array.size) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
obj2.second.first.child.array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
@ExperimentalStdlibApi
fun box(): String {
forEachIndicies()
forUntilSize()
forRangeUntilSize()
forDownToSize()
forRangeToSize()
forRangeToWithStep()
forUntilWithStep()
forRangeUntilWithStep()
forDownToWithStep()
forIndiciesWithStep()
forWithIndex()
forReversed()
forRangeUntilReversed()
forEachCall()
forLoop()
innerLoop()
argsInFunctionCall()
smallLoop()
topLevelObject()
topLevelProperty()
childClassWithFakeOverride()
chainedReceivers()
return "OK"
}
@@ -0,0 +1,73 @@
// TARGET_BACKEND: NATIVE
// DISABLE_NATIVE: isAppleTarget=false
// FILECHECK_STAGE: CStubs
// MODULE: cinterop
// FILE: direct.def
language = Objective-C
headers = direct.h
headerFilter = direct.h
// FILE: direct.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface CallingConventions : NSObject
+ (uint64_t)regular:(uint64_t)arg;
- (uint64_t)regular:(uint64_t)arg;
+ (uint64_t)direct:(uint64_t)arg __attribute__((objc_direct));
- (uint64_t)direct:(uint64_t)arg __attribute__((objc_direct));
@end
NS_ASSUME_NONNULL_END
// FILE: direct.m
#import "direct.h"
#define TEST_METHOD_IMPL(NAME) (uint64_t)NAME:(uint64_t)arg { return arg; }
@implementation CallingConventions : NSObject
+ TEST_METHOD_IMPL(regular);
- TEST_METHOD_IMPL(regular);
+ TEST_METHOD_IMPL(direct);
- TEST_METHOD_IMPL(direct);
@end
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
import kotlin.native.Retain
import direct.*
// KT-54610
fun box(): String {
callDirect()
callRegular()
return "OK"
}
@Retain
//CHECK-LABEL: define i64 @"kfun:#callDirect(){}kotlin.ULong"()
fun callDirect(): ULong {
val cc = CallingConventions()
//CHECK: invoke i64 @_{{[a-zA-Z0-9]+}}_knbridge{{[0-9]+}}(i8* %{{[0-9]+}}, i64 42)
return cc.direct(42uL)
}
@Retain
//CHECK-LABEL: define i64 @"kfun:#callRegular(){}kotlin.ULong"()
fun callRegular(): ULong {
val cc = CallingConventions()
//CHECK: invoke i64 @_{{[a-zA-Z0-9]+}}_knbridge{{[0-9]+}}(i8* %{{[0-9]+}}, i8* %{{[0-9]+}}, i64 42)
return cc.regular(42uL)
}
@@ -0,0 +1,168 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use
* of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// MODULE: cinterop
// FILE: signext_zeroext_interop_input.def
---
char char_id(char c) {
return c;
}
unsigned char unsigned_char_id(unsigned char c) {
return c;
}
short short_id(short s) {
return s;
}
unsigned short unsigned_short_id(unsigned short s) {
return s;
}
int callbackUser(int (*fn)(int, short)) {
return fn(5,5);
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import signext_zeroext_interop_input.*
import kotlinx.cinterop.*
// CHECK-DEFAULTABI-CACHE_NO: declare zeroext i1 @Kotlin_Char_isHighSurrogate(i16 zeroext){{.*}}
// CHECK-AAPCS-CACHE_NO: declare i1 @Kotlin_Char_isHighSurrogate(i16)
// CHECK-WINDOWSX64-CACHE_NO: declare zeroext i1 @Kotlin_Char_isHighSurrogate(i16)
// Check that we pass attributes to functions imported from runtime.
// CHECK-LABEL: void @"kfun:#checkRuntimeFunctionImport(){}"()
fun checkRuntimeFunctionImport() {
// CHECK-DEFAULTABI: call zeroext i1 @Kotlin_Char_isHighSurrogate(i16 zeroext {{.*}})
// CHECK-AAPCS: call i1 @Kotlin_Char_isHighSurrogate(i16 {{.*}})
// CHECK-WINDOWSX64: call zeroext i1 @Kotlin_Char_isHighSurrogate(i16 {{.*}})
'c'.isHighSurrogate()
// CHECK-DEFAULTABI: call zeroext i1 @Kotlin_Float_isNaN(float {{.*}}
// CHECK-AAPCS: call i1 @Kotlin_Float_isNaN(float {{.*}}
// CHECK-WINDOWSX64: call zeroext i1 @Kotlin_Float_isNaN(float {{.*}}
0.0f.isNaN()
}
// CHECK-LABEL: void @"kfun:#checkDirectInterop(){}"()
// CHECK-LABEL-AAPCS: void @"kfun:#checkDirectInterop(){}"()
// CHECK-LABEL-WINDOWSX64: void @"kfun:#checkDirectInterop(){}"()
fun checkDirectInterop() {
// compiler generates quite lovely names for bridges
// (e.g. `_66696c65636865636b5f7369676e6578745f7a65726f6578745f696e7465726f70_knbridge0`),
// so we don't check exact function names here.
// CHECK-DEFAULTABI: invoke signext i8 [[CHAR_ID_BRIDGE:@_.*_knbridge[0-9]+]](i8 signext {{.*}})
// CHECK-AAPCS: invoke i8 [[CHAR_ID_BRIDGE:@_.*_knbridge[0-9]+]](i8 {{.*}})
// CHECK-WINDOWSX64: invoke i8 [[CHAR_ID_BRIDGE:@_.*_knbridge[0-9]+]](i8 {{.*}})
char_id(0.toByte())
// CHECK-DEFAULTABI: invoke zeroext i8 [[UNSIGNED_CHAR_ID_BRIDGE:@_.*_knbridge[0-9]+]](i8 zeroext {{.*}})
// CHECK-AAPCS: invoke i8 [[UNSIGNED_CHAR_ID_BRIDGE:@_.*_knbridge[0-9]+]](i8 {{.*}})
// CHECK-WINDOWSX64: invoke i8 [[UNSIGNED_CHAR_ID_BRIDGE:@_.*_knbridge[0-9]+]](i8 {{.*}})
unsigned_char_id(0.toUByte())
// CHECK-DEFAULTABI: invoke signext i16 [[SHORT_ID_BRIDGE:@_.*_knbridge[0-9]+]](i16 signext {{.*}})
// CHECK-AAPCS: invoke i16 [[SHORT_ID_BRIDGE:@_.*_knbridge[0-9]+]](i16 {{.*}})
// CHECK-WINDOWSX64: invoke i16 [[SHORT_ID_BRIDGE:@_.*_knbridge[0-9]+]](i16 {{.*}})
short_id(0.toShort())
// CHECK-DEFAULTABI: invoke zeroext i16 [[UNSIGNED_SHORT_ID_BRIDGE:@_.*_knbridge[0-9]+]](i16 zeroext {{.*}})
// CHECK-AAPCS: invoke i16 [[UNSIGNED_SHORT_ID_BRIDGE:@_.*_knbridge[0-9]+]](i16 {{.*}})
// CHECK-WINDOWSX64: invoke i16 [[UNSIGNED_SHORT_ID_BRIDGE:@_.*_knbridge[0-9]+]](i16 {{.*}})
unsigned_short_id(0.toUShort())
// CHECK-DEFAULTABI: invoke i32 [[CALLBACK_USER_BRIDGE:@_.*_knbridge[0-9]+]](i8* bitcast (i32 (i32, i16)* [[STATIC_C_FUNCTION_BRIDGE:@_.*_kncfun[0-9]+]] to i8*))
// CHECK-AAPCS: invoke i32 [[CALLBACK_USER_BRIDGE:@_.*_knbridge[0-9]+]](i8* bitcast (i32 (i32, i16)* [[STATIC_C_FUNCTION_BRIDGE:@_.*_kncfun[0-9]+]] to i8*))
// CHECK-WINDOWSX64: invoke i32 [[CALLBACK_USER_BRIDGE:@_.*_knbridge[0-9]+]](i8* bitcast (i32 (i32, i16)* [[STATIC_C_FUNCTION_BRIDGE:@_.*_kncfun[0-9]+]] to i8*))
callbackUser(staticCFunction { int: Int, short: Short -> int + short })
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
checkRuntimeFunctionImport()
checkDirectInterop()
return "OK"
}
// CHECK-DEFAULTABI-CACHE_STATIC_ONLY_DIST: declare zeroext i1 @Kotlin_Char_isHighSurrogate(i16 zeroext){{.*}}
// CHECK-AAPCS-CACHE_STATIC_ONLY_DIST: declare i1 @Kotlin_Char_isHighSurrogate(i16)
// CHECK-WINDOWSX64-CACHE_STATIC_ONLY_DIST: declare zeroext i1 @Kotlin_Char_isHighSurrogate(i16)
// CHECK-DEFAULTABI: signext i8 [[CHAR_ID_BRIDGE]](i8 signext %0)
// CHECK-DEFAULTABI: [[CHAR_ID_PTR:%[0-9]+]] = load i8 (i8)*, i8 (i8)** @{{.*char_id}}
// CHECK-DEFAULTABI: call signext i8 [[CHAR_ID_PTR]](i8 signext %0)
// CHECK-AAPCS: i8 [[CHAR_ID_BRIDGE]](i8 %0)
// CHECK-AAPCS: [[CHAR_ID_PTR:%[0-9]+]] = load i8 (i8)*, i8 (i8)** @{{.*char_id}}
// CHECK-AAPCS: call i8 [[CHAR_ID_PTR]](i8 %0)
// CHECK-WINDOWSX64: i8 [[CHAR_ID_BRIDGE]](i8 %0)
// CHECK-WINDOWSX64: [[CHAR_ID_PTR:%[0-9]+]] = load i8 (i8)*, i8 (i8)** @{{.*char_id}}
// CHECK-WINDOWSX64: call i8 [[CHAR_ID_PTR]](i8 %0)
// CHECK-DEFAULTABI: zeroext i8 [[UNSIGNED_CHAR_ID_BRIDGE]](i8 zeroext %0)
// CHECK-DEFAULTABI: [[UNSIGNED_CHAR_ID_PTR:%[0-9]+]] = load i8 (i8)*, i8 (i8)** @{{.*unsigned_char_id}}
// CHECK-DEFAULTABI: call zeroext i8 [[UNSIGNED_CHAR_ID_PTR]](i8 zeroext %0)
// CHECK-AAPCS: i8 [[UNSIGNED_CHAR_ID_BRIDGE]](i8 %0)
// CHECK-AAPCS: [[UNSIGNED_CHAR_ID_PTR:%[0-9]+]] = load i8 (i8)*, i8 (i8)** @{{.*unsigned_char_id}}
// CHECK-AAPCS: call i8 [[UNSIGNED_CHAR_ID_PTR]](i8 %0)
// CHECK-WINDOWSX64: i8 [[UNSIGNED_CHAR_ID_BRIDGE]](i8 %0)
// CHECK-WINDOWSX64: [[UNSIGNED_CHAR_ID_PTR:%[0-9]+]] = load i8 (i8)*, i8 (i8)** @{{.*unsigned_char_id}}
// CHECK-WINDOWSX64: call i8 [[UNSIGNED_CHAR_ID_PTR]](i8 %0)
// CHECK-DEFAULTABI: signext i16 [[SHORT_ID_BRIDGE]](i16 signext %0)
// CHECK-DEFAULTABI: [[SHORT_ID_PTR:%[0-9]+]] = load i16 (i16)*, i16 (i16)** @{{.*short_id}}
// CHECK-DEFAULTABI: call signext i16 [[SHORT_ID_PTR]](i16 signext %0)
// CHECK-AAPCS: i16 [[SHORT_ID_BRIDGE]](i16 %0)
// CHECK-AAPCS: [[SHORT_ID_PTR:%[0-9]+]] = load i16 (i16)*, i16 (i16)** @{{.*short_id}}
// CHECK-AAPCS: call i16 [[SHORT_ID_PTR]](i16 %0)
// CHECK-WINDOWSX64: i16 [[SHORT_ID_BRIDGE]](i16 %0)
// CHECK-WINDOWSX64: [[SHORT_ID_PTR:%[0-9]+]] = load i16 (i16)*, i16 (i16)** @{{.*short_id}}
// CHECK-WINDOWSX64: call i16 [[SHORT_ID_PTR]](i16 %0)
// CHECK-DEFAULTABI: zeroext i16 [[UNSIGNED_SHORT_ID_BRIDGE]](i16 zeroext %0)
// CHECK-DEFAULTABI: [[UNSIGNED_SHORT_ID_PTR:%[0-9]+]] = load i16 (i16)*, i16 (i16)** @{{.*unsigned_short_id}}
// CHECK-DEFAULTABI: call zeroext i16 [[UNSIGNED_SHORT_ID_PTR]](i16 zeroext %0)
// CHECK-AAPCS: i16 [[UNSIGNED_SHORT_ID_BRIDGE]](i16 %0)
// CHECK-AAPCS: [[UNSIGNED_SHORT_ID_PTR:%[0-9]+]] = load i16 (i16)*, i16 (i16)** @{{.*unsigned_short_id}}
// CHECK-AAPCS: call i16 [[UNSIGNED_SHORT_ID_PTR]](i16 %0)
// CHECK-WINDOWSX64: i16 [[UNSIGNED_SHORT_ID_BRIDGE]](i16 %0)
// CHECK-WINDOWSX64: [[UNSIGNED_SHORT_ID_PTR:%[0-9]+]] = load i16 (i16)*, i16 (i16)** @{{.*unsigned_short_id}}
// CHECK-WINDOWSX64: call i16 [[UNSIGNED_SHORT_ID_PTR]](i16 %0)
// CHECK-DEFAULTABI: i32 [[STATIC_C_FUNCTION_BRIDGE]](i32 %0, i16 signext %1)
// CHECK-DEFAULTABI: call i32 {{@_.*_knbridge[0-9]+}}(i32 %0, i16 signext %1)
// CHECK-AAPCS: i32 [[STATIC_C_FUNCTION_BRIDGE]](i32 %0, i16 %1)
// CHECK-AAPCS: call i32 {{@_.*_knbridge[0-9]+}}(i32 %0, i16 %1)
// CHECK-WINDOWSX64: i32 [[STATIC_C_FUNCTION_BRIDGE]](i32 %0, i16 %1)
// CHECK-WINDOWSX64: call i32 {{@_.*_knbridge[0-9]+}}(i32 %0, i16 %1)
// CHECK-DEFAULTABI: i32 [[CALLBACK_USER_BRIDGE]](i8* %0)
// CHECK-DEFAULTABI: [[CALLBACK_USER_PTR:%[0-9]+]] = load i32 (i8*)*, i32 (i8*)** @{{.*callbackUser}}
// CHECK-DEFAULTABI: call i32 [[CALLBACK_USER_PTR]](i8* %0)
// CHECK-AAPCS: i32 [[CALLBACK_USER_BRIDGE]](i8* %0)
// CHECK-AAPCS: [[CALLBACK_USER_PTR:%[0-9]+]] = load i32 (i8*)*, i32 (i8*)** @{{.*callbackUser}}
// CHECK-AAPCS: call i32 [[CALLBACK_USER_PTR]](i8* %0)
// CHECK-WINDOWSX64: i32 [[CALLBACK_USER_BRIDGE]](i8* %0)
// CHECK-WINDOWSX64: [[CALLBACK_USER_PTR:%[0-9]+]] = load i32 (i8*)*, i32 (i8*)** @{{.*callbackUser}}
// CHECK-WINDOWSX64: call i32 [[CALLBACK_USER_PTR]](i8* %0)
@@ -0,0 +1,26 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlin.reflect.*
// CHECK: [[REG_FOR_1024:@[0-9]+]] = internal unnamed_addr constant { %struct.ObjHeader, i32 } { %struct.ObjHeader { %struct.TypeInfo* {{.*}} }, i32 1024 }
// CHECK-NOT: internal unnamed_addr constant { %struct.ObjHeader, i32 } { %struct.ObjHeader { %struct.TypeInfo* {{.*}} }, i32 1024 }
// CHECK: internal unnamed_addr constant { %struct.ArrayHeader, [3 x %struct.ObjHeader*] } { %struct.ArrayHeader { %struct.TypeInfo* {{.*}}, i32 3 }, [3 x %struct.ObjHeader*] [%struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, i32 }, { %struct.ObjHeader, i32 }* [[REG_FOR_1024]], i32 0, i32 0), %struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, i32 }, { %struct.ObjHeader, i32 }* [[REG_FOR_2048:@[0-9]+]], i32 0, i32 0), %struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, i32 }, { %struct.ObjHeader, i32 }* [[REG_FOR_4096:@[0-9]+]], i32 0, i32 0)] }
// CHECK-NOT: internal unnamed_addr constant { %struct.ArrayHeader, [3 x %struct.ObjHeader*] } { %struct.ArrayHeader { %struct.TypeInfo* {{.*}}, i32 3 }, [3 x %struct.ObjHeader*] [%struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, i32 }, { %struct.ObjHeader, i32 }* [[REG_FOR_1024]], i32 0, i32 0), %struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, i32 }, { %struct.ObjHeader, i32 }* [[REG_FOR_2048]], i32 0, i32 0), %struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, i32 }, { %struct.ObjHeader, i32 }* [[REG_FOR_4096]], i32 0, i32 0)] }
// CHECK: internal unnamed_addr constant { %struct.ObjHeader, %struct.ObjHeader*, %struct.ObjHeader*, i1 } { %struct.ObjHeader { %struct.TypeInfo* {{.*}} }, %struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, i8* }, { %struct.ObjHeader, i8* }* [[REG_FOR_CLASSIFIER_FIELD:@[0-9]+]], i32 0, i32 0), %struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, %struct.ObjHeader*, %struct.ObjHeader* }, { %struct.ObjHeader, %struct.ObjHeader*, %struct.ObjHeader* }* [[REG_FOR_ARGUMENTS_FIELD:@[0-9]+]], i32 0, i32 0), i1 false }
// CHECK-NOT: internal unnamed_addr constant { %struct.ObjHeader, %struct.ObjHeader*, %struct.ObjHeader*, i1 } { %struct.ObjHeader { %struct.TypeInfo* {{.*}} }, %struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, i8* }, { %struct.ObjHeader, i8* }* [[REG_FOR_CLASSIFIER_FIELD]], i32 0, i32 0), %struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, %struct.ObjHeader*, %struct.ObjHeader* }, { %struct.ObjHeader, %struct.ObjHeader*, %struct.ObjHeader* }* [[REG_FOR_ARGUMENTS_FIELD]], i32 0, i32 0), i1 false }
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
println(1024)
println(1024)
println(arrayOf(1024, 2048, 4096))
println(arrayOf(1024, 2048, 4096))
println(typeOf<Map<String, String>>())
println(typeOf<Map<String, String>>())
return "OK"
}
@@ -0,0 +1,35 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
value class A(val i: Int)
value class B(val a: A)
value class C(val s: String)
fun defaultInt(a: Int = 1, aa: Int = 1) = a
fun defaultA(a: A = A(1), aa: A = A(1)) = a.i
fun defaultB(b: B = B(A(1)), bb: B = B(A(1))) = b.a.i
fun defaultC(c: C = C("1"), cc: C = C("1")) = c.s
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
// CHECK-LABEL: entry
// CHECK-NOT: <Int-box>
// CHECK-NOT: <A-box>
// CHECK-NOT: <B-box>
// CHECK-NOT: <C-box>
defaultInt()
defaultA()
defaultB()
defaultC()
defaultInt(1)
defaultA(A(1))
defaultB(B(A(1)))
defaultC(C("1"))
defaultInt(1, 1)
defaultA(A(1), A(1))
defaultB(B(A(1)), B(A(1)))
defaultC(C("1"), C("1"))
// CHECK-LABEL: epilogue:
return "OK"
}
@@ -0,0 +1,28 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
enum class COLOR {
RED,
GREEN,
BLUE
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
for (i in COLOR.values()) {
// CHECK-DEBUG: = call i32 @"kfun:kotlin.Enum#<get-ordinal>(){}kotlin.Int"(
// We inline .ordinal property access in case of opt build, so check direct field load instead.
// CHECK-OPT: getelementptr inbounds %"kclassbody:kotlin.Enum#internal", %"kclassbody:kotlin.Enum#internal"* %{{[0-9a-z]*}}, i32 0, i32 2
print(when (i) {
// we can't check the register is same, because it can be saved on stack and loaded back
// CHECK: icmp eq i32 %{{[0-9a-z]*}}, 0
COLOR.RED -> 0xff0000
// CHECK: icmp eq i32 %{{[0-9a-z]*}}, 1
COLOR.GREEN -> 0x00ff00
// CHECK: icmp eq i32 %{{[0-9a-z]*}}, 2
COLOR.BLUE -> 0x0000ff
})
}
// CHECK-LABEL: epilogue:
return "OK"
}
@@ -0,0 +1,14 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
class A(val x: Int)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
// CHECK-DEBUG: call %struct.ObjHeader* @AllocInstance
// CHECK-OPT: alloca %"kclassbody:A#internal"
val a = A(5)
println(a.x)
// CHECK-LABEL: epilogue:
return "OK"
}
@@ -0,0 +1,8 @@
// TARGET_BACKEND: NATIVE
// IGNORE_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// The check below is intentionally wrong and must fail.
// Test system should report test as passed due to IGNORE_BACKEND directive above.
// CHECK-LABEL: NONEXISTENT
fun box(): String = "OK"
@@ -0,0 +1,19 @@
// TARGET_BACKEND: NATIVE
// Perform check after optimization pipeline because
// LLVM might infer attributes.
// FILECHECK_STAGE: LTOBitcodeOptimization
// NB: This is not a good test.
// What we actually want to check is that Kotlin/Native compiler is able to produce "big"
// binaries for 32-bit Apple Watch target. The problem is that such test is very-very-very
// slow to compile (~20 min on a local machine) which is not acceptable for CI.
//
// Instead, here we check that none of the module's functions are compiled in the Thumb mode.
// BL instructions in thumb mode have smaller ranges which causes "relocation out of range" failure.
// CHECK-WATCHOS_ARM32: target triple = "armv7k-apple-watchos2{{.+}}"
fun box() = "OK"
// CHECK-NOT: attributes #{{[0-9]+}} = { {{.+}}+thumb-mode{{.+}} }
@@ -0,0 +1,27 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// CHECK: declare void @ThrowException(%struct.ObjHeader*) #[[THROW_EXCEPTION_DECLARATION_ATTRIBUTES:[0-9]+]]
// CHECK: void @"kfun:#flameThrower(){}kotlin.Nothing"() #[[FLAME_THROWER_DECLARATION_ATTRIBUTES:[0-9]+]]
fun flameThrower(): Nothing {
// CHECK: call void @ThrowException(%struct.ObjHeader* {{.*}}) #[[THROW_EXCEPTION_CALLSITE_ATTRIBUTES:[0-9]+]]
throw Throwable("🔥")
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
// CHECK: invoke void @"kfun:#flameThrower(){}kotlin.Nothing"() #[[FLAME_THROWER_CALLSITE_ATTRIBUTES:[0-9]+]]
try {
flameThrower()
} catch (e: Throwable) {
return "OK"
}
return "FAIL: Uncaught exception"
}
// CHECK-DAG: attributes #[[THROW_EXCEPTION_DECLARATION_ATTRIBUTES]] = {{{.*}}noreturn{{.*}}}
// CHECK-DAG: attributes #[[THROW_EXCEPTION_CALLSITE_ATTRIBUTES]] = {{{.*}}noreturn{{.*}}}
// CHECK-DAG: attributes #[[FLAME_THROWER_DECLARATION_ATTRIBUTES]] = {{{.*}}noreturn{{.*}}}
// CHECK-DAG: attributes #[[FLAME_THROWER_CALLSITE_ATTRIBUTES]] = {{{.*}}noreturn{{.*}}}
@@ -0,0 +1,132 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlin.reflect.KFunction2
fun <StringifyTP> stringify(collection: StringifyTP, size: (StringifyTP) -> Int, get: StringifyTP.(Int) -> Any?): String {
var res = "["
for (i in 0 until size(collection)) {
if (i > 0) res += ", "
res += collection.get(i).toString()
}
res += "]"
return res
}
interface I
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#stringifyArray(kotlin.Array<0:0>){0\C2\A7<I>}kotlin.String"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader** {{%[0-9]+}})
fun <StringifyArrayTP : I> stringifyArray(array: Array<StringifyArrayTP>) =
// CHECK: call %struct.ObjHeader* @"kfun:#stringify(0:0;kotlin.Function1<0:0,kotlin.Int>;kotlin.Function2<0:0,kotlin.Int,kotlin.Any?>){0\C2\A7<kotlin.Any?>}kotlin.String"
stringify(
array,
{ it.size }, // $stringifyArray$lambda$0$FUNCTION_REFERENCE$0
Array<*>::get // $get$FUNCTION_REFERENCE$1
)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#stringifyIntArray(kotlin.Array<kotlin.Int>){}kotlin.String"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader** {{%[0-9]+}})
fun stringifyIntArray(array: Array<Int>) =
// CHECK: call %struct.ObjHeader* @"kfun:#stringify(0:0;kotlin.Function1<0:0,kotlin.Int>;kotlin.Function2<0:0,kotlin.Int,kotlin.Any?>){0\C2\A7<kotlin.Any?>}kotlin.String"
stringify(
array,
{ it.size }, // $stringifyIntArray$lambda$1$FUNCTION_REFERENCE$2
Array<Int>::get // $get$FUNCTION_REFERENCE$3
)
class N(val v: Int) : I {
override fun toString() = v.toString()
}
@Suppress("UNUSED_PARAMETER")
fun <BazTP0, BazTP1> foo(p1: BazTP0, p2: BazTP1) {}
fun <QuxTP> bar() {
val ref: KFunction2<QuxTP, QuxTP, Unit> = ::foo // $foo$FUNCTION_REFERENCE$4
println(ref)
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
println(stringifyArray(arrayOf(N(2), N(14))))
println(stringifyIntArray(arrayOf(1, 2, 3)))
bar<Int>()
bar<String>()
val ref: KFunction2<Int, Int, Unit> = ::foo // $foo$FUNCTION_REFERENCE$5
println(ref)
return "OK"
}
// CHECK-LABEL: define internal i32 @"kfun:$stringifyArray$lambda$0$FUNCTION_REFERENCE$0.invoke#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$stringifyArray$lambda$0$FUNCTION_REFERENCE$0.<init>#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:$stringifyArray$lambda$0$FUNCTION_REFERENCE$0.$<bridge-BNNN>invoke(kotlin.Array<1:0>){}kotlin.Int#internal"
// CHECK-SAME: (%struct.ObjHeader* [[this:%[0-9]+]], %struct.ObjHeader* [[array:%[0-9]+]], %struct.ObjHeader** {{%[0-9]+}})
// CHECK-OPT: call i32 @"kfun:$stringifyArray$lambda$0$FUNCTION_REFERENCE$0.invoke#internal"(%struct.ObjHeader* [[this]], %struct.ObjHeader* [[array]])
// CHECK-DEBUG: call i32 @"kfun:$stringifyArray$lambda$0$FUNCTION_REFERENCE$0.invoke#internal"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:$get$FUNCTION_REFERENCE$1.invoke#internal"
// CHECK-SAME: (%struct.ObjHeader* [[this:%[0-9]+]], %struct.ObjHeader* [[array:%[0-9]+]], i32 [[index:%[0-9]+]], %struct.ObjHeader** [[ret:%[0-9]+]])
// CHECK-OPT: call %struct.ObjHeader* @Kotlin_Array_get(%struct.ObjHeader* [[array]], i32 [[index]], %struct.ObjHeader** [[ret]])
// CHECK-DEBUG: call %struct.ObjHeader* @Kotlin_Array_get(%struct.ObjHeader* {{%[0-9]+}}, i32 {{%[0-9]+}}, %struct.ObjHeader** {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$get$FUNCTION_REFERENCE$1.<init>#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:$get$FUNCTION_REFERENCE$1.$<bridge-NNNNB>invoke(kotlin.Array<*>;kotlin.Int){}kotlin.Any?#internal"
// CHECK-SAME: (%struct.ObjHeader* [[this:%[0-9]+]], %struct.ObjHeader* [[array:%[0-9]+]], %struct.ObjHeader* [[boxedIndex:%[0-9]+]], %struct.ObjHeader** [[ret:%[0-9]+]])
// CHECK-OPT: call %struct.ObjHeader* @"kfun:$get$FUNCTION_REFERENCE$1.invoke#internal"(%struct.ObjHeader* [[this]], %struct.ObjHeader* [[array]], i32 {{%[0-9]+}}, %struct.ObjHeader** [[ret]])
// CHECK-DEBUG: call %struct.ObjHeader* @"kfun:$get$FUNCTION_REFERENCE$1.invoke#internal"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}}, i32 {{%[0-9]+}}, %struct.ObjHeader** {{%[0-9]+}})
// CHECK-LABEL: define internal i32 @"kfun:$stringifyIntArray$lambda$1$FUNCTION_REFERENCE$2.invoke#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$stringifyIntArray$lambda$1$FUNCTION_REFERENCE$2.<init>#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:$stringifyIntArray$lambda$1$FUNCTION_REFERENCE$2.$<bridge-BNNN>invoke(kotlin.Array<kotlin.Int>){}kotlin.Int#internal"
// CHECK-SAME: (%struct.ObjHeader* [[this:%[0-9]+]], %struct.ObjHeader* [[array:%[0-9]+]], %struct.ObjHeader** {{%[0-9]+}})
// CHECK-OPT: call i32 @"kfun:$stringifyIntArray$lambda$1$FUNCTION_REFERENCE$2.invoke#internal"(%struct.ObjHeader* [[this]], %struct.ObjHeader* [[array]])
// CHECK-DEBUG: call i32 @"kfun:$stringifyIntArray$lambda$1$FUNCTION_REFERENCE$2.invoke#internal"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal i32 @"kfun:$get$FUNCTION_REFERENCE$3.invoke#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}}, i32 {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$get$FUNCTION_REFERENCE$3.<init>#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:$get$FUNCTION_REFERENCE$3.$<bridge-BNNNB>invoke(kotlin.Array<kotlin.Int>;kotlin.Int){}kotlin.Int#internal"
// CHECK-SAME: (%struct.ObjHeader* [[this:%[0-9]+]], %struct.ObjHeader* [[array:%[0-9]+]], %struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader** {{%[0-9]+}})
// CHECK-OPT: call i32 @"kfun:$get$FUNCTION_REFERENCE$3.invoke#internal"(%struct.ObjHeader* [[this]], %struct.ObjHeader* [[array]], i32 {{%[0-9]+}})
// CHECK-DEBUG: call i32 @"kfun:$get$FUNCTION_REFERENCE$3.invoke#internal"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}}, i32 {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$foo$FUNCTION_REFERENCE$4.invoke#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* [[p1:%[0-9]+]], %struct.ObjHeader* [[p2:%[0-9]+]])
// CHECK-OPT: call void @"kfun:#foo(0:0;0:1){0\C2\A7<kotlin.Any?>;1\C2\A7<kotlin.Any?>}"(%struct.ObjHeader* [[p1]], %struct.ObjHeader* [[p2]])
// CHECK-DEBUG: call void @"kfun:#foo(0:0;0:1){0\C2\A7<kotlin.Any?>;1\C2\A7<kotlin.Any?>}"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$foo$FUNCTION_REFERENCE$4.<init>#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:$foo$FUNCTION_REFERENCE$4.$<bridge-UNNNN>invoke(1:0;1:0){}#internal"
// CHECK-SAME: (%struct.ObjHeader* [[this:%[0-9]+]], %struct.ObjHeader* [[p1:%[0-9]+]], %struct.ObjHeader* [[p2:%[0-9]+]], %struct.ObjHeader** {{%[0-9]+}})
// CHECK-OPT: call void @"kfun:$foo$FUNCTION_REFERENCE$4.invoke#internal"(%struct.ObjHeader* [[this]], %struct.ObjHeader* [[p1]], %struct.ObjHeader* [[p2]])
// CHECK-DEBUG: call void @"kfun:$foo$FUNCTION_REFERENCE$4.invoke#internal"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$foo$FUNCTION_REFERENCE$5.invoke#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[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?>}"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$foo$FUNCTION_REFERENCE$5.<init>#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:$foo$FUNCTION_REFERENCE$5.$<bridge-UNNBB>invoke(kotlin.Int;kotlin.Int){}#internal"
// CHECK-SAME: (%struct.ObjHeader* [[this:%[0-9]+]], %struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader** {{%[0-9]+}})
// CHECK-OPT: call void @"kfun:$foo$FUNCTION_REFERENCE$5.invoke#internal"(%struct.ObjHeader* [[this]], i32 {{%[0-9]+}}, i32 {{%[0-9]+}})
// CHECK-DEBUG: call void @"kfun:$foo$FUNCTION_REFERENCE$5.invoke#internal"(%struct.ObjHeader* {{%[0-9]+}}, i32 {{%[0-9]+}}, i32 {{%[0-9]+}})
@@ -0,0 +1,26 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// CHECK-LABEL: "kfun:#and(kotlin.Int;kotlin.Int){}kotlin.Int"
fun and(a: Int, b: Int): Int {
// CHECK: and {{.*}}, {{.*}}
return a and b
// CHECK-LABEL: epilogue:
}
// CHECK-LABEL: "kfun:#ieee754(kotlin.Float;kotlin.Float){}kotlin.Boolean"
fun ieee754(a: Float, b: Float): Boolean {
// CHECK: fcmp oeq float {{.*}}, {{.*}}
return a == b
// CHECK-LABEL: epilogue:
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
val x = and(1, 2)
val y = ieee754(0.0f, 1.0f)
// CHECK-LABEL: epilogue:
return if (x == 0 && !y)
"OK"
else "FAIL x=$x y=$y"
}
@@ -0,0 +1,21 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
class C {
fun foo(x: Int) = x
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-OPT-NOT: Int-box
// CHECK-DEBUG: Int-box
// CHECK-NOT: Int-unbox
// CHECK-LABEL: epilogue:
fun box(): String {
val c = C()
val fooref = c::foo
val result = fooref(42)
return if( result == 42)
"OK"
else
"FAIL: $result"
}
@@ -0,0 +1,20 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
class C<T> {
fun foo(x: T) = x
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-NOT: Int-box
// CHECK-OPT-NOT: Int-unbox
// CHECK-DEBUG: Int-unbox
// CHECK-LABEL: epilogue:
fun box(): String {
val c = C<Int>()
val fooref = c::foo
return if (fooref(42) == 42)
"OK"
else
"FAIL"
}
@@ -0,0 +1,29 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
fun <T> T.foo() { println(this) }
// CHECK-LABEL: define void @"kfun:#bar(0:0){0\C2\A7<kotlin.Any?>}"
// CHECK-SAME: (%struct.ObjHeader* [[x:%[0-9]+]])
fun <BarTP> bar(x: BarTP) {
// CHECK-OPT: call void @"kfun:$foo$FUNCTION_REFERENCE$0.<init>#internal"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* [[x]])
// CHECK-DEBUG: call void @"kfun:$foo$FUNCTION_REFERENCE$0.<init>#internal"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
println(x::foo)
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
// CHECK: call void @"kfun:$foo$FUNCTION_REFERENCE$1.<init>#internal"(%struct.ObjHeader* {{%[0-9]+}}, i32 5)
println(5::foo)
bar("hello")
bar(42)
return "OK"
// CHECK-LABEL: epilogue:
}
// CHECK-LABEL: define internal void @"kfun:$foo$FUNCTION_REFERENCE$0.<init>#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$foo$FUNCTION_REFERENCE$1.<init>#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}}, i32 {{%[0-9]+}})
@@ -0,0 +1,23 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
fun interface Foo {
fun bar(x: Int): Any
}
fun baz(x: Any): Int = x.hashCode()
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// Boxing needs to be used now due to non-devirtualized call
// CHECK-OPT: Int-box
// CHECK-NOT: Int-box
// CHECK-NOT: Int-unbox
// CHECK-LABEL: epilogue:
fun box(): String {
val foo: Foo = Foo(::baz)
return if (foo.bar(42) == 42)
"OK"
else "FAIL"
}
@@ -0,0 +1,19 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
fun interface Foo<T> {
fun bar(x: T): Any
}
fun baz(x: Any): Int = x.hashCode()
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-NOT: Int-box
// CHECK-NOT: Int-unbox
// CHECK-LABEL: epilogue:
fun box(): String {
val foo: Foo<Int> = Foo(::baz)
return if (foo.bar(42) == 42)
"OK"
else "FAIL"
}
@@ -0,0 +1,21 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
fun interface Foo {
fun bar(x: Int): Int
}
fun baz(x: Int): Int = x.hashCode()
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-OPT-NOT: Int-box
// CHECK-DEBUG: Int-box
// CHECK-NOT: Int-unbox
// CHECK-LABEL: epilogue:
fun box(): String {
val foo: Foo = Foo(::baz)
val result = foo.bar(42)
return if( result == 42 )
"OK"
else "FAIL: $result"
}
@@ -0,0 +1,21 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
fun interface Foo<T> {
fun bar(x: T): Int
}
fun baz(x: Any): Int = x.hashCode()
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-OPT-NOT: Int-box
// CHECK-DEBUG: Int-box
// CHECK-NOT: Int-unbox
// CHECK-LABEL: epilogue:
fun box(): String {
val foo: Foo<Int> = Foo(::baz)
val result = foo.bar(42)
return if( result == 42 )
"OK"
else "FAIL: $result"
}
@@ -0,0 +1,22 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
fun plus1(x: Int) = x + 1
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-OPT-NOT: Int-box
// CHECK-OPT-NOT: Int-unbox
// CHECK-DEBUG: Int-box
// CHECK-DEBUG: Int-unbox
// CHECK-LABEL: epilogue:
fun box(): String {
val ref = ::plus1
var y = 0
repeat(100000) {
y += ref(it) // Should be devirtualized and invoked without boxing/unboxing (`Int-box`/`Int-unbox`)
}
if (y != 705082704)
return "FAIL $y != 705082704"
return "OK"
}
@@ -0,0 +1,73 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlin.native.concurrent.*
import kotlinx.cinterop.*
val arr: Array<String> = arrayOf("1")
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
@kotlinx.cinterop.ExperimentalForeignApi
fun box(): String {
println(arr.size.toByte() == arr[0].toByte())
println(arr.size.toUByte() == arr[0].toUByte())
println(arr.size.toShort() == arr[0].toShort())
println(arr.size.toUShort() == arr[0].toUShort())
println(arr.size.toInt() == arr[0].toInt())
println(arr.size.toUInt() == arr[0].toUInt())
println(arr.size.toLong() == arr[0].toLong())
println(arr.size.toULong() == arr[0].toULong())
println(arr.size.toFloat() == arr[0].toFloat())
println(arr.size.toDouble() == arr[0].toDouble())
println(Char(arr.size) == arr[0][0])
println((arr.size == 1) == (arr[0] == "1")) // Boolean
memScoped {
val var1: IntVar = alloc()
val var2: IntVar = alloc()
println(var1.ptr.rawValue == var2.ptr.rawValue)
}
println(Result.success(arr.size) == Result.success(arr[0].toInt()))
println(vectorOf(arr.size, arr.size, arr.size, arr.size) == vectorOf(arr[0].toInt(), arr[0].toInt(), arr[0].toInt(), arr[0].toInt()))
val w1 = Worker.start()
val w2 = Worker.start()
println(w1 == w2)
val f1 = w1.requestTermination()
val f2 = w2.requestTermination()
println(f1 == f2)
f1.result
f2.result
return "OK"
}
// CHECK-OPT-NOT: {{call|invoke}} i64 @"kfun:kotlin#<Long-unbox>
// CHECK-OPT-NOT: {{call|invoke}} i64 @"kfun:kotlin#<ULong-unbox>
// CHECK-OPT-NOT: {{call|invoke}} i32 @"kfun:kotlin#<Int-unbox>
// CHECK-OPT-NOT: {{call|invoke}} i32 @"kfun:kotlin#<UInt-unbox>
// CHECK-OPT-NOT: {{call|invoke}} {{signext i16|i16}} @"kfun:kotlin#<Short-unbox>
// CHECK-OPT-NOT: {{call|invoke}} {{zeroext i16|i16}} @"kfun:kotlin#<UShort-unbox>
// CHECK-OPT-NOT: {{call|invoke}} {{signext i8|i8}} @"kfun:kotlin#<Byte-unbox>
// CHECK-OPT-NOT: {{call|invoke}} {{zeroext i8|i8}} @"kfun:kotlin#<UByte-unbox>
// CHECK-OPT-NOT: {{call|invoke}} {{zeroext i16|i16}} @"kfun:kotlin#<Char-unbox>
// CHECK-OPT-NOT: {{call|invoke}} {{zeroext i1|i1}} @"kfun:kotlin#<Boolean-unbox>
// CHECK-OPT-NOT: {{call|invoke}} double @"kfun:kotlin#<Double-unbox>
// CHECK-OPT-NOT: {{call|invoke}} float @"kfun:kotlin#<Float-unbox>
// CHECK-OPT-NOT: {{call|invoke}} i8* @"kfun:kotlin.native.internal#<NativePtr-unbox>
// CHECK-OPT-NOT: {{call|invoke}} i32 @"kfun:kotlin.native.concurrent#<Future-unbox>
// CHECK-OPT-NOT: {{call|invoke}} i32 @"kfun:kotlin.native.concurrent#<Worker-unbox>
// CHECK-OPT-NOT: {{call|invoke}} <4 x float> @"kfun:kotlin.native#<Vector128-unbox>
// CHECK-OPT-NOT: {{call|invoke}} %struct.ObjHeader* @"kfun:kotlin#<Result-unbox>
// CHECK-LABEL: epilogue:
// On APPLE targets, generated functions <T>ToNSNumber may contain non-converted invocations of unbox functions.
// CHECK-APPLE: {{IntToNSNumber|LongToNSNumber|ByteToNSNumber|ShortToNSNumber|FloatToNSNumber|DoubleToNSNumber}}
@@ -0,0 +1,20 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlinx.cinterop.*
// CHECK-AAPCS-OPT-LABEL: define i1 @"kfun:kotlinx.cinterop.CPointer#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-DEFAULTABI-OPT-LABEL: define zeroext i1 @"kfun:kotlinx.cinterop.CPointer#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-WINDOWSX64-OPT-LABEL: define zeroext i1 @"kfun:kotlinx.cinterop.CPointer#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-OPT: call i8* @"kfun:kotlinx.cinterop#<CPointer-unbox>(kotlin.Any?){}kotlinx.cinterop.CPointer<-1:0>?"
// This test is useless in debug mode.
// TODO(KT-59288): add ability to ignore tests in debug mode
// CHECK-DEBUG-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
@kotlinx.cinterop.ExperimentalForeignApi
fun box(): String = memScoped {
val var1: IntVar = alloc()
val var2: IntVar = alloc()
return if (var1.ptr == var2.ptr) "FAIL" else "OK"
}
@@ -0,0 +1,17 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlinx.cinterop.*
// CHECK-OPT-LABEL: define i8* @"kfun:kotlinx.cinterop#interpretOpaquePointed(kotlin.native.internal.NativePtr){}kotlinx.cinterop.NativePointed"(i8* %0)
// CHECK-OPT: call i8* @"kfun:kotlinx.cinterop#<NativePointed-unbox>(kotlin.Any?){}kotlinx.cinterop.NativePointed?"
// This test is useless in debug mode.
// TODO(KT-59288): add ability to ignore tests in debug mode
// CHECK-DEBUG-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
@kotlinx.cinterop.ExperimentalForeignApi
fun box(): String = memScoped {
val var1: NativePointed = alloc(4, 4)
return if (interpretOpaquePointed(var1.rawPtr) is NativePointed) "OK" else "FAIL"
}
@@ -0,0 +1,22 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlinx.cinterop.*
// CHECK-AAPCS-OPT-LABEL: define i1 @"kfun:kotlin.native.internal.NonNullNativePtr#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-DEFAULTABI-OPT-LABEL: define zeroext i1 @"kfun:kotlin.native.internal.NonNullNativePtr#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-WINDOWSX64-OPT-LABEL: define zeroext i1 @"kfun:kotlin.native.internal.NonNullNativePtr#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-OPT: call i8* @"kfun:kotlin.native.internal#<NonNullNativePtr-unbox>(kotlin.Any?){}kotlin.native.internal.NonNullNativePtr?"
// This test is useless in debug mode.
// TODO(KT-59288): add ability to ignore tests in debug mode
// CHECK-DEBUG-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
@kotlinx.cinterop.ExperimentalForeignApi
fun box(): String = memScoped {
val var1: IntVar = alloc()
val var2: IntVar = alloc()
// The first one is K1, the second one is K2.
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
return if (var1.ptr.value as Any == var2.ptr.value as Any) "FAIL" else "OK"
}
@@ -0,0 +1,26 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlinx.cinterop.*
// CHECK-AAPCS-OPT-LABEL: define i1 @"kfun:kotlinx.cinterop.StableRef#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-DEFAULTABI-OPT-LABEL: define zeroext i1 @"kfun:kotlinx.cinterop.StableRef#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-WINDOWSX64-OPT-LABEL: define zeroext i1 @"kfun:kotlinx.cinterop.StableRef#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-OPT: call i8* @"kfun:kotlinx.cinterop#<StableRef-unbox>(kotlin.Any?){}kotlinx.cinterop.StableRef<-1:0>?"
// CHECK-OPT-LABEL: epilogue:
// This test is useless in debug mode.
// TODO(KT-59288): add ability to ignore tests in debug mode
// CHECK-DEBUG-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
@kotlinx.cinterop.ExperimentalForeignApi
fun box(): String {
val ref1 = StableRef.create(Any())
val ref2 = StableRef.create(Any())
val isEqual = ref1 == ref2
ref2.dispose()
ref1.dispose()
return if (!isEqual) "OK" else "FAIL"
}
@@ -0,0 +1,18 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// CHECK-AAPCS-OPT-LABEL: define i1 @"kfun:kotlin.UByteArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-DEFAULTABI-OPT-LABEL: define zeroext i1 @"kfun:kotlin.UByteArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-WINDOWSX64-OPT-LABEL: define zeroext i1 @"kfun:kotlin.UByteArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-OPT: call %struct.ObjHeader* @"kfun:kotlin#<UByteArray-unbox>(kotlin.Any?){}kotlin.UByteArray?"
// CHECK-LABEL: epilogue:
fun box(): String {
val arr1 = UByteArray(10) { it.toUByte() }
val arr2 = UByteArray(10) { (it / 2).toUByte() }
return if (arr1 == arr2) "FAIL" else "OK"
}
@@ -0,0 +1,18 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// CHECK-AAPCS-OPT-LABEL: define i1 @"kfun:kotlin.UIntArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-DEFAULTABI-OPT-LABEL: define zeroext i1 @"kfun:kotlin.UIntArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-WINDOWSX64-OPT-LABEL: define zeroext i1 @"kfun:kotlin.UIntArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-OPT: call %struct.ObjHeader* @"kfun:kotlin#<UIntArray-unbox>(kotlin.Any?){}kotlin.UIntArray?"
// CHECK-LABEL: epilogue:
fun box(): String {
val arr1 = UIntArray(10) { it.toUInt() }
val arr2 = UIntArray(10) { (it / 2).toUInt() }
return if (arr1 == arr2) "FAIL" else "OK"
}
@@ -0,0 +1,18 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// CHECK-AAPCS-OPT-LABEL: define i1 @"kfun:kotlin.ULongArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-DEFAULTABI-OPT-LABEL: define zeroext i1 @"kfun:kotlin.ULongArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-WINDOWSX64-OPT-LABEL: define zeroext i1 @"kfun:kotlin.ULongArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-OPT: call %struct.ObjHeader* @"kfun:kotlin#<ULongArray-unbox>(kotlin.Any?){}kotlin.ULongArray?"
// CHECK-LABEL: epilogue:
fun box(): String {
val arr1 = ULongArray(10) { it.toULong() }
val arr2 = ULongArray(10) { (it / 2).toULong() }
return if (arr1 == arr2) "FAIL" else "OK"
}
@@ -0,0 +1,18 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// CHECK-AAPCS-OPT-LABEL: define i1 @"kfun:kotlin.UShortArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-DEFAULTABI-OPT-LABEL: define zeroext i1 @"kfun:kotlin.UShortArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-WINDOWSX64-OPT-LABEL: define zeroext i1 @"kfun:kotlin.UShortArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-OPT: call %struct.ObjHeader* @"kfun:kotlin#<UShortArray-unbox>(kotlin.Any?){}kotlin.UShortArray?"
// CHECK-LABEL: epilogue:
fun box(): String {
val arr1 = UShortArray(10) { it.toUShort() }
val arr2 = UShortArray(10) { (it / 2).toUShort() }
return if (arr1 == arr2) "FAIL" else "OK"
}
@@ -0,0 +1,12 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// CHECK-AAPCS-LABEL: define i1 @"kfun:C#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:C#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:C#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK: call %struct.ObjHeader* @"kfun:#<C-unbox>(kotlin.Any?){}C?"
value class C(val x: Any)
// Note: <C-unbox> is also called from bridges for equals, hashCode and toString.
fun box() =
if (C(42) == C(13)) "FAIL" else "OK"
@@ -0,0 +1,36 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// CHECK-LABEL: define i64 @"kfun:#foo(){}kotlin.Long"()
fun foo(): Long {
// CHECK-NOT: @LONG_CACHE
val data: Map<String, Any> = mapOf()
return data.getOrElse("id") { 0L } as Long
}
// CHECK: ret i64
inline fun <T> bar(x: T?, f: Boolean): Any {
when {
x != null -> return@bar x
f -> return@bar 0L
else -> return@bar 1UL
}
}
// CHECK-LABEL: define i64 @"kfun:#callBar(kotlin.Boolean){}kotlin.ULong
fun callBar(f: Boolean): ULong {
// CHECK: @LONG_CACHE
val data: Map<String, Any> = mapOf()
val x = data["id"]
return bar(x, f) as ULong
}
// CHECK: ret i64
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
val resultFoo = foo()
val resultBar = callBar(false)
return if (resultFoo == 0L && resultBar == 1UL)
"OK"
else "FAIL: resultFoo=$resultFoo resultBar=$resultBar"
}
@@ -0,0 +1,39 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
object A {
const val x = 5
}
class B(val z:Int) {
companion object {
const val y = 7
}
}
object C {
val x = listOf(1, 2, 3)
}
// CHECK-LABEL: define i32 @"kfun:#f(){}kotlin.Int"()
// CHECK-NOT: EnterFrame
fun f() = A.x + B.y
// CHECK: {{^}}epilogue:
// test that assumption on how EnterFrame looks like is not broken
// CHECK-LABEL: define void @"kfun:#g(){}"()
// CHECK: EnterFrame
fun g() {
val x = C.x
}
// CHECK: {{^}}epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
val f = f()
if (f != 12)
return "FAIL: $f != 12"
g()
return "OK"
}
@@ -0,0 +1,54 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: RemoveRedundantSafepoints
// This test checks:
// - there is only one safepoint per function
// - safepoint function is inlined in OPT mode, unless SMALLBINARY is needed (for ex, watchos_arm32)
// Might fail under -Xbinary=gc=stwms and -Xbinary=gc=noop. In this case, just add ignore clause.
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
import kotlin.native.Retain
class C
fun f(): Any {
return C()
}
fun g() = f()
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#h(kotlin.Boolean){}kotlin.Any"
@Retain
fun h(cond: Boolean): Any {
// CHECK-SMALLBINARY: {{call .*Kotlin_mm_safePointFunctionPrologue}}
// CHECK-BIGBINARY-OPT: _ZN12_GLOBAL__N_115safePointActionE
// CHECK-SMALLBINARY-NOT: _ZN12_GLOBAL__N_115safePointActionE
// CHECK-BIGBINARY-OPT-NOT: {{call .*Kotlin_mm_safePointFunctionPrologue}}
// CHECK-SMALLBINARY-NOT: {{call .*Kotlin_mm_safePointFunctionPrologue}}
// CHECK-BIGBINARY-OPT-NOT: _ZN12_GLOBAL__N_115safePointActionE
if (cond) {
return listOf(C(), C())
} else {
return listOf(C(), C(), C())
}
// CHECK-LABEL: ret
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
@Retain
fun box(): String {
// CHECK-SMALLBINARY: {{call .*Kotlin_mm_safePointFunctionPrologue}}
// CHECK-BIGBINARY-OPT: _ZN12_GLOBAL__N_115safePointActionE
// CHECK-SMALLBINARY-NOT: _ZN12_GLOBAL__N_115safePointActionE
// CHECK-BIGBINARY-OPT-NOT: {{call .*Kotlin_mm_safePointFunctionPrologue}}
// CHECK-SMALLBINARY-NOT: {{call .*Kotlin_mm_safePointFunctionPrologue}}
// CHECK-BIGBINARY-OPT-NOT: _ZN12_GLOBAL__N_115safePointActionE
println(g())
println(h(true))
return "OK"
// CHECK-LABEL: ret
}
@@ -0,0 +1,32 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
fun flameThrower() {
throw Throwable("🔥")
}
// CHECK-LABEL: "kfun:#f1(){}"
fun f1() {
// CHECK: call void @"kfun:#flameThrower(){}"()
flameThrower()
// CHECK-LABEL: epilogue:
}
// CHECK-LABEL: "kfun:#f2(){}"
fun f2() {
try {
// CHECK: invoke void @"kfun:#flameThrower(){}"()
flameThrower()
} catch (t: Throwable) {}
// CHECK-LABEL: epilogue:
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
try {
f1()
} catch (t: Throwable) {}
f2()
// CHECK-LABEL: epilogue:
return "OK"
}
@@ -0,0 +1,157 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#id(kotlin.Boolean){}kotlin.Boolean"(i1 zeroext %0)
// CHECK-AAPCS-LABEL: define i1 @"kfun:#id(kotlin.Boolean){}kotlin.Boolean"(i1 %0)
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#id(kotlin.Boolean){}kotlin.Boolean"(i1 zeroext %0)
fun id(arg: Boolean): Boolean {
return arg
}
// CHECK-DEFAULTABI-LABEL: define signext i8 @"kfun:#id(kotlin.Byte){}kotlin.Byte"(i8 signext %0)
// CHECK-AAPCS-LABEL: define i8 @"kfun:#id(kotlin.Byte){}kotlin.Byte"(i8 %0)
// CHECK-WINDOWSX64-LABEL: define i8 @"kfun:#id(kotlin.Byte){}kotlin.Byte"(i8 %0)
fun id(arg: Byte): Byte {
return arg
}
// CHECK-DEFAULTABI-LABEL: define zeroext i16 @"kfun:#id(kotlin.Char){}kotlin.Char"(i16 zeroext %0)
// CHECK-AAPCS-LABEL: define i16 @"kfun:#id(kotlin.Char){}kotlin.Char"(i16 %0)
// CHECK-WINDOWSX64-LABEL: define i16 @"kfun:#id(kotlin.Char){}kotlin.Char"(i16 %0)
fun id(arg: Char): Char {
return arg
}
// CHECK-DEFAULTABI-LABEL: define signext i16 @"kfun:#id(kotlin.Short){}kotlin.Short"(i16 signext %0)
// CHECK-AAPCS-LABEL: define i16 @"kfun:#id(kotlin.Short){}kotlin.Short"(i16 %0)
// CHECK-WINDOWSX64-LABEL: define i16 @"kfun:#id(kotlin.Short){}kotlin.Short"(i16 %0)
fun id(arg: Short): Short {
return arg
}
// CHECK-LABEL: define i32 @"kfun:#id(kotlin.Int){}kotlin.Int"(i32 %0)
fun id(arg: Int): Int {
return arg
}
// CHECK-LABEL: define i64 @"kfun:#id(kotlin.Long){}kotlin.Long"(i64 %0)
fun id(arg: Long): Long {
return arg
}
// CHECK-LABEL: define float @"kfun:#id(kotlin.Float){}kotlin.Float"(float %0)
fun id(arg: Float): Float {
return arg
}
// CHECK-LABEL: define double @"kfun:#id(kotlin.Double){}kotlin.Double"(double %0)
fun id(arg: Double): Double {
return arg
}
// CHECK-DEFAULTABI-LABEL: define zeroext i8 @"kfun:#id(kotlin.UByte){}kotlin.UByte"(i8 zeroext %0)
// CHECK-AAPCS-LABEL: define i8 @"kfun:#id(kotlin.UByte){}kotlin.UByte"(i8 %0)
// CHECK-WINDOWSX64-LABEL: define i8 @"kfun:#id(kotlin.UByte){}kotlin.UByte"(i8 %0)
fun id(arg: UByte): UByte {
return arg
}
// CHECK-DEFAULTABI-LABEL: define zeroext i16 @"kfun:#id(kotlin.UShort){}kotlin.UShort"(i16 zeroext %0)
// CHECK-AAPCS-LABEL: define i16 @"kfun:#id(kotlin.UShort){}kotlin.UShort"(i16 %0)
// CHECK-WINDOWSX64-LABEL: define i16 @"kfun:#id(kotlin.UShort){}kotlin.UShort"(i16 %0)
fun id(arg: UShort): UShort {
return arg
}
// CHECK-LABEL: define i32 @"kfun:#id(kotlin.UInt){}kotlin.UInt"(i32 %0)
fun id(arg: UInt): UInt {
return arg
}
// CHECK-LABEL: define i64 @"kfun:#id(kotlin.ULong){}kotlin.ULong"(i64 %0)
fun id(arg: ULong): ULong {
return arg
}
fun checkPrimitives() {
// CHECK-DEFAULTABI: call zeroext i1 @"kfun:#id(kotlin.Boolean){}kotlin.Boolean"(i1 zeroext {{.*}})
// CHECK-AAPCS: call i1 @"kfun:#id(kotlin.Boolean){}kotlin.Boolean"(i1 {{.*}})
// CHECK-WINDOWSX64: call zeroext i1 @"kfun:#id(kotlin.Boolean){}kotlin.Boolean"(i1 zeroext {{.*}})
id(true)
// CHECK-DEFAULTABI: call signext i8 @"kfun:#id(kotlin.Byte){}kotlin.Byte"(i8 signext {{.*}})
// CHECK-AAPCS: call i8 @"kfun:#id(kotlin.Byte){}kotlin.Byte"(i8 {{.*}})
// CHECK-WINDOWSX64: call i8 @"kfun:#id(kotlin.Byte){}kotlin.Byte"(i8 {{.*}})
id(0.toByte())
// CHECK-DEFAULTABI: call zeroext i16 @"kfun:#id(kotlin.Char){}kotlin.Char"(i16 zeroext {{.*}})
// CHECK-AAPCS: call i16 @"kfun:#id(kotlin.Char){}kotlin.Char"(i16 {{.*}})
// CHECK-WINDOWSX64: call i16 @"kfun:#id(kotlin.Char){}kotlin.Char"(i16 {{.*}})
id('a')
// CHECK-DEFAULTABI: call signext i16 @"kfun:#id(kotlin.Short){}kotlin.Short"(i16 signext {{.*}})
// CHECK-AAPCS: call i16 @"kfun:#id(kotlin.Short){}kotlin.Short"(i16 {{.*}})
// CHECK-WINDOWSX64: call i16 @"kfun:#id(kotlin.Short){}kotlin.Short"(i16 {{.*}})
id(0.toShort())
// CHECK: call i32 @"kfun:#id(kotlin.Int){}kotlin.Int"(i32 {{.*}})
id(0)
// CHECK: call i64 @"kfun:#id(kotlin.Long){}kotlin.Long"(i64 {{.*}})
id(0L)
// CHECK: call float @"kfun:#id(kotlin.Float){}kotlin.Float"(float {{.*}})
id(0.5f)
// CHECK: call double @"kfun:#id(kotlin.Double){}kotlin.Double"(double {{.*}})
id(0.5)
// CHECK-DEFAULTABI: call zeroext i8 @"kfun:#id(kotlin.UByte){}kotlin.UByte"(i8 zeroext {{.*}})
// CHECK-AAPCS: call i8 @"kfun:#id(kotlin.UByte){}kotlin.UByte"(i8 {{.*}})
// CHECK-WINDOWSX64: call i8 @"kfun:#id(kotlin.UByte){}kotlin.UByte"(i8 {{.*}})
id(0.toUByte())
// CHECK-DEFAULTABI: call zeroext i16 @"kfun:#id(kotlin.UShort){}kotlin.UShort"(i16 zeroext {{.*}})
// CHECK-AAPCS: call i16 @"kfun:#id(kotlin.UShort){}kotlin.UShort"(i16 {{.*}})
// CHECK-WINDOWSX64: call i16 @"kfun:#id(kotlin.UShort){}kotlin.UShort"(i16 {{.*}})
id(0.toUShort())
// CHECK: call i32 @"kfun:#id(kotlin.UInt){}kotlin.UInt"(i32 {{.*}})
id(15u)
// CHECK: call i64 @"kfun:#id(kotlin.ULong){}kotlin.ULong"(i64 {{.*}})
id(15uL)
}
value class CharWrapper(val ch: Char)
// CHECK-DEFAULTABI-LABEL: define zeroext i16 @"kfun:#id(CharWrapper){}CharWrapper"(i16 zeroext %0)
// CHECK-AAPCS-LABEL: define i16 @"kfun:#id(CharWrapper){}CharWrapper"(i16 %0)
// CHECK-WINDOWSX64-LABEL: define i16 @"kfun:#id(CharWrapper){}CharWrapper"(i16 %0)
fun id(arg: CharWrapper): CharWrapper {
return arg
}
// Check that value classes doesn't affect parameter attributes
fun checkInlineClasses() {
// CHECK-DEFAULTABI: call zeroext i16 @"kfun:#id(CharWrapper){}CharWrapper"(i16 zeroext {{.*}})
// CHECK-AAPCS: call i16 @"kfun:#id(CharWrapper){}CharWrapper"(i16 {{.*}})
// CHECK-WINDOWSX64: call i16 @"kfun:#id(CharWrapper){}CharWrapper"(i16 {{.*}})
id(CharWrapper('c'))
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#nullableId(kotlin.Byte?){}kotlin.Byte?"(%struct.ObjHeader* %0, %struct.ObjHeader** %1)
fun nullableId(arg: Byte?): Byte? {
return arg
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#nullableId(CharWrapper?){}CharWrapper?"(%struct.ObjHeader* %0, %struct.ObjHeader** %1)
fun nullableId(arg: CharWrapper?): CharWrapper? {
return arg
}
// Check that we don't pass primitive-specific attributes to their boxes
fun checkBoxes() {
// CHECK: call %struct.ObjHeader* @"kfun:#nullableId(kotlin.Byte?){}kotlin.Byte?"(%struct.ObjHeader* {{.*}}, %struct.ObjHeader** {{.*}})
nullableId(1.toByte())
// CHECK: call %struct.ObjHeader* @"kfun:#nullableId(CharWrapper?){}CharWrapper?"(%struct.ObjHeader* {{.*}}, %struct.ObjHeader** {{.*}})
nullableId(CharWrapper('a'))
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
checkPrimitives()
checkInlineClasses()
checkBoxes()
return "OK"
}
@@ -0,0 +1,36 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: OptimizeTLSDataLoads
class Wrapper(x: Int)
// CHECK-LABEL: define internal fastcc %struct.ObjHeader* @"kfun:#f(kotlin.Int;kotlin.String){}kotlin.String"
fun f(x: Int, s: String): String {
// https://youtrack.jetbrains.com/issue/KT-64880/K-N-EnterFrame-runtime-function-should-be-always-inlined-in-OPT-mode
// Remove `|call fastcc void @EnterFrame` below, after KT-64880 is fixed
// `call .. @EnterFrame` may or may not be inlined.
// - in case it would be inlined, several `load .. currentThreadDataNode` would happen, and only first of them must stay
// after `OptimizeTLSDataLoads` optimizaion phase.
// - in case of no-inline, several `call .. @EnterFrame` may remain in function code.
// CHECK: {{_ZN6kotlin2mm14ThreadRegistry22currentThreadDataNode_E|call fastcc void @EnterFrame}}
// CHECK-NOT: _ZN6kotlin2mm14ThreadRegistry22currentThreadDataNode_E
if (x < 0) throw IllegalStateException()
if (x > 0) return f(x - 1, s)
val b = Wrapper(2)
val a = listOf(x, x, Wrapper(1), 2, x)
return buildString {
for (i in a) { appendLine("$s i") }
}
// CHECK-LABEL: epilogue:
}
fun box(): String {
val result = f(10, "123456")
return if (result == "123456 i\n" +
"123456 i\n" +
"123456 i\n" +
"123456 i\n" +
"123456 i\n")
"OK"
else "FAIL: $result"
}
@@ -0,0 +1,18 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// CHECK-LABEL: "kfun:#id(kotlin.Any?){}kotlin.Any?"
fun id(a: Any?): Any? {
return a
// CHECK-LABEL: epilogue:
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
// CHECK: call %struct.ObjHeader* @"kfun:#id(kotlin.Any?){}kotlin.Any?"
val x = id("Hello")
// CHECK: call void @"kfun:kotlin.io#println(kotlin.Any?){}"(%struct.ObjHeader* {{.*}})
println(x)
// CHECK-LABEL: epilogue:
return "OK"
}
@@ -0,0 +1,114 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
package codegen.stringConcatenationTypeNarrowing.kt53119_append_generated
import kotlin.test.*
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated#maybeAnyMaybeAny
// CHECK-OPT: %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK-OPT: %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated.Foo#toString(){}kotlin.String"
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK: ret %struct.ObjHeader*
fun maybeAnyMaybeAny(maybeAny1: Any?, maybeAny2: Any?): String {
return "$maybeAny1,$maybeAny2"
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated#maybeAnyMaybeString
// CHECK-OPT: %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK: ret %struct.ObjHeader*
fun maybeAnyMaybeString(maybeAny1: Any?, maybeString2: String?): String {
return "$maybeAny1,$maybeString2"
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated#maybeAnyString
// CHECK-OPT: %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK: ret %struct.ObjHeader*
fun maybeAnyString(maybeAny1: Any?, string: String): String {
return "$maybeAny1,$string"
}
data class Foo(val bar: Int)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated#maybeAnyFoo
// CHECK-OPT: %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK-OPT: %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK: ret %struct.ObjHeader*
fun maybeAnyFoo(maybeAny: Any?, foo: Foo): String {
return "$maybeAny,$foo"
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated#maybeAnyMaybeFoo
// CHECK-OPT: %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT: %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK: ret %struct.ObjHeader*
fun maybeAnyMaybeFoo(maybeAny: Any?, foo: Foo?): String {
return "$maybeAny,$foo"
}
fun box(): String {
val foo = Foo(42)
val res1 = maybeAnyMaybeAny(foo, foo)
if (res1 != "Foo(bar=42),Foo(bar=42)") return "FAIL1: $res1"
val res2 = maybeAnyMaybeAny(null, null)
if (res2 != "null,null") return "FAIL2: $res2"
val res3 = maybeAnyMaybeString(foo, "bar")
if (res3 != "Foo(bar=42),bar") return "FAIL3: $res3"
val res4 = maybeAnyMaybeString(null, null)
if (res4 != "null,null") return "FAIL4: $res4"
val res5 = maybeAnyString(foo, "bar")
if (res5 != "Foo(bar=42),bar") return "FAIL5: $res5"
val res6 = maybeAnyString(null, "bar")
if (res6 != "null,bar") return "FAIL6: $res6"
val res7 = maybeAnyFoo(foo, foo)
if (res7 != "Foo(bar=42),Foo(bar=42)") return "FAIL7: $res7"
val res8 = maybeAnyFoo(null, foo)
if (res8 != "null,Foo(bar=42)") return "FAIL8: $res8"
val res9 = maybeAnyMaybeFoo(foo, foo)
if (res9 != "Foo(bar=42),Foo(bar=42)") return "FAIL9: $res9"
val res10 = maybeAnyMaybeFoo(foo, null)
if (res10 != "Foo(bar=42),null") return "FAIL10: $res10"
return "OK"
}
@@ -0,0 +1,98 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
package codegen.stringConcatenationTypeNarrowing.kt53119_append_manual
import kotlin.test.*
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_manual#appendMaybeAny(kotlin.Any?)
// CHECK-OPT: %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_manual.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK: ret %struct.ObjHeader*
fun appendMaybeAny(maybeAny: Any?): String {
val sb = kotlin.text.StringBuilder()
sb.append(maybeAny)
return sb.toString()
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_manual#appendAny(kotlin.Any)
// CHECK-OPT: %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_manual.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK: ret %struct.ObjHeader*
fun appendAny(any: Any): String {
val sb = kotlin.text.StringBuilder()
sb.append(any)
return sb.toString()
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_manual#appendMaybeString(kotlin.String?)
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.String#toString(){}kotlin.String
// CHECK: ret %struct.ObjHeader*
fun appendMaybeString(maybeStr: String?): String {
val sb = kotlin.text.StringBuilder()
sb.append(maybeStr)
return sb.toString()
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_manual#appendString(kotlin.String)
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.String#toString(){}kotlin.String
// CHECK: ret %struct.ObjHeader*
fun appendString(str: String): String {
val sb = kotlin.text.StringBuilder()
sb.append(str)
return sb.toString()
}
data class Foo(val bar: Int)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_manual#appendFoo(codegen.stringConcatenationTypeNarrowing.kt53119_append_manual.Foo)
// CHECK-OPT: %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_manual.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK-OPT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK: ret %struct.ObjHeader*
fun appendFoo(foo: Foo): String {
val sb = kotlin.text.StringBuilder()
sb.append(foo)
return sb.toString()
}
fun box(): String {
val foo = Foo(42)
val res1 = appendMaybeAny(foo)
if (res1 != "Foo(bar=42)") return "FAIL1: $res1"
val res2 = appendMaybeAny(null)
if (res2 != "null") return "FAIL2: $res2"
val res3 = appendAny(foo)
if (res3 != "Foo(bar=42)") return "FAIL3: $res3"
val res4 = appendMaybeString("foo")
if (res4 != "foo") return "FAIL4: $res4"
val res5 = appendMaybeString(null)
if (res5 != "null") return "FAIL5: $res5"
val res6 = appendString("foo")
if (res6 != "foo") return "FAIL6: $res6"
val res7 = appendFoo(foo)
if (res7 != "Foo(bar=42)") return "FAIL7: $res7"
return "OK"
}
@@ -0,0 +1,132 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
package codegen.stringConcatenationTypeNarrowing.kt53119_plus_extension
import kotlin.test.*
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_extension#manualPlusExtensionAny
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK-OPT: call %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_extension.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK-OPT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK-OPT-NOT: call %struct.ObjHeader* @"kfun:kotlin.String#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK: ret %struct.ObjHeader*
fun manualPlusExtensionAny(maybeStr: String?, maybeAny: kotlin.Any?): kotlin.String =
maybeStr + maybeAny
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_extension#manualPlusExtensionString
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK-OPT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: call %struct.ObjHeader* @"kfun:kotlin.String#toString(){}kotlin.String"
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK: ret %struct.ObjHeader*
fun manualPlusExtensionString(maybeStr: String?, str: String): kotlin.String =
maybeStr + str
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_extension#generatedPlusExtensionAny
// CHECK-OPT-NOT: kfun:kotlin#plus__at__kotlin.String?(kotlin.Any?)
// CHECK-OPT: call %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_extension.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK-OPT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: kfun:kotlin#plus__at__kotlin.String?(kotlin.Any?)
// CHECK-OPT-NOT: call %struct.ObjHeader* @"kfun:kotlin.String#toString(){}kotlin.String"
// CHECK: ret %struct.ObjHeader*
fun generatedPlusExtensionAny(maybeStr: String?, maybeAny: Any?): String {
return "$maybeStr$maybeAny"
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_extension#generatedPlusExtensionString
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK-OPT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: call %struct.ObjHeader* @"kfun:kotlin.String#toString(){}kotlin.String"
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK: ret %struct.ObjHeader*
fun generatedPlusExtensionString(maybeStr: String?, str: String): String {
return "$maybeStr$str"
}
data class Foo(val bar: Int)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_extension#generatedPlusExtensionFoo
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK-OPT: call %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_extension.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String
// CHECK-OPT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: call %struct.ObjHeader* @"kfun:kotlin.String#toString(){}kotlin.String"
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK: ret %struct.ObjHeader*
fun generatedPlusExtensionFoo(maybeStr: String?, foo: Foo): String {
return "$maybeStr$foo"
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_extension#generatedPlusExtensionMaybeFoo
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK-OPT: call %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_extension.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String
// CHECK-OPT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: call %struct.ObjHeader* @"kfun:kotlin.String#toString(){}kotlin.String"
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK: ret %struct.ObjHeader*
fun generatedPlusExtensionMaybeFoo(maybeStr: String?, foo: Foo?): String {
return "$maybeStr$foo"
}
fun box(): String {
val foo = Foo(42)
val res1 = manualPlusExtensionAny("foo", foo)
if (res1 != "fooFoo(bar=42)") return "FAIL1: $res1"
val res2 = manualPlusExtensionAny(null, null)
if (res2 != "nullnull") return "FAIL2: $res2"
val res3 = manualPlusExtensionString("foo", "bar")
if (res3 != "foobar") return "FAIL3: $res3"
val res4 = manualPlusExtensionString(null, "bar")
if (res4 != "nullbar") return "FAIL4: $res4"
val res5 = generatedPlusExtensionAny("foo", foo)
if (res5 != "fooFoo(bar=42)") return "FAIL5: $res5"
val res6 = generatedPlusExtensionAny(null, null)
if (res6 != "nullnull") return "FAIL6: $res6"
val res7 = generatedPlusExtensionString("foo", "bar")
if (res7 != "foobar") return "FAIL7: $res7"
val res8 = generatedPlusExtensionString(null, "bar")
if (res8 != "nullbar") return "FAIL8: $res8"
val res9 = generatedPlusExtensionFoo(null, Foo(42))
if (res9 != "nullFoo(bar=42)") return "FAIL9: $res9"
val res10 = generatedPlusExtensionMaybeFoo("foo", Foo(42))
if (res10 != "fooFoo(bar=42)") return "FAIL10: $res10"
val res11 = generatedPlusExtensionMaybeFoo("foo", null)
if (res11 != "foonull") return "FAIL11: $res11"
return "OK"
}
@@ -0,0 +1,29 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
package codegen.stringConcatenationTypeNarrowing.kt53119_plus_generated_noescape
import kotlin.test.*
import kotlin.random.*
// Without "string concatenation type narrowing", pointer to IntRange is conservatively considered to escape,
// since within String.plus(Any?) (within Random.nextInt), the pointer is passed as a receiver of virtual call Any.toString()
// As a result, no stack allocation is possible
// With "string concatenation type narrowing", IntRange.toString() is explicitly called, that does not escape the receiver.
// Hence, escape analysis can find out the pointer to IntRange does not escape anywhere, and stack allocation is possible.
// CHECK-LABEL: define i32 @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_generated_noescape#getNextInt(){}kotlin.Int
// CHECK-NOT ret i32
// CHECK alloca %"kclassbody:kotlin.ranges.IntRange#internal"
// CHECK ret i32
fun getNextInt(): Int {
return Random.nextInt(IntRange(42153, 42153))
}
fun box(): String {
val nextInt = getNextInt()
if (nextInt != 42153) return "FAIL: $nextInt != 42153"
return "OK"
}
@@ -0,0 +1,111 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
package codegen.stringConcatenationTypeNarrowing.kt53119_plus_member
import kotlin.test.*
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_member#manualPlusMemberAny
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK-OPT: call %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_member.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK-OPT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK: ret %struct.ObjHeader*
fun manualPlusMemberAny(str: String, maybeAny: kotlin.Any?): kotlin.String =
str + maybeAny
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_member#manualPlusMemberString
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK-OPT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK-OPT-NOT: call %struct.ObjHeader* @"kfun:kotlin.String#toString(){}kotlin.String"
// CHECK: ret %struct.ObjHeader*
fun manualPlusMemberString(str1: String, str2: String): kotlin.String =
str1 + str2
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_member#generatedPlusMemberAny
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK-OPT: call %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_member.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK-OPT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK: ret %struct.ObjHeader*
fun generatedPlusMemberAny(str: String, maybeAny: Any?): String {
return "$str$maybeAny"
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_member#generatedPlusMemberString
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK-OPT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: call %struct.ObjHeader* @"kfun:kotlin.String#toString(){}kotlin.String"
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK: ret %struct.ObjHeader*
fun generatedPlusMemberString(str1: String, str2: String): String {
return "$str1$str2"
}
data class Foo(val bar: Int)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_member#manualPlusMemberFoo
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK-OPT: call %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_member.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT Foo#toString(){}kotlin.String
// CHECK-OPT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK: ret %struct.ObjHeader*
fun manualPlusMemberFoo(str1: String, foo: Foo): kotlin.String =
str1 + foo
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_member#manualPlusMemberMaybeFoo
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK-OPT: call %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_member.Foo#toString(){}kotlin.String"
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String
// CHECK-OPT-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK-OPT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-OPT-NOT: Foo#toString(){}kotlin.String"
// CHECK: ret %struct.ObjHeader*
fun manualPlusMemberMaybeFoo(str1: String, foo: Foo?): kotlin.String =
str1 + foo
fun box(): String {
val foo = Foo(42)
val res1 = manualPlusMemberAny("foo", foo)
if (res1 != "fooFoo(bar=42)") return "FAIL1: $res1"
val res2 = manualPlusMemberAny("foo", null)
if (res2 != "foonull") return "FAIL2: $res2"
val res3 = manualPlusMemberString("foo", "bar")
if (res3 != "foobar") return "FAIL3: $res3"
val res4 = generatedPlusMemberAny("foo", null)
if (res4 != "foonull") return "FAIL4: $res4"
val res5 = generatedPlusMemberAny("foo", foo)
if (res5 != "fooFoo(bar=42)") return "FAIL5: $res5"
val res6 = generatedPlusMemberString("foo", "bar")
if (res6 != "foobar") return "FAIL6: $res6"
val res7 = manualPlusMemberFoo("foo", Foo(42))
if (res7 != "fooFoo(bar=42)") return "FAIL7: $res7"
val res8 = manualPlusMemberMaybeFoo("foo", Foo(42))
if (res8 != "fooFoo(bar=42)") return "FAIL8: $res8"
val res9 = manualPlusMemberMaybeFoo("foo", null)
if (res9 != "foonull") return "FAIL9: $res9"
return "OK"
}
@@ -0,0 +1,27 @@
// WITH_STDLIB
import kotlin.collections.*
val sideEffectsHolder = mutableListOf<Int>()
fun withSideEffect(param: Int): String? {
sideEffectsHolder.add(param)
return "Result $param"
}
fun box(): String {
val result1 = "Result1 is: " + withSideEffect(1)
if (result1 != "Result1 is: Result 1") return "FAIL 1: $result1"
if (sideEffectsHolder != listOf(1)) return "FAIL 1 sideffects: $sideEffectsHolder"
sideEffectsHolder.clear()
val result2 = "Result2 is: " + withSideEffect(2) + "!"
if (result2 != "Result2 is: Result 2!") return "FAIL 2: $result2"
if (sideEffectsHolder != listOf(2)) return "FAIL 2 sideffects: $sideEffectsHolder"
sideEffectsHolder.clear()
val result3 = withSideEffect(31) + withSideEffect(32)
if (result3 != "Result 31Result 32") return "FAIL 3: $result3"
if (sideEffectsHolder != listOf(31,32)) return "FAIL 3 sideffects: $sideEffectsHolder"
sideEffectsHolder.clear()
val result4 = withSideEffect(41) + withSideEffect(42) + withSideEffect(43)
if (result4 != "Result 41Result 42Result 43") return "FAIL 4: $result4"
if (sideEffectsHolder != listOf(41,42,43)) return "FAIL 4 sideffects: $sideEffectsHolder"
return "OK"
}
@@ -0,0 +1,41 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlin.test.*
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
companion object : EmptyContinuation()
override fun resumeWith(result: Result<Any?>) { result.getOrThrow() }
}
suspend fun suspendForever(): Int = suspendCoroutineUninterceptedOrReturn {
COROUTINE_SUSPENDED
}
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:$fooCOROUTINE
// CHECK-NOT: ; Function Attrs: {{.*}}noreturn
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#foo#suspend(kotlin.coroutines.Continuation<kotlin.Nothing>){}kotlin.Any"
suspend fun foo(): Nothing {
suspendForever()
throw Error()
}
suspend fun bar() {
foo()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
builder {
bar()
}
return "OK"
}
@@ -0,0 +1,320 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
companion object : EmptyContinuation()
override fun resumeWith(result: Result<Any?>) { result.getOrThrow() }
}
suspend fun sUnit(): Unit = suspendCoroutineUninterceptedOrReturn { x ->
println("sUnit")
x.resume(Unit)
COROUTINE_SUSPENDED
}
suspend fun sInt(): Int = suspendCoroutineUninterceptedOrReturn { x ->
println("sInt")
x.resume(42)
COROUTINE_SUSPENDED
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s1#suspend(kotlin.coroutines.Continuation<kotlin.Unit>){}kotlin.Any
suspend fun s1() {
// CHECK-NOT: call void @"kfun:$s1COROUTINE${{[0-9]*}}#<init>
println("s1")
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s2#suspend(kotlin.coroutines.Continuation<kotlin.Unit>){}kotlin.Any
suspend fun s2() {
// CHECK-NOT: call void @"kfun:$s2COROUTINE${{[0-9]*}}#<init>
println("s2")
sUnit()
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s3#suspend(kotlin.coroutines.Continuation<kotlin.Unit>){}kotlin.Any
suspend fun s3() {
// CHECK-NOT: call void @"kfun:$s3COROUTINE${{[0-9]*}}#<init>
println("s3")
sUnit()
return
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s4#suspend(kotlin.coroutines.Continuation<kotlin.Int>){}kotlin.Any
suspend fun s4(): Int {
// CHECK-NOT: call void @"kfun:$s4COROUTINE${{[0-9]*}}#<init>
println("s4")
return sInt()
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s5#suspend(kotlin.coroutines.Continuation<kotlin.Unit>){}kotlin.Any
suspend fun s5() {
// CHECK-NOT: call void @"kfun:$s5COROUTINE${{[0-9]*}}#<init>
println("s5")
run { sUnit() }
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s6#suspend(kotlin.coroutines.Continuation<kotlin.Unit>){}kotlin.Any
suspend fun s6() {
// CHECK-NOT: call void @"kfun:$s6COROUTINE${{[0-9]*}}#<init>
run {
println("s6")
sUnit()
}
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s7#suspend(kotlin.coroutines.Continuation<kotlin.Int>){}kotlin.Any
suspend fun s7(): Int {
// CHECK-NOT: call void @"kfun:$s7COROUTINE${{[0-9]*}}#<init>
return run {
println("s7")
sInt()
}
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s8#suspend(kotlin.coroutines.Continuation<kotlin.Int>){}kotlin.Any
suspend fun s8(): Int {
// CHECK-NOT: call void @"kfun:$s8COROUTINE${{[0-9]*}}#<init>
run {
println("s8")
return sInt()
}
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s9#suspend(kotlin.coroutines.Continuation<kotlin.Unit>){}kotlin.Any
suspend fun s9() {
// CHECK-NOT: call void @"kfun:$s9COROUTINE${{[0-9]*}}#<init>
run {
println("s9-1")
run {
println("s9-2")
sUnit()
}
}
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s10#suspend(kotlin.coroutines.Continuation<kotlin.Int>){}kotlin.Any
suspend fun s10(): Int {
// CHECK-NOT: call void @"kfun:$s10COROUTINE${{[0-9]*}}#<init>
run {
println("s10-1")
return run {
println("s10-2")
sInt()
}
}
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s11#suspend(kotlin.coroutines.Continuation<kotlin.Unit>){}kotlin.Any
suspend fun s11() {
// CHECK-NOT: call void @"kfun:$s11COROUTINE${{[0-9]*}}#<init>
println("s11")
sUnit()
return
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s12#suspend(kotlin.coroutines.Continuation<kotlin.Unit>){}kotlin.Any
suspend fun s12() {
// CHECK-NOT: call void @"kfun:$s12COROUTINE${{[0-9]*}}#<init>
run {
println("s12")
sUnit()
return
}
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s13#suspend(kotlin.coroutines.Continuation<kotlin.Unit>){}kotlin.Any
suspend fun s13() {
// CHECK-NOT: call void @"kfun:$s13COROUTINE${{[0-9]*}}#<init>
run {
println("s13")
sUnit()
}
return
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s14#suspend(kotlin.coroutines.Continuation<kotlin.Unit>){}kotlin.Any
suspend fun s14() {
// CHECK-NOT: call void @"kfun:$s14COROUTINE${{[0-9]*}}#<init>
run {
println("s14")
sUnit()
return@run
}
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s15#suspend(kotlin.coroutines.Continuation<kotlin.Int>){}kotlin.Any
@Suppress("UNREACHABLE_CODE")
suspend fun s15(): Int {
// CHECK-NOT: call void @"kfun:$s15COROUTINE${{[0-9]*}}#<init>
run {
println("s15-1")
return run {
println("s15-2")
return sInt()
}
}
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s16#suspend(kotlin.coroutines.Continuation<kotlin.Int>){}kotlin.Any
suspend fun s16(): Int {
// CHECK-NOT: call void @"kfun:$s16COROUTINE${{[0-9]*}}#<init>
run outer@ {
println("s16-1")
return run inner@ {
println("s16-2")
return@inner sInt()
}
}
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s17#suspend(kotlin.coroutines.Continuation<kotlin.Int>){}kotlin.Any
@Suppress("UNREACHABLE_CODE")
suspend fun s17(): Int {
// CHECK-NOT: call void @"kfun:$s17COROUTINE${{[0-9]*}}#<init>
return run outer@ {
println("s17-1")
return run inner@ {
println("s17-2")
return@outer sInt()
}
}
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s18#suspend(kotlin.Boolean;kotlin.coroutines.Continuation<kotlin.Unit>){}kotlin.Any
suspend fun s18(f: Boolean) {
// CHECK-NOT: call void @"kfun:$s18COROUTINE${{[0-9]*}}#<init>
if (f) {
println("s18-1")
sUnit()
} else {
println("s18-2")
s2()
}
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s19#suspend(kotlin.Boolean;kotlin.coroutines.Continuation<kotlin.Int>){}kotlin.Any
suspend fun s19(f: Boolean): Int {
// CHECK-NOT: call void @"kfun:$s19COROUTINE${{[0-9]*}}#<init>
if (f) {
println("s19-1")
return sInt()
} else {
println("s19-2")
return s4()
}
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s20#suspend(kotlin.Boolean;kotlin.coroutines.Continuation<kotlin.Int>){}kotlin.Any
suspend fun s20(f: Boolean): Int {
// CHECK-NOT: call void @"kfun:$s20COROUTINE${{[0-9]*}}#<init>
return if (f) {
println("s20-1")
sInt()
} else {
println("s20-2")
s4()
}
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s21#suspend(kotlin.coroutines.Continuation<kotlin.Unit>){}kotlin.Any
suspend fun s21() {
// CHECK-NOT: call void @"kfun:$s21COROUTINE${{[0-9]*}}#<init>
try {
println("s21")
} catch (t: Throwable) {
sUnit()
}
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s22#suspend(kotlin.coroutines.Continuation<kotlin.Int>){}kotlin.Any
suspend fun s22(): Int {
// CHECK-NOT: call void @"kfun:$s22COROUTINE${{[0-9]*}}#<init>
try {
println("s22")
} catch (t: Throwable) {
return sInt()
}
return s4()
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s23#suspend(kotlin.Boolean;kotlin.coroutines.Continuation<kotlin.Unit>){}kotlin.Any
suspend fun s23(f: Boolean) {
// CHECK-NOT: call void @"kfun:$s23COROUTINE${{[0-9]*}}#<init>
val x = run {
if (f) {
println("s23")
sUnit()
return
}
42
}
println(x)
}
// CHECK-LABEL: epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#s24#suspend(kotlin.coroutines.Continuation<kotlin.Unit>){}kotlin.Any
suspend fun s24() {
// CHECK: call void @"kfun:$s24COROUTINE${{[0-9]*}}.<init>#internal
sInt()
}
// CHECK-LABEL: epilogue:
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
builder {
s1()
s2()
s3()
s4()
s5()
s6()
s7()
s8()
s9()
s10()
s11()
s12()
s13()
s14()
s15()
s16()
s17()
s18(true)
s19(true)
s20(true)
s21()
s22()
s23(true)
s24()
}
return "OK"
}
@@ -0,0 +1,382 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
companion object : EmptyContinuation()
override fun resumeWith(result: Result<Any?>) { result.getOrThrow() }
}
suspend fun sUnit(): Unit = suspendCoroutineUninterceptedOrReturn { x ->
println("sUnit")
x.resume(Unit)
COROUTINE_SUSPENDED
}
suspend fun sUnit2(): Unit = suspendCoroutineUninterceptedOrReturn { x ->
println("sUnit2")
x.resume(Unit)
COROUTINE_SUSPENDED
}
suspend fun sInt(): Int = suspendCoroutineUninterceptedOrReturn { x ->
println("sInt")
x.resume(42)
COROUTINE_SUSPENDED
}
suspend fun sInt2(): Int = suspendCoroutineUninterceptedOrReturn { x ->
println("sInt2")
x.resume(42)
COROUTINE_SUSPENDED
}
fun builderUnit(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun builderInt(c: suspend () -> Int) {
c.startCoroutine(EmptyContinuation)
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
s1()
s2()
s3()
s4()
s5()
s6()
s7()
s8()
s9()
s10()
s11()
s12()
s13()
s14()
s15()
s16()
s17()
s18(true)
s19(true)
s20(true)
s21()
s22()
s23(true)
s24()
return "OK"
}
fun s1() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s1$lambda${{[0-9]*}}
builderUnit {
// CHECK-NOT: call void @"kfun:$s1$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
println("s1")
}
// CHECK-LABEL: epilogue:
}
fun s2() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s2$lambda${{[0-9]*}}
builderUnit {
// CHECK-NOT: call void @"kfun:$s2$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
println("s2")
sUnit()
}
// CHECK-LABEL: epilogue:
}
fun s3() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s3$lambda${{[0-9]*}}
builderUnit {
// CHECK-NOT: call void @"kfun:$s3$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
println("s3")
sUnit()
return@builderUnit
}
// CHECK-LABEL: epilogue:
}
fun s4() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s4$lambda${{[0-9]*}}
builderInt {
// CHECK-NOT: call void @"kfun:$s4$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
println("s4")
return@builderInt sInt()
}
// CHECK-LABEL: epilogue:
}
fun s5() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s5$lambda${{[0-9]*}}
builderUnit {
// CHECK-NOT: call void @"kfun:$s5$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
println("s5")
run { sUnit() }
}
// CHECK-LABEL: epilogue:
}
fun s6() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s6$lambda${{[0-9]*}}
builderUnit {
// CHECK-NOT: call void @"kfun:$s6$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
run {
println("s6")
sUnit()
}
}
// CHECK-LABEL: epilogue:
}
fun s7() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s7$lambda${{[0-9]*}}
builderInt {
// CHECK-NOT: call void @"kfun:$s7$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
run {
println("s7")
sInt()
}
}
// CHECK-LABEL: epilogue:
}
fun s8() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s8$lambda${{[0-9]*}}
builderInt {
// CHECK-NOT: call void @"kfun:$s8$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
run {
println("s8")
return@builderInt sInt()
}
}
// CHECK-LABEL: epilogue:
}
fun s9() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s9$lambda${{[0-9]*}}
builderUnit {
// CHECK-NOT: call void @"kfun:$s9$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
run {
println("s9-1")
run {
println("s9-2")
sUnit()
}
}
}
// CHECK-LABEL: epilogue:
}
fun s10() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s10$lambda${{[0-9]*}}
builderInt {
// CHECK-NOT: call void @"kfun:$s10$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
run {
println("s10-1")
return@builderInt run {
println("s10-2")
sInt()
}
}
}
// CHECK-LABEL: epilogue:
}
fun s11() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s11$lambda${{[0-9]*}}
builderUnit {
// CHECK-NOT: call void @"kfun:$s11$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
println("s11")
sUnit()
return@builderUnit
}
// CHECK-LABEL: epilogue:
}
fun s12() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s12$lambda${{[0-9]*}}
builderUnit {
// CHECK-NOT: call void @"kfun:$s12$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
run {
println("s12")
sUnit()
return@builderUnit
}
}
// CHECK-LABEL: epilogue:
}
fun s13() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s13$lambda${{[0-9]*}}
builderUnit {
// CHECK-NOT: call void @"kfun:$s13$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
run {
println("s13")
sUnit()
}
return@builderUnit
}
// CHECK-LABEL: epilogue:
}
fun s14() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s14$lambda${{[0-9]*}}
builderUnit {
// CHECK-NOT: call void @"kfun:$s14$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
run {
println("s14")
sUnit()
return@run
}
}
// CHECK-LABEL: epilogue:
}
@Suppress("UNREACHABLE_CODE")
fun s15() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s15$lambda${{[0-9]*}}
builderInt {
// CHECK-NOT: call void @"kfun:$s15$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
run {
println("s15-1")
return@builderInt run {
println("s15-2")
return@builderInt sInt()
}
}
}
// CHECK-LABEL: epilogue:
}
fun s16() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s16$lambda${{[0-9]*}}
builderInt {
// CHECK-NOT: call void @"kfun:$s16$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
run outer@{
println("s16-1")
return@builderInt run inner@{
println("s16-2")
return@inner sInt()
}
}
}
// CHECK-LABEL: epilogue:
}
@Suppress("UNREACHABLE_CODE")
fun s17() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s17$lambda${{[0-9]*}}
builderInt {
// CHECK-NOT: call void @"kfun:$s17$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
return@builderInt run outer@{
println("s17-1")
return@builderInt run inner@{
println("s17-2")
return@outer sInt()
}
}
}
// CHECK-LABEL: epilogue:
}
fun s18(f: Boolean) {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s18$lambda${{[0-9]*}}
builderUnit {
// CHECK-NOT: call void @"kfun:$s18$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
if (f) {
println("s18-1")
sUnit()
} else {
println("s18-2")
sUnit2()
}
}
// CHECK-LABEL: epilogue:
}
fun s19(f: Boolean) {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s19$lambda${{[0-9]*}}
builderInt {
// CHECK-NOT: call void @"kfun:$s19$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
if (f) {
println("s19-1")
return@builderInt sInt()
} else {
println("s19-2")
return@builderInt sInt2()
}
}
// CHECK-LABEL: epilogue:
}
fun s20(f: Boolean) {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s20$lambda${{[0-9]*}}
builderInt {
// CHECK-NOT: call void @"kfun:$s20$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
return@builderInt if (f) {
println("s20-1")
sInt()
} else {
println("s20-2")
sInt2()
}
}
// CHECK-LABEL: epilogue:
}
fun s21() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s21$lambda${{[0-9]*}}
builderUnit {
// CHECK-NOT: call void @"kfun:$s21$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
try {
println("s21")
} catch (t: Throwable) {
sUnit()
}
}
// CHECK-LABEL: epilogue:
}
fun s22() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s22$lambda${{[0-9]*}}
builderInt {
// CHECK-NOT: call void @"kfun:$s22$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
try {
println("s22")
} catch (t: Throwable) {
return@builderInt sInt()
}
return@builderInt sInt2()
}
// CHECK-LABEL: epilogue:
}
fun s23(f: Boolean) {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s23$lambda${{[0-9]*}}
builderUnit {
// CHECK-NOT: call void @"kfun:$s23$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
val x = run {
if (f) {
println("s23")
sUnit()
return@builderUnit
}
42
}
println(x)
}
// CHECK-LABEL: epilogue:
}
fun s24() {
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:s24$lambda${{[0-9]*}}
builderUnit {
// CHECK: call void @"kfun:$s24$lambda${{[0-9]*}}COROUTINE${{[0-9]*}}.<init>
sInt()
}
// CHECK-LABEL: epilogue:
}
+19
View File
@@ -0,0 +1,19 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
var i = 1
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String = when(i) {
0 -> "FAIL: 0"
1 -> "OK"
2 -> "FAIL: 2"
else -> "FAIL: else"
}
// CHECK: when_case
// CHECK: when_next
// CHECK: when_case1
// CHECK: when_next2
// CHECK: when_case3
// CHECK: when_next4
// CHECK: when_exit
// CHECK: ret void