History

tccgen: factor out gfunc_return

grischka committed 9 years ago

Commit 68666ee1 parent f077d165 files · +199 −212Browse files

Unified · Split

5 files
  1. arm64-gen.c +7 −6
  2. i386-gen.c +11 −10
  3. tcc.h +1 −2
  4. tccgen.c +172 −182
  5. x86_64-gen.c +8 −12
arm64-gen.c+7−6
@@ -1193,9 +1193,9 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, · 1192 unmodified lines
11931193 return 0;
11941194 }
11951195
1196−ST_FUNC void greturn(void)
1196+ST_FUNC void gfunc_return(CType *func_type)
11971197 {
1198− CType *t = &func_vt;
1198+ CType *t = func_type;
11991199 unsigned long a;
12001200
12011201 arm64_pcs(0, &t, &a);
@@ -1203,8 +1203,8 @@ ST_FUNC void greturn(void) · 1 unmodified line
12031203 case -1:
12041204 break;
12051205 case 0:
1206− if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
1207− int align, size = type_size(&func_vt, &align);
1206+ if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
1207+ int align, size = type_size(func_type, &align);
12081208 gaddrof();
12091209 gv(RC_R(0));
12101210 arm64_ldrs(0, size);
@@ -1213,7 +1213,7 @@ ST_FUNC void greturn(void) · 2 unmodified lines
12131213 gv(RC_IRET);
12141214 break;
12151215 case 1: {
1216− CType type = func_vt;
1216+ CType type = *func_type;
12171217 mk_pointer(&type);
12181218 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
12191219 indir();
@@ -1222,7 +1222,7 @@ ST_FUNC void greturn(void) · 2 unmodified lines
12221222 break;
12231223 }
12241224 case 16:
1225− if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
1225+ if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
12261226 uint32_t j, sz, n = arm64_hfa(&vtop->type, &sz);
12271227 gaddrof();
12281228 gv(RC_R(0));
@@ -1237,6 +1237,7 @@ ST_FUNC void greturn(void) · 8 unmodified lines
12371237 default:
12381238 assert(0);
12391239 }
1240+ vtop--;
12401241 }
12411242
12421243 ST_FUNC void gfunc_epilog(void)
i386-gen.c+11−10
@@ -396,21 +396,21 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int · 395 unmodified lines
396396 {
397397 #ifdef TCC_TARGET_PE
398398 int size, align;
399−
400399 *ret_align = 1; // Never have to re-align return values for x86
401400 *regsize = 4;
402401 size = type_size(vt, &align);
403− if (size > 8) {
402+ if (size > 8 || (size & (size - 1)))
404403 return 0;
405− } else if (size > 4) {
406− ret->ref = NULL;
404+ if (size == 8)
407405 ret->t = VT_LLONG;
408− return 1;
409− } else {
410− ret->ref = NULL;
406+ else if (size == 4)
411407 ret->t = VT_INT;
412− return 1;
413− }
408+ else if (size == 2)
409+ ret->t = VT_SHORT;
410+ else
411+ ret->t = VT_BYTE;
412+ ret->ref = NULL;
413+ return 1;
414414 #else
415415 *ret_align = 1; // Never have to re-align return values for x86
416416 return 0;
@@ -547,7 +547,8 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 130 unmodified lines
547547 func_var = (sym->c == FUNC_ELLIPSIS);
548548 #ifdef TCC_TARGET_PE
549549 size = type_size(&func_vt,&align);
550− if (((func_vt.t & VT_BTYPE) == VT_STRUCT) && (size > 8)) {
550+ if (((func_vt.t & VT_BTYPE) == VT_STRUCT)
551+ && (size > 8 || (size & (size - 1)))) {
551552 #else
552553 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
553554 #endif
tcc.h+1−2
@@ -1273,7 +1273,6 @@ ST_FUNC void check_vstack(void); · 1272 unmodified lines
12731273 ST_INLN int is_float(int t);
12741274 ST_FUNC int ieee_finite(double d);
12751275 ST_FUNC void test_lvalue(void);
1276−ST_FUNC void swap(int *p, int *q);
12771276 ST_FUNC void vpushi(int v);
12781277 ST_FUNC Sym *external_global_sym(int v, CType *type, int r);
12791278 ST_FUNC void vset(CType *type, int r, long v);
@@ -1519,7 +1518,7 @@ ST_FUNC void gen_cvt_itof1(int t); · 239 unmodified lines
15191518 #ifdef TCC_TARGET_ARM64
15201519 ST_FUNC void gen_cvt_sxtw(void);
15211520 ST_FUNC void gen_opl(int op);
1522−ST_FUNC void greturn(void);
1521+ST_FUNC void gfunc_return(CType *func_type);
15231522 ST_FUNC void gen_va_start(void);
15241523 ST_FUNC void gen_va_arg(CType *t);
15251524 ST_FUNC void gen_clear_cache(void);
tccgen.c+172−182
@@ -559,14 +559,6 @@ static void apply_visibility(Sym *sym, CType *type) · 558 unmodified lines
559559
560560 /* ------------------------------------------------------------------------- */
561561
562−ST_FUNC void swap(int *p, int *q)
563−{
564− int t;
565− t = *p;
566− *p = *q;
567− *q = t;
568−}
569−
570562 static void vsetc(CType *type, int r, CValue *vc)
571563 {
572564 int v;
@@ -583,12 +575,15 @@ static void vsetc(CType *type, int r, CValue *vc) · 10 unmodified lines
583575 as their value might still be used for real. All values
584576 we push under nocode_wanted will eventually be popped
585577 again, so that the VT_CMP/VT_JMP value will be in vtop
586− when code is unsuppressed again. */
578+ when code is unsuppressed again.
579+
580+ Same logic below in vswap(); */
587581 if (vtop >= vstack && !nocode_wanted) {
588582 v = vtop->r & VT_VALMASK;
589583 if (v == VT_CMP || (v & ~1) == VT_JMP)
590584 gv(RC_INT);
591585 }
586+
592587 vtop++;
593588 vtop->type = *type;
594589 vtop->r = r;
@@ -597,6 +592,38 @@ static void vsetc(CType *type, int r, CValue *vc) · 2 unmodified lines
597592 vtop->sym = NULL;
598593 }
599594
595+ST_FUNC void vswap(void)
596+{
597+ SValue tmp;
598+ /* cannot vswap cpu flags. See comment at vsetc() above */
599+ if (vtop >= vstack && !nocode_wanted) {
600+ int v = vtop->r & VT_VALMASK;
601+ if (v == VT_CMP || (v & ~1) == VT_JMP)
602+ gv(RC_INT);
603+ }
604+ tmp = vtop[0];
605+ vtop[0] = vtop[-1];
606+ vtop[-1] = tmp;
607+}
608+
609+/* pop stack value */
610+ST_FUNC void vpop(void)
611+{
612+ int v;
613+ v = vtop->r & VT_VALMASK;
614+#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
615+ /* for x86, we need to pop the FP stack */
616+ if (v == TREG_ST0) {
617+ o(0xd8dd); /* fstp %st(0) */
618+ } else
619+#endif
620+ if (v == VT_JMP || v == VT_JMPI) {
621+ /* need to put correct jump if && or || without test */
622+ gsym(vtop->c.i);
623+ }
624+ vtop--;
625+}
626+
600627 /* push constant of type "type" with useless value */
601628 ST_FUNC void vpush(CType *type)
602629 {
@@ -637,6 +664,71 @@ static inline void vpushll(long long v) · 34 unmodified lines
637664 vpush64(VT_LLONG, v);
638665 }
639666
667+ST_FUNC void vset(CType *type, int r, long v)
668+{
669+ CValue cval;
670+
671+ cval.i = v;
672+ vsetc(type, r, &cval);
673+}
674+
675+static void vseti(int r, int v)
676+{
677+ CType type;
678+ type.t = VT_INT;
679+ type.ref = 0;
680+ vset(&type, r, v);
681+}
682+
683+ST_FUNC void vpushv(SValue *v)
684+{
685+ if (vtop >= vstack + (VSTACK_SIZE - 1))
686+ tcc_error("memory full (vstack)");
687+ vtop++;
688+ *vtop = *v;
689+}
690+
691+static void vdup(void)
692+{
693+ vpushv(vtop);
694+}
695+
696+/* rotate n first stack elements to the bottom
697+ I1 ... In -> I2 ... In I1 [top is right]
698+*/
699+ST_FUNC void vrotb(int n)
700+{
701+ int i;
702+ SValue tmp;
703+
704+ tmp = vtop[-n + 1];
705+ for(i=-n+1;i!=0;i++)
706+ vtop[i] = vtop[i+1];
707+ vtop[0] = tmp;
708+}
709+
710+/* rotate the n elements before entry e towards the top
711+ I1 ... In ... -> In I1 ... I(n-1) ... [top is right]
712+ */
713+ST_FUNC void vrote(SValue *e, int n)
714+{
715+ int i;
716+ SValue tmp;
717+
718+ tmp = *e;
719+ for(i = 0;i < n - 1; i++)
720+ e[-i] = e[-i - 1];
721+ e[-n + 1] = tmp;
722+}
723+
724+/* rotate n first stack elements to the top
725+ I1 ... In -> In I1 ... I(n-1) [top is right]
726+ */
727+ST_FUNC void vrott(int n)
728+{
729+ vrote(vtop, n);
730+}
731+
640732 /* push a symbol value of TYPE */
641733 static inline void vpushsym(CType *type, Sym *sym)
642734 {
@@ -715,56 +807,6 @@ ST_FUNC void vpush_global_sym(CType *type, int v) · 72 unmodified lines
715807 vpushsym(type, external_global_sym(v, type, 0));
716808 }
717809
718−ST_FUNC void vset(CType *type, int r, long v)
719−{
720− CValue cval;
721−
722− cval.i = v;
723− vsetc(type, r, &cval);
724−}
725−
726−static void vseti(int r, int v)
727−{
728− CType type;
729− type.t = VT_INT;
730− type.ref = 0;
731− vset(&type, r, v);
732−}
733−
734−ST_FUNC void vswap(void)
735−{
736− SValue tmp;
737− /* cannot let cpu flags if other instruction are generated. Also
738− avoid leaving VT_JMP anywhere except on the top of the stack
739− because it would complicate the code generator. */
740− if (vtop >= vstack) {
741− int v = vtop->r & VT_VALMASK;
742− if (v == VT_CMP || (v & ~1) == VT_JMP)
743− gv(RC_INT);
744− }
745− tmp = vtop[0];
746− vtop[0] = vtop[-1];
747− vtop[-1] = tmp;
748−
749−/* XXX: +2% overall speed possible with optimized memswap
750− *
751− * memswap(&vtop[0], &vtop[1], sizeof *vtop);
752− */
753−}
754−
755−ST_FUNC void vpushv(SValue *v)
756−{
757− if (vtop >= vstack + (VSTACK_SIZE - 1))
758− tcc_error("memory full (vstack)");
759− vtop++;
760− *vtop = *v;
761−}
762−
763−static void vdup(void)
764−{
765− vpushv(vtop);
766−}
767−
768810 /* save registers up to (vtop - n) stack entry */
769811 ST_FUNC void save_regs(int n)
770812 {
@@ -1297,60 +1339,6 @@ static void lbuild(int t) · 526 unmodified lines
12971339 }
12981340 #endif
12991341
1300−/* rotate n first stack elements to the bottom
1301− I1 ... In -> I2 ... In I1 [top is right]
1302−*/
1303−ST_FUNC void vrotb(int n)
1304−{
1305− int i;
1306− SValue tmp;
1307−
1308− tmp = vtop[-n + 1];
1309− for(i=-n+1;i!=0;i++)
1310− vtop[i] = vtop[i+1];
1311− vtop[0] = tmp;
1312−}
1313−
1314−/* rotate the n elements before entry e towards the top
1315− I1 ... In ... -> In I1 ... I(n-1) ... [top is right]
1316− */
1317−ST_FUNC void vrote(SValue *e, int n)
1318−{
1319− int i;
1320− SValue tmp;
1321−
1322− tmp = *e;
1323− for(i = 0;i < n - 1; i++)
1324− e[-i] = e[-i - 1];
1325− e[-n + 1] = tmp;
1326−}
1327−
1328−/* rotate n first stack elements to the top
1329− I1 ... In -> In I1 ... I(n-1) [top is right]
1330− */
1331−ST_FUNC void vrott(int n)
1332−{
1333− vrote(vtop, n);
1334−}
1335−
1336−/* pop stack value */
1337−ST_FUNC void vpop(void)
1338−{
1339− int v;
1340− v = vtop->r & VT_VALMASK;
1341−#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1342− /* for x86, we need to pop the FP stack */
1343− if (v == TREG_ST0) {
1344− o(0xd8dd); /* fstp %st(0) */
1345− } else
1346−#endif
1347− if (v == VT_JMP || v == VT_JMPI) {
1348− /* need to put correct jump if && or || without test */
1349− gsym(vtop->c.i);
1350− }
1351− vtop--;
1352−}
1353−
13541342 /* convert stack entry to register and duplicate its value in another
13551343 register */
13561344 static void gv_dup(void)
@@ -2025,7 +2013,7 @@ redo: · 668 unmodified lines
20252013 /* Put pointer as first operand */
20262014 if (bt2 == VT_PTR) {
20272015 vswap();
2028− swap(&t1, &t2);
2016+ t = t1, t1 = t2, t2 = t;
20292017 }
20302018 #if PTR_SIZE == 4
20312019 if ((vtop[0].type.t & VT_BTYPE) == VT_LLONG)
@@ -4668,11 +4656,11 @@ ST_FUNC void unary(void) · 2636 unmodified lines
46684656 subtract(-0, x). */
46694657 vpush(&vtop->type);
46704658 if (t == VT_FLOAT)
4671− vtop->c.f = -0.0f;
4659+ vtop->c.f = -1.0 * 0.0;
46724660 else if (t == VT_DOUBLE)
4673− vtop->c.d = -0.0;
4661+ vtop->c.d = -1.0 * 0.0;
46744662 else
4675− vtop->c.ld = -0.0;
4663+ vtop->c.ld = -1.0 * 0.0;
46764664 } else
46774665 vpushi(0);
46784666 vswap();
@@ -5460,6 +5448,72 @@ static void label_or_decl(int l) · 781 unmodified lines
54605448 decl(l);
54615449 }
54625450
5451+#ifndef TCC_TARGET_ARM64
5452+static void gfunc_return(CType *func_type)
5453+{
5454+ if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
5455+ CType type, ret_type;
5456+ int ret_align, ret_nregs, regsize;
5457+ ret_nregs = gfunc_sret(func_type, func_var, &ret_type,
5458+ &ret_align, &regsize);
5459+ if (0 == ret_nregs) {
5460+ /* if returning structure, must copy it to implicit
5461+ first pointer arg location */
5462+ type = *func_type;
5463+ mk_pointer(&type);
5464+ vset(&type, VT_LOCAL | VT_LVAL, func_vc);
5465+ indir();
5466+ vswap();
5467+ /* copy structure value to pointer */
5468+ vstore();
5469+ } else {
5470+ /* returning structure packed into registers */
5471+ int r, size, addr, align;
5472+ size = type_size(func_type,&align);
5473+ if ((vtop->r != (VT_LOCAL | VT_LVAL) ||
5474+ (vtop->c.i & (ret_align-1)))
5475+ && (align & (ret_align-1))) {
5476+ loc = (loc - size) & -ret_align;
5477+ addr = loc;
5478+ type = *func_type;
5479+ vset(&type, VT_LOCAL | VT_LVAL, addr);
5480+ vswap();
5481+ vstore();
5482+ vpop();
5483+ vset(&ret_type, VT_LOCAL | VT_LVAL, addr);
5484+ }
5485+ vtop->type = ret_type;
5486+ if (is_float(ret_type.t))
5487+ r = rc_fret(ret_type.t);
5488+ else
5489+ r = RC_IRET;
5490+
5491+ if (ret_nregs == 1)
5492+ gv(r);
5493+ else {
5494+ for (;;) {
5495+ vdup();
5496+ gv(r);
5497+ vpop();
5498+ if (--ret_nregs == 0)
5499+ break;
5500+ /* We assume that when a structure is returned in multiple
5501+ registers, their classes are consecutive values of the
5502+ suite s(n) = 2^n */
5503+ r <<= 1;
5504+ vtop->c.i += regsize;
5505+ }
5506+ }
5507+ }
5508+ } else if (is_float(func_type->t)) {
5509+ gv(rc_fret(func_type->t));
5510+ } else {
5511+ gv(RC_IRET);
5512+ }
5513+ vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5514+}
5515+#endif
5516+
54635517 static int case_cmp(const void *pa, const void *pb)
54645518 {
54655519 int64_t a = (*(struct case_t**) pa)->v1;
@@ -5655,71 +5709,7 @@ static void block(int *bsym, int *csym, int is_expr) · 189 unmodified lines
56555709 if (tok != ';') {
56565710 gexpr();
56575711 gen_assign_cast(&func_vt);
5658−#ifdef TCC_TARGET_ARM64
5659− // Perhaps it would be better to use this for all backends:
5660− greturn();
5661−#else
5662− if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
5663− CType type, ret_type;
5664− int ret_align, ret_nregs, regsize;
5665− ret_nregs = gfunc_sret(&func_vt, func_var, &ret_type,
5666− &ret_align, &regsize);
5667− if (0 == ret_nregs) {
5668− /* if returning structure, must copy it to implicit
5669− first pointer arg location */
5670− type = func_vt;
5671− mk_pointer(&type);
5672− vset(&type, VT_LOCAL | VT_LVAL, func_vc);
5673− indir();
5674− vswap();
5675− /* copy structure value to pointer */
5676− vstore();
5677− } else {
5678− /* returning structure packed into registers */
5679− int r, size, addr, align;
5680− size = type_size(&func_vt,&align);
5681− if ((vtop->r != (VT_LOCAL | VT_LVAL) ||
5682− (vtop->c.i & (ret_align-1)))
5683− && (align & (ret_align-1))) {
5684− loc = (loc - size) & -ret_align;
5685− addr = loc;
5686− type = func_vt;
5687− vset(&type, VT_LOCAL | VT_LVAL, addr);
5688− vswap();
5689− vstore();
5690− vpop();
5691− vset(&ret_type, VT_LOCAL | VT_LVAL, addr);
5692− }
5693− vtop->type = ret_type;
5694− if (is_float(ret_type.t))
5695− r = rc_fret(ret_type.t);
5696− else
5697− r = RC_IRET;
5698−
5699− if (ret_nregs == 1)
5700− gv(r);
5701− else {
5702− for (;;) {
5703− vdup();
5704− gv(r);
5705− vpop();
5706− if (--ret_nregs == 0)
5707− break;
5708− /* We assume that when a structure is returned in multiple
5709− registers, their classes are consecutive values of the
5710− suite s(n) = 2^n */
5711− r <<= 1;
5712− vtop->c.i += regsize;
5713− }
5714− }
5715− }
5716− } else if (is_float(func_vt.t)) {
5717− gv(rc_fret(func_vt.t));
5718− } else {
5719− gv(RC_IRET);
5720− }
5721−#endif
5722− vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
5712+ gfunc_return(&func_vt);
57235713 }
57245714 skip(';');
57255715 /* jump unless last stmt in top-level block */
x86_64-gen.c+8−12
@@ -752,25 +752,21 @@ void gen_offs_sp(int b, int r, int d) · 751 unmodified lines
752752 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize)
753753 {
754754 int size, align;
755− *regsize = 8;
756755 *ret_align = 1; // Never have to re-align return values for x86-64
756+ *regsize = 8;
757757 size = type_size(vt, &align);
758− ret->ref = NULL;
759− if (size > 8) {
758+ if (size > 8 || (size & (size - 1)))
760759 return 0;
761− } else if (size > 4) {
760+ if (size == 8)
762761 ret->t = VT_LLONG;
763− return 1;
764− } else if (size > 2) {
762+ else if (size == 4)
765763 ret->t = VT_INT;
766− return 1;
767− } else if (size > 1) {
764+ else if (size == 2)
768765 ret->t = VT_SHORT;
769− return 1;
770− } else {
766+ else
771767 ret->t = VT_BYTE;
772− return 1;
773− }
768+ ret->ref = NULL;
769+ return 1;
774770 }
775771
776772 static int is_sse_float(int t) {

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