| @@ -55,10 +55,9 @@ ST_DATA Sym *define_stack; · 54 unmodified lines |
| 55 | ST_DATA Sym *global_label_stack; | 55 | ST_DATA Sym *global_label_stack; |
| 56 | ST_DATA Sym *local_label_stack; | 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 | ST_DATA int vla_sp_root_loc; /* vla_sp_loc for SP before any VLAs were pushed */ | 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 */ | 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 */ | | |
| 62 | | 61 | |
| 63 | ST_DATA SValue __vstack[1+VSTACK_SIZE], *vtop; | 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 | static void expr_eq(void); | 86 | static void expr_eq(void); |
| 88 | static void unary_type(CType *type); | 87 | static void unary_type(CType *type); |
| 89 | static void vla_runtime_type_size(CType *type, int *a); | 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 | static int is_compatible_parameter_types(CType *type1, CType *type2); | 91 | static int is_compatible_parameter_types(CType *type1, CType *type2); |
| 92 | static void expr_type(CType *type); | 92 | static void expr_type(CType *type); |
| 93 | ST_FUNC void vpush64(int ty, unsigned long long v); | 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) { | 2226 | static void vla_sp_restore(void) { |
| 2227 | if (!(vla_flags & VLA_SP_LOC_SET)) { | 2227 | if (vlas_in_scope) { |
| 2228 | *vla_sp_loc = (loc -= PTR_SIZE); | 2228 | gen_vla_sp_restore(vla_sp_loc); |
| 2229 | vla_flags |= VLA_SP_LOC_SET; | | |
| 2230 | } | 2229 | } |
| 2231 | if (!(vla_flags & VLA_SP_SAVED)) { | 2230 | } |
| 2232 | gen_vla_sp_save(*vla_sp_loc); | 2231 | |
| 2233 | vla_flags |= VLA_SP_SAVED; | 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 | } else if (tok == TOK_WHILE) { | 4795 | } else if (tok == TOK_WHILE) { |
| 4795 | next(); | 4796 | next(); |
| 4796 | d = ind; | 4797 | d = ind; |
| 4797 | if (vla_flags & VLA_IN_SCOPE) { | 4798 | vla_sp_restore(); |
| 4798 | gen_vla_sp_restore(*vla_sp_loc); | | |
| 4799 | vla_flags |= VLA_NEED_NEW_FRAME; | | |
| 4800 | } | | |
| 4801 | skip('('); | 4799 | skip('('); |
| 4802 | gexpr(); | 4800 | gexpr(); |
| 4803 | skip(')'); | 4801 | skip(')'); |
| @@ -4809,7 +4807,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 5 unmodified lines |
| 4809 | gsym_addr(b, d); | 4807 | gsym_addr(b, d); |
| 4810 | } else if (tok == '{') { | 4808 | } else if (tok == '{') { |
| 4811 | Sym *llabel; | 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 | next(); | 4812 | next(); |
| 4815 | /* record local declaration stack position */ | 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 | scope_stack_bottom = frame_bottom; | 4817 | scope_stack_bottom = frame_bottom; |
| 4820 | llabel = local_label_stack; | 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 | /* handle local labels declarations */ | 4820 | /* handle local labels declarations */ |
| 4832 | if (tok == TOK_LABEL) { | 4821 | if (tok == TOK_LABEL) { |
| 4833 | next(); | 4822 | next(); |
| @@ -4877,13 +4866,11 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 43 unmodified lines |
| 4877 | sym_pop(&local_stack, s); | 4866 | sym_pop(&local_stack, s); |
| 4878 | | 4867 | |
| 4879 | /* Pop VLA frames and restore stack pointer if required */ | 4868 | /* Pop VLA frames and restore stack pointer if required */ |
| 4880 | if (saved_vla_sp_loc != &vla_sp_root_loc) | 4869 | if (vlas_in_scope > saved_vlas_in_scope) { |
| 4881 | *saved_vla_sp_loc = block_vla_sp_loc; | 4870 | vla_sp_loc = saved_vlas_in_scope ? block_vla_sp_loc : vla_sp_root_loc; |
| 4882 | if (vla_sp_loc != orig_vla_sp_loc) { | 4871 | vla_sp_restore(); |
| 4883 | gen_vla_sp_restore(*saved_vla_sp_loc); | | |
| 4884 | } | 4872 | } |
| 4885 | vla_sp_loc = saved_vla_sp_loc; | 4873 | vlas_in_scope = saved_vlas_in_scope; |
| 4886 | vla_flags = (vla_flags & ~VLA_SCOPE_FLAGS) | (saved_vla_flags & VLA_SCOPE_FLAGS); | | |
| 4887 | | 4874 | |
| 4888 | next(); | 4875 | next(); |
| 4889 | } else if (tok == TOK_RETURN) { | 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 | /* compute jump */ | 4951 | /* compute jump */ |
| 4965 | if (!csym) | 4952 | if (!csym) |
| 4966 | tcc_error("cannot continue"); | 4953 | tcc_error("cannot continue"); |
| 4967 | if (vla_flags & VLA_IN_SCOPE) { | 4954 | vla_sp_restore_root(); |
| 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 | } | | |
| 4974 | *csym = gjmp(*csym); | 4955 | *csym = gjmp(*csym); |
| 4975 | next(); | 4956 | next(); |
| 4976 | skip(';'); | 4957 | skip(';'); |
| @@ -4993,10 +4974,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 16 unmodified lines |
| 4993 | skip(';'); | 4974 | skip(';'); |
| 4994 | d = ind; | 4975 | d = ind; |
| 4995 | c = ind; | 4976 | c = ind; |
| 4996 | if (vla_flags & VLA_IN_SCOPE) { | 4977 | vla_sp_restore(); |
| 4997 | gen_vla_sp_restore(*vla_sp_loc); | | |
| 4998 | vla_flags |= VLA_NEED_NEW_FRAME; | | |
| 4999 | } | | |
| 5000 | a = 0; | 4978 | a = 0; |
| 5001 | b = 0; | 4979 | b = 0; |
| 5002 | if (tok != ';') { | 4980 | if (tok != ';') { |
| @@ -5007,10 +4985,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 4 unmodified lines |
| 5007 | if (tok != ')') { | 4985 | if (tok != ')') { |
| 5008 | e = gjmp(0); | 4986 | e = gjmp(0); |
| 5009 | c = ind; | 4987 | c = ind; |
| 5010 | if (vla_flags & VLA_IN_SCOPE) { | 4988 | vla_sp_restore(); |
| 5011 | gen_vla_sp_restore(*vla_sp_loc); | | |
| 5012 | vla_flags |= VLA_NEED_NEW_FRAME; | | |
| 5013 | } | | |
| 5014 | gexpr(); | 4989 | gexpr(); |
| 5015 | vpop(); | 4990 | vpop(); |
| 5016 | gjmp_addr(d); | 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 | a = 0; | 5004 | a = 0; |
| 5030 | b = 0; | 5005 | b = 0; |
| 5031 | d = ind; | 5006 | d = ind; |
| 5032 | if (vla_flags & VLA_IN_SCOPE) { | 5007 | vla_sp_restore(); |
| 5033 | gen_vla_sp_restore(*vla_sp_loc); | | |
| 5034 | vla_flags |= VLA_NEED_NEW_FRAME; | | |
| 5035 | } | | |
| 5036 | block(&a, &b, case_sym, def_sym, case_reg, 0); | 5008 | block(&a, &b, case_sym, def_sym, case_reg, 0); |
| 5037 | skip(TOK_WHILE); | 5009 | skip(TOK_WHILE); |
| 5038 | skip('('); | 5010 | skip('('); |
| @@ -5130,14 +5102,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 91 unmodified lines |
| 5130 | if (s->r == LABEL_DECLARED) | 5102 | if (s->r == LABEL_DECLARED) |
| 5131 | s->r = LABEL_FORWARD; | 5103 | s->r = LABEL_FORWARD; |
| 5132 | } | 5104 | } |
| 5133 | /* label already defined */ | 5105 | vla_sp_restore_root(); |
| 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 | } | | |
| 5141 | if (s->r & LABEL_FORWARD) | 5106 | if (s->r & LABEL_FORWARD) |
| 5142 | s->jnext = gjmp(s->jnext); | 5107 | s->jnext = gjmp(s->jnext); |
| 5143 | else | 5108 | else |
| @@ -5153,12 +5118,6 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 9 unmodified lines |
| 5153 | b = is_label(); | 5118 | b = is_label(); |
| 5154 | if (b) { | 5119 | if (b) { |
| 5155 | /* label case */ | 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 | s = label_find(b); | 5121 | s = label_find(b); |
| 5163 | if (s) { | 5122 | if (s) { |
| 5164 | if (s->r == LABEL_DEFINED) | 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 | s = label_push(&global_label_stack, b, LABEL_DEFINED); | 5128 | s = label_push(&global_label_stack, b, LABEL_DEFINED); |
| 5170 | } | 5129 | } |
| 5171 | s->jnext = ind; | 5130 | s->jnext = ind; |
| 5172 | if (vla_flags & VLA_IN_SCOPE) { | 5131 | vla_sp_restore(); |
| 5173 | gen_vla_sp_restore(*vla_sp_loc); | | |
| 5174 | vla_flags |= VLA_NEED_NEW_FRAME; | | |
| 5175 | } | | |
| 5176 | /* we accept this, but it is a mistake */ | 5132 | /* we accept this, but it is a mistake */ |
| 5177 | block_after_label: | 5133 | block_after_label: |
| 5178 | if (tok == '}') { | 5134 | if (tok == '}') { |
| @@ -5476,20 +5432,17 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 297 unmodified lines |
| 5476 | int a; | 5432 | int a; |
| 5477 | | 5433 | |
| 5478 | /* save current stack pointer */ | 5434 | /* save current stack pointer */ |
| 5479 | if (vla_flags & VLA_NEED_NEW_FRAME) { | 5435 | if (vlas_in_scope == 0) { |
| 5480 | vla_sp_save(); | 5436 | if (vla_sp_root_loc == -1) |
| 5481 | vla_flags = VLA_IN_SCOPE; | 5437 | vla_sp_root_loc = (loc -= PTR_SIZE); |
| 5482 | vla_sp_loc = &vla_sp_loc_tmp; | 5438 | gen_vla_sp_save(vla_sp_root_loc); |
| 5483 | } | 5439 | } |
| 5484 | | 5440 | |
| 5485 | vla_runtime_type_size(type, &a); | 5441 | vla_runtime_type_size(type, &a); |
| 5486 | gen_vla_alloc(type, a); | 5442 | gen_vla_alloc(type, a); |
| 5487 | vla_flags = VLA_IN_SCOPE; | 5443 | gen_vla_sp_save(c); |
| 5488 | vla_sp_save(); | 5444 | vla_sp_loc = c; |
| 5489 | vset(type, VT_LOCAL|VT_LVAL, c); | 5445 | vlas_in_scope++; |
| 5490 | vswap(); | | |
| 5491 | vstore(); | | |
| 5492 | vpop(); | | |
| 5493 | } else if (type->t & VT_ARRAY) { | 5446 | } else if (type->t & VT_ARRAY) { |
| 5494 | s = type->ref; | 5447 | s = type->ref; |
| 5495 | n = s->c; | 5448 | n = s->c; |
| @@ -6072,8 +6025,8 @@ static void gen_function(Sym *sym) · 576 unmodified lines |
| 6072 | funcname = get_tok_str(sym->v, NULL); | 6025 | funcname = get_tok_str(sym->v, NULL); |
| 6073 | func_ind = ind; | 6026 | func_ind = ind; |
| 6074 | /* Initialize VLA state */ | 6027 | /* Initialize VLA state */ |
| 6075 | vla_sp_loc = &vla_sp_root_loc; | 6028 | vla_sp_loc = -1; |
| 6076 | vla_flags = VLA_NEED_NEW_FRAME; | 6029 | vla_sp_root_loc = -1; |
| 6077 | /* put debug symbol */ | 6030 | /* put debug symbol */ |
| 6078 | if (tcc_state->do_debug) | 6031 | if (tcc_state->do_debug) |
| 6079 | put_func_debug(sym); | 6032 | put_func_debug(sym); |