Skip to content

Commit 8e6bb70

Browse files
committed
Support {*, /, %, ^} operators
Also: - Fix some parsing bugs - Now integer overflows == undefined
1 parent b338125 commit 8e6bb70

5 files changed

Lines changed: 138 additions & 47 deletions

File tree

doc/e9tool-user-guide.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ The basic form of a matching (`MATCH`) is a Boolean expression of
5353
| <b>not</b> EXPR
5454
| EXPR <b>and</b> EXPR
5555
| EXPR <b>or</b> EXPR
56-
| EXPR <b>+</b> EXPR | EXPR <b>-</b> EXPR | <b>-</b>EXPR
57-
| EXPR <b>&</b> EXPR | EXPR <b>|</b> EXPR | <b>~</b>EXPR
56+
| EXPR <b>+</b> EXPR | EXPR <b>-</b> EXPR | EXPR <b>*</b> EXPR | EXPR <b>/</b> EXPR | EXPR <b>%</b> EXPR | <b>-</b>EXPR
57+
| EXPR <b>&</b> EXPR | EXPR <b>|</b> EXPR | EXPR <b>^</b> EXPR | <b>~</b>EXPR
5858
| EXPR <b>&lt;&lt;</b> EXPR | EXPR <b>&gt;&gt;</b> EXPR
5959
| EXPR <b>==</b> EXPR | EXPR <b>!=</b> EXPR
6060
| EXPR <b>&lt;</b> EXPR | EXPR <b>&lt;=</b> EXPR
@@ -119,17 +119,25 @@ Supported operators include:
119119
<td>Integer addition</td></tr>
120120
<tr><td><b><tt>-</tt></b></td>
121121
<td>Integer subtraction or unary negation</td></tr>
122+
<tr><td><b><tt>*</tt></b></td>
123+
<td>Integer multiplication</td></tr>
124+
<tr><td><b><tt>/</tt></b> or <b><tt>div</tt></b></td>
125+
<td>Integer division</td></tr>
126+
<tr><td><b><tt>%</tt></b> or <b><tt>mod</tt></b></td>
127+
<td>Integer modulus</td></tr>
122128
<tr><td><b><tt>&amp;</tt></b></td>
123129
<td>Integer bitwise and</td></tr>
124130
<tr><td><b><tt>|</tt></b></td>
125131
<td>Integer bitwise or</td></tr>
132+
<tr><td><b><tt>|</tt></b></td>
133+
<td>Integer bitwise xor</td></tr>
126134
<tr><td><b><tt>~</tt></b></td>
127135
<td>Integer bitwise negation</td></tr>
128136
<tr><td><b><tt>&lt;&lt;</tt></b></td>
129137
<td>Integer left shift</td></tr>
130138
<tr><td><b><tt>&gt;&gt;</tt></b></td>
131139
<td>Integer right shift</td></tr>
132-
<tr><td><b><tt>=</tt> or <tt>==</tt></b></td>
140+
<tr><td><b><tt>=</tt></b> or <b><tt>==</tt></b></td>
133141
<td>Equality</td></tr>
134142
<tr><td><b><tt>!=</tt></b></td>
135143
<td>Disequality</td></tr>

src/e9tool/e9action.cpp

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -680,35 +680,47 @@ static const MatchOpInfo *parseMatchOp(int t)
680680
case '&':
681681
static const MatchOpInfo info_BIT_AND = {MATCH_OP_BIT_AND, 2};
682682
return &info_BIT_AND;
683+
case '^':
684+
static const MatchOpInfo info_BIT_XOR = {MATCH_OP_BIT_XOR, 3};
685+
return &info_BIT_XOR;
683686
case '|':
684-
static const MatchOpInfo info_BIT_OR = {MATCH_OP_BIT_OR, 3};
687+
static const MatchOpInfo info_BIT_OR = {MATCH_OP_BIT_OR, 4};
685688
return &info_BIT_OR;
686689
case '-':
687-
static const MatchOpInfo info_SUB = {MATCH_OP_SUB, 4};
690+
static const MatchOpInfo info_SUB = {MATCH_OP_SUB, 5};
688691
return &info_SUB;
689692
case '+':
690-
static const MatchOpInfo info_ADD = {MATCH_OP_ADD, 4};
693+
static const MatchOpInfo info_ADD = {MATCH_OP_ADD, 5};
691694
return &info_ADD;
695+
case '*':
696+
static const MatchOpInfo info_MUL = {MATCH_OP_MUL, 6};
697+
return &info_MUL;
698+
case '/': case TOKEN_DIV:
699+
static const MatchOpInfo info_DIV = {MATCH_OP_DIV, 6};
700+
return &info_DIV;
701+
case '%': case TOKEN_MOD:
702+
static const MatchOpInfo info_MOD = {MATCH_OP_MOD, 6};
703+
return &info_MOD;
692704
case TOKEN_IN:
693-
static const MatchOpInfo info_IN = {MATCH_OP_IN, 5};
705+
static const MatchOpInfo info_IN = {MATCH_OP_IN, 7};
694706
return &info_IN;
695707
case '<':
696-
static const MatchOpInfo info_LT = {MATCH_OP_LT, 6};
708+
static const MatchOpInfo info_LT = {MATCH_OP_LT, 8};
697709
return &info_LT;
698710
case '>':
699-
static const MatchOpInfo info_GT = {MATCH_OP_GT, 6};
711+
static const MatchOpInfo info_GT = {MATCH_OP_GT, 8};
700712
return &info_GT;
701713
case TOKEN_LEQ:
702-
static const MatchOpInfo info_LEQ = {MATCH_OP_LEQ, 6};
714+
static const MatchOpInfo info_LEQ = {MATCH_OP_LEQ, 8};
703715
return &info_LEQ;
704716
case TOKEN_GEQ:
705-
static const MatchOpInfo info_GEQ = {MATCH_OP_GEQ, 6};
717+
static const MatchOpInfo info_GEQ = {MATCH_OP_GEQ, 8};
706718
return &info_GEQ;
707719
case '=':
708-
static const MatchOpInfo info_EQ = {MATCH_OP_EQ, 7};
720+
static const MatchOpInfo info_EQ = {MATCH_OP_EQ, 9};
709721
return &info_EQ;
710722
case TOKEN_NEQ:
711-
static const MatchOpInfo info_NEQ = {MATCH_OP_NEQ, 7};
723+
static const MatchOpInfo info_NEQ = {MATCH_OP_NEQ, 9};
712724
return &info_NEQ;
713725
case TOKEN_AND:
714726
static const MatchOpInfo info_AND = {MATCH_OP_AND, 11};
@@ -737,7 +749,7 @@ static MatchExpr *parseMatchExpr(Parser &parser, int prec = 99)
737749
break;
738750
case '!': case TOKEN_NOT:
739751
(void)parser.getToken();
740-
expr = parseMatchExpr(parser, 8);
752+
expr = parseMatchExpr(parser, 10);
741753
expr = new MatchExpr(MATCH_OP_NOT, expr);
742754
break;
743755
case TOKEN_NONE:
@@ -1410,7 +1422,7 @@ static void dumpExpr(const MatchExpr &expr, std::string &str, bool hex = false)
14101422
str += '~';
14111423
dumpExpr(*expr.lhs, str);
14121424
return;
1413-
case MATCH_OP_BIT_AND: case MATCH_OP_BIT_OR:
1425+
case MATCH_OP_BIT_AND: case MATCH_OP_BIT_OR: case MATCH_OP_BIT_XOR:
14141426
hex = true;
14151427
// Fallthrough:
14161428
case MATCH_OP_AND: case MATCH_OP_OR:
@@ -1419,6 +1431,7 @@ static void dumpExpr(const MatchExpr &expr, std::string &str, bool hex = false)
14191431
case MATCH_OP_GT: case MATCH_OP_GEQ:
14201432
case MATCH_OP_IN:
14211433
case MATCH_OP_ADD: case MATCH_OP_SUB:
1434+
case MATCH_OP_MUL: case MATCH_OP_DIV: case MATCH_OP_MOD:
14221435
case MATCH_OP_LSHIFT: case MATCH_OP_RSHIFT:
14231436
str += '(';
14241437
dumpExpr(*expr.lhs, str, hex);
@@ -1446,10 +1459,18 @@ static void dumpExpr(const MatchExpr &expr, std::string &str, bool hex = false)
14461459
str += '+'; break;
14471460
case MATCH_OP_SUB:
14481461
str += '-'; break;
1462+
case MATCH_OP_MUL:
1463+
str += '*'; break;
1464+
case MATCH_OP_DIV:
1465+
str += '/'; break;
1466+
case MATCH_OP_MOD:
1467+
str += '%'; break;
14491468
case MATCH_OP_BIT_AND:
14501469
str += '&'; break;
14511470
case MATCH_OP_BIT_OR:
14521471
str += '|'; break;
1472+
case MATCH_OP_BIT_XOR:
1473+
str += '^'; break;
14531474
case MATCH_OP_LSHIFT:
14541475
str += "<<"; break;
14551476
case MATCH_OP_RSHIFT:
@@ -2288,7 +2309,8 @@ static MatchVal matchDoEval(const MatchExpr *expr, const ELF &elf,
22882309
break;
22892310
}
22902311
case MATCH_OP_ADD: case MATCH_OP_SUB:
2291-
case MATCH_OP_BIT_AND: case MATCH_OP_BIT_OR:
2312+
case MATCH_OP_MUL: case MATCH_OP_DIV: case MATCH_OP_MOD:
2313+
case MATCH_OP_BIT_AND: case MATCH_OP_BIT_OR: case MATCH_OP_BIT_XOR:
22922314
case MATCH_OP_LSHIFT: case MATCH_OP_RSHIFT:
22932315
{
22942316
res.type = MATCH_TYPE_UNDEFINED;
@@ -2300,18 +2322,36 @@ static MatchVal matchDoEval(const MatchExpr *expr, const ELF &elf,
23002322
break;
23012323
res.type = MATCH_TYPE_INTEGER;
23022324
res.i = 0;
2325+
typedef __int128 int128_t;
2326+
int128_t i128 = 0;
23032327
switch (expr->op)
23042328
{
23052329
case MATCH_OP_ADD:
2306-
res.i = lhs.i + rhs.i; break;
2330+
i128 = (int128_t)lhs.i + (int128_t)rhs.i;
2331+
goto check128;
23072332
case MATCH_OP_SUB:
2308-
res.i = lhs.i - rhs.i; break;
2333+
i128 = (int128_t)lhs.i - (int128_t)rhs.i;
2334+
goto check128;
2335+
case MATCH_OP_MUL:
2336+
i128 = (int128_t)lhs.i * (int128_t)rhs.i;
2337+
goto check128;
2338+
case MATCH_OP_DIV:
2339+
if (rhs.i == 0) goto undefined;
2340+
i128 = (int128_t)lhs.i / (int128_t)rhs.i;
2341+
goto check128;
2342+
case MATCH_OP_MOD:
2343+
if (rhs.i == 0) goto undefined;
2344+
i128 = (int128_t)lhs.i % (int128_t)rhs.i;
2345+
goto check128;
23092346
case MATCH_OP_BIT_AND:
23102347
res.i = (intptr_t)((uint64_t)lhs.i & (uint64_t)rhs.i);
23112348
break;
23122349
case MATCH_OP_BIT_OR:
23132350
res.i = (intptr_t)((uint64_t)lhs.i | (uint64_t)rhs.i);
23142351
break;
2352+
case MATCH_OP_BIT_XOR:
2353+
res.i = (intptr_t)((uint64_t)lhs.i ^ (uint64_t)rhs.i);
2354+
break;
23152355
case MATCH_OP_LSHIFT:
23162356
res.i = (intptr_t)
23172357
(rhs.i <= 0? lhs.i:
@@ -2322,7 +2362,12 @@ static MatchVal matchDoEval(const MatchExpr *expr, const ELF &elf,
23222362
(rhs.i <= 0? lhs.i:
23232363
rhs.i >= 64? 0x0: (int64_t)lhs.i >> (unsigned)rhs.i);
23242364
break;
2365+
check128:
2366+
if (i128 < INTPTR_MIN || i128 > INTPTR_MAX) goto undefined;
2367+
res.i = (intptr_t)i128; break;
23252368
default:
2369+
undefined:
2370+
res.type = MATCH_TYPE_UNDEFINED;
23262371
break;
23272372
}
23282373
break;

src/e9tool/e9action.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,9 +337,13 @@ enum MatchOp
337337
MATCH_OP_NEG,
338338
MATCH_OP_ADD,
339339
MATCH_OP_SUB,
340+
MATCH_OP_MUL,
341+
MATCH_OP_DIV,
342+
MATCH_OP_MOD,
340343
MATCH_OP_BIT_NOT,
341344
MATCH_OP_BIT_AND,
342345
MATCH_OP_BIT_OR,
346+
MATCH_OP_BIT_XOR,
343347
MATCH_OP_LSHIFT,
344348
MATCH_OP_RSHIFT,
345349
};

0 commit comments

Comments
 (0)