History

struct-init: Reimplement

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.

Michael Matz committed 10 years ago

Commit 968bccd1 parent 5d0c16a1 file · +106 −78Browse files

Unified · Split

tccgen.c+106−78
@@ -5774,19 +5774,10 @@ static void decl_designator(CType *type, Section *sec, unsigned long c, · 5773 unmodified lines
5774#define EXPR_CONST 15774#define EXPR_CONST 1
5775#define EXPR_ANY 25775#define EXPR_ANY 2
5776 5776
5777/* store a value or an expression directly in global data or in local array */5777static void parse_init_elem(int expr_type)
5778static void init_putv(CType *type, Section *sec, unsigned long c,
5779 int v, int expr_type)
5780{5778{
5781 int saved_global_expr, bt, bit_pos, bit_size;5779 int saved_global_expr;
5782 void *ptr;
5783 unsigned long long bit_mask;
5784 CType dtype;
5785
5786 switch(expr_type) {5780 switch(expr_type) {
5787 case EXPR_VAL:
5788 vpushi(v);
5789 break;
5790 case EXPR_CONST:5781 case EXPR_CONST:
5791 /* compound literals must be allocated globally in this case */5782 /* compound literals must be allocated globally in this case */
5792 saved_global_expr = global_expr;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 expr_eq();5792 expr_eq();
5802 break;5793 break;
5803 }5794 }
5804 5795}
5796
5797/* store a value or an expression directly in global data or in local array */
5798static 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 dtype = *type;5806 dtype = *type;
5806 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */5807 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
5807 5808
5808 if (sec) {5809 if (sec) {
5810 int size, align;
5809 /* XXX: not portable */5811 /* XXX: not portable */
5810 /* XXX: generate error if incorrect relocation */5812 /* XXX: generate error if incorrect relocation */
5811 gen_assign_cast(&dtype);5813 gen_assign_cast(&dtype);
5812 bt = type->t & VT_BTYPE;5814 bt = type->t & VT_BTYPE;
5813 /* we'll write at most 16 bytes */5815 size = type_size(type, &align);
5814 if (c + 16 > sec->data_allocated) {5816 if (c + size > sec->data_allocated) {
5815 section_realloc(sec, c + 16);5817 section_realloc(sec, c + size);
5816 }5818 }
5817 ptr = sec->data + c;5819 ptr = sec->data + c;
5818 /* XXX: make code faster ? */5820 /* XXX: make code faster ? */
@@ -5825,79 +5827,102 @@ static void init_putv(CType *type, Section *sec, unsigned long c, · 6 unmodified lines
5825 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;5827 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
5826 bit_mask = (1LL << bit_size) - 1;5828 bit_mask = (1LL << bit_size) - 1;
5827 }5829 }
5828 if ((vtop->r & VT_SYM) &&5830 if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST) &&
5829 (bt == VT_BYTE ||5831 vtop->sym->v >= SYM_FIRST_ANOM &&
5830 bt == VT_SHORT ||5832 /* XXX This rejects compount literals like
5831 bt == VT_DOUBLE ||5833 '(void *){ptr}'. The problem is that '&sym' is
5832 bt == VT_LDOUBLE ||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#if PTR_SIZE == 85855#if PTR_SIZE == 8
5834 (bt == VT_LLONG && bit_size != 64) ||5856 (bt == VT_LLONG && bit_size != 64) ||
5835 bt == VT_INT5857 bt == VT_INT
5836#else5858#else
5837 bt == VT_LLONG ||5859 bt == VT_LLONG ||
5838 (bt == VT_INT && bit_size != 32)5860 (bt == VT_INT && bit_size != 32)
5839#endif5861#endif
5840 ))5862 ))
5841 tcc_error("initializer element is not computable at load time");5863 tcc_error("initializer element is not computable at load time");
5842 switch(bt) {5864 switch(bt) {
5843 /* XXX: when cross-compiling we assume that each type has the5865 /* XXX: when cross-compiling we assume that each type has the
5844 same representation on host and target, which is likely to5866 same representation on host and target, which is likely to
5845 be wrong in the case of long double */5867 be wrong in the case of long double */
5846 case VT_BOOL:5868 case VT_BOOL:
5847 vtop->c.i = (vtop->c.i != 0);5869 vtop->c.i = (vtop->c.i != 0);
5848 case VT_BYTE:5870 case VT_BYTE:
5849 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;5871 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
5850 break;5872 break;
5851 case VT_SHORT:5873 case VT_SHORT:
5852 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;5874 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
5853 break;5875 break;
5854 case VT_DOUBLE:5876 case VT_DOUBLE:
5855 *(double *)ptr = vtop->c.d;5877 *(double *)ptr = vtop->c.d;
5856 break;5878 break;
5857 case VT_LDOUBLE:5879 case VT_LDOUBLE:
5858 if (sizeof(long double) == LDOUBLE_SIZE)5880 if (sizeof(long double) == LDOUBLE_SIZE)
5859 *(long double *)ptr = vtop->c.ld;5881 *(long double *)ptr = vtop->c.ld;
5860 else if (sizeof(double) == LDOUBLE_SIZE)5882 else if (sizeof(double) == LDOUBLE_SIZE)
5861 *(double *)ptr = vtop->c.ld;5883 *(double *)ptr = vtop->c.ld;
5862 else5884 else
5863 tcc_error("can't cross compile long double constants");5885 tcc_error("can't cross compile long double constants");
5864 break;5886 break;
5865#if PTR_SIZE != 85887#if PTR_SIZE != 8
5866 case VT_LLONG:5888 case VT_LLONG:
5867 *(long long *)ptr |= (vtop->c.i & bit_mask) << bit_pos;5889 *(long long *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
5868 break;5890 break;
5869#else5891#else
5870 case VT_LLONG:5892 case VT_LLONG:
5871#endif5893#endif
5872 case VT_PTR: {5894 case VT_PTR:
5873 addr_t val = (vtop->c.i & bit_mask) << bit_pos;5895 {
5896 addr_t val = (vtop->c.i & bit_mask) << bit_pos;
5874#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)5897#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
5875 if (vtop->r & VT_SYM)5898 if (vtop->r & VT_SYM)
5876 greloca(sec, vtop->sym, c, R_DATA_PTR, val);5899 greloca(sec, vtop->sym, c, R_DATA_PTR, val);
5877 else5900 else
5878 *(addr_t *)ptr |= val;5901 *(addr_t *)ptr |= val;
5879#else5902#else
5880 if (vtop->r & VT_SYM)5903 if (vtop->r & VT_SYM)
5881 greloc(sec, vtop->sym, c, R_DATA_PTR);5904 greloc(sec, vtop->sym, c, R_DATA_PTR);
5882 *(addr_t *)ptr |= val;5905 *(addr_t *)ptr |= val;
5883#endif5906#endif
5884 break;5907 break;
5885 }5908 }
5886 default: {5909 default:
5887 int val = (vtop->c.i & bit_mask) << bit_pos;5910 {
5911 int val = (vtop->c.i & bit_mask) << bit_pos;
5888#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)5912#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
5889 if (vtop->r & VT_SYM)5913 if (vtop->r & VT_SYM)
5890 greloca(sec, vtop->sym, c, R_DATA_PTR, val);5914 greloca(sec, vtop->sym, c, R_DATA_PTR, val);
5891 else5915 else
5892 *(int *)ptr |= val;5916 *(int *)ptr |= val;
5893#else5917#else
5894 if (vtop->r & VT_SYM)5918 if (vtop->r & VT_SYM)
5895 greloc(sec, vtop->sym, c, R_DATA_PTR);5919 greloc(sec, vtop->sym, c, R_DATA_PTR);
5896 *(int *)ptr |= val;5920 *(int *)ptr |= val;
5897#endif5921#endif
5898 break;5922 break;
5899 }5923 }
5900 }5924 }
5925 }
5901 vtop--;5926 vtop--;
5902 } else {5927 } else {
5903 vset(&dtype, VT_LOCAL|VT_LVAL, c);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 ch = ((unsigned char *)tokc.str.data)[i];6031 ch = ((unsigned char *)tokc.str.data)[i];
6007 else6032 else
6008 ch = ((nwchar_t *)tokc.str.data)[i];6033 ch = ((nwchar_t *)tokc.str.data)[i];
6034 vpushi(ch);
6009 init_putv(t1, sec, c + (array_length + i) * size1,6035 init_putv(t1, sec, c + (array_length + i) * size1,
6010 ch, EXPR_VAL);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 warning in this case since it is standard) */6044 warning in this case since it is standard) */
6019 if (n < 0 || array_length < n) {6045 if (n < 0 || array_length < n) {
6020 if (!size_only) {6046 if (!size_only) {
6047 vpushi(0);
6021 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);6048 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
6022 }6049 }
6023 array_length++;6050 array_length++;
@@ -6058,14 +6085,14 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 34 unmodified lines
6058 if (n < 0)6085 if (n < 0)
6059 s->c = array_length;6086 s->c = array_length;
6060 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&6087 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
6061 (sec || !first || tok == '{')) {6088 (!first || tok == '{')) {
6062 6089
6063 /* NOTE: the previous test is a specific case for automatic6090 /* NOTE: the previous test is a specific case for automatic
6064 struct/union init */6091 struct/union init */
6065 /* XXX: union needs only one init */6092 /* XXX: union needs only one init */
6066 6093
6067 int par_count = 0;6094 int par_count = 0;
6068 if (tok == '(') {6095 if (0 && tok == '(') {
6069 AttributeDef ad1;6096 AttributeDef ad1;
6070 CType type1;6097 CType type1;
6071 next();6098 next();
@@ -6210,6 +6237,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 138 unmodified lines
6210 expr_type = EXPR_CONST;6237 expr_type = EXPR_CONST;
6211 if (!sec)6238 if (!sec)
6212 expr_type = EXPR_ANY;6239 expr_type = EXPR_ANY;
6240 parse_init_elem(expr_type);
6213 init_putv(type, sec, c, 0, expr_type);6241 init_putv(type, sec, c, 0, expr_type);
6214 }6242 }
6215}6243}

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