tccgen: multi-dimensional vla: bug fixes

fixes these cases:
   ptr - ptr             (-> ptrdiff_t)
   ptr +/- num           (-> ptr)
   sizeof (ptr+/-num)    (-> size_t)

Also some cleanups
This commit is contained in:
grischka 2021-12-08 10:49:28 +01:00
parent ec5d94291c
commit 0c6adcbe53
2 changed files with 31 additions and 47 deletions

View File

@ -234,7 +234,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has
static void decl(int l); static void decl(int l);
static int decl0(int l, int is_for_loop_init, Sym *); static int decl0(int l, int is_for_loop_init, Sym *);
static void expr_eq(void); static void expr_eq(void);
static void vla_runtime_type_size(CType *type, int *a); static void vpush_type_size(CType *type, int *a);
static int is_compatible_unqualified_types(CType *type1, CType *type2); static int is_compatible_unqualified_types(CType *type1, CType *type2);
static inline int64_t expr_const64(void); static inline int64_t expr_const64(void);
static void vpush64(int ty, unsigned long long v); static void vpush64(int ty, unsigned long long v);
@ -3173,7 +3173,7 @@ static void type_to_str(char *buf, int buf_size,
goto no_var; goto no_var;
case VT_PTR: case VT_PTR:
s = type->ref; s = type->ref;
if (t & VT_ARRAY) { if (t & (VT_ARRAY|VT_VLA)) {
if (varstr && '*' == *varstr) if (varstr && '*' == *varstr)
snprintf(buf1, sizeof(buf1), "(%s)[%d]", varstr, s->c); snprintf(buf1, sizeof(buf1), "(%s)[%d]", varstr, s->c);
else else
@ -3220,12 +3220,6 @@ static int pointed_size(CType *type)
return type_size(pointed_type(type), &align); return type_size(pointed_type(type), &align);
} }
static void vla_runtime_pointed_size(CType *type)
{
int align;
vla_runtime_type_size(pointed_type(type), &align);
}
static inline int is_null_pointer(SValue *p) static inline int is_null_pointer(SValue *p)
{ {
if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
@ -3436,7 +3430,7 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op)
/* generic gen_op: handles types problems */ /* generic gen_op: handles types problems */
ST_FUNC void gen_op(int op) ST_FUNC void gen_op(int op)
{ {
int u, t1, t2, bt1, bt2, t; int t1, t2, bt1, bt2, t;
CType type1, combtype; CType type1, combtype;
redo: redo:
@ -3463,17 +3457,14 @@ redo:
} else if (bt1 == VT_PTR || bt2 == VT_PTR) { } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
/* at least one operand is a pointer */ /* at least one operand is a pointer */
/* relational op: must be both pointers */ /* relational op: must be both pointers */
int align;
if (TOK_ISCOND(op)) if (TOK_ISCOND(op))
goto std_op; goto std_op;
/* if both pointers, then it must be the '-' op */ /* if both pointers, then it must be the '-' op */
if (bt1 == VT_PTR && bt2 == VT_PTR) { if (bt1 == VT_PTR && bt2 == VT_PTR) {
if (op != '-') if (op != '-')
tcc_error("cannot use pointers here"); tcc_error("cannot use pointers here");
if (vtop[-1].type.t & VT_VLA) { vpush_type_size(pointed_type(&vtop[-1].type), &align);
vla_runtime_pointed_size(&vtop[-1].type);
} else {
vpushi(pointed_size(&vtop[-1].type));
}
vrott(3); vrott(3);
gen_opic(op); gen_opic(op);
vtop->type.t = VT_PTRDIFF_T; vtop->type.t = VT_PTRDIFF_T;
@ -3494,19 +3485,7 @@ redo:
gen_cast_s(VT_INT); gen_cast_s(VT_INT);
#endif #endif
type1 = vtop[-1].type; type1 = vtop[-1].type;
if (vtop[-1].type.ref->type.t & VT_VLA) vpush_type_size(pointed_type(&vtop[-1].type), &align);
vla_runtime_pointed_size(&vtop[-1].type);
else {
u = pointed_size(&vtop[-1].type);
if (u < 0)
tcc_error("unknown array element size");
#if PTR_SIZE == 8
vpushll(u);
#else
/* XXX: cast to int ? (long long case) */
vpushi(u);
#endif
}
gen_op('*'); gen_op('*');
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check && !const_wanted) { if (tcc_state->do_bounds_check && !const_wanted) {
@ -3523,7 +3502,7 @@ redo:
{ {
gen_opic(op); gen_opic(op);
} }
type1.t &= ~VT_ARRAY; type1.t &= ~(VT_ARRAY|VT_VLA);
/* put again type if gen_opic() swaped operands */ /* put again type if gen_opic() swaped operands */
vtop->type = type1; vtop->type = type1;
} }
@ -3957,13 +3936,16 @@ ST_FUNC int type_size(CType *type, int *a)
/* push type size as known at runtime time on top of value stack. Put /* push type size as known at runtime time on top of value stack. Put
alignment at 'a' */ alignment at 'a' */
ST_FUNC void vla_runtime_type_size(CType *type, int *a) static void vpush_type_size(CType *type, int *a)
{ {
if (type->t & VT_VLA) { if (type->t & VT_VLA) {
type_size(&type->ref->type, a); type_size(&type->ref->type, a);
vset(&int_type, VT_LOCAL|VT_LVAL, type->ref->c); vset(&int_type, VT_LOCAL|VT_LVAL, type->ref->c);
} else { } else {
vpushi(type_size(type, a)); int size = type_size(type, a);
if (size < 0)
tcc_error("unknown type size");
vpushi(size);
} }
} }
@ -5501,7 +5483,7 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td)
loc &= -align; loc &= -align;
n = loc; n = loc;
vla_runtime_type_size(type, &align); vpush_type_size(type, &align);
gen_op('*'); gen_op('*');
vset(&int_type, VT_LOCAL|VT_LVAL, n); vset(&int_type, VT_LOCAL|VT_LVAL, n);
vswap(); vswap();
@ -6050,24 +6032,18 @@ ST_FUNC void unary(void)
next(); next();
in_sizeof++; in_sizeof++;
expr_type(&type, unary); /* Perform a in_sizeof = 0; */ expr_type(&type, unary); /* Perform a in_sizeof = 0; */
s = NULL;
if (vtop[1].r & VT_SYM)
s = vtop[1].sym; /* hack: accessing previous vtop */
size = type_size(&type, &align);
if (s && s->a.aligned)
align = 1 << (s->a.aligned - 1);
if (t == TOK_SIZEOF) { if (t == TOK_SIZEOF) {
if (!(type.t & VT_VLA)) { vpush_type_size(&type, &align);
if (size < 0) gen_cast_s(VT_SIZE_T);
tcc_error("sizeof applied to an incomplete type");
vpushs(size);
} else {
vla_runtime_type_size(&type, &align);
}
} else { } else {
type_size(&type, &align);
s = NULL;
if (vtop[1].r & VT_SYM)
s = vtop[1].sym; /* hack: accessing previous vtop */
if (s && s->a.aligned)
align = 1 << (s->a.aligned - 1);
vpushs(align); vpushs(align);
} }
vtop->type.t |= VT_UNSIGNED;
break; break;
case TOK_builtin_expect: case TOK_builtin_expect:
@ -8566,7 +8542,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
} }
} }
vla_runtime_type_size(type, &a); vpush_type_size(type, &a);
gen_vla_alloc(type, a); gen_vla_alloc(type, a);
#if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64 #if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
/* on _WIN64, because of the function args scratch area, the /* on _WIN64, because of the function args scratch area, the

View File

@ -2980,12 +2980,20 @@ void c99_vla_test_2(int d, int h, int w)
for (z=0; z<d; z++) { for (z=0; z<d; z++) {
for (y=0; y<h; y++) { for (y=0; y<h; y++) {
for (x=0; x<w; x++) { for (x=0; x<w; x++) {
printf("% 4i", arr[z][y][x]); printf(" %2d", arr[z][y][x]);
} }
puts(""); puts("");
} }
puts(""); puts("");
} }
printf(" sizes : %d %d %d\n"
" pdiff : %d %d\n"
" tests : %d %d\n",
sizeof (*arr), sizeof (*arr)[0], sizeof (*arr)[0][0],
arr + 2 - arr, *arr + 3 - *arr,
0 == sizeof (*arr + 1) - sizeof arr,
0 == sizeof sizeof *arr - sizeof arr
);
free (arr); free (arr);
} }