| @@ -1687,14 +1687,22 @@ static void pop_local_syms(Sym *b, int keep) · 1686 unmodified lines |
| 1687 | sym_pop(&local_stack, b, keep); | 1687 | sym_pop(&local_stack, b, keep); |
| 1688 | } | 1688 | } |
| 1689 | | 1689 | |
| 1690 | static void incr_bf_adr(int o) | 1690 | /* increment an lvalue pointer */ |
| | 1691 | static void incr_offset(int offset) |
| 1691 | { | 1692 | { |
| 1692 | vtop->type = char_pointer_type; | 1693 | int t = vtop->type.t; |
| 1693 | gaddrof(); | 1694 | gaddrof(); /* remove VT_LVAL */ |
| 1694 | vpushs(o); | 1695 | vtop->type.t = VT_PTRDIFF_T; /* set scalar type */ |
| | 1696 | vpushs(offset); |
| 1695 | gen_op('+'); | 1697 | gen_op('+'); |
| 1696 | vtop->type.t = VT_BYTE | VT_UNSIGNED; | | |
| 1697 | vtop->r |= VT_LVAL; | 1698 | vtop->r |= VT_LVAL; |
| | 1699 | vtop->type.t = t; |
| | 1700 | } |
| | 1701 | |
| | 1702 | static void incr_bf_adr(int o) |
| | 1703 | { |
| | 1704 | vtop->type.t = VT_BYTE | VT_UNSIGNED; |
| | 1705 | incr_offset(o); |
| 1698 | } | 1706 | } |
| 1699 | | 1707 | |
| 1700 | /* single-byte load mode for packed or otherwise unaligned bitfields */ | 1708 | /* single-byte load mode for packed or otherwise unaligned bitfields */ |
| @@ -1860,8 +1868,18 @@ ST_FUNC int gv(int rc) · 159 unmodified lines |
| 1860 | r2_ok = !rc2 || ((vtop->r2 < VT_CONST) && (reg_classes[vtop->r2] & rc2)); | 1868 | r2_ok = !rc2 || ((vtop->r2 < VT_CONST) && (reg_classes[vtop->r2] & rc2)); |
| 1861 | | 1869 | |
| 1862 | if (!r_ok || !r2_ok) { | 1870 | if (!r_ok || !r2_ok) { |
| 1863 | if (!r_ok) | 1871 | |
| 1864 | r = get_reg(rc); | 1872 | if (!r_ok) { |
| | 1873 | if (1 /* we can 'mov (r),r' in cases */ |
| | 1874 | && r < VT_CONST |
| | 1875 | && (reg_classes[r] & rc) |
| | 1876 | && !rc2 |
| | 1877 | ) |
| | 1878 | save_reg_upstack(r, 1); |
| | 1879 | else |
| | 1880 | r = get_reg(rc); |
| | 1881 | } |
| | 1882 | |
| 1865 | if (rc2) { | 1883 | if (rc2) { |
| 1866 | int load_type = (bt == VT_QFLOAT) ? VT_DOUBLE : VT_PTRDIFF_T; | 1884 | int load_type = (bt == VT_QFLOAT) ? VT_DOUBLE : VT_PTRDIFF_T; |
| 1867 | int original_type = vtop->type.t; | 1885 | int original_type = vtop->type.t; |
| @@ -1885,12 +1903,7 @@ ST_FUNC int gv(int rc) · 17 unmodified lines |
| 1885 | vdup(); | 1903 | vdup(); |
| 1886 | vtop[-1].r = r; /* save register value */ | 1904 | vtop[-1].r = r; /* save register value */ |
| 1887 | /* increment pointer to get second word */ | 1905 | /* increment pointer to get second word */ |
| 1888 | vtop->type.t = VT_PTRDIFF_T; | 1906 | incr_offset(PTR_SIZE); |
| 1889 | gaddrof(); | | |
| 1890 | vpushs(PTR_SIZE); | | |
| 1891 | gen_op('+'); | | |
| 1892 | vtop->r |= VT_LVAL; | | |
| 1893 | vtop->type.t = load_type; | | |
| 1894 | } else { | 1907 | } else { |
| 1895 | /* move registers */ | 1908 | /* move registers */ |
| 1896 | if (!r_ok) | 1909 | if (!r_ok) |
| @@ -3748,14 +3761,8 @@ ST_FUNC void vstore(void) · 1851 unmodified lines |
| 3748 | vtop[-1].type.t = load_type; | 3761 | vtop[-1].type.t = load_type; |
| 3749 | store(r, vtop - 1); | 3762 | store(r, vtop - 1); |
| 3750 | vswap(); | 3763 | vswap(); |
| 3751 | /* convert to int to increment easily */ | 3764 | incr_offset(PTR_SIZE); |
| 3752 | vtop->type.t = VT_PTRDIFF_T; | | |
| 3753 | gaddrof(); | | |
| 3754 | vpushs(PTR_SIZE); | | |
| 3755 | gen_op('+'); | | |
| 3756 | vtop->r |= VT_LVAL; | | |
| 3757 | vswap(); | 3765 | vswap(); |
| 3758 | vtop[-1].type.t = load_type; | | |
| 3759 | /* XXX: it works because r2 is spilled last ! */ | 3766 | /* XXX: it works because r2 is spilled last ! */ |
| 3760 | store(vtop->r2, vtop - 1); | 3767 | store(vtop->r2, vtop - 1); |
| 3761 | } else { | 3768 | } else { |
| @@ -6003,7 +6010,6 @@ special_math_val: · 2241 unmodified lines |
| 6003 | indir(); | 6010 | indir(); |
| 6004 | qualifiers = vtop->type.t & (VT_CONSTANT | VT_VOLATILE); | 6011 | qualifiers = vtop->type.t & (VT_CONSTANT | VT_VOLATILE); |
| 6005 | test_lvalue(); | 6012 | test_lvalue(); |
| 6006 | gaddrof(); | | |
| 6007 | /* expect pointer on structure */ | 6013 | /* expect pointer on structure */ |
| 6008 | if ((vtop->type.t & VT_BTYPE) != VT_STRUCT) | 6014 | if ((vtop->type.t & VT_BTYPE) != VT_STRUCT) |
| 6009 | expect("struct or union"); | 6015 | expect("struct or union"); |
| @@ -6014,16 +6020,15 @@ special_math_val: · 4 unmodified lines |
| 6014 | expect("field name"); | 6020 | expect("field name"); |
| 6015 | s = find_field(&vtop->type, tok, &cumofs); | 6021 | s = find_field(&vtop->type, tok, &cumofs); |
| 6016 | /* add field offset to pointer */ | 6022 | /* add field offset to pointer */ |
| 6017 | vtop->type = char_pointer_type; /* change type to 'char *' */ | 6023 | incr_offset(cumofs); |
| 6018 | vpushi(cumofs); | | |
| 6019 | gen_op('+'); | | |
| 6020 | /* change type to field type, and set to lvalue */ | 6024 | /* change type to field type, and set to lvalue */ |
| 6021 | vtop->type = s->type; | 6025 | vtop->type = s->type; |
| 6022 | vtop->type.t |= qualifiers; | 6026 | vtop->type.t |= qualifiers; |
| 6023 | /* an array is never an lvalue */ | 6027 | /* an array is never an lvalue */ |
| 6024 | if (!(vtop->type.t & VT_ARRAY)) { | 6028 | if (vtop->type.t & VT_ARRAY) { |
| 6025 | vtop->r |= VT_LVAL; | 6029 | vtop->r &= ~VT_LVAL; |
| 6026 | #ifdef CONFIG_TCC_BCHECK | 6030 | #ifdef CONFIG_TCC_BCHECK |
| | 6031 | } else { |
| 6027 | /* if bound checking, the referenced pointer must be checked */ | 6032 | /* if bound checking, the referenced pointer must be checked */ |
| 6028 | if (tcc_state->do_bounds_check) | 6033 | if (tcc_state->do_bounds_check) |
| 6029 | vtop->r |= VT_MUSTBOUND; | 6034 | vtop->r |= VT_MUSTBOUND; |
| @@ -6128,10 +6133,20 @@ special_math_val: · 98 unmodified lines |
| 6128 | #endif | 6133 | #endif |
| 6129 | } else { | 6134 | } else { |
| 6130 | /* return value */ | 6135 | /* return value */ |
| 6131 | for (r = ret.r + ret_nregs + !ret_nregs; r-- > ret.r;) { | 6136 | n = ret_nregs; |
| | 6137 | while (n > 1) { |
| | 6138 | int rc = reg_classes[ret.r] & ~(RC_INT | RC_FLOAT); |
| | 6139 | /* We assume that when a structure is returned in multiple |
| | 6140 | registers, their classes are consecutive values of the |
| | 6141 | suite s(n) = 2^n */ |
| | 6142 | rc <<= --n; |
| | 6143 | for (r = 0; r < NB_REGS; ++r) |
| | 6144 | if (reg_classes[r] & rc) |
| | 6145 | break; |
| 6132 | vsetc(&ret.type, r, &ret.c); | 6146 | vsetc(&ret.type, r, &ret.c); |
| 6133 | vtop->r2 = ret.r2; /* Loop only happens when r2 is VT_CONST */ | | |
| 6134 | } | 6147 | } |
| | 6148 | vsetc(&ret.type, ret.r, &ret.c); |
| | 6149 | vtop->r2 = ret.r2; |
| 6135 | | 6150 | |
| 6136 | /* handle packed struct return */ | 6151 | /* handle packed struct return */ |
| 6137 | if (((s->type.t & VT_BTYPE) == VT_STRUCT) && ret_nregs) { | 6152 | if (((s->type.t & VT_BTYPE) == VT_STRUCT) && ret_nregs) { |
| @@ -6140,9 +6155,9 @@ special_math_val: · 2 unmodified lines |
| 6140 | size = type_size(&s->type, &align); | 6155 | size = type_size(&s->type, &align); |
| 6141 | /* We're writing whole regs often, make sure there's enough | 6156 | /* We're writing whole regs often, make sure there's enough |
| 6142 | space. Assume register size is power of 2. */ | 6157 | space. Assume register size is power of 2. */ |
| 6143 | if (regsize > align) | 6158 | size = (size + regsize - 1) & -regsize; |
| 6144 | align = regsize; | 6159 | if (ret_align > align) |
| 6145 | loc &= -align; | 6160 | align = ret_align; |
| 6146 | loc = (loc - size) & -align; | 6161 | loc = (loc - size) & -align; |
| 6147 | addr = loc; | 6162 | addr = loc; |
| 6148 | offset = 0; | 6163 | offset = 0; |
| @@ -6619,11 +6634,12 @@ static void gfunc_return(CType *func_type) · 470 unmodified lines |
| 6619 | vstore(); | 6634 | vstore(); |
| 6620 | } else { | 6635 | } else { |
| 6621 | /* returning structure packed into registers */ | 6636 | /* returning structure packed into registers */ |
| 6622 | int size, addr, align, rc; | 6637 | int size, addr, align, rc, n; |
| 6623 | size = type_size(func_type,&align); | 6638 | size = type_size(func_type,&align); |
| 6624 | if ((vtop->r != (VT_LOCAL | VT_LVAL) || | 6639 | if ((align & (ret_align - 1)) |
| 6625 | (vtop->c.i & (ret_align-1))) | 6640 | && ((vtop->r & VT_VALMASK) < VT_CONST /* pointer to struct */ |
| 6626 | && (align & (ret_align-1))) { | 6641 | || (vtop->c.i & (ret_align - 1)) |
| | 6642 | )) { |
| 6627 | loc = (loc - size) & -ret_align; | 6643 | loc = (loc - size) & -ret_align; |
| 6628 | addr = loc; | 6644 | addr = loc; |
| 6629 | type = *func_type; | 6645 | type = *func_type; |
| @@ -6635,22 +6651,19 @@ static void gfunc_return(CType *func_type) · 5 unmodified lines |
| 6635 | } | 6651 | } |
| 6636 | vtop->type = ret_type; | 6652 | vtop->type = ret_type; |
| 6637 | rc = RC_RET(ret_type.t); | 6653 | rc = RC_RET(ret_type.t); |
| 6638 | if (ret_nregs == 1) | 6654 | //printf("struct return: n:%d t:%02x rc:%02x\n", ret_nregs, ret_type.t, rc); |
| | 6655 | for (n = ret_nregs; --n > 0;) { |
| | 6656 | vdup(); |
| 6639 | gv(rc); | 6657 | gv(rc); |
| 6640 | else { | 6658 | vswap(); |
| 6641 | for (;;) { | 6659 | incr_offset(regsize); |
| 6642 | vdup(); | 6660 | /* We assume that when a structure is returned in multiple |
| 6643 | gv(rc); | 6661 | registers, their classes are consecutive values of the |
| 6644 | vpop(); | 6662 | suite s(n) = 2^n */ |
| 6645 | if (--ret_nregs == 0) | 6663 | rc <<= 1; |
| 6646 | break; | | |
| 6647 | /* We assume that when a structure is returned in multiple | | |
| 6648 | registers, their classes are consecutive values of the | | |
| 6649 | suite s(n) = 2^n */ | | |
| 6650 | rc <<= 1; | | |
| 6651 | vtop->c.i += regsize; | | |
| 6652 | } | | |
| 6653 | } | 6664 | } |
| | 6665 | gv(rc); |
| | 6666 | vtop -= ret_nregs - 1; |
| 6654 | } | 6667 | } |
| 6655 | } else { | 6668 | } else { |
| 6656 | gv(RC_RET(func_type->t)); | 6669 | gv(RC_RET(func_type->t)); |