diff options
| -rw-r--r-- | codegen.c | 47 | ||||
| -rw-r--r-- | parse.c | 3 | ||||
| -rw-r--r-- | preprocess.c | 28 | ||||
| -rw-r--r-- | tests/041.sh | 18 |
4 files changed, 75 insertions, 21 deletions
@@ -196,30 +196,43 @@ void codegen_binary_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) { printf(" push rax\n"); } -void codegen_assign_expr(CodeGen* g, AstNode* ast) { - int sizeof_lhs = type_sizeof(ast->node_lhs->ty); - int sizeof_rhs = type_sizeof(ast->node_rhs->ty); - - codegen_expr(g, ast->node_lhs, GenMode_lval); - codegen_expr(g, ast->node_rhs, GenMode_rval); +void codegen_assign_expr_helper(CodeGen* g, AstNode* ast) { if (ast->node_op == TokenKind_assign) { - } else if (ast->node_op == TokenKind_assign_add) { - printf(" pop rdi\n"); - printf(" push [rsp]\n"); - codegen_lval2rval(ast->node_lhs->ty); - printf(" pop rax\n"); + return; + } + + printf(" pop rdi\n"); + printf(" push [rsp]\n"); + codegen_lval2rval(ast->node_lhs->ty); + printf(" pop rax\n"); + + if (ast->node_op == TokenKind_assign_add) { printf(" add rax, rdi\n"); - printf(" push rax\n"); } else if (ast->node_op == TokenKind_assign_sub) { - printf(" pop rdi\n"); - printf(" push [rsp]\n"); - codegen_lval2rval(ast->node_lhs->ty); - printf(" pop rax\n"); printf(" sub rax, rdi\n"); - printf(" push rax\n"); + } else if (ast->node_op == TokenKind_assign_mul) { + printf(" imul rax, rdi\n"); + } else if (ast->node_op == TokenKind_assign_div) { + printf(" cqo\n"); + printf(" idiv rdi\n"); + } else if (ast->node_op == TokenKind_assign_mod) { + printf(" cqo\n"); + printf(" idiv rdi\n"); + printf(" mov rax, rdx\n"); } else { unreachable(); } + + printf(" push rax\n"); +} + +void codegen_assign_expr(CodeGen* g, AstNode* ast) { + int sizeof_lhs = type_sizeof(ast->node_lhs->ty); + int sizeof_rhs = type_sizeof(ast->node_rhs->ty); + + codegen_expr(g, ast->node_lhs, GenMode_lval); + codegen_expr(g, ast->node_rhs, GenMode_rval); + codegen_assign_expr_helper(g, ast); if (sizeof_lhs == 1) { printf(" pop rdi\n"); printf(" pop rax\n"); @@ -651,7 +651,8 @@ AstNode* parse_assignment_expr(Parser* p) { AstNode* rhs; while (1) { TokenKind op = peek_token(p)->kind; - if (op == TokenKind_assign) { + if (op == TokenKind_assign || op == TokenKind_assign_mul || op == TokenKind_assign_div || + op == TokenKind_assign_mod) { next_token(p); rhs = parse_logical_or_expr(p); lhs = ast_new_assign_expr(op, lhs, rhs); diff --git a/preprocess.c b/preprocess.c index b7e52bf..c4b1c16 100644 --- a/preprocess.c +++ b/preprocess.c @@ -13,6 +13,9 @@ enum TokenKind { TokenKind_arrow, TokenKind_assign, TokenKind_assign_add, + TokenKind_assign_div, + TokenKind_assign_mod, + TokenKind_assign_mul, TokenKind_assign_sub, TokenKind_brace_l, TokenKind_brace_r, @@ -111,6 +114,12 @@ const char* token_kind_stringify(TokenKind k) { return "="; else if (k == TokenKind_assign_add) return "+="; + else if (k == TokenKind_assign_div) + return "/="; + else if (k == TokenKind_assign_mod) + return "%="; + else if (k == TokenKind_assign_mul) + return "*="; else if (k == TokenKind_assign_sub) return "-="; else if (k == TokenKind_brace_l) @@ -493,9 +502,17 @@ void pp_tokenize_all(Preprocessor* pp) { tok->kind = TokenKind_minus; } } else if (c == '*') { - tok->kind = TokenKind_star; + if (pp->src[pp->pos] == '=') { + ++pp->pos; + tok->kind = TokenKind_assign_mul; + } else { + tok->kind = TokenKind_star; + } } else if (c == '/') { - if (pp->src[pp->pos] == '/') { + if (pp->src[pp->pos] == '=') { + ++pp->pos; + tok->kind = TokenKind_assign_div; + } else if (pp->src[pp->pos] == '/') { start = pp->pos - 1; ++pp->pos; while (pp->src[pp->pos] && pp->src[pp->pos] != '\n' && pp->src[pp->pos] != '\r') { @@ -524,7 +541,12 @@ void pp_tokenize_all(Preprocessor* pp) { tok->kind = TokenKind_slash; } } else if (c == '%') { - tok->kind = TokenKind_percent; + if (pp->src[pp->pos] == '=') { + ++pp->pos; + tok->kind = TokenKind_assign_mod; + } else { + tok->kind = TokenKind_percent; + } } else if (c == '.') { if (pp->src[pp->pos] == '.') { ++pp->pos; diff --git a/tests/041.sh b/tests/041.sh index b4bb21e..d409158 100644 --- a/tests/041.sh +++ b/tests/041.sh @@ -13,6 +13,12 @@ cat <<'EOF' > expected 2 1 0 + +56088 + +24 + +3 EOF bash ../../test_diff.sh <<'EOF' int printf(); @@ -27,6 +33,18 @@ int main() { printf("%d\n", i); } + int x = 123; + x *= 456; + printf("\n%d\n", x); + + int y = 120; + y /= 5; + printf("\n%d\n", y); + + int z = 17; + z %= 7; + printf("\n%d\n", z); + return 0; } EOF |
