History

x86-64 ABI fixes.

abitest now passes; however test1-3 fail in init_test. All other tests pass. I need to re-test Win32 and Linux-x86. I've added a dummy implementation of gfunc_sret to c67-gen.c so it should now compile, and I think it should behave as before I created gfunc_sret.

James Lyon committed 13 years ago

Commit 55ea6d31 parent 3f1d9009 files · +334 −75Browse files

Unified · Split

9 files
  1. .gitignore +2 −0
  2. arm-gen.c +8 −3
  3. c67-gen.c +6 −0
  4. tcc.c +1 −1
  5. tcc.h +2 −0
  6. tccgen.c +11 −3
  7. tests/Makefile +2 −2
  8. tests/abitest.c +59 −4
  9. x86_64-gen.c +243 −62
.gitignore+2−0
@@ -57,3 +57,5 @@ tcc-doc.info · 56 unmodified lines
5757 conftest*
5858 tiny_libmaker
5959 *.dSYM
60+*~
61+
arm-gen.c+8−3
@@ -801,16 +801,21 @@ int assign_fpreg(struct avail_regs *avregs, int align, int size) · 800 unmodified lines
801801 #endif
802802
803803 /* Return 1 if this function returns via an sret pointer, 0 otherwise */
804−ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *align) {
804+ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) {
805+#if TCC_ARM_EABI
806+ int size, align;
805807 size = type_size(vt, &align);
806808 if (size > 4) {
807809 return 1;
808810 } else {
809− *align = 4;
811+ *ret_align = 4;
810812 ret->ref = NULL;
811813 ret->t = VT_INT;
814+ return 0;
812815 }
813− return 0;
816+#else
817+ return 1;
818+#endif
814819 }
815820
816821 /* Generate function call. The function address is pushed first, then
c67-gen.c+6−0
@@ -1879,6 +1879,12 @@ static void gcall_or_jmp(int is_jmp) · 1878 unmodified lines
18791879 }
18801880 }
18811881
1882+/* Return 1 if this function returns via an sret pointer, 0 otherwise */
1883+ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) {
1884+ *ret_align = 1; // Never have to re-align return values for x86-64
1885+ return 1;
1886+}
1887+
18821888 /* generate function call with address in (vtop->t, vtop->c) and free function
18831889 context. Stack entry is popped */
18841890 void gfunc_call(int nb_args)
tcc.c+1−1
@@ -69,7 +69,7 @@ static void help(void) · 68 unmodified lines
6969 " -Bdir use 'dir' as tcc internal library and include path\n"
7070 " -MD generate target dependencies for make\n"
7171 " -MF depfile put generated dependencies here\n"
72− " -norunsrc Do not compile the file which is the first argument after -run."
72+ " -norunsrc Do not compile the file which is the first argument after -run.\n"
7373 );
7474 }
7575
tcc.h+2−0
@@ -718,6 +718,8 @@ struct TCCState { · 717 unmodified lines
718718 #define VT_LLONG 12 /* 64 bit integer */
719719 #define VT_LONG 13 /* long integer (NEVER USED as type, only
720720 during parsing) */
721+#define VT_QLONG 14 /* 128-bit integer. Only used for x86-64 ABI */
722+#define VT_QFLOAT 15 /* 128-bit float. Only used for x86-64 ABI */
721723 #define VT_UNSIGNED 0x0010 /* unsigned type */
722724 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
723725 #define VT_BITFIELD 0x0040 /* bitfield modifier */
tccgen.c+11−3
@@ -2495,21 +2495,29 @@ ST_FUNC void vstore(void) · 2494 unmodified lines
24952495 vtop[-1].r = t | VT_LVAL;
24962496 }
24972497 store(r, vtop - 1);
2498−#ifndef TCC_TARGET_X86_64
2499− /* two word case handling : store second register at word + 4 */
2498+ /* two word case handling : store second register at word + 4 (or +8 for x86-64) */
2499+#ifdef TCC_TARGET_X86_64
2500+ if ((ft & VT_BTYPE) == VT_QLONG) {
2501+#else
25002502 if ((ft & VT_BTYPE) == VT_LLONG) {
2503+#endif
25012504 vswap();
25022505 /* convert to int to increment easily */
2506+#ifdef TCC_TARGET_X86_64
2507+ vtop->type.t = VT_LLONG;
2508+ gaddrof();
2509+ vpushi(8);
2510+#else
25032511 vtop->type.t = VT_INT;
25042512 gaddrof();
25052513 vpushi(4);
2514+#endif
25062515 gen_op('+');
25072516 vtop->r |= VT_LVAL;
25082517 vswap();
25092518 /* XXX: it works because r2 is spilled last ! */
25102519 store(vtop->r2, vtop - 1);
25112520 }
2512−#endif
25132521 }
25142522 vswap();
25152523 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
tests/Makefile+2−2
@@ -188,8 +188,8 @@ abitest-tcc$(EXESUF): abitest.c $(top_builddir)/$(LIBTCC) · 187 unmodified lines
188188
189189 abitest: abitest-cc$(EXESUF) abitest-tcc$(EXESUF)
190190 @echo ------------ $@ ------------
191− abitest-cc$(EXESUF) lib_path=..
192− abitest-tcc$(EXESUF) lib_path=..
191+ ./abitest-cc$(EXESUF) lib_path=..
192+ ./abitest-tcc$(EXESUF) lib_path=..
193193
194194 # targets for development
195195 %.bin: %.c tcc
tests/abitest.c+59−4
@@ -54,6 +54,7 @@ RET_PRIMITIVE_TEST(int, int) · 53 unmodified lines
5454 RET_PRIMITIVE_TEST(longlong, long long)
5555 RET_PRIMITIVE_TEST(float, float)
5656 RET_PRIMITIVE_TEST(double, double)
57+RET_PRIMITIVE_TEST(longdouble, long double)
5758
5859 typedef struct ret_2float_test_type_s {float x, y;} ret_2float_test_type;
5960 typedef ret_2float_test_type (*ret_2float_test_function_type) (ret_2float_test_type);
@@ -128,8 +129,52 @@ static int sret_test(void) { · 68 unmodified lines
128129 return run_callback(src, sret_test_callback);
129130 }
130131
132+typedef union one_member_union_test_type_u {int x;} one_member_union_test_type;
133+typedef one_member_union_test_type (*one_member_union_test_function_type) (one_member_union_test_type);
134+
135+static int one_member_union_test_callback(void *ptr) {
136+ one_member_union_test_function_type f = (one_member_union_test_function_type)ptr;
137+ one_member_union_test_type a, b;
138+ a.x = 34;
139+ b = f(a);
140+ return (b.x == a.x*2) ? 0 : -1;
141+}
142+
143+static int one_member_union_test(void) {
144+ const char *src =
145+ "typedef union one_member_union_test_type_u {int x;} one_member_union_test_type;\n"
146+ "one_member_union_test_type f(one_member_union_test_type a) {\n"
147+ " one_member_union_test_type b;\n"
148+ " b.x = a.x * 2;\n"
149+ " return b;\n"
150+ "}\n";
151+ return run_callback(src, one_member_union_test_callback);
152+}
153+
154+typedef union two_member_union_test_type_u {int x; long y;} two_member_union_test_type;
155+typedef two_member_union_test_type (*two_member_union_test_function_type) (two_member_union_test_type);
156+
157+static int two_member_union_test_callback(void *ptr) {
158+ two_member_union_test_function_type f = (two_member_union_test_function_type)ptr;
159+ two_member_union_test_type a, b;
160+ a.x = 34;
161+ b = f(a);
162+ return (b.x == a.x*2) ? 0 : -1;
163+}
164+
165+static int two_member_union_test(void) {
166+ const char *src =
167+ "typedef union two_member_union_test_type_u {int x; long y;} two_member_union_test_type;\n"
168+ "two_member_union_test_type f(two_member_union_test_type a) {\n"
169+ " two_member_union_test_type b;\n"
170+ " b.x = a.x * 2;\n"
171+ " return b;\n"
172+ "}\n";
173+ return run_callback(src, two_member_union_test_callback);
174+}
175+
131176 #define RUN_TEST(t) \
132− do { \
177+ if (!testname || (strcmp(#t, testname) == 0)) { \
133178 fputs(#t "... ", stdout); \
134179 fflush(stdout); \
135180 if (t() == 0) { \
@@ -138,20 +183,30 @@ static int sret_test(void) { · 2 unmodified lines
138183 fputs("failure\n", stdout); \
139184 retval = EXIT_FAILURE; \
140185 } \
141− } while (0);
186+ }
142187
143188 int main(int argc, char **argv) {
189+ int i;
190+ const char *testname = NULL;
144191 int retval = EXIT_SUCCESS;
192+
145193 /* if tcclib.h and libtcc1.a are not installed, where can we find them */
146− if (argc == 2 && !memcmp(argv[1], "lib_path=",9))
147− tccdir = argv[1] + 9;
194+ for (i = 1; i < argc; ++i) {
195+ if (!memcmp(argv[i], "lib_path=",9))
196+ tccdir = argv[i] + 9;
197+ else if (!memcmp(argv[i], "run_test=", 9))
198+ testname = argv[i] + 9;
199+ }
148200
149201 RUN_TEST(ret_int_test);
150202 RUN_TEST(ret_longlong_test);
151203 RUN_TEST(ret_float_test);
152204 RUN_TEST(ret_double_test);
205+ RUN_TEST(ret_longdouble_test);
153206 RUN_TEST(ret_2float_test);
154207 RUN_TEST(reg_pack_test);
155208 RUN_TEST(sret_test);
209+ RUN_TEST(one_member_union_test);
210+ RUN_TEST(two_member_union_test);
156211 return retval;
157212 }
x86_64-gen.c+243−62
@@ -602,6 +602,12 @@ void gen_offs_sp(int b, int r, int d) · 601 unmodified lines
602602 }
603603 }
604604
605+/* Return 1 if this function returns via an sret pointer, 0 otherwise */
606+ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) {
607+ *ret_align = 1; // Never have to re-align return values for x86-64
608+ return 1;
609+}
610+
605611 void gfunc_call(int nb_args)
606612 {
607613 int size, align, r, args_size, i, d, j, bt, struct_size;
@@ -817,6 +823,139 @@ static void gadd_sp(int val) · 209 unmodified lines
817823 }
818824 }
819825
826+typedef enum X86_64_Mode {
827+ x86_64_mode_none,
828+ x86_64_mode_memory,
829+ x86_64_mode_integer,
830+ x86_64_mode_sse,
831+ x86_64_mode_x87
832+} X86_64_Mode;
833+
834+static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b) {
835+ if (a == b)
836+ return a;
837+ else if (a == x86_64_mode_none)
838+ return b;
839+ else if (b == x86_64_mode_none)
840+ return a;
841+ else if ((a == x86_64_mode_memory) || (b == x86_64_mode_memory))
842+ return x86_64_mode_memory;
843+ else if ((a == x86_64_mode_integer) || (b == x86_64_mode_integer))
844+ return x86_64_mode_integer;
845+ else if ((a == x86_64_mode_x87) || (b == x86_64_mode_x87))
846+ return x86_64_mode_memory;
847+ else
848+ return x86_64_mode_sse;
849+}
850+
851+static X86_64_Mode classify_x86_64_inner(CType *ty) {
852+ X86_64_Mode mode;
853+ Sym *f;
854+
855+ if (ty->t & VT_BITFIELD)
856+ return x86_64_mode_memory;
857+
858+ switch (ty->t & VT_BTYPE) {
859+ case VT_VOID: return x86_64_mode_none;
860+
861+ case VT_INT:
862+ case VT_BYTE:
863+ case VT_SHORT:
864+ case VT_LLONG:
865+ case VT_BOOL:
866+ case VT_PTR:
867+ case VT_ENUM: return x86_64_mode_integer;
868+
869+ case VT_FLOAT:
870+ case VT_DOUBLE: return x86_64_mode_sse;
871+
872+ case VT_LDOUBLE: return x86_64_mode_x87;
873+
874+ case VT_STRUCT:
875+ f = ty->ref;
876+
877+ // Detect union
878+ if (f->next && (f->c == f->next->c))
879+ return x86_64_mode_memory;
880+
881+ mode = x86_64_mode_none;
882+ for (; f; f = f->next)
883+ mode = classify_x86_64_merge(mode, classify_x86_64_inner(&f->type));
884+
885+ return mode;
886+ }
887+}
888+
889+static X86_64_Mode classify_x86_64_arg(CType *ty, int *psize, int *reg_count) {
890+ X86_64_Mode mode;
891+ int size, align;
892+
893+ if (ty->t & VT_ARRAY) {
894+ *psize = 8;
895+ *reg_count = 1;
896+ return x86_64_mode_integer;
897+ }
898+
899+ size = type_size(ty, &align);
900+ size = (size + 7) & ~7;
901+ *psize = size;
902+ if (size > 16)
903+ return x86_64_mode_memory;
904+
905+ mode = classify_x86_64_inner(ty);
906+ if (reg_count) {
907+ if (mode == x86_64_mode_integer)
908+ *reg_count = size / 8;
909+ else if (mode == x86_64_mode_none)
910+ *reg_count = 0;
911+ else
912+ *reg_count = 1;
913+ }
914+ return mode;
915+}
916+
917+static X86_64_Mode classify_x86_64_arg_type(CType *vt, CType *ret, int *psize, int *reg_count) {
918+ X86_64_Mode mode;
919+ int size;
920+
921+ ret->ref = NULL;
922+
923+ mode = classify_x86_64_arg(vt, &size, reg_count);
924+ *psize = size;
925+ switch (mode) {
926+ case x86_64_mode_integer:
927+ if (size > 8)
928+ ret->t = VT_QLONG;
929+ else if (size > 4)
930+ ret->t = VT_LLONG;
931+ else
932+ ret->t = VT_INT;
933+ break;
934+
935+ case x86_64_mode_x87:
936+ ret->t = VT_LDOUBLE;
937+ break;
938+
939+ case x86_64_mode_sse:
940+ if (size > 8)
941+ ret->t = VT_QFLOAT;
942+ else if (size > 4)
943+ ret->t = VT_DOUBLE;
944+ else
945+ ret->t = VT_FLOAT;
946+ break;
947+ }
948+
949+ return mode;
950+}
951+
952+/* Return 1 if this function returns via an sret pointer, 0 otherwise */
953+int gfunc_sret(CType *vt, CType *ret, int *ret_align) {
954+ int size, reg_count;
955+ *ret_align = 1; // Never have to re-align return values for x86-64
956+ return (classify_x86_64_arg_type(vt, ret, &size, &reg_count) == x86_64_mode_memory);
957+}
958+
820959 #define REGN 6
821960 static const uint8_t arg_regs[REGN] = {
822961 TREG_RDI, TREG_RSI, TREG_RDX, TREG_RCX, TREG_R8, TREG_R9
@@ -827,7 +966,9 @@ static const uint8_t arg_regs[REGN] = { · 4 unmodified lines
827966 parameters and the function address. */
828967 void gfunc_call(int nb_args)
829968 {
830− int size, align, r, args_size, i;
969+ X86_64_Mode mode;
970+ CType type;
971+ int size, align, r, args_size, i, j, reg_count;
831972 int nb_reg_args = 0;
832973 int nb_sse_args = 0;
833974 int sse_reg, gen_reg;
@@ -835,17 +976,22 @@ void gfunc_call(int nb_args) · 1 unmodified line
835976 /* calculate the number of integer/float arguments */
836977 args_size = 0;
837978 for(i = 0; i < nb_args; i++) {
838− if ((vtop[-i].type.t & VT_BTYPE) == VT_STRUCT) {
839− args_size += type_size(&vtop[-i].type, &align);
840− args_size = (args_size + 7) & ~7;
841− } else if ((vtop[-i].type.t & VT_BTYPE) == VT_LDOUBLE) {
842− args_size += 16;
843− } else if (is_sse_float(vtop[-i].type.t)) {
844− nb_sse_args++;
845− if (nb_sse_args > 8) args_size += 8;
846− } else {
847− nb_reg_args++;
848− if (nb_reg_args > REGN) args_size += 8;
979+ mode = classify_x86_64_arg(&vtop[-i].type, &size, &reg_count);
980+ switch (mode) {
981+ case x86_64_mode_memory:
982+ case x86_64_mode_x87:
983+ args_size += size;
984+ break;
985+
986+ case x86_64_mode_sse:
987+ nb_sse_args += reg_count;
988+ if (nb_sse_args > 8) args_size += size;
989+ break;
990+
991+ case x86_64_mode_integer:
992+ nb_reg_args += reg_count;
993+ if (nb_reg_args > REGN) args_size += size;
994+ break;
849995 }
850996 }
851997
@@ -875,10 +1021,9 @@ void gfunc_call(int nb_args) · 23 unmodified lines
8751021 SValue tmp = vtop[0];
8761022 vtop[0] = vtop[-i];
8771023 vtop[-i] = tmp;
878− if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
879− size = type_size(&vtop->type, &align);
880− /* align to stack align size */
881− size = (size + 7) & ~7;
1024+ mode = classify_x86_64_arg(&vtop->type, &size, &reg_count);
1025+ switch (mode) {
1026+ case x86_64_mode_memory:
8821027 /* allocate the necessary size on stack */
8831028 o(0x48);
8841029 oad(0xec81, size); /* sub $xxx, %rsp */
@@ -890,7 +1035,9 @@ void gfunc_call(int nb_args) · 5 unmodified lines
8901035 vswap();
8911036 vstore();
8921037 args_size += size;
893− } else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
1038+ break;
1039+
1040+ case x86_64_mode_x87:
8941041 gv(RC_ST0);
8951042 size = LDOUBLE_SIZE;
8961043 oad(0xec8148, size); /* sub $xxx, %rsp */
@@ -898,25 +1045,30 @@ void gfunc_call(int nb_args) · 1 unmodified line
8981045 g(0x24);
8991046 g(0x00);
9001047 args_size += size;
901− } else if (is_sse_float(vtop->type.t)) {
902− int j = --sse_reg;
903− if (j >= 8) {
1048+ break;
1049+
1050+ case x86_64_mode_sse:
1051+ if (sse_reg > 8) {
9041052 gv(RC_FLOAT);
9051053 o(0x50); /* push $rax */
9061054 /* movq %xmm0, (%rsp) */
9071055 o(0x04d60f66);
9081056 o(0x24);
909− args_size += 8;
1057+ args_size += size;
9101058 }
911− } else {
912− int j = --gen_reg;
1059+ sse_reg -= reg_count;
1060+ break;
1061+
1062+ case x86_64_mode_integer:
9131063 /* simple type */
9141064 /* XXX: implicit cast ? */
915− if (j >= REGN) {
1065+ if (gen_reg > REGN) {
9161066 r = gv(RC_INT);
9171067 orex(0,r,0,0x50 + REG_VALUE(r)); /* push r */
918− args_size += 8;
1068+ args_size += size;
9191069 }
1070+ gen_reg -= reg_count;
1071+ break;
9201072 }
9211073
9221074 /* And swap the argument back to it's original position. */
@@ -935,29 +1087,45 @@ void gfunc_call(int nb_args) · 12 unmodified lines
9351087 gen_reg = nb_reg_args;
9361088 sse_reg = nb_sse_args;
9371089 for(i = 0; i < nb_args; i++) {
938− if ((vtop->type.t & VT_BTYPE) == VT_STRUCT ||
939− (vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
940− } else if (is_sse_float(vtop->type.t)) {
941− int j = --sse_reg;
942− if (j < 8) {
943− gv(RC_FLOAT); /* only one float register */
944− /* movaps %xmm0, %xmmN */
945− o(0x280f);
946− o(0xc0 + (sse_reg << 3));
1090+ mode = classify_x86_64_arg_type(&vtop->type, &type, &size, &reg_count);
1091+ /* Alter stack entry type so that gv() knows how to treat it */
1092+ vtop->type = type;
1093+ switch (mode) {
1094+ default:
1095+ break;
1096+
1097+ case x86_64_mode_sse:
1098+ if (sse_reg > 8) {
1099+ sse_reg -= reg_count;
1100+ } else {
1101+ for (j = 0; j < reg_count; ++j) {
1102+ --sse_reg;
1103+ gv(RC_FLOAT); /* only one float register */
1104+ /* movaps %xmm0, %xmmN */
1105+ o(0x280f);
1106+ o(0xc0 + (sse_reg << 3));
1107+ }
9471108 }
948− } else {
949− int j = --gen_reg;
1109+ break;
1110+
1111+ case x86_64_mode_integer:
9501112 /* simple type */
9511113 /* XXX: implicit cast ? */
952− if (j < REGN) {
953− int d = arg_regs[j];
954− r = gv(RC_INT);
955− if (j == 2 || j == 3)
956− /* j=2: r10, j=3: r11 */
957− d = j + 8;
958− orex(1,d,r,0x89); /* mov */
959− o(0xc0 + REG_VALUE(r) * 8 + REG_VALUE(d));
1114+ if (gen_reg > 8) {
1115+ gen_reg -= reg_count;
1116+ } else {
1117+ for (j = 0; j < reg_count; ++j) {
1118+ --gen_reg;
1119+ int d = arg_regs[gen_reg];
1120+ r = gv(RC_INT);
1121+ if (gen_reg == 2 || gen_reg == 3)
1122+ /* gen_reg=2: r10, gen_reg=3: r11 */
1123+ d = gen_reg + 8;
1124+ orex(1,d,r,0x89); /* mov */
1125+ o(0xc0 + REG_VALUE(r) * 8 + REG_VALUE(d));
1126+ }
9601127 }
1128+ break;
9611129 }
9621130 vtop--;
9631131 }
@@ -994,7 +1162,8 @@ static void push_arg_reg(int i) { · 30 unmodified lines
9941162 /* generate function prolog of type 't' */
9951163 void gfunc_prolog(CType *func_type)
9961164 {
997− int i, addr, align, size;
1165+ X86_64_Mode mode;
1166+ int i, addr, align, size, reg_count;
9981167 int param_index, param_addr, reg_param_index, sse_param_index;
9991168 Sym *sym;
10001169 CType *type;
@@ -1070,7 +1239,8 @@ void gfunc_prolog(CType *func_type) · 69 unmodified lines
10701239 /* if the function returns a structure, then add an
10711240 implicit pointer parameter */
10721241 func_vt = sym->type;
1073− if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
1242+ mode = classify_x86_64_arg(&func_vt, &size, &reg_count);
1243+ if (mode == x86_64_mode_memory) {
10741244 push_arg_reg(reg_param_index);
10751245 param_addr = loc;
10761246
@@ -1081,35 +1251,46 @@ void gfunc_prolog(CType *func_type) · 4 unmodified lines
10811251 /* define parameters */
10821252 while ((sym = sym->next) != NULL) {
10831253 type = &sym->type;
1084− size = type_size(type, &align);
1085− size = (size + 7) & ~7;
1086− if (is_sse_float(type->t)) {
1087− if (sse_param_index < 8) {
1254+ mode = classify_x86_64_arg(type, &size, &reg_count);
1255+ switch (mode) {
1256+ case x86_64_mode_sse:
1257+ if (sse_param_index + reg_count <= 8) {
10881258 /* save arguments passed by register */
1089− loc -= 8;
1090− o(0xd60f66); /* movq */
1091− gen_modrm(sse_param_index, VT_LOCAL, NULL, loc);
1259+ for (i = 0; i < reg_count; ++i) {
1260+ loc -= 8;
1261+ o(0xd60f66); /* movq */
1262+ gen_modrm(sse_param_index, VT_LOCAL, NULL, loc);
1263+ ++sse_param_index;
1264+ }
10921265 param_addr = loc;
10931266 } else {
10941267 param_addr = addr;
10951268 addr += size;
1269+ sse_param_index += reg_count;
10961270 }
1097− sse_param_index++;
1098−
1099− } else if ((type->t & VT_BTYPE) == VT_STRUCT ||
1100− (type->t & VT_BTYPE) == VT_LDOUBLE) {
1271+ break;
1272+
1273+ case x86_64_mode_memory:
1274+ case x86_64_mode_x87:
11011275 param_addr = addr;
11021276 addr += size;
1103− } else {
1104− if (reg_param_index < REGN) {
1277+ break;
1278+
1279+ case x86_64_mode_integer: {
1280+ if (reg_param_index + reg_count <= REGN) {
11051281 /* save arguments passed by register */
1106− push_arg_reg(reg_param_index);
1282+ for (i = 0; i < reg_count; ++i) {
1283+ push_arg_reg(reg_param_index);
1284+ ++reg_param_index;
1285+ }
11071286 param_addr = loc;
11081287 } else {
11091288 param_addr = addr;
1110− addr += 8;
1289+ addr += size;
1290+ reg_param_index += reg_count;
11111291 }
1112− reg_param_index++;
1292+ break;
1293+ }
11131294 }
11141295 sym_push(sym->v & ~SYM_FIELD, type,
11151296 VT_LOCAL | VT_LVAL, param_addr);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t