VLA fix [3/3]: store VLA sizeofs in anonymous runtime stack vars
This commit is contained in:
parent
7c7ca3c6aa
commit
1446b543ae
2 changed files with 22 additions and 34 deletions
1
tcc.h
1
tcc.h
|
@ -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 {
|
||||||
|
|
55
tccgen.c
55
tccgen.c
|
@ -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,10 +3732,7 @@ ST_FUNC void unary(void)
|
||||||
} else {
|
} else {
|
||||||
r = s->r;
|
r = s->r;
|
||||||
}
|
}
|
||||||
if (s->type.t & VT_VLA)
|
vset(&s->type, r, s->c);
|
||||||
vpushv(s->s);
|
|
||||||
else
|
|
||||||
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) {
|
||||||
vtop->sym = s;
|
vtop->sym = s;
|
||||||
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue