[K/N][Tests] Migrate some cinterop tests to new infra

^KT-61259
This commit is contained in:
Vladimir Sukharev
2024-01-04 19:01:46 +01:00
committed by Space Team
parent 422128f3dc
commit bf01cb16b4
63 changed files with 1776 additions and 1025 deletions
+27
View File
@@ -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"
}
+36
View File
@@ -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_3.def
headers = stdlib.h
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import cstdlib_3.*
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,68 @@
/*
* 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_setenv.def
headers = stdlib.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
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class, kotlin.experimental.ExperimentalNativeApi::class)
import kotlin.native.*
import kotlin.test.*
import cstdlib_setenv.*
import kotlinx.cinterop.*
@OptIn(kotlin.ExperimentalStdlibApi::class)
fun box(): String {
val platformProcessors: Int = Platform.getAvailableProcessors()
val jvmProcessors: Int = platformProcessors // Ideally, must be value of Runtime.getRuntime().availableProcessors() from testsystem
assertTrue(jvmProcessors > 0)
assertTrue(platformProcessors > 0)
assertEquals(jvmProcessors, 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"
}
+151
View File
@@ -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,319 @@
// 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;
}
// 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;
}
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;
}
// 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];
}
// 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;
}
struct StructAnonRecordMember_Packed {
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));
static struct StructAnonRecordMember_Packed retByValue_StructAnonRecordMember_Packed() {
INIT(StructAnonRecordMember_Packed, c);
return c;
}
// 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()
static struct StructAnonRecordMember_PragmaPacked retByValue_StructAnonRecordMember_PragmaPacked() {
INIT(StructAnonRecordMember_PragmaPacked, c);
return c;
}
#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()
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 test_GLKVector3() {
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)
}
}
fun test_StructAnonRecordMember_ImplicitAlignment() {
retByValue_StructAnonRecordMember_ImplicitAlignment()
.useContents {
assertEquals(1, a[0])
assertEquals(4, a[3])
assertEquals(42, b)
}
}
fun test_StructAnonRecordMember_ExplicitAlignment() {
retByValue_StructAnonRecordMember_ExplicitAlignment()
.useContents {
assertEquals('a', a.toInt().toChar())
assertEquals('x', x.toInt().toChar())
}
}
fun test_StructAnonRecordMember_Nested() {
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()))
}
}
fun test_StructAnonym_Complicate() {
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)
}
}
fun test_StructAnonym_Packed() {
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)
}
}
fun test_StructAnonym_PragmaPacked() {
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)
}
}
fun test_StructAnonym_Packed2() {
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)
}
}
fun box(): String {
test_GLKVector3()
test_StructAnonRecordMember_ImplicitAlignment()
test_StructAnonRecordMember_ExplicitAlignment()
test_StructAnonRecordMember_Nested()
test_StructAnonym_Complicate()
test_StructAnonym_Packed()
test_StructAnonym_PragmaPacked()
test_StructAnonym_Packed2()
return "OK"
}
+193
View File
@@ -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
}
+132
View File
@@ -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"
}
+63
View File
@@ -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"
}
+30
View File
@@ -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"
}