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