aboutsummaryrefslogtreecommitdiff
path: root/tccgen.c
diff options
context:
space:
mode:
authorseyko <seyko2@gmail.com>2015-05-04 04:09:05 +0300
committerseyko <seyko2@gmail.com>2015-05-04 04:09:05 +0300
commit999274ca900b23da11abeda5f38413eb6fbec9a8 (patch)
tree8ad58caf548733cac9e840cc1ad0b606438ab753 /tccgen.c
parentfca58734fb9819f7c7ccc768284b28439ad4b9f3 (diff)
downloadtinycc-999274ca900b23da11abeda5f38413eb6fbec9a8.tar.gz
tinycc-999274ca900b23da11abeda5f38413eb6fbec9a8.tar.bz2
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
Diffstat (limited to 'tccgen.c')
-rw-r--r--tccgen.c113
1 files changed, 33 insertions, 80 deletions
diff --git a/tccgen.c b/tccgen.c
index e054b4b..5c89b2d 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -55,10 +55,9 @@ ST_DATA Sym *define_stack;
ST_DATA Sym *global_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_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 int vla_sp_loc; /* Pointer to variable holding location to store stack pointer on the stack when modifying stack pointer */
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 unary_type(CType *type);
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 void expr_type(CType *type);
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) {
- if (!(vla_flags & VLA_SP_LOC_SET)) {
- *vla_sp_loc = (loc -= PTR_SIZE);
- vla_flags |= VLA_SP_LOC_SET;
+static void vla_sp_restore(void) {
+ if (vlas_in_scope) {
+ gen_vla_sp_restore(vla_sp_loc);
}
- 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) {
next();
d = ind;
- if (vla_flags & VLA_IN_SCOPE) {
- gen_vla_sp_restore(*vla_sp_loc);
- vla_flags |= VLA_NEED_NEW_FRAME;
- }
+ vla_sp_restore();
skip('(');
gexpr();
skip(')');
@@ -4809,7 +4807,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
gsym_addr(b, d);
} else if (tok == '{') {
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();
/* 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;
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 */
if (tok == TOK_LABEL) {
next();
@@ -4877,13 +4866,11 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
sym_pop(&local_stack, s);
/* Pop VLA frames and restore stack pointer if required */
- if (saved_vla_sp_loc != &vla_sp_root_loc)
- *saved_vla_sp_loc = block_vla_sp_loc;
- if (vla_sp_loc != orig_vla_sp_loc) {
- gen_vla_sp_restore(*saved_vla_sp_loc);
+ if (vlas_in_scope > saved_vlas_in_scope) {
+ vla_sp_loc = saved_vlas_in_scope ? block_vla_sp_loc : vla_sp_root_loc;
+ vla_sp_restore();
}
- vla_sp_loc = saved_vla_sp_loc;
- vla_flags = (vla_flags & ~VLA_SCOPE_FLAGS) | (saved_vla_flags & VLA_SCOPE_FLAGS);
+ vlas_in_scope = saved_vlas_in_scope;
next();
} else if (tok == TOK_RETURN) {
@@ -4964,13 +4951,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
/* compute jump */
if (!csym)
tcc_error("cannot continue");
- 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);
- }
+ vla_sp_restore_root();
*csym = gjmp(*csym);
next();
skip(';');
@@ -4993,10 +4974,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
skip(';');
d = ind;
c = ind;
- if (vla_flags & VLA_IN_SCOPE) {
- gen_vla_sp_restore(*vla_sp_loc);
- vla_flags |= VLA_NEED_NEW_FRAME;
- }
+ vla_sp_restore();
a = 0;
b = 0;
if (tok != ';') {
@@ -5007,10 +4985,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
if (tok != ')') {
e = gjmp(0);
c = ind;
- if (vla_flags & VLA_IN_SCOPE) {
- gen_vla_sp_restore(*vla_sp_loc);
- vla_flags |= VLA_NEED_NEW_FRAME;
- }
+ vla_sp_restore();
gexpr();
vpop();
gjmp_addr(d);
@@ -5029,10 +5004,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
a = 0;
b = 0;
d = ind;
- if (vla_flags & VLA_IN_SCOPE) {
- gen_vla_sp_restore(*vla_sp_loc);
- vla_flags |= VLA_NEED_NEW_FRAME;
- }
+ vla_sp_restore();
block(&a, &b, case_sym, def_sym, case_reg, 0);
skip(TOK_WHILE);
skip('(');
@@ -5130,14 +5102,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
if (s->r == LABEL_DECLARED)
s->r = LABEL_FORWARD;
}
- /* label already defined */
- 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);
- }
+ vla_sp_restore_root();
if (s->r & LABEL_FORWARD)
s->jnext = gjmp(s->jnext);
else
@@ -5153,12 +5118,6 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
b = is_label();
if (b) {
/* 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);
if (s) {
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->jnext = ind;
- if (vla_flags & VLA_IN_SCOPE) {
- gen_vla_sp_restore(*vla_sp_loc);
- vla_flags |= VLA_NEED_NEW_FRAME;
- }
+ vla_sp_restore();
/* we accept this, but it is a mistake */
block_after_label:
if (tok == '}') {
@@ -5476,20 +5432,17 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
int a;
/* save current stack pointer */
- if (vla_flags & VLA_NEED_NEW_FRAME) {
- vla_sp_save();
- vla_flags = VLA_IN_SCOPE;
- vla_sp_loc = &vla_sp_loc_tmp;
+ if (vlas_in_scope == 0) {
+ if (vla_sp_root_loc == -1)
+ vla_sp_root_loc = (loc -= PTR_SIZE);
+ gen_vla_sp_save(vla_sp_root_loc);
}
vla_runtime_type_size(type, &a);
gen_vla_alloc(type, a);
- vla_flags = VLA_IN_SCOPE;
- vla_sp_save();
- vset(type, VT_LOCAL|VT_LVAL, c);
- vswap();
- vstore();
- vpop();
+ gen_vla_sp_save(c);
+ vla_sp_loc = c;
+ vlas_in_scope++;
} else if (type->t & VT_ARRAY) {
s = type->ref;
n = s->c;
@@ -6072,8 +6025,8 @@ static void gen_function(Sym *sym)
funcname = get_tok_str(sym->v, NULL);
func_ind = ind;
/* Initialize VLA state */
- vla_sp_loc = &vla_sp_root_loc;
- vla_flags = VLA_NEED_NEW_FRAME;
+ vla_sp_loc = -1;
+ vla_sp_root_loc = -1;
/* put debug symbol */
if (tcc_state->do_debug)
put_func_debug(sym);