a lot simpler VLA code
Author: Philip <pipcet@gmail.com> Our VLA code can be made a lot simpler (simple enough for even me to understand it) by giving up on the optimization idea, which is very tempting. There's a patch to do that attached, feel free to test and commit it if you like. (It passes all the tests, at least
This commit is contained in:
parent
fca58734fb
commit
999274ca90
4 changed files with 33 additions and 94 deletions
|
@ -1126,11 +1126,7 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) {
|
||||||
/* We align to 16 bytes rather than align */
|
/* We align to 16 bytes rather than align */
|
||||||
/* and ~15, %esp */
|
/* and ~15, %esp */
|
||||||
o(0xf0e483);
|
o(0xf0e483);
|
||||||
/* mov %esp, r */
|
|
||||||
o(0x89);
|
|
||||||
o(0xe0 | r);
|
|
||||||
vpop();
|
vpop();
|
||||||
vset(type, r, 0);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
tcc.h
6
tcc.h
|
@ -464,12 +464,6 @@ typedef struct DLLReference {
|
||||||
#define SYM_FIELD 0x20000000 /* struct/union field symbol space */
|
#define SYM_FIELD 0x20000000 /* struct/union field symbol space */
|
||||||
#define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
|
#define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
|
||||||
|
|
||||||
#define VLA_SP_LOC_SET 0x01 /* Location of SP on stack has been allocated */
|
|
||||||
#define VLA_SP_SAVED 0x02 /* SP has been saved to slot already */
|
|
||||||
#define VLA_NEED_NEW_FRAME 0x04 /* Needs new frame for next VLA */
|
|
||||||
#define VLA_IN_SCOPE 0x08 /* One or more VLAs are in scope */
|
|
||||||
#define VLA_SCOPE_FLAGS (VLA_SP_SAVED|VLA_NEED_NEW_FRAME|VLA_IN_SCOPE) /* Flags which are saved and restored upon entering and exiting a block */
|
|
||||||
|
|
||||||
/* stored in 'Sym.c' field */
|
/* stored in 'Sym.c' field */
|
||||||
#define FUNC_NEW 1 /* ansi function prototype */
|
#define FUNC_NEW 1 /* ansi function prototype */
|
||||||
#define FUNC_OLD 2 /* old function prototype */
|
#define FUNC_OLD 2 /* old function prototype */
|
||||||
|
|
113
tccgen.c
113
tccgen.c
|
@ -55,10 +55,9 @@ ST_DATA Sym *define_stack;
|
||||||
ST_DATA Sym *global_label_stack;
|
ST_DATA Sym *global_label_stack;
|
||||||
ST_DATA Sym *local_label_stack;
|
ST_DATA Sym *local_label_stack;
|
||||||
|
|
||||||
ST_DATA int vla_sp_loc_tmp; /* vla_sp_loc is set to this when the value won't be needed later */
|
ST_DATA int vlas_in_scope; /* number of VLAs that are currently in scope */
|
||||||
ST_DATA int vla_sp_root_loc; /* vla_sp_loc for SP before any VLAs were pushed */
|
ST_DATA int vla_sp_root_loc; /* vla_sp_loc for SP before any VLAs were pushed */
|
||||||
ST_DATA int *vla_sp_loc; /* Pointer to variable holding location to store stack pointer on the stack when modifying stack pointer */
|
ST_DATA int vla_sp_loc; /* Pointer to variable holding location to store stack pointer on the stack when modifying stack pointer */
|
||||||
ST_DATA int vla_flags; /* VLA_* flags */
|
|
||||||
|
|
||||||
ST_DATA SValue __vstack[1+VSTACK_SIZE], *vtop;
|
ST_DATA SValue __vstack[1+VSTACK_SIZE], *vtop;
|
||||||
|
|
||||||
|
@ -87,7 +86,8 @@ static int decl0(int l, int is_for_loop_init);
|
||||||
static void expr_eq(void);
|
static void expr_eq(void);
|
||||||
static void unary_type(CType *type);
|
static void unary_type(CType *type);
|
||||||
static void vla_runtime_type_size(CType *type, int *a);
|
static void vla_runtime_type_size(CType *type, int *a);
|
||||||
static void vla_sp_save(void);
|
static void vla_sp_restore(void);
|
||||||
|
static void vla_sp_restore_root(void);
|
||||||
static int is_compatible_parameter_types(CType *type1, CType *type2);
|
static int is_compatible_parameter_types(CType *type1, CType *type2);
|
||||||
static void expr_type(CType *type);
|
static void expr_type(CType *type);
|
||||||
ST_FUNC void vpush64(int ty, unsigned long long v);
|
ST_FUNC void vpush64(int ty, unsigned long long v);
|
||||||
|
@ -2223,14 +2223,15 @@ ST_FUNC void vla_runtime_type_size(CType *type, int *a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vla_sp_save(void) {
|
static void vla_sp_restore(void) {
|
||||||
if (!(vla_flags & VLA_SP_LOC_SET)) {
|
if (vlas_in_scope) {
|
||||||
*vla_sp_loc = (loc -= PTR_SIZE);
|
gen_vla_sp_restore(vla_sp_loc);
|
||||||
vla_flags |= VLA_SP_LOC_SET;
|
|
||||||
}
|
}
|
||||||
if (!(vla_flags & VLA_SP_SAVED)) {
|
}
|
||||||
gen_vla_sp_save(*vla_sp_loc);
|
|
||||||
vla_flags |= VLA_SP_SAVED;
|
static void vla_sp_restore_root(void) {
|
||||||
|
if (vlas_in_scope) {
|
||||||
|
gen_vla_sp_restore(vla_sp_root_loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4794,10 +4795,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||||
} else if (tok == TOK_WHILE) {
|
} else if (tok == TOK_WHILE) {
|
||||||
next();
|
next();
|
||||||
d = ind;
|
d = ind;
|
||||||
if (vla_flags & VLA_IN_SCOPE) {
|
vla_sp_restore();
|
||||||
gen_vla_sp_restore(*vla_sp_loc);
|
|
||||||
vla_flags |= VLA_NEED_NEW_FRAME;
|
|
||||||
}
|
|
||||||
skip('(');
|
skip('(');
|
||||||
gexpr();
|
gexpr();
|
||||||
skip(')');
|
skip(')');
|
||||||
|
@ -4809,7 +4807,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||||
gsym_addr(b, d);
|
gsym_addr(b, d);
|
||||||
} else if (tok == '{') {
|
} else if (tok == '{') {
|
||||||
Sym *llabel;
|
Sym *llabel;
|
||||||
int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags, *orig_vla_sp_loc;
|
int block_vla_sp_loc = vla_sp_loc, saved_vlas_in_scope = vlas_in_scope;
|
||||||
|
|
||||||
next();
|
next();
|
||||||
/* record local declaration stack position */
|
/* record local declaration stack position */
|
||||||
|
@ -4819,15 +4817,6 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||||
scope_stack_bottom = frame_bottom;
|
scope_stack_bottom = frame_bottom;
|
||||||
llabel = local_label_stack;
|
llabel = local_label_stack;
|
||||||
|
|
||||||
/* save VLA state */
|
|
||||||
block_vla_sp_loc = *(saved_vla_sp_loc = vla_sp_loc);
|
|
||||||
if (saved_vla_sp_loc != &vla_sp_root_loc)
|
|
||||||
vla_sp_loc = &block_vla_sp_loc;
|
|
||||||
orig_vla_sp_loc = vla_sp_loc;
|
|
||||||
|
|
||||||
saved_vla_flags = vla_flags;
|
|
||||||
vla_flags |= VLA_NEED_NEW_FRAME;
|
|
||||||
|
|
||||||
/* handle local labels declarations */
|
/* handle local labels declarations */
|
||||||
if (tok == TOK_LABEL) {
|
if (tok == TOK_LABEL) {
|
||||||
next();
|
next();
|
||||||
|
@ -4877,13 +4866,11 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||||
sym_pop(&local_stack, s);
|
sym_pop(&local_stack, s);
|
||||||
|
|
||||||
/* Pop VLA frames and restore stack pointer if required */
|
/* Pop VLA frames and restore stack pointer if required */
|
||||||
if (saved_vla_sp_loc != &vla_sp_root_loc)
|
if (vlas_in_scope > saved_vlas_in_scope) {
|
||||||
*saved_vla_sp_loc = block_vla_sp_loc;
|
vla_sp_loc = saved_vlas_in_scope ? block_vla_sp_loc : vla_sp_root_loc;
|
||||||
if (vla_sp_loc != orig_vla_sp_loc) {
|
vla_sp_restore();
|
||||||
gen_vla_sp_restore(*saved_vla_sp_loc);
|
|
||||||
}
|
}
|
||||||
vla_sp_loc = saved_vla_sp_loc;
|
vlas_in_scope = saved_vlas_in_scope;
|
||||||
vla_flags = (vla_flags & ~VLA_SCOPE_FLAGS) | (saved_vla_flags & VLA_SCOPE_FLAGS);
|
|
||||||
|
|
||||||
next();
|
next();
|
||||||
} else if (tok == TOK_RETURN) {
|
} else if (tok == TOK_RETURN) {
|
||||||
|
@ -4964,13 +4951,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||||
/* compute jump */
|
/* compute jump */
|
||||||
if (!csym)
|
if (!csym)
|
||||||
tcc_error("cannot continue");
|
tcc_error("cannot continue");
|
||||||
if (vla_flags & VLA_IN_SCOPE) {
|
vla_sp_restore_root();
|
||||||
/* If VLAs are in use, save the current stack pointer and
|
|
||||||
reset the stack pointer to what it was at function entry
|
|
||||||
(label will restore stack pointer in inner scopes) */
|
|
||||||
vla_sp_save();
|
|
||||||
gen_vla_sp_restore(vla_sp_root_loc);
|
|
||||||
}
|
|
||||||
*csym = gjmp(*csym);
|
*csym = gjmp(*csym);
|
||||||
next();
|
next();
|
||||||
skip(';');
|
skip(';');
|
||||||
|
@ -4993,10 +4974,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||||
skip(';');
|
skip(';');
|
||||||
d = ind;
|
d = ind;
|
||||||
c = ind;
|
c = ind;
|
||||||
if (vla_flags & VLA_IN_SCOPE) {
|
vla_sp_restore();
|
||||||
gen_vla_sp_restore(*vla_sp_loc);
|
|
||||||
vla_flags |= VLA_NEED_NEW_FRAME;
|
|
||||||
}
|
|
||||||
a = 0;
|
a = 0;
|
||||||
b = 0;
|
b = 0;
|
||||||
if (tok != ';') {
|
if (tok != ';') {
|
||||||
|
@ -5007,10 +4985,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||||
if (tok != ')') {
|
if (tok != ')') {
|
||||||
e = gjmp(0);
|
e = gjmp(0);
|
||||||
c = ind;
|
c = ind;
|
||||||
if (vla_flags & VLA_IN_SCOPE) {
|
vla_sp_restore();
|
||||||
gen_vla_sp_restore(*vla_sp_loc);
|
|
||||||
vla_flags |= VLA_NEED_NEW_FRAME;
|
|
||||||
}
|
|
||||||
gexpr();
|
gexpr();
|
||||||
vpop();
|
vpop();
|
||||||
gjmp_addr(d);
|
gjmp_addr(d);
|
||||||
|
@ -5029,10 +5004,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||||
a = 0;
|
a = 0;
|
||||||
b = 0;
|
b = 0;
|
||||||
d = ind;
|
d = ind;
|
||||||
if (vla_flags & VLA_IN_SCOPE) {
|
vla_sp_restore();
|
||||||
gen_vla_sp_restore(*vla_sp_loc);
|
|
||||||
vla_flags |= VLA_NEED_NEW_FRAME;
|
|
||||||
}
|
|
||||||
block(&a, &b, case_sym, def_sym, case_reg, 0);
|
block(&a, &b, case_sym, def_sym, case_reg, 0);
|
||||||
skip(TOK_WHILE);
|
skip(TOK_WHILE);
|
||||||
skip('(');
|
skip('(');
|
||||||
|
@ -5130,14 +5102,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||||
if (s->r == LABEL_DECLARED)
|
if (s->r == LABEL_DECLARED)
|
||||||
s->r = LABEL_FORWARD;
|
s->r = LABEL_FORWARD;
|
||||||
}
|
}
|
||||||
/* label already defined */
|
vla_sp_restore_root();
|
||||||
if (vla_flags & VLA_IN_SCOPE) {
|
|
||||||
/* If VLAs are in use, save the current stack pointer and
|
|
||||||
reset the stack pointer to what it was at function entry
|
|
||||||
(label will restore stack pointer in inner scopes) */
|
|
||||||
vla_sp_save();
|
|
||||||
gen_vla_sp_restore(vla_sp_root_loc);
|
|
||||||
}
|
|
||||||
if (s->r & LABEL_FORWARD)
|
if (s->r & LABEL_FORWARD)
|
||||||
s->jnext = gjmp(s->jnext);
|
s->jnext = gjmp(s->jnext);
|
||||||
else
|
else
|
||||||
|
@ -5153,12 +5118,6 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||||
b = is_label();
|
b = is_label();
|
||||||
if (b) {
|
if (b) {
|
||||||
/* label case */
|
/* label case */
|
||||||
if (vla_flags & VLA_IN_SCOPE) {
|
|
||||||
/* save/restore stack pointer across label
|
|
||||||
this is a no-op when combined with the load immediately
|
|
||||||
after the label unless we arrive via goto */
|
|
||||||
vla_sp_save();
|
|
||||||
}
|
|
||||||
s = label_find(b);
|
s = label_find(b);
|
||||||
if (s) {
|
if (s) {
|
||||||
if (s->r == LABEL_DEFINED)
|
if (s->r == LABEL_DEFINED)
|
||||||
|
@ -5169,10 +5128,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||||
s = label_push(&global_label_stack, b, LABEL_DEFINED);
|
s = label_push(&global_label_stack, b, LABEL_DEFINED);
|
||||||
}
|
}
|
||||||
s->jnext = ind;
|
s->jnext = ind;
|
||||||
if (vla_flags & VLA_IN_SCOPE) {
|
vla_sp_restore();
|
||||||
gen_vla_sp_restore(*vla_sp_loc);
|
|
||||||
vla_flags |= VLA_NEED_NEW_FRAME;
|
|
||||||
}
|
|
||||||
/* we accept this, but it is a mistake */
|
/* we accept this, but it is a mistake */
|
||||||
block_after_label:
|
block_after_label:
|
||||||
if (tok == '}') {
|
if (tok == '}') {
|
||||||
|
@ -5476,20 +5432,17 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
|
||||||
int a;
|
int a;
|
||||||
|
|
||||||
/* save current stack pointer */
|
/* save current stack pointer */
|
||||||
if (vla_flags & VLA_NEED_NEW_FRAME) {
|
if (vlas_in_scope == 0) {
|
||||||
vla_sp_save();
|
if (vla_sp_root_loc == -1)
|
||||||
vla_flags = VLA_IN_SCOPE;
|
vla_sp_root_loc = (loc -= PTR_SIZE);
|
||||||
vla_sp_loc = &vla_sp_loc_tmp;
|
gen_vla_sp_save(vla_sp_root_loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
vla_runtime_type_size(type, &a);
|
vla_runtime_type_size(type, &a);
|
||||||
gen_vla_alloc(type, a);
|
gen_vla_alloc(type, a);
|
||||||
vla_flags = VLA_IN_SCOPE;
|
gen_vla_sp_save(c);
|
||||||
vla_sp_save();
|
vla_sp_loc = c;
|
||||||
vset(type, VT_LOCAL|VT_LVAL, c);
|
vlas_in_scope++;
|
||||||
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;
|
||||||
|
@ -6072,8 +6025,8 @@ static void gen_function(Sym *sym)
|
||||||
funcname = get_tok_str(sym->v, NULL);
|
funcname = get_tok_str(sym->v, NULL);
|
||||||
func_ind = ind;
|
func_ind = ind;
|
||||||
/* Initialize VLA state */
|
/* Initialize VLA state */
|
||||||
vla_sp_loc = &vla_sp_root_loc;
|
vla_sp_loc = -1;
|
||||||
vla_flags = VLA_NEED_NEW_FRAME;
|
vla_sp_root_loc = -1;
|
||||||
/* put debug symbol */
|
/* put debug symbol */
|
||||||
if (tcc_state->do_debug)
|
if (tcc_state->do_debug)
|
||||||
put_func_debug(sym);
|
put_func_debug(sym);
|
||||||
|
|
|
@ -2240,11 +2240,7 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) {
|
||||||
/* We align to 16 bytes rather than align */
|
/* We align to 16 bytes rather than align */
|
||||||
/* and ~15, %rsp */
|
/* and ~15, %rsp */
|
||||||
o(0xf0e48348);
|
o(0xf0e48348);
|
||||||
/* mov %rsp, r */
|
|
||||||
o(0x8948);
|
|
||||||
o(0xe0 | REG_VALUE(r));
|
|
||||||
vpop();
|
vpop();
|
||||||
vset(type, r, 0);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue