diff --git a/i386-gen.c b/i386-gen.c index b9dec83..a1ce4c5 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -1126,11 +1126,7 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) { /* We align to 16 bytes rather than align */ /* and ~15, %esp */ o(0xf0e483); - /* mov %esp, r */ - o(0x89); - o(0xe0 | r); vpop(); - vset(type, r, 0); #endif } diff --git a/tcc.h b/tcc.h index 384e8de..f63d83c 100644 --- a/tcc.h +++ b/tcc.h @@ -464,12 +464,6 @@ typedef struct DLLReference { #define SYM_FIELD 0x20000000 /* struct/union field symbol space */ #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 */ #define FUNC_NEW 1 /* ansi function prototype */ #define FUNC_OLD 2 /* old function prototype */ diff --git a/tccgen.c b/tccgen.c index 8c1165f..9df285b 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) { @@ -4963,13 +4950,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(';'); @@ -4992,10 +4973,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 != ';') { @@ -5006,10 +4984,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); @@ -5028,10 +5003,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('('); @@ -5129,14 +5101,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 @@ -5152,12 +5117,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) @@ -5168,10 +5127,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 == '}') { @@ -5475,20 +5431,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; @@ -6071,8 +6024,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); diff --git a/x86_64-gen.c b/x86_64-gen.c index c7a35d8..5a080af 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -2240,11 +2240,7 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) { /* We align to 16 bytes rather than align */ /* and ~15, %rsp */ o(0xf0e48348); - /* mov %rsp, r */ - o(0x8948); - o(0xe0 | REG_VALUE(r)); vpop(); - vset(type, r, 0); #endif }