History

increased hash table sizes - added cdecl and stdcall attributes - #elif fix - empty args in macro fix - benchmark option

bellard committed 24 years ago

Commit 6e2d1a81 parent d2c91571 file · +132 −46Browse files

Unified · Split

tcc.c+132−46
@@ -52,9 +52,9 @@ · 51 unmodified lines
5252 #define STRING_MAX_SIZE 1024
5353 #define INCLUDE_PATHS_MAX 32
5454
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
5858
5959 /* token symbol management */
6060 typedef struct TokenSym {
@@ -131,16 +131,22 @@ typedef struct Section { · 70 unmodified lines
131131 typedef struct AttributeDef {
132132 int aligned;
133133 Section *section;
134+ unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
134135 } AttributeDef;
135136
136137 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
137138 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
138139 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
139140
141+/* stored in 'Sym.c' field */
140142 #define FUNC_NEW 1 /* ansi function prototype */
141143 #define FUNC_OLD 2 /* old function prototype */
142144 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
143145
146+/* stored in 'Sym.r' field */
147+#define FUNC_CDECL 0 /* standard c call */
148+#define FUNC_STDCALL 1 /* pascal c call */
149+
144150 /* field 'Sym.t' for macros */
145151 #define MACRO_OBJ 0 /* object like macro */
146152 #define MACRO_FUNC 1 /* function like macro */
@@ -215,6 +221,11 @@ int do_debug = 0; · 68 unmodified lines
215221 /* compile with built-in memory and bounds checker */
216222 int do_bounds_check = 0;
217223
224+/* display benchmark infos */
225+int do_bench = 0;
226+int total_lines;
227+int total_bytes;
228+
218229 /* use GNU C extensions */
219230 int gnu_ext = 1;
220231
@@ -405,8 +416,33 @@ enum { · 184 unmodified lines
405416 TOK___ALIGNED__,
406417 TOK_UNUSED,
407418 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__,
408427 };
409428
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+
410446 #ifdef WIN32
411447 #define snprintf _snprintf
412448 /* currently incorrect */
@@ -459,7 +495,7 @@ int pointed_type(int t); · 46 unmodified lines
459495 int pointed_size(int t);
460496 int is_compatible_types(int t1, int t2);
461497 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);
463499
464500 void error(const char *fmt, ...);
465501 void rt_error(unsigned long pc, const char *fmt, ...);
@@ -800,7 +836,7 @@ TokenSym *tok_alloc(const char *str, int len) · 334 unmodified lines
800836 len = strlen(str);
801837 h = 1;
802838 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);
804840
805841 pts = &hash_ident[h];
806842 while (1) {
@@ -1034,11 +1070,13 @@ BufferedFile *tcc_open(const char *filename) · 227 unmodified lines
10341070 bf->buffer[0] = CH_EOB; /* put eob symbol */
10351071 pstrcpy(bf->filename, sizeof(bf->filename), filename);
10361072 bf->line_num = 1;
1073+ // printf("opening '%s'\n", filename);
10371074 return bf;
10381075 }
10391076
10401077 void tcc_close(BufferedFile *bf)
10411078 {
1079+ total_lines += bf->line_num;
10421080 close(bf->fd);
10431081 free(bf);
10441082 }
@@ -1059,6 +1097,7 @@ int tcc_getc_slow(BufferedFile *bf) · 14 unmodified lines
10591097 } else {
10601098 len = 0;
10611099 }
1100+ total_bytes += len;
10621101 bf->buf_ptr = bf->buffer;
10631102 bf->buf_end = bf->buffer + len;
10641103 *bf->buf_end = CH_EOB;
@@ -1290,7 +1329,7 @@ int expr_preprocess(void) · 225 unmodified lines
12901329 return c != 0;
12911330 }
12921331
1293−#if defined(DEBUG)
1332+#if defined(DEBUG) || defined(PP_DEBUG)
12941333 void tok_print(int *str)
12951334 {
12961335 int t;
@@ -1454,25 +1493,32 @@ void preprocess(void) · 157 unmodified lines
14541493 *ifdef_stack_ptr++ = c;
14551494 goto test_skip;
14561495 } 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)
14591499 error("#else after #else");
14601500 c = (ifdef_stack_ptr[-1] ^= 3);
14611501 goto test_skip;
14621502 } 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)
14651507 error("#elif after #else");
1508+ /* last #if/#elif expression was true: we skip */
1509+ if (c == 1)
1510+ goto skip;
14661511 c = expr_preprocess();
14671512 ifdef_stack_ptr[-1] = c;
14681513 test_skip:
14691514 if (!(c & 1)) {
1515+ skip:
14701516 preprocess_skip();
14711517 goto redo;
14721518 }
14731519 } else if (tok == TOK_ENDIF) {
14741520 if (ifdef_stack_ptr == ifdef_stack)
1475− expect("#if");
1521+ error("#endif without matching #if");
14761522 ifdef_stack_ptr--;
14771523 } else if (tok == TOK_LINE) {
14781524 next();
@@ -1876,7 +1922,7 @@ void next_nomacro1(void) · 397 unmodified lines
18761922 while(1) {
18771923 while (ch == '\n') {
18781924 cinp();
1879− while (ch == ' ' || ch == 9)
1925+ while (ch == ' ' || ch == '\t')
18801926 cinp();
18811927 if (ch == '#') {
18821928 /* preprocessor command if # at start of line after
@@ -2157,7 +2203,14 @@ void macro_subst(int **tok_str, int *tok_len, · 274 unmodified lines
21572203 next_nomacro();
21582204 args = NULL;
21592205 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));
21612214 len = 0;
21622215 str = NULL;
21632216 parlevel = 0;
@@ -2175,13 +2228,17 @@ void macro_subst(int **tok_str, int *tok_len, · 11 unmodified lines
21752228 }
21762229 tok_add(&str, &len, 0);
21772230 sym_push2(&args, sa->v & ~SYM_FIELD, 0, (int)str);
2178− if (tok != ',')
2231+ if (tok == ')')
21792232 break;
2233+ if (tok != ',')
2234+ expect(",");
21802235 next_nomacro();
21812236 sa = sa->next;
21822237 }
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+
21852242 /* now subst each arg */
21862243 mstr = macro_arg_subst(nested_list, mstr, args);
21872244 /* free memory */
@@ -2232,7 +2289,7 @@ void next(void) · 44 unmodified lines
22322289 } else {
22332290 redo:
22342291 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 */
22362293 len = 0;
22372294 ptr = NULL;
22382295 nested_list = NULL;
@@ -2338,7 +2395,8 @@ void save_reg(int r) · 99 unmodified lines
23382395 if (!saved) {
23392396 /* store register in the stack */
23402397 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))
23422400 t = VT_INT;
23432401 size = type_size(t, &align);
23442402 loc = (loc - size) & -align;
@@ -2690,7 +2748,7 @@ void gen_opl(int op) · 345 unmodified lines
26902748 func = __modull;
26912749 gen_func:
26922750 /* call generic long long function */
2693− gfunc_start(&gf);
2751+ gfunc_start(&gf, FUNC_CDECL);
26942752 gfunc_param(&gf);
26952753 gfunc_param(&gf);
26962754 vpushi((int)func);
@@ -3139,7 +3197,7 @@ void gen_cvt_itof1(int t) · 442 unmodified lines
31393197 if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
31403198 (VT_LLONG | VT_UNSIGNED)) {
31413199
3142− gfunc_start(&gf);
3200+ gfunc_start(&gf, FUNC_CDECL);
31433201 gfunc_param(&gf);
31443202 if (t == VT_FLOAT)
31453203 vpushi((int)&__ulltof);
@@ -3163,7 +3221,7 @@ void gen_cvt_ftoi1(int t) · 17 unmodified lines
31633221
31643222 if (t == (VT_LLONG | VT_UNSIGNED)) {
31653223 /* not handled natively */
3166− gfunc_start(&gf);
3224+ gfunc_start(&gf, FUNC_CDECL);
31673225 st = vtop->t & VT_BTYPE;
31683226 gfunc_param(&gf);
31693227 if (st == VT_FLOAT)
@@ -3346,6 +3404,8 @@ void gen_cast(int t) · 176 unmodified lines
33463404 /* from long long: just take low order word */
33473405 lexpand();
33483406 vpop();
3407+ } else if (sbt == VT_PTR) {
3408+ /* ok to cast */
33493409 } else if (vtop->r & VT_LVAL) {
33503410 /* if lvalue and single word type, nothing to do (XXX:
33513411 maybe incorrect for sizeof op) */
@@ -3616,7 +3676,7 @@ void vstore(void) · 264 unmodified lines
36163676 /* XXX: optimize if small size */
36173677
36183678 vdup();
3619− gfunc_start(&gf);
3679+ gfunc_start(&gf, FUNC_CDECL);
36203680 /* type size */
36213681 size = type_size(vtop->t, &align);
36223682 vpushi(size);
@@ -3759,6 +3819,21 @@ void parse_attribute(AttributeDef *ad) · 136 unmodified lines
37593819 /* currently, no need to handle it because tcc does not
37603820 track unused objects */
37613821 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;
37623837 default:
37633838 warning("'%s' attribute ignored", get_tok_str(t, NULL));
37643839 /* skip parameters */
@@ -3837,7 +3912,7 @@ int struct_decl(int u) · 72 unmodified lines
38373912 bit_size = -1;
38383913 v = 0;
38393914 if (tok != ':') {
3840− t = type_decl(&v, b, TYPE_DIRECT);
3915+ t = type_decl(&ad, &v, b, TYPE_DIRECT);
38413916 if ((t & VT_BTYPE) == VT_FUNC ||
38423917 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
38433918 error("invalid type for '%s'",
@@ -4055,11 +4130,11 @@ the_end: · 211 unmodified lines
40554130 return type_found;
40564131 }
40574132
4058−int post_type(int t)
4133+int post_type(int t, AttributeDef *ad)
40594134 {
40604135 int p, n, pt, l, t1;
40614136 Sym **plast, *s, *first;
4062− AttributeDef ad;
4137+ AttributeDef ad1;
40634138
40644139 if (tok == '(') {
40654140 /* function declaration */
@@ -4070,7 +4145,7 @@ int post_type(int t) · 4 unmodified lines
40704145 while (tok != ')') {
40714146 /* read param name and compute offset */
40724147 if (l != FUNC_OLD) {
4073− if (!parse_btype(&pt, &ad)) {
4148+ if (!parse_btype(&pt, &ad1)) {
40744149 if (l) {
40754150 error("invalid type");
40764151 } else {
@@ -4081,7 +4156,7 @@ int post_type(int t) · 4 unmodified lines
40814156 l = FUNC_NEW;
40824157 if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
40834158 break;
4084− pt = type_decl(&n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
4159+ pt = type_decl(&ad1, &n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
40854160 if ((pt & VT_BTYPE) == VT_VOID)
40864161 error("parameter declared as void");
40874162 } else {
@@ -4109,10 +4184,10 @@ int post_type(int t) · 21 unmodified lines
41094184 l = FUNC_OLD;
41104185 skip(')');
41114186 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);
41134188 /* we push a anonymous symbol which will contain the function prototype */
41144189 p = anon_sym++;
4115− s = sym_push(p, t, 0, l);
4190+ s = sym_push(p, t, ad->func_call, l);
41164191 s->next = first;
41174192 t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
41184193 } else if (tok == '[') {
@@ -4127,7 +4202,7 @@ int post_type(int t) · 8 unmodified lines
41274202 skip(']');
41284203 /* parse next post type */
41294204 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);
41314206
41324207 /* we push a anonymous symbol which will contain the array
41334208 element type */
@@ -4139,8 +4214,10 @@ int post_type(int t) · 5 unmodified lines
41394214 }
41404215
41414216 /* 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)
41444221 {
41454222 int u, p;
41464223 Sym *s;
@@ -4156,7 +4233,11 @@ int type_decl(int *v, int t, int td) · 9 unmodified lines
41564233 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
41574234 if (tok == '(') {
41584235 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);
41604241 skip(')');
41614242 } else {
41624243 u = 0;
@@ -4171,8 +4252,10 @@ int type_decl(int *v, int t, int td) · 8 unmodified lines
41714252 }
41724253 }
41734254 /* 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)
41764259 return t;
41774260 p = u;
41784261 while(1) {
@@ -4295,7 +4378,7 @@ void unary(void) · 116 unmodified lines
42954378 if (t == '(') {
42964379 /* cast ? */
42974380 if (parse_btype(&t, &ad)) {
4298− ft = type_decl(&n, t, TYPE_ABSTRACT);
4381+ ft = type_decl(&ad, &n, t, TYPE_ABSTRACT);
42994382 skip(')');
43004383 /* check ISOC99 compound literal */
43014384 if (tok == '{') {
@@ -4353,7 +4436,7 @@ void unary(void) · 51 unmodified lines
43534436 if (tok == '(') {
43544437 next();
43554438 if (parse_btype(&t, &ad)) {
4356− t = type_decl(&n, t, TYPE_ABSTRACT);
4439+ t = type_decl(&ad, &n, t, TYPE_ABSTRACT);
43574440 } else {
43584441 /* XXX: some code could be generated: add eval
43594442 flag */
@@ -4457,7 +4540,7 @@ void unary(void) · 97 unmodified lines
44574540 /* get return type */
44584541 s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
44594542 save_regs(); /* save used temporary registers */
4460− gfunc_start(&gf);
4543+ gfunc_start(&gf, s->r);
44614544 next();
44624545 sa = s->next; /* first parameter */
44634546 #ifdef INVERT_FUNC_PARAMS
@@ -4682,7 +4765,7 @@ void expr_eq(void) · 218 unmodified lines
46824765 if (is_float(vtop->t))
46834766 rc = RC_FLOAT;
46844767 r1 = gv(rc);
4685− vpop();
4768+ vtop--; /* no vpop so that FP stack is not flushed */
46864769 skip(':');
46874770 u = gjmp(0);
46884771
@@ -5143,7 +5226,7 @@ void init_putz(int t, int r, int c, int size) · 454 unmodified lines
51435226 if ((r & VT_VALMASK) == VT_CONST) {
51445227 /* nothing to do because globals are already set to zero */
51455228 } else {
5146− gfunc_start(&gf);
5229+ gfunc_start(&gf, FUNC_CDECL);
51475230 vpushi(size);
51485231 gfunc_param(&gf);
51495232 vpushi(0);
@@ -5472,11 +5555,7 @@ void decl(int l) · 322 unmodified lines
54725555 continue;
54735556 }
54745557 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);
54805559 #if 0
54815560 {
54825561 char buf[500];
@@ -6204,7 +6283,7 @@ int main(int argc, char **argv) · 721 unmodified lines
62046283
62056284 /* add all tokens */
62066285 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;
62086287 while (*p) {
62096288 r = p;
62106289 while (*r++);
@@ -6252,6 +6331,8 @@ int main(int argc, char **argv) · 41 unmodified lines
62526331 if (optind >= argc)
62536332 goto show_help;
62546333 tcc_compile_file(argv[optind++]);
6334+ } else if (!strcmp(r + 1, "bench")) {
6335+ do_bench = 1;
62556336 } else if (r[1] == 'b') {
62566337 if (!do_bounds_check) {
62576338 do_bounds_check = 1;
@@ -6300,6 +6381,11 @@ int main(int argc, char **argv) · 42 unmodified lines
63006381
63016382 tcc_compile_file(argv[optind]);
63026383
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+
63036389 resolve_extern_syms();
63046390
63056391 if (outfile) {