Use precedence parser for expressions

This is smaller and uses less stack depth per expression (eight function
calls from expr_or to get down to a unary).  It's a tiny bit faster
depending on how good the branch predictor is, on my machine a wash.
This commit is contained in:
Michael Matz 2017-01-17 03:56:42 +01:00
parent fdeeb62e28
commit 23a8bac7b5
3 changed files with 36 additions and 83 deletions

3
tcc.h
View File

@ -1434,8 +1434,7 @@ ST_FUNC void parse_mult_str (CString *astr, const char *msg);
ST_FUNC void parse_asm_str(CString *astr); ST_FUNC void parse_asm_str(CString *astr);
ST_FUNC void indir(void); ST_FUNC void indir(void);
ST_FUNC void unary(void); ST_FUNC void unary(void);
ST_FUNC void expr_prod(void); ST_FUNC void init_prec(void);
ST_FUNC void expr_sum(void);
ST_FUNC void gexpr(void); ST_FUNC void gexpr(void);
ST_FUNC int expr_const(void); ST_FUNC int expr_const(void);
#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67 #if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67

114
tccgen.c
View File

@ -5681,100 +5681,52 @@ special_math_val:
} }
} }
ST_FUNC void expr_prod(void) static int precedence(int tok)
{ {
int t; switch (tok) {
case '|': return 1;
unary(); case '^': return 2;
while (tok == '*' || tok == '/' || tok == '%') { case '&': return 3;
t = tok; case TOK_EQ: case TOK_NE: return 4;
next(); relat: case TOK_ULT: case TOK_UGE: return 5;
unary(); case TOK_SHL: case TOK_SAR: return 6;
gen_op(t); case '+': case '-': return 7;
case '*': case '/': case '%': return 8;
default:
if (tok >= TOK_ULE && tok <= TOK_GT)
goto relat;
return 0;
} }
} }
ST_FUNC void expr_sum(void) static unsigned char prec[256];
ST_FUNC void init_prec(void)
{ {
int t; int i;
for (i = 0; i < 256; i++)
expr_prod(); prec[i] = precedence(i);
while (tok == '+' || tok == '-') {
t = tok;
next();
expr_prod();
gen_op(t);
}
} }
static void expr_shift(void) #define precedence(i) ((unsigned)i < 256 ? prec[i] : 0)
static void expr_infix(int p)
{ {
int t; int t = tok, p2, p3;
while ((p2 = precedence(t)) >= p) {
expr_sum(); next();
while (tok == TOK_SHL || tok == TOK_SAR) { unary();
t = tok; while ((p3 = precedence(tok)) > p2) {
next(); expr_infix(p3);
expr_sum(); }
gen_op(t); gen_op(t);
} t = tok;
}
static void expr_cmp(void)
{
int t;
expr_shift();
while ((tok >= TOK_ULE && tok <= TOK_GT) ||
tok == TOK_ULT || tok == TOK_UGE) {
t = tok;
next();
expr_shift();
gen_op(t);
}
}
static void expr_cmpeq(void)
{
int t;
expr_cmp();
while (tok == TOK_EQ || tok == TOK_NE) {
t = tok;
next();
expr_cmp();
gen_op(t);
}
}
static void expr_and(void)
{
expr_cmpeq();
while (tok == '&') {
next();
expr_cmpeq();
gen_op('&');
}
}
static void expr_xor(void)
{
expr_and();
while (tok == '^') {
next();
expr_and();
gen_op('^');
} }
} }
static void expr_or(void) static void expr_or(void)
{ {
expr_xor(); unary();
while (tok == '|') { expr_infix(1);
next();
expr_xor();
gen_op('|');
}
} }
static int condition_3way(void); static int condition_3way(void);

View File

@ -3679,6 +3679,8 @@ ST_FUNC void tccpp_new(TCCState *s)
define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL); define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL); define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL); define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL);
init_prec();
} }
ST_FUNC void tccpp_delete(TCCState *s) ST_FUNC void tccpp_delete(TCCState *s)