Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support modulo operator #27

Merged
merged 1 commit into from
Nov 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/cfront.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ typedef enum {
T_close_square, /* ] */
T_asterisk, /* '*' */
T_divide, /* / */
T_mod, /* % */
T_bit_or, /* | */
T_bit_xor, /* ^ */
T_log_and, /* && */
Expand Down Expand Up @@ -338,6 +339,10 @@ token_t get_next_token()
skip_whitespace();
return T_lt;
}
if (next_char == '%') {
read_char(1);
return T_mod;
}
if (next_char == '>') {
read_char(0);
if (next_char == '=') {
Expand Down Expand Up @@ -876,6 +881,7 @@ int get_operator_prio(opcode_t op)
return 12;
case OP_mul:
case OP_div:
case OP_mod:
return 13;
default:
return 0;
Expand All @@ -893,6 +899,8 @@ opcode_t get_operator()
op = OP_mul;
else if (lex_accept(T_divide))
op = OP_div;
else if (lex_accept(T_mod))
op = OP_mod;
else if (lex_accept(T_lshift))
op = OP_lshift;
else if (lex_accept(T_rshift))
Expand Down Expand Up @@ -1357,6 +1365,7 @@ int read_numeric_sconstant()
int eval_expression_imm(opcode_t op, int op1, int op2)
{
/* return immediate result */
int tmp = op2;
int res = 0;
switch (op) {
case OP_add:
Expand All @@ -1371,6 +1380,16 @@ int eval_expression_imm(opcode_t op, int op1, int op2)
case OP_div:
res = op1 / op2;
break;
case OP_mod:
/* TODO: provide arithmetic & operation instead of '&=' */
/* TODO: do optimization for local expression */
tmp &= (tmp - 1);
if ((op2 != 0) && (tmp == 0)) {
res = op1;
res &= (op2 - 1);
} else
res = op1 % op2;
break;
case OP_lshift:
res = op1 << op2;
break;
Expand Down
9 changes: 9 additions & 0 deletions src/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ int get_code_length(ir_instr_t *ii)
case OP_func_exit:
return 16;
case OP_exit:
case OP_mod:
return 12;
case OP_load_data_address:
case OP_jz:
Expand Down Expand Up @@ -367,6 +368,14 @@ void code_generate()
if (dump_ir == 1)
printf(" x%d /= x%d", dest_reg, OP_reg);
break;
case OP_mod:
emit(__div(__AL, OP_reg + 1, OP_reg, dest_reg));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both div and mul instruction are heavier. Instead, you can add shortcut for power-of-2. That is, convert the original modulo operation into n & (d - 1) if d is power-of-2. You should implement the shortcut in src/cfront.c.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think only global expression can do this shortcut because shecc can't determine the value of operand in local expression before execution time. Can we ignore optimization for local expression in this patch?

BTW, relative issue#28 and detailed information was sent.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, let's merge this change first. Do append the comments with TODO: optimize ...

emit(__mul(__AL, OP_reg, OP_reg, OP_reg + 1));
emit(__sub_r(__AL, dest_reg, dest_reg, OP_reg));
/* TODO: support percent-sign character (%) in format string */
if (dump_ir == 1)
printf(" x%d = x%d mod x%d", dest_reg, dest_reg, OP_reg);
break;
case OP_negate:
emit(__rsb_i(__AL, dest_reg, 0, dest_reg));
if (dump_ir == 1)
Expand Down
1 change: 1 addition & 0 deletions src/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ typedef enum {
OP_sub,
OP_mul,
OP_div, /* signed division */
OP_mod, /* modulo */
OP_lshift,
OP_rshift,
OP_log_and,
Expand Down
4 changes: 2 additions & 2 deletions tests/driver.sh
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ expr 55 "1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + 10))))))))"
# expr 21 "+1+20"
# expr 10 "-15+(+35-10)"

# expr 2 "5 % 3"
# expr 6 "111 % 7"
expr 2 "5 % 3"
expr 6 "111 % 7"

expr 1 "10 > 5"
expr 1 "3+3 > 5"
Expand Down