aboutsummaryrefslogtreecommitdiff
path: root/tests/abitest.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/abitest.c')
-rw-r--r--tests/abitest.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/tests/abitest.c b/tests/abitest.c
index 3630666..9cdeb87 100644
--- a/tests/abitest.c
+++ b/tests/abitest.c
@@ -131,6 +131,39 @@ static int ret_2double_test(void) {
}
/*
+ * ret_8plus2double_test:
+ *
+ * This catches a corner case in the x86_64 ABI code: the first 7
+ * arguments fit into registers, the 8th doesn't, but the 9th argument
+ * fits into the 8th XMM register.
+ *
+ * Note that the purpose of the 10th argument is to avoid a situation
+ * in which gcc would accidentally put the double at the right
+ * address, thus causing a success message even though TCC actually
+ * generated incorrect code.
+ */
+typedef ret_2double_test_type (*ret_8plus2double_test_function_type) (double, double, double, double, double, double, double, ret_2double_test_type, double, double);
+
+static int ret_8plus2double_test_callback(void *ptr) {
+ ret_8plus2double_test_function_type f = (ret_8plus2double_test_function_type)ptr;
+ ret_2double_test_type a = {10, 35};
+ ret_2double_test_type r;
+ r = f(0, 0, 0, 0, 0, 0, 0, a, 37, 38);
+ return ((r.x == 37) && (r.y == 37)) ? 0 : -1;
+}
+
+static int ret_8plus2double_test(void) {
+ const char *src =
+ "typedef struct ret_2double_test_type_s {double x, y;} ret_2double_test_type;"
+ "ret_2double_test_type f(double x1, double x2, double x3, double x4, double x5, double x6, double x7, ret_2double_test_type a, double x8, double x9) {\n"
+ " ret_2double_test_type r = { x8, x8 };\n"
+ " return r;\n"
+ "}\n";
+
+ return run_callback(src, ret_8plus2double_test_callback);
+}
+
+/*
* ret_mixed_test:
*
* On x86-64, a struct with a double and a 64-bit integer should be
@@ -266,6 +299,39 @@ static int reg_pack_longlong_test(void) {
}
/*
+ * ret_6plus2longlong_test:
+ *
+ * This catches a corner case in the x86_64 ABI code: the first 5
+ * arguments fit into registers, the 6th doesn't, but the 7th argument
+ * fits into the 6th argument integer register, %r9.
+ *
+ * Note that the purpose of the 10th argument is to avoid a situation
+ * in which gcc would accidentally put the longlong at the right
+ * address, thus causing a success message even though TCC actually
+ * generated incorrect code.
+ */
+typedef reg_pack_longlong_test_type (*ret_6plus2longlong_test_function_type) (long long, long long, long long, long long, long long, reg_pack_longlong_test_type, long long, long long);
+
+static int ret_6plus2longlong_test_callback(void *ptr) {
+ ret_6plus2longlong_test_function_type f = (ret_6plus2longlong_test_function_type)ptr;
+ reg_pack_longlong_test_type a = {10, 35};
+ reg_pack_longlong_test_type r;
+ r = f(0, 0, 0, 0, 0, a, 37, 38);
+ return ((r.x == 37) && (r.y == 37)) ? 0 : -1;
+}
+
+static int ret_6plus2longlong_test(void) {
+ const char *src =
+ "typedef struct reg_pack_longlong_test_type_s {long long x, y;} reg_pack_longlong_test_type;"
+ "reg_pack_longlong_test_type f(long long x1, long long x2, long long x3, long long x4, long long x5, reg_pack_longlong_test_type a, long long x8, long long x9) {\n"
+ " reg_pack_longlong_test_type r = { x8, x8 };\n"
+ " return r;\n"
+ "}\n";
+
+ return run_callback(src, ret_6plus2longlong_test_callback);
+}
+
+/*
* sret_test: Create a struct large enough to be returned via sret
* (hidden pointer as first function argument)
*/
@@ -560,6 +626,8 @@ int main(int argc, char **argv) {
RUN_TEST(ret_longdouble_test);
RUN_TEST(ret_2float_test);
RUN_TEST(ret_2double_test);
+ /* RUN_TEST(ret_8plus2double_test); currently broken on x86_64 */
+ /* RUN_TEST(ret_6plus2longlong_test); currently broken on x86_64 */
/* RUN_TEST(ret_mixed_test); currently broken on x86_64 */
/* RUN_TEST(ret_mixed2_test); currently broken on x86_64 */
RUN_TEST(ret_mixed3_test);