Before this patch, save_reg can't reuse the temporary local variable created before to save register. It may consume a lot of stack memory. this patch make save_reg reuse the temporary local variable.
Unified · Split
| @@ -70,6 +70,14 @@ ST_DATA struct switch_t { · 69 unmodified lines | ||
| 70 | 70 | int def_sym; /* default symbol */ |
| 71 | 71 | } *cur_switch; /* current switch */ |
| 72 | 72 | |
| 73 | +#define MAX_TEMP_LOCAL_VARIABLE_NUMBER 0x4 | |
| 74 | +/*list of temporary local variables on the stack in current function. */ | |
| 75 | +ST_DATA struct temp_local_variable { | |
| 76 | + int location; //offset on stack. Svalue.c.i | |
| 77 | + short size; | |
| 78 | + short align; | |
| 79 | +} arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER]; | |
| 80 | +short nb_temp_local_vars; | |
| 73 | 81 | /* ------------------------------------------------------------------------- */ |
| 74 | 82 | |
| 75 | 83 | static void gen_cast(CType *type); |
| @@ -97,6 +105,8 @@ static int gvtst(int inv, int t); · 21 unmodified lines | ||
| 97 | 105 | static void gen_inline_functions(TCCState *s); |
| 98 | 106 | static void skip_or_save_block(TokenString **str); |
| 99 | 107 | static void gv_dup(void); |
| 108 | +static int get_temp_local_var(int size,int align); | |
| 109 | +static void clear_temp_local_var_list(); | |
| 100 | 110 | |
| 101 | 111 | ST_INLN int is_float(int t) |
| 102 | 112 | { |
| @@ -1033,10 +1043,10 @@ ST_FUNC void save_reg_upstack(int r, int n) · 930 unmodified lines | ||
| 1033 | 1043 | type = &int_type; |
| 1034 | 1044 | #endif |
| 1035 | 1045 | size = type_size(type, &align); |
| 1036 | − loc = (loc - size) & -align; | |
| 1046 | + l=get_temp_local_var(size,align); | |
| 1037 | 1047 | sv.type.t = type->t; |
| 1038 | 1048 | sv.r = VT_LOCAL | VT_LVAL; |
| 1039 | − sv.c.i = loc; | |
| 1049 | + sv.c.i = l; | |
| 1040 | 1050 | store(r, &sv); |
| 1041 | 1051 | #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) |
| 1042 | 1052 | /* x86 specific: need to pop fp register ST0 if saved */ |
| @@ -1051,7 +1061,6 @@ ST_FUNC void save_reg_upstack(int r, int n) · 8 unmodified lines | ||
| 1051 | 1061 | store(p->r2, &sv); |
| 1052 | 1062 | } |
| 1053 | 1063 | #endif |
| 1054 | − l = loc; | |
| 1055 | 1064 | saved = 1; |
| 1056 | 1065 | } |
| 1057 | 1066 | /* mark that stack entry as being saved on the stack */ |
| @@ -1134,6 +1143,56 @@ ST_FUNC int get_reg(int rc) · 76 unmodified lines | ||
| 1134 | 1143 | return -1; |
| 1135 | 1144 | } |
| 1136 | 1145 | |
| 1146 | +/* find a free temporary local variable (return the offset on stack) match the size and align. If none, add new temporary stack variable*/ | |
| 1147 | +static int get_temp_local_var(int size,int align){ | |
| 1148 | + int i; | |
| 1149 | + struct temp_local_variable *temp_var; | |
| 1150 | + int found_var; | |
| 1151 | + SValue *p; | |
| 1152 | + int r; | |
| 1153 | + char free; | |
| 1154 | + char found; | |
| 1155 | + found=0; | |
| 1156 | + for(i=0;i<nb_temp_local_vars;i++){ | |
| 1157 | + temp_var=&arr_temp_local_vars[i]; | |
| 1158 | + if(temp_var->size<size||align!=temp_var->align){ | |
| 1159 | + continue; | |
| 1160 | + } | |
| 1161 | + /*check if temp_var is free*/ | |
| 1162 | + free=1; | |
| 1163 | + for(p=vstack;p<=vtop;p++) { | |
| 1164 | + r=p->r&VT_VALMASK; | |
| 1165 | + if(r==VT_LOCAL||r==VT_LLOCAL){ | |
| 1166 | + if(p->c.i==temp_var->location){ | |
| 1167 | + free=0; | |
| 1168 | + break; | |
| 1169 | + } | |
| 1170 | + } | |
| 1171 | + } | |
| 1172 | + if(free){ | |
| 1173 | + found_var=temp_var->location; | |
| 1174 | + found=1; | |
| 1175 | + break; | |
| 1176 | + } | |
| 1177 | + } | |
| 1178 | + if(!found){ | |
| 1179 | + loc = (loc - size) & -align; | |
| 1180 | + if(nb_temp_local_vars<MAX_TEMP_LOCAL_VARIABLE_NUMBER){ | |
| 1181 | + temp_var=&arr_temp_local_vars[i]; | |
| 1182 | + temp_var->location=loc; | |
| 1183 | + temp_var->size=size; | |
| 1184 | + temp_var->align=align; | |
| 1185 | + nb_temp_local_vars++; | |
| 1186 | + } | |
| 1187 | + found_var=loc; | |
| 1188 | + } | |
| 1189 | + return found_var; | |
| 1190 | +} | |
| 1191 | + | |
| 1192 | +static void clear_temp_local_var_list(){ | |
| 1193 | + nb_temp_local_vars=0; | |
| 1194 | +} | |
| 1195 | + | |
| 1137 | 1196 | /* move register 's' (of type 't') to 'r', and flush previous value of r to memory |
| 1138 | 1197 | if needed */ |
| 1139 | 1198 | static void move_reg(int r, int s, int t) |
| @@ -7169,6 +7228,7 @@ static void gen_function(Sym *sym) · 6029 unmodified lines | ||
| 7169 | 7228 | gfunc_prolog(&sym->type); |
| 7170 | 7229 | local_scope = 0; |
| 7171 | 7230 | rsym = 0; |
| 7231 | + clear_temp_local_var_list(); | |
| 7172 | 7232 | block(NULL, NULL, 0); |
| 7173 | 7233 | if (!(nocode_wanted & 0x20000000) |
| 7174 | 7234 | && ((func_vt.t & VT_BTYPE) == VT_INT) |