aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2016-08-06 22:38:26 +0200
committerMichael Matz <matz@suse.de>2016-12-15 17:47:09 +0100
commit4e46c22d5ca4d03220e30fa524a5aba4b4df75f9 (patch)
tree18533be6e414c09081b6defe4a632241e3c0f708
parent4cb7047f0fa000c83ca5592d9a64a2cbc96d8fdc (diff)
downloadtinycc-4e46c22d5ca4d03220e30fa524a5aba4b4df75f9.tar.gz
tinycc-4e46c22d5ca4d03220e30fa524a5aba4b4df75f9.tar.bz2
struct-init: Support range inits for local vars
Implement missing support for range init for local variables.
-rw-r--r--tccgen.c45
-rw-r--r--tests/tests2/86-struct-init.c4
-rw-r--r--tests/tests2/86-struct-init.expect1
3 files changed, 33 insertions, 17 deletions
diff --git a/tccgen.c b/tccgen.c
index a833b17..aafea36 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -5713,7 +5713,8 @@ static void parse_init_elem(int expr_type)
/* t is the array or struct type. c is the array or struct
address. cur_field is the pointer to the current
- value, for arrays the 'c' member contains the current index.
+ value, for arrays the 'c' member contains the current start
+ index and the 'r' contains the end index (in case of range init).
'size_only' is true if only size info is needed (only used
in arrays) */
static void decl_designator(CType *type, Section *sec, unsigned long c,
@@ -5748,8 +5749,10 @@ static void decl_designator(CType *type, Section *sec, unsigned long c,
index_last = index;
}
skip(']');
- if (!notfirst)
- (*cur_field)->c = index_last;
+ if (!notfirst) {
+ (*cur_field)->c = index;
+ (*cur_field)->r = index_last;
+ }
type = pointed_type(type);
elem_size = type_size(type, &align);
c += index * elem_size;
@@ -5812,17 +5815,25 @@ static void decl_designator(CType *type, Section *sec, unsigned long c,
uint8_t *src, *dst;
int i;
- if (!sec)
- tcc_error("range init not supported yet for dynamic storage");
- 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);
- }
+ 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 {
+ 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);
+ }
+ }
}
}
@@ -6014,7 +6025,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
!(type->t & VT_ARRAY) &&
/* Use i_c_parameter_t, to strip toplevel qualifiers.
The source type might have VT_CONSTANT set, which is
- of course assignable to a non-const elements. */
+ of course assignable to non-const elements. */
is_compatible_parameter_types(type, &vtop->type)) {
init_putv(type, sec, c);
} else if (type->t & VT_ARRAY) {
@@ -6088,6 +6099,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
}
} else {
indexsym.c = 0;
+ indexsym.r = 0;
f = &indexsym;
do_init_list:
@@ -6102,8 +6114,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
(index - array_length) * size1);
}
if (type->t & VT_ARRAY) {
- index++;
- indexsym.c++;
+ index = indexsym.c = ++indexsym.r;
} else {
index = index + type_size(&f->type, &align1);
if (s->type.t == TOK_UNION)
diff --git a/tests/tests2/86-struct-init.c b/tests/tests2/86-struct-init.c
index 6ce4e24..3cf25c7 100644
--- a/tests/tests2/86-struct-init.c
+++ b/tests/tests2/86-struct-init.c
@@ -148,6 +148,9 @@ void foo (struct W *w, struct pkthdr *phdr_)
struct V lv3 = {((struct S){7,8,{9,10}}), ((const struct W *)w)->t.t, 50};
const struct pkthdr *phdr = phdr_;
struct flowi6 flow = { .daddr = phdr->daddr, .saddr = phdr->saddr };
+ int elt = 0x42;
+ /* Range init, overlapping */
+ struct T lt2 = { { [1 ... 5] = 9, [6 ... 10] = elt, [4 ... 7] = elt+1 }, 1 };
print(ls);
print(ls2);
print(lt);
@@ -163,6 +166,7 @@ void foo (struct W *w, struct pkthdr *phdr_)
print(lv);
print(lv2);
print(lv3);
+ print(lt2);
print(flow);
}
#endif
diff --git a/tests/tests2/86-struct-init.expect b/tests/tests2/86-struct-init.expect
index b827ec4..1498a3d 100644
--- a/tests/tests2/86-struct-init.expect
+++ b/tests/tests2/86-struct-init.expect
@@ -33,4 +33,5 @@ ls3: 1 2 3 4
lv: 3 4 5 6 68 61 68 61 0 0 0 0 0 0 0 0 0 0 0 0 2d 2e
lv2: 1 2 3 4 68 69 68 69 0 0 0 0 0 0 0 0 0 0 0 0 2f 30
lv3: 7 8 9 a 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32
+lt2: 0 9 9 9 43 43 43 43 42 42 42 0 0 0 0 0 1
flow: 9 8 7 6 0 0 0 0 0 0 0 0 0 0 0 0 6 5 4 3 0 0 0 0 0 0 0 0 0 0 0 0