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:
parent
781872517d
commit
b5faa45d90
3 changed files with 145 additions and 132 deletions
114
tcc.h
114
tcc.h
|
@ -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);
|
||||
|
|
33
tccgen.c
33
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();
|
||||
}
|
||||
|
|
130
tccpp.c
130
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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue