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

^KT-61259
This commit is contained in:
Vladimir Sukharev
2024-02-14 13:07:40 +01:00
committed by Space Team
parent 05cbe66ee0
commit bf0150108d
144 changed files with 1683 additions and 5542 deletions
@@ -0,0 +1,34 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: carrayPointers.def
---
int (*arrayPointer)[1];
int globalArray[3] = {1, 2, 3};
struct StructWithArrayPtr {
int (*arrayPointer)[1];
};
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import carrayPointers.*
import kotlin.test.*
import kotlinx.cinterop.*
fun box(): String {
arrayPointer = globalArray
assertEquals(globalArray[0], arrayPointer!![0])
arrayPointer!![0] = 15
assertEquals(15, globalArray[0])
memScoped {
val struct = alloc<StructWithArrayPtr>()
struct.arrayPointer = globalArray
assertEquals(globalArray[0], struct.arrayPointer!![0])
}
return "OK"
}
@@ -0,0 +1,41 @@
// TARGET_BACKEND: NATIVE
// FREE_CINTEROP_ARGS: -header auxiliaryCppSources.h
// MODULE: cinterop
// FILE: auxiliaryCppSources.def
# The def file is intentionally empty
# `auxiliaryCppSources.h` is meant to be included via `-header` free arg of cinterop tool
// FILE: auxiliaryCppSources.h
#ifdef __cplusplus
extern "C" {
#endif
const char* name();
#ifdef __cplusplus
}
#endif
// FILE: auxiliaryCppSources.cpp
#include <string>
#include "auxiliaryCppSources.h"
static std::string _name = "OK";
extern "C" const char* name() {
return _name.c_str();
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import auxiliaryCppSources.*
import kotlin.test.*
import kotlinx.cinterop.*
fun box(): String {
return name()!!.toKString()
}
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: cstdlib.def
headers = stdlib.h
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import cstdlib.*
import kotlinx.cinterop.*
import kotlin.test.*
fun box(): String {
assertEquals(257, atoi("257"))
val divResult = div(-5, 3)
val (quot, rem) = divResult.useContents { Pair(quot, rem) }
assertEquals(-1, quot)
assertEquals(-2, rem)
return "OK"
}
@@ -0,0 +1,36 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: cstdlib.def
headers = stdlib.h
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import cstdlib.*
import kotlinx.cinterop.*
import kotlin.test.*
fun box(): String {
val values = intArrayOf(14, 12, 9, 13, 8)
val count = values.size
qsort(values.refTo(0), count.convert(), IntVar.size.convert(), staticCFunction { a, b ->
val aValue = a!!.reinterpret<IntVar>()[0]
val bValue = b!!.reinterpret<IntVar>()[0]
(aValue - bValue)
})
assertEquals(8, values[0])
assertEquals(9, values[1])
assertEquals(12, values[2])
assertEquals(13, values[3])
assertEquals(14, values[4])
return "OK"
}
@@ -0,0 +1,75 @@
/*
* 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
// MODULE: cinterop
// FILE: cstdlib.def
headers = stdlib.h processor_count.h
compilerOpts.mingw = -D ADD_WINDOWS_ENV_FUNCTIONS
---
#ifdef ADD_WINDOWS_ENV_FUNCTIONS
static inline int setenv(const char *name, const char *value, int overwrite)
{
int errcode = 0;
if (!overwrite) {
size_t envsize = 0;
errcode = getenv_s(&envsize, NULL, 0, name);
if(errcode || envsize) return errcode;
}
return _putenv_s(name, value);
}
static inline int unsetenv(const char *name)
{
return _putenv_s(name, "");
}
#endif
// FILE: processor_count.h
int availableProcessors();
// FILE: processor_count.cpp
#include <thread>
extern "C" {
#include "processor_count.h"
int availableProcessors () { return std::thread::hardware_concurrency(); }
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class, kotlin.experimental.ExperimentalNativeApi::class)
import kotlin.native.*
import kotlin.test.*
import cstdlib.*
import kotlinx.cinterop.*
@OptIn(kotlin.ExperimentalStdlibApi::class)
fun box(): String {
val platformProcessors: Int = Platform.getAvailableProcessors()
assertTrue(platformProcessors > 0)
assertEquals(availableProcessors(), platformProcessors)
setenv("KOTLIN_NATIVE_AVAILABLE_PROCESSORS", "12345", 1)
assertEquals(Platform.getAvailableProcessors(), 12345)
setenv("KOTLIN_NATIVE_AVAILABLE_PROCESSORS", Long.MAX_VALUE.toString(), 1)
assertFailsWith<IllegalStateException> { Platform.getAvailableProcessors() }
setenv("KOTLIN_NATIVE_AVAILABLE_PROCESSORS", "-1", 1)
assertFailsWith<IllegalStateException> { Platform.getAvailableProcessors() }
setenv("KOTLIN_NATIVE_AVAILABLE_PROCESSORS", "0", 1)
assertFailsWith<IllegalStateException> { Platform.getAvailableProcessors() }
// windows doesn't support empty env variables
if (Platform.osFamily != OsFamily.WINDOWS) {
setenv("KOTLIN_NATIVE_AVAILABLE_PROCESSORS", "", 1)
assertFailsWith<IllegalStateException> { Platform.getAvailableProcessors() }
}
setenv("KOTLIN_NATIVE_AVAILABLE_PROCESSORS", "123aaaa", 1)
assertFailsWith<IllegalStateException> { Platform.getAvailableProcessors() }
unsetenv("KOTLIN_NATIVE_AVAILABLE_PROCESSORS")
assertEquals(Platform.getAvailableProcessors(), platformProcessors)
return "OK"
}
@@ -0,0 +1,151 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: cmacros.def
excludedMacros = EXCLUDED
---
int* ptr_call() {
return (int*) 1;
}
int int_call() {
return 42;
}
void void_call() {}
int arg_call(int x) {
return x;
}
typedef struct {
int value
} struct_t;
struct_t getStruct() {
return (struct_t){ 1 };
}
int global_var = 5;
#define TOO_MANY_ERRORS x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x
#define LEFT_BRACE {
#define ZERO 0
#define ONE 1
#define RIGHT_BRACE }
#define MAX_LONG 9223372036854775807
#define FOO_STRING "foo"
// This one should be ignored:
#define WIDE_FOO_STRING L"foo"
#define FOURTY_TWO 42
#define SEVENTEEN ((long long) 17)
#define ONE_POINT_ZERO 1.0
#define ONE_POINT_FIVE 1.5f
#define LEFT_PAREN (
#define NULL_PTR ((void*)0)
#define VOID_PTR ((void*)1)
#define INT_PTR ((int*)1)
#define PTR_SUM (INT_PTR + 1)
#define PTR_SUM_EXPECTED (sizeof(int) + 1)
#define RIGHT_PAREN )
enum {
INT_CALL = 1 // Should be replaced by macro below.
};
#define PTR_CALL ptr_call()
#define INT_CALL int_call()
#define CALL_SUM (int_call() + int_call())
#define GLOBAL_VAR (global_var)
// This one should be excluded:
#define EXCLUDED 42
// These ones should be ignored:
#define VOID_CALL (void_call())
#define ARG_CALL(x) (arg_call(x))
#define GET_STRUCT (getStruct())
#define UNDECLARED (undeclared())
#define BAD1 bar
#define BAD2 5;
#define BAD3 { foo(); }
void increment(int* counter);
#define increment(counter) { (*(counter))++; }
#define DEFAULT_DOUBLE_NAN __builtin_nan("")
#define DEFAULT_FLOAT_NAN __builtin_nanf("")
#define OTHER_DOUBLE_NAN __builtin_nan("0x123456789ab")
#define OTHER_FLOAT_NAN __builtin_nanf("0x12345")
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlin.experimental.ExperimentalNativeApi::class, kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.test.*
import cmacros.*
import kotlinx.cinterop.*
fun box(): String {
assertEquals("foo", FOO_STRING)
assertEquals(0, ZERO)
assertEquals(1, ONE)
assertEquals(Long.MAX_VALUE, MAX_LONG)
assertEquals(42, FOURTY_TWO)
val seventeen: Long = SEVENTEEN
assertEquals(17L, seventeen)
val onePointFive: Float = ONE_POINT_FIVE
val onePointZero: Double = ONE_POINT_ZERO
assertEquals(1.5f, onePointFive)
assertEquals(1.0, onePointZero)
val nullPtr: COpaquePointer? = NULL_PTR
val voidPtr: COpaquePointer? = VOID_PTR
val intPtr: CPointer<IntVar>? = INT_PTR
val ptrSum: CPointer<IntVar>? = PTR_SUM
val ptrCall: CPointer<IntVar>? = PTR_CALL
assertEquals(null, nullPtr)
assertEquals(1L, voidPtr.rawValue.toLong())
assertEquals(1L, intPtr.rawValue.toLong())
assertEquals(PTR_SUM_EXPECTED.toLong(), ptrSum.rawValue.toLong())
assertEquals(1L, ptrCall.rawValue.toLong())
assertEquals(42, INT_CALL)
assertEquals(84, CALL_SUM)
assertEquals(5, GLOBAL_VAR)
memScoped {
val counter = alloc<IntVar>()
counter.value = 42
increment(counter.ptr)
assertEquals(43, counter.value)
}
val floatNanBase = Float.NaN.toRawBits()
assertEquals(floatNanBase, 0x7fc00000)
val doubleNanBase = Double.NaN.toRawBits()
assertEquals(doubleNanBase, 0x7ff8000000000000L)
assertEquals(floatNanBase, DEFAULT_FLOAT_NAN.toRawBits())
assertEquals(doubleNanBase, DEFAULT_DOUBLE_NAN.toRawBits())
assertEquals(floatNanBase, OTHER_FLOAT_NAN.toRawBits())
assertEquals(doubleNanBase, OTHER_DOUBLE_NAN.toRawBits())
return "OK"
}
@@ -0,0 +1,24 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: mangling.def
---
// test mangling of special names
enum _Companion {Companion, Any};
enum _Companion companion = Companion;
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlinx.cinterop.*
import kotlin.test.*
import mangling.*
fun box(): String {
companion = _Companion.`Companion$`
assertEquals(_Companion.`Companion$`, companion)
return "OK"
}
@@ -0,0 +1,23 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: mangling2.def
---
// test mangling of special names
enum Companion {One, Two};
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlinx.cinterop.*
import kotlin.test.*
import mangling2.*
fun box(): String {
val mangled = `Companion$`.Two
assertEquals(`Companion$`.Two, mangled)
return "OK"
}
@@ -0,0 +1,55 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: mangling_keywords.def
---
#define as "as"
#define class "class"
#define dynamic "dynamic"
#define false "false"
#define fun "fun"
#define in "in"
#define interface "interface"
#define is "is"
#define null "null"
#define object "object"
#define package "package"
#define super "super"
#define this "this"
#define throw "throw"
#define true "true"
#define try "try"
#define typealias "typealias"
#define val "val"
#define var "var"
#define when "when"
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.test.*
import mangling_keywords.*
fun box(): String {
// Check that all Kotlin keywords are imported and mangled.
assertEquals("as", `as`)
assertEquals("class", `class`)
assertEquals("dynamic", `dynamic`)
assertEquals("false", `false`)
assertEquals("fun", `fun`)
assertEquals("in", `in`)
assertEquals("interface", `interface`)
assertEquals("is", `is`)
assertEquals("null", `null`)
assertEquals("object", `object`)
assertEquals("package", `package`)
assertEquals("super", `super`)
assertEquals("this", `this`)
assertEquals("throw", `throw`)
assertEquals("true", `true`)
assertEquals("try", `try`)
assertEquals("typealias", `typealias`)
assertEquals("val", `val`)
assertEquals("var", `var`)
assertEquals("when", `when`)
return "OK"
}
@@ -0,0 +1,131 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: mangling_keywords2.def
---
enum KotlinKeywordsEnum {
as,
class,
dynamic,
false,
fun,
in,
interface,
is,
null,
object,
package,
super,
this,
throw,
true,
try,
typealias,
val,
var,
when,
};
struct KotlinKeywordsStruct {
int as;
int class;
int dynamic;
int false;
int fun;
int in;
int interface;
int is;
int null;
int object;
int package;
int super;
int this;
int throw;
int true;
int try;
int typealias;
int val;
int var;
int when;
};
struct KotlinKeywordsStruct createKotlinKeywordsStruct() {
struct KotlinKeywordsStruct s = {
.as = 0,
.class = 0,
.dynamic = 0,
.false = 0,
.fun = 0,
.in = 0,
.interface = 0,
.is = 0,
.null = 0,
.object = 0,
.package = 0,
.super = 0,
.this = 0,
.throw = 0,
.true = 0,
.try = 0,
.typealias = 0,
.val = 0,
.var = 0,
.when = 0,
};
return s;
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.test.*
import mangling_keywords2.*
import kotlinx.cinterop.useContents
fun box(): String {
// Check that all Kotlin keywords are imported and mangled.
createKotlinKeywordsStruct().useContents {
assertEquals(0, `as`)
assertEquals(0, `class`)
assertEquals(0, `dynamic`)
assertEquals(0, `false`)
assertEquals(0, `fun`)
assertEquals(0, `in`)
assertEquals(0, `interface`)
assertEquals(0, `is`)
assertEquals(0, `null`)
assertEquals(0, `object`)
assertEquals(0, `package`)
assertEquals(0, `super`)
assertEquals(0, `this`)
assertEquals(0, `throw`)
assertEquals(0, `true`)
assertEquals(0, `try`)
assertEquals(0, `typealias`)
assertEquals(0, `val`)
assertEquals(0, `var`)
assertEquals(0, `when`)
}
assertEquals(KotlinKeywordsEnum.`as`, KotlinKeywordsEnum.`as`)
assertEquals(KotlinKeywordsEnum.`class`, KotlinKeywordsEnum.`class`)
assertEquals(KotlinKeywordsEnum.`dynamic`, KotlinKeywordsEnum.`dynamic`)
assertEquals(KotlinKeywordsEnum.`false`, KotlinKeywordsEnum.`false`)
assertEquals(KotlinKeywordsEnum.`fun`, KotlinKeywordsEnum.`fun`)
assertEquals(KotlinKeywordsEnum.`in`, KotlinKeywordsEnum.`in`)
assertEquals(KotlinKeywordsEnum.`interface`, KotlinKeywordsEnum.`interface`)
assertEquals(KotlinKeywordsEnum.`is`, KotlinKeywordsEnum.`is`)
assertEquals(KotlinKeywordsEnum.`null`, KotlinKeywordsEnum.`null`)
assertEquals(KotlinKeywordsEnum.`object`, KotlinKeywordsEnum.`object`)
assertEquals(KotlinKeywordsEnum.`package`, KotlinKeywordsEnum.`package`)
assertEquals(KotlinKeywordsEnum.`super`, KotlinKeywordsEnum.`super`)
assertEquals(KotlinKeywordsEnum.`this`, KotlinKeywordsEnum.`this`)
assertEquals(KotlinKeywordsEnum.`throw`, KotlinKeywordsEnum.`throw`)
assertEquals(KotlinKeywordsEnum.`true`, KotlinKeywordsEnum.`true`)
assertEquals(KotlinKeywordsEnum.`try`, KotlinKeywordsEnum.`try`)
assertEquals(KotlinKeywordsEnum.`typealias`, KotlinKeywordsEnum.`typealias`)
assertEquals(KotlinKeywordsEnum.`val`, KotlinKeywordsEnum.`val`)
assertEquals(KotlinKeywordsEnum.`var`, KotlinKeywordsEnum.`var`)
assertEquals(KotlinKeywordsEnum.`when`, KotlinKeywordsEnum.`when`)
return "OK"
}
@@ -0,0 +1,25 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
// TARGET_BACKEND: NATIVE
// IGNORE_NATIVE: target=linux_arm64
// MODULE: cinterop
// FILE: sysstat.def
headers = sys/stat.h
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import sysstat.*
import kotlin.test.*
import kotlinx.cinterop.*
fun box(): String {
val statBuf = nativeHeap.alloc<stat>()
assertEquals(0, stat("/", statBuf.ptr))
assertEquals("0", statBuf.st_uid.toString())
return "OK"
}
@@ -0,0 +1,51 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: structAnonym.def
---
/*
* Test of return/send-by-value for aggregate type (struct or union) with anonymous inner struct or union member.
* Specific issues: alignment, packed, nested named and anon struct/union, other anon types (named field of anon struct type; anon bitfield)
*/
#include <inttypes.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winitializer-overrides"
struct StructAnonRecordMember_ExplicitAlignment {
char a;
struct {
__attribute__((aligned(4)))
char x;
};
};
static struct StructAnonRecordMember_ExplicitAlignment retByValue_StructAnonRecordMember_ExplicitAlignment() {
struct StructAnonRecordMember_ExplicitAlignment t = {
.a = 'a',
.x = 'x'
};
return t;
}
#pragma clang diagnostic pop
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlinx.cinterop.*
import kotlin.test.*
import structAnonym.*
fun box(): String {
retByValue_StructAnonRecordMember_ExplicitAlignment()
.useContents {
assertEquals('a', a.toInt().toChar())
assertEquals('x', x.toInt().toChar())
}
return "OK"
}
@@ -0,0 +1,52 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: structAnonym.def
---
/*
* Test of return/send-by-value for aggregate type (struct or union) with anonymous inner struct or union member.
* Specific issues: alignment, packed, nested named and anon struct/union, other anon types (named field of anon struct type; anon bitfield)
*/
#include <inttypes.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winitializer-overrides"
// trivial alignment: member is already aligned, but this implies implicit larger alignment of the root struct
struct StructAnonRecordMember_ImplicitAlignment {
int32_t a[4];
struct {
int b __attribute__((aligned(16)));
};
};
static struct StructAnonRecordMember_ImplicitAlignment retByValue_StructAnonRecordMember_ImplicitAlignment() {
struct StructAnonRecordMember_ImplicitAlignment t = {
.a = {1,2,3,4},
.b = 42
};
return t;
}
#pragma clang diagnostic pop
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlinx.cinterop.*
import kotlin.test.*
import structAnonym.*
fun box(): String {
retByValue_StructAnonRecordMember_ImplicitAlignment()
.useContents {
assertEquals(1, a[0])
assertEquals(4, a[3])
assertEquals(42, b)
}
return "OK"
}
@@ -0,0 +1,68 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: structAnonym.def
---
/*
* Test of return/send-by-value for aggregate type (struct or union) with anonymous inner struct or union member.
* Specific issues: alignment, packed, nested named and anon struct/union, other anon types (named field of anon struct type; anon bitfield)
*/
#include <inttypes.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winitializer-overrides"
// Deep nesting
struct StructAnonRecordMember_Nested {
int x;
union { // implicitly aligned to 8 bytes due to int64, or 4 bytes at 32-bit arch
int a[2];
struct {
int64_t b;
};
};
char z;
double y;
};
static struct StructAnonRecordMember_Nested retByValue_StructAnonRecordMember_Nested() {
struct StructAnonRecordMember_Nested c = {
.x = 37,
.b = 42,
.z = 'z',
.y = 3.14
};
return c;
}
static int sendByValue_StructAnonRecordMember_Nested(struct StructAnonRecordMember_Nested c) {
return c.a[0] + 2 * c.a[1];
}
#pragma clang diagnostic pop
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlinx.cinterop.*
import kotlin.test.*
import structAnonym.*
fun box(): String {
retByValue_StructAnonRecordMember_Nested()
.useContents {
assertEquals(37, x)
assertEquals(42, b)
assertEquals('z', z.toInt().toChar())
assertEquals(3.14, y)
a[0] = 3
a[1] = 5
assertEquals(3 + 2*5, sendByValue_StructAnonRecordMember_Nested(this.readValue()))
}
return "OK"
}
@@ -0,0 +1,74 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: structAnonym.def
---
/*
* Test of return/send-by-value for aggregate type (struct or union) with anonymous inner struct or union member.
* Specific issues: alignment, packed, nested named and anon struct/union, other anon types (named field of anon struct type; anon bitfield)
*/
#include <inttypes.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winitializer-overrides"
// Basic, 2 levels
struct StructAnonRecordMember_Complicate {
char first; // __attribute__((aligned(16)));
union {
int a[2];
union { char c1; int c2; };
struct { char b1; int64_t b2; }; // implicit 64-bits alignment
};
char second __attribute__((aligned(16)));
struct {
char x;
struct { int64_t b11, b12; } Y2;
int32_t f __attribute__((aligned(16)));
}; // __attribute__((aligned(16)));
char last;
};
#define INIT(T, x) struct T x = \
{ \
.first = 'a', \
.b1 = 'b', \
.b2 = 42, \
.second = 's', \
.last = 'z', \
.f = 314, \
.Y2 = {11, 12} \
}
static struct StructAnonRecordMember_Complicate retByValue_StructAnonRecordMember_Complicate() {
INIT(StructAnonRecordMember_Complicate, c);
return c;
}
#pragma clang diagnostic pop
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlinx.cinterop.*
import kotlin.test.*
import structAnonym.*
fun box(): String {
retByValue_StructAnonRecordMember_Complicate()
.useContents{
assertEquals('a', first.toInt().toChar())
assertEquals('s', second.toInt().toChar())
assertEquals('z', last.toInt().toChar())
assertEquals('b', b1.toInt().toChar())
assertEquals(42L, b2)
assertEquals(314, f)
assertEquals(11L, Y2.b11)
}
return "OK"
}
@@ -0,0 +1,63 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: structAnonym.def
---
/*
* Test of return/send-by-value for aggregate type (struct or union) with anonymous inner struct or union member.
* Specific issues: alignment, packed, nested named and anon struct/union, other anon types (named field of anon struct type; anon bitfield)
*/
#include <inttypes.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winitializer-overrides"
union _GLKVector3
{
struct { float x, y, z; };
struct { float r, g, b; };
struct { float s, t, p; };
float v[3];
};
static union _GLKVector3 get_GLKVector3() {
union _GLKVector3 ret = {{1, 2, 3}};
return ret;
}
static float hash_GLKVector3(union _GLKVector3 x) {
union _GLKVector3 ret = {{1, 2, 3}};
return x.x + 2.0f * x.y + 4.0f * x.z;
}
#pragma clang diagnostic pop
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlinx.cinterop.*
import kotlin.test.*
import structAnonym.*
fun box(): String {
get_GLKVector3().useContents {
assertEquals(1.0f, x)
assertEquals(2.0f, g)
assertEquals(3.0f, p)
r = 0.1f
g = 0.2f
b = 0.3f
assertEquals(v[0], r)
assertEquals(v[1], g)
assertEquals(v[2], b)
val ret = hash_GLKVector3(this.readValue())
assertEquals(s + 2f * t + 4f * p , ret)
}
return "OK"
}
@@ -0,0 +1,75 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: structAnonym.def
---
/*
* Test of return/send-by-value for aggregate type (struct or union) with anonymous inner struct or union member.
* Specific issues: alignment, packed, nested named and anon struct/union, other anon types (named field of anon struct type; anon bitfield)
*/
#include <inttypes.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winitializer-overrides"
#pragma pack(2)
struct StructAnonRecordMember_Packed2 {
char first;
union {
int a[2];
union { char c1; int c2; };
struct { char b1; int64_t b2; };
};
char second;
struct {
char x;
struct { int64_t b11, b12; } Y2;
int32_t f;
} __attribute__((aligned(16)));
char last;
} __attribute__ ((packed));
#pragma pack()
#define INIT(T, x) struct T x = \
{ \
.first = 'a', \
.b1 = 'b', \
.b2 = 42, \
.second = 's', \
.last = 'z', \
.f = 314, \
.Y2 = {11, 12} \
}
static struct StructAnonRecordMember_Packed2 retByValue_StructAnonRecordMember_Packed2() {
INIT(StructAnonRecordMember_Packed2, c);
return c;
}
#pragma clang diagnostic pop
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlinx.cinterop.*
import kotlin.test.*
import structAnonym.*
fun box(): String {
retByValue_StructAnonRecordMember_Packed2()
.useContents{
assertEquals('a', first.toInt().toChar())
assertEquals('s', second.toInt().toChar())
assertEquals('z', last.toInt().toChar())
assertEquals('b', b1.toInt().toChar())
assertEquals(42L, b2)
assertEquals(314, f)
assertEquals(11L, Y2.b11)
}
return "OK"
}
@@ -0,0 +1,76 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: structAnonym.def
---
/*
* Test of return/send-by-value for aggregate type (struct or union) with anonymous inner struct or union member.
* Specific issues: alignment, packed, nested named and anon struct/union, other anon types (named field of anon struct type; anon bitfield)
*/
#include <inttypes.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winitializer-overrides"
// Nested struct may be packed too
#pragma pack(2)
struct StructAnonRecordMember_Packed2 {
char first;
union {
int a[2];
union { char c1; int c2; };
struct { char b1; int64_t b2; };
};
char second;
struct {
char x;
struct { int64_t b11, b12; } Y2;
int32_t f;
} __attribute__((aligned(16)));
char last;
} __attribute__ ((packed));
#pragma pack()
#define INIT(T, x) struct T x = \
{ \
.first = 'a', \
.b1 = 'b', \
.b2 = 42, \
.second = 's', \
.last = 'z', \
.f = 314, \
.Y2 = {11, 12} \
}
static struct StructAnonRecordMember_Packed2 retByValue_StructAnonRecordMember_Packed2() {
INIT(StructAnonRecordMember_Packed2, c);
return c;
}
#pragma clang diagnostic pop
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlinx.cinterop.*
import kotlin.test.*
import structAnonym.*
fun box(): String {
retByValue_StructAnonRecordMember_Packed2()
.useContents{
assertEquals('a', first.toInt().toChar())
assertEquals('s', second.toInt().toChar())
assertEquals('z', last.toInt().toChar())
assertEquals('b', b1.toInt().toChar())
assertEquals(42L, b2)
assertEquals(314, f)
assertEquals(11L, Y2.b11)
}
return "OK"
}
@@ -0,0 +1,75 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: structAnonym.def
---
/*
* Test of return/send-by-value for aggregate type (struct or union) with anonymous inner struct or union member.
* Specific issues: alignment, packed, nested named and anon struct/union, other anon types (named field of anon struct type; anon bitfield)
*/
#include <inttypes.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winitializer-overrides"
// Nested struct may be packed too
#pragma pack(1)
struct StructAnonRecordMember_PragmaPacked {
char first;
union {
int a[2];
union { char c1; int c2; };
struct { char b1; int64_t b2; };
};
char second;
struct {
char x;
struct { int64_t b11, b12; } Y2;
int32_t f __attribute__((aligned(16))); // another kind of alignment
};
char last;
} __attribute__ ((packed));
#pragma pack()
#define INIT(T, x) struct T x = \
{ \
.first = 'a', \
.b1 = 'b', \
.b2 = 42, \
.second = 's', \
.last = 'z', \
.f = 314, \
.Y2 = {11, 12} \
}
static struct StructAnonRecordMember_PragmaPacked retByValue_StructAnonRecordMember_PragmaPacked() {
INIT(StructAnonRecordMember_PragmaPacked, c);
return c;
}
#pragma clang diagnostic pop
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlinx.cinterop.*
import kotlin.test.*
import structAnonym.*
fun box(): String {
retByValue_StructAnonRecordMember_PragmaPacked()
.useContents{
assertEquals('a', first.toInt().toChar())
assertEquals('s', second.toInt().toChar())
assertEquals('z', last.toInt().toChar())
assertEquals('b', b1.toInt().toChar())
assertEquals(42L, b2)
assertEquals(314, f)
assertEquals(11L, Y2.b11)
}
return "OK"
}
@@ -0,0 +1,193 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: cstructs.def
nonStrictEnums = NonStrict
---
typedef struct {
int i;
} Trivial;
enum E {
R, G, B
};
enum NonStrict {
N, S, K
};
struct Complex {
unsigned int ui;
Trivial t;
struct Complex* next;
enum E e;
enum NonStrict nonStrict;
int arr[2];
_Bool b;
};
struct __attribute__((packed)) Packed {
int i : 1;
enum E e : 2;
};
struct Complex produceComplex() {
struct Complex complex = {
.ui = 128,
.t = {1},
.next = 0,
.e = R,
.nonStrict = K,
.arr = {-51, -19},
.b = 1
};
return complex;
};
struct WithFlexibleArray {
int size;
int data[];
};
struct WithFlexibleArrayWithPadding {
int size;
char c;
long long data[];
};
void fillArray(struct WithFlexibleArrayWithPadding *flex, int count) {
flex->size = count;
flex->c = '!';
for (int i = 0; i < count; i++) {
flex->data[i] = (((long long)i) << 32) | (i * 100);
}
}
struct WithZeroSizedArray {
int size;
int data[0];
};
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import cstructs.*
import kotlinx.cinterop.*
import kotlin.test.*
fun box(): String {
produceComplex().useContents {
assertEquals(ui, 128u)
ui = 333u
assertEquals(ui, 333u)
assertEquals(t.i, 1)
t.i += 15
assertEquals(t.i, 16)
assertEquals(next, null)
next = this.ptr
assertEquals(next, this.ptr)
// Check null pointer because it has Nothing? type.
next = null
assertEquals(next, null)
assertEquals(e, E.R)
e = E.G
assertEquals(e, E.G)
assertEquals(K, nonStrict)
nonStrict = S
assertEquals(S, nonStrict)
assertEquals(arr[0], -51)
assertEquals(arr[1], -19)
arr[0] = 51
arr[1] = 19
assertEquals(arr[0], 51)
assertEquals(arr[1], 19)
assertEquals(true, b)
b = false
assertEquals(false, b)
// Check that subtyping via Nothing-returning functions does not break compiler.
assertFailsWith<NotImplementedError> {
ui = TODO()
t.i = TODO()
next = TODO()
e = TODO()
nonStrict = TODO()
b = TODO()
}
}
memScoped {
val packed = alloc<Packed>()
packed.i = -1
assertEquals(-1, packed.i)
packed.e = E.R
assertEquals(E.R, packed.e)
// Check that subtyping via Nothing-returning functions does not break compiler.
assertFailsWith<NotImplementedError> {
packed.i = TODO()
packed.e = TODO()
}
}
// Check that generics doesn't break anything.
checkEnumSubTyping(E.R)
checkIntSubTyping(630090)
memScoped {
val SIZE = 10
val flex = alloc(sizeOf<WithFlexibleArray>() + sizeOf<IntVar>() * SIZE, alignOf<WithFlexibleArray>()).reinterpret<WithFlexibleArray>()
flex.size = SIZE
for (i in 0 until SIZE) {
flex.data[i] = i
}
assertEquals(SIZE, flex.size)
for (i in 0 until SIZE) {
assertEquals(i, flex.data[i])
}
}
memScoped {
val SIZE = 10
val flex = alloc(sizeOf<WithZeroSizedArray>() + sizeOf<IntVar>() * SIZE, alignOf<WithZeroSizedArray>()).reinterpret<WithZeroSizedArray>()
assertEquals(4, sizeOf<WithZeroSizedArray>())
assertEquals(4, alignOf<WithZeroSizedArray>())
flex.size = SIZE
for (i in 0 until SIZE) {
flex.data[i] = i
}
assertEquals(SIZE, flex.size)
for (i in 0 until SIZE) {
assertEquals(i, flex.data[i])
}
}
memScoped {
val SIZE = 10
assertEquals(8, sizeOf<WithFlexibleArrayWithPadding>())
assertEquals(8, alignOf<WithFlexibleArrayWithPadding>())
val flex = alloc(sizeOf<WithFlexibleArrayWithPadding>() + sizeOf<LongVar>() * SIZE, alignOf<WithFlexibleArrayWithPadding>())
.reinterpret<WithFlexibleArrayWithPadding>()
fillArray(flex.ptr, SIZE)
assertEquals(SIZE, flex.size)
assertEquals('!'.code.toByte(), flex.c);
for (i in 0 until SIZE) {
assertEquals((i.toLong() shl 32) or (i.toLong() * 100), flex.data[i])
}
}
return "OK"
}
fun <T : E> checkEnumSubTyping(e: T) = memScoped {
val s = alloc<Complex>()
s.e = e
}
fun <T : Int> checkIntSubTyping(x: T) = memScoped {
val s = alloc<Trivial>()
s.i = x
}
@@ -0,0 +1,132 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: ctypes.def
---
// KT-28065
struct StructWithConstFields {
int x;
const int y;
};
struct StructWithConstFields getStructWithConstFields() {
struct StructWithConstFields result = { 111, 222 };
return result;
}
enum ForwardDeclaredEnum;
enum ForwardDeclaredEnum {
ZERO, ONE, TWO
};
static int vlaSum(int size, int array[size]) {
int result = 0;
for (int i = 0; i < size; ++i) {
result += array[i];
}
return result;
}
static int vlaSum2D(int size, int array[][size]) {
int result = 0;
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
result += array[i][j];
}
}
return result;
}
static int vlaSum2DBothDimensions(int rows, int columns, int array[rows][columns]) {
int result = 0;
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns; ++j) {
result += array[i][j];
}
}
return result;
}
/*
// Not supported by clang:
static int vlaSum2DForward(int size; int array[][size], int size) {
return vlaSum2D(size, array);
}
*/
// "Strict" enums heuristic based on whether enum constants are defined explicitly:
enum StrictEnum1 {
StrictEnum1A,
StrictEnum1B
};
enum StrictEnum2 {
StrictEnum2A __attribute__((unused)),
StrictEnum2B __attribute__((unused))
};
enum NonStrictEnum1 {
NonStrictEnum1A = 0,
NonStrictEnum1B __attribute__((unused))
};
enum NonStrictEnum2 {
NonStrictEnum2A,
NonStrictEnum2B __attribute__((unused)) = 1
};
// KT-34025
typedef char Char;
enum EnumCharBase : Char {
EnumCharBaseA,
EnumCharBaseB
};
static int sendEnum(enum EnumCharBase x) {
return (int)x + 2;
}
enum EnumExplicitChar : char {
EnumExplicitCharA = 'a',
EnumExplicitCharB = 'b',
EnumExplicitCharDup = 'a'
};
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlinx.cinterop.*
import kotlin.native.*
import kotlin.test.*
import ctypes.*
fun box(): String {
getStructWithConstFields().useContents {
assertEquals(111, x)
assertEquals(222, y)
}
assertEquals(1u, ForwardDeclaredEnum.ONE.value)
assertEquals(6, vlaSum(3, cValuesOf(1, 2, 3)))
assertEquals(10, vlaSum2D(2, cValuesOf(1, 2, 3, 4)))
assertEquals(21, vlaSum2DBothDimensions(2, 3, cValuesOf(1, 2, 3, 4, 5, 6)))
// Not supported by clang:
// assertEquals(10, vlaSum2DForward(cValuesOf(1, 2, 3, 4), 2))
assertEquals(0u, StrictEnum1.StrictEnum1A.value)
assertEquals(1u, StrictEnum2.StrictEnum2B.value)
assertEquals(0u, NonStrictEnum1A)
assertEquals(1u, NonStrictEnum2B)
assertEquals(1, EnumCharBase.EnumCharBaseB.value)
assertEquals(3, sendEnum(EnumCharBase.EnumCharBaseB))
assertEquals('a'.toByte(), EnumExplicitCharA)
assertEquals('b'.toByte(), EnumExplicitCharB)
assertEquals(EnumExplicitCharA, EnumExplicitCharDup)
return "OK"
}
@@ -0,0 +1,63 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: cunion.def
---
typedef union {
short s;
long long ll;
} BasicUnion;
typedef struct {
union {
int i;
float f;
} as;
} StructWithUnion;
typedef union {
unsigned int i : 31;
unsigned char b : 1;
} Packed;
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlin.experimental.ExperimentalNativeApi::class, kotlinx.cinterop.ExperimentalForeignApi::class)
import cunion.*
import kotlinx.cinterop.*
import kotlin.native.*
import kotlin.test.*
fun box(): String {
memScoped {
val basicUnion = alloc<BasicUnion>()
for (value in Short.MIN_VALUE..Short.MAX_VALUE) {
basicUnion.ll = value.toLong()
val expected = if (Platform.isLittleEndian) {
value
} else {
value.toLong() ushr (Long.SIZE_BITS - Short.SIZE_BITS)
}
assertEquals(expected.toShort(), basicUnion.s)
}
}
memScoped {
val struct = alloc<StructWithUnion>()
struct.`as`.i = Float.NaN.toRawBits()
assertEquals(Float.NaN, struct.`as`.f)
}
memScoped {
val union = alloc<Packed>()
union.b = 1u
var expected = if (Platform.isLittleEndian) {
1u
} else {
1u shl (Int.SIZE_BITS - Byte.SIZE_BITS)
}
assertEquals(expected, union.i)
union.i = 0u
assertEquals(0u, union.b)
}
return "OK"
}
@@ -0,0 +1,47 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: cunsupported.def
compilerOpts = -mno-xsave
---
static void noAttr() {}
__attribute__((always_inline)) noTargetAttr() {}
__attribute__((always_inline, __target__("xsave"))) void plainAttrs1() {}
__attribute__((__target__("xsave"), always_inline)) void plainAttrs2() {}
#define TARGET __target__
__attribute__((always_inline, TARGET("xsave"))) void macroAttr1() {}
__attribute__((TARGET("xsave"), always_inline)) void macroAttr2() {}
#define TARGET_ATTR __target__("xsave")
__attribute__((TARGET_ATTR, always_inline)) void macroAttr3() {}
__attribute__((always_inline, TARGET_ATTR)) void macroAttr4() {}
#define ALL_ATTRS1 __attribute__((always_inline, __target__("xsave")))
ALL_ATTRS1 void macroAttr5() {}
#define ALL_ATTRS2 __attribute__((always_inline, __target__("xsave")))
ALL_ATTRS2 void macroAttr6() {}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.test.*
import cunsupported.*
fun box(): String {
noAttr()
noTargetAttr()
return "OK"
}
@@ -0,0 +1,30 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: cvalues.def
---
_Bool isNullString(const char* str) {
return str == (const char*)0;
}
typedef const short* LPCWSTR;
_Bool isNullWString(LPCWSTR str) {
return str == (LPCWSTR)0;
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlinx.cinterop.*
import kotlin.test.*
import cvalues.*
fun box(): String {
assertTrue(isNullString(null))
assertTrue(isNullWString(null))
assertFalse(isNullString("a"))
assertFalse(isNullWString("b"))
return "OK"
}
@@ -0,0 +1,64 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: cvectors.def
---
typedef float __attribute__ ((__vector_size__ (16))) KVector4f;
typedef int __attribute__ ((__vector_size__ (16))) KVector4i32;
struct Complex {
unsigned int ui;
KVector4f vec4f;
struct Complex* next;
int arr[2];
};
struct Complex produceComplexVector() {
struct Complex complex = {
.ui = 128,
.vec4f = {1.0, 1.0, 1.0, 1.0},
.next = 0,
.arr = {-51, -19}
};
return complex;
};
static float sendV4F(KVector4f v) {
return v[0] + 2 * v[1] + 4 * v[2] + 8 * v[3];
}
static int sendV4I(KVector4i32 v) {
return v[0] + 2 * v[1] + 4 * v[2] + 8 * v[3];
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class, kotlin.experimental.ExperimentalNativeApi::class)
import kotlinx.cinterop.*
import kotlinx.cinterop.vectorOf
import kotlin.native.*
import kotlin.test.*
import cvectors.*
fun box(): String {
produceComplexVector().useContents {
assertEquals(vec4f, vectorOf(1.0f, 1.0f, 1.0f, 1.0f))
vec4f = vectorOf(0.0f, 0.0f, 0.0f, 0.0f)
assertEquals(vec4f, vectorOf(0.0f, 0.0f, 0.0f, 0.0f))
}
// FIXME: KT-36285
if (Platform.osFamily != OsFamily.LINUX || Platform.cpuArchitecture != CpuArchitecture.ARM32) {
assertEquals(49, sendV4I(vectorOf(1, 2, 3, 4)))
}
assertEquals(49, (sendV4F(vectorOf(1f, 2f, 3f, 4f)) + 0.00001).toInt())
memScoped {
val vector = alloc<KVector4i32Var>().also {
it.value = vectorOf(1, 2, 3, 4)
}
assertEquals(vector.value, vectorOf(1, 2, 3, 4))
}
return "OK"
}
@@ -0,0 +1,138 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
// May need disabling when gcSchedulerType=aggressive . since it may be too slow
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: bitfields.def
---
enum B2 {
ZERO, ONE, TWO, THREE
};
enum E : short {
A, B
};
struct __attribute__((packed)) S {
long long x1 : 1;
enum B2 x2 : 2;
unsigned short x3 : 3;
unsigned int x4 : 4;
int x5 : 5;
long long x6 : 63;
enum E x7: 2;
_Bool x8 : 1;
struct { int x9:4; };
};
static long long getX1(struct S* s) { return s->x1; }
static enum B2 getX2(struct S* s) { return s->x2; }
static unsigned short getX3(struct S* s) { return s->x3; }
static unsigned int getX4(struct S* s) { return s->x4; }
static int getX5(struct S* s) { return s->x5; }
static long long getX6(struct S* s) { return s->x6; }
static enum E getX7(struct S* s) { return s->x7; }
static _Bool getX8(struct S* s) { return s->x8; }
static int getX9(struct S* s) { return s->x9; }
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import bitfields.*
import kotlinx.cinterop.*
fun assertEquals(value1: Any?, value2: Any?) {
if (value1 != value2)
throw AssertionError("Expected $value1, got $value2")
}
fun check(s: S, x1: Long, x2: B2, x3: UShort, x4: UInt, x5: Int, x6: Long, x7: E, x8: Boolean, x9: Int) {
assertEquals(x1, s.x1)
assertEquals(x1, getX1(s.ptr))
assertEquals(x2, s.x2)
assertEquals(x2, getX2(s.ptr))
assertEquals(x3, s.x3)
assertEquals(x3, getX3(s.ptr))
assertEquals(x4, s.x4)
assertEquals(x4, getX4(s.ptr))
assertEquals(x5, s.x5)
assertEquals(x5, getX5(s.ptr))
assertEquals(x6, s.x6)
assertEquals(x6, getX6(s.ptr))
assertEquals(x7, s.x7)
assertEquals(x7, getX7(s.ptr))
assertEquals(x8, s.x8)
assertEquals(x8, getX8(s.ptr))
assertEquals(x9, s.x9)
assertEquals(x9, getX9(s.ptr))
}
fun assign(s: S, x1: Long, x2: B2, x3: UShort, x4: UInt, x5: Int, x6: Long, x7: E, x8: Boolean, x9: Int) {
s.x1 = x1
s.x2 = x2
s.x3 = x3
s.x4 = x4
s.x5 = x5
s.x6 = x6
s.x7 = x7
s.x8 = x8
s.x9 = x9
}
fun assignReversed(s: S, x1: Long, x2: B2, x3: UShort, x4: UInt, x5: Int, x6: Long, x7: E, x8: Boolean, x9: Int) {
s.x9 = x9
s.x8 = x8
s.x7 = x7
s.x6 = x6
s.x5 = x5
s.x4 = x4
s.x3 = x3
s.x2 = x2
s.x1 = x1
}
fun test(s: S, x1: Long, x2: B2, x3: UShort, x4: UInt, x5: Int, x6: Long, x7: E, x8: Boolean, x9: Int) {
assign(s, x1, x2, x3, x4, x5, x6, x7, x8, x9)
check(s, x1, x2, x3, x4, x5, x6, x7, x8, x9)
assignReversed(s, x1, x2, x3, x4, x5, x6, x7, x8, x9)
check(s, x1, x2, x3, x4, x5, x6, x7, x8, x9)
// Also check with some insignificant bits modified:
assign(s, x1 + 2, x2, (x3 + 8u).toUShort(), x4 - 16u, x5 + 32, x6 + Long.MIN_VALUE, x7, x8, x9 + 16)
check(s, x1, x2, x3, x4, x5, x6, x7, x8, x9)
assignReversed(s, x1 + 2, x2, (x3 + 8u).toUShort(), x4 - 16u, x5 + 32, x6 + Long.MIN_VALUE, x7, x8, x9 + 16)
check(s, x1, x2, x3, x4, x5, x6, x7, x8, x9)
}
fun box(): String {
memScoped {
val s = alloc<S>()
for (x1 in -1L..0L)
for (x2 in arrayOf(B2.ZERO, B2.ONE, B2.THREE))
for (x3 in ushortArrayOf(0u, 2u, 7u))
for (x4 in uintArrayOf(0u, 6u, 15u))
for (x5 in intArrayOf(-16, -1, 0, 5, 15))
for (x6 in longArrayOf(Long.MIN_VALUE/2, -325L, 0, 1L shl 48, Long.MAX_VALUE/2))
for (x7 in E.values())
for (x8 in arrayOf(false, true))
for (x9 in intArrayOf(-8, -1, 0, 5, 7)) // 4 bits width
test(s, x1, x2, x3.toUShort(), x4, x5, x6, x7, x8, x9)
}
return "OK"
}
@@ -0,0 +1,155 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: ccallbacksAndVarargs.def
---
#include <stdarg.h>
struct S {
int x;
};
static int getX(struct S (*callback)(void)) {
return callback().x;
}
static void applyCallback(struct S s, void (*callback)(struct S)) {
callback(s);
}
static struct S makeS(int x, ...) {
return (struct S){ x };
}
enum E {
ZERO, ONE, TWO
};
static enum E makeE(int ordinal, ...) {
return ordinal;
}
struct Args {
char a1;
char a2;
short a3;
int a4;
long long a5;
float a6;
double a7;
void* a8;
unsigned char a9;
unsigned short a10;
unsigned int a11;
unsigned long long a12;
enum E a13;
struct S a14;
void* a15;
};
static struct Args getVarargs(int ignore, ...) {
va_list args;
va_start(args, ignore);
struct Args result = {
va_arg(args, char),
va_arg(args, char),
va_arg(args, short),
va_arg(args, int),
va_arg(args, long long),
va_arg(args, double),
va_arg(args, double),
va_arg(args, void*),
va_arg(args, unsigned char),
va_arg(args, unsigned short),
va_arg(args, unsigned int),
va_arg(args, unsigned long long),
va_arg(args, enum E),
va_arg(args, struct S),
va_arg(args, void*)
};
va_end(args);
return result;
}
static int sum(int first, int second) {
return first + second;
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.test.*
import kotlinx.cinterop.*
import ccallbacksAndVarargs.*
fun box(): String {
testStructCallbacks()
testVarargs()
testCallableReferences()
return "OK"
}
fun testStructCallbacks() {
assertEquals(42, getX(staticCFunction { -> cValue<S> { x = 42 } }))
applyCallback(cValue { x = 17 }, staticCFunction { it: CValue<S> ->
assertEquals(17, it.useContents { x })
})
assertEquals(66, makeS(66, 111).useContents { x })
}
fun testVarargs() {
assertEquals(E.ONE, makeE(1))
getVarargs(
0,
true,
2.toByte(),
Short.MIN_VALUE,
42,
Long.MAX_VALUE,
3.14f,
2.71,
0x1234ABCDL.toCPointer<COpaque>(),
UByte.MAX_VALUE,
22.toUShort(),
111u,
ULong.MAX_VALUE,
E.TWO,
cValue<S> { x = 15 },
null
).useContents {
assertEquals(1, a1)
assertEquals(2.toByte(), a2)
assertEquals(Short.MIN_VALUE, a3)
assertEquals(42, a4)
assertEquals(Long.MAX_VALUE, a5)
assertEquals(3.14f, a6)
assertEquals(2.71, a7)
assertEquals(0x1234ABCDL, a8.toLong())
assertEquals(UByte.MAX_VALUE, a9)
assertEquals(22.toUShort(), a10)
assertEquals(111u, a11)
assertEquals(ULong.MAX_VALUE, a12)
assertEquals(E.TWO, a13)
assertEquals(15, a14.x)
assertEquals(null, a15)
}
}
fun testCallableReferences() {
val sumRef = ::sum
assertEquals(3, sumRef(1, 2))
val sumPtr = staticCFunction(::sum)
assertEquals(7, sumPtr(3, 4))
}
+44
View File
@@ -0,0 +1,44 @@
/*
* 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
// MODULE: cinterop
// FILE: cenums.def
---
enum E {
A, B, C
};
// MODULE: main(cinterop)
// FILE: main.kt
// !LANGUAGE: +EnumEntries
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import cenums.*
import kotlinx.cinterop.*
import kotlin.test.*
@OptIn(kotlin.ExperimentalStdlibApi::class)
fun box(): String {
memScoped {
val e = alloc<E.Var>()
e.value = E.C
assertEquals(E.C, e.value)
assertFailsWith<NotImplementedError> {
e.value = TODO()
}
}
val values = E.values()
assertEquals(values[0], E.A)
assertEquals(values[1], E.B)
assertEquals(values[2], E.C)
// TODO: temporariry commented. Task for investigation is KT-56107
// val entries = E.entries
// assertEquals(entries[0], E.A)
// assertEquals(entries[1], E.B)
// assertEquals(entries[2], E.C)
return "OK"
}
@@ -0,0 +1,37 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: cCallback.def
language = C
---
extern char* sb;
void runAndCatch(void(*f)(void));
// FILE: cCallback.cpp
#include <stdio.h>
char* sb = nullptr;
extern "C" void runAndCatch(void(*f)(void)) {
try {
f();
} catch (...) {
sb = "OK";
}
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlinx.cinterop.staticCFunction
import kotlinx.cinterop.toKString
import cCallback.runAndCatch
import cCallback.sb
fun throwingCallback() {
throw IllegalStateException("Kotlin Exception!")
}
fun box(): String {
runAndCatch(staticCFunction(::throwingCallback))
return sb?.toKString() ?: "FAIL"
}
@@ -0,0 +1,56 @@
// This test mostly checks frontend behaviour.
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: cForwardDeclarations.def
---
struct StructDeclared;
struct StructDefined { int x; };
int useStructDeclared(struct StructDeclared* declared) {
return -1;
}
int useStructDefined(struct StructDefined* defined) {
return -2;
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import cForwardDeclarations.*
import cnames.structs.StructDeclared
import kotlin.test.assertEquals
import kotlinx.cinterop.COpaque
import kotlinx.cinterop.CStructVar
import kotlinx.cinterop.ptr
// The test should also check that these references can't be resolved, but the test infra doesn't support this yet:
// import cForwardDeclarations.StructUndeclared
// import cnames.structs.StructUndeclared // Supported in K1 though.
fun <T1 : T2, T2> checkSubtype2() {}
// Here we rely on frontend reporting conflicting overloads if some of these types turn out to be the same.
fun checkDifferentTypes(s: StructDeclared?) = 1
fun checkDifferentTypes(s: StructDefined?) = 2
fun box(): String {
checkSubtype2<StructDeclared, COpaque>()
checkSubtype2<StructDefined, CStructVar>()
val declared: StructDeclared? = null
val defined: StructDefined? = null
assertEquals(1, checkDifferentTypes(declared))
assertEquals(2, checkDifferentTypes(defined))
assertEquals(-1, useStructDeclared(declared?.ptr))
assertEquals(-2, useStructDefined(defined?.ptr))
return "OK"
}
@@ -0,0 +1,130 @@
// This test mostly checks frontend behaviour.
// TARGET_BACKEND: NATIVE
// MODULE: cinterop1
// FILE: cForwardDeclarationsTwoLibs1.def
---
struct StructDeclaredUndeclared;
struct StructDeclaredDeclared;
struct StructDeclaredDefined;
struct StructDefinedUndeclared {};
struct StructDefinedDeclared {};
struct StructDefinedDefined {};
int use1StructDeclaredUndeclared(struct StructDeclaredUndeclared* declaredUndeclared) { return -3; }
int use1StructDeclaredDeclared(struct StructDeclaredDeclared* declaredDeclared) { return -4; }
int use1StructDeclaredDefined(struct StructDeclaredDefined* declaredDefined) { return -5; }
int use1StructDefinedUndeclared(struct StructDefinedUndeclared* definedUndeclared) { return -6; }
int use1StructDefinedDeclared(struct StructDefinedDeclared* definedDeclared) { return -7; }
int use1StructDefinedDefined(struct StructDefinedDefined* definedDefined) { return -8; }
// MODULE: cinterop2
// FILE: cForwardDeclarationsTwoLibs2.def
---
struct StructUndeclaredDeclared;
struct StructUndeclaredDefined {};
struct StructDeclaredDeclared;
struct StructDeclaredDefined {};
struct StructDefinedDeclared;
struct StructDefinedDefined {};
int use2StructUndeclaredDeclared(struct StructUndeclaredDeclared* undeclaredDeclared) { return 1; }
int use2StructUndeclaredDefined(struct StructUndeclaredDefined* undeclaredDefined) { return 2; }
int use2StructDeclaredDeclared(struct StructDeclaredDeclared* declaredDeclared) { return 4; }
int use2StructDeclaredDefined(struct StructDeclaredDefined* declaredDefined) { return 5; }
int use2StructDefinedDeclared(struct StructDefinedDeclared* definedDeclared) { return 7; }
int use2StructDefinedDefined(struct StructDefinedDefined* definedDefined) { return 8; }
// MODULE: main(cinterop1, cinterop2)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import cForwardDeclarationsTwoLibs1.*
import cForwardDeclarationsTwoLibs2.*
import cnames.structs.StructUndeclaredDeclared
import cnames.structs.StructDeclaredUndeclared
import cnames.structs.StructDeclaredDeclared
import kotlin.test.assertEquals
import kotlinx.cinterop.COpaque
import kotlinx.cinterop.CPointed
import kotlinx.cinterop.CStructVar
import kotlinx.cinterop.ptr
// The test should also check that these references can't be resolved, but the test infra doesn't support this yet:
// import cForwardDeclarationsTwoLibs1.StructUndeclaredUndeclared
// import cForwardDeclarationsTwoLibs1.StructUndeclaredDeclared
// import cForwardDeclarationsTwoLibs1.StructUndeclaredDefined
// import cForwardDeclarationsTwoLibs2.StructUndeclaredUndeclared
// import cForwardDeclarationsTwoLibs2.StructDeclaredUndeclared
// import cForwardDeclarationsTwoLibs2.StructDefinedUndeclared
// import cnames.structs.StructUndeclaredUndeclared // Supported in K1 though.
fun <T1 : T2, T2> checkSubtype2() {}
// Here we rely on frontend reporting conflicting overloads if some of these types turn out to be the same.
fun checkDifferentTypes(s: StructUndeclaredDeclared?) = 1
fun checkDifferentTypes(s: StructUndeclaredDefined?) = 2
fun checkDifferentTypes(s: StructDeclaredUndeclared?) = 3
fun checkDifferentTypes(s: StructDeclaredDeclared?) = 4
fun checkDifferentTypes(s: StructDeclaredDefined?) = 5
fun checkDifferentTypes(s: StructDefinedUndeclared?) = 6
fun checkDifferentTypes(s: StructDefinedDeclared?) = 7
fun checkDifferentTypes(s: cForwardDeclarationsTwoLibs1.StructDefinedDefined?) = 8
fun checkDifferentTypes(s: cForwardDeclarationsTwoLibs2.StructDefinedDefined?) = 9
fun box(): String {
checkSubtype2<StructUndeclaredDeclared, COpaque>()
checkSubtype2<StructUndeclaredDefined, CStructVar>()
checkSubtype2<StructDeclaredUndeclared, COpaque>()
checkSubtype2<StructDeclaredDeclared, COpaque>()
checkSubtype2<cnames.structs.StructDeclaredDefined, CPointed>()
checkSubtype2<StructDeclaredDefined, CStructVar>()
checkSubtype2<StructDefinedUndeclared, CStructVar>()
checkSubtype2<cnames.structs.StructDefinedDeclared, CPointed>()
checkSubtype2<StructDefinedDeclared, CStructVar>()
checkSubtype2<cForwardDeclarationsTwoLibs1.StructDefinedDefined, CStructVar>()
checkSubtype2<cForwardDeclarationsTwoLibs2.StructDefinedDefined, CStructVar>()
val undeclaredDeclared: StructUndeclaredDeclared? = null
val undeclaredDefined: StructUndeclaredDefined? = null
val declaredUndeclared: StructDeclaredUndeclared? = null
val declaredDeclared: StructDeclaredDeclared? = null
val cnamesDeclaredDefined: cnames.structs.StructDeclaredDefined? = null
val declaredDefined: StructDeclaredDefined? = null
val definedUndeclared: StructDefinedUndeclared? = null
val cnamesDefinedDeclared: cnames.structs.StructDefinedDeclared? = null
val definedDeclared: StructDefinedDeclared? = null
val definedDefined1: cForwardDeclarationsTwoLibs1.StructDefinedDefined? = null
val definedDefined2: cForwardDeclarationsTwoLibs2.StructDefinedDefined? = null
assertEquals(1, checkDifferentTypes(undeclaredDeclared))
assertEquals(2, checkDifferentTypes(undeclaredDefined))
assertEquals(3, checkDifferentTypes(declaredUndeclared))
assertEquals(4, checkDifferentTypes(declaredDeclared))
assertEquals(5, checkDifferentTypes(declaredDefined))
assertEquals(6, checkDifferentTypes(definedUndeclared))
assertEquals(7, checkDifferentTypes(definedDeclared))
assertEquals(8, checkDifferentTypes(definedDefined1))
assertEquals(9, checkDifferentTypes(definedDefined2))
assertEquals(1, use2StructUndeclaredDeclared(undeclaredDeclared?.ptr))
assertEquals(2, use2StructUndeclaredDefined(undeclaredDefined?.ptr))
assertEquals(-3, use1StructDeclaredUndeclared(declaredUndeclared?.ptr))
assertEquals(-4, use1StructDeclaredDeclared(declaredDeclared?.ptr))
assertEquals(4, use2StructDeclaredDeclared(declaredDeclared?.ptr))
assertEquals(-5, use1StructDeclaredDefined(cnamesDeclaredDefined?.ptr))
assertEquals(5, use2StructDeclaredDefined(declaredDefined?.ptr))
assertEquals(-6, use1StructDefinedUndeclared(definedUndeclared?.ptr))
assertEquals(-7, use1StructDefinedDeclared(definedDeclared?.ptr))
assertEquals(7, use2StructDefinedDeclared(cnamesDefinedDeclared?.ptr))
assertEquals(-8, use1StructDefinedDefined(definedDefined1?.ptr))
assertEquals(8, use2StructDefinedDefined(definedDefined2?.ptr))
return "OK"
}
@@ -0,0 +1,77 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: cglobals.def
---
const int g1 = 42;
int g2 = 17;
struct S {
int x;
} g3 = { 128 };
int g4[2] = { 13, 14 };
int g5[2][2] = { 15, 16, 17, 18 };
struct S* const g6 = &g3;
void globals_foo() {
// Test that local vars are not treated as global ones.
float g1;
}
// Test non-compilable variable:
typedef int MyInt;
MyInt g7;
#define g7 bad macro
// Test property name mangling:
struct g1 {};
struct g1_ {};
typedef void* voidptr;
_Pragma("clang assume_nonnull begin")
const voidptr g8 = 0x1, g9 = 0x2;
_Pragma("clang assume_nonnull end")
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class, kotlin.experimental.ExperimentalNativeApi::class)
import kotlinx.cinterop.*
import cglobals.*
fun box(): String {
assert(g1__ == 42)
assert(g2 == 17)
g2 = 42
assert(g2 == 42)
assert(g3.x == 128)
g3.x = 7
assert(g3.x == 7)
assert(g4[1] == 14)
g4[1] = 15
assert(g4[1] == 15)
assert(g5[0] == 15)
assert(g5[3] == 18)
g5[0] = 16
assert(g5[0] == 16)
assert(g6 == g3.ptr)
assert(g8.toLong() == 0x1L)
assert(g9.toLong() == 0x2L)
return "OK"
}
@@ -0,0 +1,124 @@
// FREE_CINTEROP_ARGS: -header incompleteTypes.h
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: incompleteTypes.def
# The def file is intentionally empty
# `incompleteTypes.h` is meant to be included via `-header` option of cinterop tool
// FILE: incompleteTypes.h
#ifdef __cplusplus
extern "C" {
#endif
// Forward declaration.
struct S;
extern struct S s;
const char* getContent(struct S* s);
void setContent(struct S* s, const char* name);
union U;
extern union U u;
double getDouble(union U* u);
void setDouble(union U* u, double value);
// Global array of unknown size.
extern char array[];
int arrayLength();
void setArrayValue(char* array, char value);
#ifdef __cplusplus
}
#endif
// FILE: incompleteTypes.cpp
#include <string>
#include "incompleteTypes.h"
extern "C" {
struct S {
std::string name;
};
S s = {
.name = "initial"
};
void setContent(struct S* s, const char* name) {
// Note that copy here is intentional: we use it as a workaround
// for short lifetime of copy of the passed Kotlin string.
s->name = name;
}
const char* getContent(struct S* s) {
return s->name.c_str();
}
union U {
float f;
double d;
};
void setDouble(union U* u, double value) {
u->d = value;
}
double getDouble(union U* u) {
return u->d;
}
union U u = {
.d = 0.0
};
char array[5] = { 0, 0, 0, 0, 0 };
void setArrayValue(char* array, char value) {
for (int i = 0; i < 5; ++i) {
array[i] = value;
}
}
int arrayLength() {
return sizeof(array) / sizeof(char);
}
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import incompleteTypes.*
import kotlinx.cinterop.*
import kotlin.test.*
fun box(): String {
assertNotNull(s.ptr)
assertNotNull(u.ptr)
assertNotNull(array)
assertEquals("initial", getContent(s.ptr)?.toKString())
setContent(s.ptr, "yo")
val ptr = getContent(s.ptr)
assertEquals("yo", ptr?.toKString())
assertEquals(0.0, getDouble(u.ptr))
setDouble(u.ptr, Double.MIN_VALUE)
assertEquals(Double.MIN_VALUE, getDouble(u.ptr))
for (i in 0 until arrayLength()) {
assertEquals(0x0, array[i])
}
setArrayValue(array, 0x1)
for (i in 0 until arrayLength()) {
assertEquals(0x1, array[i])
}
return "OK"
}
@@ -0,0 +1,23 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: kt43265.def
strictEnums = bcm2835FunctionSelect
---
enum bcm2835FunctionSelect {
BCM2835_GPIO_FSEL_INPT = 0x00, BCM2835_GPIO_FSEL_OUTP = 0x01, BCM2835_GPIO_FSEL_ALT0 = 0x04, BCM2835_GPIO_FSEL_ALT1 = 0x05,
BCM2835_GPIO_FSEL_ALT2 = 0x06, BCM2835_GPIO_FSEL_ALT3 = 0x07, BCM2835_GPIO_FSEL_ALT4 = 0x03, BCM2835_GPIO_FSEL_ALT5 = 0x02,
BCM2835_GPIO_FSEL_MASK = 0x07
};
// MODULE: main(cinterop)
// FILE: main.kt
import kt43265.*
import kotlin.test.*
@kotlinx.cinterop.ExperimentalForeignApi
fun box(): String {
assertEquals(bcm2835FunctionSelect.BCM2835_GPIO_FSEL_ALT3, bcm2835FunctionSelect.BCM2835_GPIO_FSEL_MASK)
return "OK"
}
@@ -0,0 +1,58 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: kt44283.def
---
#include <stdlib.h>
#include <pthread.h>
typedef struct {
int d;
} TestStruct;
typedef struct {
void (*f)(TestStruct data);
} ThreadData;
void *dispatch(void *rawArg) {
ThreadData *arg = rawArg;
arg->f((TestStruct) {.d = 1});
return NULL;
}
void invokeFromThread(void (*f)(TestStruct data)) {
pthread_t thread_id;
ThreadData *threadData = malloc(sizeof(ThreadData));
threadData->f = f;
pthread_create(&thread_id, NULL, dispatch, (void *) threadData);
pthread_join(thread_id, NULL);
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
import kotlinx.cinterop.*
import kt44283.*
import kotlin.concurrent.AtomicInt
import kotlin.test.*
val callbackCounter = AtomicInt(0)
@ExperimentalForeignApi
fun box(): String {
val func = staticCFunction<CValue<TestStruct>, Unit> {
kotlin.native.runtime.GC.collect() // Helps to ensure that "runtime" is already initialized.
memScoped {
println("Hello, Kotlin/Native! ${it.ptr.pointed.d}")
}
callbackCounter.incrementAndGet()
}
assertEquals(0, callbackCounter.value)
invokeFromThread(func.reinterpret())
assertEquals(1, callbackCounter.value)
return "OK"
}
@@ -0,0 +1,49 @@
/*
* Copyright 2010-2022 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
// MODULE: cinterop
// FILE: kt51925.def
strictEnums = E
---
enum E {
X = 1, Y = 2, Z = 42
};
typedef struct {
int d;
} Struct;
// MODULE: lib(cinterop)
// FILE: lib.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kt51925.*
import kotlinx.cinterop.*
fun bar1(e: E) = e.value
inline fun foo1() = bar1(E.Z)
fun bar2(s: Struct): Int {
return s.d
}
inline fun foo2(): Int {
memScoped {
val s = alloc<Struct>()
s.d = 42
return bar2(s)
}
}
// MODULE: main(lib)
// FILE: main.kt
import kotlin.test.*
fun box(): String {
assertEquals(42u, foo1())
assertEquals(42, foo2())
return "OK"
}
@@ -0,0 +1,30 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: kt54284.def
---
#define KFILE "FILE:" __FILE__
#define KLINE "LINE:" __LINE__
#define KTIME "TIME:" __TIME__
#define KDATE "DATE:" __DATE__
#define KFILENAME "NAME:" __FILE_NAME__
#define KBASEFILE "BASE:" __BASE_FILE__
// MODULE: main(cinterop)
// FILE: main.kt
import kotlinx.cinterop.*
import kt54284.*
import kotlin.test.*
@ExperimentalForeignApi
fun box(): String {
assertEquals("FILE:__FILE__", KFILE)
assertEquals("LINE:__LINE__", KLINE)
assertEquals("TIME:__TIME__", KTIME)
assertEquals("DATE:__DATE__", KDATE)
assertEquals("NAME:__FILE_NAME__", KFILENAME)
assertEquals("BASE:__BASE_FILE__", KBASEFILE)
return "OK"
}
@@ -0,0 +1,30 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: kt54284_fmodules.def
compilerOpts = -fmodules
---
#define KFILE "FILE:" __FILE__
#define KLINE "LINE:" __LINE__
#define KTIME "TIME:" __TIME__
#define KDATE "DATE:" __DATE__
#define KFILENAME "NAME:" __FILE_NAME__
#define KBASEFILE "BASE:" __BASE_FILE__
// MODULE: main(cinterop)
// FILE: main.kt
import kotlinx.cinterop.*
import kt54284_fmodules.*
import kotlin.test.*
@ExperimentalForeignApi
fun box(): String {
assertEquals("FILE:__FILE__", KFILE)
assertEquals("LINE:__LINE__", KLINE)
assertEquals("TIME:__TIME__", KTIME)
assertEquals("DATE:__DATE__", KDATE)
assertEquals("NAME:__FILE_NAME__", KFILENAME)
assertEquals("BASE:__BASE_FILE__", KBASEFILE)
return "OK"
}
+680
View File
@@ -0,0 +1,680 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: kt57640.def
language = Objective-C
headers = kt57640.h
// FILE: kt57640.h
#import <Foundation/NSObject.h>
@interface Base : NSObject
@property (readwrite) Base* delegate;
@end
@protocol Foo
@property (readwrite) id<Foo> delegate;
@end
@protocol Bar
@property (readwrite) id<Bar> delegate;
@end
@interface Derived : Base<Bar, Foo>
// This interface does not have re-declaration of property `delegate`.
// Return type of getter `delegate()` and param type of setter `setDelegate()` are:
// the type of property defined in the first mentioned protocol (id<Bar>), which is incompatible with property type.
@end
@interface DerivedWithPropertyOverride : Base<Bar, Foo>
// This interface does not have re-declaration of property `delegate`.
// Return type of getter `delegate()` and param type of setter `setDelegate()` are `DerivedWithPropertyOverride*`
@property (readwrite) DerivedWithPropertyOverride* delegate;
@end
// FILE: kt57640.m
#import "kt57640.h"
@implementation Base
@end
@implementation Derived
@end
@implementation DerivedWithPropertyOverride
@end
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kt57640.*
import kotlin.test.*
class GrandDerived: Derived() {}
class GrandDerivedWithPropertyOverride: DerivedWithPropertyOverride() {}
/**
* class KotlinInterfaceDerived would cause errors, this deserves a diagnostic test
* error: class 'KotlinInterfaceDerived' must override 'delegate' because it inherits multiple implementations for it.
* error: 'delegate' clashes with 'delegate': return types are incompatible.
* error: 'delegate' clashes with 'delegate': property types do not match.
*/
//class KotlinInterfaceDerived: Base(), FooProtocol, BarProtocol
fun box(): String {
testBase()
testAssignmentDerivedToDerived()
testAssignmentDerivedToBase()
testAssignmentBaseToDerived()
testAssignmentDerivedWithPropertyOverrideToDerivedWithPropertyOverride()
testAssignmentDerivedWithPropertyOverrideToBase()
testAssignmentBaseToDerivedWithPropertyOverride()
testGrandDerived()
testGrandDerivedWithPropertyOverride()
testAssigmmentDerivedWithPropertyOverrideToGrandDerivedWithPropertyOverride()
return "OK"
}
private fun testBase() {
val base = Base()
val delegate00_Base: Base? = base.delegate
assertEquals(null, delegate00_Base)
val delegate01_Base: Base? = base.delegate()
assertEquals(null, delegate01_Base)
base.delegate = base
val delegate02_Base: Base? = base.delegate
assertEquals(base, delegate02_Base)
val delegate03_Base: Base? = base.delegate()
assertEquals(base, delegate03_Base)
}
private fun testAssignmentDerivedToDerived() {
val derived = Derived()
val delegate10_Base: Base? = derived.delegate
assertEquals(null, delegate10_Base)
val delegate11_Bar: BarProtocol? = derived.delegate()
assertEquals(null, delegate11_Bar)
derived.delegate = derived
derived.setDelegate(derived)
val delegate12_Base: Base? = derived.delegate
assertTrue(delegate12_Base is Base)
assertTrue(delegate12_Base is FooProtocol)
assertTrue(delegate12_Base is BarProtocol)
assertTrue(delegate12_Base is Derived)
assertEquals(derived, delegate12_Base)
val delegate16_Bar: BarProtocol? = derived.delegate()
assertTrue(delegate16_Bar is Base)
assertTrue(delegate16_Bar is FooProtocol)
assertTrue(delegate16_Bar is BarProtocol)
assertTrue(delegate16_Bar is Derived)
assertEquals(derived, delegate16_Bar)
val delegate13_Base: Base? = (derived as Base).delegate
assertTrue(delegate13_Base is Base)
assertTrue(delegate13_Base is FooProtocol)
assertTrue(delegate13_Base is BarProtocol)
assertTrue(delegate13_Base is Derived)
assertEquals(derived, delegate13_Base)
val delegate17_Base: Base? = (derived as Base).delegate()
assertTrue(delegate17_Base is Base)
assertTrue(delegate17_Base is FooProtocol)
assertTrue(delegate17_Base is BarProtocol)
assertTrue(delegate17_Base is Derived)
assertEquals(derived, delegate17_Base)
val delegate14_Foo: FooProtocol? = (derived as FooProtocol).delegate
assertTrue(delegate14_Foo is Base)
assertTrue(delegate14_Foo is FooProtocol)
assertTrue(delegate14_Foo is BarProtocol)
assertTrue(delegate14_Foo is Derived)
assertEquals(derived, delegate14_Foo)
val delegate18_Foo: FooProtocol? = (derived as FooProtocol).delegate()
assertTrue(delegate18_Foo is Base)
assertTrue(delegate18_Foo is FooProtocol)
assertTrue(delegate18_Foo is BarProtocol)
assertTrue(delegate18_Foo is Derived)
assertEquals(derived, delegate18_Foo)
val delegate15_Bar: BarProtocol? = (derived as BarProtocol).delegate
assertTrue(delegate15_Bar is Base)
assertTrue(delegate15_Bar is FooProtocol)
assertTrue(delegate15_Bar is BarProtocol)
assertTrue(delegate15_Bar is Derived)
assertEquals(derived, delegate15_Bar)
val delegate19_Bar: BarProtocol? = (derived as BarProtocol).delegate()
assertTrue(delegate19_Bar is Base)
assertTrue(delegate19_Bar is FooProtocol)
assertTrue(delegate19_Bar is BarProtocol)
assertTrue(delegate19_Bar is Derived)
assertEquals(derived, delegate19_Bar)
}
private fun testAssignmentDerivedToBase() {
val base = Base()
val delegate10_Base: Base? = base.delegate
assertEquals(null, delegate10_Base)
val delegate11_Base: Base? = base.delegate()
assertEquals(null, delegate11_Base)
base.delegate = base
base.setDelegate(base)
val derived = Derived()
base.delegate = derived
val delegate12_Base: Base? = base.delegate
assertTrue(delegate12_Base is Base)
assertTrue(delegate12_Base is FooProtocol)
assertTrue(delegate12_Base is BarProtocol)
assertTrue(delegate12_Base is Derived)
assertEquals(derived, delegate12_Base)
val delegate16_Base: Base? = base.delegate()
assertTrue(delegate16_Base is Base)
assertTrue(delegate16_Base is FooProtocol)
assertTrue(delegate16_Base is BarProtocol)
assertTrue(delegate16_Base is Derived)
assertEquals(derived, delegate16_Base)
}
private fun testAssignmentBaseToDerived() {
val derived = Derived()
val delegate10_Base: Base? = derived.delegate
assertEquals(null, delegate10_Base)
val delegate11_Bar: BarProtocol? = derived.delegate()
assertEquals(null, delegate11_Bar)
val base = Base()
derived.delegate = base
// derived.setDelegate(base) // argument type mismatch, this deserves a diagnostic test
val delegate12_Base: Base? = derived.delegate
assertTrue(delegate12_Base is Base)
assertFalse(delegate12_Base is FooProtocol)
assertFalse(delegate12_Base is BarProtocol)
assertFalse(delegate12_Base is Derived)
assertEquals(base, delegate12_Base)
val delegate16_Bar: BarProtocol? = derived.delegate()
val delegate16_Any: Any? = delegate16_Bar
assertTrue(delegate16_Bar is Base)
assertTrue(delegate16_Any is Base)
assertFalse(delegate16_Bar is FooProtocol)
assertFalse(delegate16_Any is FooProtocol)
// Behavior of next "is" check depends on existence of static type analysis: static analysis calculates "is" result as "true",
// while at run-time, the type is Base, which isn't BarProtocol, and the "is" result is "false"
// assertFalse(delegate16_Bar is BarProtocol)
assertFalse(delegate16_Any is BarProtocol) // actual type is Base, which isn't BarProtocol
assertFalse(delegate16_Bar is Derived)
assertFalse(delegate16_Any is Derived)
assertEquals(base, delegate16_Bar)
assertEquals(base, delegate16_Any)
val delegate13_Base: Base? = (derived as Base).delegate
assertTrue(delegate13_Base is Base)
assertFalse(delegate13_Base is FooProtocol)
assertFalse(delegate13_Base is BarProtocol)
assertFalse(delegate13_Base is Derived)
assertEquals(base, delegate13_Base)
val delegate17_Base: Base? = (derived as Base).delegate()
assertTrue(delegate17_Base is Base)
assertFalse(delegate17_Base is FooProtocol)
assertFalse(delegate17_Base is BarProtocol)
assertFalse(delegate17_Base is Derived)
assertEquals(base, delegate17_Base)
val delegate14_Foo: FooProtocol? = (derived as FooProtocol).delegate
val delegate14_Any: Any? = delegate14_Foo
assertTrue(delegate14_Foo is Base)
assertTrue(delegate14_Any is Base)
// Behavior of next "is" check depends on existence of static type analysis: static analysis calculates "is" result as "true",
// while at run-time, the type is Base, which isn't FooProtocol, and the "is" result is "false"
// assertFalse(delegate14_Foo is FooProtocol)
assertFalse(delegate14_Any is FooProtocol) // actual type is Base, which isn't FooProtocol
assertFalse(delegate14_Foo is BarProtocol)
assertFalse(delegate14_Any is BarProtocol)
assertFalse(delegate14_Foo is Derived)
assertEquals(base, delegate14_Foo as Base)
assertEquals(base, delegate14_Any as Base)
val delegate18_Foo: FooProtocol? = (derived as FooProtocol).delegate()
val delegate18_Any: Any? = delegate18_Foo
assertTrue(delegate18_Foo is Base)
assertTrue(delegate18_Any is Base)
// Behavior of next "is" check depends on existence of static type analysis: static analysis calculates "is" result as "true",
// while at run-time, the type is Base, which isn't FooProtocol, and the "is" result is "false"
// assertFalse(delegate18_Foo is FooProtocol)
assertFalse(delegate18_Any is FooProtocol) // actual type is Base, which isn't FooProtocol
assertFalse(delegate18_Foo is BarProtocol)
assertFalse(delegate18_Any is BarProtocol)
assertFalse(delegate18_Foo is Derived)
assertFalse(delegate18_Any is Derived)
assertEquals(base, delegate18_Foo)
assertEquals(base, delegate18_Any)
val delegate15_Bar: BarProtocol? = (derived as BarProtocol).delegate
val delegate15_Any: Any? = delegate15_Bar
assertTrue(delegate15_Bar is Base)
assertTrue(delegate15_Any is Base)
assertFalse(delegate15_Bar is FooProtocol)
assertFalse(delegate15_Any is FooProtocol)
// Behavior of next "is" check depends on existence of static type analysis: static analysis calculates "is" result as "true",
// while at run-time, the type is Base, which isn't BarProtocol, and the "is" result is "false"
// assertFalse(delegate15_Bar is BarProtocol)
assertFalse(delegate15_Any is BarProtocol) // actual type is Base, which isn't BarProtocol
assertFalse(delegate15_Bar is Derived)
assertFalse(delegate15_Any is Derived)
assertEquals(base, delegate15_Bar as Base)
assertEquals(base, delegate15_Any as Base)
val delegate19_Bar: BarProtocol? = (derived as BarProtocol).delegate()
val delegate19_Any: Any? = delegate19_Bar
assertTrue(delegate19_Bar is Base)
assertTrue(delegate19_Any is Base)
assertFalse(delegate19_Bar is FooProtocol)
assertFalse(delegate19_Any is FooProtocol)
// Behavior of next "is" check depends on existence of static type analysis: static analysis calculates "is" result as "true",
// while at run-time, the type is Base, which isn't BarProtocol, and the "is" result is "false"
// assertFalse(delegate19_Bar is BarProtocol)
assertFalse(delegate19_Any is BarProtocol) // actual type is Base, which isn't BarProtocol
assertFalse(delegate19_Bar is Derived)
assertFalse(delegate19_Any is Derived)
assertEquals(base, delegate19_Bar)
assertEquals(base, delegate19_Any)
}
private fun testAssignmentDerivedWithPropertyOverrideToDerivedWithPropertyOverride() {
val derived = DerivedWithPropertyOverride()
// WARNING: static type of backing field in CInterop KLib is `Base?`, but not expected `DerivedWithPropertyOverride?`. Comments below are related
val delegate10_Base: Base? = derived.delegate
assertEquals(null, delegate10_Base)
val delegate11_Bar: BarProtocol? = derived.delegate()
assertEquals(null, delegate11_Bar)
derived.delegate = derived
derived.setDelegate(derived)
val delegate12_Base: Base? = derived.delegate // static type is Base?, not DerivedWithPropertyOverride?, this deserves a diagnostic test
assertTrue(delegate12_Base is Base)
assertTrue(delegate12_Base is FooProtocol)
assertTrue(delegate12_Base is BarProtocol)
assertTrue(delegate12_Base is DerivedWithPropertyOverride)
assertEquals(derived, delegate12_Base)
val delegate19_DerivedWithPropertyOverride: DerivedWithPropertyOverride? = derived.delegate()
assertTrue(delegate19_DerivedWithPropertyOverride is Base)
assertTrue(delegate19_DerivedWithPropertyOverride is FooProtocol)
assertTrue(delegate19_DerivedWithPropertyOverride is BarProtocol)
assertTrue(delegate19_DerivedWithPropertyOverride is DerivedWithPropertyOverride)
assertEquals(derived, delegate19_DerivedWithPropertyOverride)
val delegate13_Base: Base? = (derived as Base).delegate
assertTrue(delegate13_Base is Base)
assertTrue(delegate13_Base is FooProtocol)
assertTrue(delegate13_Base is BarProtocol)
assertTrue(delegate13_Base is DerivedWithPropertyOverride)
assertEquals(derived, delegate13_Base)
val delegate17_Base: Base? = (derived as Base).delegate() // static type is Base?, not DerivedWithPropertyOverride?, this deserves a diagnostic test
assertTrue(delegate17_Base is Base)
assertTrue(delegate17_Base is FooProtocol)
assertTrue(delegate17_Base is BarProtocol)
assertTrue(delegate17_Base is DerivedWithPropertyOverride)
assertEquals(derived, delegate17_Base)
val delegate14_Foo: FooProtocol? = (derived as FooProtocol).delegate
assertTrue(delegate14_Foo is Base)
assertTrue(delegate14_Foo is FooProtocol)
assertTrue(delegate14_Foo is BarProtocol)
assertTrue(delegate14_Foo is DerivedWithPropertyOverride)
assertEquals(derived, delegate14_Foo)
val delegate18_Foo: FooProtocol? = (derived as FooProtocol).delegate() // static type is FooProtocol?, not DerivedWithPropertyOverride?, this deserves a diagnostic test
assertTrue(delegate18_Foo is Base)
assertTrue(delegate18_Foo is FooProtocol)
assertTrue(delegate18_Foo is BarProtocol)
assertTrue(delegate18_Foo is DerivedWithPropertyOverride)
assertEquals(derived, delegate18_Foo)
val delegate15_Bar: BarProtocol? = (derived as BarProtocol).delegate
assertTrue(delegate15_Bar is Base)
assertTrue(delegate15_Bar is FooProtocol)
assertTrue(delegate15_Bar is BarProtocol)
assertTrue(delegate15_Bar is DerivedWithPropertyOverride)
assertEquals(derived, delegate15_Bar)
val delegate19_Bar: BarProtocol? = (derived as BarProtocol).delegate() // static type is BarProtocol?, not DerivedWithPropertyOverride?, this deserves a diagnostic test
assertTrue(delegate19_Bar is Base)
assertTrue(delegate19_Bar is FooProtocol)
assertTrue(delegate19_Bar is BarProtocol)
assertTrue(delegate19_Bar is DerivedWithPropertyOverride)
assertEquals(derived, delegate19_Bar)
}
private fun testAssignmentDerivedWithPropertyOverrideToBase() {
val base = Base()
val delegate10_Base: Base? = base.delegate
assertEquals(null, delegate10_Base)
val delegate11_Base: Base? = base.delegate()
assertEquals(null, delegate11_Base)
val derived = DerivedWithPropertyOverride()
base.delegate = derived
base.setDelegate(derived)
val delegate12_Base: Base? = base.delegate
assertTrue(delegate12_Base is Base)
assertTrue(delegate12_Base is FooProtocol)
assertTrue(delegate12_Base is BarProtocol)
assertTrue(delegate12_Base is DerivedWithPropertyOverride)
assertEquals(derived, delegate12_Base)
val delegate19_Base: Base? = base.delegate()
assertTrue(delegate19_Base is Base)
assertTrue(delegate19_Base is FooProtocol)
assertTrue(delegate19_Base is BarProtocol)
assertTrue(delegate19_Base is DerivedWithPropertyOverride)
assertEquals(derived, delegate19_Base)
}
private fun testAssignmentBaseToDerivedWithPropertyOverride() {
val derived = DerivedWithPropertyOverride()
// WARNING: static type of backing field in CInterop KLib is `Base?`, but not expected `DerivedWithPropertyOverride?`. Comments below are related
val delegate10_Base: Base? = derived.delegate
assertEquals(null, delegate10_Base)
val delegate11_Bar: BarProtocol? = derived.delegate()
assertEquals(null, delegate11_Bar)
val base = Base()
derived.delegate = base
// derived.setDelegate(base) // argument type mismatch: actual type is 'library.Base', but 'library.DerivedWithPropertyOverride?' was expected, this deserves a diagnostic test
val delegate12_Base: Base? = derived.delegate // static type is Base?, not DerivedWithPropertyOverride?, this deserves a diagnostic test
assertTrue(delegate12_Base is Base)
assertFalse(delegate12_Base is FooProtocol)
assertFalse(delegate12_Base is BarProtocol)
assertFalse(delegate12_Base is DerivedWithPropertyOverride)
assertEquals(base, delegate12_Base)
val delegate19_DerivedWithPropertyOverride: DerivedWithPropertyOverride? = derived.delegate()
assertTrue(delegate19_DerivedWithPropertyOverride is Base)
assertTrue(delegate19_DerivedWithPropertyOverride is FooProtocol)
assertTrue(delegate19_DerivedWithPropertyOverride is BarProtocol)
assertTrue(delegate19_DerivedWithPropertyOverride is DerivedWithPropertyOverride)
assertEquals(base, delegate19_DerivedWithPropertyOverride)
val delegate13_Base: Base? = (derived as Base).delegate
assertTrue(delegate13_Base is Base)
assertFalse(delegate13_Base is FooProtocol)
assertFalse(delegate13_Base is BarProtocol)
assertFalse(delegate13_Base is DerivedWithPropertyOverride)
assertEquals(base, delegate13_Base)
val delegate17_Base: Base? = (derived as Base).delegate() // static type is Base?, not DerivedWithPropertyOverride?, this deserves a diagnostic test
assertTrue(delegate17_Base is Base)
assertFalse(delegate17_Base is FooProtocol)
assertFalse(delegate17_Base is BarProtocol)
assertFalse(delegate17_Base is DerivedWithPropertyOverride)
assertEquals(base, delegate17_Base)
val delegate14_Foo: FooProtocol? = (derived as FooProtocol).delegate
assertTrue(delegate14_Foo is Base)
// Behavior of next "is" check depends on existence of static type analysis: static analysis calculates "is" result as "true",
// while at run-time, the type is Base, which isn't FooProtocol, and the "is" result is "false"
// assertFalse(delegate14_Foo is FooProtocol)
assertFalse(delegate14_Foo is BarProtocol)
assertFalse(delegate14_Foo is DerivedWithPropertyOverride)
assertEquals(base, delegate14_Foo)
val delegate18_Foo: FooProtocol? = (derived as FooProtocol).delegate() // static type is FooProtocol?, not DerivedWithPropertyOverride?, this deserves a diagnostic test
assertTrue(delegate18_Foo is Base)
// Behavior of next "is" check depends on existence of static type analysis: static analysis calculates "is" result as "true",
// while at run-time, the type is Base, which isn't FooProtocol, and the "is" result is "false"
// assertFalse(delegate18_Foo is FooProtocol)
assertFalse(delegate18_Foo is BarProtocol)
assertFalse(delegate18_Foo is DerivedWithPropertyOverride)
assertEquals(base, delegate18_Foo)
val delegate15_Bar: BarProtocol? = (derived as BarProtocol).delegate
assertTrue(delegate15_Bar is Base)
assertFalse(delegate15_Bar is FooProtocol)
// Behavior of next "is" check depends on existence of static type analysis: static analysis calculates "is" result as "true",
// while at run-time, the type is Base, which isn't BarProtocol, and the "is" result is "false"
// assertFalse(delegate15_Bar is BarProtocol)
assertFalse(delegate15_Bar is DerivedWithPropertyOverride)
assertEquals(base, delegate15_Bar)
val delegate19_Bar: BarProtocol? = (derived as BarProtocol).delegate() // static type is BarProtocol?, not DerivedWithPropertyOverride?, this deserves a diagnostic test
assertTrue(delegate19_Bar is Base)
assertFalse(delegate19_Bar is FooProtocol)
// Behavior of next "is" check depends on existence of static type analysis: static analysis calculates "is" result as "true",
// while at run-time, the type is Base, which isn't BarProtocol, and the "is" result is "false"
// assertFalse(delegate19_Bar is BarProtocol)
assertFalse(delegate19_Bar is DerivedWithPropertyOverride)
assertEquals(base, delegate19_Bar)
}
private fun testGrandDerived() {
val grandDerived = GrandDerived()
val delegate10_Base: Base? = grandDerived.delegate
assertEquals(null, delegate10_Base)
val delegate11_Bar: BarProtocol? = grandDerived.delegate()
assertEquals(null, delegate11_Bar)
grandDerived.delegate = Base()
// grandDerived.setDelegate(Base()) // argument type mismatch: actual type is 'library.Base', but 'library.BarProtocol?' was expected, this deserves a diagnostic test
grandDerived.delegate = Derived()
grandDerived.setDelegate(Derived())
grandDerived.delegate = grandDerived
grandDerived.setDelegate(grandDerived)
val delegate12_Base: Base? = grandDerived.delegate
assertTrue(delegate12_Base is Base)
assertTrue(delegate12_Base is FooProtocol)
assertTrue(delegate12_Base is BarProtocol)
assertTrue(delegate12_Base is Derived)
assertTrue(delegate12_Base is GrandDerived)
assertEquals(grandDerived, delegate12_Base)
val delegate21_Bar: BarProtocol? = grandDerived.delegate()
assertTrue(delegate21_Bar is Base)
assertTrue(delegate21_Bar is FooProtocol)
assertTrue(delegate21_Bar is BarProtocol)
assertTrue(delegate21_Bar is Derived)
assertTrue(delegate21_Bar is GrandDerived)
assertEquals(grandDerived, delegate21_Bar)
val delegate13_Base: Base? = (grandDerived as Base).delegate
assertTrue(delegate13_Base is Base)
assertTrue(delegate13_Base is FooProtocol)
assertTrue(delegate13_Base is BarProtocol)
assertTrue(delegate13_Base is Derived)
assertTrue(delegate13_Base is GrandDerived)
assertEquals(grandDerived, delegate13_Base)
val delegate17_Base: Base? = (grandDerived as Base).delegate()
assertTrue(delegate17_Base is Base)
assertTrue(delegate17_Base is FooProtocol)
assertTrue(delegate17_Base is BarProtocol)
assertTrue(delegate17_Base is Derived)
assertTrue(delegate17_Base is GrandDerived)
assertEquals(grandDerived, delegate17_Base)
val delegate14_Foo: FooProtocol? = (grandDerived as FooProtocol).delegate
assertTrue(delegate14_Foo is Base)
assertTrue(delegate14_Foo is FooProtocol)
assertTrue(delegate14_Foo is BarProtocol)
assertTrue(delegate14_Foo is Derived)
assertTrue(delegate14_Foo is GrandDerived)
assertEquals(grandDerived, delegate14_Foo)
val delegate18_Foo: FooProtocol? = (grandDerived as FooProtocol).delegate()
assertTrue(delegate18_Foo is Base)
assertTrue(delegate18_Foo is FooProtocol)
assertTrue(delegate18_Foo is BarProtocol)
assertTrue(delegate18_Foo is Derived)
assertTrue(delegate18_Foo is GrandDerived)
assertEquals(grandDerived, delegate18_Foo)
val delegate15_Bar: BarProtocol? = (grandDerived as BarProtocol).delegate
assertTrue(delegate15_Bar is Base)
assertTrue(delegate15_Bar is FooProtocol)
assertTrue(delegate15_Bar is BarProtocol)
assertTrue(delegate15_Bar is Derived)
assertTrue(delegate15_Bar is GrandDerived)
assertEquals(grandDerived, delegate15_Bar)
val delegate19_Bar: BarProtocol? = (grandDerived as BarProtocol).delegate()
assertTrue(delegate19_Bar is Base)
assertTrue(delegate19_Bar is FooProtocol)
assertTrue(delegate19_Bar is BarProtocol)
assertTrue(delegate19_Bar is Derived)
assertTrue(delegate19_Bar is GrandDerived)
assertEquals(grandDerived, delegate19_Bar)
val delegate16_Base: Base? = (grandDerived as Derived).delegate
assertTrue(delegate16_Base is Base)
assertTrue(delegate16_Base is FooProtocol)
assertTrue(delegate16_Base is BarProtocol)
assertTrue(delegate16_Base is Derived)
assertTrue(delegate16_Base is GrandDerived)
assertEquals(grandDerived, delegate16_Base)
val delegate20_Bar: BarProtocol? = (grandDerived as Derived).delegate()
assertTrue(delegate20_Bar is Base)
assertTrue(delegate20_Bar is FooProtocol)
assertTrue(delegate20_Bar is BarProtocol)
assertTrue(delegate20_Bar is Derived)
assertTrue(delegate20_Bar is GrandDerived)
assertEquals(grandDerived, delegate20_Bar)
}
private fun testGrandDerivedWithPropertyOverride() {
val grandDerived = GrandDerivedWithPropertyOverride()
val delegate10_Base: Base? = grandDerived.delegate
assertEquals(null, delegate10_Base)
val delegate11_Bar: BarProtocol? = grandDerived.delegate()
assertEquals(null, delegate11_Bar)
grandDerived.delegate = Base()
// grandDerived.setDelegate(Base()) // argument type mismatch: actual type is 'library.Base', but 'library.DerivedWithPropertyOverride?' was expected, this deserves a diagnostic test
grandDerived.delegate = Derived()
// grandDerived.setDelegate(Derived()) // argument type mismatch: actual type is 'library.Derived', but 'library.DerivedWithPropertyOverride?' was expected, this deserves a diagnostic test
grandDerived.delegate = DerivedWithPropertyOverride()
grandDerived.setDelegate(DerivedWithPropertyOverride())
grandDerived.delegate = grandDerived
grandDerived.setDelegate(grandDerived)
val delegate12_Base: Base? = grandDerived.delegate
assertTrue(delegate12_Base is Base)
assertTrue(delegate12_Base is FooProtocol)
assertTrue(delegate12_Base is BarProtocol)
assertTrue(delegate12_Base is DerivedWithPropertyOverride)
assertTrue(delegate12_Base is GrandDerivedWithPropertyOverride)
assertEquals(grandDerived, delegate12_Base)
val delegate13_Base: Base? = (grandDerived as Base).delegate
assertTrue(delegate13_Base is Base)
assertTrue(delegate13_Base is FooProtocol)
assertTrue(delegate13_Base is BarProtocol)
assertTrue(delegate13_Base is DerivedWithPropertyOverride)
assertTrue(delegate13_Base is GrandDerivedWithPropertyOverride)
assertEquals(grandDerived, delegate13_Base)
val delegate14_Foo: FooProtocol? = (grandDerived as FooProtocol).delegate
assertTrue(delegate14_Foo is Base)
assertTrue(delegate14_Foo is FooProtocol)
assertTrue(delegate14_Foo is BarProtocol)
assertTrue(delegate14_Foo is DerivedWithPropertyOverride)
assertTrue(delegate14_Foo is GrandDerivedWithPropertyOverride)
assertEquals(grandDerived, delegate14_Foo)
val delegate15_Bar: BarProtocol? = (grandDerived as BarProtocol).delegate
assertTrue(delegate15_Bar is Base)
assertTrue(delegate15_Bar is FooProtocol)
assertTrue(delegate15_Bar is BarProtocol)
assertTrue(delegate15_Bar is DerivedWithPropertyOverride)
assertTrue(delegate15_Bar is GrandDerivedWithPropertyOverride)
assertEquals(grandDerived, delegate15_Bar)
val delegate16_DerivedWithPropertyOverride: DerivedWithPropertyOverride? = grandDerived.delegate()
assertTrue(delegate16_DerivedWithPropertyOverride is Base)
assertTrue(delegate16_DerivedWithPropertyOverride is FooProtocol)
assertTrue(delegate16_DerivedWithPropertyOverride is BarProtocol)
assertTrue(delegate16_DerivedWithPropertyOverride is DerivedWithPropertyOverride)
assertTrue(delegate16_DerivedWithPropertyOverride is GrandDerivedWithPropertyOverride)
assertEquals(grandDerived, delegate16_DerivedWithPropertyOverride)
val delegate17_Base: Base? = (grandDerived as Base).delegate()
assertTrue(delegate17_Base is Base)
assertTrue(delegate17_Base is FooProtocol)
assertTrue(delegate17_Base is BarProtocol)
assertTrue(delegate17_Base is DerivedWithPropertyOverride)
assertTrue(delegate17_Base is GrandDerivedWithPropertyOverride)
assertEquals(grandDerived, delegate17_Base)
val delegate18_FooProtocol: FooProtocol? = (grandDerived as FooProtocol).delegate()
assertTrue(delegate18_FooProtocol is Base)
assertTrue(delegate18_FooProtocol is FooProtocol)
assertTrue(delegate18_FooProtocol is BarProtocol)
assertTrue(delegate18_FooProtocol is DerivedWithPropertyOverride)
assertTrue(delegate18_FooProtocol is GrandDerivedWithPropertyOverride)
assertEquals(grandDerived, delegate18_FooProtocol)
val delegate19_BarProtocol: BarProtocol? = (grandDerived as BarProtocol).delegate()
assertTrue(delegate19_BarProtocol is Base)
assertTrue(delegate19_BarProtocol is FooProtocol)
assertTrue(delegate19_BarProtocol is BarProtocol)
assertTrue(delegate19_BarProtocol is DerivedWithPropertyOverride)
assertTrue(delegate19_BarProtocol is GrandDerivedWithPropertyOverride)
assertEquals(grandDerived, delegate19_BarProtocol)
val delegate20_DerivedWithPropertyOverride: DerivedWithPropertyOverride? = (grandDerived as DerivedWithPropertyOverride).delegate()
assertTrue(delegate20_DerivedWithPropertyOverride is Base)
assertTrue(delegate20_DerivedWithPropertyOverride is FooProtocol)
assertTrue(delegate20_DerivedWithPropertyOverride is BarProtocol)
assertTrue(delegate20_DerivedWithPropertyOverride is DerivedWithPropertyOverride)
assertTrue(delegate20_DerivedWithPropertyOverride is GrandDerivedWithPropertyOverride)
assertEquals(grandDerived, delegate20_DerivedWithPropertyOverride)
}
private fun testAssigmmentDerivedWithPropertyOverrideToGrandDerivedWithPropertyOverride() {
val grandDerived = GrandDerivedWithPropertyOverride()
val delegate10_Base: Base? = grandDerived.delegate
assertEquals(null, delegate10_Base)
val delegate11_Bar: BarProtocol? = grandDerived.delegate()
assertEquals(null, delegate11_Bar)
val derived = DerivedWithPropertyOverride()
grandDerived.delegate = derived
grandDerived.setDelegate(derived) // argument type mismatch: actual type is 'library.Base', but 'library.DerivedWithPropertyOverride?' was expected, this deserves a diagnostic test
val delegate12_Base: Base? = grandDerived.delegate
assertTrue(delegate12_Base is Base)
assertTrue(delegate12_Base is FooProtocol)
assertTrue(delegate12_Base is BarProtocol)
assertTrue(delegate12_Base is DerivedWithPropertyOverride)
assertFalse(delegate12_Base is GrandDerivedWithPropertyOverride)
assertEquals(derived, delegate12_Base)
val delegate13_Base: Base? = (grandDerived as Base).delegate
assertTrue(delegate13_Base is Base)
assertTrue(delegate13_Base is FooProtocol)
assertTrue(delegate13_Base is BarProtocol)
assertTrue(delegate13_Base is DerivedWithPropertyOverride)
assertFalse(delegate13_Base is GrandDerivedWithPropertyOverride)
assertEquals(derived, delegate13_Base)
val delegate14_Foo: FooProtocol? = (grandDerived as FooProtocol).delegate
assertTrue(delegate14_Foo is Base)
assertTrue(delegate14_Foo is FooProtocol)
assertTrue(delegate14_Foo is BarProtocol)
assertTrue(delegate14_Foo is DerivedWithPropertyOverride)
assertFalse(delegate14_Foo is GrandDerivedWithPropertyOverride)
assertEquals(derived, delegate14_Foo)
val delegate15_Bar: BarProtocol? = (grandDerived as BarProtocol).delegate
assertTrue(delegate15_Bar is Base)
assertTrue(delegate15_Bar is FooProtocol)
assertTrue(delegate15_Bar is BarProtocol)
assertTrue(delegate15_Bar is DerivedWithPropertyOverride)
assertFalse(delegate15_Bar is GrandDerivedWithPropertyOverride)
assertEquals(derived, delegate15_Bar)
val delegate16_DerivedWithPropertyOverride: DerivedWithPropertyOverride? = (grandDerived as DerivedWithPropertyOverride).delegate()
assertTrue(delegate16_DerivedWithPropertyOverride is Base)
assertTrue(delegate16_DerivedWithPropertyOverride is FooProtocol)
assertTrue(delegate16_DerivedWithPropertyOverride is BarProtocol)
assertTrue(delegate16_DerivedWithPropertyOverride is DerivedWithPropertyOverride)
assertFalse(delegate16_DerivedWithPropertyOverride is GrandDerivedWithPropertyOverride)
assertEquals(derived, delegate16_DerivedWithPropertyOverride)
}
@@ -0,0 +1,30 @@
/*
* 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
// DISABLE_NATIVE: isAppleTarget=false
// There is no GameController on watchOS.
// DISABLE_NATIVE: targetFamily=WATCHOS
// MODULE: cinterop
// FILE: kt59167.def
language=Objective-C
---
#import <GameController/GCDevice.h>
// We only need to touch the problematic header to trigger the problem,
// so actual code does not matter.
id<GCDevice> dummy() {
return nil;
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.test.*
import kt59167.*
fun box(): String {
assertNull(dummy())
return "OK"
}
@@ -0,0 +1,51 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop_kt63048
// FILE: kt63048.def
language = Objective-C
headers = kt63048.h
// FILE: kt63048.h
#import "Foundation/NSString.h"
#import "Foundation/NSObject.h"
@interface WithClassProperty : NSObject
-(instancetype) init;
@property (class, readonly, copy) NSString * stringProperty;
@end
// FILE: kt63048.m
#import "kt63048.h"
@implementation WithClassProperty : NSObject
-(instancetype) init {}
+ (NSString *) stringProperty { return @"153"; }
@end
// MODULE: main(cinterop_kt63048)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class, kotlin.experimental.ExperimentalObjCName::class)
import kt63048.*
import kotlin.test.assertEquals
@ObjCName("KotlinImplWithCompanionPropertyOverride")
class Impl : WithClassProperty() {
companion object : WithClassPropertyMeta() {
override fun stringProperty(): String? = "42"
}
}
@ObjCName("KotlinImplWithoutCompanionPropertyOverride")
class ImplWithoutOverride : WithClassProperty() {
companion object : WithClassPropertyMeta() {
}
}
fun box(): String {
assertEquals("42", Impl.stringProperty())
assertEquals("153", ImplWithoutOverride.stringProperty())
return "OK"
}
@@ -0,0 +1,31 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: kt63049.def
depends = Foundation
language = Objective-C
headers = kt63049.h
// FILE: kt63049.h
#import "Foundation/NSObject.h"
@interface KT63049 : NSObject
@end
// FILE: kt63049.m
#import "kt63049.h"
@implementation KT63049 : NSObject
@end
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class, kotlin.experimental.ExperimentalObjCName::class)
import kt63049.*
import kotlin.test.assertEquals
class Impl : KT63049() {
companion object : KT63049Meta() {
fun stringProperty(): String? = "OK"
}
}
fun box() = Impl.stringProperty()
@@ -0,0 +1,57 @@
/*
* 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
// MODULE: lib1
// FILE: lib1.def
language=Objective-C
headers=lib1.h
// FILE: lib1.h
@class Foo;
@protocol Bar;
struct Baz;
// MODULE: lib2(lib1)
// FILE: lib2.def
language=Objective-C
headers=lib2.h
// FILE: lib2.h
#import "../lib1/lib1.h"
Foo* createFoo() {
return 0;
}
id<Bar> createBar() {
return 0;
}
struct Baz* createBaz() {
return 0;
}
// MODULE: main(lib1,lib2)
// FILE: main.kt
import kotlinx.cinterop.CPointer
import lib1.*
import lib2.*
import cnames.structs.Baz
import objcnames.classes.Foo
import objcnames.protocols.BarProtocol
@OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
fun box(): String {
val foo: Foo? = createFoo()
if (foo !== null) return "FAIL 1"
val bar: BarProtocol? = createBar()
if (bar !== null) return "FAIL 2"
val baz: CPointer<Baz>? = createBaz()
if (baz !== null) return "FAIL 3"
return "OK"
}
@@ -0,0 +1,72 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: leakMemoryWithRunningThreadUnchecked.def
---
void test_RunInNewThread(void (*)());
// FILE: leakMemoryWithRunningThreadUnchecked.h
#ifdef __cplusplus
extern "C" {
#endif
void test_RunInNewThread(void (*)());
#ifdef __cplusplus
}
#endif
// FILE: leakMemoryWithRunningThreadUnchecked.cpp
#include "leakMemoryWithRunningThreadUnchecked.h"
#include <atomic>
#include <thread>
extern "C" void test_RunInNewThread(void (*f)()) {
std::atomic<bool> haveRun(false);
std::thread t([f, &haveRun]() {
f();
haveRun = true;
while (true) {}
});
t.detach();
while (!haveRun) {}
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(
kotlin.experimental.ExperimentalNativeApi::class,
kotlin.native.runtime.NativeRuntimeApi::class,
kotlinx.cinterop.ExperimentalForeignApi::class
)
import leakMemoryWithRunningThreadUnchecked.*
import kotlin.concurrent.AtomicInt
import kotlin.native.concurrent.*
import kotlin.native.Platform
import kotlin.test.*
import kotlinx.cinterop.*
val global = AtomicInt(0)
fun ensureInititalized() {
// Only needed with the legacy MM. TODO: Remove when legacy MM is gone.
kotlin.native.initRuntimeIfNeeded()
// Leak memory
StableRef.create(Any())
global.value = 1
}
fun box(): String {
Platform.isMemoryLeakCheckerActive = true
kotlin.native.runtime.Debugging.forceCheckedShutdown = false
assertTrue(global.value == 0)
// Created a thread, made sure Kotlin is initialized there.
test_RunInNewThread(staticCFunction(::ensureInititalized))
assertTrue(global.value == 1)
// Now exiting. With unchecked shutdown, we exit quietly, even though there're
// unfinished threads with runtimes.
return "OK"
}
@@ -0,0 +1,125 @@
// TARGET_BACKEND: NATIVE
// DISABLE_NATIVE: isAppleTarget=false
// LANGUAGE: +ImplicitSignedToUnsignedIntegerConversion
// 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
__attribute__((objc_runtime_name("CC")))
__attribute__((swift_name("CC")))
@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
@interface CallingConventions(Ext)
+ (uint64_t)regularExt:(uint64_t)arg;
- (uint64_t)regularExt:(uint64_t)arg;
+ (uint64_t)directExt:(uint64_t)arg __attribute__((objc_direct));
- (uint64_t)directExt:(uint64_t)arg __attribute__((objc_direct));
@end
__attribute__((objc_runtime_name("CCH")))
__attribute__((swift_name("CCH")))
@interface CallingConventionsHeir : CallingConventions
@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
@implementation CallingConventions(Ext)
+ TEST_METHOD_IMPL(regularExt);
- TEST_METHOD_IMPL(regularExt);
+ TEST_METHOD_IMPL(directExt);
- TEST_METHOD_IMPL(directExt);
@end
@implementation CallingConventionsHeir
@end
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import direct.*
import kotlinx.cinterop.*
import kotlin.test.*
class CallingConventionsNativeHeir() : CallingConventions() {
// nothing
}
typealias CC = CallingConventions
typealias CCH = CallingConventionsHeir
typealias CCN = CallingConventionsNativeHeir
// KT-54610
fun box(): String {
autoreleasepool {
val cc = CC()
val cch = CCH()
val ccn = CCN()
assertEquals(42UL, CC.regular(42))
assertEquals(42UL, cc.regular(42))
assertEquals(42UL, CC.regularExt(42))
assertEquals(42UL, cc.regularExt(42))
assertEquals(42UL, CCH.regular(42))
assertEquals(42UL, cch.regular(42))
assertEquals(42UL, CCH.regularExt(42))
assertEquals(42UL, cch.regularExt(42))
assertEquals(42UL, ccn.regular(42UL))
assertEquals(42UL, ccn.regularExt(42UL))
assertEquals(42UL, CC.direct(42))
assertEquals(42UL, cc.direct(42))
assertEquals(42UL, CC.directExt(42))
assertEquals(42UL, cc.directExt(42))
assertEquals(42UL, CCH.direct(42))
assertEquals(42UL, cch .direct(42))
assertEquals(42UL, CCH.directExt(42))
assertEquals(42UL, cch .directExt(42))
assertEquals(42UL, ccn .direct(42UL))
assertEquals(42UL, ccn .directExt(42UL))
}
return "OK"
}
@@ -0,0 +1,113 @@
// TARGET_BACKEND: NATIVE
// `import objcnames` somehow works only with NATIVE_STANDALONE test directive
// NATIVE_STANDALONE
// DISABLE_NATIVE: isAppleTarget=false
// MODULE: a
// FILE: a.def
language = Objective-C
---
#import <Foundation/Foundation.h>
#include <stdio.h>
struct ForwardDeclaredStruct;
@class ForwardDeclaredClass;
@protocol ForwardDeclaredProtocol;
NSString* consumeProtocol(id<ForwardDeclaredProtocol> s) {
return [NSString stringWithUTF8String:"Protocol"];
}
NSString* consumeClass(ForwardDeclaredClass* s) {
return [NSString stringWithUTF8String:"Class"];
}
NSString* consumeStruct(struct ForwardDeclaredStruct* s) {
return [NSString stringWithUTF8String:"Struct"];
}
// MODULE: b
// FILE: b.def
language = Objective-C
headers = b.h
---
// FILE: b.h
#define NS_FORMAT_ARGUMENT(X)
#import <Foundation/Foundation.h>
@protocol ForwardDeclaredProtocol
@end
@interface ForwardDeclaredProtocolImpl : NSObject<ForwardDeclaredProtocol>
@end;
@interface ForwardDeclaredClass : NSObject
@end;
struct ForwardDeclaredStruct {};
id<ForwardDeclaredProtocol> produceProtocol();
ForwardDeclaredClass* produceClass();
struct ForwardDeclaredStruct* produceStruct();
// FILE: b.m
#import "b.h"
@implementation ForwardDeclaredProtocolImpl : NSObject
@end;
@implementation ForwardDeclaredClass : NSObject
@end;
id<ForwardDeclaredProtocol> produceProtocol() {
return [ForwardDeclaredProtocolImpl new];
}
ForwardDeclaredClass* produceClass() {
return [ForwardDeclaredClass new];
}
struct ForwardDeclaredStruct S;
struct ForwardDeclaredStruct* produceStruct() {
return &S;
}
// MODULE: lib(a)
// FILE: lib.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import cnames.structs.ForwardDeclaredStruct
import objcnames.classes.ForwardDeclaredClass
import objcnames.protocols.ForwardDeclaredProtocolProtocol
import a.*
import kotlinx.cinterop.*
fun testStruct(s: Any?) = consumeStruct(s as CPointer<ForwardDeclaredStruct>)
fun testClass(s: Any?) = consumeClass(s as ForwardDeclaredClass)
fun testProtocol(s: Any?) = consumeProtocol(s as ForwardDeclaredProtocolProtocol)
fun <T : ForwardDeclaredClass> testClass2Impl(s: Any?) = consumeClass(s as T)
fun <T : ForwardDeclaredProtocolProtocol> testProtocol2Impl(s: Any?) = consumeProtocol(s as T)
fun testClass2(s: Any?) = testClass2Impl<ForwardDeclaredClass>(s)
fun testProtocol2(s: Any?) = testProtocol2Impl<ForwardDeclaredProtocolProtocol>(s)
// MODULE: main(lib, b)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import a.*
import b.*
fun box(): String {
if (testStruct(produceStruct()) != "Struct") throw IllegalStateException()
if (testClass(produceClass()) != "Class") throw IllegalStateException()
if (testProtocol(produceProtocol()) != "Protocol") throw IllegalStateException()
if (testClass2(produceClass()) != "Class") throw IllegalStateException()
if (testProtocol2(produceProtocol()) != "Protocol") throw IllegalStateException()
return "OK"
}
@@ -0,0 +1,34 @@
// TARGET_BACKEND: NATIVE
// DISABLE_NATIVE: isAppleTarget=false
// FREE_CINTEROP_ARGS: -compiler-option -fmodule-map-file=$generatedSourcesDir/cinterop/module_library.modulemap
// MODULE: cinterop
// FILE: module_library.def
language = Objective-C
modules = module_library
// FILE: module_library.modulemap
module module_library {
umbrella header "module_library_umbrella.h"
export *
module * { export * }
}
// FILE: module_library_umbrella.h
#import <foo.h>
// FILE: foo.h
#define ANSWER 42
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import module_library.*
fun box(): String {
val answer = ANSWER
if (answer != 42)
return "FAIL: $answer"
return "OK"
}
@@ -0,0 +1,78 @@
// TARGET_BACKEND: NATIVE
// DISABLE_NATIVE: isAppleTarget=false
// Without a fix, fails in two-stage mode.
// The bug was accidentally fixed with lazy IR for caches, so testing it with this feature disabled:
// FREE_COMPILER_ARGS: -Xlazy-ir-for-caches=disable
// MODULE: cinterop
// FILE: objclib.def
language = Objective-C
headers = objclib.h
headerFilter = objclib.h **/NSObject.h **/NSDate.h **/NSUUID.h
// FILE: objclib.h
#import <Foundation/NSObject.h>
#import <Foundation/NSDate.h>
#import <Foundation/NSUUID.h>
@interface MyClass1 : NSObject
@end
@interface MyClass2 : NSObject
@end
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.reflect.*
import kotlin.test.*
import objclib.*
// https://youtrack.jetbrains.com/issue/KT-48816
open class Base<Ref> {
operator fun KProperty1<Ref, NSUUID>.getValue(ref: Base<Ref>, property: KProperty<*>): NSUUID? {
return null
}
operator fun KProperty1<Ref, NSDate>.getValue(ref: Base<Ref>, property: KProperty<*>): NSDate? {
return null
}
}
class Usage: Base<B>()
class B
// The compilation should fail with the above;
// but anyway try to actually use the code, just to ensure it doesn't get DCEd:
val B.uuid: NSUUID get() = fail()
val B.date: NSDate get() = fail()
fun test1() {
val uuidProperty = B::uuid
val dateProperty = B::date
val usage = Usage()
with(usage) {
assertNull(uuidProperty.getValue(usage, uuidProperty))
assertNull(dateProperty.getValue(usage, dateProperty))
}
}
// One more reproducer, just in case:
class Property<out R>
open class Base2 {
fun getValue(property: Property<MyClass1>) = null
fun getValue(property: Property<MyClass2>) = null
}
class Usage2 : Base2()
fun test2() {
val usage = Usage2()
assertNull(usage.getValue(Property<MyClass1>()))
assertNull(usage.getValue(Property<MyClass2>()))
}
fun box(): String {
test1()
test2()
return "OK"
}
@@ -0,0 +1,77 @@
// TARGET_BACKEND: NATIVE
// DISABLE_NATIVE: isAppleTarget=false
// The bug was accidentally fixed with lazy IR for caches, so testing it with this feature enabled, and disabled(in other test file):
// FREE_COMPILER_ARGS: -Xlazy-ir-for-caches=enable
// MODULE: cinterop
// FILE: objclib.def
language = Objective-C
headers = objclib.h
headerFilter = objclib.h **/NSObject.h **/NSDate.h **/NSUUID.h
// FILE: objclib.h
#import <Foundation/NSObject.h>
#import <Foundation/NSDate.h>
#import <Foundation/NSUUID.h>
@interface MyClass1 : NSObject
@end
@interface MyClass2 : NSObject
@end
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.reflect.*
import kotlin.test.*
import objclib.*
// https://youtrack.jetbrains.com/issue/KT-48816
open class Base<Ref> {
operator fun KProperty1<Ref, NSUUID>.getValue(ref: Base<Ref>, property: KProperty<*>): NSUUID? {
return null
}
operator fun KProperty1<Ref, NSDate>.getValue(ref: Base<Ref>, property: KProperty<*>): NSDate? {
return null
}
}
class Usage: Base<B>()
class B
// The compilation should fail with the above;
// but anyway try to actually use the code, just to ensure it doesn't get DCEd:
val B.uuid: NSUUID get() = fail()
val B.date: NSDate get() = fail()
fun test1() {
val uuidProperty = B::uuid
val dateProperty = B::date
val usage = Usage()
with(usage) {
assertNull(uuidProperty.getValue(usage, uuidProperty))
assertNull(dateProperty.getValue(usage, dateProperty))
}
}
// One more reproducer, just in case:
class Property<out R>
open class Base2 {
fun getValue(property: Property<MyClass1>) = null
fun getValue(property: Property<MyClass2>) = null
}
class Usage2 : Base2()
fun test2() {
val usage = Usage2()
assertNull(usage.getValue(Property<MyClass1>()))
assertNull(usage.getValue(Property<MyClass2>()))
}
fun box(): String {
test1()
test2()
return "OK"
}
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2022 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
// `import objcnames` somehow works only with NATIVE_STANDALONE test directive
// NATIVE_STANDALONE
// The test checks no collision between kt49034.__darwin_fp_control and platform.posix.__darwin_fp_control
// The test makes sense only on Apple x64 targets, where `class __darwin_fp_control` present in posix platform lib
// DISABLE_NATIVE: isAppleTarget=false
// DISABLE_NATIVE: targetArchitecture=ARM64
// MODULE: cinterop
// FILE: kt49034.def
headers = kt49034.h
language = Objective-C
// FILE: kt49034.h
@class __darwin_fp_control;
void foo(__darwin_fp_control*);
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import objcnames.classes.__darwin_fp_control
open class C<T : kotlinx.cinterop.ObjCObject>
class D : C<__darwin_fp_control>()
fun box(): String {
println(D())
return "OK"
}
// FILE: checkPlatformDarwinFPControl.kt
import platform.posix.__darwin_fp_control
@@ -0,0 +1,58 @@
/*
* Copyright 2010-2022 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
// The test depends on collision between kt49034.JSContext and platform.JavaScriptCore.JSContext
// DISABLE_NATIVE: isAppleTarget=false
// There is no JavaScriptCore on watchOS.
// DISABLE_NATIVE: targetFamily=WATCHOS
// MODULE: cinterop
// FILE: kt49034.def
headers = kt49034.h
// FILE: kt49034.h
#ifdef __cplusplus
extern "C" {
#endif
struct JSContext;
struct JSContext* bar();
#ifdef __cplusplus
}
#endif
// FILE: impl.c
#include "kt49034.h"
struct JSContext {
int field;
};
struct JSContext global = { 15 };
extern "C" struct JSContext* bar() {
return &global;
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kt49034.bar
import cnames.structs.JSContext
import kotlinx.cinterop.CPointer
fun baz(s: CPointer<JSContext>) {
println(s)
}
fun box(): String {
baz(bar()!!)
return "OK"
}
// FILE: checkPlatformJavaScriptCore.kt
import platform.JavaScriptCore.JSContext
@@ -0,0 +1,39 @@
// TARGET_BACKEND: NATIVE
// DISABLE_NATIVE: isAppleTarget=false
// FREE_CINTEROP_ARGS: -compiler-option -F$generatedSourcesDir/cinterop
// MODULE: cinterop
// FILE: objclib.def
language = Objective-C
modules = Foo
---
static int getDefInt() {
return 2;
}
static int getFrameworkIntFromDef() {
return getFrameworkInt();
}
// FILE: Foo.framework/Headers/Foo.h
static int getFrameworkInt() {
return 1;
}
// FILE: Foo.framework/Modules/module.modulemap
framework module Foo {
umbrella header "Foo.h"
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.test.*
import objclib.*
fun box(): String {
assertEquals(1, getFrameworkInt())
assertEquals(2, getDefInt())
assertEquals(1, getFrameworkIntFromDef())
return "OK"
}
@@ -0,0 +1,104 @@
// TARGET_BACKEND: NATIVE
// DISABLE_NATIVE: isAppleTarget=false
// MODULE: cinterop
// FILE: lib.def
language = Objective-C
headers = lib.h
headerFilter = lib.h
// FILE: lib.h
#import <Foundation/NSObject.h>
#import <Foundation/NSDate.h>
#import <Foundation/NSUUID.h>
@interface ObjCClass : NSObject
- (NSString*)fooWithArg:(int)arg arg2:(NSString*)arg2;
- (NSString*)fooWithArg:(int)ohNoOtherName name2:(NSString*)name2;
- (NSString*)fooWithArg:(int)arg name3:(NSString*)name3;
@end
// FILE: lib.m
#import "lib.h"
@implementation ObjCClass {
}
- (NSString*)fooWithArg:(int)arg arg2:(NSString*)arg2 {
return @"A";
}
- (NSString*)fooWithArg:(int)ohNoOtherName name2:(NSString*)name2 {
return @"B";
}
- (NSString*)fooWithArg:(int)arg name3:(NSString*)name3 {
return @"C";
}
@end
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
// required for K1
@file:Suppress("CONFLICTING_OVERLOADS", "UNRESOLVED_REFERENCE", "API_NOT_AVAILABLE")
import lib.ObjCClass
import kotlinx.cinterop.ObjCSignatureOverride
class OverrideAll : ObjCClass() {
@ObjCSignatureOverride
override fun fooWithArg(arg: Int, arg2: String?) = "D"
@ObjCSignatureOverride
override fun fooWithArg(ohNoOtherName: Int, name2: String?) = "E"
@ObjCSignatureOverride
override fun fooWithArg(arg: Int, name3: String?) = "F"
}
class OverrideNone : ObjCClass() {
}
class OverrideOne : ObjCClass() {
override fun fooWithArg(arg: Int, arg2: String?) = "G"
}
class OverrideWithDifferentFirstArgName : ObjCClass() {
@ObjCSignatureOverride
override fun fooWithArg(a: Int, arg2: String?) = "H"
@ObjCSignatureOverride
override fun fooWithArg(b: Int, name2: String?) = "I"
@ObjCSignatureOverride
override fun fooWithArg(c: Int, name3: String?) = "J"
}
fun test(x: ObjCClass, expected: String) {
val res = x.fooWithArg(arg = 0, arg2 = "") +
x.fooWithArg(ohNoOtherName = 0, name2="") +
x.fooWithArg(arg = 0, name3 = "")
if (res != expected) throw IllegalStateException("Fail ${x::class}: ${res} instead of $expected")
}
fun box(): String {
test(ObjCClass(), "ABC")
test(OverrideAll(), "DEF")
test(OverrideNone(), "ABC")
test(OverrideOne(), "GBC")
test(OverrideWithDifferentFirstArgName(), "HIJ")
// Also test non-virtual calls
val x1 = OverrideAll()
val res1 = x1.fooWithArg(arg = 0, arg2 = "") +
x1.fooWithArg(ohNoOtherName = 0, name2="") +
x1.fooWithArg(arg = 0, name3 = "")
if (res1 != "DEF") throw IllegalStateException("Fail OverrideAll non-virtual: ${res1} instead of DEF")
val x2 = OverrideNone()
val res2 = x2.fooWithArg(arg = 0, arg2 = "") +
x2.fooWithArg(ohNoOtherName = 0, name2="") +
x2.fooWithArg(arg = 0, name3 = "")
if (res2 != "ABC") throw IllegalStateException("Fail OverrideNone non-virtual: ${res2} instead of ABC")
return "OK"
}
@@ -0,0 +1,54 @@
// TARGET_BACKEND: NATIVE
// DISABLE_NATIVE: isAppleTarget=false
// MODULE: cinterop
// FILE: objclib.def
language = Objective-C
headers = objclib.h
headerFilter = objclib.h
// FILE: objclib.h
#import <objc/NSObject.h>
static NSObject* __weak globalObject = nil;
void setObject(NSObject* obj) {
globalObject = obj;
}
bool isObjectAlive() {
return globalObject != nil;
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(ObsoleteWorkersApi::class, kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.native.concurrent.*
import kotlin.test.*
import kotlinx.cinterop.autoreleasepool
import objclib.*
fun box(): String {
val success = autoreleasepool {
run()
}
// Experimental MM supports arbitrary object sharing.
return if (success) "OK" else "FAIL"
}
private class NSObjectImpl : NSObject() {
var x = 111
}
fun run() = withWorker {
val obj = NSObjectImpl()
setObject(obj)
try {
execute(TransferMode.SAFE, {}) {
isObjectAlive()
}.result
} catch (e: Throwable) {
false
}
}
@@ -0,0 +1,17 @@
/*
* Copyright 2010-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: part1.part2.def
package package1
---
#define OK_STRING "OK"
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import package1.*
fun box(): String = OK_STRING
@@ -0,0 +1,17 @@
/*
* Copyright 2010-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: filename1.filename2.def
package package1.package2
---
#define OK_STRING "OK"
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import package1.package2.*
fun box(): String = OK_STRING
@@ -0,0 +1,16 @@
/*
* Copyright 2010-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: root1.root2.def
---
#define OK_STRING "OK"
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import root2.root1.*
fun box(): String = OK_STRING
@@ -0,0 +1,17 @@
/*
* Copyright 2010-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: packages.def
package package1
---
#define OK_STRING "OK"
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import package1.*
fun box(): String = OK_STRING
@@ -0,0 +1,17 @@
/*
* Copyright 2010-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: packages.def
package package1.package2
---
#define OK_STRING "OK"
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import package1.package2.*
fun box(): String = OK_STRING
@@ -0,0 +1,16 @@
/*
* Copyright 2010-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: root1.def
---
#define OK_STRING "OK"
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import root1.*
fun box(): String = OK_STRING
@@ -0,0 +1,52 @@
/*
* Copyright 2010-2021 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
// NATIVE_STANDALONE
// MODULE: cinterop
// FILE: threadStates.def
language = C
---
void assertNativeThreadState();
void runCallback(void(*callback)(void)) {
assertNativeThreadState();
callback();
assertNativeThreadState();
}
// FILE: threadStates.cpp
#include <stdio.h>
#include <stdlib.h>
// Implemented in the runtime for test purposes.
extern "C" bool Kotlin_Debugging_isThreadStateNative();
extern "C" void assertNativeThreadState() {
if (!Kotlin_Debugging_isThreadStateNative()) {
printf("Incorrect thread state. Expected native thread state.");
abort();
}
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class, kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.native.runtime.Debugging
import kotlin.test.*
import kotlinx.cinterop.*
import threadStates.*
fun box(): String {
runCallback(staticCFunction { ->
assertRunnableThreadState()
})
assertRunnableThreadState()
return "OK"
}
fun assertRunnableThreadState() {
assertTrue(Debugging.isThreadStateRunnable)
}
@@ -0,0 +1,41 @@
/*
* Copyright 2010-2021 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
// NATIVE_STANDALONE
// MODULE: cinterop
// FILE: threadStates.def
language = C
---
void runInNewThread(void(*callback)(void));
// FILE: threadStates.cpp
#include <thread>
extern "C" void runInNewThread(void(*callback)(void)) {
std::thread t([callback]() {
callback();
});
t.join();
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class, kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.native.runtime.Debugging
import kotlin.test.*
import kotlinx.cinterop.*
import threadStates.*
fun box(): String {
runInNewThread(staticCFunction { ->
assertRunnableThreadState()
})
return "OK"
}
fun assertRunnableThreadState() {
assertTrue(Debugging.isThreadStateRunnable)
}
@@ -0,0 +1,64 @@
/*
* Copyright 2010-2021 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
// NATIVE_STANDALONE
// MODULE: cinterop
// FILE: threadStates.def
language = C
---
void assertNativeThreadState();
void runCallback(void(*callback)(void)) {
assertNativeThreadState();
callback();
assertNativeThreadState();
}
// FILE: threadStates.cpp
#include <stdio.h>
#include <stdlib.h>
// Implemented in the runtime for test purposes.
extern "C" bool Kotlin_Debugging_isThreadStateNative();
extern "C" void assertNativeThreadState() {
if (!Kotlin_Debugging_isThreadStateNative()) {
printf("Incorrect thread state. Expected native thread state.");
abort();
}
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class, kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.native.runtime.Debugging
import kotlin.test.*
import kotlinx.cinterop.staticCFunction
import threadStates.*
fun box(): String {
try {
runCallback(staticCFunction(::throwException))
} catch (e: CustomException) {
assertRunnableThreadState()
return "OK"
} catch (e: Throwable) {
assertRunnableThreadState()
fail("Wrong exception type: ${e.message}")
}
fail("No exception thrown")
}
fun assertRunnableThreadState() {
assertTrue(Debugging.isThreadStateRunnable)
}
class CustomException() : Exception()
fun throwException() {
assertRunnableThreadState()
throw CustomException()
}
@@ -0,0 +1,63 @@
/*
* Copyright 2010-2021 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
// NATIVE_STANDALONE
// MODULE: cinterop
// FILE: threadStates.def
language = C
---
void assertNativeThreadState();
void runCallback(void(*callback)(void)) {
assertNativeThreadState();
callback();
assertNativeThreadState();
}
// FILE: threadStates.cpp
#include <stdio.h>
#include <stdlib.h>
// Implemented in the runtime for test purposes.
extern "C" bool Kotlin_Debugging_isThreadStateNative();
extern "C" void assertNativeThreadState() {
if (!Kotlin_Debugging_isThreadStateNative()) {
printf("Incorrect thread state. Expected native thread state.");
abort();
}
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class, kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.native.runtime.Debugging
import kotlin.test.*
import kotlinx.cinterop.staticCFunction
import threadStates.*
fun box(): String {
try {
runCallback(staticCFunction(::throwException))
} catch (e: CustomException) {
assertRunnableThreadState()
return "OK"
} finally {
assertRunnableThreadState()
}
fail("No exception thrown")
}
fun assertRunnableThreadState() {
assertTrue(Debugging.isThreadStateRunnable)
}
class CustomException() : Exception()
fun throwException() {
assertRunnableThreadState()
throw CustomException()
}
@@ -0,0 +1,63 @@
/*
* Copyright 2010-2021 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
// NATIVE_STANDALONE
// MODULE: cinterop
// FILE: threadStates.def
language = C
---
void assertNativeThreadState();
void runCallback(void(*callback)(void)) {
assertNativeThreadState();
callback();
assertNativeThreadState();
}
// FILE: threadStates.cpp
#include <stdio.h>
#include <stdlib.h>
// Implemented in the runtime for test purposes.
extern "C" bool Kotlin_Debugging_isThreadStateNative();
extern "C" void assertNativeThreadState() {
if (!Kotlin_Debugging_isThreadStateNative()) {
printf("Incorrect thread state. Expected native thread state.");
abort();
}
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class, kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.native.runtime.Debugging
import kotlin.test.*
import kotlinx.cinterop.staticCFunction
import threadStates.*
fun box(): String {
try {
try {
runCallback(staticCFunction(::throwException))
} finally {
assertRunnableThreadState()
}
assertRunnableThreadState()
} catch (_: CustomException) {}
return "OK"
}
fun assertRunnableThreadState() {
assertTrue(Debugging.isThreadStateRunnable)
}
class CustomException() : Exception()
fun throwException() {
assertRunnableThreadState()
throw CustomException()
}
@@ -0,0 +1,25 @@
/*
* Copyright 2010-2021 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
// NATIVE_STANDALONE
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class, kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.native.runtime.Debugging
import kotlin.test.*
import kotlinx.cinterop.*
fun box(): String {
val funPtr = staticCFunction { ->
assertRunnableThreadState()
}
assertRunnableThreadState()
funPtr()
assertRunnableThreadState()
return "OK"
}
fun assertRunnableThreadState() {
assertTrue(Debugging.isThreadStateRunnable)
}
@@ -0,0 +1,51 @@
/*
* Copyright 2010-2021 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
// NATIVE_STANDALONE
// MODULE: cinterop
// FILE: threadStates.def
language = C
---
#include <stdint.h>
void assertNativeThreadState();
int32_t answer() {
assertNativeThreadState();
return 42;
}
// FILE: threadStates.cpp
#include <stdio.h>
#include <stdlib.h>
// Implemented in the runtime for test purposes.
extern "C" bool Kotlin_Debugging_isThreadStateNative();
extern "C" void assertNativeThreadState() {
if (!Kotlin_Debugging_isThreadStateNative()) {
printf("Incorrect thread state. Expected native thread state.");
abort();
}
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class, kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.native.runtime.Debugging
import kotlin.test.*
import kotlinx.cinterop.*
import threadStates.*
fun box(): String {
answer()
assertRunnableThreadState()
return "OK"
}
fun assertRunnableThreadState() {
assertTrue(Debugging.isThreadStateRunnable)
}
@@ -0,0 +1,67 @@
/*
* Copyright 2010-2021 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
// NATIVE_STANDALONE
// MODULE: cinterop
// FILE: threadStates.def
language = C
---
void assertNativeThreadState();
void runCallback(void(*callback)(void)) {
assertNativeThreadState();
callback();
assertNativeThreadState();
}
// FILE: threadStates.cpp
#include <stdio.h>
#include <stdlib.h>
// Implemented in the runtime for test purposes.
extern "C" bool Kotlin_Debugging_isThreadStateNative();
extern "C" void assertNativeThreadState() {
if (!Kotlin_Debugging_isThreadStateNative()) {
printf("Incorrect thread state. Expected native thread state.");
abort();
}
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class, kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.native.runtime.Debugging
import kotlin.test.*
import kotlinx.cinterop.staticCFunction
import threadStates.*
fun box(): String {
try {
runCallback(staticCFunction { ->
assertRunnableThreadState()
runCallback(staticCFunction(::throwException))
})
} catch (e: CustomException) {
assertRunnableThreadState()
return "OK"
} catch (e: Throwable) {
assertRunnableThreadState()
fail("Wrong exception type: ${e.message}")
}
fail("No exception thrown")
}
fun assertRunnableThreadState() {
assertTrue(Debugging.isThreadStateRunnable)
}
class CustomException() : Exception()
fun throwException() {
assertRunnableThreadState()
throw CustomException()
}
@@ -0,0 +1,66 @@
/*
* Copyright 2010-2021 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
// NATIVE_STANDALONE
// MODULE: cinterop
// FILE: threadStates.def
language = C
---
void assertNativeThreadState();
void runCallback(void(*callback)(void)) {
assertNativeThreadState();
callback();
assertNativeThreadState();
}
// FILE: threadStates.cpp
#include <stdio.h>
#include <stdlib.h>
// Implemented in the runtime for test purposes.
extern "C" bool Kotlin_Debugging_isThreadStateNative();
extern "C" void assertNativeThreadState() {
if (!Kotlin_Debugging_isThreadStateNative()) {
printf("Incorrect thread state. Expected native thread state.");
abort();
}
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class, kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.native.runtime.Debugging
import kotlin.test.*
import kotlinx.cinterop.staticCFunction
import threadStates.*
fun box(): String {
try {
runCallback(staticCFunction { ->
assertRunnableThreadState()
runCallback(staticCFunction(::throwException))
})
} catch (e: CustomException) {
assertRunnableThreadState()
return "OK"
} finally {
assertRunnableThreadState()
}
fail("No exception thrown")
}
fun assertRunnableThreadState() {
assertTrue(Debugging.isThreadStateRunnable)
}
class CustomException() : Exception()
fun throwException() {
assertRunnableThreadState()
throw CustomException()
}
@@ -0,0 +1,61 @@
/*
* Copyright 2010-2021 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
// NATIVE_STANDALONE
// MODULE: cinterop
// FILE: threadStates.def
language = C
---
#include <stdint.h>
void assertNativeThreadState();
void runCallback(void(*callback)(void)) {
assertNativeThreadState();
callback();
assertNativeThreadState();
}
int32_t answer() {
assertNativeThreadState();
return 42;
}
// FILE: threadStates.cpp
#include <stdio.h>
#include <stdlib.h>
// Implemented in the runtime for test purposes.
extern "C" bool Kotlin_Debugging_isThreadStateNative();
extern "C" void assertNativeThreadState() {
if (!Kotlin_Debugging_isThreadStateNative()) {
printf("Incorrect thread state. Expected native thread state.");
abort();
}
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class, kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.native.runtime.Debugging
import kotlin.test.*
import kotlinx.cinterop.*
import threadStates.*
fun box(): String {
runCallback(staticCFunction { ->
assertRunnableThreadState()
answer()
Unit
})
assertRunnableThreadState()
return "OK"
}
fun assertRunnableThreadState() {
assertTrue(Debugging.isThreadStateRunnable)
}
@@ -0,0 +1,29 @@
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: toKString.def
---
const char* empty() { return ""; }
const char* foo() { return "foo"; }
const char* kuku() { return "куку"; }
const char* invalid_utf8() { return "\x85\xAF"; }
const char* zero_in_the_middle() { return "before zero\0after zero"; }
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import toKString.*
import kotlinx.cinterop.*
import kotlin.native.*
import kotlin.test.*
fun box(): String {
assertEquals("", empty()!!.toKStringFromUtf8())
assertEquals("foo", foo()!!.toKStringFromUtf8())
assertEquals("куку", kuku()!!.toKStringFromUtf8())
assertEquals("\uFFFD\uFFFD", invalid_utf8()!!.toKStringFromUtf8())
assertEquals("before zero", zero_in_the_middle()!!.toKStringFromUtf8())
return "OK"
}
@@ -0,0 +1,18 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
inline fun foo(x: () -> Unit): String {
x()
return "OK"
}
fun String.id(s: String = this, vararg xs: Int): String = s
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
// CHECK-LABEL: entry
// CHECK-NOT: call %struct.ObjHeader* @AllocInstance
// CHECK-NOT: alloca
return foo("Fail"::id)
// CHECK-LABEL: epilogue:
}
@@ -0,0 +1,372 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlin.concurrent.*
// CHECK-AAPCS-LABEL: define i8 @"kfun:#<get-byteGlobal>(){}kotlin.Byte"()
// CHECK-DEFAULTABI-LABEL: define signext i8 @"kfun:#<get-byteGlobal>(){}kotlin.Byte"()
// CHECK-WINDOWSX64-LABEL: define i8 @"kfun:#<get-byteGlobal>(){}kotlin.Byte"()
// CHECK: load atomic i8, i8* @"kvar:byteGlobal#internal" seq_cst
// CHECK-LABEL: define void @"kfun:#<set-byteGlobal>(kotlin.Byte){}"(i8
// CHECK: store atomic i8 %{{[0-9]+}}, i8* @"kvar:byteGlobal#internal" seq_cst
@Volatile var byteGlobal: Byte = 42
// CHECK-AAPCS-LABEL: define i16 @"kfun:#<get-shortGlobal>(){}kotlin.Short"()
// CHECK-DEFAULTABI-LABEL: define signext i16 @"kfun:#<get-shortGlobal>(){}kotlin.Short"()
// CHECK-WINDOWSX64-LABEL: define i16 @"kfun:#<get-shortGlobal>(){}kotlin.Short"()
// CHECK: load atomic i16, i16* @"kvar:shortGlobal#internal" seq_cst
// CHECK-LABEL: define void @"kfun:#<set-shortGlobal>(kotlin.Short){}"(i16
// CHECK: store atomic i16 %{{[0-9]+}}, i16* @"kvar:shortGlobal#internal" seq_cst
@Volatile var shortGlobal: Short = 42
// CHECK-LABEL: define i32 @"kfun:#<get-intGlobal>(){}kotlin.Int"()
// CHECK: load atomic i32, i32* @"kvar:intGlobal#internal" seq_cst
// CHECK-LABEL: define void @"kfun:#<set-intGlobal>(kotlin.Int){}"(i32
// CHECK: store atomic i32 %{{[0-9]+}}, i32* @"kvar:intGlobal#internal" seq_cst
@Volatile var intGlobal: Int = 42
// CHECK-LABEL: define i64 @"kfun:#<get-longGlobal>(){}kotlin.Long"()
// CHECK: load atomic i64, i64* @"kvar:longGlobal#internal" seq_cst
// CHECK-LABEL: define void @"kfun:#<set-longGlobal>(kotlin.Long){}"(i64
// CHECK: store atomic i64 %{{[0-9]+}}, i64* @"kvar:longGlobal#internal" seq_cst
@Volatile var longGlobal: Long = 42
// CHECK-AAPCS-LABEL: define i1 @"kfun:#<get-booleanGlobal>(){}kotlin.Boolean"()
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#<get-booleanGlobal>(){}kotlin.Boolean"()
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#<get-booleanGlobal>(){}kotlin.Boolean"()
// CHECK: load atomic i8, i8* @"kvar:booleanGlobal#internal" seq_cst
// CHECK-LABEL: define void @"kfun:#<set-booleanGlobal>(kotlin.Boolean){}"(i1
// CHECK: store atomic i8 %{{[0-9]+}}, i8* @"kvar:booleanGlobal#internal" seq_cst
@Volatile var booleanGlobal: Boolean = true
// Byte
fun byteGlobal_getField() = byteGlobal
fun byteGlobal_setField() { byteGlobal = 0 }
// CHECK-AAPCS-LABEL: define i8 @"kfun:#byteGlobal_getAndSetField(){}kotlin.Byte"()
// CHECK-DEFAULTABI-LABEL: define signext i8 @"kfun:#byteGlobal_getAndSetField(){}kotlin.Byte"()
// CHECK-WINDOWSX64-LABEL: define i8 @"kfun:#byteGlobal_getAndSetField(){}kotlin.Byte"()
// CHECK: atomicrmw xchg i8* @"kvar:byteGlobal#internal", i8 0 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun byteGlobal_getAndSetField() = ::byteGlobal.getAndSetField(0.toByte())
// CHECK-AAPCS-LABEL: define i8 @"kfun:#byteGlobal_getAndAddField(){}kotlin.Byte"()
// CHECK-DEFAULTABI-LABEL: define signext i8 @"kfun:#byteGlobal_getAndAddField(){}kotlin.Byte"()
// CHECK-WINDOWSX64-LABEL: define i8 @"kfun:#byteGlobal_getAndAddField(){}kotlin.Byte"()
// CHECK: atomicrmw add i8* @"kvar:byteGlobal#internal", i8 0 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun byteGlobal_getAndAddField() = ::byteGlobal.getAndAddField(0.toByte())
// CHECK-AAPCS-LABEL: define i1 @"kfun:#byteGlobal_compareAndSetField(){}kotlin.Boolean"()
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#byteGlobal_compareAndSetField(){}kotlin.Boolean"()
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#byteGlobal_compareAndSetField(){}kotlin.Boolean"()
// CHECK: cmpxchg i8* @"kvar:byteGlobal#internal", i8 0, i8 1 seq_cst seq_cst
// CHECK: extractvalue { i8, i1 } %{{[0-9]+}}, 1
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun byteGlobal_compareAndSetField() = ::byteGlobal.compareAndSetField(0.toByte(), 1.toByte())
// CHECK-AAPCS-LABEL: define i8 @"kfun:#byteGlobal_compareAndExchangeField(){}kotlin.Byte"()
// CHECK-DEFAULTABI-LABEL: define signext i8 @"kfun:#byteGlobal_compareAndExchangeField(){}kotlin.Byte"()
// CHECK-WINDOWSX64-LABEL: define i8 @"kfun:#byteGlobal_compareAndExchangeField(){}kotlin.Byte"()
// CHECK: cmpxchg i8* @"kvar:byteGlobal#internal", i8 0, i8 1 seq_cst seq_cst
// CHECK: extractvalue { i8, i1 } %{{[0-9]+}}, 0
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun byteGlobal_compareAndExchangeField() = ::byteGlobal.compareAndExchangeField(0.toByte(), 1.toByte())
// Short
fun shortGlobal_getField() = shortGlobal
fun shortGlobal_setField() { shortGlobal = 0 }
// CHECK-AAPCS-LABEL: define i16 @"kfun:#shortGlobal_getAndSetField(){}
// CHECK-DEFAULTABI-LABEL: define signext i16 @"kfun:#shortGlobal_getAndSetField(){}
// CHECK-WINDOWSX64-LABEL: define i16 @"kfun:#shortGlobal_getAndSetField(){}
// CHECK: atomicrmw xchg i16* @"kvar:shortGlobal#internal", i16 0 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun shortGlobal_getAndSetField() = ::shortGlobal.getAndSetField(0.toShort())
// CHECK-AAPCS-LABEL: define i16 @"kfun:#shortGlobal_getAndAddField(){}
// CHECK-DEFAULTABI-LABEL: define signext i16 @"kfun:#shortGlobal_getAndAddField(){}
// CHECK-WINDOWSX64-LABEL: define i16 @"kfun:#shortGlobal_getAndAddField(){}
// CHECK: atomicrmw add i16* @"kvar:shortGlobal#internal", i16 0 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun shortGlobal_getAndAddField() = ::shortGlobal.getAndAddField(0.toShort())
// CHECK-AAPCS-LABEL: define i1 @"kfun:#shortGlobal_compareAndSetField(){}
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#shortGlobal_compareAndSetField(){}
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#shortGlobal_compareAndSetField(){}
// CHECK: cmpxchg i16* @"kvar:shortGlobal#internal", i16 0, i16 1 seq_cst seq_cst
// CHECK: extractvalue { i16, i1 } %{{[0-9]+}}, 1
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun shortGlobal_compareAndSetField() = ::shortGlobal.compareAndSetField(0.toShort(), 1.toShort())
// CHECK-AAPCS-LABEL: define i16 @"kfun:#shortGlobal_compareAndExchangeField(){}
// CHECK-DEFAULTABI-LABEL: define signext i16 @"kfun:#shortGlobal_compareAndExchangeField(){}
// CHECK-WINDOWSX64-LABEL: define i16 @"kfun:#shortGlobal_compareAndExchangeField(){}
// CHECK: cmpxchg i16* @"kvar:shortGlobal#internal", i16 0, i16 1 seq_cst seq_cst
// CHECK: extractvalue { i16, i1 } %{{[0-9]+}}, 0
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun shortGlobal_compareAndExchangeField() = ::shortGlobal.compareAndExchangeField(0.toShort(), 1.toShort())
// Int
fun intGlobal_getField() = intGlobal
fun intGlobal_setField() { intGlobal = 0 }
// CHECK-LABEL: define i32 @"kfun:#intGlobal_getAndSetField(){}
// CHECK: atomicrmw xchg i32* @"kvar:intGlobal#internal", i32 0 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intGlobal_getAndSetField() = ::intGlobal.getAndSetField(0)
// CHECK-LABEL: define i32 @"kfun:#intGlobal_getAndAddField(){}
// CHECK: atomicrmw add i32* @"kvar:intGlobal#internal", i32 0 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intGlobal_getAndAddField() = ::intGlobal.getAndAddField(0)
// CHECK-AAPCS-LABEL: define i1 @"kfun:#intGlobal_compareAndSetField(){}
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#intGlobal_compareAndSetField(){}
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#intGlobal_compareAndSetField(){}
// CHECK: cmpxchg i32* @"kvar:intGlobal#internal", i32 0, i32 1 seq_cst seq_cst
// CHECK: extractvalue { i32, i1 } %{{[0-9]+}}, 1
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intGlobal_compareAndSetField() = ::intGlobal.compareAndSetField(0, 1)
// CHECK-LABEL: define i32 @"kfun:#intGlobal_compareAndExchangeField(){}
// CHECK: cmpxchg i32* @"kvar:intGlobal#internal", i32 0, i32 1 seq_cst seq_cst
// CHECK: extractvalue { i32, i1 } %{{[0-9]+}}, 0
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intGlobal_compareAndExchangeField() = ::intGlobal.compareAndExchangeField(0, 1)
// Long
fun longGlobal_getField() = longGlobal
fun longGlobal_setField() { longGlobal = 0 }
// CHECK-LABEL: define i64 @"kfun:#longGlobal_getAndSetField(){}
// CHECK: atomicrmw xchg i64* @"kvar:longGlobal#internal", i64 0 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longGlobal_getAndSetField() = ::longGlobal.getAndSetField(0L)
// CHECK-LABEL: define i64 @"kfun:#longGlobal_getAndAddField(){}
// CHECK: atomicrmw add i64* @"kvar:longGlobal#internal", i64 0 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longGlobal_getAndAddField() = ::longGlobal.getAndAddField(0L)
// CHECK-AAPCS-LABEL: define i1 @"kfun:#longGlobal_compareAndSetField(){}
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#longGlobal_compareAndSetField(){}
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#longGlobal_compareAndSetField(){}
// CHECK: cmpxchg i64* @"kvar:longGlobal#internal", i64 0, i64 1 seq_cst seq_cst
// CHECK: extractvalue { i64, i1 } %{{[0-9]+}}, 1
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longGlobal_compareAndSetField() = ::longGlobal.compareAndSetField(0L, 1L)
// CHECK-LABEL: define i64 @"kfun:#longGlobal_compareAndExchangeField(){}
// CHECK: cmpxchg i64* @"kvar:longGlobal#internal", i64 0, i64 1 seq_cst seq_cst
// CHECK: extractvalue { i64, i1 } %{{[0-9]+}}, 0
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longGlobal_compareAndExchangeField() = ::longGlobal.compareAndExchangeField(0L, 1L)
// Boolean
fun booleanGlobal_getField() = booleanGlobal
fun booleanGlobal_setField() { booleanGlobal = false }
// CHECK-AAPCS-LABEL: define i1 @"kfun:#booleanGlobal_getAndSetField(){}kotlin.Boolean"
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#booleanGlobal_getAndSetField(){}kotlin.Boolean"
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#booleanGlobal_getAndSetField(){}kotlin.Boolean"
// CHECK: atomicrmw xchg i8* @"kvar:booleanGlobal#internal", i8 %{{[0-9]+}} seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun booleanGlobal_getAndSetField() = ::booleanGlobal.getAndSetField(false)
// CHECK-AAPCS-LABEL: define i1 @"kfun:#booleanGlobal_compareAndSetField(){}
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#booleanGlobal_compareAndSetField(){}
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#booleanGlobal_compareAndSetField(){}
// CHECK: cmpxchg i8* @"kvar:booleanGlobal#internal", i8 %{{[0-9]+}}, i8 %{{[0-9]+}} seq_cst seq_cst
// CHECK: extractvalue { i8, i1 } %{{[0-9]+}}, 1
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun booleanGlobal_compareAndSetField() = ::booleanGlobal.compareAndSetField(false, true)
// CHECK-AAPCS-LABEL: define i1 @"kfun:#booleanGlobal_compareAndExchangeField(){}
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#booleanGlobal_compareAndExchangeField(){}
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#booleanGlobal_compareAndExchangeField(){}
// CHECK: cmpxchg i8* @"kvar:booleanGlobal#internal", i8 %{{[0-9]+}}, i8 %{{[0-9]+}} seq_cst seq_cst
// CHECK: extractvalue { i8, i1 } %{{[0-9]+}}, 0
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun booleanGlobal_compareAndExchangeField() = ::booleanGlobal.compareAndExchangeField(false, true)
// IntArray
val intArr = IntArray(2)
// CHECK-LABEL: define i32 @"kfun:#intArr_atomicGet(){}kotlin.Int"()
// CHECK: call i32* @Kotlin_intArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: load atomic i32, i32* %{{[0-9]+}} seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intArr_atomicGet() = intArr.atomicGet(0)
// CHECK-LABEL: define void @"kfun:#intArr_atomicSet(){}"()
// CHECK: call i32* @Kotlin_intArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: store atomic i32 1, i32* %{{[0-9]+}} seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intArr_atomicSet() = intArr.atomicSet(0, 1)
// CHECK-LABEL: define i32 @"kfun:#intArr_getAndSet(){}kotlin.Int"()
// CHECK: call i32* @Kotlin_intArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: atomicrmw xchg i32* %{{[0-9]+}}, i32 1 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intArr_getAndSet() = intArr.getAndSet(0, 1)
// CHECK-LABEL: define i32 @"kfun:#intArr_getAndAdd(){}kotlin.Int"()
// CHECK: call i32* @Kotlin_intArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: atomicrmw add i32* %{{[0-9]+}}, i32 1 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intArr_getAndAdd() = intArr.getAndAdd(0, 1)
// CHECK-LABEL: define i32 @"kfun:#intArr_compareAndExchange(){}kotlin.Int"()
// CHECK: call i32* @Kotlin_intArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: cmpxchg i32* %{{[0-9]+}}, i32 1, i32 2 seq_cst seq_cst
// CHECK: extractvalue { i32, i1 } %{{[0-9]+}}, 0
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intArr_compareAndExchange() = intArr.compareAndExchange(0, 1, 2)
// CHECK-AAPCS-LABEL: define i1 @"kfun:#intArr_compareAndSet(){}kotlin.Boolean"()
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#intArr_compareAndSet(){}kotlin.Boolean"()
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#intArr_compareAndSet(){}kotlin.Boolean"()
// CHECK: call i32* @Kotlin_intArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: cmpxchg i32* %{{[0-9]+}}, i32 1, i32 2 seq_cst seq_cst
// CHECK: extractvalue { i32, i1 } %{{[0-9]+}}, 1
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun intArr_compareAndSet() = intArr.compareAndSet(0, 1, 2)
// LongArray
val longArr = LongArray(2)
// CHECK-LABEL: define i64 @"kfun:#longArr_atomicGet(){}kotlin.Long"()
// CHECK: call i64* @Kotlin_longArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: load atomic i64, i64* %{{[0-9]+}} seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longArr_atomicGet() = longArr.atomicGet(0)
// CHECK-LABEL: define void @"kfun:#longArr_atomicSet(){}"()
// CHECK: call i64* @Kotlin_longArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: store atomic i64 1, i64* %{{[0-9]+}} seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longArr_atomicSet() = longArr.atomicSet(0, 1L)
// CHECK-LABEL: define i64 @"kfun:#longArr_getAndSet(){}kotlin.Long"()
// CHECK: call i64* @Kotlin_longArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: atomicrmw xchg i64* %{{[0-9]+}}, i64 1 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longArr_getAndSet() = longArr.getAndSet(0, 1L)
// CHECK-LABEL: define i64 @"kfun:#longArr_getAndAdd(){}kotlin.Long"()
// CHECK: call i64* @Kotlin_longArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: atomicrmw add i64* %{{[0-9]+}}, i64 1 seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longArr_getAndAdd() = longArr.getAndAdd(0, 1L)
// CHECK-LABEL: define i64 @"kfun:#longArr_compareAndExchange(){}kotlin.Long"()
// CHECK: call i64* @Kotlin_longArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: cmpxchg i64* %{{[0-9]+}}, i64 1, i64 2 seq_cst seq_cst
// CHECK: extractvalue { i64, i1 } %{{[0-9]+}}, 0
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longArr_compareAndExchange() = longArr.compareAndExchange(0, 1L, 2L)
// CHECK-AAPCS-LABEL: define i1 @"kfun:#longArr_compareAndSet(){}kotlin.Boolean"()
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#longArr_compareAndSet(){}kotlin.Boolean"()
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#longArr_compareAndSet(){}kotlin.Boolean"()
// CHECK: call i64* @Kotlin_longArrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: cmpxchg i64* %{{[0-9]+}}, i64 1, i64 2 seq_cst seq_cst
// CHECK: extractvalue { i64, i1 } %{{[0-9]+}}, 1
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun longArr_compareAndSet() = longArr.compareAndSet(0, 1L, 2L)
// Array<T>
val refArr = arrayOfNulls<String?>(2)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#refArr_atomicGet(){}kotlin.String?"
// CHECK: call %struct.ObjHeader** @Kotlin_arrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: load atomic %struct.ObjHeader*, %struct.ObjHeader** %{{[0-9]+}} seq_cst
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun refArr_atomicGet() = refArr.atomicGet(0)
// CHECK-LABEL: define void @"kfun:#refArr_atomicSet(){}"()
// CHECK: call %struct.ObjHeader** @Kotlin_arrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: call void @UpdateVolatileHeapRef(%struct.ObjHeader** %{{[0-9]+}}, %struct.ObjHeader* null)
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun refArr_atomicSet() = refArr.atomicSet(0, null)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#refArr_getAndSet(){}kotlin.String?"
// CHECK: call %struct.ObjHeader** @Kotlin_arrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: call %struct.ObjHeader* @GetAndSetVolatileHeapRef(%struct.ObjHeader** %{{[0-9]+}}, %struct.ObjHeader* null, %struct.ObjHeader** %{{[0-9]+}})
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun refArr_getAndSet() = refArr.getAndSet(0, null)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#refArr_compareAndExchange(){}kotlin.String?"
// CHECK: call %struct.ObjHeader** @Kotlin_arrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK: call %struct.ObjHeader* @CompareAndSwapVolatileHeapRef(%struct.ObjHeader** %{{[0-9]+}}, %struct.ObjHeader* null, %struct.ObjHeader* null, %struct.ObjHeader** %{{[0-9]+}})
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun refArr_compareAndExchange() = refArr.compareAndExchange(0, null, null)
// CHECK-AAPCS-LABEL: define i1 @"kfun:#refArr_compareAndSet(){}kotlin.Boolean"()
// CHECK-DEFAULTABI-LABEL: define zeroext i1 @"kfun:#refArr_compareAndSet(){}kotlin.Boolean"()
// CHECK-WINDOWSX64-LABEL: define zeroext i1 @"kfun:#refArr_compareAndSet(){}kotlin.Boolean"()
// CHECK: call %struct.ObjHeader** @Kotlin_arrayGetElementAddress(%struct.ObjHeader* %{{[0-9]+}}, i32 0)
// CHECK-AAPCS: call i1 @CompareAndSetVolatileHeapRef(%struct.ObjHeader** %{{[0-9]+}}, %struct.ObjHeader* null, %struct.ObjHeader* null)
// CHECK-DEFAULTABI: call zeroext i1 @CompareAndSetVolatileHeapRef(%struct.ObjHeader** %{{[0-9]+}}, %struct.ObjHeader* null, %struct.ObjHeader* null)
// CHECK-WINDOWSX64: call zeroext i1 @CompareAndSetVolatileHeapRef(%struct.ObjHeader** %{{[0-9]+}}, %struct.ObjHeader* null, %struct.ObjHeader* null)
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun refArr_compareAndSet() = refArr.compareAndSet(0, null, null)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
byteGlobal_getField()
byteGlobal_setField()
byteGlobal_getAndSetField()
byteGlobal_getAndAddField()
byteGlobal_compareAndSetField()
byteGlobal_compareAndExchangeField()
shortGlobal_getField()
shortGlobal_setField()
shortGlobal_getAndSetField()
shortGlobal_getAndAddField()
shortGlobal_compareAndSetField()
shortGlobal_compareAndExchangeField()
intGlobal_getField()
intGlobal_setField()
intGlobal_getAndSetField()
intGlobal_getAndAddField()
intGlobal_compareAndSetField()
intGlobal_compareAndExchangeField()
longGlobal_getField()
longGlobal_setField()
longGlobal_getAndSetField()
longGlobal_getAndAddField()
longGlobal_compareAndSetField()
longGlobal_compareAndExchangeField()
booleanGlobal_getField()
booleanGlobal_setField()
booleanGlobal_getAndSetField()
booleanGlobal_compareAndSetField()
booleanGlobal_compareAndExchangeField()
intArr_atomicGet()
intArr_atomicSet()
intArr_getAndSet()
intArr_getAndAdd()
intArr_compareAndSet()
intArr_compareAndExchange()
longArr_atomicGet()
longArr_atomicSet()
longArr_getAndSet()
longArr_getAndAdd()
longArr_compareAndSet()
longArr_compareAndExchange()
refArr_atomicGet()
refArr_atomicSet()
refArr_getAndSet()
refArr_compareAndSet()
refArr_compareAndExchange()
return "OK"
}
+338
View File
@@ -0,0 +1,338 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// CHECK-LABEL: define void @"kfun:#forEachIndicies(){}"()
fun forEachIndicies() {
val array = Array(10) { 0 }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in array.indices) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forUntilSize(){}"()
fun forUntilSize() {
val array = Array(10) { 0L }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0 until array.size) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forRangeUntilSize(){}"()
@ExperimentalStdlibApi
fun forRangeUntilSize() {
val array = Array(10) { 0L }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0..<array.size) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forDownToSize(){}"()
fun forDownToSize() {
val array = Array(10) { 0L }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in array.size - 1 downTo 0) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
// CHECK: {{^}}do_while_loop{{.*}}:
for (j in array.size - 3 downTo 0) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[j] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forRangeToSize(){}"()
fun forRangeToSize() {
val array = Array(10) { 0L }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0..array.size - 1) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
val length = array.size - 1
// CHECK: {{^}}do_while_loop{{.*}}:
for (j in 0..length) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[j] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forRangeToWithStep(){}"()
fun forRangeToWithStep() {
val array = Array(10) { 0L }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0..array.size - 1 step 2) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forUntilWithStep(){}"()
fun forUntilWithStep() {
val array = CharArray(10) { '0' }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0 until array.size step 2) {
// CHECK: {{call|invoke}} void @Kotlin_CharArray_set_without_BoundCheck
array[i] = '6'
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forRangeUntilWithStep(){}"()
@ExperimentalStdlibApi
fun forRangeUntilWithStep() {
val array = CharArray(10) { '0' }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0..<array.size step 2) {
// CHECK: {{call|invoke}} void @Kotlin_CharArray_set_without_BoundCheck
array[i] = '6'
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forDownToWithStep(){}"()
fun forDownToWithStep() {
val array = UIntArray(10) { 0U }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in array.size - 1 downTo 0 step 2) {
// CHECK: {{call|invoke}} void @Kotlin_IntArray_set_without_BoundCheck
array[i] = 6U
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forIndiciesWithStep(){}"()
fun forIndiciesWithStep() {
val array = Array(10) { 0L }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in array.indices step 2) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forWithIndex(){}"()
fun forWithIndex() {
val array = Array(10) { 100 }
// CHECK: {{^}}while_loop{{.*}}:
for ((index, value) in array.withIndex()) {
// CHECK: {{call|invoke}} %struct.ObjHeader* @Kotlin_Array_get_without_BoundCheck
array[index] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forReversed(){}"()
fun forReversed() {
val array = Array(10) { 100 }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in (0..array.size-1).reversed()) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forRangeUntilReversed(){}"()
@ExperimentalStdlibApi
fun forRangeUntilReversed() {
val array = Array(10) { 100 }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in (0..<array.size).reversed()) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
fun foo(a: Int, b : Int): Int = a + b * 2
// CHECK-LABEL: define void @"kfun:#forEachCall(){}"()
fun forEachCall() {
val array = Array(10) { 100 }
var sum = 0
// CHECK: {{^}}while_loop{{.*}}:
array.forEach {
// CHECK: {{call|invoke}} %struct.ObjHeader* @Kotlin_Array_get_without_BoundCheck
sum += it
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#forLoop(){}"()
fun forLoop() {
val array = Array(10) { 100 }
var sum = 0
// CHECK: {{^}}while_loop{{.*}}:
for (it in array) {
// CHECK: {{call|invoke}} %struct.ObjHeader* @Kotlin_Array_get_without_BoundCheck
sum += it
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#innerLoop(){}"()
fun innerLoop() {
val array = Array(10) { 100 }
val array1 = Array(3) { 0 }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0 until array.size) {
// CHECK-DAG: {{call|invoke}} %struct.ObjHeader* @Kotlin_Array_get_without_BoundCheck
array[i] = 7
// CHECK-DAG: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
// CHECK-DAG: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
for (j in 0 until array1.size) {
array1[j] = array[i]
}
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#argsInFunctionCall(){}"()
fun argsInFunctionCall() {
val array = Array(10) { 100 }
val size = array.size - 1
val size1 = size
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0..size1) {
// CHECK: {{call|invoke}} %struct.ObjHeader* @Kotlin_Array_get_without_BoundCheck
// CHECK: {{call|invoke}} %struct.ObjHeader* @Kotlin_Array_get_without_BoundCheck
// CHECK: {{call|invoke}} i32 @"kfun:#foo(kotlin.Int;kotlin.Int){}kotlin.Int"
foo(array[i], array[i])
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define void @"kfun:#smallLoop(){}"()
fun smallLoop() {
val array = Array(10) { 100 }
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0..array.size - 2) {
// CHECK: {{call|invoke}} %struct.ObjHeader* @Kotlin_Array_get_without_BoundCheck
array[i+1] = array[i]
}
}
// CHECK-LABEL: {{^}}epilogue:
object TopLevelObject {
val array = Array(10) { 100 }
}
// CHECK-LABEL: define void @"kfun:#topLevelObject(){}"()
fun topLevelObject() {
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0 until TopLevelObject.array.size) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
TopLevelObject.array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
val array = Array(10) { 100 }
// CHECK-LABEL: define void @"kfun:#topLevelProperty(){}"()
fun topLevelProperty() {
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0..array.size - 2) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
open class Base() {
open val array = Array(10) { 100 }
}
class Child() : Base()
// CHECK-LABEL: define void @"kfun:#childClassWithFakeOverride(){}"()
fun childClassWithFakeOverride() {
val child = Child()
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0..child.array.size - 1) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
child.array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
class First {
val child = Child()
}
class Second{
val first = First()
}
class Third {
val second = Second()
}
// CHECK-LABEL: define void @"kfun:#chainedReceivers(){}"()
fun chainedReceivers() {
val obj = Third()
val obj1 = obj
val obj2 = obj1
// CHECK: {{^}}do_while_loop{{.*}}:
for (i in 0 until obj1.second.first.child.array.size) {
// CHECK: {{call|invoke}} void @Kotlin_Array_set_without_BoundCheck
obj2.second.first.child.array[i] = 6
}
}
// CHECK-LABEL: {{^}}epilogue:
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
@ExperimentalStdlibApi
fun box(): String {
forEachIndicies()
forUntilSize()
forRangeUntilSize()
forDownToSize()
forRangeToSize()
forRangeToWithStep()
forUntilWithStep()
forRangeUntilWithStep()
forDownToWithStep()
forIndiciesWithStep()
forWithIndex()
forReversed()
forRangeUntilReversed()
forEachCall()
forLoop()
innerLoop()
argsInFunctionCall()
smallLoop()
topLevelObject()
topLevelProperty()
childClassWithFakeOverride()
chainedReceivers()
return "OK"
}
@@ -0,0 +1,73 @@
// TARGET_BACKEND: NATIVE
// DISABLE_NATIVE: isAppleTarget=false
// FILECHECK_STAGE: CStubs
// MODULE: cinterop
// FILE: direct.def
language = Objective-C
headers = direct.h
headerFilter = direct.h
// FILE: direct.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface CallingConventions : NSObject
+ (uint64_t)regular:(uint64_t)arg;
- (uint64_t)regular:(uint64_t)arg;
+ (uint64_t)direct:(uint64_t)arg __attribute__((objc_direct));
- (uint64_t)direct:(uint64_t)arg __attribute__((objc_direct));
@end
NS_ASSUME_NONNULL_END
// FILE: direct.m
#import "direct.h"
#define TEST_METHOD_IMPL(NAME) (uint64_t)NAME:(uint64_t)arg { return arg; }
@implementation CallingConventions : NSObject
+ TEST_METHOD_IMPL(regular);
- TEST_METHOD_IMPL(regular);
+ TEST_METHOD_IMPL(direct);
- TEST_METHOD_IMPL(direct);
@end
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
import kotlin.native.Retain
import direct.*
// KT-54610
fun box(): String {
callDirect()
callRegular()
return "OK"
}
@Retain
//CHECK-LABEL: define i64 @"kfun:#callDirect(){}kotlin.ULong"()
fun callDirect(): ULong {
val cc = CallingConventions()
//CHECK: invoke i64 @_{{[a-zA-Z0-9]+}}_knbridge{{[0-9]+}}(i8* %{{[0-9]+}}, i64 42)
return cc.direct(42uL)
}
@Retain
//CHECK-LABEL: define i64 @"kfun:#callRegular(){}kotlin.ULong"()
fun callRegular(): ULong {
val cc = CallingConventions()
//CHECK: invoke i64 @_{{[a-zA-Z0-9]+}}_knbridge{{[0-9]+}}(i8* %{{[0-9]+}}, i8* %{{[0-9]+}}, i64 42)
return cc.regular(42uL)
}
@@ -0,0 +1,168 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use
* of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// MODULE: cinterop
// FILE: signext_zeroext_interop_input.def
---
char char_id(char c) {
return c;
}
unsigned char unsigned_char_id(unsigned char c) {
return c;
}
short short_id(short s) {
return s;
}
unsigned short unsigned_short_id(unsigned short s) {
return s;
}
int callbackUser(int (*fn)(int, short)) {
return fn(5,5);
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import signext_zeroext_interop_input.*
import kotlinx.cinterop.*
// CHECK-DEFAULTABI-CACHE_NO: declare zeroext i1 @Kotlin_Char_isHighSurrogate(i16 zeroext){{.*}}
// CHECK-AAPCS-CACHE_NO: declare i1 @Kotlin_Char_isHighSurrogate(i16)
// CHECK-WINDOWSX64-CACHE_NO: declare zeroext i1 @Kotlin_Char_isHighSurrogate(i16)
// Check that we pass attributes to functions imported from runtime.
// CHECK-LABEL: void @"kfun:#checkRuntimeFunctionImport(){}"()
fun checkRuntimeFunctionImport() {
// CHECK-DEFAULTABI: call zeroext i1 @Kotlin_Char_isHighSurrogate(i16 zeroext {{.*}})
// CHECK-AAPCS: call i1 @Kotlin_Char_isHighSurrogate(i16 {{.*}})
// CHECK-WINDOWSX64: call zeroext i1 @Kotlin_Char_isHighSurrogate(i16 {{.*}})
'c'.isHighSurrogate()
// CHECK-DEFAULTABI: call zeroext i1 @Kotlin_Float_isNaN(float {{.*}}
// CHECK-AAPCS: call i1 @Kotlin_Float_isNaN(float {{.*}}
// CHECK-WINDOWSX64: call zeroext i1 @Kotlin_Float_isNaN(float {{.*}}
0.0f.isNaN()
}
// CHECK-LABEL: void @"kfun:#checkDirectInterop(){}"()
// CHECK-LABEL-AAPCS: void @"kfun:#checkDirectInterop(){}"()
// CHECK-LABEL-WINDOWSX64: void @"kfun:#checkDirectInterop(){}"()
fun checkDirectInterop() {
// compiler generates quite lovely names for bridges
// (e.g. `_66696c65636865636b5f7369676e6578745f7a65726f6578745f696e7465726f70_knbridge0`),
// so we don't check exact function names here.
// CHECK-DEFAULTABI: invoke signext i8 [[CHAR_ID_BRIDGE:@_.*_knbridge[0-9]+]](i8 signext {{.*}})
// CHECK-AAPCS: invoke i8 [[CHAR_ID_BRIDGE:@_.*_knbridge[0-9]+]](i8 {{.*}})
// CHECK-WINDOWSX64: invoke i8 [[CHAR_ID_BRIDGE:@_.*_knbridge[0-9]+]](i8 {{.*}})
char_id(0.toByte())
// CHECK-DEFAULTABI: invoke zeroext i8 [[UNSIGNED_CHAR_ID_BRIDGE:@_.*_knbridge[0-9]+]](i8 zeroext {{.*}})
// CHECK-AAPCS: invoke i8 [[UNSIGNED_CHAR_ID_BRIDGE:@_.*_knbridge[0-9]+]](i8 {{.*}})
// CHECK-WINDOWSX64: invoke i8 [[UNSIGNED_CHAR_ID_BRIDGE:@_.*_knbridge[0-9]+]](i8 {{.*}})
unsigned_char_id(0.toUByte())
// CHECK-DEFAULTABI: invoke signext i16 [[SHORT_ID_BRIDGE:@_.*_knbridge[0-9]+]](i16 signext {{.*}})
// CHECK-AAPCS: invoke i16 [[SHORT_ID_BRIDGE:@_.*_knbridge[0-9]+]](i16 {{.*}})
// CHECK-WINDOWSX64: invoke i16 [[SHORT_ID_BRIDGE:@_.*_knbridge[0-9]+]](i16 {{.*}})
short_id(0.toShort())
// CHECK-DEFAULTABI: invoke zeroext i16 [[UNSIGNED_SHORT_ID_BRIDGE:@_.*_knbridge[0-9]+]](i16 zeroext {{.*}})
// CHECK-AAPCS: invoke i16 [[UNSIGNED_SHORT_ID_BRIDGE:@_.*_knbridge[0-9]+]](i16 {{.*}})
// CHECK-WINDOWSX64: invoke i16 [[UNSIGNED_SHORT_ID_BRIDGE:@_.*_knbridge[0-9]+]](i16 {{.*}})
unsigned_short_id(0.toUShort())
// CHECK-DEFAULTABI: invoke i32 [[CALLBACK_USER_BRIDGE:@_.*_knbridge[0-9]+]](i8* bitcast (i32 (i32, i16)* [[STATIC_C_FUNCTION_BRIDGE:@_.*_kncfun[0-9]+]] to i8*))
// CHECK-AAPCS: invoke i32 [[CALLBACK_USER_BRIDGE:@_.*_knbridge[0-9]+]](i8* bitcast (i32 (i32, i16)* [[STATIC_C_FUNCTION_BRIDGE:@_.*_kncfun[0-9]+]] to i8*))
// CHECK-WINDOWSX64: invoke i32 [[CALLBACK_USER_BRIDGE:@_.*_knbridge[0-9]+]](i8* bitcast (i32 (i32, i16)* [[STATIC_C_FUNCTION_BRIDGE:@_.*_kncfun[0-9]+]] to i8*))
callbackUser(staticCFunction { int: Int, short: Short -> int + short })
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
checkRuntimeFunctionImport()
checkDirectInterop()
return "OK"
}
// CHECK-DEFAULTABI-CACHE_STATIC_ONLY_DIST: declare zeroext i1 @Kotlin_Char_isHighSurrogate(i16 zeroext){{.*}}
// CHECK-AAPCS-CACHE_STATIC_ONLY_DIST: declare i1 @Kotlin_Char_isHighSurrogate(i16)
// CHECK-WINDOWSX64-CACHE_STATIC_ONLY_DIST: declare zeroext i1 @Kotlin_Char_isHighSurrogate(i16)
// CHECK-DEFAULTABI: signext i8 [[CHAR_ID_BRIDGE]](i8 signext %0)
// CHECK-DEFAULTABI: [[CHAR_ID_PTR:%[0-9]+]] = load i8 (i8)*, i8 (i8)** @{{.*char_id}}
// CHECK-DEFAULTABI: call signext i8 [[CHAR_ID_PTR]](i8 signext %0)
// CHECK-AAPCS: i8 [[CHAR_ID_BRIDGE]](i8 %0)
// CHECK-AAPCS: [[CHAR_ID_PTR:%[0-9]+]] = load i8 (i8)*, i8 (i8)** @{{.*char_id}}
// CHECK-AAPCS: call i8 [[CHAR_ID_PTR]](i8 %0)
// CHECK-WINDOWSX64: i8 [[CHAR_ID_BRIDGE]](i8 %0)
// CHECK-WINDOWSX64: [[CHAR_ID_PTR:%[0-9]+]] = load i8 (i8)*, i8 (i8)** @{{.*char_id}}
// CHECK-WINDOWSX64: call i8 [[CHAR_ID_PTR]](i8 %0)
// CHECK-DEFAULTABI: zeroext i8 [[UNSIGNED_CHAR_ID_BRIDGE]](i8 zeroext %0)
// CHECK-DEFAULTABI: [[UNSIGNED_CHAR_ID_PTR:%[0-9]+]] = load i8 (i8)*, i8 (i8)** @{{.*unsigned_char_id}}
// CHECK-DEFAULTABI: call zeroext i8 [[UNSIGNED_CHAR_ID_PTR]](i8 zeroext %0)
// CHECK-AAPCS: i8 [[UNSIGNED_CHAR_ID_BRIDGE]](i8 %0)
// CHECK-AAPCS: [[UNSIGNED_CHAR_ID_PTR:%[0-9]+]] = load i8 (i8)*, i8 (i8)** @{{.*unsigned_char_id}}
// CHECK-AAPCS: call i8 [[UNSIGNED_CHAR_ID_PTR]](i8 %0)
// CHECK-WINDOWSX64: i8 [[UNSIGNED_CHAR_ID_BRIDGE]](i8 %0)
// CHECK-WINDOWSX64: [[UNSIGNED_CHAR_ID_PTR:%[0-9]+]] = load i8 (i8)*, i8 (i8)** @{{.*unsigned_char_id}}
// CHECK-WINDOWSX64: call i8 [[UNSIGNED_CHAR_ID_PTR]](i8 %0)
// CHECK-DEFAULTABI: signext i16 [[SHORT_ID_BRIDGE]](i16 signext %0)
// CHECK-DEFAULTABI: [[SHORT_ID_PTR:%[0-9]+]] = load i16 (i16)*, i16 (i16)** @{{.*short_id}}
// CHECK-DEFAULTABI: call signext i16 [[SHORT_ID_PTR]](i16 signext %0)
// CHECK-AAPCS: i16 [[SHORT_ID_BRIDGE]](i16 %0)
// CHECK-AAPCS: [[SHORT_ID_PTR:%[0-9]+]] = load i16 (i16)*, i16 (i16)** @{{.*short_id}}
// CHECK-AAPCS: call i16 [[SHORT_ID_PTR]](i16 %0)
// CHECK-WINDOWSX64: i16 [[SHORT_ID_BRIDGE]](i16 %0)
// CHECK-WINDOWSX64: [[SHORT_ID_PTR:%[0-9]+]] = load i16 (i16)*, i16 (i16)** @{{.*short_id}}
// CHECK-WINDOWSX64: call i16 [[SHORT_ID_PTR]](i16 %0)
// CHECK-DEFAULTABI: zeroext i16 [[UNSIGNED_SHORT_ID_BRIDGE]](i16 zeroext %0)
// CHECK-DEFAULTABI: [[UNSIGNED_SHORT_ID_PTR:%[0-9]+]] = load i16 (i16)*, i16 (i16)** @{{.*unsigned_short_id}}
// CHECK-DEFAULTABI: call zeroext i16 [[UNSIGNED_SHORT_ID_PTR]](i16 zeroext %0)
// CHECK-AAPCS: i16 [[UNSIGNED_SHORT_ID_BRIDGE]](i16 %0)
// CHECK-AAPCS: [[UNSIGNED_SHORT_ID_PTR:%[0-9]+]] = load i16 (i16)*, i16 (i16)** @{{.*unsigned_short_id}}
// CHECK-AAPCS: call i16 [[UNSIGNED_SHORT_ID_PTR]](i16 %0)
// CHECK-WINDOWSX64: i16 [[UNSIGNED_SHORT_ID_BRIDGE]](i16 %0)
// CHECK-WINDOWSX64: [[UNSIGNED_SHORT_ID_PTR:%[0-9]+]] = load i16 (i16)*, i16 (i16)** @{{.*unsigned_short_id}}
// CHECK-WINDOWSX64: call i16 [[UNSIGNED_SHORT_ID_PTR]](i16 %0)
// CHECK-DEFAULTABI: i32 [[STATIC_C_FUNCTION_BRIDGE]](i32 %0, i16 signext %1)
// CHECK-DEFAULTABI: call i32 {{@_.*_knbridge[0-9]+}}(i32 %0, i16 signext %1)
// CHECK-AAPCS: i32 [[STATIC_C_FUNCTION_BRIDGE]](i32 %0, i16 %1)
// CHECK-AAPCS: call i32 {{@_.*_knbridge[0-9]+}}(i32 %0, i16 %1)
// CHECK-WINDOWSX64: i32 [[STATIC_C_FUNCTION_BRIDGE]](i32 %0, i16 %1)
// CHECK-WINDOWSX64: call i32 {{@_.*_knbridge[0-9]+}}(i32 %0, i16 %1)
// CHECK-DEFAULTABI: i32 [[CALLBACK_USER_BRIDGE]](i8* %0)
// CHECK-DEFAULTABI: [[CALLBACK_USER_PTR:%[0-9]+]] = load i32 (i8*)*, i32 (i8*)** @{{.*callbackUser}}
// CHECK-DEFAULTABI: call i32 [[CALLBACK_USER_PTR]](i8* %0)
// CHECK-AAPCS: i32 [[CALLBACK_USER_BRIDGE]](i8* %0)
// CHECK-AAPCS: [[CALLBACK_USER_PTR:%[0-9]+]] = load i32 (i8*)*, i32 (i8*)** @{{.*callbackUser}}
// CHECK-AAPCS: call i32 [[CALLBACK_USER_PTR]](i8* %0)
// CHECK-WINDOWSX64: i32 [[CALLBACK_USER_BRIDGE]](i8* %0)
// CHECK-WINDOWSX64: [[CALLBACK_USER_PTR:%[0-9]+]] = load i32 (i8*)*, i32 (i8*)** @{{.*callbackUser}}
// CHECK-WINDOWSX64: call i32 [[CALLBACK_USER_PTR]](i8* %0)
@@ -0,0 +1,26 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlin.reflect.*
// CHECK: [[REG_FOR_1024:@[0-9]+]] = internal unnamed_addr constant { %struct.ObjHeader, i32 } { %struct.ObjHeader { %struct.TypeInfo* {{.*}} }, i32 1024 }
// CHECK-NOT: internal unnamed_addr constant { %struct.ObjHeader, i32 } { %struct.ObjHeader { %struct.TypeInfo* {{.*}} }, i32 1024 }
// CHECK: internal unnamed_addr constant { %struct.ArrayHeader, [3 x %struct.ObjHeader*] } { %struct.ArrayHeader { %struct.TypeInfo* {{.*}}, i32 3 }, [3 x %struct.ObjHeader*] [%struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, i32 }, { %struct.ObjHeader, i32 }* [[REG_FOR_1024]], i32 0, i32 0), %struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, i32 }, { %struct.ObjHeader, i32 }* [[REG_FOR_2048:@[0-9]+]], i32 0, i32 0), %struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, i32 }, { %struct.ObjHeader, i32 }* [[REG_FOR_4096:@[0-9]+]], i32 0, i32 0)] }
// CHECK-NOT: internal unnamed_addr constant { %struct.ArrayHeader, [3 x %struct.ObjHeader*] } { %struct.ArrayHeader { %struct.TypeInfo* {{.*}}, i32 3 }, [3 x %struct.ObjHeader*] [%struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, i32 }, { %struct.ObjHeader, i32 }* [[REG_FOR_1024]], i32 0, i32 0), %struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, i32 }, { %struct.ObjHeader, i32 }* [[REG_FOR_2048]], i32 0, i32 0), %struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, i32 }, { %struct.ObjHeader, i32 }* [[REG_FOR_4096]], i32 0, i32 0)] }
// CHECK: internal unnamed_addr constant { %struct.ObjHeader, %struct.ObjHeader*, %struct.ObjHeader*, i1 } { %struct.ObjHeader { %struct.TypeInfo* {{.*}} }, %struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, i8* }, { %struct.ObjHeader, i8* }* [[REG_FOR_CLASSIFIER_FIELD:@[0-9]+]], i32 0, i32 0), %struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, %struct.ObjHeader*, %struct.ObjHeader* }, { %struct.ObjHeader, %struct.ObjHeader*, %struct.ObjHeader* }* [[REG_FOR_ARGUMENTS_FIELD:@[0-9]+]], i32 0, i32 0), i1 false }
// CHECK-NOT: internal unnamed_addr constant { %struct.ObjHeader, %struct.ObjHeader*, %struct.ObjHeader*, i1 } { %struct.ObjHeader { %struct.TypeInfo* {{.*}} }, %struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, i8* }, { %struct.ObjHeader, i8* }* [[REG_FOR_CLASSIFIER_FIELD]], i32 0, i32 0), %struct.ObjHeader* getelementptr inbounds ({ %struct.ObjHeader, %struct.ObjHeader*, %struct.ObjHeader* }, { %struct.ObjHeader, %struct.ObjHeader*, %struct.ObjHeader* }* [[REG_FOR_ARGUMENTS_FIELD]], i32 0, i32 0), i1 false }
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
println(1024)
println(1024)
println(arrayOf(1024, 2048, 4096))
println(arrayOf(1024, 2048, 4096))
println(typeOf<Map<String, String>>())
println(typeOf<Map<String, String>>())
return "OK"
}
@@ -0,0 +1,35 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
value class A(val i: Int)
value class B(val a: A)
value class C(val s: String)
fun defaultInt(a: Int = 1, aa: Int = 1) = a
fun defaultA(a: A = A(1), aa: A = A(1)) = a.i
fun defaultB(b: B = B(A(1)), bb: B = B(A(1))) = b.a.i
fun defaultC(c: C = C("1"), cc: C = C("1")) = c.s
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
// CHECK-LABEL: entry
// CHECK-NOT: <Int-box>
// CHECK-NOT: <A-box>
// CHECK-NOT: <B-box>
// CHECK-NOT: <C-box>
defaultInt()
defaultA()
defaultB()
defaultC()
defaultInt(1)
defaultA(A(1))
defaultB(B(A(1)))
defaultC(C("1"))
defaultInt(1, 1)
defaultA(A(1), A(1))
defaultB(B(A(1)), B(A(1)))
defaultC(C("1"), C("1"))
// CHECK-LABEL: epilogue:
return "OK"
}
@@ -0,0 +1,28 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
enum class COLOR {
RED,
GREEN,
BLUE
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
for (i in COLOR.values()) {
// CHECK-DEBUG: = call i32 @"kfun:kotlin.Enum#<get-ordinal>(){}kotlin.Int"(
// We inline .ordinal property access in case of opt build, so check direct field load instead.
// CHECK-OPT: getelementptr inbounds %"kclassbody:kotlin.Enum#internal", %"kclassbody:kotlin.Enum#internal"* %{{[0-9a-z]*}}, i32 0, i32 2
print(when (i) {
// we can't check the register is same, because it can be saved on stack and loaded back
// CHECK: icmp eq i32 %{{[0-9a-z]*}}, 0
COLOR.RED -> 0xff0000
// CHECK: icmp eq i32 %{{[0-9a-z]*}}, 1
COLOR.GREEN -> 0x00ff00
// CHECK: icmp eq i32 %{{[0-9a-z]*}}, 2
COLOR.BLUE -> 0x0000ff
})
}
// CHECK-LABEL: epilogue:
return "OK"
}
@@ -0,0 +1,14 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
class A(val x: Int)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
// CHECK-DEBUG: call %struct.ObjHeader* @AllocInstance
// CHECK-OPT: alloca %"kclassbody:A#internal"
val a = A(5)
println(a.x)
// CHECK-LABEL: epilogue:
return "OK"
}
@@ -0,0 +1,8 @@
// TARGET_BACKEND: NATIVE
// IGNORE_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// The check below is intentionally wrong and must fail.
// Test system should report test as passed due to IGNORE_BACKEND directive above.
// CHECK-LABEL: NONEXISTENT
fun box(): String = "OK"
@@ -0,0 +1,19 @@
// TARGET_BACKEND: NATIVE
// Perform check after optimization pipeline because
// LLVM might infer attributes.
// FILECHECK_STAGE: LTOBitcodeOptimization
// NB: This is not a good test.
// What we actually want to check is that Kotlin/Native compiler is able to produce "big"
// binaries for 32-bit Apple Watch target. The problem is that such test is very-very-very
// slow to compile (~20 min on a local machine) which is not acceptable for CI.
//
// Instead, here we check that none of the module's functions are compiled in the Thumb mode.
// BL instructions in thumb mode have smaller ranges which causes "relocation out of range" failure.
// CHECK-WATCHOS_ARM32: target triple = "armv7k-apple-watchos2{{.+}}"
fun box() = "OK"
// CHECK-NOT: attributes #{{[0-9]+}} = { {{.+}}+thumb-mode{{.+}} }
@@ -0,0 +1,27 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// CHECK: declare void @ThrowException(%struct.ObjHeader*) #[[THROW_EXCEPTION_DECLARATION_ATTRIBUTES:[0-9]+]]
// CHECK: void @"kfun:#flameThrower(){}kotlin.Nothing"() #[[FLAME_THROWER_DECLARATION_ATTRIBUTES:[0-9]+]]
fun flameThrower(): Nothing {
// CHECK: call void @ThrowException(%struct.ObjHeader* {{.*}}) #[[THROW_EXCEPTION_CALLSITE_ATTRIBUTES:[0-9]+]]
throw Throwable("🔥")
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
// CHECK: invoke void @"kfun:#flameThrower(){}kotlin.Nothing"() #[[FLAME_THROWER_CALLSITE_ATTRIBUTES:[0-9]+]]
try {
flameThrower()
} catch (e: Throwable) {
return "OK"
}
return "FAIL: Uncaught exception"
}
// CHECK-DAG: attributes #[[THROW_EXCEPTION_DECLARATION_ATTRIBUTES]] = {{{.*}}noreturn{{.*}}}
// CHECK-DAG: attributes #[[THROW_EXCEPTION_CALLSITE_ATTRIBUTES]] = {{{.*}}noreturn{{.*}}}
// CHECK-DAG: attributes #[[FLAME_THROWER_DECLARATION_ATTRIBUTES]] = {{{.*}}noreturn{{.*}}}
// CHECK-DAG: attributes #[[FLAME_THROWER_CALLSITE_ATTRIBUTES]] = {{{.*}}noreturn{{.*}}}
@@ -0,0 +1,132 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlin.reflect.KFunction2
fun <StringifyTP> stringify(collection: StringifyTP, size: (StringifyTP) -> Int, get: StringifyTP.(Int) -> Any?): String {
var res = "["
for (i in 0 until size(collection)) {
if (i > 0) res += ", "
res += collection.get(i).toString()
}
res += "]"
return res
}
interface I
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#stringifyArray(kotlin.Array<0:0>){0\C2\A7<I>}kotlin.String"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader** {{%[0-9]+}})
fun <StringifyArrayTP : I> stringifyArray(array: Array<StringifyArrayTP>) =
// CHECK: call %struct.ObjHeader* @"kfun:#stringify(0:0;kotlin.Function1<0:0,kotlin.Int>;kotlin.Function2<0:0,kotlin.Int,kotlin.Any?>){0\C2\A7<kotlin.Any?>}kotlin.String"
stringify(
array,
{ it.size }, // $stringifyArray$lambda$0$FUNCTION_REFERENCE$0
Array<*>::get // $get$FUNCTION_REFERENCE$1
)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#stringifyIntArray(kotlin.Array<kotlin.Int>){}kotlin.String"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader** {{%[0-9]+}})
fun stringifyIntArray(array: Array<Int>) =
// CHECK: call %struct.ObjHeader* @"kfun:#stringify(0:0;kotlin.Function1<0:0,kotlin.Int>;kotlin.Function2<0:0,kotlin.Int,kotlin.Any?>){0\C2\A7<kotlin.Any?>}kotlin.String"
stringify(
array,
{ it.size }, // $stringifyIntArray$lambda$1$FUNCTION_REFERENCE$2
Array<Int>::get // $get$FUNCTION_REFERENCE$3
)
class N(val v: Int) : I {
override fun toString() = v.toString()
}
@Suppress("UNUSED_PARAMETER")
fun <BazTP0, BazTP1> foo(p1: BazTP0, p2: BazTP1) {}
fun <QuxTP> bar() {
val ref: KFunction2<QuxTP, QuxTP, Unit> = ::foo // $foo$FUNCTION_REFERENCE$4
println(ref)
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
println(stringifyArray(arrayOf(N(2), N(14))))
println(stringifyIntArray(arrayOf(1, 2, 3)))
bar<Int>()
bar<String>()
val ref: KFunction2<Int, Int, Unit> = ::foo // $foo$FUNCTION_REFERENCE$5
println(ref)
return "OK"
}
// CHECK-LABEL: define internal i32 @"kfun:$stringifyArray$lambda$0$FUNCTION_REFERENCE$0.invoke#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$stringifyArray$lambda$0$FUNCTION_REFERENCE$0.<init>#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:$stringifyArray$lambda$0$FUNCTION_REFERENCE$0.$<bridge-BNNN>invoke(kotlin.Array<1:0>){}kotlin.Int#internal"
// CHECK-SAME: (%struct.ObjHeader* [[this:%[0-9]+]], %struct.ObjHeader* [[array:%[0-9]+]], %struct.ObjHeader** {{%[0-9]+}})
// CHECK-OPT: call i32 @"kfun:$stringifyArray$lambda$0$FUNCTION_REFERENCE$0.invoke#internal"(%struct.ObjHeader* [[this]], %struct.ObjHeader* [[array]])
// CHECK-DEBUG: call i32 @"kfun:$stringifyArray$lambda$0$FUNCTION_REFERENCE$0.invoke#internal"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:$get$FUNCTION_REFERENCE$1.invoke#internal"
// CHECK-SAME: (%struct.ObjHeader* [[this:%[0-9]+]], %struct.ObjHeader* [[array:%[0-9]+]], i32 [[index:%[0-9]+]], %struct.ObjHeader** [[ret:%[0-9]+]])
// CHECK-OPT: call %struct.ObjHeader* @Kotlin_Array_get(%struct.ObjHeader* [[array]], i32 [[index]], %struct.ObjHeader** [[ret]])
// CHECK-DEBUG: call %struct.ObjHeader* @Kotlin_Array_get(%struct.ObjHeader* {{%[0-9]+}}, i32 {{%[0-9]+}}, %struct.ObjHeader** {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$get$FUNCTION_REFERENCE$1.<init>#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:$get$FUNCTION_REFERENCE$1.$<bridge-NNNNB>invoke(kotlin.Array<*>;kotlin.Int){}kotlin.Any?#internal"
// CHECK-SAME: (%struct.ObjHeader* [[this:%[0-9]+]], %struct.ObjHeader* [[array:%[0-9]+]], %struct.ObjHeader* [[boxedIndex:%[0-9]+]], %struct.ObjHeader** [[ret:%[0-9]+]])
// CHECK-OPT: call %struct.ObjHeader* @"kfun:$get$FUNCTION_REFERENCE$1.invoke#internal"(%struct.ObjHeader* [[this]], %struct.ObjHeader* [[array]], i32 {{%[0-9]+}}, %struct.ObjHeader** [[ret]])
// CHECK-DEBUG: call %struct.ObjHeader* @"kfun:$get$FUNCTION_REFERENCE$1.invoke#internal"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}}, i32 {{%[0-9]+}}, %struct.ObjHeader** {{%[0-9]+}})
// CHECK-LABEL: define internal i32 @"kfun:$stringifyIntArray$lambda$1$FUNCTION_REFERENCE$2.invoke#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$stringifyIntArray$lambda$1$FUNCTION_REFERENCE$2.<init>#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:$stringifyIntArray$lambda$1$FUNCTION_REFERENCE$2.$<bridge-BNNN>invoke(kotlin.Array<kotlin.Int>){}kotlin.Int#internal"
// CHECK-SAME: (%struct.ObjHeader* [[this:%[0-9]+]], %struct.ObjHeader* [[array:%[0-9]+]], %struct.ObjHeader** {{%[0-9]+}})
// CHECK-OPT: call i32 @"kfun:$stringifyIntArray$lambda$1$FUNCTION_REFERENCE$2.invoke#internal"(%struct.ObjHeader* [[this]], %struct.ObjHeader* [[array]])
// CHECK-DEBUG: call i32 @"kfun:$stringifyIntArray$lambda$1$FUNCTION_REFERENCE$2.invoke#internal"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal i32 @"kfun:$get$FUNCTION_REFERENCE$3.invoke#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}}, i32 {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$get$FUNCTION_REFERENCE$3.<init>#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:$get$FUNCTION_REFERENCE$3.$<bridge-BNNNB>invoke(kotlin.Array<kotlin.Int>;kotlin.Int){}kotlin.Int#internal"
// CHECK-SAME: (%struct.ObjHeader* [[this:%[0-9]+]], %struct.ObjHeader* [[array:%[0-9]+]], %struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader** {{%[0-9]+}})
// CHECK-OPT: call i32 @"kfun:$get$FUNCTION_REFERENCE$3.invoke#internal"(%struct.ObjHeader* [[this]], %struct.ObjHeader* [[array]], i32 {{%[0-9]+}})
// CHECK-DEBUG: call i32 @"kfun:$get$FUNCTION_REFERENCE$3.invoke#internal"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}}, i32 {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$foo$FUNCTION_REFERENCE$4.invoke#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* [[p1:%[0-9]+]], %struct.ObjHeader* [[p2:%[0-9]+]])
// CHECK-OPT: call void @"kfun:#foo(0:0;0:1){0\C2\A7<kotlin.Any?>;1\C2\A7<kotlin.Any?>}"(%struct.ObjHeader* [[p1]], %struct.ObjHeader* [[p2]])
// CHECK-DEBUG: call void @"kfun:#foo(0:0;0:1){0\C2\A7<kotlin.Any?>;1\C2\A7<kotlin.Any?>}"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$foo$FUNCTION_REFERENCE$4.<init>#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:$foo$FUNCTION_REFERENCE$4.$<bridge-UNNNN>invoke(1:0;1:0){}#internal"
// CHECK-SAME: (%struct.ObjHeader* [[this:%[0-9]+]], %struct.ObjHeader* [[p1:%[0-9]+]], %struct.ObjHeader* [[p2:%[0-9]+]], %struct.ObjHeader** {{%[0-9]+}})
// CHECK-OPT: call void @"kfun:$foo$FUNCTION_REFERENCE$4.invoke#internal"(%struct.ObjHeader* [[this]], %struct.ObjHeader* [[p1]], %struct.ObjHeader* [[p2]])
// CHECK-DEBUG: call void @"kfun:$foo$FUNCTION_REFERENCE$4.invoke#internal"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$foo$FUNCTION_REFERENCE$5.invoke#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}}, i32 {{%[0-9]+}}, i32 {{%[0-9]+}})
// CHECK: call void @"kfun:#foo(0:0;0:1){0\C2\A7<kotlin.Any?>;1\C2\A7<kotlin.Any?>}"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$foo$FUNCTION_REFERENCE$5.<init>#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal %struct.ObjHeader* @"kfun:$foo$FUNCTION_REFERENCE$5.$<bridge-UNNBB>invoke(kotlin.Int;kotlin.Int){}#internal"
// CHECK-SAME: (%struct.ObjHeader* [[this:%[0-9]+]], %struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader** {{%[0-9]+}})
// CHECK-OPT: call void @"kfun:$foo$FUNCTION_REFERENCE$5.invoke#internal"(%struct.ObjHeader* [[this]], i32 {{%[0-9]+}}, i32 {{%[0-9]+}})
// CHECK-DEBUG: call void @"kfun:$foo$FUNCTION_REFERENCE$5.invoke#internal"(%struct.ObjHeader* {{%[0-9]+}}, i32 {{%[0-9]+}}, i32 {{%[0-9]+}})
@@ -0,0 +1,26 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// CHECK-LABEL: "kfun:#and(kotlin.Int;kotlin.Int){}kotlin.Int"
fun and(a: Int, b: Int): Int {
// CHECK: and {{.*}}, {{.*}}
return a and b
// CHECK-LABEL: epilogue:
}
// CHECK-LABEL: "kfun:#ieee754(kotlin.Float;kotlin.Float){}kotlin.Boolean"
fun ieee754(a: Float, b: Float): Boolean {
// CHECK: fcmp oeq float {{.*}}, {{.*}}
return a == b
// CHECK-LABEL: epilogue:
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
val x = and(1, 2)
val y = ieee754(0.0f, 1.0f)
// CHECK-LABEL: epilogue:
return if (x == 0 && !y)
"OK"
else "FAIL x=$x y=$y"
}
@@ -0,0 +1,21 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
class C {
fun foo(x: Int) = x
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-OPT-NOT: Int-box
// CHECK-DEBUG: Int-box
// CHECK-NOT: Int-unbox
// CHECK-LABEL: epilogue:
fun box(): String {
val c = C()
val fooref = c::foo
val result = fooref(42)
return if( result == 42)
"OK"
else
"FAIL: $result"
}
@@ -0,0 +1,20 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
class C<T> {
fun foo(x: T) = x
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-NOT: Int-box
// CHECK-OPT-NOT: Int-unbox
// CHECK-DEBUG: Int-unbox
// CHECK-LABEL: epilogue:
fun box(): String {
val c = C<Int>()
val fooref = c::foo
return if (fooref(42) == 42)
"OK"
else
"FAIL"
}
@@ -0,0 +1,29 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
fun <T> T.foo() { println(this) }
// CHECK-LABEL: define void @"kfun:#bar(0:0){0\C2\A7<kotlin.Any?>}"
// CHECK-SAME: (%struct.ObjHeader* [[x:%[0-9]+]])
fun <BarTP> bar(x: BarTP) {
// CHECK-OPT: call void @"kfun:$foo$FUNCTION_REFERENCE$0.<init>#internal"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* [[x]])
// CHECK-DEBUG: call void @"kfun:$foo$FUNCTION_REFERENCE$0.<init>#internal"(%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
println(x::foo)
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
fun box(): String {
// CHECK: call void @"kfun:$foo$FUNCTION_REFERENCE$1.<init>#internal"(%struct.ObjHeader* {{%[0-9]+}}, i32 5)
println(5::foo)
bar("hello")
bar(42)
return "OK"
// CHECK-LABEL: epilogue:
}
// CHECK-LABEL: define internal void @"kfun:$foo$FUNCTION_REFERENCE$0.<init>#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}}, %struct.ObjHeader* {{%[0-9]+}})
// CHECK-LABEL: define internal void @"kfun:$foo$FUNCTION_REFERENCE$1.<init>#internal"
// CHECK-SAME: (%struct.ObjHeader* {{%[0-9]+}}, i32 {{%[0-9]+}})
@@ -0,0 +1,23 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
fun interface Foo {
fun bar(x: Int): Any
}
fun baz(x: Any): Int = x.hashCode()
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// Boxing needs to be used now due to non-devirtualized call
// CHECK-OPT: Int-box
// CHECK-NOT: Int-box
// CHECK-NOT: Int-unbox
// CHECK-LABEL: epilogue:
fun box(): String {
val foo: Foo = Foo(::baz)
return if (foo.bar(42) == 42)
"OK"
else "FAIL"
}
@@ -0,0 +1,19 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
fun interface Foo<T> {
fun bar(x: T): Any
}
fun baz(x: Any): Int = x.hashCode()
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-NOT: Int-box
// CHECK-NOT: Int-unbox
// CHECK-LABEL: epilogue:
fun box(): String {
val foo: Foo<Int> = Foo(::baz)
return if (foo.bar(42) == 42)
"OK"
else "FAIL"
}
@@ -0,0 +1,21 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
fun interface Foo {
fun bar(x: Int): Int
}
fun baz(x: Int): Int = x.hashCode()
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-OPT-NOT: Int-box
// CHECK-DEBUG: Int-box
// CHECK-NOT: Int-unbox
// CHECK-LABEL: epilogue:
fun box(): String {
val foo: Foo = Foo(::baz)
val result = foo.bar(42)
return if( result == 42 )
"OK"
else "FAIL: $result"
}
@@ -0,0 +1,21 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
fun interface Foo<T> {
fun bar(x: T): Int
}
fun baz(x: Any): Int = x.hashCode()
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-OPT-NOT: Int-box
// CHECK-DEBUG: Int-box
// CHECK-NOT: Int-unbox
// CHECK-LABEL: epilogue:
fun box(): String {
val foo: Foo<Int> = Foo(::baz)
val result = foo.bar(42)
return if( result == 42 )
"OK"
else "FAIL: $result"
}
@@ -0,0 +1,22 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
fun plus1(x: Int) = x + 1
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-OPT-NOT: Int-box
// CHECK-OPT-NOT: Int-unbox
// CHECK-DEBUG: Int-box
// CHECK-DEBUG: Int-unbox
// CHECK-LABEL: epilogue:
fun box(): String {
val ref = ::plus1
var y = 0
repeat(100000) {
y += ref(it) // Should be devirtualized and invoked without boxing/unboxing (`Int-box`/`Int-unbox`)
}
if (y != 705082704)
return "FAIL $y != 705082704"
return "OK"
}
@@ -0,0 +1,73 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlin.native.concurrent.*
import kotlinx.cinterop.*
val arr: Array<String> = arrayOf("1")
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
@kotlinx.cinterop.ExperimentalForeignApi
fun box(): String {
println(arr.size.toByte() == arr[0].toByte())
println(arr.size.toUByte() == arr[0].toUByte())
println(arr.size.toShort() == arr[0].toShort())
println(arr.size.toUShort() == arr[0].toUShort())
println(arr.size.toInt() == arr[0].toInt())
println(arr.size.toUInt() == arr[0].toUInt())
println(arr.size.toLong() == arr[0].toLong())
println(arr.size.toULong() == arr[0].toULong())
println(arr.size.toFloat() == arr[0].toFloat())
println(arr.size.toDouble() == arr[0].toDouble())
println(Char(arr.size) == arr[0][0])
println((arr.size == 1) == (arr[0] == "1")) // Boolean
memScoped {
val var1: IntVar = alloc()
val var2: IntVar = alloc()
println(var1.ptr.rawValue == var2.ptr.rawValue)
}
println(Result.success(arr.size) == Result.success(arr[0].toInt()))
println(vectorOf(arr.size, arr.size, arr.size, arr.size) == vectorOf(arr[0].toInt(), arr[0].toInt(), arr[0].toInt(), arr[0].toInt()))
val w1 = Worker.start()
val w2 = Worker.start()
println(w1 == w2)
val f1 = w1.requestTermination()
val f2 = w2.requestTermination()
println(f1 == f2)
f1.result
f2.result
return "OK"
}
// CHECK-OPT-NOT: {{call|invoke}} i64 @"kfun:kotlin#<Long-unbox>
// CHECK-OPT-NOT: {{call|invoke}} i64 @"kfun:kotlin#<ULong-unbox>
// CHECK-OPT-NOT: {{call|invoke}} i32 @"kfun:kotlin#<Int-unbox>
// CHECK-OPT-NOT: {{call|invoke}} i32 @"kfun:kotlin#<UInt-unbox>
// CHECK-OPT-NOT: {{call|invoke}} {{signext i16|i16}} @"kfun:kotlin#<Short-unbox>
// CHECK-OPT-NOT: {{call|invoke}} {{zeroext i16|i16}} @"kfun:kotlin#<UShort-unbox>
// CHECK-OPT-NOT: {{call|invoke}} {{signext i8|i8}} @"kfun:kotlin#<Byte-unbox>
// CHECK-OPT-NOT: {{call|invoke}} {{zeroext i8|i8}} @"kfun:kotlin#<UByte-unbox>
// CHECK-OPT-NOT: {{call|invoke}} {{zeroext i16|i16}} @"kfun:kotlin#<Char-unbox>
// CHECK-OPT-NOT: {{call|invoke}} {{zeroext i1|i1}} @"kfun:kotlin#<Boolean-unbox>
// CHECK-OPT-NOT: {{call|invoke}} double @"kfun:kotlin#<Double-unbox>
// CHECK-OPT-NOT: {{call|invoke}} float @"kfun:kotlin#<Float-unbox>
// CHECK-OPT-NOT: {{call|invoke}} i8* @"kfun:kotlin.native.internal#<NativePtr-unbox>
// CHECK-OPT-NOT: {{call|invoke}} i32 @"kfun:kotlin.native.concurrent#<Future-unbox>
// CHECK-OPT-NOT: {{call|invoke}} i32 @"kfun:kotlin.native.concurrent#<Worker-unbox>
// CHECK-OPT-NOT: {{call|invoke}} <4 x float> @"kfun:kotlin.native#<Vector128-unbox>
// CHECK-OPT-NOT: {{call|invoke}} %struct.ObjHeader* @"kfun:kotlin#<Result-unbox>
// CHECK-LABEL: epilogue:
// On APPLE targets, generated functions <T>ToNSNumber may contain non-converted invocations of unbox functions.
// CHECK-APPLE: {{IntToNSNumber|LongToNSNumber|ByteToNSNumber|ShortToNSNumber|FloatToNSNumber|DoubleToNSNumber}}
@@ -0,0 +1,20 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlinx.cinterop.*
// CHECK-AAPCS-OPT-LABEL: define i1 @"kfun:kotlinx.cinterop.CPointer#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-DEFAULTABI-OPT-LABEL: define zeroext i1 @"kfun:kotlinx.cinterop.CPointer#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-WINDOWSX64-OPT-LABEL: define zeroext i1 @"kfun:kotlinx.cinterop.CPointer#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-OPT: call i8* @"kfun:kotlinx.cinterop#<CPointer-unbox>(kotlin.Any?){}kotlinx.cinterop.CPointer<-1:0>?"
// This test is useless in debug mode.
// TODO(KT-59288): add ability to ignore tests in debug mode
// CHECK-DEBUG-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
@kotlinx.cinterop.ExperimentalForeignApi
fun box(): String = memScoped {
val var1: IntVar = alloc()
val var2: IntVar = alloc()
return if (var1.ptr == var2.ptr) "FAIL" else "OK"
}
@@ -0,0 +1,17 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlinx.cinterop.*
// CHECK-OPT-LABEL: define i8* @"kfun:kotlinx.cinterop#interpretOpaquePointed(kotlin.native.internal.NativePtr){}kotlinx.cinterop.NativePointed"(i8* %0)
// CHECK-OPT: call i8* @"kfun:kotlinx.cinterop#<NativePointed-unbox>(kotlin.Any?){}kotlinx.cinterop.NativePointed?"
// This test is useless in debug mode.
// TODO(KT-59288): add ability to ignore tests in debug mode
// CHECK-DEBUG-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
@kotlinx.cinterop.ExperimentalForeignApi
fun box(): String = memScoped {
val var1: NativePointed = alloc(4, 4)
return if (interpretOpaquePointed(var1.rawPtr) is NativePointed) "OK" else "FAIL"
}
@@ -0,0 +1,22 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlinx.cinterop.*
// CHECK-AAPCS-OPT-LABEL: define i1 @"kfun:kotlin.native.internal.NonNullNativePtr#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-DEFAULTABI-OPT-LABEL: define zeroext i1 @"kfun:kotlin.native.internal.NonNullNativePtr#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-WINDOWSX64-OPT-LABEL: define zeroext i1 @"kfun:kotlin.native.internal.NonNullNativePtr#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-OPT: call i8* @"kfun:kotlin.native.internal#<NonNullNativePtr-unbox>(kotlin.Any?){}kotlin.native.internal.NonNullNativePtr?"
// This test is useless in debug mode.
// TODO(KT-59288): add ability to ignore tests in debug mode
// CHECK-DEBUG-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
@kotlinx.cinterop.ExperimentalForeignApi
fun box(): String = memScoped {
val var1: IntVar = alloc()
val var2: IntVar = alloc()
// The first one is K1, the second one is K2.
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
return if (var1.ptr.value as Any == var2.ptr.value as Any) "FAIL" else "OK"
}
@@ -0,0 +1,26 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
import kotlinx.cinterop.*
// CHECK-AAPCS-OPT-LABEL: define i1 @"kfun:kotlinx.cinterop.StableRef#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-DEFAULTABI-OPT-LABEL: define zeroext i1 @"kfun:kotlinx.cinterop.StableRef#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-WINDOWSX64-OPT-LABEL: define zeroext i1 @"kfun:kotlinx.cinterop.StableRef#equals(kotlin.Any?){}kotlin.Boolean"(i8* %0, %struct.ObjHeader* %1)
// CHECK-OPT: call i8* @"kfun:kotlinx.cinterop#<StableRef-unbox>(kotlin.Any?){}kotlinx.cinterop.StableRef<-1:0>?"
// CHECK-OPT-LABEL: epilogue:
// This test is useless in debug mode.
// TODO(KT-59288): add ability to ignore tests in debug mode
// CHECK-DEBUG-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
@kotlinx.cinterop.ExperimentalForeignApi
fun box(): String {
val ref1 = StableRef.create(Any())
val ref2 = StableRef.create(Any())
val isEqual = ref1 == ref2
ref2.dispose()
ref1.dispose()
return if (!isEqual) "OK" else "FAIL"
}
@@ -0,0 +1,18 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// CHECK-AAPCS-OPT-LABEL: define i1 @"kfun:kotlin.UByteArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-DEFAULTABI-OPT-LABEL: define zeroext i1 @"kfun:kotlin.UByteArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-WINDOWSX64-OPT-LABEL: define zeroext i1 @"kfun:kotlin.UByteArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-OPT: call %struct.ObjHeader* @"kfun:kotlin#<UByteArray-unbox>(kotlin.Any?){}kotlin.UByteArray?"
// CHECK-LABEL: epilogue:
fun box(): String {
val arr1 = UByteArray(10) { it.toUByte() }
val arr2 = UByteArray(10) { (it / 2).toUByte() }
return if (arr1 == arr2) "FAIL" else "OK"
}
@@ -0,0 +1,18 @@
// TARGET_BACKEND: NATIVE
// FILECHECK_STAGE: CStubs
// CHECK-AAPCS-OPT-LABEL: define i1 @"kfun:kotlin.UIntArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-DEFAULTABI-OPT-LABEL: define zeroext i1 @"kfun:kotlin.UIntArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-WINDOWSX64-OPT-LABEL: define zeroext i1 @"kfun:kotlin.UIntArray#equals(kotlin.Any?){}kotlin.Boolean"(%struct.ObjHeader* %0, %struct.ObjHeader* %1)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:#box(){}kotlin.String"
// CHECK-OPT: call %struct.ObjHeader* @"kfun:kotlin#<UIntArray-unbox>(kotlin.Any?){}kotlin.UIntArray?"
// CHECK-LABEL: epilogue:
fun box(): String {
val arr1 = UIntArray(10) { it.toUInt() }
val arr2 = UIntArray(10) { (it / 2).toUInt() }
return if (arr1 == arr2) "FAIL" else "OK"
}

Some files were not shown because too many files have changed in this diff Show More