| @@ -55,10 +55,9 @@ ST_DATA Sym *define_stack; · 54 unmodified lines |
| 55 | 55 | ST_DATA Sym *global_label_stack; |
| 56 | 56 | ST_DATA Sym *local_label_stack; |
| 57 | 57 | |
| 58 | | −ST_DATA int vla_sp_loc_tmp; /* vla_sp_loc is set to this when the value won't be needed later */ |
| 58 | +ST_DATA int vlas_in_scope; /* number of VLAs that are currently in scope */ |
| 59 | 59 | ST_DATA int vla_sp_root_loc; /* vla_sp_loc for SP before any VLAs were pushed */ |
| 60 | | −ST_DATA int *vla_sp_loc; /* Pointer to variable holding location to store stack pointer on the stack when modifying stack pointer */ |
| 61 | | −ST_DATA int vla_flags; /* VLA_* flags */ |
| 60 | +ST_DATA int vla_sp_loc; /* Pointer to variable holding location to store stack pointer on the stack when modifying stack pointer */ |
| 62 | 61 | |
| 63 | 62 | ST_DATA SValue __vstack[1+VSTACK_SIZE], *vtop; |
| 64 | 63 | |
| @@ -87,7 +86,8 @@ static int decl0(int l, int is_for_loop_init); · 22 unmodified lines |
| 87 | 86 | static void expr_eq(void); |
| 88 | 87 | static void unary_type(CType *type); |
| 89 | 88 | static void vla_runtime_type_size(CType *type, int *a); |
| 90 | | −static void vla_sp_save(void); |
| 89 | +static void vla_sp_restore(void); |
| 90 | +static void vla_sp_restore_root(void); |
| 91 | 91 | static int is_compatible_parameter_types(CType *type1, CType *type2); |
| 92 | 92 | static void expr_type(CType *type); |
| 93 | 93 | 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) · 2129 unmodified lines |
| 2223 | 2223 | } |
| 2224 | 2224 | } |
| 2225 | 2225 | |
| 2226 | | −static void vla_sp_save(void) { |
| 2227 | | − if (!(vla_flags & VLA_SP_LOC_SET)) { |
| 2228 | | − *vla_sp_loc = (loc -= PTR_SIZE); |
| 2229 | | − vla_flags |= VLA_SP_LOC_SET; |
| 2226 | +static void vla_sp_restore(void) { |
| 2227 | + if (vlas_in_scope) { |
| 2228 | + gen_vla_sp_restore(vla_sp_loc); |
| 2230 | 2229 | } |
| 2231 | | − if (!(vla_flags & VLA_SP_SAVED)) { |
| 2232 | | − gen_vla_sp_save(*vla_sp_loc); |
| 2233 | | − vla_flags |= VLA_SP_SAVED; |
| 2230 | +} |
| 2231 | + |
| 2232 | +static void vla_sp_restore_root(void) { |
| 2233 | + if (vlas_in_scope) { |
| 2234 | + gen_vla_sp_restore(vla_sp_root_loc); |
| 2234 | 2235 | } |
| 2235 | 2236 | } |
| 2236 | 2237 | |
| @@ -4794,10 +4795,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 2557 unmodified lines |
| 4794 | 4795 | } else if (tok == TOK_WHILE) { |
| 4795 | 4796 | next(); |
| 4796 | 4797 | d = ind; |
| 4797 | | − if (vla_flags & VLA_IN_SCOPE) { |
| 4798 | | − gen_vla_sp_restore(*vla_sp_loc); |
| 4799 | | − vla_flags |= VLA_NEED_NEW_FRAME; |
| 4800 | | − } |
| 4798 | + vla_sp_restore(); |
| 4801 | 4799 | skip('('); |
| 4802 | 4800 | gexpr(); |
| 4803 | 4801 | skip(')'); |
| @@ -4809,7 +4807,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 5 unmodified lines |
| 4809 | 4807 | gsym_addr(b, d); |
| 4810 | 4808 | } else if (tok == '{') { |
| 4811 | 4809 | Sym *llabel; |
| 4812 | | − int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags, *orig_vla_sp_loc; |
| 4810 | + int block_vla_sp_loc = vla_sp_loc, saved_vlas_in_scope = vlas_in_scope; |
| 4813 | 4811 | |
| 4814 | 4812 | next(); |
| 4815 | 4813 | /* record local declaration stack position */ |
| @@ -4819,15 +4817,6 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 3 unmodified lines |
| 4819 | 4817 | scope_stack_bottom = frame_bottom; |
| 4820 | 4818 | llabel = local_label_stack; |
| 4821 | 4819 | |
| 4822 | | − /* save VLA state */ |
| 4823 | | − block_vla_sp_loc = *(saved_vla_sp_loc = vla_sp_loc); |
| 4824 | | − if (saved_vla_sp_loc != &vla_sp_root_loc) |
| 4825 | | − vla_sp_loc = &block_vla_sp_loc; |
| 4826 | | − orig_vla_sp_loc = vla_sp_loc; |
| 4827 | | − |
| 4828 | | − saved_vla_flags = vla_flags; |
| 4829 | | − vla_flags |= VLA_NEED_NEW_FRAME; |
| 4830 | | − |
| 4831 | 4820 | /* handle local labels declarations */ |
| 4832 | 4821 | if (tok == TOK_LABEL) { |
| 4833 | 4822 | next(); |
| @@ -4877,13 +4866,11 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 43 unmodified lines |
| 4877 | 4866 | sym_pop(&local_stack, s); |
| 4878 | 4867 | |
| 4879 | 4868 | /* Pop VLA frames and restore stack pointer if required */ |
| 4880 | | − if (saved_vla_sp_loc != &vla_sp_root_loc) |
| 4881 | | − *saved_vla_sp_loc = block_vla_sp_loc; |
| 4882 | | − if (vla_sp_loc != orig_vla_sp_loc) { |
| 4883 | | − gen_vla_sp_restore(*saved_vla_sp_loc); |
| 4869 | + if (vlas_in_scope > saved_vlas_in_scope) { |
| 4870 | + vla_sp_loc = saved_vlas_in_scope ? block_vla_sp_loc : vla_sp_root_loc; |
| 4871 | + vla_sp_restore(); |
| 4884 | 4872 | } |
| 4885 | | − vla_sp_loc = saved_vla_sp_loc; |
| 4886 | | − vla_flags = (vla_flags & ~VLA_SCOPE_FLAGS) | (saved_vla_flags & VLA_SCOPE_FLAGS); |
| 4873 | + vlas_in_scope = saved_vlas_in_scope; |
| 4887 | 4874 | |
| 4888 | 4875 | next(); |
| 4889 | 4876 | } else if (tok == TOK_RETURN) { |
| @@ -4964,13 +4951,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 74 unmodified lines |
| 4964 | 4951 | /* compute jump */ |
| 4965 | 4952 | if (!csym) |
| 4966 | 4953 | tcc_error("cannot continue"); |
| 4967 | | − if (vla_flags & VLA_IN_SCOPE) { |
| 4968 | | − /* If VLAs are in use, save the current stack pointer and |
| 4969 | | − reset the stack pointer to what it was at function entry |
| 4970 | | − (label will restore stack pointer in inner scopes) */ |
| 4971 | | − vla_sp_save(); |
| 4972 | | − gen_vla_sp_restore(vla_sp_root_loc); |
| 4973 | | − } |
| 4954 | + vla_sp_restore_root(); |
| 4974 | 4955 | *csym = gjmp(*csym); |
| 4975 | 4956 | next(); |
| 4976 | 4957 | skip(';'); |
| @@ -4993,10 +4974,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 16 unmodified lines |
| 4993 | 4974 | skip(';'); |
| 4994 | 4975 | d = ind; |
| 4995 | 4976 | c = ind; |
| 4996 | | − if (vla_flags & VLA_IN_SCOPE) { |
| 4997 | | − gen_vla_sp_restore(*vla_sp_loc); |
| 4998 | | − vla_flags |= VLA_NEED_NEW_FRAME; |
| 4999 | | − } |
| 4977 | + vla_sp_restore(); |
| 5000 | 4978 | a = 0; |
| 5001 | 4979 | b = 0; |
| 5002 | 4980 | if (tok != ';') { |
| @@ -5007,10 +4985,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 4 unmodified lines |
| 5007 | 4985 | if (tok != ')') { |
| 5008 | 4986 | e = gjmp(0); |
| 5009 | 4987 | c = ind; |
| 5010 | | − if (vla_flags & VLA_IN_SCOPE) { |
| 5011 | | − gen_vla_sp_restore(*vla_sp_loc); |
| 5012 | | − vla_flags |= VLA_NEED_NEW_FRAME; |
| 5013 | | − } |
| 4988 | + vla_sp_restore(); |
| 5014 | 4989 | gexpr(); |
| 5015 | 4990 | vpop(); |
| 5016 | 4991 | gjmp_addr(d); |
| @@ -5029,10 +5004,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 12 unmodified lines |
| 5029 | 5004 | a = 0; |
| 5030 | 5005 | b = 0; |
| 5031 | 5006 | d = ind; |
| 5032 | | − if (vla_flags & VLA_IN_SCOPE) { |
| 5033 | | − gen_vla_sp_restore(*vla_sp_loc); |
| 5034 | | − vla_flags |= VLA_NEED_NEW_FRAME; |
| 5035 | | − } |
| 5007 | + vla_sp_restore(); |
| 5036 | 5008 | block(&a, &b, case_sym, def_sym, case_reg, 0); |
| 5037 | 5009 | skip(TOK_WHILE); |
| 5038 | 5010 | skip('('); |
| @@ -5130,14 +5102,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 91 unmodified lines |
| 5130 | 5102 | if (s->r == LABEL_DECLARED) |
| 5131 | 5103 | s->r = LABEL_FORWARD; |
| 5132 | 5104 | } |
| 5133 | | − /* label already defined */ |
| 5134 | | − if (vla_flags & VLA_IN_SCOPE) { |
| 5135 | | − /* If VLAs are in use, save the current stack pointer and |
| 5136 | | − reset the stack pointer to what it was at function entry |
| 5137 | | − (label will restore stack pointer in inner scopes) */ |
| 5138 | | − vla_sp_save(); |
| 5139 | | − gen_vla_sp_restore(vla_sp_root_loc); |
| 5140 | | − } |
| 5105 | + vla_sp_restore_root(); |
| 5141 | 5106 | if (s->r & LABEL_FORWARD) |
| 5142 | 5107 | s->jnext = gjmp(s->jnext); |
| 5143 | 5108 | else |
| @@ -5153,12 +5118,6 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 9 unmodified lines |
| 5153 | 5118 | b = is_label(); |
| 5154 | 5119 | if (b) { |
| 5155 | 5120 | /* label case */ |
| 5156 | | − if (vla_flags & VLA_IN_SCOPE) { |
| 5157 | | − /* save/restore stack pointer across label |
| 5158 | | − this is a no-op when combined with the load immediately |
| 5159 | | − after the label unless we arrive via goto */ |
| 5160 | | − vla_sp_save(); |
| 5161 | | − } |
| 5162 | 5121 | s = label_find(b); |
| 5163 | 5122 | if (s) { |
| 5164 | 5123 | if (s->r == LABEL_DEFINED) |
| @@ -5169,10 +5128,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 4 unmodified lines |
| 5169 | 5128 | s = label_push(&global_label_stack, b, LABEL_DEFINED); |
| 5170 | 5129 | } |
| 5171 | 5130 | s->jnext = ind; |
| 5172 | | − if (vla_flags & VLA_IN_SCOPE) { |
| 5173 | | − gen_vla_sp_restore(*vla_sp_loc); |
| 5174 | | − vla_flags |= VLA_NEED_NEW_FRAME; |
| 5175 | | − } |
| 5131 | + vla_sp_restore(); |
| 5176 | 5132 | /* we accept this, but it is a mistake */ |
| 5177 | 5133 | block_after_label: |
| 5178 | 5134 | if (tok == '}') { |
| @@ -5476,20 +5432,17 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 297 unmodified lines |
| 5476 | 5432 | int a; |
| 5477 | 5433 | |
| 5478 | 5434 | /* save current stack pointer */ |
| 5479 | | − if (vla_flags & VLA_NEED_NEW_FRAME) { |
| 5480 | | − vla_sp_save(); |
| 5481 | | − vla_flags = VLA_IN_SCOPE; |
| 5482 | | − vla_sp_loc = &vla_sp_loc_tmp; |
| 5435 | + if (vlas_in_scope == 0) { |
| 5436 | + if (vla_sp_root_loc == -1) |
| 5437 | + vla_sp_root_loc = (loc -= PTR_SIZE); |
| 5438 | + gen_vla_sp_save(vla_sp_root_loc); |
| 5483 | 5439 | } |
| 5484 | 5440 | |
| 5485 | 5441 | vla_runtime_type_size(type, &a); |
| 5486 | 5442 | gen_vla_alloc(type, a); |
| 5487 | | − vla_flags = VLA_IN_SCOPE; |
| 5488 | | − vla_sp_save(); |
| 5489 | | − vset(type, VT_LOCAL|VT_LVAL, c); |
| 5490 | | − vswap(); |
| 5491 | | − vstore(); |
| 5492 | | − vpop(); |
| 5443 | + gen_vla_sp_save(c); |
| 5444 | + vla_sp_loc = c; |
| 5445 | + vlas_in_scope++; |
| 5493 | 5446 | } else if (type->t & VT_ARRAY) { |
| 5494 | 5447 | s = type->ref; |
| 5495 | 5448 | n = s->c; |
| @@ -6072,8 +6025,8 @@ static void gen_function(Sym *sym) · 576 unmodified lines |
| 6072 | 6025 | funcname = get_tok_str(sym->v, NULL); |
| 6073 | 6026 | func_ind = ind; |
| 6074 | 6027 | /* Initialize VLA state */ |
| 6075 | | − vla_sp_loc = &vla_sp_root_loc; |
| 6076 | | − vla_flags = VLA_NEED_NEW_FRAME; |
| 6028 | + vla_sp_loc = -1; |
| 6029 | + vla_sp_root_loc = -1; |
| 6077 | 6030 | /* put debug symbol */ |
| 6078 | 6031 | if (tcc_state->do_debug) |
| 6079 | 6032 | put_func_debug(sym); |