aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--codegen.c47
-rw-r--r--parse.c3
-rw-r--r--preprocess.c28
-rw-r--r--tests/041.sh18
4 files changed, 75 insertions, 21 deletions
diff --git a/codegen.c b/codegen.c
index 796dd14..f3790d2 100644
--- a/codegen.c
+++ b/codegen.c
@@ -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");
diff --git a/parse.c b/parse.c
index 67103c7..820d3e2 100644
--- a/parse.c
+++ b/parse.c
@@ -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