Init range wth symbols

The init range with symbols did only init the first value.
The relocation for all other symbols was missing.
Also see testcase.

tccgen.c:
- New function get_init_string
- Use macro processing in decl_designator for each init string
- Use get_init_string in decl_initializer_alloc

tccelf.c:
- Fix insertion sort in squeeze_multi_relocs

tests/tests2/90_struct-init.c:
- Add test case test_init_ranges
This commit is contained in:
herman ten brugge 2020-10-01 17:50:20 +02:00
parent afc0917f88
commit 0da93838c1
4 changed files with 66 additions and 40 deletions

View File

@ -774,13 +774,13 @@ ST_FUNC void squeeze_multi_relocs(Section *s, size_t oldrelocoffset)
a simple insertion sort. */
for (a = oldrelocoffset + sizeof(*r); a < sr->data_offset; a += sizeof(*r)) {
ssize_t i = a - sizeof(*r);
addr = ((ElfW_Rel*)(sr->data + a))->r_offset;
ElfW_Rel tmp = *(ElfW_Rel*)(sr->data + a);
addr = tmp.r_offset;
for (; i >= (ssize_t)oldrelocoffset &&
((ElfW_Rel*)(sr->data + i))->r_offset > addr; i -= sizeof(*r)) {
ElfW_Rel tmp = *(ElfW_Rel*)(sr->data + a);
*(ElfW_Rel*)(sr->data + a) = *(ElfW_Rel*)(sr->data + i);
*(ElfW_Rel*)(sr->data + i) = tmp;
*(ElfW_Rel*)(sr->data + i + sizeof(*r)) = *(ElfW_Rel*)(sr->data + i);
}
*(ElfW_Rel*)(sr->data + i + sizeof(*r)) = tmp;
}
r = (ElfW_Rel*)(sr->data + oldrelocoffset);

View File

@ -7296,6 +7296,23 @@ static void skip_or_save_block(TokenString **str)
}
}
static void get_init_string(TokenString **str, int has_init)
{
if (has_init == 2) {
*str = tok_str_alloc();
/* only get strings */
while (tok == TOK_STR || tok == TOK_LSTR) {
tok_str_add_tok(*str);
next();
}
tok_str_add(*str, -1);
tok_str_add(*str, 0);
}
else
skip_or_save_block(str);
unget_tok(0);
}
#define EXPR_CONST 1
#define EXPR_ANY 2
@ -7361,6 +7378,7 @@ static int decl_designator(CType *type, Section *sec, unsigned long c,
Sym *s, *f;
int index, index_last, align, l, nb_elems, elem_size;
unsigned long corig = c;
TokenString *init_str = NULL;
elem_size = 0;
nb_elems = 1;
@ -7454,34 +7472,26 @@ static int decl_designator(CType *type, Section *sec, unsigned long c,
init_putz(sec, corig + al, zlen);
}
if (!(flags & DIF_SIZE_ONLY) && nb_elems > 1) {
get_init_string(&init_str, tok == TOK_STR || tok == TOK_LSTR ? 2 : 0);
begin_macro(init_str, 1);
next();
}
decl_initializer(type, sec, c, flags & ~DIF_FIRST);
/* XXX: make it more general */
if (!(flags & DIF_SIZE_ONLY) && nb_elems > 1) {
unsigned long c_end;
uint8_t *src, *dst;
int i;
if (!sec) {
vset(type, VT_LOCAL|VT_LVAL, c);
for (i = 1; i < nb_elems; i++) {
vset(type, VT_LOCAL|VT_LVAL, c + elem_size * i);
vswap();
vstore();
}
vpop();
} else if (!NODATA_WANTED) {
c_end = c + nb_elems * elem_size;
if (c_end > sec->data_allocated)
section_realloc(sec, c_end);
src = sec->data + c;
dst = src;
for(i = 1; i < nb_elems; i++) {
dst += elem_size;
memcpy(dst, src, elem_size);
}
}
for(i = 1; i < nb_elems; i++) {
macro_ptr = init_str->str;
next();
decl_initializer(type, sec, c + i * elem_size, flags & ~DIF_FIRST);
}
end_macro();
next();
}
c += nb_elems * type_size(type, &align);
if (c - corig > al)
al = c - corig;
@ -7919,20 +7929,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
if (size < 0 || (flexible_array && has_init)) {
if (!has_init)
tcc_error("unknown type size");
/* get all init string */
if (has_init == 2) {
init_str = tok_str_alloc();
/* only get strings */
while (tok == TOK_STR || tok == TOK_LSTR) {
tok_str_add_tok(init_str);
next();
}
tok_str_add(init_str, -1);
tok_str_add(init_str, 0);
} else {
skip_or_save_block(&init_str);
}
unget_tok(0);
get_init_string(&init_str, has_init);
/* compute size */
begin_macro(init_str, 1);

View File

@ -235,6 +235,33 @@ void test_multi_relocs(void)
for (i = 0; i < sizeof(table)/sizeof(table[0]); i++)
table[i]();
}
void test_init_ranges(void) {
int i,c=0;
static void *gostring[] = {
[0 ... 31] = &&l_bad, [127] = &&l_bad,
[32 ... 126] = &&l_loop,
['\\'] = &&l_esc, ['"'] = &&l_qdown,
[128 ... 191] = &&l_bad,
[192 ... 223] = &&l_utf8_2,
[224 ... 239] = &&l_utf8_3,
[240 ... 247] = &&l_utf8_4,
[248 ... 255] = &&l_bad
};
for (i = 0; i < 256; i++) {
goto *gostring[i];
l_bad: c++;
l_loop: c++;
l_esc: c++;
l_qdown: c++;
l_utf8_2: c++;
l_utf8_3: c++;
l_utf8_4: c++;
}
printf ("%d\n", c);
}
/* Following is from GCC gcc.c-torture/execute/20050613-1.c. */
@ -298,5 +325,6 @@ int main()
test_compound_with_relocs();
test_multi_relocs();
test_zero_init();
test_init_ranges();
return 0;
}

View File

@ -46,3 +46,4 @@ three
sea_fill0: okay
sea_fill1: okay
sea_fill2: okay
1438