VLA fix [3/3]: store VLA sizeofs in anonymous runtime stack vars

This commit is contained in:
Joe Soroka 2011-04-09 22:52:25 -07:00
parent 7c7ca3c6aa
commit 1446b543ae
2 changed files with 22 additions and 34 deletions

1
tcc.h
View file

@ -224,7 +224,6 @@ typedef struct Sym {
union { union {
long c; /* associated number */ long c; /* associated number */
int *d; /* define token stream */ int *d; /* define token stream */
SValue *s; /* associated stack value */
}; };
CType type; /* associated type */ CType type; /* associated type */
union { union {

View file

@ -2036,22 +2036,9 @@ ST_FUNC int type_size(CType *type, int *a)
ST_FUNC void vla_runtime_type_size(CType *type, int *a) ST_FUNC void vla_runtime_type_size(CType *type, int *a)
{ {
if (type->t & VT_VLA) { if (type->t & VT_VLA) {
Sym *s; vset(&int_type, VT_LOCAL|VT_LVAL, type->ref->c);
s = type->ref;
vla_runtime_type_size(&s->type, a);
vpushv(s->s);
if ((vtop->r & (VT_SYM|VT_LVAL|VT_VALMASK)) != VT_CONST) {
gv_dup();
vswap();
vpop();
}
gen_op('*');
} else { } else {
int size; vpushi(type_size(type, a));
size = type_size(type, a);
vpushi(size);
} }
} }
@ -3170,8 +3157,6 @@ static void post_type(CType *type, AttributeDef *ad)
type->t = VT_FUNC; type->t = VT_FUNC;
type->ref = s; type->ref = s;
} else if (tok == '[') { } else if (tok == '[') {
SValue *last_vtop = NULL;
/* array definition */ /* array definition */
next(); next();
if (tok == TOK_RESTRICT1) if (tok == TOK_RESTRICT1)
@ -3182,14 +3167,12 @@ static void post_type(CType *type, AttributeDef *ad)
gexpr(); gexpr();
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
n = vtop->c.i; n = vtop->c.i;
last_vtop = vtop;
if (n < 0) if (n < 0)
error("invalid array size"); error("invalid array size");
} else { } else {
if (!is_integer_btype(vtop->type.t & VT_BTYPE)) if (!is_integer_btype(vtop->type.t & VT_BTYPE))
error("size of variable length array should be an integer"); error("size of variable length array should be an integer");
t1 = VT_VLA; t1 = VT_VLA;
last_vtop = vtop;
} }
} }
skip(']'); skip(']');
@ -3197,15 +3180,23 @@ static void post_type(CType *type, AttributeDef *ad)
post_type(type, ad); post_type(type, ad);
t1 |= type->t & VT_VLA; t1 |= type->t & VT_VLA;
if (t1 & VT_VLA) {
loc -= type_size(&int_type, &align);
loc &= -align;
n = loc;
vla_runtime_type_size(type, &align);
gen_op('*');
vset(&int_type, VT_LOCAL|VT_LVAL, loc);
vswap();
vstore();
}
if (n != -1)
vpop();
/* we push an anonymous symbol which will contain the array /* we push an anonymous symbol which will contain the array
element type */ element type */
s = sym_push(SYM_FIELD, type, 0, n); s = sym_push(SYM_FIELD, type, 0, n);
if (t1 & VT_VLA) {
s->s = last_vtop; // That's ok, we don't need n with VLA
} else {
if (n >= 0)
vpop();
}
type->t = (t1 ? VT_VLA : VT_ARRAY) | VT_PTR; type->t = (t1 ? VT_VLA : VT_ARRAY) | VT_PTR;
type->ref = s; type->ref = s;
} }
@ -3741,9 +3732,6 @@ ST_FUNC void unary(void)
} else { } else {
r = s->r; r = s->r;
} }
if (s->type.t & VT_VLA)
vpushv(s->s);
else
vset(&s->type, r, s->c); vset(&s->type, r, s->c);
/* if forward reference, we must point to s */ /* if forward reference, we must point to s */
if (vtop->r & VT_SYM) { if (vtop->r & VT_SYM) {
@ -4895,6 +4883,10 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
/* return value */ /* return value */
retcval.i = 0; retcval.i = 0;
vsetc(type, REG_IRET, &retcval); vsetc(type, REG_IRET, &retcval);
vset(type, VT_LOCAL|VT_LVAL, c);
vswap();
vstore();
vpop();
} else if (type->t & VT_ARRAY) { } else if (type->t & VT_ARRAY) {
s = type->ref; s = type->ref;
n = s->c; n = s->c;
@ -5132,7 +5124,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
ParseState saved_parse_state = {0}; ParseState saved_parse_state = {0};
TokenString init_str; TokenString init_str;
Section *sec; Section *sec;
Sym *vla = NULL;
Sym *flexible_array; Sym *flexible_array;
flexible_array = NULL; flexible_array = NULL;
@ -5233,7 +5224,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
#endif #endif
if (v) { if (v) {
/* local variable */ /* local variable */
vla = sym_push(v, type, r, addr); sym_push(v, type, r, addr);
} else { } else {
/* push local reference */ /* push local reference */
vset(type, r, addr); vset(type, r, addr);
@ -5348,8 +5339,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
} }
if (has_init || (type->t & VT_VLA)) { if (has_init || (type->t & VT_VLA)) {
decl_initializer(type, sec, addr, 1, 0); decl_initializer(type, sec, addr, 1, 0);
if (type->t & VT_VLA)
vla->s = vtop;
/* restore parse state if needed */ /* restore parse state if needed */
if (init_str.str) { if (init_str.str) {
tok_str_free(init_str.str); tok_str_free(init_str.str);