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
57745774 #define EXPR_CONST 1
57755775 #define EXPR_ANY 2
57765776
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)
57805778 {
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;
57865780 switch(expr_type) {
5787− case EXPR_VAL:
5788− vpushi(v);
5789− break;
57905781 case EXPR_CONST:
57915782 /* compound literals must be allocated globally in this case */
57925783 saved_global_expr = global_expr;
@@ -5801,18 +5792,29 @@ static void init_putv(CType *type, Section *sec, unsigned long c, · 8 unmodified lines
58015792 expr_eq();
58025793 break;
58035794 }
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+
58055806 dtype = *type;
58065807 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
58075808
58085809 if (sec) {
5810+ int size, align;
58095811 /* XXX: not portable */
58105812 /* XXX: generate error if incorrect relocation */
58115813 gen_assign_cast(&dtype);
58125814 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);
58165818 }
58175819 ptr = sec->data + c;
58185820 /* XXX: make code faster ? */
@@ -5825,79 +5827,102 @@ static void init_putv(CType *type, Section *sec, unsigned long c, · 6 unmodified lines
58255827 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
58265828 bit_mask = (1LL << bit_size) - 1;
58275829 }
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 ||
58335855 #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
58365858 #else
5837− bt == VT_LLONG ||
5838− (bt == VT_INT && bit_size != 32)
5859+ bt == VT_LLONG ||
5860+ (bt == VT_INT && bit_size != 32)
58395861 #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;
58655887 #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;
58695891 #else
5870− case VT_LLONG:
5892+ case VT_LLONG:
58715893 #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;
58745897 #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;
58795902 #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;
58835906 #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;
58885912 #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;
58935917 #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;
58975921 #endif
5898− break;
5899− }
5900− }
5922+ break;
5923+ }
5924+ }
5925+ }
59015926 vtop--;
59025927 } else {
59035928 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
60066031 ch = ((unsigned char *)tokc.str.data)[i];
60076032 else
60086033 ch = ((nwchar_t *)tokc.str.data)[i];
6034+ vpushi(ch);
60096035 init_putv(t1, sec, c + (array_length + i) * size1,
60106036 ch, EXPR_VAL);
60116037 }
@@ -6018,6 +6044,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 6 unmodified lines
60186044 warning in this case since it is standard) */
60196045 if (n < 0 || array_length < n) {
60206046 if (!size_only) {
6047+ vpushi(0);
60216048 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
60226049 }
60236050 array_length++;
@@ -6058,14 +6085,14 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 34 unmodified lines
60586085 if (n < 0)
60596086 s->c = array_length;
60606087 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
6061− (sec || !first || tok == '{')) {
6088+ (!first || tok == '{')) {
60626089
60636090 /* NOTE: the previous test is a specific case for automatic
60646091 struct/union init */
60656092 /* XXX: union needs only one init */
60666093
60676094 int par_count = 0;
6068− if (tok == '(') {
6095+ if (0 && tok == '(') {
60696096 AttributeDef ad1;
60706097 CType type1;
60716098 next();
@@ -6210,6 +6237,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 138 unmodified lines
62106237 expr_type = EXPR_CONST;
62116238 if (!sec)
62126239 expr_type = EXPR_ANY;
6240+ parse_init_elem(expr_type);
62136241 init_putv(type, sec, c, 0, expr_type);
62146242 }
62156243 }

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