#include #include 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; }