| @@ -123,6 +123,12 @@ static struct scope { · 122 unmodified lines |
| 123 | 123 | Sym *lstk, *llstk; |
| 124 | 124 | } *cur_scope, *loop_scope, *root_scope; |
| 125 | 125 | |
| 126 | +typedef struct { |
| 127 | + Section *sec; |
| 128 | + int local_offset; |
| 129 | + Sym *flex_array_ref; |
| 130 | +} init_params; |
| 131 | + |
| 126 | 132 | /********************************************************/ |
| 127 | 133 | /* stab debug support */ |
| 128 | 134 | |
| @@ -218,8 +224,8 @@ static int is_compatible_types(CType *type1, CType *type2); · 89 unmodified lines |
| 218 | 224 | static int parse_btype(CType *type, AttributeDef *ad); |
| 219 | 225 | static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td); |
| 220 | 226 | static void parse_expr_type(CType *type); |
| 221 | | −static void init_putv(CType *type, Section *sec, unsigned long c); |
| 222 | | −static void decl_initializer(CType *type, Section *sec, unsigned long c, int flags); |
| 227 | +static void init_putv(init_params *p, CType *type, unsigned long c); |
| 228 | +static void decl_initializer(init_params *p, CType *type, unsigned long c, int flags); |
| 223 | 229 | static void block(int is_expr); |
| 224 | 230 | static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope); |
| 225 | 231 | static void decl(int l); |
| @@ -2167,16 +2173,17 @@ ST_FUNC int gv(int rc) · 1941 unmodified lines |
| 2167 | 2173 | } else { |
| 2168 | 2174 | if (is_float(vtop->type.t) && |
| 2169 | 2175 | (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { |
| 2170 | | − unsigned long offset; |
| 2171 | 2176 | /* CPUs usually cannot use float constants, so we store them |
| 2172 | 2177 | generically in data segment */ |
| 2178 | + init_params p = { data_section }; |
| 2179 | + unsigned long offset; |
| 2173 | 2180 | size = type_size(&vtop->type, &align); |
| 2174 | 2181 | if (NODATA_WANTED) |
| 2175 | 2182 | size = 0, align = 1; |
| 2176 | | − offset = section_add(data_section, size, align); |
| 2177 | | − vpush_ref(&vtop->type, data_section, offset, size); |
| 2183 | + offset = section_add(p.sec, size, align); |
| 2184 | + vpush_ref(&vtop->type, p.sec, offset, size); |
| 2178 | 2185 | vswap(); |
| 2179 | | − init_putv(&vtop->type, data_section, offset); |
| 2186 | + init_putv(&p, &vtop->type, offset); |
| 2180 | 2187 | vtop->r |= VT_LVAL; |
| 2181 | 2188 | } |
| 2182 | 2189 | #ifdef CONFIG_TCC_BCHECK |
| @@ -5444,7 +5451,7 @@ static void parse_builtin_params(int nc, const char *args) · 3261 unmodified lines |
| 5444 | 5451 | type.t = VT_SIZE_T; |
| 5445 | 5452 | break; |
| 5446 | 5453 | default: |
| 5447 | | − tcc_error("internal error"); |
| 5454 | + break; |
| 5448 | 5455 | } |
| 5449 | 5456 | gen_assign_cast(&type); |
| 5450 | 5457 | } |
| @@ -6102,7 +6109,8 @@ special_math_val: · 651 unmodified lines |
| 6102 | 6109 | problems */ |
| 6103 | 6110 | vseti(VT_LOCAL, loc); |
| 6104 | 6111 | #ifdef CONFIG_TCC_BCHECK |
| 6105 | | − loc -= tcc_state->do_bounds_check != 0; |
| 6112 | + if (tcc_state->do_bounds_check) |
| 6113 | + --loc; |
| 6106 | 6114 | #endif |
| 6107 | 6115 | ret.c = vtop->c; |
| 6108 | 6116 | if (ret_nregs < 0) |
| @@ -7296,23 +7304,6 @@ static void skip_or_save_block(TokenString **str) · 1187 unmodified lines |
| 7296 | 7304 | } |
| 7297 | 7305 | } |
| 7298 | 7306 | |
| 7299 | | −static void get_init_string(TokenString **str, int has_init) |
| 7300 | | −{ |
| 7301 | | − if (has_init == 2) { |
| 7302 | | − *str = tok_str_alloc(); |
| 7303 | | − /* only get strings */ |
| 7304 | | − while (tok == TOK_STR || tok == TOK_LSTR) { |
| 7305 | | − tok_str_add_tok(*str); |
| 7306 | | − next(); |
| 7307 | | − } |
| 7308 | | − tok_str_add(*str, -1); |
| 7309 | | − tok_str_add(*str, 0); |
| 7310 | | − } |
| 7311 | | − else |
| 7312 | | − skip_or_save_block(str); |
| 7313 | | − unget_tok(0); |
| 7314 | | −} |
| 7315 | | − |
| 7316 | 7307 | #define EXPR_CONST 1 |
| 7317 | 7308 | #define EXPR_ANY 2 |
| 7318 | 7309 | |
| @@ -7343,10 +7334,22 @@ static void parse_init_elem(int expr_type) · 24 unmodified lines |
| 7343 | 7334 | } |
| 7344 | 7335 | } |
| 7345 | 7336 | |
| 7337 | +#if 1 |
| 7338 | +static void init_assert(init_params *p, int offset) |
| 7339 | +{ |
| 7340 | + if (p->sec ? !NODATA_WANTED && offset > p->sec->data_offset |
| 7341 | + : !nocode_wanted && offset > p->local_offset) |
| 7342 | + tcc_internal_error("initializer overflow"); |
| 7343 | +} |
| 7344 | +#else |
| 7345 | +#define init_assert(sec, offset) |
| 7346 | +#endif |
| 7347 | + |
| 7346 | 7348 | /* put zeros for variable based init */ |
| 7347 | | −static void init_putz(Section *sec, unsigned long c, int size) |
| 7349 | +static void init_putz(init_params *p, unsigned long c, int size) |
| 7348 | 7350 | { |
| 7349 | | − if (sec) { |
| 7351 | + init_assert(p, c + size); |
| 7352 | + if (p->sec) { |
| 7350 | 7353 | /* nothing to do because globals are already set to zero */ |
| 7351 | 7354 | } else { |
| 7352 | 7355 | vpush_global_sym(&func_old_type, TOK_memset); |
| @@ -7365,6 +7368,37 @@ static void init_putz(Section *sec, unsigned long c, int size) · 12 unmodified lines |
| 7365 | 7368 | #define DIF_FIRST 1 |
| 7366 | 7369 | #define DIF_SIZE_ONLY 2 |
| 7367 | 7370 | #define DIF_HAVE_ELEM 4 |
| 7371 | +#define DIF_CLEAR 8 |
| 7372 | + |
| 7373 | +/* delete relocations for specified range c ... c + size. Unfortunatly |
| 7374 | + in very special cases, relocations may occur unordered */ |
| 7375 | +static void decl_design_delrels(Section *sec, int c, int size) |
| 7376 | +{ |
| 7377 | + ElfW_Rel *rel, *rel2, *rel_end; |
| 7378 | + if (!sec || !sec->reloc) |
| 7379 | + return; |
| 7380 | + rel = rel2 = (ElfW_Rel*)sec->reloc->data; |
| 7381 | + rel_end = (ElfW_Rel*)(sec->reloc->data + sec->reloc->data_offset); |
| 7382 | + while (rel < rel_end) { |
| 7383 | + if (rel->r_offset >= c && rel->r_offset < c + size) { |
| 7384 | + sec->reloc->data_offset -= sizeof *rel; |
| 7385 | + } else { |
| 7386 | + if (rel2 != rel) |
| 7387 | + memcpy(rel2, rel, sizeof *rel); |
| 7388 | + ++rel2; |
| 7389 | + } |
| 7390 | + ++rel; |
| 7391 | + } |
| 7392 | +} |
| 7393 | + |
| 7394 | +static void decl_design_flex(init_params *p, Sym *ref, int index) |
| 7395 | +{ |
| 7396 | + if (ref == p->flex_array_ref) { |
| 7397 | + if (index >= ref->c) |
| 7398 | + ref->c = index + 1; |
| 7399 | + } else if (ref->c < 0) |
| 7400 | + tcc_error("flexible array has zero size in this context"); |
| 7401 | +} |
| 7368 | 7402 | |
| 7369 | 7403 | /* t is the array or struct type. c is the array or struct |
| 7370 | 7404 | address. cur_field is the pointer to the current |
| @@ -7372,13 +7406,12 @@ static void init_putz(Section *sec, unsigned long c, int size) · 1 unmodified line |
| 7372 | 7406 | index. 'flags' is as in decl_initializer. |
| 7373 | 7407 | 'al' contains the already initialized length of the |
| 7374 | 7408 | current container (starting at c). This returns the new length of that. */ |
| 7375 | | −static int decl_designator(CType *type, Section *sec, unsigned long c, |
| 7376 | | − Sym **cur_field, int flags, int al, int size) |
| 7409 | +static int decl_designator(init_params *p, CType *type, unsigned long c, |
| 7410 | + Sym **cur_field, int flags, int al) |
| 7377 | 7411 | { |
| 7378 | 7412 | Sym *s, *f; |
| 7379 | 7413 | int index, index_last, align, l, nb_elems, elem_size; |
| 7380 | 7414 | unsigned long corig = c; |
| 7381 | | − TokenString *init_str = NULL; |
| 7382 | 7415 | |
| 7383 | 7416 | elem_size = 0; |
| 7384 | 7417 | nb_elems = 1; |
| @@ -7406,9 +7439,9 @@ static int decl_designator(CType *type, Section *sec, unsigned long c, · 21 unmodified lines |
| 7406 | 7439 | } |
| 7407 | 7440 | skip(']'); |
| 7408 | 7441 | s = type->ref; |
| 7409 | | − if (index < 0 || (s->c >= 0 && index_last >= s->c) || |
| 7410 | | − index_last < index) |
| 7411 | | − tcc_error("invalid index"); |
| 7442 | + decl_design_flex(p, s, index_last); |
| 7443 | + if (index < 0 || index_last >= s->c || index_last < index) |
| 7444 | + tcc_error("index exceeds array bounds or range is empty"); |
| 7412 | 7445 | if (cur_field) |
| 7413 | 7446 | (*cur_field)->c = index_last; |
| 7414 | 7447 | type = pointed_type(type); |
| @@ -7444,72 +7477,82 @@ static int decl_designator(CType *type, Section *sec, unsigned long c, · 29 unmodified lines |
| 7444 | 7477 | no_designator: |
| 7445 | 7478 | if (type->t & VT_ARRAY) { |
| 7446 | 7479 | index = (*cur_field)->c; |
| 7447 | | − if (type->ref->c >= 0 && index >= type->ref->c) |
| 7448 | | − tcc_error("index too large"); |
| 7480 | + s = type->ref; |
| 7481 | + decl_design_flex(p, s, index); |
| 7482 | + if (index >= s->c) |
| 7483 | + tcc_error("too many initializers"); |
| 7449 | 7484 | type = pointed_type(type); |
| 7450 | | − c += index * type_size(type, &align); |
| 7485 | + elem_size = type_size(type, &align); |
| 7486 | + c += index * elem_size; |
| 7451 | 7487 | } else { |
| 7452 | 7488 | f = *cur_field; |
| 7453 | 7489 | while (f && (f->v & SYM_FIRST_ANOM) && (f->type.t & VT_BITFIELD)) |
| 7454 | 7490 | *cur_field = f = f->next; |
| 7455 | 7491 | if (!f) |
| 7456 | | − tcc_error("too many field init"); |
| 7492 | + tcc_error("too many initializers"); |
| 7457 | 7493 | type = &f->type; |
| 7458 | 7494 | c += f->c; |
| 7459 | 7495 | } |
| 7460 | 7496 | } |
| 7461 | 7497 | |
| 7462 | | − /* must put zero in holes (note that doing it that way |
| 7463 | | − ensures that it even works with designators) */ |
| 7464 | | − if (!(flags & DIF_SIZE_ONLY)) { |
| 7465 | | − int zlen = c - (corig + al); |
| 7466 | | − if (type->t & VT_BITFIELD) { /* must include current field too */ |
| 7467 | | − zlen += type_size(type, &align); |
| 7468 | | − if (al + zlen > size) |
| 7469 | | − zlen = size - al; |
| 7470 | | − } |
| 7471 | | − if (zlen > 0) |
| 7472 | | − init_putz(sec, corig + al, zlen); |
| 7473 | | − } |
| 7498 | + if (!elem_size) /* for structs */ |
| 7499 | + elem_size = type_size(type, &align); |
| 7474 | 7500 | |
| 7475 | | − if (!(flags & DIF_SIZE_ONLY) && nb_elems > 1) { |
| 7476 | | − get_init_string(&init_str, tok == TOK_STR || tok == TOK_LSTR ? 2 : 0); |
| 7477 | | − begin_macro(init_str, 1); |
| 7478 | | − next(); |
| 7501 | + /* Using designators the same element can be initialized more |
| 7502 | + than once. In that case we need to delete possibly already |
| 7503 | + existing relocations. */ |
| 7504 | + if (!(flags & DIF_SIZE_ONLY) && c - corig < al) { |
| 7505 | + decl_design_delrels(p->sec, c, elem_size * nb_elems); |
| 7506 | + flags &= ~DIF_CLEAR; /* mark stack dirty too */ |
| 7479 | 7507 | } |
| 7480 | 7508 | |
| 7481 | | − decl_initializer(type, sec, c, flags & ~DIF_FIRST); |
| 7509 | + decl_initializer(p, type, c, flags & ~DIF_FIRST); |
| 7482 | 7510 | |
| 7483 | 7511 | if (!(flags & DIF_SIZE_ONLY) && nb_elems > 1) { |
| 7512 | + Sym aref = {0}; |
| 7513 | + CType t1; |
| 7484 | 7514 | int i; |
| 7485 | | − |
| 7486 | | − for(i = 1; i < nb_elems; i++) { |
| 7487 | | − macro_ptr = init_str->str; |
| 7488 | | − next(); |
| 7489 | | − decl_initializer(type, sec, c + i * elem_size, flags & ~DIF_FIRST); |
| 7490 | | − } |
| 7491 | | − end_macro(); |
| 7492 | | − next(); |
| 7515 | + if (p->sec || (type->t & VT_ARRAY)) { |
| 7516 | + /* make init_putv/vstore believe it were a struct */ |
| 7517 | + aref.c = elem_size; |
| 7518 | + t1.t = VT_STRUCT, t1.ref = &aref; |
| 7519 | + type = &t1; |
| 7520 | + } |
| 7521 | + if (p->sec) |
| 7522 | + vpush_ref(type, p->sec, c, elem_size); |
| 7523 | + else |
| 7524 | + vset(type, VT_LOCAL|VT_LVAL, c); |
| 7525 | + for (i = 1; i < nb_elems; i++) { |
| 7526 | + vdup(); |
| 7527 | + init_putv(p, type, c + elem_size * i); |
| 7528 | + } |
| 7529 | + vpop(); |
| 7493 | 7530 | } |
| 7494 | 7531 | |
| 7495 | | − c += nb_elems * type_size(type, &align); |
| 7532 | + c += nb_elems * elem_size; |
| 7496 | 7533 | if (c - corig > al) |
| 7497 | 7534 | al = c - corig; |
| 7498 | 7535 | return al; |
| 7499 | 7536 | } |
| 7500 | 7537 | |
| 7501 | 7538 | /* store a value or an expression directly in global data or in local array */ |
| 7502 | | −static void init_putv(CType *type, Section *sec, unsigned long c) |
| 7539 | +static void init_putv(init_params *p, CType *type, unsigned long c) |
| 7503 | 7540 | { |
| 7504 | 7541 | int bt; |
| 7505 | 7542 | void *ptr; |
| 7506 | 7543 | CType dtype; |
| 7544 | + int size, align; |
| 7545 | + Section *sec = p->sec; |
| 7507 | 7546 | |
| 7508 | 7547 | dtype = *type; |
| 7509 | 7548 | dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */ |
| 7510 | 7549 | |
| 7550 | + size = type_size(type, &align); |
| 7551 | + if (type->t & VT_BITFIELD) |
| 7552 | + size = (BIT_POS(type->t) + BIT_SIZE(type->t) + 7) / 8; |
| 7553 | + init_assert(p, c + size); |
| 7554 | + |
| 7511 | 7555 | if (sec) { |
| 7512 | | − int size, align; |
| 7513 | 7556 | /* XXX: not portable */ |
| 7514 | 7557 | /* XXX: generate error if incorrect relocation */ |
| 7515 | 7558 | gen_assign_cast(&dtype); |
| @@ -7529,8 +7572,6 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 13 unmodified lines |
| 7529 | 7572 | return; |
| 7530 | 7573 | } |
| 7531 | 7574 | |
| 7532 | | − size = type_size(type, &align); |
| 7533 | | − section_reserve(sec, c + size); |
| 7534 | 7575 | ptr = sec->data + c; |
| 7535 | 7576 | |
| 7536 | 7577 | /* XXX: make code faster ? */ |
| @@ -7567,12 +7608,6 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 30 unmodified lines |
| 7567 | 7608 | continue; |
| 7568 | 7609 | if (rel->r_offset < esym->st_value) |
| 7569 | 7610 | break; |
| 7570 | | − /* Note: if the same fields are initialized multiple |
| 7571 | | − times (possible with designators) then we possibly |
| 7572 | | − add multiple relocations for the same offset here. |
| 7573 | | − That would lead to wrong code, the last reloc needs |
| 7574 | | − to win. We clean this up later after the whole |
| 7575 | | − initializer is parsed. */ |
| 7576 | 7611 | put_elf_reloca(symtab_section, sec, |
| 7577 | 7612 | c + rel->r_offset - esym->st_value, |
| 7578 | 7613 | ELFW(R_TYPE)(rel->r_info), |
| @@ -7610,10 +7645,10 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 31 unmodified lines |
| 7610 | 7645 | case VT_BOOL: |
| 7611 | 7646 | vtop->c.i = vtop->c.i != 0; |
| 7612 | 7647 | case VT_BYTE: |
| 7613 | | − *(char *)ptr |= vtop->c.i; |
| 7648 | + *(char *)ptr = vtop->c.i; |
| 7614 | 7649 | break; |
| 7615 | 7650 | case VT_SHORT: |
| 7616 | | − *(short *)ptr |= vtop->c.i; |
| 7651 | + *(short *)ptr = vtop->c.i; |
| 7617 | 7652 | break; |
| 7618 | 7653 | case VT_FLOAT: |
| 7619 | 7654 | *(float*)ptr = vtop->c.f; |
| @@ -7642,7 +7677,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 22 unmodified lines |
| 7642 | 7677 | break; |
| 7643 | 7678 | #if PTR_SIZE != 8 |
| 7644 | 7679 | case VT_LLONG: |
| 7645 | | − *(long long *)ptr |= vtop->c.i; |
| 7680 | + *(long long *)ptr = vtop->c.i; |
| 7646 | 7681 | break; |
| 7647 | 7682 | #else |
| 7648 | 7683 | case VT_LLONG: |
| @@ -7654,11 +7689,11 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 5 unmodified lines |
| 7654 | 7689 | if (vtop->r & VT_SYM) |
| 7655 | 7690 | greloca(sec, vtop->sym, c, R_DATA_PTR, val); |
| 7656 | 7691 | else |
| 7657 | | − *(addr_t *)ptr |= val; |
| 7692 | + *(addr_t *)ptr = val; |
| 7658 | 7693 | #else |
| 7659 | 7694 | if (vtop->r & VT_SYM) |
| 7660 | 7695 | greloc(sec, vtop->sym, c, R_DATA_PTR); |
| 7661 | | − *(addr_t *)ptr |= val; |
| 7696 | + *(addr_t *)ptr = val; |
| 7662 | 7697 | #endif |
| 7663 | 7698 | break; |
| 7664 | 7699 | } |
| @@ -7669,11 +7704,11 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 4 unmodified lines |
| 7669 | 7704 | if (vtop->r & VT_SYM) |
| 7670 | 7705 | greloca(sec, vtop->sym, c, R_DATA_PTR, val); |
| 7671 | 7706 | else |
| 7672 | | − *(int *)ptr |= val; |
| 7707 | + *(int *)ptr = val; |
| 7673 | 7708 | #else |
| 7674 | 7709 | if (vtop->r & VT_SYM) |
| 7675 | 7710 | greloc(sec, vtop->sym, c, R_DATA_PTR); |
| 7676 | | − *(int *)ptr |= val; |
| 7711 | + *(int *)ptr = val; |
| 7677 | 7712 | #endif |
| 7678 | 7713 | break; |
| 7679 | 7714 | } |
| @@ -7693,8 +7728,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 13 unmodified lines |
| 7693 | 7728 | allocation. 'flags & DIF_FIRST' is true if array '{' must be read (multi |
| 7694 | 7729 | dimension implicit array init handling). 'flags & DIF_SIZE_ONLY' is true if |
| 7695 | 7730 | size only evaluation is wanted (only for arrays). */ |
| 7696 | | −static void decl_initializer(CType *type, Section *sec, unsigned long c, |
| 7697 | | − int flags) |
| 7731 | +static void decl_initializer(init_params *p, CType *type, unsigned long c, int flags) |
| 7698 | 7732 | { |
| 7699 | 7733 | int len, n, no_oblock, i; |
| 7700 | 7734 | int size1, align1; |
| @@ -7702,13 +7736,17 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 1 unmodified line |
| 7702 | 7736 | Sym indexsym; |
| 7703 | 7737 | CType *t1; |
| 7704 | 7738 | |
| 7739 | + /* generate line number info */ |
| 7740 | + if (!p->sec && tcc_state->do_debug) |
| 7741 | + tcc_debug_line(tcc_state); |
| 7742 | + |
| 7705 | 7743 | if (!(flags & DIF_HAVE_ELEM) && tok != '{' && |
| 7706 | 7744 | /* In case of strings we have special handling for arrays, so |
| 7707 | 7745 | don't consume them as initializer value (which would commit them |
| 7708 | 7746 | to some anonymous symbol). */ |
| 7709 | 7747 | tok != TOK_LSTR && tok != TOK_STR && |
| 7710 | 7748 | !(flags & DIF_SIZE_ONLY)) { |
| 7711 | | − parse_init_elem(!sec ? EXPR_ANY : EXPR_CONST); |
| 7749 | + parse_init_elem(!p->sec ? EXPR_ANY : EXPR_CONST); |
| 7712 | 7750 | flags |= DIF_HAVE_ELEM; |
| 7713 | 7751 | } |
| 7714 | 7752 | |
| @@ -7718,23 +7756,21 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 3 unmodified lines |
| 7718 | 7756 | The source type might have VT_CONSTANT set, which is |
| 7719 | 7757 | of course assignable to non-const elements. */ |
| 7720 | 7758 | is_compatible_unqualified_types(type, &vtop->type)) { |
| 7721 | | − init_putv(type, sec, c); |
| 7722 | | − } else if (type->t & VT_ARRAY) { |
| 7723 | | − s = type->ref; |
| 7724 | | − n = s->c; |
| 7725 | | − t1 = pointed_type(type); |
| 7726 | | − size1 = type_size(t1, &align1); |
| 7759 | + goto init_putv; |
| 7727 | 7760 | |
| 7761 | + } else if (type->t & VT_ARRAY) { |
| 7728 | 7762 | no_oblock = 1; |
| 7729 | 7763 | if (((flags & DIF_FIRST) && tok != TOK_LSTR && tok != TOK_STR) || |
| 7730 | 7764 | tok == '{') { |
| 7731 | | − if (tok != '{') |
| 7732 | | − tcc_error("character array initializer must be a literal," |
| 7733 | | − " optionally enclosed in braces"); |
| 7734 | 7765 | skip('{'); |
| 7735 | 7766 | no_oblock = 0; |
| 7736 | 7767 | } |
| 7737 | 7768 | |
| 7769 | + s = type->ref; |
| 7770 | + n = s->c; |
| 7771 | + t1 = pointed_type(type); |
| 7772 | + size1 = type_size(t1, &align1); |
| 7773 | + |
| 7738 | 7774 | /* only parse strings here if correct type (otherwise: handle |
| 7739 | 7775 | them as ((w)char *) expressions */ |
| 7740 | 7776 | if ((tok == TOK_LSTR && |
| @@ -7744,7 +7780,6 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 3 unmodified lines |
| 7744 | 7780 | (t1->t & VT_BTYPE) == VT_INT |
| 7745 | 7781 | #endif |
| 7746 | 7782 | ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) { |
| 7747 | | − int nb; |
| 7748 | 7783 | len = 0; |
| 7749 | 7784 | cstr_reset(&initstr); |
| 7750 | 7785 | if (size1 != (tok == TOK_STR ? 1 : sizeof(nwchar_t))) |
| @@ -7766,54 +7801,61 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 15 unmodified lines |
| 7766 | 7801 | unget_tok(size1 == 1 ? TOK_STR : TOK_LSTR); |
| 7767 | 7802 | tokc.str.size = initstr.size; |
| 7768 | 7803 | tokc.str.data = initstr.data; |
| 7769 | | − indexsym.c = 0; |
| 7770 | | − f = &indexsym; |
| 7771 | | − goto do_init_list; |
| 7804 | + goto do_init_array; |
| 7772 | 7805 | } |
| 7773 | | − nb = len; |
| 7774 | | − if (n >= 0 && len > n) |
| 7775 | | − nb = n; |
| 7806 | + |
| 7776 | 7807 | if (!(flags & DIF_SIZE_ONLY)) { |
| 7777 | | − if (sec && !NODATA_WANTED && |
| 7778 | | − (c + nb > sec->data_allocated)) |
| 7779 | | − nb = sec->data_allocated - c; |
| 7808 | + int nb = n; |
| 7809 | + if (len < nb) |
| 7810 | + nb = len; |
| 7780 | 7811 | if (len > nb) |
| 7781 | 7812 | tcc_warning("initializer-string for array is too long"); |
| 7782 | 7813 | /* in order to go faster for common case (char |
| 7783 | 7814 | string in global variable, we handle it |
| 7784 | 7815 | specifically */ |
| 7785 | | − if (sec && size1 == 1) { |
| 7816 | + if (p->sec && size1 == 1) { |
| 7817 | + init_assert(p, c + nb); |
| 7786 | 7818 | if (!NODATA_WANTED) |
| 7787 | | − memcpy(sec->data + c, initstr.data, nb); |
| 7819 | + memcpy(p->sec->data + c, initstr.data, nb); |
| 7788 | 7820 | } else { |
| 7789 | | − for(i=0;i<nb;i++) { |
| 7790 | | − if (size1 == 1) |
| 7821 | + for(i=0;i<n;i++) { |
| 7822 | + if (i >= nb) { |
| 7823 | + /* only add trailing zero if enough storage (no |
| 7824 | + warning in this case since it is standard) */ |
| 7825 | + if (flags & DIF_CLEAR) |
| 7826 | + break; |
| 7827 | + if (n - i >= 4) { |
| 7828 | + init_putz(p, c + i * size1, (n - i) * size1); |
| 7829 | + break; |
| 7830 | + } |
| 7831 | + ch = 0; |
| 7832 | + } else if (size1 == 1) |
| 7791 | 7833 | ch = ((unsigned char *)initstr.data)[i]; |
| 7792 | 7834 | else |
| 7793 | 7835 | ch = ((nwchar_t *)initstr.data)[i]; |
| 7794 | 7836 | vpushi(ch); |
| 7795 | | − init_putv(t1, sec, c + i * size1); |
| 7837 | + init_putv(p, t1, c + i * size1); |
| 7796 | 7838 | } |
| 7797 | 7839 | } |
| 7840 | + } else { |
| 7841 | + decl_design_flex(p, s, len); |
| 7798 | 7842 | } |
| 7799 | | − /* only add trailing zero if enough storage (no |
| 7800 | | − warning in this case since it is standard) */ |
| 7801 | | − if (n < 0 || len < n) { |
| 7802 | | − if (!(flags & DIF_SIZE_ONLY)) { |
| 7803 | | − vpushi(0); |
| 7804 | | − init_putv(t1, sec, c + (len * size1)); |
| 7805 | | − } |
| 7806 | | − len++; |
| 7807 | | − } |
| 7808 | | − len *= size1; |
| 7809 | 7843 | } else { |
| 7844 | + |
| 7845 | + do_init_array: |
| 7810 | 7846 | indexsym.c = 0; |
| 7811 | 7847 | f = &indexsym; |
| 7812 | 7848 | |
| 7813 | 7849 | do_init_list: |
| 7850 | + /* zero memory once in advance */ |
| 7851 | + if (!(flags & (DIF_CLEAR | DIF_SIZE_ONLY))) { |
| 7852 | + init_putz(p, c, n*size1); |
| 7853 | + flags |= DIF_CLEAR; |
| 7854 | + } |
| 7855 | + |
| 7814 | 7856 | len = 0; |
| 7815 | 7857 | while (tok != '}' || (flags & DIF_HAVE_ELEM)) { |
| 7816 | | − len = decl_designator(type, sec, c, &f, flags, len, n*size1); |
| 7858 | + len = decl_designator(p, type, c, &f, flags, len); |
| 7817 | 7859 | flags &= ~DIF_HAVE_ELEM; |
| 7818 | 7860 | if (type->t & VT_ARRAY) { |
| 7819 | 7861 | ++indexsym.c; |
| @@ -7836,16 +7878,9 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 16 unmodified lines |
| 7836 | 7878 | skip(','); |
| 7837 | 7879 | } |
| 7838 | 7880 | } |
| 7839 | | − /* put zeros at the end */ |
| 7840 | | − if (!(flags & DIF_SIZE_ONLY) && len < n*size1) |
| 7841 | | − init_putz(sec, c + len, n*size1 - len); |
| 7842 | 7881 | if (!no_oblock) |
| 7843 | 7882 | skip('}'); |
| 7844 | | − /* patch type size if needed, which happens only for array types */ |
| 7845 | | − if (n < 0) |
| 7846 | | − s->c = size1 == 1 ? len : ((len + size1 - 1)/size1); |
| 7847 | 7883 | } else if ((type->t & VT_BTYPE) == VT_STRUCT) { |
| 7848 | | − size1 = 1; |
| 7849 | 7884 | no_oblock = 1; |
| 7850 | 7885 | if ((flags & DIF_FIRST) || tok == '{') { |
| 7851 | 7886 | skip('{'); |
| @@ -7854,12 +7889,13 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 2 unmodified lines |
| 7854 | 7889 | s = type->ref; |
| 7855 | 7890 | f = s->next; |
| 7856 | 7891 | n = s->c; |
| 7892 | + size1 = 1; |
| 7857 | 7893 | goto do_init_list; |
| 7858 | 7894 | } else if (tok == '{') { |
| 7859 | 7895 | if (flags & DIF_HAVE_ELEM) |
| 7860 | 7896 | skip(';'); |
| 7861 | 7897 | next(); |
| 7862 | | − decl_initializer(type, sec, c, flags & ~DIF_HAVE_ELEM); |
| 7898 | + decl_initializer(p, type, c, flags & ~DIF_HAVE_ELEM); |
| 7863 | 7899 | skip('}'); |
| 7864 | 7900 | } else if ((flags & DIF_SIZE_ONLY)) { |
| 7865 | 7901 | /* If we supported only ISO C we wouldn't have to accept calling |
| @@ -7877,9 +7913,17 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 11 unmodified lines |
| 7877 | 7913 | string constant to memory too early. */ |
| 7878 | 7914 | if (tok != TOK_STR && tok != TOK_LSTR) |
| 7879 | 7915 | expect("string constant"); |
| 7880 | | − parse_init_elem(!sec ? EXPR_ANY : EXPR_CONST); |
| 7916 | + parse_init_elem(!p->sec ? EXPR_ANY : EXPR_CONST); |
| 7881 | 7917 | } |
| 7882 | | − init_putv(type, sec, c); |
| 7918 | + init_putv: |
| 7919 | + if (!p->sec && (flags & DIF_CLEAR) /* container was already zero'd */ |
| 7920 | + && (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST |
| 7921 | + && vtop->c.i == 0 |
| 7922 | + && btype_size(type->t & VT_BTYPE) /* not for fp constants */ |
| 7923 | + ) |
| 7924 | + vpop(); |
| 7925 | + else |
| 7926 | + init_putv(p, type, c); |
| 7883 | 7927 | } |
| 7884 | 7928 | } |
| 7885 | 7929 | |
| @@ -7903,38 +7947,60 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 17 unmodified lines |
| 7903 | 7947 | #ifdef CONFIG_TCC_BCHECK |
| 7904 | 7948 | int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED; |
| 7905 | 7949 | #endif |
| 7950 | + init_params p = {0}; |
| 7906 | 7951 | |
| 7907 | 7952 | /* Always allocate static or global variables */ |
| 7908 | 7953 | if (v && (r & VT_VALMASK) == VT_CONST) |
| 7909 | 7954 | nocode_wanted |= 0x80000000; |
| 7910 | 7955 | |
| 7911 | 7956 | flexible_array = NULL; |
| 7912 | | − if ((type->t & VT_BTYPE) == VT_STRUCT) { |
| 7957 | + size = type_size(type, &align); |
| 7958 | + |
| 7959 | + /* exactly one flexible array may be initialized, either the |
| 7960 | + toplevel array or the last member of the toplevel struct */ |
| 7961 | + |
| 7962 | + if (size < 0) { |
| 7963 | + /* If the base type itself was an array type of unspecified size |
| 7964 | + (like in 'typedef int arr[]; arr x = {1};') then we will |
| 7965 | + overwrite the unknown size by the real one for this decl. |
| 7966 | + We need to unshare the ref symbol holding that size. */ |
| 7967 | + type->ref = sym_push(SYM_FIELD, &type->ref->type, 0, type->ref->c); |
| 7968 | + p.flex_array_ref = type->ref; |
| 7969 | + |
| 7970 | + } else if (has_init && (type->t & VT_BTYPE) == VT_STRUCT) { |
| 7913 | 7971 | Sym *field = type->ref->next; |
| 7914 | 7972 | if (field) { |
| 7915 | 7973 | while (field->next) |
| 7916 | 7974 | field = field->next; |
| 7917 | | − if (field->type.t & VT_ARRAY && field->type.ref->c < 0) |
| 7975 | + if (field->type.t & VT_ARRAY && field->type.ref->c < 0) { |
| 7918 | 7976 | flexible_array = field; |
| 7977 | + p.flex_array_ref = field->type.ref; |
| 7978 | + size = -1; |
| 7979 | + } |
| 7919 | 7980 | } |
| 7920 | 7981 | } |
| 7921 | 7982 | |
| 7922 | | − size = type_size(type, &align); |
| 7923 | | − /* If unknown size, we must evaluate it before |
| 7924 | | − evaluating initializers because |
| 7925 | | − initializers can generate global data too |
| 7926 | | − (e.g. string pointers or ISOC99 compound |
| 7927 | | − literals). It also simplifies local |
| 7928 | | − initializers handling */ |
| 7929 | | − if (size < 0 || (flexible_array && has_init)) { |
| 7983 | + if (size < 0) { |
| 7984 | + /* If unknown size, do a dry-run 1st pass */ |
| 7930 | 7985 | if (!has_init) |
| 7931 | 7986 | tcc_error("unknown type size"); |
| 7932 | | − get_init_string(&init_str, has_init); |
| 7987 | + if (has_init == 2) { |
| 7988 | + /* only get strings */ |
| 7989 | + init_str = tok_str_alloc(); |
| 7990 | + while (tok == TOK_STR || tok == TOK_LSTR) { |
| 7991 | + tok_str_add_tok(init_str); |
| 7992 | + next(); |
| 7993 | + } |
| 7994 | + tok_str_add(init_str, -1); |
| 7995 | + tok_str_add(init_str, 0); |
| 7996 | + } else |
| 7997 | + skip_or_save_block(&init_str); |
| 7998 | + unget_tok(0); |
| 7933 | 7999 | |
| 7934 | 8000 | /* compute size */ |
| 7935 | 8001 | begin_macro(init_str, 1); |
| 7936 | 8002 | next(); |
| 7937 | | − decl_initializer(type, NULL, 0, DIF_FIRST | DIF_SIZE_ONLY); |
| 8003 | + decl_initializer(&p, type, 0, DIF_FIRST | DIF_SIZE_ONLY); |
| 7938 | 8004 | /* prepare second initializer parsing */ |
| 7939 | 8005 | macro_ptr = init_str->str; |
| 7940 | 8006 | next(); |
| @@ -7943,13 +8009,14 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 2 unmodified lines |
| 7943 | 8009 | size = type_size(type, &align); |
| 7944 | 8010 | if (size < 0) |
| 7945 | 8011 | tcc_error("unknown type size"); |
| 8012 | + |
| 8013 | + /* If there's a flex member and it was used in the initializer |
| 8014 | + adjust size. */ |
| 8015 | + if (flexible_array && flexible_array->type.ref->c > 0) |
| 8016 | + size += flexible_array->type.ref->c |
| 8017 | + * pointed_size(&flexible_array->type); |
| 7946 | 8018 | } |
| 7947 | | − /* If there's a flex member and it was used in the initializer |
| 7948 | | − adjust size. */ |
| 7949 | | − if (flexible_array && |
| 7950 | | − flexible_array->type.ref->c > 0) |
| 7951 | | − size += flexible_array->type.ref->c |
| 7952 | | − * pointed_size(&flexible_array->type); |
| 8019 | + |
| 7953 | 8020 | /* take into account specified alignment if bigger */ |
| 7954 | 8021 | if (ad->a.aligned) { |
| 7955 | 8022 | int speca = 1 << (ad->a.aligned - 1); |
| @@ -7972,6 +8039,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 16 unmodified lines |
| 7972 | 8039 | #endif |
| 7973 | 8040 | loc = (loc - size) & -align; |
| 7974 | 8041 | addr = loc; |
| 8042 | + p.local_offset = addr + size; |
| 7975 | 8043 | #ifdef CONFIG_TCC_BCHECK |
| 7976 | 8044 | if (bcheck && v) { |
| 7977 | 8045 | /* add padding between stack variables for bound checking */ |
| @@ -8088,12 +8156,8 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 110 unmodified lines |
| 8088 | 8156 | cur_scope->vla.loc = addr; |
| 8089 | 8157 | cur_scope->vla.num++; |
| 8090 | 8158 | } else if (has_init) { |
| 8091 | | − size_t oldreloc_offset = 0; |
| 8092 | | − if (sec && sec->reloc) |
| 8093 | | − oldreloc_offset = sec->reloc->data_offset; |
| 8094 | | − decl_initializer(type, sec, addr, DIF_FIRST); |
| 8095 | | − if (sec && sec->reloc) |
| 8096 | | − squeeze_multi_relocs(sec, oldreloc_offset); |
| 8159 | + p.sec = sec; |
| 8160 | + decl_initializer(&p, type, addr, DIF_FIRST); |
| 8097 | 8161 | /* patch flexible array member size back to -1, */ |
| 8098 | 8162 | /* for possible subsequent similar declarations */ |
| 8099 | 8163 | if (flexible_array) |
| @@ -8288,14 +8352,6 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym) · 188 unmodified lines |
| 8288 | 8352 | } |
| 8289 | 8353 | while (1) { /* iterate thru each declaration */ |
| 8290 | 8354 | type = btype; |
| 8291 | | − /* If the base type itself was an array type of unspecified |
| 8292 | | − size (like in 'typedef int arr[]; arr x = {1};') then |
| 8293 | | − we will overwrite the unknown size by the real one for |
| 8294 | | − this decl. We need to unshare the ref symbol holding |
| 8295 | | − that size. */ |
| 8296 | | − if ((type.t & VT_ARRAY) && type.ref->c < 0) { |
| 8297 | | − type.ref = sym_push(SYM_FIELD, &type.ref->type, 0, type.ref->c); |
| 8298 | | − } |
| 8299 | 8355 | ad = adbase; |
| 8300 | 8356 | type_decl(&type, &ad, &v, TYPE_DIRECT); |
| 8301 | 8357 | #if 0 |