diff --git a/compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_ExplicitAlignment.kt b/compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_ExplicitAlignment.kt new file mode 100644 index 00000000000..c5d97180ac9 --- /dev/null +++ b/compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_ExplicitAlignment.kt @@ -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 + +#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" +} diff --git a/compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_ImplicitAlignment.kt b/compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_ImplicitAlignment.kt new file mode 100644 index 00000000000..a5761e483e4 --- /dev/null +++ b/compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_ImplicitAlignment.kt @@ -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 + +#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" +} diff --git a/compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_Nested.kt b/compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_Nested.kt new file mode 100644 index 00000000000..f320dad9005 --- /dev/null +++ b/compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_Nested.kt @@ -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 + +#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" +} diff --git a/compiler/testData/codegen/box/cinterop/basics/structAnonym.kt b/compiler/testData/codegen/box/cinterop/basics/structAnonym.kt deleted file mode 100644 index fa77adbffc4..00000000000 --- a/compiler/testData/codegen/box/cinterop/basics/structAnonym.kt +++ /dev/null @@ -1,319 +0,0 @@ -// 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 - -#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" -} diff --git a/compiler/testData/codegen/box/cinterop/basics/structAnonym_Complicate.kt b/compiler/testData/codegen/box/cinterop/basics/structAnonym_Complicate.kt new file mode 100644 index 00000000000..13d347aa557 --- /dev/null +++ b/compiler/testData/codegen/box/cinterop/basics/structAnonym_Complicate.kt @@ -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 + +#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" +} diff --git a/compiler/testData/codegen/box/cinterop/basics/structAnonym_GLKVector3.kt b/compiler/testData/codegen/box/cinterop/basics/structAnonym_GLKVector3.kt new file mode 100644 index 00000000000..816bbe4ce59 --- /dev/null +++ b/compiler/testData/codegen/box/cinterop/basics/structAnonym_GLKVector3.kt @@ -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 + +#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" +} diff --git a/compiler/testData/codegen/box/cinterop/basics/structAnonym_Packed.kt b/compiler/testData/codegen/box/cinterop/basics/structAnonym_Packed.kt new file mode 100644 index 00000000000..7f246c1a9c2 --- /dev/null +++ b/compiler/testData/codegen/box/cinterop/basics/structAnonym_Packed.kt @@ -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 + +#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" +} diff --git a/compiler/testData/codegen/box/cinterop/basics/structAnonym_Packed2.kt b/compiler/testData/codegen/box/cinterop/basics/structAnonym_Packed2.kt new file mode 100644 index 00000000000..42beecbca73 --- /dev/null +++ b/compiler/testData/codegen/box/cinterop/basics/structAnonym_Packed2.kt @@ -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 + +#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" +} diff --git a/compiler/testData/codegen/box/cinterop/basics/structAnonym_PragmaPacked.kt b/compiler/testData/codegen/box/cinterop/basics/structAnonym_PragmaPacked.kt new file mode 100644 index 00000000000..31077ad22ee --- /dev/null +++ b/compiler/testData/codegen/box/cinterop/basics/structAnonym_PragmaPacked.kt @@ -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 + +#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" +} diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeCodegenBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeCodegenBoxTestGenerated.java index 1881d0b0543..a3da480325f 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeCodegenBoxTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeCodegenBoxTestGenerated.java @@ -4929,9 +4929,51 @@ public class FirNativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTe } @Test - @TestMetadata("structAnonym.kt") - public void testStructAnonym() throws Exception { - runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym.kt"); + @TestMetadata("structAnonRecordMember_ExplicitAlignment.kt") + public void testStructAnonRecordMember_ExplicitAlignment() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_ExplicitAlignment.kt"); + } + + @Test + @TestMetadata("structAnonRecordMember_ImplicitAlignment.kt") + public void testStructAnonRecordMember_ImplicitAlignment() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_ImplicitAlignment.kt"); + } + + @Test + @TestMetadata("structAnonRecordMember_Nested.kt") + public void testStructAnonRecordMember_Nested() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_Nested.kt"); + } + + @Test + @TestMetadata("structAnonym_Complicate.kt") + public void testStructAnonym_Complicate() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_Complicate.kt"); + } + + @Test + @TestMetadata("structAnonym_GLKVector3.kt") + public void testStructAnonym_GLKVector3() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_GLKVector3.kt"); + } + + @Test + @TestMetadata("structAnonym_Packed.kt") + public void testStructAnonym_Packed() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_Packed.kt"); + } + + @Test + @TestMetadata("structAnonym_Packed2.kt") + public void testStructAnonym_Packed2() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_Packed2.kt"); + } + + @Test + @TestMetadata("structAnonym_PragmaPacked.kt") + public void testStructAnonym_PragmaPacked() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_PragmaPacked.kt"); } @Test diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeCodegenBoxTestNoPLGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeCodegenBoxTestNoPLGenerated.java index 2ccabb64bb4..a0cb67d58be 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeCodegenBoxTestNoPLGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeCodegenBoxTestNoPLGenerated.java @@ -5041,9 +5041,51 @@ public class FirNativeCodegenBoxTestNoPLGenerated extends AbstractNativeCodegenB } @Test - @TestMetadata("structAnonym.kt") - public void testStructAnonym() throws Exception { - runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym.kt"); + @TestMetadata("structAnonRecordMember_ExplicitAlignment.kt") + public void testStructAnonRecordMember_ExplicitAlignment() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_ExplicitAlignment.kt"); + } + + @Test + @TestMetadata("structAnonRecordMember_ImplicitAlignment.kt") + public void testStructAnonRecordMember_ImplicitAlignment() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_ImplicitAlignment.kt"); + } + + @Test + @TestMetadata("structAnonRecordMember_Nested.kt") + public void testStructAnonRecordMember_Nested() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_Nested.kt"); + } + + @Test + @TestMetadata("structAnonym_Complicate.kt") + public void testStructAnonym_Complicate() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_Complicate.kt"); + } + + @Test + @TestMetadata("structAnonym_GLKVector3.kt") + public void testStructAnonym_GLKVector3() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_GLKVector3.kt"); + } + + @Test + @TestMetadata("structAnonym_Packed.kt") + public void testStructAnonym_Packed() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_Packed.kt"); + } + + @Test + @TestMetadata("structAnonym_Packed2.kt") + public void testStructAnonym_Packed2() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_Packed2.kt"); + } + + @Test + @TestMetadata("structAnonym_PragmaPacked.kt") + public void testStructAnonym_PragmaPacked() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_PragmaPacked.kt"); } @Test diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/NativeCodegenBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/NativeCodegenBoxTestGenerated.java index 966c9c04790..a6adc656eb1 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/NativeCodegenBoxTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/NativeCodegenBoxTestGenerated.java @@ -4817,9 +4817,51 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest } @Test - @TestMetadata("structAnonym.kt") - public void testStructAnonym() throws Exception { - runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym.kt"); + @TestMetadata("structAnonRecordMember_ExplicitAlignment.kt") + public void testStructAnonRecordMember_ExplicitAlignment() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_ExplicitAlignment.kt"); + } + + @Test + @TestMetadata("structAnonRecordMember_ImplicitAlignment.kt") + public void testStructAnonRecordMember_ImplicitAlignment() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_ImplicitAlignment.kt"); + } + + @Test + @TestMetadata("structAnonRecordMember_Nested.kt") + public void testStructAnonRecordMember_Nested() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_Nested.kt"); + } + + @Test + @TestMetadata("structAnonym_Complicate.kt") + public void testStructAnonym_Complicate() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_Complicate.kt"); + } + + @Test + @TestMetadata("structAnonym_GLKVector3.kt") + public void testStructAnonym_GLKVector3() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_GLKVector3.kt"); + } + + @Test + @TestMetadata("structAnonym_Packed.kt") + public void testStructAnonym_Packed() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_Packed.kt"); + } + + @Test + @TestMetadata("structAnonym_Packed2.kt") + public void testStructAnonym_Packed2() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_Packed2.kt"); + } + + @Test + @TestMetadata("structAnonym_PragmaPacked.kt") + public void testStructAnonym_PragmaPacked() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_PragmaPacked.kt"); } @Test diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/NativeCodegenBoxTestNoPLGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/NativeCodegenBoxTestNoPLGenerated.java index 9168084c4d2..6530c6941c2 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/NativeCodegenBoxTestNoPLGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/NativeCodegenBoxTestNoPLGenerated.java @@ -4930,9 +4930,51 @@ public class NativeCodegenBoxTestNoPLGenerated extends AbstractNativeCodegenBoxT } @Test - @TestMetadata("structAnonym.kt") - public void testStructAnonym() throws Exception { - runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym.kt"); + @TestMetadata("structAnonRecordMember_ExplicitAlignment.kt") + public void testStructAnonRecordMember_ExplicitAlignment() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_ExplicitAlignment.kt"); + } + + @Test + @TestMetadata("structAnonRecordMember_ImplicitAlignment.kt") + public void testStructAnonRecordMember_ImplicitAlignment() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_ImplicitAlignment.kt"); + } + + @Test + @TestMetadata("structAnonRecordMember_Nested.kt") + public void testStructAnonRecordMember_Nested() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonRecordMember_Nested.kt"); + } + + @Test + @TestMetadata("structAnonym_Complicate.kt") + public void testStructAnonym_Complicate() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_Complicate.kt"); + } + + @Test + @TestMetadata("structAnonym_GLKVector3.kt") + public void testStructAnonym_GLKVector3() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_GLKVector3.kt"); + } + + @Test + @TestMetadata("structAnonym_Packed.kt") + public void testStructAnonym_Packed() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_Packed.kt"); + } + + @Test + @TestMetadata("structAnonym_Packed2.kt") + public void testStructAnonym_Packed2() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_Packed2.kt"); + } + + @Test + @TestMetadata("structAnonym_PragmaPacked.kt") + public void testStructAnonym_PragmaPacked() throws Exception { + runTest("compiler/testData/codegen/box/cinterop/basics/structAnonym_PragmaPacked.kt"); } @Test