summaryrefslogtreecommitdiffstats
path: root/tests/run-make/extern-fn-struct-passing-abi/test.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/run-make/extern-fn-struct-passing-abi/test.c')
-rw-r--r--tests/run-make/extern-fn-struct-passing-abi/test.c314
1 files changed, 314 insertions, 0 deletions
diff --git a/tests/run-make/extern-fn-struct-passing-abi/test.c b/tests/run-make/extern-fn-struct-passing-abi/test.c
new file mode 100644
index 000000000..136b07129
--- /dev/null
+++ b/tests/run-make/extern-fn-struct-passing-abi/test.c
@@ -0,0 +1,314 @@
+#include <assert.h>
+#include <stdint.h>
+
+struct Rect {
+ int32_t a;
+ int32_t b;
+ int32_t c;
+ int32_t d;
+};
+
+struct BiggerRect {
+ struct Rect s;
+ int32_t a;
+ int32_t b;
+};
+
+struct FloatRect {
+ int32_t a;
+ int32_t b;
+ double c;
+};
+
+struct Huge {
+ int32_t a;
+ int32_t b;
+ int32_t c;
+ int32_t d;
+ int32_t e;
+};
+
+struct FloatPoint {
+ double x;
+ double y;
+};
+
+struct FloatOne {
+ double x;
+};
+
+struct IntOdd {
+ int8_t a;
+ int8_t b;
+ int8_t c;
+};
+
+// System V x86_64 ABI:
+// a, b, c, d, e should be in registers
+// s should be byval pointer
+//
+// Win64 ABI:
+// a, b, c, d should be in registers
+// e should be on the stack
+// s should be byval pointer
+void byval_rect(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, struct Rect s) {
+ assert(a == 1);
+ assert(b == 2);
+ assert(c == 3);
+ assert(d == 4);
+ assert(e == 5);
+ assert(s.a == 553);
+ assert(s.b == 554);
+ assert(s.c == 555);
+ assert(s.d == 556);
+}
+
+// System V x86_64 ABI:
+// a, b, c, d, e, f should be in registers
+// s should be byval pointer on the stack
+//
+// Win64 ABI:
+// a, b, c, d should be in registers
+// e, f should be on the stack
+// s should be byval pointer on the stack
+void byval_many_rect(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e,
+ int32_t f, struct Rect s) {
+ assert(a == 1);
+ assert(b == 2);
+ assert(c == 3);
+ assert(d == 4);
+ assert(e == 5);
+ assert(f == 6);
+ assert(s.a == 553);
+ assert(s.b == 554);
+ assert(s.c == 555);
+ assert(s.d == 556);
+}
+
+// System V x86_64 ABI:
+// a, b, c, d, e, f, g should be in sse registers
+// s should be split across 2 registers
+// t should be byval pointer
+//
+// Win64 ABI:
+// a, b, c, d should be in sse registers
+// e, f, g should be on the stack
+// s should be on the stack (treated as 2 i64's)
+// t should be on the stack (treated as an i64 and a double)
+void byval_rect_floats(float a, float b, double c, float d, float e,
+ float f, double g, struct Rect s, struct FloatRect t) {
+ assert(a == 1.);
+ assert(b == 2.);
+ assert(c == 3.);
+ assert(d == 4.);
+ assert(e == 5.);
+ assert(f == 6.);
+ assert(g == 7.);
+ assert(s.a == 553);
+ assert(s.b == 554);
+ assert(s.c == 555);
+ assert(s.d == 556);
+ assert(t.a == 3489);
+ assert(t.b == 3490);
+ assert(t.c == 8.);
+}
+
+// System V x86_64 ABI:
+// a, b, d, e, f should be in registers
+// c passed via sse registers
+// s should be byval pointer
+//
+// Win64 ABI:
+// a, b, d should be in registers
+// c passed via sse registers
+// e, f should be on the stack
+// s should be byval pointer
+void byval_rect_with_float(int32_t a, int32_t b, float c, int32_t d,
+ int32_t e, int32_t f, struct Rect s) {
+ assert(a == 1);
+ assert(b == 2);
+ assert(c == 3.);
+ assert(d == 4);
+ assert(e == 5);
+ assert(f == 6);
+ assert(s.a == 553);
+ assert(s.b == 554);
+ assert(s.c == 555);
+ assert(s.d == 556);
+}
+
+// System V x86_64 ABI:
+// a, b, d, e, f should be byval pointer (on the stack)
+// g passed via register (fixes #41375)
+//
+// Win64 ABI:
+// a, b, d, e, f, g should be byval pointer
+void byval_rect_with_many_huge(struct Huge a, struct Huge b, struct Huge c,
+ struct Huge d, struct Huge e, struct Huge f,
+ struct Rect g) {
+ assert(g.a == 123);
+ assert(g.b == 456);
+ assert(g.c == 789);
+ assert(g.d == 420);
+}
+
+// System V x86_64 & Win64 ABI:
+// a, b should be in registers
+// s should be split across 2 integer registers
+void split_rect(int32_t a, int32_t b, struct Rect s) {
+ assert(a == 1);
+ assert(b == 2);
+ assert(s.a == 553);
+ assert(s.b == 554);
+ assert(s.c == 555);
+ assert(s.d == 556);
+}
+
+// System V x86_64 & Win64 ABI:
+// a, b should be in sse registers
+// s should be split across integer & sse registers
+void split_rect_floats(float a, float b, struct FloatRect s) {
+ assert(a == 1.);
+ assert(b == 2.);
+ assert(s.a == 3489);
+ assert(s.b == 3490);
+ assert(s.c == 8.);
+}
+
+// System V x86_64 ABI:
+// a, b, d, f should be in registers
+// c, e passed via sse registers
+// s should be split across 2 registers
+//
+// Win64 ABI:
+// a, b, d should be in registers
+// c passed via sse registers
+// e, f should be on the stack
+// s should be on the stack (treated as 2 i64's)
+void split_rect_with_floats(int32_t a, int32_t b, float c,
+ int32_t d, float e, int32_t f, struct Rect s) {
+ assert(a == 1);
+ assert(b == 2);
+ assert(c == 3.);
+ assert(d == 4);
+ assert(e == 5.);
+ assert(f == 6);
+ assert(s.a == 553);
+ assert(s.b == 554);
+ assert(s.c == 555);
+ assert(s.d == 556);
+}
+
+// System V x86_64 & Win64 ABI:
+// a, b, c should be in registers
+// s should be split across 2 registers
+// t should be a byval pointer
+void split_and_byval_rect(int32_t a, int32_t b, int32_t c, struct Rect s, struct Rect t) {
+ assert(a == 1);
+ assert(b == 2);
+ assert(c == 3);
+ assert(s.a == 553);
+ assert(s.b == 554);
+ assert(s.c == 555);
+ assert(s.d == 556);
+ assert(t.a == 553);
+ assert(t.b == 554);
+ assert(t.c == 555);
+ assert(t.d == 556);
+}
+
+// System V x86_64 & Win64 ABI:
+// a, b should in registers
+// s and return should be split across 2 registers
+struct Rect split_ret_byval_struct(int32_t a, int32_t b, struct Rect s) {
+ assert(a == 1);
+ assert(b == 2);
+ assert(s.a == 553);
+ assert(s.b == 554);
+ assert(s.c == 555);
+ assert(s.d == 556);
+ return s;
+}
+
+// System V x86_64 & Win64 ABI:
+// a, b, c, d should be in registers
+// return should be in a hidden sret pointer
+// s should be a byval pointer
+struct BiggerRect sret_byval_struct(int32_t a, int32_t b, int32_t c, int32_t d, struct Rect s) {
+ assert(a == 1);
+ assert(b == 2);
+ assert(c == 3);
+ assert(d == 4);
+ assert(s.a == 553);
+ assert(s.b == 554);
+ assert(s.c == 555);
+ assert(s.d == 556);
+
+ struct BiggerRect t;
+ t.s = s; t.a = 27834; t.b = 7657;
+ return t;
+}
+
+// System V x86_64 & Win64 ABI:
+// a, b should be in registers
+// return should be in a hidden sret pointer
+// s should be split across 2 registers
+struct BiggerRect sret_split_struct(int32_t a, int32_t b, struct Rect s) {
+ assert(a == 1);
+ assert(b == 2);
+ assert(s.a == 553);
+ assert(s.b == 554);
+ assert(s.c == 555);
+ assert(s.d == 556);
+
+ struct BiggerRect t;
+ t.s = s; t.a = 27834; t.b = 7657;
+ return t;
+}
+
+// System V x86_64 & Win64 ABI:
+// s should be byval pointer (since sizeof(s) > 16)
+// return should in a hidden sret pointer
+struct Huge huge_struct(struct Huge s) {
+ assert(s.a == 5647);
+ assert(s.b == 5648);
+ assert(s.c == 5649);
+ assert(s.d == 5650);
+ assert(s.e == 5651);
+
+ return s;
+}
+
+// System V x86_64 ABI:
+// p should be in registers
+// return should be in registers
+//
+// Win64 ABI and 64-bit PowerPC ELFv1 ABI:
+// p should be a byval pointer
+// return should be in a hidden sret pointer
+struct FloatPoint float_point(struct FloatPoint p) {
+ assert(p.x == 5.);
+ assert(p.y == -3.);
+
+ return p;
+}
+
+// 64-bit PowerPC ELFv1 ABI:
+// f1 should be in a register
+// return should be in a hidden sret pointer
+struct FloatOne float_one(struct FloatOne f1) {
+ assert(f1.x == 7.);
+
+ return f1;
+}
+
+// 64-bit PowerPC ELFv1 ABI:
+// i should be in the least-significant bits of a register
+// return should be in a hidden sret pointer
+struct IntOdd int_odd(struct IntOdd i) {
+ assert(i.a == 1);
+ assert(i.b == 2);
+ assert(i.c == 3);
+
+ return i;
+}