| @@ -559,14 +559,6 @@ static void apply_visibility(Sym *sym, CType *type) · 558 unmodified lines |
| 559 | 559 | |
| 560 | 560 | /* ------------------------------------------------------------------------- */ |
| 561 | 561 | |
| 562 | | −ST_FUNC void swap(int *p, int *q) |
| 563 | | −{ |
| 564 | | − int t; |
| 565 | | − t = *p; |
| 566 | | − *p = *q; |
| 567 | | − *q = t; |
| 568 | | −} |
| 569 | | − |
| 570 | 562 | static void vsetc(CType *type, int r, CValue *vc) |
| 571 | 563 | { |
| 572 | 564 | int v; |
| @@ -583,12 +575,15 @@ static void vsetc(CType *type, int r, CValue *vc) · 10 unmodified lines |
| 583 | 575 | as their value might still be used for real. All values |
| 584 | 576 | we push under nocode_wanted will eventually be popped |
| 585 | 577 | 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 | 581 | if (vtop >= vstack && !nocode_wanted) { |
| 588 | 582 | v = vtop->r & VT_VALMASK; |
| 589 | 583 | if (v == VT_CMP || (v & ~1) == VT_JMP) |
| 590 | 584 | gv(RC_INT); |
| 591 | 585 | } |
| 586 | + |
| 592 | 587 | vtop++; |
| 593 | 588 | vtop->type = *type; |
| 594 | 589 | vtop->r = r; |
| @@ -597,6 +592,38 @@ static void vsetc(CType *type, int r, CValue *vc) · 2 unmodified lines |
| 597 | 592 | vtop->sym = NULL; |
| 598 | 593 | } |
| 599 | 594 | |
| 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 | + |
| 600 | 627 | /* push constant of type "type" with useless value */ |
| 601 | 628 | ST_FUNC void vpush(CType *type) |
| 602 | 629 | { |
| @@ -637,6 +664,71 @@ static inline void vpushll(long long v) · 34 unmodified lines |
| 637 | 664 | vpush64(VT_LLONG, v); |
| 638 | 665 | } |
| 639 | 666 | |
| 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 | + |
| 640 | 732 | /* push a symbol value of TYPE */ |
| 641 | 733 | static 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 | 807 | vpushsym(type, external_global_sym(v, type, 0)); |
| 716 | 808 | } |
| 717 | 809 | |
| 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 | | − |
| 768 | 810 | /* save registers up to (vtop - n) stack entry */ |
| 769 | 811 | ST_FUNC void save_regs(int n) |
| 770 | 812 | { |
| @@ -1297,60 +1339,6 @@ static void lbuild(int t) · 526 unmodified lines |
| 1297 | 1339 | } |
| 1298 | 1340 | #endif |
| 1299 | 1341 | |
| 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 | | − |
| 1354 | 1342 | /* convert stack entry to register and duplicate its value in another |
| 1355 | 1343 | register */ |
| 1356 | 1344 | static void gv_dup(void) |
| @@ -2025,7 +2013,7 @@ redo: · 668 unmodified lines |
| 2025 | 2013 | /* Put pointer as first operand */ |
| 2026 | 2014 | if (bt2 == VT_PTR) { |
| 2027 | 2015 | vswap(); |
| 2028 | | − swap(&t1, &t2); |
| 2016 | + t = t1, t1 = t2, t2 = t; |
| 2029 | 2017 | } |
| 2030 | 2018 | #if PTR_SIZE == 4 |
| 2031 | 2019 | if ((vtop[0].type.t & VT_BTYPE) == VT_LLONG) |
| @@ -4668,11 +4656,11 @@ ST_FUNC void unary(void) · 2636 unmodified lines |
| 4668 | 4656 | subtract(-0, x). */ |
| 4669 | 4657 | vpush(&vtop->type); |
| 4670 | 4658 | if (t == VT_FLOAT) |
| 4671 | | − vtop->c.f = -0.0f; |
| 4659 | + vtop->c.f = -1.0 * 0.0; |
| 4672 | 4660 | else if (t == VT_DOUBLE) |
| 4673 | | − vtop->c.d = -0.0; |
| 4661 | + vtop->c.d = -1.0 * 0.0; |
| 4674 | 4662 | else |
| 4675 | | − vtop->c.ld = -0.0; |
| 4663 | + vtop->c.ld = -1.0 * 0.0; |
| 4676 | 4664 | } else |
| 4677 | 4665 | vpushi(0); |
| 4678 | 4666 | vswap(); |
| @@ -5460,6 +5448,72 @@ static void label_or_decl(int l) · 781 unmodified lines |
| 5460 | 5448 | decl(l); |
| 5461 | 5449 | } |
| 5462 | 5450 | |
| 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, ®size); |
| 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 | + |
| 5463 | 5517 | static int case_cmp(const void *pa, const void *pb) |
| 5464 | 5518 | { |
| 5465 | 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 | 5709 | if (tok != ';') { |
| 5656 | 5710 | gexpr(); |
| 5657 | 5711 | 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, ®size); |
| 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); |
| 5723 | 5713 | } |
| 5724 | 5714 | skip(';'); |
| 5725 | 5715 | /* jump unless last stmt in top-level block */ |