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