| @@ -123,6 +123,12 @@ static struct scope { · 122 unmodified lines |
| 123 | Sym *lstk, *llstk; | 123 | Sym *lstk, *llstk; |
| 124 | } *cur_scope, *loop_scope, *root_scope; | 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 | /* stab debug support */ | 133 | /* stab debug support */ |
| 128 | | 134 | |
| @@ -218,8 +224,8 @@ static int is_compatible_types(CType *type1, CType *type2); · 89 unmodified lines |
| 218 | static int parse_btype(CType *type, AttributeDef *ad); | 224 | static int parse_btype(CType *type, AttributeDef *ad); |
| 219 | static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td); | 225 | static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td); |
| 220 | static void parse_expr_type(CType *type); | 226 | static void parse_expr_type(CType *type); |
| 221 | static void init_putv(CType *type, Section *sec, unsigned long c); | 227 | static void init_putv(init_params *p, CType *type, unsigned long c); |
| 222 | static void decl_initializer(CType *type, Section *sec, unsigned long c, int flags); | 228 | static void decl_initializer(init_params *p, CType *type, unsigned long c, int flags); |
| 223 | static void block(int is_expr); | 229 | static void block(int is_expr); |
| 224 | static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope); | 230 | static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope); |
| 225 | static void decl(int l); | 231 | static void decl(int l); |
| @@ -2167,16 +2173,17 @@ ST_FUNC int gv(int rc) · 1941 unmodified lines |
| 2167 | } else { | 2173 | } else { |
| 2168 | if (is_float(vtop->type.t) && | 2174 | if (is_float(vtop->type.t) && |
| 2169 | (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { | 2175 | (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { |
| 2170 | unsigned long offset; | | |
| 2171 | /* CPUs usually cannot use float constants, so we store them | 2176 | /* CPUs usually cannot use float constants, so we store them |
| 2172 | generically in data segment */ | 2177 | generically in data segment */ |
| | 2178 | init_params p = { data_section }; |
| | 2179 | unsigned long offset; |
| 2173 | size = type_size(&vtop->type, &align); | 2180 | size = type_size(&vtop->type, &align); |
| 2174 | if (NODATA_WANTED) | 2181 | if (NODATA_WANTED) |
| 2175 | size = 0, align = 1; | 2182 | size = 0, align = 1; |
| 2176 | offset = section_add(data_section, size, align); | 2183 | offset = section_add(p.sec, size, align); |
| 2177 | vpush_ref(&vtop->type, data_section, offset, size); | 2184 | vpush_ref(&vtop->type, p.sec, offset, size); |
| 2178 | vswap(); | 2185 | vswap(); |
| 2179 | init_putv(&vtop->type, data_section, offset); | 2186 | init_putv(&p, &vtop->type, offset); |
| 2180 | vtop->r |= VT_LVAL; | 2187 | vtop->r |= VT_LVAL; |
| 2181 | } | 2188 | } |
| 2182 | #ifdef CONFIG_TCC_BCHECK | 2189 | #ifdef CONFIG_TCC_BCHECK |
| @@ -5444,7 +5451,7 @@ static void parse_builtin_params(int nc, const char *args) · 3261 unmodified lines |
| 5444 | type.t = VT_SIZE_T; | 5451 | type.t = VT_SIZE_T; |
| 5445 | break; | 5452 | break; |
| 5446 | default: | 5453 | default: |
| 5447 | tcc_error("internal error"); | 5454 | break; |
| 5448 | } | 5455 | } |
| 5449 | gen_assign_cast(&type); | 5456 | gen_assign_cast(&type); |
| 5450 | } | 5457 | } |
| @@ -6102,7 +6109,8 @@ special_math_val: · 651 unmodified lines |
| 6102 | problems */ | 6109 | problems */ |
| 6103 | vseti(VT_LOCAL, loc); | 6110 | vseti(VT_LOCAL, loc); |
| 6104 | #ifdef CONFIG_TCC_BCHECK | 6111 | #ifdef CONFIG_TCC_BCHECK |
| 6105 | loc -= tcc_state->do_bounds_check != 0; | 6112 | if (tcc_state->do_bounds_check) |
| | 6113 | --loc; |
| 6106 | #endif | 6114 | #endif |
| 6107 | ret.c = vtop->c; | 6115 | ret.c = vtop->c; |
| 6108 | if (ret_nregs < 0) | 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 | #define EXPR_CONST 1 | 7307 | #define EXPR_CONST 1 |
| 7317 | #define EXPR_ANY 2 | 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 | /* put zeros for variable based init */ | 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 | /* nothing to do because globals are already set to zero */ | 7353 | /* nothing to do because globals are already set to zero */ |
| 7351 | } else { | 7354 | } else { |
| 7352 | vpush_global_sym(&func_old_type, TOK_memset); | 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 | #define DIF_FIRST 1 | 7368 | #define DIF_FIRST 1 |
| 7366 | #define DIF_SIZE_ONLY 2 | 7369 | #define DIF_SIZE_ONLY 2 |
| 7367 | #define DIF_HAVE_ELEM 4 | 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 | /* t is the array or struct type. c is the array or struct | 7403 | /* t is the array or struct type. c is the array or struct |
| 7370 | address. cur_field is the pointer to the current | 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 | index. 'flags' is as in decl_initializer. | 7406 | index. 'flags' is as in decl_initializer. |
| 7373 | 'al' contains the already initialized length of the | 7407 | 'al' contains the already initialized length of the |
| 7374 | current container (starting at c). This returns the new length of that. */ | 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, | 7409 | static int decl_designator(init_params *p, CType *type, unsigned long c, |
| 7376 | Sym **cur_field, int flags, int al, int size) | 7410 | Sym **cur_field, int flags, int al) |
| 7377 | { | 7411 | { |
| 7378 | Sym *s, *f; | 7412 | Sym *s, *f; |
| 7379 | int index, index_last, align, l, nb_elems, elem_size; | 7413 | int index, index_last, align, l, nb_elems, elem_size; |
| 7380 | unsigned long corig = c; | 7414 | unsigned long corig = c; |
| 7381 | TokenString *init_str = NULL; | | |
| 7382 | | 7415 | |
| 7383 | elem_size = 0; | 7416 | elem_size = 0; |
| 7384 | nb_elems = 1; | 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 | skip(']'); | 7440 | skip(']'); |
| 7408 | s = type->ref; | 7441 | s = type->ref; |
| 7409 | if (index < 0 || (s->c >= 0 && index_last >= s->c) || | 7442 | decl_design_flex(p, s, index_last); |
| 7410 | index_last < index) | 7443 | if (index < 0 || index_last >= s->c || index_last < index) |
| 7411 | tcc_error("invalid index"); | 7444 | tcc_error("index exceeds array bounds or range is empty"); |
| 7412 | if (cur_field) | 7445 | if (cur_field) |
| 7413 | (*cur_field)->c = index_last; | 7446 | (*cur_field)->c = index_last; |
| 7414 | type = pointed_type(type); | 7447 | type = pointed_type(type); |
| @@ -7444,72 +7477,82 @@ static int decl_designator(CType *type, Section *sec, unsigned long c, · 29 unmodified lines |
| 7444 | no_designator: | 7477 | no_designator: |
| 7445 | if (type->t & VT_ARRAY) { | 7478 | if (type->t & VT_ARRAY) { |
| 7446 | index = (*cur_field)->c; | 7479 | index = (*cur_field)->c; |
| 7447 | if (type->ref->c >= 0 && index >= type->ref->c) | 7480 | s = type->ref; |
| 7448 | tcc_error("index too large"); | 7481 | decl_design_flex(p, s, index); |
| | 7482 | if (index >= s->c) |
| | 7483 | tcc_error("too many initializers"); |
| 7449 | type = pointed_type(type); | 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 | } else { | 7487 | } else { |
| 7452 | f = *cur_field; | 7488 | f = *cur_field; |
| 7453 | while (f && (f->v & SYM_FIRST_ANOM) && (f->type.t & VT_BITFIELD)) | 7489 | while (f && (f->v & SYM_FIRST_ANOM) && (f->type.t & VT_BITFIELD)) |
| 7454 | *cur_field = f = f->next; | 7490 | *cur_field = f = f->next; |
| 7455 | if (!f) | 7491 | if (!f) |
| 7456 | tcc_error("too many field init"); | 7492 | tcc_error("too many initializers"); |
| 7457 | type = &f->type; | 7493 | type = &f->type; |
| 7458 | c += f->c; | 7494 | c += f->c; |
| 7459 | } | 7495 | } |
| 7460 | } | 7496 | } |
| 7461 | | 7497 | |
| 7462 | /* must put zero in holes (note that doing it that way | 7498 | if (!elem_size) /* for structs */ |
| 7463 | ensures that it even works with designators) */ | 7499 | elem_size = type_size(type, &align); |
| 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 | } | | |
| 7474 | | 7500 | |
| 7475 | if (!(flags & DIF_SIZE_ONLY) && nb_elems > 1) { | 7501 | /* Using designators the same element can be initialized more |
| 7476 | get_init_string(&init_str, tok == TOK_STR || tok == TOK_LSTR ? 2 : 0); | 7502 | than once. In that case we need to delete possibly already |
| 7477 | begin_macro(init_str, 1); | 7503 | existing relocations. */ |
| 7478 | next(); | 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 | if (!(flags & DIF_SIZE_ONLY) && nb_elems > 1) { | 7511 | if (!(flags & DIF_SIZE_ONLY) && nb_elems > 1) { |
| | 7512 | Sym aref = {0}; |
| | 7513 | CType t1; |
| 7484 | int i; | 7514 | int i; |
| 7485 | | 7515 | if (p->sec || (type->t & VT_ARRAY)) { |
| 7486 | for(i = 1; i < nb_elems; i++) { | 7516 | /* make init_putv/vstore believe it were a struct */ |
| 7487 | macro_ptr = init_str->str; | 7517 | aref.c = elem_size; |
| 7488 | next(); | 7518 | t1.t = VT_STRUCT, t1.ref = &aref; |
| 7489 | decl_initializer(type, sec, c + i * elem_size, flags & ~DIF_FIRST); | 7519 | type = &t1; |
| 7490 | } | 7520 | } |
| 7491 | end_macro(); | 7521 | if (p->sec) |
| 7492 | next(); | 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 | if (c - corig > al) | 7533 | if (c - corig > al) |
| 7497 | al = c - corig; | 7534 | al = c - corig; |
| 7498 | return al; | 7535 | return al; |
| 7499 | } | 7536 | } |
| 7500 | | 7537 | |
| 7501 | /* store a value or an expression directly in global data or in local array */ | 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 | int bt; | 7541 | int bt; |
| 7505 | void *ptr; | 7542 | void *ptr; |
| 7506 | CType dtype; | 7543 | CType dtype; |
| | 7544 | int size, align; |
| | 7545 | Section *sec = p->sec; |
| 7507 | | 7546 | |
| 7508 | dtype = *type; | 7547 | dtype = *type; |
| 7509 | dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */ | 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 | if (sec) { | 7555 | if (sec) { |
| 7512 | int size, align; | | |
| 7513 | /* XXX: not portable */ | 7556 | /* XXX: not portable */ |
| 7514 | /* XXX: generate error if incorrect relocation */ | 7557 | /* XXX: generate error if incorrect relocation */ |
| 7515 | gen_assign_cast(&dtype); | 7558 | gen_assign_cast(&dtype); |
| @@ -7529,8 +7572,6 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 13 unmodified lines |
| 7529 | return; | 7572 | return; |
| 7530 | } | 7573 | } |
| 7531 | | 7574 | |
| 7532 | size = type_size(type, &align); | | |
| 7533 | section_reserve(sec, c + size); | | |
| 7534 | ptr = sec->data + c; | 7575 | ptr = sec->data + c; |
| 7535 | | 7576 | |
| 7536 | /* XXX: make code faster ? */ | 7577 | /* XXX: make code faster ? */ |
| @@ -7567,12 +7608,6 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 30 unmodified lines |
| 7567 | continue; | 7608 | continue; |
| 7568 | if (rel->r_offset < esym->st_value) | 7609 | if (rel->r_offset < esym->st_value) |
| 7569 | break; | 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 | put_elf_reloca(symtab_section, sec, | 7611 | put_elf_reloca(symtab_section, sec, |
| 7577 | c + rel->r_offset - esym->st_value, | 7612 | c + rel->r_offset - esym->st_value, |
| 7578 | ELFW(R_TYPE)(rel->r_info), | 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 | case VT_BOOL: | 7645 | case VT_BOOL: |
| 7611 | vtop->c.i = vtop->c.i != 0; | 7646 | vtop->c.i = vtop->c.i != 0; |
| 7612 | case VT_BYTE: | 7647 | case VT_BYTE: |
| 7613 | *(char *)ptr |= vtop->c.i; | 7648 | *(char *)ptr = vtop->c.i; |
| 7614 | break; | 7649 | break; |
| 7615 | case VT_SHORT: | 7650 | case VT_SHORT: |
| 7616 | *(short *)ptr |= vtop->c.i; | 7651 | *(short *)ptr = vtop->c.i; |
| 7617 | break; | 7652 | break; |
| 7618 | case VT_FLOAT: | 7653 | case VT_FLOAT: |
| 7619 | *(float*)ptr = vtop->c.f; | 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 | break; | 7677 | break; |
| 7643 | #if PTR_SIZE != 8 | 7678 | #if PTR_SIZE != 8 |
| 7644 | case VT_LLONG: | 7679 | case VT_LLONG: |
| 7645 | *(long long *)ptr |= vtop->c.i; | 7680 | *(long long *)ptr = vtop->c.i; |
| 7646 | break; | 7681 | break; |
| 7647 | #else | 7682 | #else |
| 7648 | case VT_LLONG: | 7683 | case VT_LLONG: |
| @@ -7654,11 +7689,11 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 5 unmodified lines |
| 7654 | if (vtop->r & VT_SYM) | 7689 | if (vtop->r & VT_SYM) |
| 7655 | greloca(sec, vtop->sym, c, R_DATA_PTR, val); | 7690 | greloca(sec, vtop->sym, c, R_DATA_PTR, val); |
| 7656 | else | 7691 | else |
| 7657 | *(addr_t *)ptr |= val; | 7692 | *(addr_t *)ptr = val; |
| 7658 | #else | 7693 | #else |
| 7659 | if (vtop->r & VT_SYM) | 7694 | if (vtop->r & VT_SYM) |
| 7660 | greloc(sec, vtop->sym, c, R_DATA_PTR); | 7695 | greloc(sec, vtop->sym, c, R_DATA_PTR); |
| 7661 | *(addr_t *)ptr |= val; | 7696 | *(addr_t *)ptr = val; |
| 7662 | #endif | 7697 | #endif |
| 7663 | break; | 7698 | break; |
| 7664 | } | 7699 | } |
| @@ -7669,11 +7704,11 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 4 unmodified lines |
| 7669 | if (vtop->r & VT_SYM) | 7704 | if (vtop->r & VT_SYM) |
| 7670 | greloca(sec, vtop->sym, c, R_DATA_PTR, val); | 7705 | greloca(sec, vtop->sym, c, R_DATA_PTR, val); |
| 7671 | else | 7706 | else |
| 7672 | *(int *)ptr |= val; | 7707 | *(int *)ptr = val; |
| 7673 | #else | 7708 | #else |
| 7674 | if (vtop->r & VT_SYM) | 7709 | if (vtop->r & VT_SYM) |
| 7675 | greloc(sec, vtop->sym, c, R_DATA_PTR); | 7710 | greloc(sec, vtop->sym, c, R_DATA_PTR); |
| 7676 | *(int *)ptr |= val; | 7711 | *(int *)ptr = val; |
| 7677 | #endif | 7712 | #endif |
| 7678 | break; | 7713 | break; |
| 7679 | } | 7714 | } |
| @@ -7693,8 +7728,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 13 unmodified lines |
| 7693 | allocation. 'flags & DIF_FIRST' is true if array '{' must be read (multi | 7728 | allocation. 'flags & DIF_FIRST' is true if array '{' must be read (multi |
| 7694 | dimension implicit array init handling). 'flags & DIF_SIZE_ONLY' is true if | 7729 | dimension implicit array init handling). 'flags & DIF_SIZE_ONLY' is true if |
| 7695 | size only evaluation is wanted (only for arrays). */ | 7730 | size only evaluation is wanted (only for arrays). */ |
| 7696 | static void decl_initializer(CType *type, Section *sec, unsigned long c, | 7731 | static void decl_initializer(init_params *p, CType *type, unsigned long c, int flags) |
| 7697 | int flags) | | |
| 7698 | { | 7732 | { |
| 7699 | int len, n, no_oblock, i; | 7733 | int len, n, no_oblock, i; |
| 7700 | int size1, align1; | 7734 | int size1, align1; |
| @@ -7702,13 +7736,17 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 1 unmodified line |
| 7702 | Sym indexsym; | 7736 | Sym indexsym; |
| 7703 | CType *t1; | 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 | if (!(flags & DIF_HAVE_ELEM) && tok != '{' && | 7743 | if (!(flags & DIF_HAVE_ELEM) && tok != '{' && |
| 7706 | /* In case of strings we have special handling for arrays, so | 7744 | /* In case of strings we have special handling for arrays, so |
| 7707 | don't consume them as initializer value (which would commit them | 7745 | don't consume them as initializer value (which would commit them |
| 7708 | to some anonymous symbol). */ | 7746 | to some anonymous symbol). */ |
| 7709 | tok != TOK_LSTR && tok != TOK_STR && | 7747 | tok != TOK_LSTR && tok != TOK_STR && |
| 7710 | !(flags & DIF_SIZE_ONLY)) { | 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 | flags |= DIF_HAVE_ELEM; | 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 | The source type might have VT_CONSTANT set, which is | 7756 | The source type might have VT_CONSTANT set, which is |
| 7719 | of course assignable to non-const elements. */ | 7757 | of course assignable to non-const elements. */ |
| 7720 | is_compatible_unqualified_types(type, &vtop->type)) { | 7758 | is_compatible_unqualified_types(type, &vtop->type)) { |
| 7721 | init_putv(type, sec, c); | 7759 | goto init_putv; |
| 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); | | |
| 7727 | | 7760 | |
| | 7761 | } else if (type->t & VT_ARRAY) { |
| 7728 | no_oblock = 1; | 7762 | no_oblock = 1; |
| 7729 | if (((flags & DIF_FIRST) && tok != TOK_LSTR && tok != TOK_STR) || | 7763 | if (((flags & DIF_FIRST) && tok != TOK_LSTR && tok != TOK_STR) || |
| 7730 | tok == '{') { | 7764 | tok == '{') { |
| 7731 | if (tok != '{') | | |
| 7732 | tcc_error("character array initializer must be a literal," | | |
| 7733 | " optionally enclosed in braces"); | | |
| 7734 | skip('{'); | 7765 | skip('{'); |
| 7735 | no_oblock = 0; | 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 | /* only parse strings here if correct type (otherwise: handle | 7774 | /* only parse strings here if correct type (otherwise: handle |
| 7739 | them as ((w)char *) expressions */ | 7775 | them as ((w)char *) expressions */ |
| 7740 | if ((tok == TOK_LSTR && | 7776 | if ((tok == TOK_LSTR && |
| @@ -7744,7 +7780,6 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 3 unmodified lines |
| 7744 | (t1->t & VT_BTYPE) == VT_INT | 7780 | (t1->t & VT_BTYPE) == VT_INT |
| 7745 | #endif | 7781 | #endif |
| 7746 | ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) { | 7782 | ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) { |
| 7747 | int nb; | | |
| 7748 | len = 0; | 7783 | len = 0; |
| 7749 | cstr_reset(&initstr); | 7784 | cstr_reset(&initstr); |
| 7750 | if (size1 != (tok == TOK_STR ? 1 : sizeof(nwchar_t))) | 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 | unget_tok(size1 == 1 ? TOK_STR : TOK_LSTR); | 7801 | unget_tok(size1 == 1 ? TOK_STR : TOK_LSTR); |
| 7767 | tokc.str.size = initstr.size; | 7802 | tokc.str.size = initstr.size; |
| 7768 | tokc.str.data = initstr.data; | 7803 | tokc.str.data = initstr.data; |
| 7769 | indexsym.c = 0; | 7804 | goto do_init_array; |
| 7770 | f = &indexsym; | | |
| 7771 | goto do_init_list; | | |
| 7772 | } | 7805 | } |
| 7773 | nb = len; | 7806 | |
| 7774 | if (n >= 0 && len > n) | | |
| 7775 | nb = n; | | |
| 7776 | if (!(flags & DIF_SIZE_ONLY)) { | 7807 | if (!(flags & DIF_SIZE_ONLY)) { |
| 7777 | if (sec && !NODATA_WANTED && | 7808 | int nb = n; |
| 7778 | (c + nb > sec->data_allocated)) | 7809 | if (len < nb) |
| 7779 | nb = sec->data_allocated - c; | 7810 | nb = len; |
| 7780 | if (len > nb) | 7811 | if (len > nb) |
| 7781 | tcc_warning("initializer-string for array is too long"); | 7812 | tcc_warning("initializer-string for array is too long"); |
| 7782 | /* in order to go faster for common case (char | 7813 | /* in order to go faster for common case (char |
| 7783 | string in global variable, we handle it | 7814 | string in global variable, we handle it |
| 7784 | specifically */ | 7815 | specifically */ |
| 7785 | if (sec && size1 == 1) { | 7816 | if (p->sec && size1 == 1) { |
| | 7817 | init_assert(p, c + nb); |
| 7786 | if (!NODATA_WANTED) | 7818 | if (!NODATA_WANTED) |
| 7787 | memcpy(sec->data + c, initstr.data, nb); | 7819 | memcpy(p->sec->data + c, initstr.data, nb); |
| 7788 | } else { | 7820 | } else { |
| 7789 | for(i=0;i<nb;i++) { | 7821 | for(i=0;i<n;i++) { |
| 7790 | if (size1 == 1) | 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 | ch = ((unsigned char *)initstr.data)[i]; | 7833 | ch = ((unsigned char *)initstr.data)[i]; |
| 7792 | else | 7834 | else |
| 7793 | ch = ((nwchar_t *)initstr.data)[i]; | 7835 | ch = ((nwchar_t *)initstr.data)[i]; |
| 7794 | vpushi(ch); | 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 | } else { | 7843 | } else { |
| | 7844 | |
| | 7845 | do_init_array: |
| 7810 | indexsym.c = 0; | 7846 | indexsym.c = 0; |
| 7811 | f = &indexsym; | 7847 | f = &indexsym; |
| 7812 | | 7848 | |
| 7813 | do_init_list: | 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 | len = 0; | 7856 | len = 0; |
| 7815 | while (tok != '}' || (flags & DIF_HAVE_ELEM)) { | 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 | flags &= ~DIF_HAVE_ELEM; | 7859 | flags &= ~DIF_HAVE_ELEM; |
| 7818 | if (type->t & VT_ARRAY) { | 7860 | if (type->t & VT_ARRAY) { |
| 7819 | ++indexsym.c; | 7861 | ++indexsym.c; |
| @@ -7836,16 +7878,9 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 16 unmodified lines |
| 7836 | skip(','); | 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 | if (!no_oblock) | 7881 | if (!no_oblock) |
| 7843 | skip('}'); | 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 | } else if ((type->t & VT_BTYPE) == VT_STRUCT) { | 7883 | } else if ((type->t & VT_BTYPE) == VT_STRUCT) { |
| 7848 | size1 = 1; | | |
| 7849 | no_oblock = 1; | 7884 | no_oblock = 1; |
| 7850 | if ((flags & DIF_FIRST) || tok == '{') { | 7885 | if ((flags & DIF_FIRST) || tok == '{') { |
| 7851 | skip('{'); | 7886 | skip('{'); |
| @@ -7854,12 +7889,13 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 2 unmodified lines |
| 7854 | s = type->ref; | 7889 | s = type->ref; |
| 7855 | f = s->next; | 7890 | f = s->next; |
| 7856 | n = s->c; | 7891 | n = s->c; |
| | 7892 | size1 = 1; |
| 7857 | goto do_init_list; | 7893 | goto do_init_list; |
| 7858 | } else if (tok == '{') { | 7894 | } else if (tok == '{') { |
| 7859 | if (flags & DIF_HAVE_ELEM) | 7895 | if (flags & DIF_HAVE_ELEM) |
| 7860 | skip(';'); | 7896 | skip(';'); |
| 7861 | next(); | 7897 | next(); |
| 7862 | decl_initializer(type, sec, c, flags & ~DIF_HAVE_ELEM); | 7898 | decl_initializer(p, type, c, flags & ~DIF_HAVE_ELEM); |
| 7863 | skip('}'); | 7899 | skip('}'); |
| 7864 | } else if ((flags & DIF_SIZE_ONLY)) { | 7900 | } else if ((flags & DIF_SIZE_ONLY)) { |
| 7865 | /* If we supported only ISO C we wouldn't have to accept calling | 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 | string constant to memory too early. */ | 7913 | string constant to memory too early. */ |
| 7878 | if (tok != TOK_STR && tok != TOK_LSTR) | 7914 | if (tok != TOK_STR && tok != TOK_LSTR) |
| 7879 | expect("string constant"); | 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 | #ifdef CONFIG_TCC_BCHECK | 7947 | #ifdef CONFIG_TCC_BCHECK |
| 7904 | int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED; | 7948 | int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED; |
| 7905 | #endif | 7949 | #endif |
| | 7950 | init_params p = {0}; |
| 7906 | | 7951 | |
| 7907 | /* Always allocate static or global variables */ | 7952 | /* Always allocate static or global variables */ |
| 7908 | if (v && (r & VT_VALMASK) == VT_CONST) | 7953 | if (v && (r & VT_VALMASK) == VT_CONST) |
| 7909 | nocode_wanted |= 0x80000000; | 7954 | nocode_wanted |= 0x80000000; |
| 7910 | | 7955 | |
| 7911 | flexible_array = NULL; | 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 | Sym *field = type->ref->next; | 7971 | Sym *field = type->ref->next; |
| 7914 | if (field) { | 7972 | if (field) { |
| 7915 | while (field->next) | 7973 | while (field->next) |
| 7916 | field = field->next; | 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 | flexible_array = field; | 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); | 7983 | if (size < 0) { |
| 7923 | /* If unknown size, we must evaluate it before | 7984 | /* If unknown size, do a dry-run 1st pass */ |
| 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)) { | | |
| 7930 | if (!has_init) | 7985 | if (!has_init) |
| 7931 | tcc_error("unknown type size"); | 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 | /* compute size */ | 8000 | /* compute size */ |
| 7935 | begin_macro(init_str, 1); | 8001 | begin_macro(init_str, 1); |
| 7936 | next(); | 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 | /* prepare second initializer parsing */ | 8004 | /* prepare second initializer parsing */ |
| 7939 | macro_ptr = init_str->str; | 8005 | macro_ptr = init_str->str; |
| 7940 | next(); | 8006 | next(); |
| @@ -7943,13 +8009,14 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 2 unmodified lines |
| 7943 | size = type_size(type, &align); | 8009 | size = type_size(type, &align); |
| 7944 | if (size < 0) | 8010 | if (size < 0) |
| 7945 | tcc_error("unknown type size"); | 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 | 8019 | |
| 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); | | |
| 7953 | /* take into account specified alignment if bigger */ | 8020 | /* take into account specified alignment if bigger */ |
| 7954 | if (ad->a.aligned) { | 8021 | if (ad->a.aligned) { |
| 7955 | int speca = 1 << (ad->a.aligned - 1); | 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 | #endif | 8039 | #endif |
| 7973 | loc = (loc - size) & -align; | 8040 | loc = (loc - size) & -align; |
| 7974 | addr = loc; | 8041 | addr = loc; |
| | 8042 | p.local_offset = addr + size; |
| 7975 | #ifdef CONFIG_TCC_BCHECK | 8043 | #ifdef CONFIG_TCC_BCHECK |
| 7976 | if (bcheck && v) { | 8044 | if (bcheck && v) { |
| 7977 | /* add padding between stack variables for bound checking */ | 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 | cur_scope->vla.loc = addr; | 8156 | cur_scope->vla.loc = addr; |
| 8089 | cur_scope->vla.num++; | 8157 | cur_scope->vla.num++; |
| 8090 | } else if (has_init) { | 8158 | } else if (has_init) { |
| 8091 | size_t oldreloc_offset = 0; | 8159 | p.sec = sec; |
| 8092 | if (sec && sec->reloc) | 8160 | decl_initializer(&p, type, addr, DIF_FIRST); |
| 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); | | |
| 8097 | /* patch flexible array member size back to -1, */ | 8161 | /* patch flexible array member size back to -1, */ |
| 8098 | /* for possible subsequent similar declarations */ | 8162 | /* for possible subsequent similar declarations */ |
| 8099 | if (flexible_array) | 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 | while (1) { /* iterate thru each declaration */ | 8353 | while (1) { /* iterate thru each declaration */ |
| 8290 | type = btype; | 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 | ad = adbase; | 8355 | ad = adbase; |
| 8300 | type_decl(&type, &ad, &v, TYPE_DIRECT); | 8356 | type_decl(&type, &ad, &v, TYPE_DIRECT); |
| 8301 | #if 0 | 8357 | #if 0 |