added alignof and typeof - better sizeof support - fixed get_tok_str() for TOK_PPNUM
This commit is contained in:
		
							parent
							
								
									c0180c4e5f
								
							
						
					
					
						commit
						43f30315f9
					
				
					 1 changed files with 227 additions and 163 deletions
				
			
		
							
								
								
									
										390
									
								
								tcc.c
									
										
									
									
									
								
							
							
						
						
									
										390
									
								
								tcc.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -270,6 +270,7 @@ int rsym, anon_sym,
 | 
			
		|||
    prog, ind, loc;
 | 
			
		||||
/* expression generation modifiers */
 | 
			
		||||
int const_wanted; /* true if constant wanted */
 | 
			
		||||
int nocode_wanted; /* true if no code generation wanted for an expression */
 | 
			
		||||
int global_expr;  /* true if compound literals must be allocated
 | 
			
		||||
                     globally (used during initializers parsing */
 | 
			
		||||
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<
 | 
			
		|||
#define TOK_IDENT 256
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    TOK_INT = TOK_IDENT,
 | 
			
		||||
    TOK_VOID,
 | 
			
		||||
    TOK_CHAR,
 | 
			
		||||
    TOK_IF,
 | 
			
		||||
    TOK_ELSE,
 | 
			
		||||
    TOK_WHILE,
 | 
			
		||||
    TOK_BREAK,
 | 
			
		||||
    TOK_RETURN,
 | 
			
		||||
    TOK_FOR,
 | 
			
		||||
    TOK_EXTERN,
 | 
			
		||||
    TOK_STATIC,
 | 
			
		||||
    TOK_UNSIGNED,
 | 
			
		||||
    TOK_GOTO,
 | 
			
		||||
    TOK_DO,
 | 
			
		||||
    TOK_CONTINUE,
 | 
			
		||||
    TOK_SWITCH,
 | 
			
		||||
    TOK_CASE,
 | 
			
		||||
 | 
			
		||||
    /* ignored types Must have contiguous values */
 | 
			
		||||
    TOK_CONST,
 | 
			
		||||
    TOK_VOLATILE,
 | 
			
		||||
    TOK_LONG,
 | 
			
		||||
    TOK_REGISTER,
 | 
			
		||||
    TOK_SIGNED,
 | 
			
		||||
    TOK___SIGNED__, /* gcc keyword */
 | 
			
		||||
    TOK_AUTO,
 | 
			
		||||
    TOK_INLINE,
 | 
			
		||||
    TOK___INLINE__, /* gcc keyword */
 | 
			
		||||
    TOK_RESTRICT,
 | 
			
		||||
 | 
			
		||||
    /* unsupported type */
 | 
			
		||||
    TOK_FLOAT,
 | 
			
		||||
    TOK_DOUBLE,
 | 
			
		||||
    TOK_BOOL,
 | 
			
		||||
 | 
			
		||||
    TOK_SHORT,
 | 
			
		||||
    TOK_STRUCT,
 | 
			
		||||
    TOK_UNION,
 | 
			
		||||
    TOK_TYPEDEF,
 | 
			
		||||
    TOK_DEFAULT,
 | 
			
		||||
    TOK_ENUM,
 | 
			
		||||
    TOK_SIZEOF,
 | 
			
		||||
    TOK___ATTRIBUTE__,
 | 
			
		||||
    
 | 
			
		||||
    /* preprocessor only */
 | 
			
		||||
    TOK_UIDENT, /* first "user" ident (not keyword) */
 | 
			
		||||
    TOK_DEFINE = TOK_UIDENT,
 | 
			
		||||
    TOK_INCLUDE,
 | 
			
		||||
    TOK_IFDEF,
 | 
			
		||||
    TOK_IFNDEF,
 | 
			
		||||
    TOK_ELIF,
 | 
			
		||||
    TOK_ENDIF,
 | 
			
		||||
    TOK_DEFINED,
 | 
			
		||||
    TOK_UNDEF,
 | 
			
		||||
    TOK_ERROR,
 | 
			
		||||
    TOK_LINE,
 | 
			
		||||
 | 
			
		||||
    TOK_LAST = TOK_IDENT - 1,
 | 
			
		||||
#define DEF(id, str) id,
 | 
			
		||||
#include "tcctok.h"
 | 
			
		||||
#undef DEF
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
char *tcc_keywords = 
 | 
			
		||||
"int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0"
 | 
			
		||||
"unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0"
 | 
			
		||||
"register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0"
 | 
			
		||||
"float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0"
 | 
			
		||||
"sizeof\0__attribute__\0"
 | 
			
		||||
/* the following are not keywords. They are included to ease parsing */
 | 
			
		||||
"define\0include\0ifdef\0ifndef\0elif\0endif\0"
 | 
			
		||||
"defined\0undef\0error\0line\0"
 | 
			
		||||
/* builtin functions */
 | 
			
		||||
static const char *tcc_keywords = 
 | 
			
		||||
#define DEF(id, str) str "\0"
 | 
			
		||||
#include "tcctok.h"
 | 
			
		||||
#undef DEF
 | 
			
		||||
;
 | 
			
		||||
 | 
			
		||||
#define TOK_UIDENT TOK_DEFINE
 | 
			
		||||
 | 
			
		||||
#ifdef WIN32
 | 
			
		||||
#define snprintf _snprintf
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -590,13 +528,16 @@ extern long double strtold (const char *__nptr, char **__endptr);
 | 
			
		|||
static char *pstrcpy(char *buf, int buf_size, const char *s);
 | 
			
		||||
static char *pstrcat(char *buf, int buf_size, const char *s);
 | 
			
		||||
 | 
			
		||||
void sum(int l);
 | 
			
		||||
void next(void);
 | 
			
		||||
void next_nomacro(void);
 | 
			
		||||
static void sum(int l);
 | 
			
		||||
static void next(void);
 | 
			
		||||
static void next_nomacro(void);
 | 
			
		||||
static int parse_expr_type(void);
 | 
			
		||||
static int expr_type(void);
 | 
			
		||||
static int unary_type(void);
 | 
			
		||||
static int expr_const(void);
 | 
			
		||||
void expr_eq(void);
 | 
			
		||||
void gexpr(void);
 | 
			
		||||
void decl(int l);
 | 
			
		||||
static void expr_eq(void);
 | 
			
		||||
static void gexpr(void);
 | 
			
		||||
static void decl(int l);
 | 
			
		||||
static void decl_initializer(int t, Section *sec, unsigned long c, 
 | 
			
		||||
                             int first, int size_only);
 | 
			
		||||
static void decl_initializer_alloc(int t, AttributeDef *ad, int r, 
 | 
			
		||||
| 
						 | 
				
			
			@ -1301,12 +1242,12 @@ char *get_tok_str(int v, CValue *cv)
 | 
			
		|||
    switch(v) {
 | 
			
		||||
    case TOK_CINT:
 | 
			
		||||
    case TOK_CUINT:
 | 
			
		||||
        /* XXX: not quite exact, but useful for ## in macros  */
 | 
			
		||||
        /* XXX: not quite exact, but only useful for testing */
 | 
			
		||||
        sprintf(p, "%u", cv->ui);
 | 
			
		||||
        break;
 | 
			
		||||
    case TOK_CLLONG:
 | 
			
		||||
    case TOK_CULLONG:
 | 
			
		||||
        /* XXX: not quite exact, but useful for ## in macros  */
 | 
			
		||||
        /* XXX: not quite exact, but only useful for testing  */
 | 
			
		||||
        sprintf(p, "%Lu", cv->ull);
 | 
			
		||||
        break;
 | 
			
		||||
    case TOK_CCHAR:
 | 
			
		||||
| 
						 | 
				
			
			@ -1321,6 +1262,7 @@ char *get_tok_str(int v, CValue *cv)
 | 
			
		|||
        len = cstr->size - 1;
 | 
			
		||||
        for(i=0;i<len;i++)
 | 
			
		||||
            add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
 | 
			
		||||
        cstr_ccat(&cstr_buf, '\0');
 | 
			
		||||
        break;
 | 
			
		||||
    case TOK_STR:
 | 
			
		||||
    case TOK_LSTR:
 | 
			
		||||
| 
						 | 
				
			
			@ -2754,7 +2696,7 @@ static inline void next_nomacro1(void)
 | 
			
		|||
 | 
			
		||||
/* return next token without macro substitution. Can read input from
 | 
			
		||||
   macro_ptr buffer */
 | 
			
		||||
void next_nomacro()
 | 
			
		||||
static void next_nomacro(void)
 | 
			
		||||
{
 | 
			
		||||
    if (macro_ptr) {
 | 
			
		||||
    redo:
 | 
			
		||||
| 
						 | 
				
			
			@ -2772,7 +2714,7 @@ void next_nomacro()
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/* substitute args in macro_str and return allocated string */
 | 
			
		||||
int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
 | 
			
		||||
static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
 | 
			
		||||
{
 | 
			
		||||
    int *st, last_tok, t, notfirst;
 | 
			
		||||
    Sym *s;
 | 
			
		||||
| 
						 | 
				
			
			@ -2894,7 +2836,7 @@ static int *macro_twosharps(void)
 | 
			
		|||
                p2 = get_tok_str(t, &cval);
 | 
			
		||||
                cstr_cat(&cstr, p2);
 | 
			
		||||
                cstr_ccat(&cstr, '\0');
 | 
			
		||||
                    
 | 
			
		||||
                
 | 
			
		||||
                if ((tok >= TOK_IDENT || tok == TOK_PPNUM) && 
 | 
			
		||||
                    (t >= TOK_IDENT || t == TOK_PPNUM)) {
 | 
			
		||||
                    if (tok == TOK_PPNUM) {
 | 
			
		||||
| 
						 | 
				
			
			@ -3130,7 +3072,7 @@ static void macro_subst(TokenString *tok_str,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/* return next token with macro substitution */
 | 
			
		||||
void next(void)
 | 
			
		||||
static void next(void)
 | 
			
		||||
{
 | 
			
		||||
    Sym *nested_list, *s;
 | 
			
		||||
    TokenString str;
 | 
			
		||||
| 
						 | 
				
			
			@ -3670,7 +3612,7 @@ void vpop(void)
 | 
			
		|||
    v = vtop->r & VT_VALMASK;
 | 
			
		||||
#ifdef TCC_TARGET_I386
 | 
			
		||||
    /* for x86, we need to pop the FP stack */
 | 
			
		||||
    if (v == REG_ST0) {
 | 
			
		||||
    if (v == REG_ST0 && !nocode_wanted) {
 | 
			
		||||
        o(0xd9dd); /* fstp %st(1) */
 | 
			
		||||
    } else
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -4045,8 +3987,12 @@ void gen_opic(int op)
 | 
			
		|||
            vtop->c.i += fc;
 | 
			
		||||
        } else {
 | 
			
		||||
        general_case:
 | 
			
		||||
            /* call low level op generator */
 | 
			
		||||
            gen_opi(op);
 | 
			
		||||
            if (!nocode_wanted) {
 | 
			
		||||
                /* call low level op generator */
 | 
			
		||||
                gen_opi(op);
 | 
			
		||||
            } else {
 | 
			
		||||
                vtop--;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4107,7 +4053,11 @@ void gen_opif(int op)
 | 
			
		|||
        vtop--;
 | 
			
		||||
    } else {
 | 
			
		||||
    general_case:
 | 
			
		||||
        gen_opf(op);
 | 
			
		||||
        if (!nocode_wanted) {
 | 
			
		||||
            gen_opf(op);
 | 
			
		||||
        } else {
 | 
			
		||||
            vtop--;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4355,7 +4305,7 @@ void gen_cast(int t)
 | 
			
		|||
    dbt = t & (VT_BTYPE | VT_UNSIGNED);
 | 
			
		||||
    sbt = vtop->t & (VT_BTYPE | VT_UNSIGNED);
 | 
			
		||||
 | 
			
		||||
    if (sbt != dbt) {
 | 
			
		||||
    if (sbt != dbt && !nocode_wanted) {
 | 
			
		||||
        sf = is_float(sbt);
 | 
			
		||||
        df = is_float(dbt);
 | 
			
		||||
        c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
 | 
			
		||||
| 
						 | 
				
			
			@ -4749,25 +4699,30 @@ void vstore(void)
 | 
			
		|||
        /* if structure, only generate pointer */
 | 
			
		||||
        /* structure assignment : generate memcpy */
 | 
			
		||||
        /* XXX: optimize if small size */
 | 
			
		||||
        vdup();
 | 
			
		||||
        gfunc_start(&gf, FUNC_CDECL);
 | 
			
		||||
        /* type size */
 | 
			
		||||
        size = type_size(vtop->t, &align);
 | 
			
		||||
        vpushi(size);
 | 
			
		||||
        gfunc_param(&gf);
 | 
			
		||||
        /* source */
 | 
			
		||||
        vtop->t = VT_INT;
 | 
			
		||||
        gaddrof();
 | 
			
		||||
        gfunc_param(&gf);
 | 
			
		||||
        /* destination */
 | 
			
		||||
        vswap();
 | 
			
		||||
        vtop->t = VT_INT;
 | 
			
		||||
        gaddrof();
 | 
			
		||||
        gfunc_param(&gf);
 | 
			
		||||
 | 
			
		||||
        save_regs(0);
 | 
			
		||||
        vpush_global_sym(func_old_type, TOK_memcpy);
 | 
			
		||||
        gfunc_call(&gf);
 | 
			
		||||
        if (!nocode_wanted) {
 | 
			
		||||
            vdup();
 | 
			
		||||
            gfunc_start(&gf, FUNC_CDECL);
 | 
			
		||||
            /* type size */
 | 
			
		||||
            size = type_size(vtop->t, &align);
 | 
			
		||||
            vpushi(size);
 | 
			
		||||
            gfunc_param(&gf);
 | 
			
		||||
            /* source */
 | 
			
		||||
            vtop->t = VT_INT;
 | 
			
		||||
            gaddrof();
 | 
			
		||||
            gfunc_param(&gf);
 | 
			
		||||
            /* destination */
 | 
			
		||||
            vswap();
 | 
			
		||||
            vtop->t = VT_INT;
 | 
			
		||||
            gaddrof();
 | 
			
		||||
            gfunc_param(&gf);
 | 
			
		||||
            
 | 
			
		||||
            save_regs(0);
 | 
			
		||||
            vpush_global_sym(func_old_type, TOK_memcpy);
 | 
			
		||||
            gfunc_call(&gf);
 | 
			
		||||
        } else {
 | 
			
		||||
            vswap();
 | 
			
		||||
            vpop();
 | 
			
		||||
        }
 | 
			
		||||
        /* leave source on stack */
 | 
			
		||||
    } else if (ft & VT_BITFIELD) {
 | 
			
		||||
        /* bitfield store handling */
 | 
			
		||||
| 
						 | 
				
			
			@ -4801,33 +4756,35 @@ void vstore(void)
 | 
			
		|||
            vswap();
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
        rc = RC_INT;
 | 
			
		||||
        if (is_float(ft))
 | 
			
		||||
            rc = RC_FLOAT;
 | 
			
		||||
        r = gv(rc);  /* generate value */
 | 
			
		||||
        /* if lvalue was saved on stack, must read it */
 | 
			
		||||
        if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
 | 
			
		||||
            SValue sv;
 | 
			
		||||
            t = get_reg(RC_INT);
 | 
			
		||||
            sv.t = VT_INT;
 | 
			
		||||
            sv.r = VT_LOCAL | VT_LVAL;
 | 
			
		||||
            sv.c.ul = vtop[-1].c.ul;
 | 
			
		||||
            load(t, &sv);
 | 
			
		||||
            vtop[-1].r = t | VT_LVAL;
 | 
			
		||||
        }
 | 
			
		||||
        store(r, vtop - 1);
 | 
			
		||||
        /* two word case handling : store second register at word + 4 */
 | 
			
		||||
        if ((ft & VT_BTYPE) == VT_LLONG) {
 | 
			
		||||
            vswap();
 | 
			
		||||
            /* convert to int to increment easily */
 | 
			
		||||
            vtop->t = VT_INT;
 | 
			
		||||
            gaddrof();
 | 
			
		||||
            vpushi(4);
 | 
			
		||||
            gen_op('+');
 | 
			
		||||
            vtop->r |= VT_LVAL;
 | 
			
		||||
            vswap();
 | 
			
		||||
            /* XXX: it works because r2 is spilled last ! */
 | 
			
		||||
            store(vtop->r2, vtop - 1);
 | 
			
		||||
        if (!nocode_wanted) {
 | 
			
		||||
            rc = RC_INT;
 | 
			
		||||
            if (is_float(ft))
 | 
			
		||||
                rc = RC_FLOAT;
 | 
			
		||||
            r = gv(rc);  /* generate value */
 | 
			
		||||
            /* if lvalue was saved on stack, must read it */
 | 
			
		||||
            if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
 | 
			
		||||
                SValue sv;
 | 
			
		||||
                t = get_reg(RC_INT);
 | 
			
		||||
                sv.t = VT_INT;
 | 
			
		||||
                sv.r = VT_LOCAL | VT_LVAL;
 | 
			
		||||
                sv.c.ul = vtop[-1].c.ul;
 | 
			
		||||
                load(t, &sv);
 | 
			
		||||
                vtop[-1].r = t | VT_LVAL;
 | 
			
		||||
            }
 | 
			
		||||
            store(r, vtop - 1);
 | 
			
		||||
            /* two word case handling : store second register at word + 4 */
 | 
			
		||||
            if ((ft & VT_BTYPE) == VT_LLONG) {
 | 
			
		||||
                vswap();
 | 
			
		||||
                /* convert to int to increment easily */
 | 
			
		||||
                vtop->t = VT_INT;
 | 
			
		||||
                gaddrof();
 | 
			
		||||
                vpushi(4);
 | 
			
		||||
                gen_op('+');
 | 
			
		||||
                vtop->r |= VT_LVAL;
 | 
			
		||||
                vswap();
 | 
			
		||||
                /* XXX: it works because r2 is spilled last ! */
 | 
			
		||||
                store(vtop->r2, vtop - 1);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        vswap();
 | 
			
		||||
        vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
 | 
			
		||||
| 
						 | 
				
			
			@ -5188,6 +5145,11 @@ int parse_btype(int *type_ptr, AttributeDef *ad)
 | 
			
		|||
        case TOK___ATTRIBUTE__:
 | 
			
		||||
            parse_attribute(ad);
 | 
			
		||||
            break;
 | 
			
		||||
            /* GNUC typeof */
 | 
			
		||||
        case TOK_TYPEOF:
 | 
			
		||||
            next();
 | 
			
		||||
            u = parse_expr_type();
 | 
			
		||||
            goto basic_type1;
 | 
			
		||||
        default:
 | 
			
		||||
            s = sym_find(tok);
 | 
			
		||||
            if (!s || !(s->t & VT_TYPEDEF))
 | 
			
		||||
| 
						 | 
				
			
			@ -5367,7 +5329,7 @@ static void indir(void)
 | 
			
		|||
{
 | 
			
		||||
    if ((vtop->t & VT_BTYPE) != VT_PTR)
 | 
			
		||||
        expect("pointer");
 | 
			
		||||
    if (vtop->r & VT_LVAL)
 | 
			
		||||
    if ((vtop->r & VT_LVAL) && !nocode_wanted)
 | 
			
		||||
        gv(RC_INT);
 | 
			
		||||
    vtop->t = pointed_type(vtop->t);
 | 
			
		||||
    /* an array is never an lvalue */
 | 
			
		||||
| 
						 | 
				
			
			@ -5394,10 +5356,31 @@ void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
 | 
			
		|||
    } else {
 | 
			
		||||
        gen_assign_cast(arg->t);
 | 
			
		||||
    }
 | 
			
		||||
    gfunc_param(gf);
 | 
			
		||||
    if (!nocode_wanted) {
 | 
			
		||||
        gfunc_param(gf);
 | 
			
		||||
    } else {
 | 
			
		||||
        vpop();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void unary(void)
 | 
			
		||||
/* parse an expression of the form '(type)' or '(expr)' and return its
 | 
			
		||||
   type */
 | 
			
		||||
static int parse_expr_type(void)
 | 
			
		||||
{
 | 
			
		||||
    int ft, n;
 | 
			
		||||
    AttributeDef ad;
 | 
			
		||||
 | 
			
		||||
    skip('(');
 | 
			
		||||
    if (parse_btype(&ft, &ad)) {
 | 
			
		||||
        ft = type_decl(&ad, &n, ft, TYPE_ABSTRACT);
 | 
			
		||||
    } else {
 | 
			
		||||
        ft = expr_type();
 | 
			
		||||
    }
 | 
			
		||||
    skip(')');
 | 
			
		||||
    return ft;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void unary(void)
 | 
			
		||||
{
 | 
			
		||||
    int n, t, ft, align, size, r;
 | 
			
		||||
    Sym *s;
 | 
			
		||||
| 
						 | 
				
			
			@ -5515,25 +5498,17 @@ void unary(void)
 | 
			
		|||
            vpushi(0);
 | 
			
		||||
            gen_op('+');
 | 
			
		||||
        } else 
 | 
			
		||||
        if (t == TOK_SIZEOF) {
 | 
			
		||||
        if (t == TOK_SIZEOF || t == TOK_ALIGNOF) {
 | 
			
		||||
            if (tok == '(') {
 | 
			
		||||
                next();
 | 
			
		||||
                if (parse_btype(&t, &ad)) {
 | 
			
		||||
                    t = type_decl(&ad, &n, t, TYPE_ABSTRACT);
 | 
			
		||||
                } else {
 | 
			
		||||
                    /* XXX: some code could be generated: add eval
 | 
			
		||||
                       flag */
 | 
			
		||||
                    gexpr();
 | 
			
		||||
                    t = vtop->t;
 | 
			
		||||
                    vpop();
 | 
			
		||||
                }
 | 
			
		||||
                skip(')');
 | 
			
		||||
                ft = parse_expr_type();
 | 
			
		||||
            } else {
 | 
			
		||||
                unary();
 | 
			
		||||
                t = vtop->t;
 | 
			
		||||
                vpop();
 | 
			
		||||
                ft = unary_type();
 | 
			
		||||
            }
 | 
			
		||||
            vpushi(type_size(t, &t));
 | 
			
		||||
            size = type_size(ft, &align);
 | 
			
		||||
            if (t == TOK_SIZEOF)
 | 
			
		||||
                vpushi(size);
 | 
			
		||||
            else
 | 
			
		||||
                vpushi(align);
 | 
			
		||||
        } else
 | 
			
		||||
        if (t == TOK_INC || t == TOK_DEC) {
 | 
			
		||||
            unary();
 | 
			
		||||
| 
						 | 
				
			
			@ -5627,8 +5602,10 @@ void unary(void)
 | 
			
		|||
            }
 | 
			
		||||
            /* get return type */
 | 
			
		||||
            s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
 | 
			
		||||
            save_regs(0); /* save used temporary registers */
 | 
			
		||||
            gfunc_start(&gf, s->r);
 | 
			
		||||
            if (!nocode_wanted) {
 | 
			
		||||
                save_regs(0); /* save used temporary registers */
 | 
			
		||||
                gfunc_start(&gf, s->r);
 | 
			
		||||
            }
 | 
			
		||||
            next();
 | 
			
		||||
            sa = s->next; /* first parameter */
 | 
			
		||||
#ifdef INVERT_FUNC_PARAMS
 | 
			
		||||
| 
						 | 
				
			
			@ -5693,7 +5670,10 @@ void unary(void)
 | 
			
		|||
                   problems */
 | 
			
		||||
                vset(VT_INT, VT_LOCAL, loc);
 | 
			
		||||
                ret.c = vtop->c;
 | 
			
		||||
                gfunc_param(&gf);
 | 
			
		||||
                if (!nocode_wanted)
 | 
			
		||||
                    gfunc_param(&gf);
 | 
			
		||||
                else
 | 
			
		||||
                    vtop--;
 | 
			
		||||
            } else {
 | 
			
		||||
                ret.t = s->t; 
 | 
			
		||||
                ret.r2 = VT_CONST;
 | 
			
		||||
| 
						 | 
				
			
			@ -5723,7 +5703,10 @@ void unary(void)
 | 
			
		|||
            if (sa)
 | 
			
		||||
                error("too few arguments to function");
 | 
			
		||||
            skip(')');
 | 
			
		||||
            gfunc_call(&gf);
 | 
			
		||||
            if (!nocode_wanted)
 | 
			
		||||
                gfunc_call(&gf);
 | 
			
		||||
            else
 | 
			
		||||
                vtop--;
 | 
			
		||||
            /* return value */
 | 
			
		||||
            vsetc(ret.t, ret.r, &ret.c);
 | 
			
		||||
            vtop->r2 = ret.r2;
 | 
			
		||||
| 
						 | 
				
			
			@ -5733,7 +5716,7 @@ void unary(void)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void uneq(void)
 | 
			
		||||
static void uneq(void)
 | 
			
		||||
{
 | 
			
		||||
    int t;
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -5756,7 +5739,7 @@ void uneq(void)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void sum(int l)
 | 
			
		||||
static void sum(int l)
 | 
			
		||||
{
 | 
			
		||||
    int t;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -5784,7 +5767,7 @@ void sum(int l)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/* only used if non constant */
 | 
			
		||||
void eand(void)
 | 
			
		||||
static void eand(void)
 | 
			
		||||
{
 | 
			
		||||
    int t;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -5804,7 +5787,7 @@ void eand(void)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eor(void)
 | 
			
		||||
static void eor(void)
 | 
			
		||||
{
 | 
			
		||||
    int t;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -5825,7 +5808,7 @@ void eor(void)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/* XXX: better constant handling */
 | 
			
		||||
void expr_eq(void)
 | 
			
		||||
static void expr_eq(void)
 | 
			
		||||
{
 | 
			
		||||
    int tt, u, r1, r2, rc, t1, t2, t, bt1, bt2;
 | 
			
		||||
    SValue sv;
 | 
			
		||||
| 
						 | 
				
			
			@ -5925,7 +5908,7 @@ void expr_eq(void)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void gexpr(void)
 | 
			
		||||
static void gexpr(void)
 | 
			
		||||
{
 | 
			
		||||
    while (1) {
 | 
			
		||||
        expr_eq();
 | 
			
		||||
| 
						 | 
				
			
			@ -5936,6 +5919,35 @@ void gexpr(void)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* parse an expression and return its type without any side effect. */
 | 
			
		||||
static int expr_type(void)
 | 
			
		||||
{
 | 
			
		||||
    int a, t;
 | 
			
		||||
 | 
			
		||||
    a = nocode_wanted;
 | 
			
		||||
    nocode_wanted = 1;
 | 
			
		||||
    gexpr();
 | 
			
		||||
    t = vtop->t;
 | 
			
		||||
    vpop();
 | 
			
		||||
    nocode_wanted = a;
 | 
			
		||||
    return t;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* parse a unary expression and return its type without any side
 | 
			
		||||
   effect. */
 | 
			
		||||
static int unary_type(void)
 | 
			
		||||
{
 | 
			
		||||
    int a, t;
 | 
			
		||||
 | 
			
		||||
    a = nocode_wanted;
 | 
			
		||||
    nocode_wanted = 1;
 | 
			
		||||
    unary();
 | 
			
		||||
    t = vtop->t;
 | 
			
		||||
    vpop();
 | 
			
		||||
    nocode_wanted = a;
 | 
			
		||||
    return t;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* parse a constant expression and return value in vtop.  */
 | 
			
		||||
static void expr_const1(void)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -5960,7 +5972,7 @@ static int expr_const(void)
 | 
			
		|||
 | 
			
		||||
/* return the label token if current token is a label, otherwise
 | 
			
		||||
   return zero */
 | 
			
		||||
int is_label(void)
 | 
			
		||||
static int is_label(void)
 | 
			
		||||
{
 | 
			
		||||
    int t;
 | 
			
		||||
    CValue c;
 | 
			
		||||
| 
						 | 
				
			
			@ -5985,7 +5997,7 @@ int is_label(void)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
 | 
			
		||||
static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg)
 | 
			
		||||
{
 | 
			
		||||
    int a, b, c, d;
 | 
			
		||||
    Sym *s;
 | 
			
		||||
| 
						 | 
				
			
			@ -6819,8 +6831,52 @@ void analyse_function(void)
 | 
			
		|||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* parse an old style function declaration list */
 | 
			
		||||
/* XXX: check multiple parameter */
 | 
			
		||||
static void func_decl_list(Sym *func_sym)
 | 
			
		||||
{
 | 
			
		||||
    AttributeDef ad;
 | 
			
		||||
    int b, v, t;
 | 
			
		||||
    Sym *s;
 | 
			
		||||
    /* parse each declaration */
 | 
			
		||||
    while (tok != '{' && tok != ';' && tok != TOK_EOF) {
 | 
			
		||||
        if (!parse_btype(&b, &ad)) 
 | 
			
		||||
            expect("declaration list");
 | 
			
		||||
        if (((b & VT_BTYPE) == VT_ENUM ||
 | 
			
		||||
             (b & VT_BTYPE) == VT_STRUCT) && 
 | 
			
		||||
            tok == ';') {
 | 
			
		||||
            /* we accept no variable after */
 | 
			
		||||
        } else {
 | 
			
		||||
            for(;;) {
 | 
			
		||||
                t = type_decl(&ad, &v, b, TYPE_DIRECT);
 | 
			
		||||
                /* find parameter in function parameter list */
 | 
			
		||||
                s = func_sym->next;
 | 
			
		||||
                while (s != NULL) {
 | 
			
		||||
                    if ((s->v & ~SYM_FIELD) == v)
 | 
			
		||||
                        goto found;
 | 
			
		||||
                    s = s->next;
 | 
			
		||||
                }
 | 
			
		||||
                error("declaration for parameter '%s' but no such parameter",
 | 
			
		||||
                      get_tok_str(v, NULL));
 | 
			
		||||
            found:
 | 
			
		||||
                /* check that no storage specifier except 'register' was given */
 | 
			
		||||
                if (t & (VT_EXTERN | VT_STATIC | VT_TYPEDEF))
 | 
			
		||||
                    error("storage class specified for '%s'", get_tok_str(v, NULL));
 | 
			
		||||
                /* we can add the type (NOTE: it could be local to the function) */
 | 
			
		||||
                s->t = t;
 | 
			
		||||
                /* accept other parameters */
 | 
			
		||||
                if (tok == ',')
 | 
			
		||||
                    next();
 | 
			
		||||
                else
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        skip(';');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 'l' is VT_LOCAL or VT_CONST to define default storage type */
 | 
			
		||||
void decl(int l)
 | 
			
		||||
static void decl(int l)
 | 
			
		||||
{
 | 
			
		||||
    int t, b, v, has_init, r;
 | 
			
		||||
    Sym *sym;
 | 
			
		||||
| 
						 | 
				
			
			@ -6856,6 +6912,14 @@ void decl(int l)
 | 
			
		|||
                printf("type = '%s'\n", buf);
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
            if ((t & VT_BTYPE) == VT_FUNC) {
 | 
			
		||||
                /* if old style function prototype, we accept a
 | 
			
		||||
                   declaration list */
 | 
			
		||||
                sym = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
 | 
			
		||||
                if (sym->c == FUNC_OLD)
 | 
			
		||||
                    func_decl_list(sym);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (tok == '{') {
 | 
			
		||||
#ifdef CONFIG_REG_VARS
 | 
			
		||||
                TokenString func_str;
 | 
			
		||||
| 
						 | 
				
			
			@ -7392,7 +7456,7 @@ int tcc_run(TCCState *s1, int argc, char **argv)
 | 
			
		|||
 | 
			
		||||
TCCState *tcc_new(void)
 | 
			
		||||
{
 | 
			
		||||
    char *p, *r;
 | 
			
		||||
    const char *p, *r;
 | 
			
		||||
    TCCState *s;
 | 
			
		||||
 | 
			
		||||
    s = tcc_mallocz(sizeof(TCCState));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue