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
This commit is contained in:
grischka 2020-06-17 18:08:09 +02:00
parent 781872517d
commit b5faa45d90
3 changed files with 145 additions and 132 deletions

114
tcc.h
View file

@ -35,6 +35,7 @@
#include <time.h>
#ifndef _WIN32
# define WIN32_LEAN_AND_MEAN 1
# include <unistd.h>
# include <sys/time.h>
# 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);

View file

@ -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();
}

116
tccpp.c
View file

@ -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, &macro_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, &macro_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();
t = tok;
if (macro_ptr) {
if (tok == TOK_NOSUBST || tok == TOK_PLCHLDR) {
if (!TOK_HAS_VALUE(t)) {
if (t == TOK_NOSUBST || t == TOK_PLCHLDR) {
/* discard preprocessor markers */
goto redo;
} else if (tok == 0) {
} else if (t == 0) {
/* end of macro or unget token string */
end_macro();
goto redo;
} else if (tok == '\\' && !(parse_flags & PARSE_FLAG_ACCEPT_STRAYS))
} else if (t == '\\') {
if (!(parse_flags & PARSE_FLAG_ACCEPT_STRAYS))
tcc_error("stray '\\' in program");
} else if (tok >= TOK_IDENT && (parse_flags & PARSE_FLAG_PREPROCESS)) {
Sym *s;
}
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);
}