[K/N][Tests] Move filecheck and cinterop tests to /native/
^KT-61259
This commit is contained in:
committed by
Space Team
parent
05cbe66ee0
commit
bf0150108d
@@ -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"
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
+168
@@ -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"
|
||||
}
|
||||
+35
@@ -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{{.+}} }
|
||||
+27
@@ -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{{.*}}}
|
||||
+132
@@ -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"
|
||||
}
|
||||
+22
@@ -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"
|
||||
}
|
||||
+73
@@ -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}}
|
||||
+20
@@ -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"
|
||||
}
|
||||
+17
@@ -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"
|
||||
}
|
||||
Vendored
+22
@@ -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"
|
||||
}
|
||||
+26
@@ -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"
|
||||
}
|
||||
+18
@@ -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"
|
||||
}
|
||||
+18
@@ -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"
|
||||
}
|
||||
+18
@@ -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"
|
||||
}
|
||||
+18
@@ -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"
|
||||
}
|
||||
+12
@@ -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"
|
||||
}
|
||||
+39
@@ -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"
|
||||
}
|
||||
+114
@@ -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"
|
||||
}
|
||||
+98
@@ -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"
|
||||
}
|
||||
+132
@@ -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"
|
||||
}
|
||||
+29
@@ -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"
|
||||
}
|
||||
+111
@@ -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"
|
||||
}
|
||||
+27
@@ -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"
|
||||
}
|
||||
|
||||
+320
@@ -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:
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user