aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/codegen.c
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-03 16:46:10 +0900
committernsfisis <nsfisis@gmail.com>2026-05-03 16:46:10 +0900
commit1b406b13b03055d2b2d08e8279a4a80c41ca7c20 (patch)
treebe9ed42948eda98add8eab24016ee015bf0389a7 /src/codegen.c
parent6e9ffa7cf08c83853e2fe84555d35eeaaf84e4f0 (diff)
downloadducc-1b406b13b03055d2b2d08e8279a4a80c41ca7c20.tar.gz
ducc-1b406b13b03055d2b2d08e8279a4a80c41ca7c20.tar.zst
ducc-1b406b13b03055d2b2d08e8279a4a80c41ca7c20.zip
fix: div/mod/shift operations on unsigned integers
Diffstat (limited to 'src/codegen.c')
-rw-r--r--src/codegen.c49
1 files changed, 38 insertions, 11 deletions
diff --git a/src/codegen.c b/src/codegen.c
index 2da6851..10a0287 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -205,11 +205,21 @@ static void codegen_binary_expr(CodeGen* g, BinaryExprNode* expr, GenMode gen_mo
} else if (expr->op == TokenKind_star) {
fprintf(g->out, " imul rax, rdi\n");
} else if (expr->op == TokenKind_slash) {
- fprintf(g->out, " cqo\n");
- fprintf(g->out, " idiv rdi\n");
+ if (type_is_unsigned(expr->lhs->ty)) {
+ fprintf(g->out, " xor rdx, rdx\n");
+ fprintf(g->out, " div rdi\n");
+ } else {
+ fprintf(g->out, " cqo\n");
+ fprintf(g->out, " idiv rdi\n");
+ }
} else if (expr->op == TokenKind_percent) {
- fprintf(g->out, " cqo\n");
- fprintf(g->out, " idiv rdi\n");
+ if (type_is_unsigned(expr->lhs->ty)) {
+ fprintf(g->out, " xor rdx, rdx\n");
+ fprintf(g->out, " div rdi\n");
+ } else {
+ fprintf(g->out, " cqo\n");
+ fprintf(g->out, " idiv rdi\n");
+ }
fprintf(g->out, " mov rax, rdx\n");
} else if (expr->op == TokenKind_and) {
fprintf(g->out, " and rax, rdi\n");
@@ -221,9 +231,12 @@ static void codegen_binary_expr(CodeGen* g, BinaryExprNode* expr, GenMode gen_mo
fprintf(g->out, " mov rcx, rdi\n");
fprintf(g->out, " shl rax, cl\n");
} else if (expr->op == TokenKind_rshift) {
- // TODO: check if the operand is signed or unsigned
fprintf(g->out, " mov rcx, rdi\n");
- fprintf(g->out, " sar rax, cl\n");
+ if (type_is_unsigned(expr->lhs->ty)) {
+ fprintf(g->out, " shr rax, cl\n");
+ } else {
+ fprintf(g->out, " sar rax, cl\n");
+ }
} else if (expr->op == TokenKind_eq) {
fprintf(g->out, " cmp rax, rdi\n");
fprintf(g->out, " sete al\n");
@@ -274,11 +287,21 @@ static void codegen_assign_expr_helper(CodeGen* g, AssignExprNode* expr) {
} else if (expr->op == TokenKind_assign_mul) {
fprintf(g->out, " imul rax, rdi\n");
} else if (expr->op == TokenKind_assign_div) {
- fprintf(g->out, " cqo\n");
- fprintf(g->out, " idiv rdi\n");
+ if (type_is_unsigned(expr->lhs->ty)) {
+ fprintf(g->out, " xor rdx, rdx\n");
+ fprintf(g->out, " div rdi\n");
+ } else {
+ fprintf(g->out, " cqo\n");
+ fprintf(g->out, " idiv rdi\n");
+ }
} else if (expr->op == TokenKind_assign_mod) {
- fprintf(g->out, " cqo\n");
- fprintf(g->out, " idiv rdi\n");
+ if (type_is_unsigned(expr->lhs->ty)) {
+ fprintf(g->out, " xor rdx, rdx\n");
+ fprintf(g->out, " div rdi\n");
+ } else {
+ fprintf(g->out, " cqo\n");
+ fprintf(g->out, " idiv rdi\n");
+ }
fprintf(g->out, " mov rax, rdx\n");
} else if (expr->op == TokenKind_assign_or) {
fprintf(g->out, " or rax, rdi\n");
@@ -291,7 +314,11 @@ static void codegen_assign_expr_helper(CodeGen* g, AssignExprNode* expr) {
fprintf(g->out, " shl rax, cl\n");
} else if (expr->op == TokenKind_assign_rshift) {
fprintf(g->out, " mov rcx, rdi\n");
- fprintf(g->out, " sar rax, cl\n");
+ if (type_is_unsigned(expr->lhs->ty)) {
+ fprintf(g->out, " shr rax, cl\n");
+ } else {
+ fprintf(g->out, " sar rax, cl\n");
+ }
} else {
unreachable();
}