| @@ -154,8 +154,7 @@ static void gen_inline_functions(TCCState *s); · 153 unmodified lines |
| 154 | static void free_inline_functions(TCCState *s); | 154 | static void free_inline_functions(TCCState *s); |
| 155 | static void skip_or_save_block(TokenString **str); | 155 | static void skip_or_save_block(TokenString **str); |
| 156 | static void gv_dup(void); | 156 | static void gv_dup(void); |
| 157 | static int get_temp_local_var(int size,int align); | 157 | static int get_temp_local_var(int size,int align,int *r2); |
| 158 | static void clear_temp_local_var_list(); | | |
| 159 | static void cast_error(CType *st, CType *dt); | 158 | static void cast_error(CType *st, CType *dt); |
| 160 | static void end_switch(void); | 159 | static void end_switch(void); |
| 161 | | 160 | |
| @@ -957,42 +956,38 @@ static void vdup(void) · 795 unmodified lines |
| 957 | vpushv(vtop); | 956 | vpushv(vtop); |
| 958 | } | 957 | } |
| 959 | | 958 | |
| 960 | /* rotate n first stack elements to the bottom | 959 | /* rotate the stack element at position n-1 to the top */ |
| 961 | I1 ... In -> I2 ... In I1 [top is right] | | |
| 962 | */ | | |
| 963 | ST_FUNC void vrotb(int n) | 960 | ST_FUNC void vrotb(int n) |
| 964 | { | 961 | { |
| 965 | int i; | | |
| 966 | SValue tmp; | 962 | SValue tmp; |
| 967 | | 963 | if (--n < 1) |
| | 964 | return; |
| 968 | vcheck_cmp(); | 965 | vcheck_cmp(); |
| 969 | tmp = vtop[-n + 1]; | 966 | tmp = vtop[-n]; |
| 970 | for(i=-n+1;i!=0;i++) | 967 | memmove(vtop - n, vtop - n + 1, sizeof *vtop * n); |
| 971 | vtop[i] = vtop[i+1]; | | |
| 972 | vtop[0] = tmp; | 968 | vtop[0] = tmp; |
| 973 | } | 969 | } |
| 974 | | 970 | |
| 975 | /* rotate the n elements before entry e towards the top | 971 | /* rotate the top stack element into position n-1 */ |
| 976 | I1 ... In ... -> In I1 ... I(n-1) ... [top is right] | 972 | ST_FUNC void vrott(int n) |
| 977 | */ | | |
| 978 | ST_FUNC void vrote(SValue *e, int n) | | |
| 979 | { | 973 | { |
| 980 | int i; | | |
| 981 | SValue tmp; | 974 | SValue tmp; |
| 982 | | 975 | if (--n < 1) |
| | 976 | return; |
| 983 | vcheck_cmp(); | 977 | vcheck_cmp(); |
| 984 | tmp = *e; | 978 | tmp = vtop[0]; |
| 985 | for(i = 0;i < n - 1; i++) | 979 | memmove(vtop - n + 1, vtop - n, sizeof *vtop * n); |
| 986 | e[-i] = e[-i - 1]; | 980 | vtop[-n] = tmp; |
| 987 | e[-n + 1] = tmp; | | |
| 988 | } | 981 | } |
| 989 | | 982 | |
| 990 | /* rotate n first stack elements to the top | 983 | /* reverse order of the the first n stack elements */ |
| 991 | I1 ... In -> In I1 ... I(n-1) [top is right] | 984 | ST_FUNC void vrev(int n) |
| 992 | */ | | |
| 993 | ST_FUNC void vrott(int n) | | |
| 994 | { | 985 | { |
| 995 | vrote(vtop, n); | 986 | int i; |
| | 987 | SValue tmp; |
| | 988 | vcheck_cmp(); |
| | 989 | for (i = 0, n = -n; i > ++n; --i) |
| | 990 | tmp = vtop[i], vtop[i] = vtop[n], vtop[n] = tmp; |
| 996 | } | 991 | } |
| 997 | | 992 | |
| 998 | /* ------------------------------------------------------------------------- */ | 993 | /* ------------------------------------------------------------------------- */ |
| @@ -1354,14 +1349,14 @@ ST_FUNC void save_reg(int r) · 355 unmodified lines |
| 1354 | if seen up to (vtop - n) stack entry */ | 1349 | if seen up to (vtop - n) stack entry */ |
| 1355 | ST_FUNC void save_reg_upstack(int r, int n) | 1350 | ST_FUNC void save_reg_upstack(int r, int n) |
| 1356 | { | 1351 | { |
| 1357 | int l, size, align, bt; | 1352 | int l, size, align, bt, r2; |
| 1358 | SValue *p, *p1, sv; | 1353 | SValue *p, *p1, sv; |
| 1359 | | 1354 | |
| 1360 | if ((r &= VT_VALMASK) >= VT_CONST) | 1355 | if ((r &= VT_VALMASK) >= VT_CONST) |
| 1361 | return; | 1356 | return; |
| 1362 | if (nocode_wanted) | 1357 | if (nocode_wanted) |
| 1363 | return; | 1358 | return; |
| 1364 | l = 0; | 1359 | l = r2 = 0; |
| 1365 | for(p = vstack, p1 = vtop - n; p <= p1; p++) { | 1360 | for(p = vstack, p1 = vtop - n; p <= p1; p++) { |
| 1366 | if ((p->r & VT_VALMASK) == r || p->r2 == r) { | 1361 | if ((p->r & VT_VALMASK) == r || p->r2 == r) { |
| 1367 | /* must save value on stack if not already done */ | 1362 | /* must save value on stack if not already done */ |
| @@ -1373,7 +1368,7 @@ ST_FUNC void save_reg_upstack(int r, int n) · 5 unmodified lines |
| 1373 | bt = VT_PTR; | 1368 | bt = VT_PTR; |
| 1374 | sv.type.t = bt; | 1369 | sv.type.t = bt; |
| 1375 | size = type_size(&sv.type, &align); | 1370 | size = type_size(&sv.type, &align); |
| 1376 | l = get_temp_local_var(size,align); | 1371 | l = get_temp_local_var(size, align, &r2); |
| 1377 | sv.r = VT_LOCAL | VT_LVAL; | 1372 | sv.r = VT_LOCAL | VT_LVAL; |
| 1378 | sv.c.i = l; | 1373 | sv.c.i = l; |
| 1379 | store(p->r & VT_VALMASK, &sv); | 1374 | store(p->r & VT_VALMASK, &sv); |
| @@ -1400,7 +1395,7 @@ ST_FUNC void save_reg_upstack(int r, int n) · 20 unmodified lines |
| 1400 | p->type.t &= ~VT_ARRAY; /* cannot combine VT_LVAL with VT_ARRAY */ | 1395 | p->type.t &= ~VT_ARRAY; /* cannot combine VT_LVAL with VT_ARRAY */ |
| 1401 | } | 1396 | } |
| 1402 | p->sym = NULL; | 1397 | p->sym = NULL; |
| 1403 | p->r2 = VT_CONST; | 1398 | p->r2 = r2; |
| 1404 | p->c.i = l; | 1399 | p->c.i = l; |
| 1405 | } | 1400 | } |
| 1406 | } | 1401 | } |
| @@ -1471,54 +1466,46 @@ ST_FUNC int get_reg(int rc) · 64 unmodified lines |
| 1471 | return -1; | 1466 | return -1; |
| 1472 | } | 1467 | } |
| 1473 | | 1468 | |
| 1474 | /* find a free temporary local variable (return the offset on stack) match the size and align. If none, add new temporary stack variable*/ | 1469 | /* find a free temporary local variable (return the offset on stack) match |
| 1475 | static int get_temp_local_var(int size,int align){ | 1470 | size and align. If none, add new temporary stack variable */ |
| 1476 | int i; | 1471 | static int get_temp_local_var(int size,int align, int *r2) |
| 1477 | struct temp_local_variable *temp_var; | 1472 | { |
| 1478 | int found_var; | 1473 | int i; |
| 1479 | SValue *p; | 1474 | struct temp_local_variable *temp_var; |
| 1480 | int r; | 1475 | SValue *p; |
| 1481 | char free; | 1476 | int r; |
| 1482 | char found; | 1477 | unsigned used = 0; |
| 1483 | found=0; | 1478 | |
| 1484 | for(i=0;i<nb_temp_local_vars;i++){ | 1479 | /* mark locations that are still in use */ |
| 1485 | temp_var=&arr_temp_local_vars[i]; | 1480 | for (p = vstack; p <= vtop; p++) { |
| 1486 | if(temp_var->size<size||align!=temp_var->align){ | 1481 | r = p->r & VT_VALMASK; |
| 1487 | continue; | 1482 | if (r == VT_LOCAL || r == VT_LLOCAL) { |
| 1488 | } | 1483 | r = p->r2 - (VT_CONST + 1); |
| 1489 | /*check if temp_var is free*/ | 1484 | if (r >= 0 && r < MAX_TEMP_LOCAL_VARIABLE_NUMBER) |
| 1490 | free=1; | 1485 | used |= 1<<r; |
| 1491 | for(p=vstack;p<=vtop;p++) { | | |
| 1492 | r=p->r&VT_VALMASK; | | |
| 1493 | if(r==VT_LOCAL||r==VT_LLOCAL){ | | |
| 1494 | if(p->c.i==temp_var->location){ | | |
| 1495 | free=0; | | |
| 1496 | break; | | |
| 1497 | } | | |
| 1498 | } | | |
| 1499 | } | | |
| 1500 | if(free){ | | |
| 1501 | found_var=temp_var->location; | | |
| 1502 | found=1; | | |
| 1503 | break; | | |
| 1504 | } | | |
| 1505 | } | 1486 | } |
| 1506 | if(!found){ | 1487 | } |
| 1507 | loc = (loc - size) & -align; | 1488 | for (i=0;i<nb_temp_local_vars;i++) { |
| 1508 | if(nb_temp_local_vars<MAX_TEMP_LOCAL_VARIABLE_NUMBER){ | 1489 | temp_var=&arr_temp_local_vars[i]; |
| 1509 | temp_var=&arr_temp_local_vars[i]; | 1490 | if(!(used & 1<<i) |
| 1510 | temp_var->location=loc; | 1491 | && temp_var->size>=size |
| 1511 | temp_var->size=size; | 1492 | && temp_var->align>=align) { |
| 1512 | temp_var->align=align; | 1493 | ret_tmp: |
| 1513 | nb_temp_local_vars++; | 1494 | *r2 = (VT_CONST + 1) + i; |
| 1514 | } | 1495 | return temp_var->location; |
| 1515 | found_var=loc; | | |
| 1516 | } | 1496 | } |
| 1517 | return found_var; | 1497 | } |
| 1518 | } | 1498 | loc = (loc - size) & -align; |
| 1519 | | 1499 | if (nb_temp_local_vars<MAX_TEMP_LOCAL_VARIABLE_NUMBER) { |
| 1520 | static void clear_temp_local_var_list(){ | 1500 | temp_var=&arr_temp_local_vars[i]; |
| 1521 | nb_temp_local_vars=0; | 1501 | temp_var->location=loc; |
| | 1502 | temp_var->size=size; |
| | 1503 | temp_var->align=align; |
| | 1504 | nb_temp_local_vars++; |
| | 1505 | goto ret_tmp; |
| | 1506 | } |
| | 1507 | *r2 = VT_CONST; |
| | 1508 | return loc; |
| 1522 | } | 1509 | } |
| 1523 | | 1510 | |
| 1524 | /* move register 's' (of type 't') to 'r', and flush previous value of r to memory | 1511 | /* move register 's' (of type 't') to 'r', and flush previous value of r to memory |
| @@ -6056,6 +6043,7 @@ special_math_val: · 4531 unmodified lines |
| 6056 | SValue ret; | 6043 | SValue ret; |
| 6057 | Sym *sa; | 6044 | Sym *sa; |
| 6058 | int nb_args, ret_nregs, ret_align, regsize, variadic; | 6045 | int nb_args, ret_nregs, ret_align, regsize, variadic; |
| | 6046 | TokenString *p, *p2; |
| 6059 | | 6047 | |
| 6060 | /* function call */ | 6048 | /* function call */ |
| 6061 | if ((vtop->type.t & VT_BTYPE) != VT_FUNC) { | 6049 | if ((vtop->type.t & VT_BTYPE) != VT_FUNC) { |
| @@ -6120,10 +6108,18 @@ special_math_val: · 58 unmodified lines |
| 6120 | ret.c.i = 0; | 6108 | ret.c.i = 0; |
| 6121 | PUT_R_RET(&ret, ret.type.t); | 6109 | PUT_R_RET(&ret, ret.type.t); |
| 6122 | } | 6110 | } |
| | 6111 | |
| | 6112 | p = NULL; |
| 6123 | if (tok != ')') { | 6113 | if (tok != ')') { |
| | 6114 | r = tcc_state->reverse_funcargs; |
| 6124 | for(;;) { | 6115 | for(;;) { |
| 6125 | expr_eq(); | 6116 | if (r) { |
| 6126 | gfunc_param_typed(s, sa); | 6117 | skip_or_save_block(&p2); |
| | 6118 | p2->prev = p, p = p2; |
| | 6119 | } else { |
| | 6120 | expr_eq(); |
| | 6121 | gfunc_param_typed(s, sa); |
| | 6122 | } |
| 6127 | nb_args++; | 6123 | nb_args++; |
| 6128 | if (sa) | 6124 | if (sa) |
| 6129 | sa = sa->next; | 6125 | sa = sa->next; |
| @@ -6134,7 +6130,23 @@ special_math_val: · 4 unmodified lines |
| 6134 | } | 6130 | } |
| 6135 | if (sa) | 6131 | if (sa) |
| 6136 | tcc_error("too few arguments to function"); | 6132 | tcc_error("too few arguments to function"); |
| 6137 | skip(')'); | 6133 | |
| | 6134 | if (p) { /* with reverse_funcargs */ |
| | 6135 | for (n = 0; p; p = p2, ++n) { |
| | 6136 | p2 = p, sa = s; |
| | 6137 | do { |
| | 6138 | sa = sa->next, p2 = p2->prev; |
| | 6139 | } while (p2 && sa); |
| | 6140 | p2 = p->prev; |
| | 6141 | begin_macro(p, 1), next(); |
| | 6142 | expr_eq(); |
| | 6143 | gfunc_param_typed(s, sa); |
| | 6144 | end_macro(); |
| | 6145 | } |
| | 6146 | vrev(n); |
| | 6147 | } |
| | 6148 | |
| | 6149 | next(); |
| 6138 | gfunc_call(nb_args); | 6150 | gfunc_call(nb_args); |
| 6139 | | 6151 | |
| 6140 | if (ret_nregs < 0) { | 6152 | if (ret_nregs < 0) { |
| @@ -8335,12 +8347,12 @@ static void gen_function(Sym *sym) · 2194 unmodified lines |
| 8335 | /* push a dummy symbol to enable local sym storage */ | 8347 | /* push a dummy symbol to enable local sym storage */ |
| 8336 | sym_push2(&local_stack, SYM_FIELD, 0, 0); | 8348 | sym_push2(&local_stack, SYM_FIELD, 0, 0); |
| 8337 | local_scope = 1; /* for function parameters */ | 8349 | local_scope = 1; /* for function parameters */ |
| | 8350 | nb_temp_local_vars = 0; |
| 8338 | gfunc_prolog(sym); | 8351 | gfunc_prolog(sym); |
| 8339 | tcc_debug_prolog_epilog(tcc_state, 0); | 8352 | tcc_debug_prolog_epilog(tcc_state, 0); |
| 8340 | | 8353 | |
| 8341 | local_scope = 0; | 8354 | local_scope = 0; |
| 8342 | rsym = 0; | 8355 | rsym = 0; |
| 8343 | clear_temp_local_var_list(); | | |
| 8344 | func_vla_arg(sym); | 8356 | func_vla_arg(sym); |
| 8345 | block(0); | 8357 | block(0); |
| 8346 | gsym(rsym); | 8358 | gsym(rsym); |