History

added alignof and typeof - better sizeof support - fixed get_tok_str() for TOK_PPNUM

bellard committed 24 years ago

Commit 43f30311 parent c0180c41 file · +227 −163Browse files

Unified · Split

tcc.c+227−163
@@ -270,6 +270,7 @@ int rsym, anon_sym, · 269 unmodified lines
270270 prog, ind, loc;
271271 /* expression generation modifiers */
272272 int const_wanted; /* true if constant wanted */
273+int nocode_wanted; /* true if no code generation wanted for an expression */
273274 int global_expr; /* true if compound literals must be allocated
274275 globally (used during initializers parsing */
275276 int func_vt, func_vc; /* current function return type (used by
@@ -490,83 +491,20 @@ static char tok_two_chars[] = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224< · 214 unmodified lines
490491 #define TOK_IDENT 256
491492
492493 enum {
493− TOK_INT = TOK_IDENT,
494− TOK_VOID,
495− TOK_CHAR,
496− TOK_IF,
497− TOK_ELSE,
498− TOK_WHILE,
499− TOK_BREAK,
500− TOK_RETURN,
501− TOK_FOR,
502− TOK_EXTERN,
503− TOK_STATIC,
504− TOK_UNSIGNED,
505− TOK_GOTO,
506− TOK_DO,
507− TOK_CONTINUE,
508− TOK_SWITCH,
509− TOK_CASE,
510−
511− /* ignored types Must have contiguous values */
512− TOK_CONST,
513− TOK_VOLATILE,
514− TOK_LONG,
515− TOK_REGISTER,
516− TOK_SIGNED,
517− TOK___SIGNED__, /* gcc keyword */
518− TOK_AUTO,
519− TOK_INLINE,
520− TOK___INLINE__, /* gcc keyword */
521− TOK_RESTRICT,
522−
523− /* unsupported type */
524− TOK_FLOAT,
525− TOK_DOUBLE,
526− TOK_BOOL,
527−
528− TOK_SHORT,
529− TOK_STRUCT,
530− TOK_UNION,
531− TOK_TYPEDEF,
532− TOK_DEFAULT,
533− TOK_ENUM,
534− TOK_SIZEOF,
535− TOK___ATTRIBUTE__,
536−
537− /* preprocessor only */
538− TOK_UIDENT, /* first "user" ident (not keyword) */
539− TOK_DEFINE = TOK_UIDENT,
540− TOK_INCLUDE,
541− TOK_IFDEF,
542− TOK_IFNDEF,
543− TOK_ELIF,
544− TOK_ENDIF,
545− TOK_DEFINED,
546− TOK_UNDEF,
547− TOK_ERROR,
548− TOK_LINE,
549−
494+ TOK_LAST = TOK_IDENT - 1,
550495 #define DEF(id, str) id,
551496 #include "tcctok.h"
552497 #undef DEF
553498 };
554499
555−char *tcc_keywords =
556−"int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0"
557−"unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0"
558−"register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0"
559−"float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0"
560−"sizeof\0__attribute__\0"
561−/* the following are not keywords. They are included to ease parsing */
562−"define\0include\0ifdef\0ifndef\0elif\0endif\0"
563−"defined\0undef\0error\0line\0"
564−/* builtin functions */
500+static const char *tcc_keywords =
565501 #define DEF(id, str) str "\0"
566502 #include "tcctok.h"
567503 #undef DEF
568504 ;
569505
506+#define TOK_UIDENT TOK_DEFINE
507+
570508 #ifdef WIN32
571509 #define snprintf _snprintf
572510 #endif
@@ -590,13 +528,16 @@ extern long double strtold (const char *__nptr, char **__endptr); · 17 unmodified lines
590528 static char *pstrcpy(char *buf, int buf_size, const char *s);
591529 static char *pstrcat(char *buf, int buf_size, const char *s);
592530
593−void sum(int l);
594−void next(void);
595−void next_nomacro(void);
531+static void sum(int l);
532+static void next(void);
533+static void next_nomacro(void);
534+static int parse_expr_type(void);
535+static int expr_type(void);
536+static int unary_type(void);
596537 static int expr_const(void);
597−void expr_eq(void);
598−void gexpr(void);
599−void decl(int l);
538+static void expr_eq(void);
539+static void gexpr(void);
540+static void decl(int l);
600541 static void decl_initializer(int t, Section *sec, unsigned long c,
601542 int first, int size_only);
602543 static void decl_initializer_alloc(int t, AttributeDef *ad, int r,
@@ -1301,12 +1242,12 @@ char *get_tok_str(int v, CValue *cv) · 698 unmodified lines
13011242 switch(v) {
13021243 case TOK_CINT:
13031244 case TOK_CUINT:
1304− /* XXX: not quite exact, but useful for ## in macros */
1245+ /* XXX: not quite exact, but only useful for testing */
13051246 sprintf(p, "%u", cv->ui);
13061247 break;
13071248 case TOK_CLLONG:
13081249 case TOK_CULLONG:
1309− /* XXX: not quite exact, but useful for ## in macros */
1250+ /* XXX: not quite exact, but only useful for testing */
13101251 sprintf(p, "%Lu", cv->ull);
13111252 break;
13121253 case TOK_CCHAR:
@@ -1321,6 +1262,7 @@ char *get_tok_str(int v, CValue *cv) · 8 unmodified lines
13211262 len = cstr->size - 1;
13221263 for(i=0;i<len;i++)
13231264 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1265+ cstr_ccat(&cstr_buf, '\0');
13241266 break;
13251267 case TOK_STR:
13261268 case TOK_LSTR:
@@ -2754,7 +2696,7 @@ static inline void next_nomacro1(void) · 1427 unmodified lines
27542696
27552697 /* return next token without macro substitution. Can read input from
27562698 macro_ptr buffer */
2757−void next_nomacro()
2699+static void next_nomacro(void)
27582700 {
27592701 if (macro_ptr) {
27602702 redo:
@@ -2772,7 +2714,7 @@ void next_nomacro() · 11 unmodified lines
27722714 }
27732715
27742716 /* substitute args in macro_str and return allocated string */
2775−int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
2717+static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
27762718 {
27772719 int *st, last_tok, t, notfirst;
27782720 Sym *s;
@@ -2894,7 +2836,7 @@ static int *macro_twosharps(void) · 115 unmodified lines
28942836 p2 = get_tok_str(t, &cval);
28952837 cstr_cat(&cstr, p2);
28962838 cstr_ccat(&cstr, '\0');
2897−
2839+
28982840 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
28992841 (t >= TOK_IDENT || t == TOK_PPNUM)) {
29002842 if (tok == TOK_PPNUM) {
@@ -3130,7 +3072,7 @@ static void macro_subst(TokenString *tok_str, · 229 unmodified lines
31303072 }
31313073
31323074 /* return next token with macro substitution */
3133−void next(void)
3075+static void next(void)
31343076 {
31353077 Sym *nested_list, *s;
31363078 TokenString str;
@@ -3670,7 +3612,7 @@ void vpop(void) · 533 unmodified lines
36703612 v = vtop->r & VT_VALMASK;
36713613 #ifdef TCC_TARGET_I386
36723614 /* for x86, we need to pop the FP stack */
3673− if (v == REG_ST0) {
3615+ if (v == REG_ST0 && !nocode_wanted) {
36743616 o(0xd9dd); /* fstp %st(1) */
36753617 } else
36763618 #endif
@@ -4045,8 +3987,12 @@ void gen_opic(int op) · 368 unmodified lines
40453987 vtop->c.i += fc;
40463988 } else {
40473989 general_case:
4048− /* call low level op generator */
4049− gen_opi(op);
3990+ if (!nocode_wanted) {
3991+ /* call low level op generator */
3992+ gen_opi(op);
3993+ } else {
3994+ vtop--;
3995+ }
40503996 }
40513997 }
40523998 }
@@ -4107,7 +4053,11 @@ void gen_opif(int op) · 54 unmodified lines
41074053 vtop--;
41084054 } else {
41094055 general_case:
4110− gen_opf(op);
4056+ if (!nocode_wanted) {
4057+ gen_opf(op);
4058+ } else {
4059+ vtop--;
4060+ }
41114061 }
41124062 }
41134063
@@ -4355,7 +4305,7 @@ void gen_cast(int t) · 241 unmodified lines
43554305 dbt = t & (VT_BTYPE | VT_UNSIGNED);
43564306 sbt = vtop->t & (VT_BTYPE | VT_UNSIGNED);
43574307
4358− if (sbt != dbt) {
4308+ if (sbt != dbt && !nocode_wanted) {
43594309 sf = is_float(sbt);
43604310 df = is_float(dbt);
43614311 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
@@ -4749,25 +4699,30 @@ void vstore(void) · 387 unmodified lines
47494699 /* if structure, only generate pointer */
47504700 /* structure assignment : generate memcpy */
47514701 /* XXX: optimize if small size */
4752− vdup();
4753− gfunc_start(&gf, FUNC_CDECL);
4754− /* type size */
4755− size = type_size(vtop->t, &align);
4756− vpushi(size);
4757− gfunc_param(&gf);
4758− /* source */
4759− vtop->t = VT_INT;
4760− gaddrof();
4761− gfunc_param(&gf);
4762− /* destination */
4763− vswap();
4764− vtop->t = VT_INT;
4765− gaddrof();
4766− gfunc_param(&gf);
4767−
4768− save_regs(0);
4769− vpush_global_sym(func_old_type, TOK_memcpy);
4770− gfunc_call(&gf);
4702+ if (!nocode_wanted) {
4703+ vdup();
4704+ gfunc_start(&gf, FUNC_CDECL);
4705+ /* type size */
4706+ size = type_size(vtop->t, &align);
4707+ vpushi(size);
4708+ gfunc_param(&gf);
4709+ /* source */
4710+ vtop->t = VT_INT;
4711+ gaddrof();
4712+ gfunc_param(&gf);
4713+ /* destination */
4714+ vswap();
4715+ vtop->t = VT_INT;
4716+ gaddrof();
4717+ gfunc_param(&gf);
4718+
4719+ save_regs(0);
4720+ vpush_global_sym(func_old_type, TOK_memcpy);
4721+ gfunc_call(&gf);
4722+ } else {
4723+ vswap();
4724+ vpop();
4725+ }
47714726 /* leave source on stack */
47724727 } else if (ft & VT_BITFIELD) {
47734728 /* bitfield store handling */
@@ -4801,33 +4756,35 @@ void vstore(void) · 27 unmodified lines
48014756 vswap();
48024757 }
48034758 #endif
4804− rc = RC_INT;
4805− if (is_float(ft))
4806− rc = RC_FLOAT;
4807− r = gv(rc); /* generate value */
4808− /* if lvalue was saved on stack, must read it */
4809− if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
4810− SValue sv;
4811− t = get_reg(RC_INT);
4812− sv.t = VT_INT;
4813− sv.r = VT_LOCAL | VT_LVAL;
4814− sv.c.ul = vtop[-1].c.ul;
4815− load(t, &sv);
4816− vtop[-1].r = t | VT_LVAL;
4817− }
4818− store(r, vtop - 1);
4819− /* two word case handling : store second register at word + 4 */
4820− if ((ft & VT_BTYPE) == VT_LLONG) {
4821− vswap();
4822− /* convert to int to increment easily */
4823− vtop->t = VT_INT;
4824− gaddrof();
4825− vpushi(4);
4826− gen_op('+');
4827− vtop->r |= VT_LVAL;
4828− vswap();
4829− /* XXX: it works because r2 is spilled last ! */
4830− store(vtop->r2, vtop - 1);
4759+ if (!nocode_wanted) {
4760+ rc = RC_INT;
4761+ if (is_float(ft))
4762+ rc = RC_FLOAT;
4763+ r = gv(rc); /* generate value */
4764+ /* if lvalue was saved on stack, must read it */
4765+ if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
4766+ SValue sv;
4767+ t = get_reg(RC_INT);
4768+ sv.t = VT_INT;
4769+ sv.r = VT_LOCAL | VT_LVAL;
4770+ sv.c.ul = vtop[-1].c.ul;
4771+ load(t, &sv);
4772+ vtop[-1].r = t | VT_LVAL;
4773+ }
4774+ store(r, vtop - 1);
4775+ /* two word case handling : store second register at word + 4 */
4776+ if ((ft & VT_BTYPE) == VT_LLONG) {
4777+ vswap();
4778+ /* convert to int to increment easily */
4779+ vtop->t = VT_INT;
4780+ gaddrof();
4781+ vpushi(4);
4782+ gen_op('+');
4783+ vtop->r |= VT_LVAL;
4784+ vswap();
4785+ /* XXX: it works because r2 is spilled last ! */
4786+ store(vtop->r2, vtop - 1);
4787+ }
48314788 }
48324789 vswap();
48334790 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
@@ -5188,6 +5145,11 @@ int parse_btype(int *type_ptr, AttributeDef *ad) · 354 unmodified lines
51885145 case TOK___ATTRIBUTE__:
51895146 parse_attribute(ad);
51905147 break;
5148+ /* GNUC typeof */
5149+ case TOK_TYPEOF:
5150+ next();
5151+ u = parse_expr_type();
5152+ goto basic_type1;
51915153 default:
51925154 s = sym_find(tok);
51935155 if (!s || !(s->t & VT_TYPEDEF))
@@ -5367,7 +5329,7 @@ static void indir(void) · 173 unmodified lines
53675329 {
53685330 if ((vtop->t & VT_BTYPE) != VT_PTR)
53695331 expect("pointer");
5370− if (vtop->r & VT_LVAL)
5332+ if ((vtop->r & VT_LVAL) && !nocode_wanted)
53715333 gv(RC_INT);
53725334 vtop->t = pointed_type(vtop->t);
53735335 /* an array is never an lvalue */
@@ -5394,10 +5356,31 @@ void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg) · 20 unmodified lines
53945356 } else {
53955357 gen_assign_cast(arg->t);
53965358 }
5397− gfunc_param(gf);
5359+ if (!nocode_wanted) {
5360+ gfunc_param(gf);
5361+ } else {
5362+ vpop();
5363+ }
5364+}
5365+
5366+/* parse an expression of the form '(type)' or '(expr)' and return its
5367+ type */
5368+static int parse_expr_type(void)
5369+{
5370+ int ft, n;
5371+ AttributeDef ad;
5372+
5373+ skip('(');
5374+ if (parse_btype(&ft, &ad)) {
5375+ ft = type_decl(&ad, &n, ft, TYPE_ABSTRACT);
5376+ } else {
5377+ ft = expr_type();
5378+ }
5379+ skip(')');
5380+ return ft;
53985381 }
53995382
5400−void unary(void)
5383+static void unary(void)
54015384 {
54025385 int n, t, ft, align, size, r;
54035386 Sym *s;
@@ -5515,25 +5498,17 @@ void unary(void) · 111 unmodified lines
55155498 vpushi(0);
55165499 gen_op('+');
55175500 } else
5518− if (t == TOK_SIZEOF) {
5501+ if (t == TOK_SIZEOF || t == TOK_ALIGNOF) {
55195502 if (tok == '(') {
5520− next();
5521− if (parse_btype(&t, &ad)) {
5522− t = type_decl(&ad, &n, t, TYPE_ABSTRACT);
5523− } else {
5524− /* XXX: some code could be generated: add eval
5525− flag */
5526− gexpr();
5527− t = vtop->t;
5528− vpop();
5529− }
5530− skip(')');
5503+ ft = parse_expr_type();
55315504 } else {
5532− unary();
5533− t = vtop->t;
5534− vpop();
5505+ ft = unary_type();
55355506 }
5536− vpushi(type_size(t, &t));
5507+ size = type_size(ft, &align);
5508+ if (t == TOK_SIZEOF)
5509+ vpushi(size);
5510+ else
5511+ vpushi(align);
55375512 } else
55385513 if (t == TOK_INC || t == TOK_DEC) {
55395514 unary();
@@ -5627,8 +5602,10 @@ void unary(void) · 87 unmodified lines
56275602 }
56285603 /* get return type */
56295604 s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
5630− save_regs(0); /* save used temporary registers */
5631− gfunc_start(&gf, s->r);
5605+ if (!nocode_wanted) {
5606+ save_regs(0); /* save used temporary registers */
5607+ gfunc_start(&gf, s->r);
5608+ }
56325609 next();
56335610 sa = s->next; /* first parameter */
56345611 #ifdef INVERT_FUNC_PARAMS
@@ -5693,7 +5670,10 @@ void unary(void) · 58 unmodified lines
56935670 problems */
56945671 vset(VT_INT, VT_LOCAL, loc);
56955672 ret.c = vtop->c;
5696− gfunc_param(&gf);
5673+ if (!nocode_wanted)
5674+ gfunc_param(&gf);
5675+ else
5676+ vtop--;
56975677 } else {
56985678 ret.t = s->t;
56995679 ret.r2 = VT_CONST;
@@ -5723,7 +5703,10 @@ void unary(void) · 23 unmodified lines
57235703 if (sa)
57245704 error("too few arguments to function");
57255705 skip(')');
5726− gfunc_call(&gf);
5706+ if (!nocode_wanted)
5707+ gfunc_call(&gf);
5708+ else
5709+ vtop--;
57275710 /* return value */
57285711 vsetc(ret.t, ret.r, &ret.c);
57295712 vtop->r2 = ret.r2;
@@ -5733,7 +5716,7 @@ void unary(void) · 3 unmodified lines
57335716 }
57345717 }
57355718
5736−void uneq(void)
5719+static void uneq(void)
57375720 {
57385721 int t;
57395722
@@ -5756,7 +5739,7 @@ void uneq(void) · 16 unmodified lines
57565739 }
57575740 }
57585741
5759−void sum(int l)
5742+static void sum(int l)
57605743 {
57615744 int t;
57625745
@@ -5784,7 +5767,7 @@ void sum(int l) · 21 unmodified lines
57845767 }
57855768
57865769 /* only used if non constant */
5787−void eand(void)
5770+static void eand(void)
57885771 {
57895772 int t;
57905773
@@ -5804,7 +5787,7 @@ void eand(void) · 13 unmodified lines
58045787 }
58055788 }
58065789
5807−void eor(void)
5790+static void eor(void)
58085791 {
58095792 int t;
58105793
@@ -5825,7 +5808,7 @@ void eor(void) · 14 unmodified lines
58255808 }
58265809
58275810 /* XXX: better constant handling */
5828−void expr_eq(void)
5811+static void expr_eq(void)
58295812 {
58305813 int tt, u, r1, r2, rc, t1, t2, t, bt1, bt2;
58315814 SValue sv;
@@ -5925,7 +5908,7 @@ void expr_eq(void) · 93 unmodified lines
59255908 }
59265909 }
59275910
5928−void gexpr(void)
5911+static void gexpr(void)
59295912 {
59305913 while (1) {
59315914 expr_eq();
@@ -5936,6 +5919,35 @@ void gexpr(void) · 4 unmodified lines
59365919 }
59375920 }
59385921
5922+/* parse an expression and return its type without any side effect. */
5923+static int expr_type(void)
5924+{
5925+ int a, t;
5926+
5927+ a = nocode_wanted;
5928+ nocode_wanted = 1;
5929+ gexpr();
5930+ t = vtop->t;
5931+ vpop();
5932+ nocode_wanted = a;
5933+ return t;
5934+}
5935+
5936+/* parse a unary expression and return its type without any side
5937+ effect. */
5938+static int unary_type(void)
5939+{
5940+ int a, t;
5941+
5942+ a = nocode_wanted;
5943+ nocode_wanted = 1;
5944+ unary();
5945+ t = vtop->t;
5946+ vpop();
5947+ nocode_wanted = a;
5948+ return t;
5949+}
5950+
59395951 /* parse a constant expression and return value in vtop. */
59405952 static void expr_const1(void)
59415953 {
@@ -5960,7 +5972,7 @@ static int expr_const(void) · 18 unmodified lines
59605972
59615973 /* return the label token if current token is a label, otherwise
59625974 return zero */
5963−int is_label(void)
5975+static int is_label(void)
59645976 {
59655977 int t;
59665978 CValue c;
@@ -5985,7 +5997,7 @@ int is_label(void) · 18 unmodified lines
59855997 }
59865998 }
59875999
5988−void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
6000+static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
59896001 {
59906002 int a, b, c, d;
59916003 Sym *s;
@@ -6819,8 +6831,52 @@ void analyse_function(void) · 827 unmodified lines
68196831 }
68206832 #endif
68216833
6834+/* parse an old style function declaration list */
6835+/* XXX: check multiple parameter */
6836+static void func_decl_list(Sym *func_sym)
6837+{
6838+ AttributeDef ad;
6839+ int b, v, t;
6840+ Sym *s;
6841+ /* parse each declaration */
6842+ while (tok != '{' && tok != ';' && tok != TOK_EOF) {
6843+ if (!parse_btype(&b, &ad))
6844+ expect("declaration list");
6845+ if (((b & VT_BTYPE) == VT_ENUM ||
6846+ (b & VT_BTYPE) == VT_STRUCT) &&
6847+ tok == ';') {
6848+ /* we accept no variable after */
6849+ } else {
6850+ for(;;) {
6851+ t = type_decl(&ad, &v, b, TYPE_DIRECT);
6852+ /* find parameter in function parameter list */
6853+ s = func_sym->next;
6854+ while (s != NULL) {
6855+ if ((s->v & ~SYM_FIELD) == v)
6856+ goto found;
6857+ s = s->next;
6858+ }
6859+ error("declaration for parameter '%s' but no such parameter",
6860+ get_tok_str(v, NULL));
6861+ found:
6862+ /* check that no storage specifier except 'register' was given */
6863+ if (t & (VT_EXTERN | VT_STATIC | VT_TYPEDEF))
6864+ error("storage class specified for '%s'", get_tok_str(v, NULL));
6865+ /* we can add the type (NOTE: it could be local to the function) */
6866+ s->t = t;
6867+ /* accept other parameters */
6868+ if (tok == ',')
6869+ next();
6870+ else
6871+ break;
6872+ }
6873+ }
6874+ skip(';');
6875+ }
6876+}
6877+
68226878 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
6823−void decl(int l)
6879+static void decl(int l)
68246880 {
68256881 int t, b, v, has_init, r;
68266882 Sym *sym;
@@ -6856,6 +6912,14 @@ void decl(int l) · 29 unmodified lines
68566912 printf("type = '%s'\n", buf);
68576913 }
68586914 #endif
6915+ if ((t & VT_BTYPE) == VT_FUNC) {
6916+ /* if old style function prototype, we accept a
6917+ declaration list */
6918+ sym = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
6919+ if (sym->c == FUNC_OLD)
6920+ func_decl_list(sym);
6921+ }
6922+
68596923 if (tok == '{') {
68606924 #ifdef CONFIG_REG_VARS
68616925 TokenString func_str;
@@ -7392,7 +7456,7 @@ int tcc_run(TCCState *s1, int argc, char **argv) · 530 unmodified lines
73927456
73937457 TCCState *tcc_new(void)
73947458 {
7395− char *p, *r;
7459+ const char *p, *r;
73967460 TCCState *s;
73977461
73987462 s = tcc_mallocz(sizeof(TCCState));