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
1193 return 0;1193 return 0;
1194}1194}
1195 1195
1196ST_FUNC void greturn(void)1196ST_FUNC void gfunc_return(CType *func_type)
1197{1197{
1198 CType *t = &func_vt;1198 CType *t = func_type;
1199 unsigned long a;1199 unsigned long a;
1200 1200
1201 arm64_pcs(0, &t, &a);1201 arm64_pcs(0, &t, &a);
@@ -1203,8 +1203,8 @@ ST_FUNC void greturn(void) · 1 unmodified line
1203 case -1:1203 case -1:
1204 break;1204 break;
1205 case 0:1205 case 0:
1206 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {1206 if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
1207 int align, size = type_size(&func_vt, &align);1207 int align, size = type_size(func_type, &align);
1208 gaddrof();1208 gaddrof();
1209 gv(RC_R(0));1209 gv(RC_R(0));
1210 arm64_ldrs(0, size);1210 arm64_ldrs(0, size);
@@ -1213,7 +1213,7 @@ ST_FUNC void greturn(void) · 2 unmodified lines
1213 gv(RC_IRET);1213 gv(RC_IRET);
1214 break;1214 break;
1215 case 1: {1215 case 1: {
1216 CType type = func_vt;1216 CType type = *func_type;
1217 mk_pointer(&type);1217 mk_pointer(&type);
1218 vset(&type, VT_LOCAL | VT_LVAL, func_vc);1218 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
1219 indir();1219 indir();
@@ -1222,7 +1222,7 @@ ST_FUNC void greturn(void) · 2 unmodified lines
1222 break;1222 break;
1223 }1223 }
1224 case 16:1224 case 16:
1225 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {1225 if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
1226 uint32_t j, sz, n = arm64_hfa(&vtop->type, &sz);1226 uint32_t j, sz, n = arm64_hfa(&vtop->type, &sz);
1227 gaddrof();1227 gaddrof();
1228 gv(RC_R(0));1228 gv(RC_R(0));
@@ -1237,6 +1237,7 @@ ST_FUNC void greturn(void) · 8 unmodified lines
1237 default:1237 default:
1238 assert(0);1238 assert(0);
1239 }1239 }
1240 vtop--;
1240}1241}
1241 1242
1242ST_FUNC void gfunc_epilog(void)1243ST_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
396{396{
397#ifdef TCC_TARGET_PE397#ifdef TCC_TARGET_PE
398 int size, align;398 int size, align;
399
400 *ret_align = 1; // Never have to re-align return values for x86399 *ret_align = 1; // Never have to re-align return values for x86
401 *regsize = 4;400 *regsize = 4;
402 size = type_size(vt, &align);401 size = type_size(vt, &align);
403 if (size > 8) {402 if (size > 8 || (size & (size - 1)))
404 return 0;403 return 0;
405 } else if (size > 4) {404 if (size == 8)
406 ret->ref = NULL;
407 ret->t = VT_LLONG;405 ret->t = VT_LLONG;
408 return 1;406 else if (size == 4)
409 } else {
410 ret->ref = NULL;
411 ret->t = VT_INT;407 ret->t = VT_INT;
412 return 1;408 else if (size == 2)
413 }409 ret->t = VT_SHORT;
410 else
411 ret->t = VT_BYTE;
412 ret->ref = NULL;
413 return 1;
414#else414#else
415 *ret_align = 1; // Never have to re-align return values for x86415 *ret_align = 1; // Never have to re-align return values for x86
416 return 0;416 return 0;
@@ -547,7 +547,8 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 130 unmodified lines
547 func_var = (sym->c == FUNC_ELLIPSIS);547 func_var = (sym->c == FUNC_ELLIPSIS);
548#ifdef TCC_TARGET_PE548#ifdef TCC_TARGET_PE
549 size = type_size(&func_vt,&align);549 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)))) {
551#else552#else
552 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {553 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
553#endif554#endif
tcc.h+1−2
@@ -1273,7 +1273,6 @@ ST_FUNC void check_vstack(void); · 1272 unmodified lines
1273ST_INLN int is_float(int t);1273ST_INLN int is_float(int t);
1274ST_FUNC int ieee_finite(double d);1274ST_FUNC int ieee_finite(double d);
1275ST_FUNC void test_lvalue(void);1275ST_FUNC void test_lvalue(void);
1276ST_FUNC void swap(int *p, int *q);
1277ST_FUNC void vpushi(int v);1276ST_FUNC void vpushi(int v);
1278ST_FUNC Sym *external_global_sym(int v, CType *type, int r);1277ST_FUNC Sym *external_global_sym(int v, CType *type, int r);
1279ST_FUNC void vset(CType *type, int r, long v);1278ST_FUNC void vset(CType *type, int r, long v);
@@ -1519,7 +1518,7 @@ ST_FUNC void gen_cvt_itof1(int t); · 239 unmodified lines
1519#ifdef TCC_TARGET_ARM641518#ifdef TCC_TARGET_ARM64
1520ST_FUNC void gen_cvt_sxtw(void);1519ST_FUNC void gen_cvt_sxtw(void);
1521ST_FUNC void gen_opl(int op);1520ST_FUNC void gen_opl(int op);
1522ST_FUNC void greturn(void);1521ST_FUNC void gfunc_return(CType *func_type);
1523ST_FUNC void gen_va_start(void);1522ST_FUNC void gen_va_start(void);
1524ST_FUNC void gen_va_arg(CType *t);1523ST_FUNC void gen_va_arg(CType *t);
1525ST_FUNC void gen_clear_cache(void);1524ST_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
559 559
560/* ------------------------------------------------------------------------- */560/* ------------------------------------------------------------------------- */
561 561
562ST_FUNC void swap(int *p, int *q)
563{
564 int t;
565 t = *p;
566 *p = *q;
567 *q = t;
568}
569
570static void vsetc(CType *type, int r, CValue *vc)562static void vsetc(CType *type, int r, CValue *vc)
571{563{
572 int v;564 int v;
@@ -583,12 +575,15 @@ static void vsetc(CType *type, int r, CValue *vc) · 10 unmodified lines
583 as their value might still be used for real. All values575 as their value might still be used for real. All values
584 we push under nocode_wanted will eventually be popped576 we push under nocode_wanted will eventually be popped
585 again, so that the VT_CMP/VT_JMP value will be in vtop577 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(); */
587 if (vtop >= vstack && !nocode_wanted) {581 if (vtop >= vstack && !nocode_wanted) {
588 v = vtop->r & VT_VALMASK;582 v = vtop->r & VT_VALMASK;
589 if (v == VT_CMP || (v & ~1) == VT_JMP)583 if (v == VT_CMP || (v & ~1) == VT_JMP)
590 gv(RC_INT);584 gv(RC_INT);
591 }585 }
586
592 vtop++;587 vtop++;
593 vtop->type = *type;588 vtop->type = *type;
594 vtop->r = r;589 vtop->r = r;
@@ -597,6 +592,38 @@ static void vsetc(CType *type, int r, CValue *vc) · 2 unmodified lines
597 vtop->sym = NULL;592 vtop->sym = NULL;
598}593}
599 594
595ST_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 */
610ST_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
600/* push constant of type "type" with useless value */627/* push constant of type "type" with useless value */
601ST_FUNC void vpush(CType *type)628ST_FUNC void vpush(CType *type)
602{629{
@@ -637,6 +664,71 @@ static inline void vpushll(long long v) · 34 unmodified lines
637 vpush64(VT_LLONG, v);664 vpush64(VT_LLONG, v);
638}665}
639 666
667ST_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
675static 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
683ST_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
691static 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*/
699ST_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 */
713ST_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 */
727ST_FUNC void vrott(int n)
728{
729 vrote(vtop, n);
730}
731
640/* push a symbol value of TYPE */732/* push a symbol value of TYPE */
641static inline void vpushsym(CType *type, Sym *sym)733static inline void vpushsym(CType *type, Sym *sym)
642{734{
@@ -715,56 +807,6 @@ ST_FUNC void vpush_global_sym(CType *type, int v) · 72 unmodified lines
715 vpushsym(type, external_global_sym(v, type, 0));807 vpushsym(type, external_global_sym(v, type, 0));
716}808}
717 809
718ST_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
726static 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
734ST_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
755ST_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
763static void vdup(void)
764{
765 vpushv(vtop);
766}
767
768/* save registers up to (vtop - n) stack entry */810/* save registers up to (vtop - n) stack entry */
769ST_FUNC void save_regs(int n)811ST_FUNC void save_regs(int n)
770{812{
@@ -1297,60 +1339,6 @@ static void lbuild(int t) · 526 unmodified lines
1297}1339}
1298#endif1340#endif
1299 1341
1300/* rotate n first stack elements to the bottom
1301 I1 ... In -> I2 ... In I1 [top is right]
1302*/
1303ST_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 */
1317ST_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 */
1331ST_FUNC void vrott(int n)
1332{
1333 vrote(vtop, n);
1334}
1335
1336/* pop stack value */
1337ST_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
1354/* convert stack entry to register and duplicate its value in another1342/* convert stack entry to register and duplicate its value in another
1355 register */1343 register */
1356static void gv_dup(void)1344static void gv_dup(void)
@@ -2025,7 +2013,7 @@ redo: · 668 unmodified lines
2025 /* Put pointer as first operand */2013 /* Put pointer as first operand */
2026 if (bt2 == VT_PTR) {2014 if (bt2 == VT_PTR) {
2027 vswap();2015 vswap();
2028 swap(&t1, &t2);2016 t = t1, t1 = t2, t2 = t;
2029 }2017 }
2030#if PTR_SIZE == 42018#if PTR_SIZE == 4
2031 if ((vtop[0].type.t & VT_BTYPE) == VT_LLONG)2019 if ((vtop[0].type.t & VT_BTYPE) == VT_LLONG)
@@ -4668,11 +4656,11 @@ ST_FUNC void unary(void) · 2636 unmodified lines
4668 subtract(-0, x). */4656 subtract(-0, x). */
4669 vpush(&vtop->type);4657 vpush(&vtop->type);
4670 if (t == VT_FLOAT)4658 if (t == VT_FLOAT)
4671 vtop->c.f = -0.0f;4659 vtop->c.f = -1.0 * 0.0;
4672 else if (t == VT_DOUBLE)4660 else if (t == VT_DOUBLE)
4673 vtop->c.d = -0.0;4661 vtop->c.d = -1.0 * 0.0;
4674 else4662 else
4675 vtop->c.ld = -0.0;4663 vtop->c.ld = -1.0 * 0.0;
4676 } else4664 } else
4677 vpushi(0);4665 vpushi(0);
4678 vswap();4666 vswap();
@@ -5460,6 +5448,72 @@ static void label_or_decl(int l) · 781 unmodified lines
5460 decl(l);5448 decl(l);
5461}5449}
5462 5450
5451#ifndef TCC_TARGET_ARM64
5452static 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
5463static int case_cmp(const void *pa, const void *pb)5517static int case_cmp(const void *pa, const void *pb)
5464{5518{
5465 int64_t a = (*(struct case_t**) pa)->v1;5519 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
5655 if (tok != ';') {5709 if (tok != ';') {
5656 gexpr();5710 gexpr();
5657 gen_assign_cast(&func_vt);5711 gen_assign_cast(&func_vt);
5658#ifdef TCC_TARGET_ARM645712 gfunc_return(&func_vt);
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 */
5723 }5713 }
5724 skip(';');5714 skip(';');
5725 /* jump unless last stmt in top-level block */5715 /* 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
752ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize)752ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize)
753{753{
754 int size, align;754 int size, align;
755 *regsize = 8;
756 *ret_align = 1; // Never have to re-align return values for x86-64755 *ret_align = 1; // Never have to re-align return values for x86-64
756 *regsize = 8;
757 size = type_size(vt, &align);757 size = type_size(vt, &align);
758 ret->ref = NULL;758 if (size > 8 || (size & (size - 1)))
759 if (size > 8) {
760 return 0;759 return 0;
761 } else if (size > 4) {760 if (size == 8)
762 ret->t = VT_LLONG;761 ret->t = VT_LLONG;
763 return 1;762 else if (size == 4)
764 } else if (size > 2) {
765 ret->t = VT_INT;763 ret->t = VT_INT;
766 return 1;764 else if (size == 2)
767 } else if (size > 1) {
768 ret->t = VT_SHORT;765 ret->t = VT_SHORT;
769 return 1;766 else
770 } else {
771 ret->t = VT_BYTE;767 ret->t = VT_BYTE;
772 return 1;768 ret->ref = NULL;
773 }769 return 1;
774}770}
775 771
776static int is_sse_float(int t) {772static 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