Start reimplementing the whole initializer handling to be conforming to ISO C. This patch just reimplements current functionality to prepare for further changes, all tests pass.
Unified · Split
| @@ -5774,19 +5774,10 @@ static void decl_designator(CType *type, Section *sec, unsigned long c, · 5773 unmodified lines | ||
| 5774 | 5774 | #define EXPR_CONST 1 |
| 5775 | 5775 | #define EXPR_ANY 2 |
| 5776 | 5776 | |
| 5777 | −/* store a value or an expression directly in global data or in local array */ | |
| 5778 | −static void init_putv(CType *type, Section *sec, unsigned long c, | |
| 5779 | − int v, int expr_type) | |
| 5777 | +static void parse_init_elem(int expr_type) | |
| 5780 | 5778 | { |
| 5781 | − int saved_global_expr, bt, bit_pos, bit_size; | |
| 5782 | − void *ptr; | |
| 5783 | − unsigned long long bit_mask; | |
| 5784 | − CType dtype; | |
| 5785 | − | |
| 5779 | + int saved_global_expr; | |
| 5786 | 5780 | switch(expr_type) { |
| 5787 | − case EXPR_VAL: | |
| 5788 | − vpushi(v); | |
| 5789 | − break; | |
| 5790 | 5781 | case EXPR_CONST: |
| 5791 | 5782 | /* compound literals must be allocated globally in this case */ |
| 5792 | 5783 | saved_global_expr = global_expr; |
| @@ -5801,18 +5792,29 @@ static void init_putv(CType *type, Section *sec, unsigned long c, · 8 unmodified lines | ||
| 5801 | 5792 | expr_eq(); |
| 5802 | 5793 | break; |
| 5803 | 5794 | } |
| 5804 | − | |
| 5795 | +} | |
| 5796 | + | |
| 5797 | +/* store a value or an expression directly in global data or in local array */ | |
| 5798 | +static void init_putv(CType *type, Section *sec, unsigned long c, | |
| 5799 | + int v, int expr_type) | |
| 5800 | +{ | |
| 5801 | + int bt, bit_pos, bit_size; | |
| 5802 | + void *ptr; | |
| 5803 | + unsigned long long bit_mask; | |
| 5804 | + CType dtype; | |
| 5805 | + | |
| 5805 | 5806 | dtype = *type; |
| 5806 | 5807 | dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */ |
| 5807 | 5808 | |
| 5808 | 5809 | if (sec) { |
| 5810 | + int size, align; | |
| 5809 | 5811 | /* XXX: not portable */ |
| 5810 | 5812 | /* XXX: generate error if incorrect relocation */ |
| 5811 | 5813 | gen_assign_cast(&dtype); |
| 5812 | 5814 | bt = type->t & VT_BTYPE; |
| 5813 | − /* we'll write at most 16 bytes */ | |
| 5814 | − if (c + 16 > sec->data_allocated) { | |
| 5815 | − section_realloc(sec, c + 16); | |
| 5815 | + size = type_size(type, &align); | |
| 5816 | + if (c + size > sec->data_allocated) { | |
| 5817 | + section_realloc(sec, c + size); | |
| 5816 | 5818 | } |
| 5817 | 5819 | ptr = sec->data + c; |
| 5818 | 5820 | /* XXX: make code faster ? */ |
| @@ -5825,79 +5827,102 @@ static void init_putv(CType *type, Section *sec, unsigned long c, · 6 unmodified lines | ||
| 5825 | 5827 | bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f; |
| 5826 | 5828 | bit_mask = (1LL << bit_size) - 1; |
| 5827 | 5829 | } |
| 5828 | − if ((vtop->r & VT_SYM) && | |
| 5829 | − (bt == VT_BYTE || | |
| 5830 | − bt == VT_SHORT || | |
| 5831 | − bt == VT_DOUBLE || | |
| 5832 | − bt == VT_LDOUBLE || | |
| 5830 | + if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST) && | |
| 5831 | + vtop->sym->v >= SYM_FIRST_ANOM && | |
| 5832 | + /* XXX This rejects compount literals like | |
| 5833 | + '(void *){ptr}'. The problem is that '&sym' is | |
| 5834 | + represented the same way, which would be ruled out | |
| 5835 | + by the SYM_FIRST_ANOM check above, but also '"string"' | |
| 5836 | + in 'char *p = "string"' is represented the same | |
| 5837 | + with the type being VT_PTR and the symbol being an | |
| 5838 | + anonymous one. That is, there's no difference in vtop | |
| 5839 | + between '(void *){x}' and '&(void *){x}'. Ignore | |
| 5840 | + pointer typed entities here. Hopefully no real code | |
| 5841 | + will every use compound literals with scalar type. */ | |
| 5842 | + (vtop->type.t & VT_BTYPE) != VT_PTR) { | |
| 5843 | + /* These come from compound literals, memcpy stuff over. */ | |
| 5844 | + Section *ssec; | |
| 5845 | + ElfW(Sym) *esym; | |
| 5846 | + esym = &((ElfW(Sym) *)symtab_section->data)[vtop->sym->c]; | |
| 5847 | + ssec = tcc_state->sections[esym->st_shndx]; | |
| 5848 | + memmove (ptr, ssec->data + esym->st_value, size); | |
| 5849 | + } else { | |
| 5850 | + if ((vtop->r & VT_SYM) && | |
| 5851 | + (bt == VT_BYTE || | |
| 5852 | + bt == VT_SHORT || | |
| 5853 | + bt == VT_DOUBLE || | |
| 5854 | + bt == VT_LDOUBLE || | |
| 5833 | 5855 | #if PTR_SIZE == 8 |
| 5834 | − (bt == VT_LLONG && bit_size != 64) || | |
| 5835 | − bt == VT_INT | |
| 5856 | + (bt == VT_LLONG && bit_size != 64) || | |
| 5857 | + bt == VT_INT | |
| 5836 | 5858 | #else |
| 5837 | − bt == VT_LLONG || | |
| 5838 | − (bt == VT_INT && bit_size != 32) | |
| 5859 | + bt == VT_LLONG || | |
| 5860 | + (bt == VT_INT && bit_size != 32) | |
| 5839 | 5861 | #endif |
| 5840 | − )) | |
| 5841 | − tcc_error("initializer element is not computable at load time"); | |
| 5842 | − switch(bt) { | |
| 5843 | − /* XXX: when cross-compiling we assume that each type has the | |
| 5844 | − same representation on host and target, which is likely to | |
| 5845 | − be wrong in the case of long double */ | |
| 5846 | − case VT_BOOL: | |
| 5847 | − vtop->c.i = (vtop->c.i != 0); | |
| 5848 | − case VT_BYTE: | |
| 5849 | − *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos; | |
| 5850 | − break; | |
| 5851 | − case VT_SHORT: | |
| 5852 | − *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos; | |
| 5853 | − break; | |
| 5854 | − case VT_DOUBLE: | |
| 5855 | − *(double *)ptr = vtop->c.d; | |
| 5856 | − break; | |
| 5857 | − case VT_LDOUBLE: | |
| 5858 | − if (sizeof(long double) == LDOUBLE_SIZE) | |
| 5859 | − *(long double *)ptr = vtop->c.ld; | |
| 5860 | − else if (sizeof(double) == LDOUBLE_SIZE) | |
| 5861 | − *(double *)ptr = vtop->c.ld; | |
| 5862 | − else | |
| 5863 | − tcc_error("can't cross compile long double constants"); | |
| 5864 | − break; | |
| 5862 | + )) | |
| 5863 | + tcc_error("initializer element is not computable at load time"); | |
| 5864 | + switch(bt) { | |
| 5865 | + /* XXX: when cross-compiling we assume that each type has the | |
| 5866 | + same representation on host and target, which is likely to | |
| 5867 | + be wrong in the case of long double */ | |
| 5868 | + case VT_BOOL: | |
| 5869 | + vtop->c.i = (vtop->c.i != 0); | |
| 5870 | + case VT_BYTE: | |
| 5871 | + *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos; | |
| 5872 | + break; | |
| 5873 | + case VT_SHORT: | |
| 5874 | + *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos; | |
| 5875 | + break; | |
| 5876 | + case VT_DOUBLE: | |
| 5877 | + *(double *)ptr = vtop->c.d; | |
| 5878 | + break; | |
| 5879 | + case VT_LDOUBLE: | |
| 5880 | + if (sizeof(long double) == LDOUBLE_SIZE) | |
| 5881 | + *(long double *)ptr = vtop->c.ld; | |
| 5882 | + else if (sizeof(double) == LDOUBLE_SIZE) | |
| 5883 | + *(double *)ptr = vtop->c.ld; | |
| 5884 | + else | |
| 5885 | + tcc_error("can't cross compile long double constants"); | |
| 5886 | + break; | |
| 5865 | 5887 | #if PTR_SIZE != 8 |
| 5866 | − case VT_LLONG: | |
| 5867 | − *(long long *)ptr |= (vtop->c.i & bit_mask) << bit_pos; | |
| 5868 | − break; | |
| 5888 | + case VT_LLONG: | |
| 5889 | + *(long long *)ptr |= (vtop->c.i & bit_mask) << bit_pos; | |
| 5890 | + break; | |
| 5869 | 5891 | #else |
| 5870 | − case VT_LLONG: | |
| 5892 | + case VT_LLONG: | |
| 5871 | 5893 | #endif |
| 5872 | − case VT_PTR: { | |
| 5873 | − addr_t val = (vtop->c.i & bit_mask) << bit_pos; | |
| 5894 | + case VT_PTR: | |
| 5895 | + { | |
| 5896 | + addr_t val = (vtop->c.i & bit_mask) << bit_pos; | |
| 5874 | 5897 | #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64) |
| 5875 | − if (vtop->r & VT_SYM) | |
| 5876 | − greloca(sec, vtop->sym, c, R_DATA_PTR, val); | |
| 5877 | − else | |
| 5878 | − *(addr_t *)ptr |= val; | |
| 5898 | + if (vtop->r & VT_SYM) | |
| 5899 | + greloca(sec, vtop->sym, c, R_DATA_PTR, val); | |
| 5900 | + else | |
| 5901 | + *(addr_t *)ptr |= val; | |
| 5879 | 5902 | #else |
| 5880 | − if (vtop->r & VT_SYM) | |
| 5881 | − greloc(sec, vtop->sym, c, R_DATA_PTR); | |
| 5882 | − *(addr_t *)ptr |= val; | |
| 5903 | + if (vtop->r & VT_SYM) | |
| 5904 | + greloc(sec, vtop->sym, c, R_DATA_PTR); | |
| 5905 | + *(addr_t *)ptr |= val; | |
| 5883 | 5906 | #endif |
| 5884 | − break; | |
| 5885 | − } | |
| 5886 | − default: { | |
| 5887 | − int val = (vtop->c.i & bit_mask) << bit_pos; | |
| 5907 | + break; | |
| 5908 | + } | |
| 5909 | + default: | |
| 5910 | + { | |
| 5911 | + int val = (vtop->c.i & bit_mask) << bit_pos; | |
| 5888 | 5912 | #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64) |
| 5889 | − if (vtop->r & VT_SYM) | |
| 5890 | − greloca(sec, vtop->sym, c, R_DATA_PTR, val); | |
| 5891 | − else | |
| 5892 | − *(int *)ptr |= val; | |
| 5913 | + if (vtop->r & VT_SYM) | |
| 5914 | + greloca(sec, vtop->sym, c, R_DATA_PTR, val); | |
| 5915 | + else | |
| 5916 | + *(int *)ptr |= val; | |
| 5893 | 5917 | #else |
| 5894 | − if (vtop->r & VT_SYM) | |
| 5895 | − greloc(sec, vtop->sym, c, R_DATA_PTR); | |
| 5896 | − *(int *)ptr |= val; | |
| 5918 | + if (vtop->r & VT_SYM) | |
| 5919 | + greloc(sec, vtop->sym, c, R_DATA_PTR); | |
| 5920 | + *(int *)ptr |= val; | |
| 5897 | 5921 | #endif |
| 5898 | − break; | |
| 5899 | − } | |
| 5900 | − } | |
| 5922 | + break; | |
| 5923 | + } | |
| 5924 | + } | |
| 5925 | + } | |
| 5901 | 5926 | vtop--; |
| 5902 | 5927 | } else { |
| 5903 | 5928 | vset(&dtype, VT_LOCAL|VT_LVAL, c); |
| @@ -6006,6 +6031,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 102 unmodified lines | ||
| 6006 | 6031 | ch = ((unsigned char *)tokc.str.data)[i]; |
| 6007 | 6032 | else |
| 6008 | 6033 | ch = ((nwchar_t *)tokc.str.data)[i]; |
| 6034 | + vpushi(ch); | |
| 6009 | 6035 | init_putv(t1, sec, c + (array_length + i) * size1, |
| 6010 | 6036 | ch, EXPR_VAL); |
| 6011 | 6037 | } |
| @@ -6018,6 +6044,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 6 unmodified lines | ||
| 6018 | 6044 | warning in this case since it is standard) */ |
| 6019 | 6045 | if (n < 0 || array_length < n) { |
| 6020 | 6046 | if (!size_only) { |
| 6047 | + vpushi(0); | |
| 6021 | 6048 | init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL); |
| 6022 | 6049 | } |
| 6023 | 6050 | array_length++; |
| @@ -6058,14 +6085,14 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 34 unmodified lines | ||
| 6058 | 6085 | if (n < 0) |
| 6059 | 6086 | s->c = array_length; |
| 6060 | 6087 | } else if ((type->t & VT_BTYPE) == VT_STRUCT && |
| 6061 | − (sec || !first || tok == '{')) { | |
| 6088 | + (!first || tok == '{')) { | |
| 6062 | 6089 | |
| 6063 | 6090 | /* NOTE: the previous test is a specific case for automatic |
| 6064 | 6091 | struct/union init */ |
| 6065 | 6092 | /* XXX: union needs only one init */ |
| 6066 | 6093 | |
| 6067 | 6094 | int par_count = 0; |
| 6068 | − if (tok == '(') { | |
| 6095 | + if (0 && tok == '(') { | |
| 6069 | 6096 | AttributeDef ad1; |
| 6070 | 6097 | CType type1; |
| 6071 | 6098 | next(); |
| @@ -6210,6 +6237,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 138 unmodified lines | ||
| 6210 | 6237 | expr_type = EXPR_CONST; |
| 6211 | 6238 | if (!sec) |
| 6212 | 6239 | expr_type = EXPR_ANY; |
| 6240 | + parse_init_elem(expr_type); | |
| 6213 | 6241 | init_putv(type, sec, c, 0, expr_type); |
| 6214 | 6242 | } |
| 6215 | 6243 | } |