Unified · Split
| @@ -52,9 +52,9 @@ · 51 unmodified lines | ||
| 52 | 52 | #define STRING_MAX_SIZE 1024 |
| 53 | 53 | #define INCLUDE_PATHS_MAX 32 |
| 54 | 54 | |
| 55 | −#define TOK_HASH_SIZE 521 | |
| 56 | −#define TOK_ALLOC_INCR 256 /* must be a power of two */ | |
| 57 | −#define SYM_HASH_SIZE 263 | |
| 55 | +#define TOK_HASH_SIZE 2048 /* must be a power of two */ | |
| 56 | +#define TOK_ALLOC_INCR 512 /* must be a power of two */ | |
| 57 | +#define SYM_HASH_SIZE 1031 | |
| 58 | 58 | |
| 59 | 59 | /* token symbol management */ |
| 60 | 60 | typedef struct TokenSym { |
| @@ -131,16 +131,22 @@ typedef struct Section { · 70 unmodified lines | ||
| 131 | 131 | typedef struct AttributeDef { |
| 132 | 132 | int aligned; |
| 133 | 133 | Section *section; |
| 134 | + unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */ | |
| 134 | 135 | } AttributeDef; |
| 135 | 136 | |
| 136 | 137 | #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */ |
| 137 | 138 | #define SYM_FIELD 0x20000000 /* struct/union field symbol space */ |
| 138 | 139 | #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */ |
| 139 | 140 | |
| 141 | +/* stored in 'Sym.c' field */ | |
| 140 | 142 | #define FUNC_NEW 1 /* ansi function prototype */ |
| 141 | 143 | #define FUNC_OLD 2 /* old function prototype */ |
| 142 | 144 | #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */ |
| 143 | 145 | |
| 146 | +/* stored in 'Sym.r' field */ | |
| 147 | +#define FUNC_CDECL 0 /* standard c call */ | |
| 148 | +#define FUNC_STDCALL 1 /* pascal c call */ | |
| 149 | + | |
| 144 | 150 | /* field 'Sym.t' for macros */ |
| 145 | 151 | #define MACRO_OBJ 0 /* object like macro */ |
| 146 | 152 | #define MACRO_FUNC 1 /* function like macro */ |
| @@ -215,6 +221,11 @@ int do_debug = 0; · 68 unmodified lines | ||
| 215 | 221 | /* compile with built-in memory and bounds checker */ |
| 216 | 222 | int do_bounds_check = 0; |
| 217 | 223 | |
| 224 | +/* display benchmark infos */ | |
| 225 | +int do_bench = 0; | |
| 226 | +int total_lines; | |
| 227 | +int total_bytes; | |
| 228 | + | |
| 218 | 229 | /* use GNU C extensions */ |
| 219 | 230 | int gnu_ext = 1; |
| 220 | 231 | |
| @@ -405,8 +416,33 @@ enum { · 184 unmodified lines | ||
| 405 | 416 | TOK___ALIGNED__, |
| 406 | 417 | TOK_UNUSED, |
| 407 | 418 | TOK___UNUSED__, |
| 419 | + TOK_CDECL, | |
| 420 | + TOK___CDECL, | |
| 421 | + TOK___CDECL__, | |
| 422 | + TOK_STDCALL, | |
| 423 | + TOK___STDCALL, | |
| 424 | + TOK___STDCALL__, | |
| 425 | + TOK_NORETURN, | |
| 426 | + TOK___NORETURN__, | |
| 408 | 427 | }; |
| 409 | 428 | |
| 429 | +char *tcc_keywords = | |
| 430 | +"int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0" | |
| 431 | +"unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0" | |
| 432 | +"register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0" | |
| 433 | +"float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0" | |
| 434 | +"sizeof\0__attribute__\0" | |
| 435 | +/* the following are not keywords. They are included to ease parsing */ | |
| 436 | +"define\0include\0ifdef\0ifndef\0elif\0endif\0" | |
| 437 | +"defined\0undef\0error\0line\0" | |
| 438 | +"__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0" | |
| 439 | +"__func__\0main\0" | |
| 440 | +/* attributes */ | |
| 441 | +"section\0__section__\0aligned\0__aligned__\0unused\0__unused__\0" | |
| 442 | +"cdecl\0__cdecl\0__cdecl__\0stdcall\0__stdcall\0__stdcall__\0" | |
| 443 | +"noreturn\0__noreturn__\0" | |
| 444 | +; | |
| 445 | + | |
| 410 | 446 | #ifdef WIN32 |
| 411 | 447 | #define snprintf _snprintf |
| 412 | 448 | /* currently incorrect */ |
| @@ -459,7 +495,7 @@ int pointed_type(int t); · 46 unmodified lines | ||
| 459 | 495 | int pointed_size(int t); |
| 460 | 496 | int is_compatible_types(int t1, int t2); |
| 461 | 497 | int parse_btype(int *type_ptr, AttributeDef *ad); |
| 462 | −int type_decl(int *v, int t, int td); | |
| 498 | +int type_decl(AttributeDef *ad, int *v, int t, int td); | |
| 463 | 499 | |
| 464 | 500 | void error(const char *fmt, ...); |
| 465 | 501 | void rt_error(unsigned long pc, const char *fmt, ...); |
| @@ -800,7 +836,7 @@ TokenSym *tok_alloc(const char *str, int len) · 334 unmodified lines | ||
| 800 | 836 | len = strlen(str); |
| 801 | 837 | h = 1; |
| 802 | 838 | for(i=0;i<len;i++) |
| 803 | − h = ((h << 8) | (str[i] & 0xff)) % TOK_HASH_SIZE; | |
| 839 | + h = (h * 263 + ((unsigned char *)str)[i]) & (TOK_HASH_SIZE - 1); | |
| 804 | 840 | |
| 805 | 841 | pts = &hash_ident[h]; |
| 806 | 842 | while (1) { |
| @@ -1034,11 +1070,13 @@ BufferedFile *tcc_open(const char *filename) · 227 unmodified lines | ||
| 1034 | 1070 | bf->buffer[0] = CH_EOB; /* put eob symbol */ |
| 1035 | 1071 | pstrcpy(bf->filename, sizeof(bf->filename), filename); |
| 1036 | 1072 | bf->line_num = 1; |
| 1073 | + // printf("opening '%s'\n", filename); | |
| 1037 | 1074 | return bf; |
| 1038 | 1075 | } |
| 1039 | 1076 | |
| 1040 | 1077 | void tcc_close(BufferedFile *bf) |
| 1041 | 1078 | { |
| 1079 | + total_lines += bf->line_num; | |
| 1042 | 1080 | close(bf->fd); |
| 1043 | 1081 | free(bf); |
| 1044 | 1082 | } |
| @@ -1059,6 +1097,7 @@ int tcc_getc_slow(BufferedFile *bf) · 14 unmodified lines | ||
| 1059 | 1097 | } else { |
| 1060 | 1098 | len = 0; |
| 1061 | 1099 | } |
| 1100 | + total_bytes += len; | |
| 1062 | 1101 | bf->buf_ptr = bf->buffer; |
| 1063 | 1102 | bf->buf_end = bf->buffer + len; |
| 1064 | 1103 | *bf->buf_end = CH_EOB; |
| @@ -1290,7 +1329,7 @@ int expr_preprocess(void) · 225 unmodified lines | ||
| 1290 | 1329 | return c != 0; |
| 1291 | 1330 | } |
| 1292 | 1331 | |
| 1293 | −#if defined(DEBUG) | |
| 1332 | +#if defined(DEBUG) || defined(PP_DEBUG) | |
| 1294 | 1333 | void tok_print(int *str) |
| 1295 | 1334 | { |
| 1296 | 1335 | int t; |
| @@ -1454,25 +1493,32 @@ void preprocess(void) · 157 unmodified lines | ||
| 1454 | 1493 | *ifdef_stack_ptr++ = c; |
| 1455 | 1494 | goto test_skip; |
| 1456 | 1495 | } else if (tok == TOK_ELSE) { |
| 1457 | − if (ifdef_stack_ptr == ifdef_stack || | |
| 1458 | − (ifdef_stack_ptr[-1] & 2)) | |
| 1496 | + if (ifdef_stack_ptr == ifdef_stack) | |
| 1497 | + error("#else without matching #if"); | |
| 1498 | + if (ifdef_stack_ptr[-1] & 2) | |
| 1459 | 1499 | error("#else after #else"); |
| 1460 | 1500 | c = (ifdef_stack_ptr[-1] ^= 3); |
| 1461 | 1501 | goto test_skip; |
| 1462 | 1502 | } else if (tok == TOK_ELIF) { |
| 1463 | − if (ifdef_stack_ptr == ifdef_stack || | |
| 1464 | − ifdef_stack_ptr[-1] > 1) | |
| 1503 | + if (ifdef_stack_ptr == ifdef_stack) | |
| 1504 | + error("#elif without matching #if"); | |
| 1505 | + c = ifdef_stack_ptr[-1]; | |
| 1506 | + if (c > 1) | |
| 1465 | 1507 | error("#elif after #else"); |
| 1508 | + /* last #if/#elif expression was true: we skip */ | |
| 1509 | + if (c == 1) | |
| 1510 | + goto skip; | |
| 1466 | 1511 | c = expr_preprocess(); |
| 1467 | 1512 | ifdef_stack_ptr[-1] = c; |
| 1468 | 1513 | test_skip: |
| 1469 | 1514 | if (!(c & 1)) { |
| 1515 | + skip: | |
| 1470 | 1516 | preprocess_skip(); |
| 1471 | 1517 | goto redo; |
| 1472 | 1518 | } |
| 1473 | 1519 | } else if (tok == TOK_ENDIF) { |
| 1474 | 1520 | if (ifdef_stack_ptr == ifdef_stack) |
| 1475 | − expect("#if"); | |
| 1521 | + error("#endif without matching #if"); | |
| 1476 | 1522 | ifdef_stack_ptr--; |
| 1477 | 1523 | } else if (tok == TOK_LINE) { |
| 1478 | 1524 | next(); |
| @@ -1876,7 +1922,7 @@ void next_nomacro1(void) · 397 unmodified lines | ||
| 1876 | 1922 | while(1) { |
| 1877 | 1923 | while (ch == '\n') { |
| 1878 | 1924 | cinp(); |
| 1879 | − while (ch == ' ' || ch == 9) | |
| 1925 | + while (ch == ' ' || ch == '\t') | |
| 1880 | 1926 | cinp(); |
| 1881 | 1927 | if (ch == '#') { |
| 1882 | 1928 | /* preprocessor command if # at start of line after |
| @@ -2157,7 +2203,14 @@ void macro_subst(int **tok_str, int *tok_len, · 274 unmodified lines | ||
| 2157 | 2203 | next_nomacro(); |
| 2158 | 2204 | args = NULL; |
| 2159 | 2205 | sa = s->next; |
| 2160 | − while (tok != ')' && sa) { | |
| 2206 | + /* NOTE: empty args are allowed, except if no args */ | |
| 2207 | + for(;;) { | |
| 2208 | + /* handle '()' case */ | |
| 2209 | + if (!args && tok == ')') | |
| 2210 | + break; | |
| 2211 | + if (!sa) | |
| 2212 | + error("macro '%s' used with too many args", | |
| 2213 | + get_tok_str(s->v, 0)); | |
| 2161 | 2214 | len = 0; |
| 2162 | 2215 | str = NULL; |
| 2163 | 2216 | parlevel = 0; |
| @@ -2175,13 +2228,17 @@ void macro_subst(int **tok_str, int *tok_len, · 11 unmodified lines | ||
| 2175 | 2228 | } |
| 2176 | 2229 | tok_add(&str, &len, 0); |
| 2177 | 2230 | sym_push2(&args, sa->v & ~SYM_FIELD, 0, (int)str); |
| 2178 | − if (tok != ',') | |
| 2231 | + if (tok == ')') | |
| 2179 | 2232 | break; |
| 2233 | + if (tok != ',') | |
| 2234 | + expect(","); | |
| 2180 | 2235 | next_nomacro(); |
| 2181 | 2236 | sa = sa->next; |
| 2182 | 2237 | } |
| 2183 | − if (tok != ')') | |
| 2184 | − expect(")"); | |
| 2238 | + if (sa->next) | |
| 2239 | + error("macro '%s' used with too few args", | |
| 2240 | + get_tok_str(s->v, 0)); | |
| 2241 | + | |
| 2185 | 2242 | /* now subst each arg */ |
| 2186 | 2243 | mstr = macro_arg_subst(nested_list, mstr, args); |
| 2187 | 2244 | /* free memory */ |
| @@ -2232,7 +2289,7 @@ void next(void) · 44 unmodified lines | ||
| 2232 | 2289 | } else { |
| 2233 | 2290 | redo: |
| 2234 | 2291 | if (!macro_ptr) { |
| 2235 | − /* if not reading from macro substuted string, then try to substitute */ | |
| 2292 | + /* if not reading from macro substituted string, then try to substitute */ | |
| 2236 | 2293 | len = 0; |
| 2237 | 2294 | ptr = NULL; |
| 2238 | 2295 | nested_list = NULL; |
| @@ -2338,7 +2395,8 @@ void save_reg(int r) · 99 unmodified lines | ||
| 2338 | 2395 | if (!saved) { |
| 2339 | 2396 | /* store register in the stack */ |
| 2340 | 2397 | t = p->t; |
| 2341 | − if (!is_float(t) && (t & VT_BTYPE) != VT_LLONG) | |
| 2398 | + if ((p->r & VT_LVAL) || | |
| 2399 | + (!is_float(t) && (t & VT_BTYPE) != VT_LLONG)) | |
| 2342 | 2400 | t = VT_INT; |
| 2343 | 2401 | size = type_size(t, &align); |
| 2344 | 2402 | loc = (loc - size) & -align; |
| @@ -2690,7 +2748,7 @@ void gen_opl(int op) · 345 unmodified lines | ||
| 2690 | 2748 | func = __modull; |
| 2691 | 2749 | gen_func: |
| 2692 | 2750 | /* call generic long long function */ |
| 2693 | − gfunc_start(&gf); | |
| 2751 | + gfunc_start(&gf, FUNC_CDECL); | |
| 2694 | 2752 | gfunc_param(&gf); |
| 2695 | 2753 | gfunc_param(&gf); |
| 2696 | 2754 | vpushi((int)func); |
| @@ -3139,7 +3197,7 @@ void gen_cvt_itof1(int t) · 442 unmodified lines | ||
| 3139 | 3197 | if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == |
| 3140 | 3198 | (VT_LLONG | VT_UNSIGNED)) { |
| 3141 | 3199 | |
| 3142 | − gfunc_start(&gf); | |
| 3200 | + gfunc_start(&gf, FUNC_CDECL); | |
| 3143 | 3201 | gfunc_param(&gf); |
| 3144 | 3202 | if (t == VT_FLOAT) |
| 3145 | 3203 | vpushi((int)&__ulltof); |
| @@ -3163,7 +3221,7 @@ void gen_cvt_ftoi1(int t) · 17 unmodified lines | ||
| 3163 | 3221 | |
| 3164 | 3222 | if (t == (VT_LLONG | VT_UNSIGNED)) { |
| 3165 | 3223 | /* not handled natively */ |
| 3166 | − gfunc_start(&gf); | |
| 3224 | + gfunc_start(&gf, FUNC_CDECL); | |
| 3167 | 3225 | st = vtop->t & VT_BTYPE; |
| 3168 | 3226 | gfunc_param(&gf); |
| 3169 | 3227 | if (st == VT_FLOAT) |
| @@ -3346,6 +3404,8 @@ void gen_cast(int t) · 176 unmodified lines | ||
| 3346 | 3404 | /* from long long: just take low order word */ |
| 3347 | 3405 | lexpand(); |
| 3348 | 3406 | vpop(); |
| 3407 | + } else if (sbt == VT_PTR) { | |
| 3408 | + /* ok to cast */ | |
| 3349 | 3409 | } else if (vtop->r & VT_LVAL) { |
| 3350 | 3410 | /* if lvalue and single word type, nothing to do (XXX: |
| 3351 | 3411 | maybe incorrect for sizeof op) */ |
| @@ -3616,7 +3676,7 @@ void vstore(void) · 264 unmodified lines | ||
| 3616 | 3676 | /* XXX: optimize if small size */ |
| 3617 | 3677 | |
| 3618 | 3678 | vdup(); |
| 3619 | − gfunc_start(&gf); | |
| 3679 | + gfunc_start(&gf, FUNC_CDECL); | |
| 3620 | 3680 | /* type size */ |
| 3621 | 3681 | size = type_size(vtop->t, &align); |
| 3622 | 3682 | vpushi(size); |
| @@ -3759,6 +3819,21 @@ void parse_attribute(AttributeDef *ad) · 136 unmodified lines | ||
| 3759 | 3819 | /* currently, no need to handle it because tcc does not |
| 3760 | 3820 | track unused objects */ |
| 3761 | 3821 | break; |
| 3822 | + case TOK_NORETURN: | |
| 3823 | + case TOK___NORETURN__: | |
| 3824 | + /* currently, no need to handle it because tcc does not | |
| 3825 | + track unused objects */ | |
| 3826 | + break; | |
| 3827 | + case TOK_CDECL: | |
| 3828 | + case TOK___CDECL: | |
| 3829 | + case TOK___CDECL__: | |
| 3830 | + ad->func_call = FUNC_CDECL; | |
| 3831 | + break; | |
| 3832 | + case TOK_STDCALL: | |
| 3833 | + case TOK___STDCALL: | |
| 3834 | + case TOK___STDCALL__: | |
| 3835 | + ad->func_call = FUNC_STDCALL; | |
| 3836 | + break; | |
| 3762 | 3837 | default: |
| 3763 | 3838 | warning("'%s' attribute ignored", get_tok_str(t, NULL)); |
| 3764 | 3839 | /* skip parameters */ |
| @@ -3837,7 +3912,7 @@ int struct_decl(int u) · 72 unmodified lines | ||
| 3837 | 3912 | bit_size = -1; |
| 3838 | 3913 | v = 0; |
| 3839 | 3914 | if (tok != ':') { |
| 3840 | − t = type_decl(&v, b, TYPE_DIRECT); | |
| 3915 | + t = type_decl(&ad, &v, b, TYPE_DIRECT); | |
| 3841 | 3916 | if ((t & VT_BTYPE) == VT_FUNC || |
| 3842 | 3917 | (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN))) |
| 3843 | 3918 | error("invalid type for '%s'", |
| @@ -4055,11 +4130,11 @@ the_end: · 211 unmodified lines | ||
| 4055 | 4130 | return type_found; |
| 4056 | 4131 | } |
| 4057 | 4132 | |
| 4058 | −int post_type(int t) | |
| 4133 | +int post_type(int t, AttributeDef *ad) | |
| 4059 | 4134 | { |
| 4060 | 4135 | int p, n, pt, l, t1; |
| 4061 | 4136 | Sym **plast, *s, *first; |
| 4062 | − AttributeDef ad; | |
| 4137 | + AttributeDef ad1; | |
| 4063 | 4138 | |
| 4064 | 4139 | if (tok == '(') { |
| 4065 | 4140 | /* function declaration */ |
| @@ -4070,7 +4145,7 @@ int post_type(int t) · 4 unmodified lines | ||
| 4070 | 4145 | while (tok != ')') { |
| 4071 | 4146 | /* read param name and compute offset */ |
| 4072 | 4147 | if (l != FUNC_OLD) { |
| 4073 | − if (!parse_btype(&pt, &ad)) { | |
| 4148 | + if (!parse_btype(&pt, &ad1)) { | |
| 4074 | 4149 | if (l) { |
| 4075 | 4150 | error("invalid type"); |
| 4076 | 4151 | } else { |
| @@ -4081,7 +4156,7 @@ int post_type(int t) · 4 unmodified lines | ||
| 4081 | 4156 | l = FUNC_NEW; |
| 4082 | 4157 | if ((pt & VT_BTYPE) == VT_VOID && tok == ')') |
| 4083 | 4158 | break; |
| 4084 | − pt = type_decl(&n, pt, TYPE_DIRECT | TYPE_ABSTRACT); | |
| 4159 | + pt = type_decl(&ad1, &n, pt, TYPE_DIRECT | TYPE_ABSTRACT); | |
| 4085 | 4160 | if ((pt & VT_BTYPE) == VT_VOID) |
| 4086 | 4161 | error("parameter declared as void"); |
| 4087 | 4162 | } else { |
| @@ -4109,10 +4184,10 @@ int post_type(int t) · 21 unmodified lines | ||
| 4109 | 4184 | l = FUNC_OLD; |
| 4110 | 4185 | skip(')'); |
| 4111 | 4186 | t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN); |
| 4112 | − t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN)); | |
| 4187 | + t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad); | |
| 4113 | 4188 | /* we push a anonymous symbol which will contain the function prototype */ |
| 4114 | 4189 | p = anon_sym++; |
| 4115 | − s = sym_push(p, t, 0, l); | |
| 4190 | + s = sym_push(p, t, ad->func_call, l); | |
| 4116 | 4191 | s->next = first; |
| 4117 | 4192 | t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT); |
| 4118 | 4193 | } else if (tok == '[') { |
| @@ -4127,7 +4202,7 @@ int post_type(int t) · 8 unmodified lines | ||
| 4127 | 4202 | skip(']'); |
| 4128 | 4203 | /* parse next post type */ |
| 4129 | 4204 | t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN); |
| 4130 | − t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN)); | |
| 4205 | + t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad); | |
| 4131 | 4206 | |
| 4132 | 4207 | /* we push a anonymous symbol which will contain the array |
| 4133 | 4208 | element type */ |
| @@ -4139,8 +4214,10 @@ int post_type(int t) · 5 unmodified lines | ||
| 4139 | 4214 | } |
| 4140 | 4215 | |
| 4141 | 4216 | /* Read a type declaration (except basic type), and return the |
| 4142 | − type. If v is true, then also put variable name in 'vtop->c' */ | |
| 4143 | −int type_decl(int *v, int t, int td) | |
| 4217 | + type. 'td' is a bitmask indicating which kind of type decl is | |
| 4218 | + expected. 't' should contain the basic type. 'ad' is the attribute | |
| 4219 | + definition of the basic type. It can be modified by type_decl(). */ | |
| 4220 | +int type_decl(AttributeDef *ad, int *v, int t, int td) | |
| 4144 | 4221 | { |
| 4145 | 4222 | int u, p; |
| 4146 | 4223 | Sym *s; |
| @@ -4156,7 +4233,11 @@ int type_decl(int *v, int t, int td) · 9 unmodified lines | ||
| 4156 | 4233 | /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */ |
| 4157 | 4234 | if (tok == '(') { |
| 4158 | 4235 | next(); |
| 4159 | − u = type_decl(v, 0, td); | |
| 4236 | + /* XXX: this is not correct to modify 'ad' at this point, but | |
| 4237 | + the syntax is not clear */ | |
| 4238 | + if (tok == TOK___ATTRIBUTE__) | |
| 4239 | + parse_attribute(ad); | |
| 4240 | + u = type_decl(ad, v, 0, td); | |
| 4160 | 4241 | skip(')'); |
| 4161 | 4242 | } else { |
| 4162 | 4243 | u = 0; |
| @@ -4171,8 +4252,10 @@ int type_decl(int *v, int t, int td) · 8 unmodified lines | ||
| 4171 | 4252 | } |
| 4172 | 4253 | } |
| 4173 | 4254 | /* append t at the end of u */ |
| 4174 | − t = post_type(t); | |
| 4175 | − if (!u) | |
| 4255 | + t = post_type(t, ad); | |
| 4256 | + if (tok == TOK___ATTRIBUTE__) | |
| 4257 | + parse_attribute(ad); | |
| 4258 | + if (!u) | |
| 4176 | 4259 | return t; |
| 4177 | 4260 | p = u; |
| 4178 | 4261 | while(1) { |
| @@ -4295,7 +4378,7 @@ void unary(void) · 116 unmodified lines | ||
| 4295 | 4378 | if (t == '(') { |
| 4296 | 4379 | /* cast ? */ |
| 4297 | 4380 | if (parse_btype(&t, &ad)) { |
| 4298 | − ft = type_decl(&n, t, TYPE_ABSTRACT); | |
| 4381 | + ft = type_decl(&ad, &n, t, TYPE_ABSTRACT); | |
| 4299 | 4382 | skip(')'); |
| 4300 | 4383 | /* check ISOC99 compound literal */ |
| 4301 | 4384 | if (tok == '{') { |
| @@ -4353,7 +4436,7 @@ void unary(void) · 51 unmodified lines | ||
| 4353 | 4436 | if (tok == '(') { |
| 4354 | 4437 | next(); |
| 4355 | 4438 | if (parse_btype(&t, &ad)) { |
| 4356 | − t = type_decl(&n, t, TYPE_ABSTRACT); | |
| 4439 | + t = type_decl(&ad, &n, t, TYPE_ABSTRACT); | |
| 4357 | 4440 | } else { |
| 4358 | 4441 | /* XXX: some code could be generated: add eval |
| 4359 | 4442 | flag */ |
| @@ -4457,7 +4540,7 @@ void unary(void) · 97 unmodified lines | ||
| 4457 | 4540 | /* get return type */ |
| 4458 | 4541 | s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT); |
| 4459 | 4542 | save_regs(); /* save used temporary registers */ |
| 4460 | − gfunc_start(&gf); | |
| 4543 | + gfunc_start(&gf, s->r); | |
| 4461 | 4544 | next(); |
| 4462 | 4545 | sa = s->next; /* first parameter */ |
| 4463 | 4546 | #ifdef INVERT_FUNC_PARAMS |
| @@ -4682,7 +4765,7 @@ void expr_eq(void) · 218 unmodified lines | ||
| 4682 | 4765 | if (is_float(vtop->t)) |
| 4683 | 4766 | rc = RC_FLOAT; |
| 4684 | 4767 | r1 = gv(rc); |
| 4685 | − vpop(); | |
| 4768 | + vtop--; /* no vpop so that FP stack is not flushed */ | |
| 4686 | 4769 | skip(':'); |
| 4687 | 4770 | u = gjmp(0); |
| 4688 | 4771 | |
| @@ -5143,7 +5226,7 @@ void init_putz(int t, int r, int c, int size) · 454 unmodified lines | ||
| 5143 | 5226 | if ((r & VT_VALMASK) == VT_CONST) { |
| 5144 | 5227 | /* nothing to do because globals are already set to zero */ |
| 5145 | 5228 | } else { |
| 5146 | − gfunc_start(&gf); | |
| 5229 | + gfunc_start(&gf, FUNC_CDECL); | |
| 5147 | 5230 | vpushi(size); |
| 5148 | 5231 | gfunc_param(&gf); |
| 5149 | 5232 | vpushi(0); |
| @@ -5472,11 +5555,7 @@ void decl(int l) · 322 unmodified lines | ||
| 5472 | 5555 | continue; |
| 5473 | 5556 | } |
| 5474 | 5557 | while (1) { /* iterate thru each declaration */ |
| 5475 | − t = type_decl(&v, b, TYPE_DIRECT); | |
| 5476 | − /* currently, we do not parse attribute in | |
| 5477 | − type_decl(). May change if needed */ | |
| 5478 | − if (tok == TOK___ATTRIBUTE__) | |
| 5479 | − parse_attribute(&ad); | |
| 5558 | + t = type_decl(&ad, &v, b, TYPE_DIRECT); | |
| 5480 | 5559 | #if 0 |
| 5481 | 5560 | { |
| 5482 | 5561 | char buf[500]; |
| @@ -6204,7 +6283,7 @@ int main(int argc, char **argv) · 721 unmodified lines | ||
| 6204 | 6283 | |
| 6205 | 6284 | /* add all tokens */ |
| 6206 | 6285 | tok_ident = TOK_IDENT; |
| 6207 | − p = "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0sizeof\0__attribute__\0define\0include\0ifdef\0ifndef\0elif\0endif\0defined\0undef\0error\0line\0__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0__func__\0main\0section\0__section__\0aligned\0__aligned__\0unused\0__unused__\0"; | |
| 6286 | + p = tcc_keywords; | |
| 6208 | 6287 | while (*p) { |
| 6209 | 6288 | r = p; |
| 6210 | 6289 | while (*r++); |
| @@ -6252,6 +6331,8 @@ int main(int argc, char **argv) · 41 unmodified lines | ||
| 6252 | 6331 | if (optind >= argc) |
| 6253 | 6332 | goto show_help; |
| 6254 | 6333 | tcc_compile_file(argv[optind++]); |
| 6334 | + } else if (!strcmp(r + 1, "bench")) { | |
| 6335 | + do_bench = 1; | |
| 6255 | 6336 | } else if (r[1] == 'b') { |
| 6256 | 6337 | if (!do_bounds_check) { |
| 6257 | 6338 | do_bounds_check = 1; |
| @@ -6300,6 +6381,11 @@ int main(int argc, char **argv) · 42 unmodified lines | ||
| 6300 | 6381 | |
| 6301 | 6382 | tcc_compile_file(argv[optind]); |
| 6302 | 6383 | |
| 6384 | + if (do_bench) { | |
| 6385 | + printf("total: %d idents, %d lines, %d bytes\n", | |
| 6386 | + tok_ident - TOK_IDENT, total_lines, total_bytes); | |
| 6387 | + } | |
| 6388 | + | |
| 6303 | 6389 | resolve_extern_syms(); |
| 6304 | 6390 | |
| 6305 | 6391 | if (outfile) { |