[K/N][Tests] Migrate some cinterop tests to new infra
^KT-61259
This commit is contained in:
committed by
Space Team
parent
422128f3dc
commit
bf01cb16b4
@@ -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_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"
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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,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"
|
||||
}
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
// TARGET_BACKEND: NATIVE
|
||||
// MODULE: cinterop
|
||||
// MODULE: cinterop_kt63048
|
||||
// FILE: kt63048.def
|
||||
language = Objective-C
|
||||
headers = kt63048.h
|
||||
@@ -23,7 +23,7 @@ headers = kt63048.h
|
||||
@end
|
||||
|
||||
|
||||
// MODULE: main(cinterop)
|
||||
// MODULE: main(cinterop_kt63048)
|
||||
// FILE: main.kt
|
||||
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class, kotlin.experimental.ExperimentalObjCName::class)
|
||||
|
||||
|
||||
+12
-4
@@ -3,8 +3,16 @@
|
||||
// FILE: kt63049.def
|
||||
depends = Foundation
|
||||
language = Objective-C
|
||||
---
|
||||
@interface WithClassProperty
|
||||
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)
|
||||
@@ -14,8 +22,8 @@ language = Objective-C
|
||||
import kt63049.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class Impl : WithClassProperty() {
|
||||
companion object : WithClassPropertyMeta() {
|
||||
class Impl : KT63049() {
|
||||
companion object : KT63049Meta() {
|
||||
fun stringProperty(): String? = "OK"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user