From b5faa45d9065cafc1a18dc91d6c2bd0fa8af9d7c Mon Sep 17 00:00:00 2001 From: grischka Date: Wed, 17 Jun 2020 18:08:09 +0200 Subject: [PATCH] tccpp: faster next() - call TOK_GET() as a function only for tokens with values - get rid of 'next_nomacro_spc()' - be sligtly more efficient in next() This made about 4-5%+ speed in my tests. Also: tcc.h: reorder tokens --- tcc.h | 114 +++++++++++++++++++++++++----------------------- tccgen.c | 33 +++++--------- tccpp.c | 130 +++++++++++++++++++++++++++++++------------------------ 3 files changed, 145 insertions(+), 132 deletions(-) diff --git a/tcc.h b/tcc.h index b6166198..e814f3a3 100644 --- a/tcc.h +++ b/tcc.h @@ -35,6 +35,7 @@ #include #ifndef _WIN32 +# define WIN32_LEAN_AND_MEAN 1 # include # include # ifndef CONFIG_TCC_STATIC @@ -1009,6 +1010,9 @@ struct filespec { /* token values */ +/* conditional ops */ +#define TOK_LAND 0x90 +#define TOK_LOR 0x91 /* warning: the following compare tokens depend on i386 asm code */ #define TOK_ULT 0x92 #define TOK_UGE 0x93 @@ -1023,62 +1027,65 @@ struct filespec { #define TOK_LE 0x9e #define TOK_GT 0x9f -#define TOK_LAND 0xa0 -#define TOK_LOR 0xa1 -#define TOK_DEC 0xa2 -#define TOK_MID 0xa3 /* inc/dec, to void constant */ -#define TOK_INC 0xa4 -#define TOK_UDIV 0xb0 /* unsigned division */ -#define TOK_UMOD 0xb1 /* unsigned modulo */ -#define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */ +#define TOK_ISCOND(t) (t >= TOK_LAND && t <= TOK_GT) + +#define TOK_DEC 0x80 /* -- */ +#define TOK_MID 0x81 /* inc/dec, to void constant */ +#define TOK_INC 0x82 /* ++ */ +#define TOK_UDIV 0x83 /* unsigned division */ +#define TOK_UMOD 0x84 /* unsigned modulo */ +#define TOK_PDIV 0x85 /* fast division with undefined rounding for pointers */ +#define TOK_UMULL 0x86 /* unsigned 32x32 -> 64 mul */ +#define TOK_ADDC1 0x87 /* add with carry generation */ +#define TOK_ADDC2 0x88 /* add with carry use */ +#define TOK_SUBC1 0x89 /* add with carry generation */ +#define TOK_SUBC2 0x8a /* add with carry use */ +#define TOK_SHL '<' /* shift left */ +#define TOK_SAR '>' /* signed shift right */ +#define TOK_SHR 0x8b /* unsigned shift right */ + +#define TOK_ARROW 0xa0 /* -> */ +#define TOK_DOTS 0xa1 /* three dots */ +#define TOK_TWODOTS 0xa2 /* C++ token ? */ +#define TOK_TWOSHARPS 0xa3 /* ## preprocessing token */ +#define TOK_PLCHLDR 0xa4 /* placeholder token as defined in C99 */ +#define TOK_NOSUBST 0xa5 /* means following token has already been pp'd */ +#define TOK_PPJOIN 0xa6 /* A '##' in the right position to mean pasting */ + +/* assignment operators */ +#define TOK_A_ADD 0xb0 +#define TOK_A_SUB 0xb1 +#define TOK_A_MUL 0xb2 +#define TOK_A_DIV 0xb3 +#define TOK_A_MOD 0xb4 +#define TOK_A_AND 0xb5 +#define TOK_A_OR 0xb6 +#define TOK_A_XOR 0xb7 +#define TOK_A_SHL 0xb8 +#define TOK_A_SAR 0xb9 + +#define TOK_ASSIGN(t) (t >= TOK_A_ADD && t <= TOK_A_SAR) +#define TOK_ASSIGN_OP(t) ("+-*/%&|^<>"[t - TOK_A_ADD]) /* tokens that carry values (in additional token string space / tokc) --> */ -#define TOK_CCHAR 0xb3 /* char constant in tokc */ -#define TOK_LCHAR 0xb4 -#define TOK_CINT 0xb5 /* number in tokc */ -#define TOK_CUINT 0xb6 /* unsigned int constant */ -#define TOK_CLLONG 0xb7 /* long long constant */ -#define TOK_CULLONG 0xb8 /* unsigned long long constant */ -#define TOK_STR 0xb9 /* pointer to string in tokc */ -#define TOK_LSTR 0xba -#define TOK_CFLOAT 0xbb /* float constant */ -#define TOK_CDOUBLE 0xbc /* double constant */ -#define TOK_CLDOUBLE 0xbd /* long double constant */ -#define TOK_PPNUM 0xbe /* preprocessor number */ -#define TOK_PPSTR 0xbf /* preprocessor string */ -#define TOK_LINENUM 0xc0 /* line number info */ -#define TOK_TWODOTS 0xa8 /* C++ token ? */ -/* <-- */ +#define TOK_CCHAR 0xc0 /* char constant in tokc */ +#define TOK_LCHAR 0xc1 +#define TOK_CINT 0xc2 /* number in tokc */ +#define TOK_CUINT 0xc3 /* unsigned int constant */ +#define TOK_CLLONG 0xc4 /* long long constant */ +#define TOK_CULLONG 0xc5 /* unsigned long long constant */ +#define TOK_CLONG 0xc6 /* long constant */ +#define TOK_CULONG 0xc7 /* unsigned long constant */ +#define TOK_STR 0xc8 /* pointer to string in tokc */ +#define TOK_LSTR 0xc9 +#define TOK_CFLOAT 0xca /* float constant */ +#define TOK_CDOUBLE 0xcb /* double constant */ +#define TOK_CLDOUBLE 0xcc /* long double constant */ +#define TOK_PPNUM 0xcd /* preprocessor number */ +#define TOK_PPSTR 0xce /* preprocessor string */ +#define TOK_LINENUM 0xcf /* line number info */ -#define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */ -#define TOK_ADDC1 0xc3 /* add with carry generation */ -#define TOK_ADDC2 0xc4 /* add with carry use */ -#define TOK_SUBC1 0xc5 /* add with carry generation */ -#define TOK_SUBC2 0xc6 /* add with carry use */ -#define TOK_ARROW 0xc7 -#define TOK_DOTS 0xc8 /* three dots */ -#define TOK_SHR 0xc9 /* unsigned shift right */ -#define TOK_TWOSHARPS 0xca /* ## preprocessing token */ -#define TOK_PLCHLDR 0xcb /* placeholder token as defined in C99 */ -#define TOK_NOSUBST 0xcc /* means following token has already been pp'd */ -#define TOK_PPJOIN 0xcd /* A '##' in the right position to mean pasting */ -#define TOK_CLONG 0xce /* long constant */ -#define TOK_CULONG 0xcf /* unsigned long constant */ - -#define TOK_SHL 0x01 /* shift left */ -#define TOK_SAR 0x02 /* signed shift right */ - -/* assignment operators : normal operator or 0x80 */ -#define TOK_A_MOD 0xa5 -#define TOK_A_AND 0xa6 -#define TOK_A_MUL 0xaa -#define TOK_A_ADD 0xab -#define TOK_A_SUB 0xad -#define TOK_A_DIV 0xaf -#define TOK_A_XOR 0xde -#define TOK_A_OR 0xfc -#define TOK_A_SHL 0x81 -#define TOK_A_SAR 0x82 +#define TOK_HAS_VALUE(t) (t >= TOK_CCHAR && t <= TOK_LINENUM) #define TOK_EOF (-1) /* end of file */ #define TOK_LINEFEED 10 /* line feed */ @@ -1346,7 +1353,6 @@ ST_FUNC Sym *label_push(Sym **ptop, int v, int flags); ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep); ST_FUNC void parse_define(void); ST_FUNC void preprocess(int is_bof); -ST_FUNC void next_nomacro(void); ST_FUNC void next(void); ST_INLN void unget_tok(int last_tok); ST_FUNC void preprocess_start(TCCState *s1, int is_asm); diff --git a/tccgen.c b/tccgen.c index 2f76d4f8..aa10395f 100644 --- a/tccgen.c +++ b/tccgen.c @@ -3064,7 +3064,7 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op) else if (bt1 != bt2) { /* accept comparison or cond-expr between pointer and integer with a warning */ - if ((op == '?' || (op >= TOK_ULT && op <= TOK_LOR)) + if ((op == '?' || TOK_ISCOND(op)) && (is_integer_btype(bt1) || is_integer_btype(bt2))) tcc_warning("pointer/integer mismatch in %s", op == '?' ? "conditional expression" : "comparison"); @@ -3079,7 +3079,7 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op) int newquals, copied = 0; if (pbt1 != VT_VOID && pbt2 != VT_VOID && !compare_types(pt1, pt2, 1/*unqualif*/)) { - if (op != '?' && (op < TOK_ULT || op > TOK_LOR)) + if (op != '?' && !TOK_ISCOND(op)) ret = 0; else type_incompatibility_warning(type1, type2, @@ -3120,7 +3120,7 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op) } } } - if (op >= TOK_ULT && op <= TOK_LOR) + if (TOK_ISCOND(op)) type.t = VT_SIZE_T; } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) { if (op != '?' || !compare_types(type1, type2, 1)) @@ -3188,7 +3188,7 @@ redo: } else if (bt1 == VT_PTR || bt2 == VT_PTR) { /* at least one operand is a pointer */ /* relational op: must be both pointers */ - if (op >= TOK_ULT && op <= TOK_LOR) + if (TOK_ISCOND(op)) goto std_op; /* if both pointers, then it must be the '-' op */ if (bt1 == VT_PTR && bt2 == VT_PTR) { @@ -3256,7 +3256,7 @@ redo: /* floats can only be used for a few operations */ if (is_float(combtype.t) && op != '+' && op != '-' && op != '*' && op != '/' - && (op < TOK_ULT || op > TOK_LOR)) + && !TOK_ISCOND(op)) tcc_error("invalid operands for binary operation"); else if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL) { t = bt1 == VT_LLONG ? VT_LLONG : VT_INT; @@ -3297,7 +3297,7 @@ redo: gen_opif(op); else gen_opic(op); - if (op >= TOK_ULT && op <= TOK_LOR) { + if (TOK_ISCOND(op)) { /* relational op: the result is an int */ vtop->type.t = VT_INT; } else { @@ -4065,13 +4065,8 @@ redo: tcc_warning("implicit declaration of function '%s'", get_tok_str(tok, &tokc)); s = external_global_sym(tok, &func_old_type); - } - else if ((s->type.t & VT_BTYPE) == VT_FUNC) { - ad->cleanup_func = s; - } - else { + } else if ((s->type.t & VT_BTYPE) != VT_FUNC) tcc_error("'%s' is not declared as function", get_tok_str(tok, &tokc)); - } ad->cleanup_func = s; next(); skip(')'); @@ -5937,11 +5932,8 @@ special_math_val: test_lvalue(); gaddrof(); /* expect pointer on structure */ - if ((vtop->type.t & VT_BTYPE) != VT_STRUCT) { - char got[256]; - type_to_str(got, sizeof got, &vtop->type, NULL); - tcc_error("expected struct or union but not '%s'", got); - } + if ((vtop->type.t & VT_BTYPE) != VT_STRUCT) + expect("struct or union"); if (tok == TOK_CDOUBLE) expect("field name"); next(); @@ -6487,10 +6479,7 @@ static void expr_eq(void) int t; expr_cond(); - if ((t = tok) == '=' - || (t >= TOK_A_MOD && t <= TOK_A_DIV) - || t == TOK_A_XOR || t == TOK_A_OR - || t == TOK_A_SHL || t == TOK_A_SAR) { + if ((t = tok) == '=' || TOK_ASSIGN(t)) { test_lvalue(); next(); if (t == '=') { @@ -6498,7 +6487,7 @@ static void expr_eq(void) } else { vdup(); expr_eq(); - gen_op(t & 0x7f); + gen_op(TOK_ASSIGN_OP(t)); } vstore(); } diff --git a/tccpp.c b/tccpp.c index 74cdbff2..1cd6c999 100644 --- a/tccpp.c +++ b/tccpp.c @@ -92,7 +92,7 @@ static const unsigned char tok_two_chars[] = 0 }; -static void next_nomacro_spc(void); +static void next_nomacro(void); ST_FUNC void skip(int c) { @@ -1230,7 +1230,7 @@ ST_FUNC void tok_str_add_tok(TokenString *s) } /* get a token from an integer array and increment pointer. */ -static inline void TOK_GET(int *t, const int **pp, CValue *cv) +static inline void tok_get(int *t, const int **pp, CValue *cv) { const int *p = *pp; int n, *tab; @@ -1293,6 +1293,18 @@ static inline void TOK_GET(int *t, const int **pp, CValue *cv) *pp = p; } +#if 0 +# define TOK_GET(t,p,c) tok_get(t,p,c) +#else +# define TOK_GET(t,p,c) do { \ + int _t = **(p); \ + if (TOK_HAS_VALUE(_t)) \ + tok_get(t, p, c); \ + else \ + *(t) = _t, ++*(p); \ + } while (0) +#endif + static int macro_is_equal(const int *a, const int *b) { CValue cv; @@ -1493,7 +1505,8 @@ ST_FUNC void parse_define(void) character. */ parse_flags = ((parse_flags & ~PARSE_FLAG_ASM_FILE) | PARSE_FLAG_SPACES); /* '(' must be just after macro definition for MACRO_FUNC */ - next_nomacro_spc(); + next_nomacro(); + parse_flags &= ~PARSE_FLAG_SPACES; if (tok == '(') { int dotid = set_idnum('.', 0); next_nomacro(); @@ -1521,7 +1534,8 @@ ST_FUNC void parse_define(void) goto bad_list; next_nomacro(); } - next_nomacro_spc(); + parse_flags |= PARSE_FLAG_SPACES; + next_nomacro(); t = MACRO_FUNC; set_idnum('.', dotid); } @@ -1550,7 +1564,7 @@ ST_FUNC void parse_define(void) } tok_str_add2(&tokstr_buf, tok, &tokc); skip: - next_nomacro_spc(); + next_nomacro(); } parse_flags = saved_parse_flags; @@ -2586,6 +2600,7 @@ static inline void next_nomacro1(void) case '\t': tok = c; p++; + maybe_space: if (parse_flags & PARSE_FLAG_SPACES) goto keep_tok_flags; while (isidnum_table[*p - CH_EOF] & IS_SPC) @@ -2932,11 +2947,11 @@ maybe_newline: p = parse_comment(p); /* comments replaced by a blank */ tok = ' '; - goto keep_tok_flags; + goto maybe_space; } else if (c == '/') { p = parse_line_comment(p); tok = ' '; - goto keep_tok_flags; + goto maybe_space; } else if (c == '=') { p++; tok = TOK_A_DIV; @@ -2978,34 +2993,6 @@ keep_tok_flags: #endif } -/* return next token without macro substitution. Can read input from - macro_ptr buffer */ -static void next_nomacro_spc(void) -{ - if (macro_ptr) { - redo: - tok = *macro_ptr; - if (tok) { - TOK_GET(&tok, ¯o_ptr, &tokc); - if (tok == TOK_LINENUM) { - file->line_num = tokc.i; - goto redo; - } - } - } else { - next_nomacro1(); - } - //printf("token = %s\n", get_tok_str(tok, &tokc)); -} - -ST_FUNC void next_nomacro(void) -{ - do { - next_nomacro_spc(); - } while (tok < 256 && (isidnum_table[tok - CH_EOF] & IS_SPC)); -} - - static void macro_subst( TokenString *tok_str, Sym **nested_list, @@ -3281,7 +3268,7 @@ static int next_argstream(Sym **nested_list, TokenString *ws_str) if (ws_str) return t; - next_nomacro_spc(); + next_nomacro(); return tok; } } @@ -3372,7 +3359,7 @@ static int macro_subst_tok( } do { next_nomacro(); /* eat '(' */ - } while (tok == TOK_PLCHLDR); + } while (tok == TOK_PLCHLDR || is_space(tok)); /* argument macro */ args = NULL; @@ -3533,29 +3520,59 @@ no_subst: } } +/* return next token without macro substitution. Can read input from + macro_ptr buffer */ +static void next_nomacro(void) +{ + int t; + if (macro_ptr) { + redo: + t = *macro_ptr; + if (TOK_HAS_VALUE(t)) { + tok_get(&tok, ¯o_ptr, &tokc); + if (t == TOK_LINENUM) { + file->line_num = tokc.i; + goto redo; + } + } else { + macro_ptr++; + if (t < TOK_IDENT) { + if (!(parse_flags & PARSE_FLAG_SPACES) + && (isidnum_table[t - CH_EOF] & IS_SPC)) + goto redo; + } + tok = t; + } + } else { + next_nomacro1(); + } +} + /* return next token with macro substitution */ ST_FUNC void next(void) { + int t; redo: - if (parse_flags & PARSE_FLAG_SPACES) - next_nomacro_spc(); - else - next_nomacro(); - + next_nomacro(); + t = tok; if (macro_ptr) { - if (tok == TOK_NOSUBST || tok == TOK_PLCHLDR) { - /* discard preprocessor markers */ - goto redo; - } else if (tok == 0) { - /* end of macro or unget token string */ - end_macro(); - goto redo; - } else if (tok == '\\' && !(parse_flags & PARSE_FLAG_ACCEPT_STRAYS)) - tcc_error("stray '\\' in program"); - } else if (tok >= TOK_IDENT && (parse_flags & PARSE_FLAG_PREPROCESS)) { - Sym *s; + if (!TOK_HAS_VALUE(t)) { + if (t == TOK_NOSUBST || t == TOK_PLCHLDR) { + /* discard preprocessor markers */ + goto redo; + } else if (t == 0) { + /* end of macro or unget token string */ + end_macro(); + goto redo; + } else if (t == '\\') { + if (!(parse_flags & PARSE_FLAG_ACCEPT_STRAYS)) + tcc_error("stray '\\' in program"); + } + return; + } + } else if (t >= TOK_IDENT && (parse_flags & PARSE_FLAG_PREPROCESS)) { /* if reading from file, try to substitute macros */ - s = define_find(tok); + Sym *s = define_find(t); if (s) { Sym *nested_list = NULL; tokstr_buf.len = 0; @@ -3564,12 +3581,13 @@ ST_FUNC void next(void) begin_macro(&tokstr_buf, 0); goto redo; } + return; } /* convert preprocessor tokens into C tokens */ - if (tok == TOK_PPNUM) { + if (t == TOK_PPNUM) { if (parse_flags & PARSE_FLAG_TOK_NUM) parse_number((char *)tokc.str.data); - } else if (tok == TOK_PPSTR) { + } else if (t == TOK_PPSTR) { if (parse_flags & PARSE_FLAG_TOK_STR) parse_string((char *)tokc.str.data, tokc.str.size - 1); }