mirror of
https://github.com/mirror/tinycc.git
synced 2025-02-04 06:30:10 +08:00
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:
parent
fdeeb62e28
commit
23a8bac7b5
3
tcc.h
3
tcc.h
@ -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 indir(void);
|
||||
ST_FUNC void unary(void);
|
||||
ST_FUNC void expr_prod(void);
|
||||
ST_FUNC void expr_sum(void);
|
||||
ST_FUNC void init_prec(void);
|
||||
ST_FUNC void gexpr(void);
|
||||
ST_FUNC int expr_const(void);
|
||||
#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67
|
||||
|
114
tccgen.c
114
tccgen.c
@ -5681,100 +5681,52 @@ special_math_val:
|
||||
}
|
||||
}
|
||||
|
||||
ST_FUNC void expr_prod(void)
|
||||
static int precedence(int tok)
|
||||
{
|
||||
int t;
|
||||
|
||||
unary();
|
||||
while (tok == '*' || tok == '/' || tok == '%') {
|
||||
t = tok;
|
||||
next();
|
||||
unary();
|
||||
gen_op(t);
|
||||
switch (tok) {
|
||||
case '|': return 1;
|
||||
case '^': return 2;
|
||||
case '&': return 3;
|
||||
case TOK_EQ: case TOK_NE: return 4;
|
||||
relat: case TOK_ULT: case TOK_UGE: return 5;
|
||||
case TOK_SHL: case TOK_SAR: return 6;
|
||||
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;
|
||||
|
||||
expr_prod();
|
||||
while (tok == '+' || tok == '-') {
|
||||
t = tok;
|
||||
next();
|
||||
expr_prod();
|
||||
gen_op(t);
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < 256; i++)
|
||||
prec[i] = precedence(i);
|
||||
}
|
||||
|
||||
static void expr_shift(void)
|
||||
#define precedence(i) ((unsigned)i < 256 ? prec[i] : 0)
|
||||
|
||||
static void expr_infix(int p)
|
||||
{
|
||||
int t;
|
||||
|
||||
expr_sum();
|
||||
while (tok == TOK_SHL || tok == TOK_SAR) {
|
||||
t = tok;
|
||||
next();
|
||||
expr_sum();
|
||||
gen_op(t);
|
||||
}
|
||||
}
|
||||
|
||||
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('^');
|
||||
int t = tok, p2, p3;
|
||||
while ((p2 = precedence(t)) >= p) {
|
||||
next();
|
||||
unary();
|
||||
while ((p3 = precedence(tok)) > p2) {
|
||||
expr_infix(p3);
|
||||
}
|
||||
gen_op(t);
|
||||
t = tok;
|
||||
}
|
||||
}
|
||||
|
||||
static void expr_or(void)
|
||||
{
|
||||
expr_xor();
|
||||
while (tok == '|') {
|
||||
next();
|
||||
expr_xor();
|
||||
gen_op('|');
|
||||
}
|
||||
unary();
|
||||
expr_infix(1);
|
||||
}
|
||||
|
||||
static int condition_3way(void);
|
||||
|
Loading…
Reference in New Issue
Block a user