aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/codegen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen.c')
-rw-r--r--src/codegen.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/codegen.c b/src/codegen.c
index 000126b..dccabe4 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -134,6 +134,46 @@ static void codegen_deref_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) {
}
}
+static void codegen_cast_expr(CodeGen* g, AstNode* ast) {
+ codegen_expr(g, ast->node_operand, GenMode_rval);
+
+ int src_size = type_sizeof(ast->node_operand->ty);
+ int dst_size = type_sizeof(ast->ty);
+
+ if (src_size == dst_size)
+ return;
+
+ fprintf(g->out, " pop rax\n");
+
+ if (dst_size == 1) {
+ fprintf(g->out, " movsx rax, al\n");
+ } else if (dst_size == 2) {
+ if (src_size == 1) {
+ fprintf(g->out, " movsx rax, al\n");
+ } else {
+ fprintf(g->out, " movsx rax, ax\n");
+ }
+ } else if (dst_size == 4) {
+ if (src_size == 1) {
+ fprintf(g->out, " movsx rax, al\n");
+ } else if (src_size == 2) {
+ fprintf(g->out, " movsx rax, ax\n");
+ } else {
+ fprintf(g->out, " movsxd rax, eax\n");
+ }
+ } else if (dst_size == 8) {
+ if (src_size == 1) {
+ fprintf(g->out, " movsx rax, al\n");
+ } else if (src_size == 2) {
+ fprintf(g->out, " movsx rax, ax\n");
+ } else if (src_size == 4) {
+ fprintf(g->out, " movsxd rax, eax\n");
+ }
+ }
+
+ fprintf(g->out, " push rax\n");
+}
+
static void codegen_logical_expr(CodeGen* g, AstNode* ast) {
int label = codegen_new_label(g);
@@ -406,6 +446,8 @@ static void codegen_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) {
codegen_ref_expr(g, ast, gen_mode);
} else if (ast->kind == AstNodeKind_deref_expr) {
codegen_deref_expr(g, ast, gen_mode);
+ } else if (ast->kind == AstNodeKind_cast_expr) {
+ codegen_cast_expr(g, ast);
} else if (ast->kind == AstNodeKind_binary_expr) {
codegen_binary_expr(g, ast, gen_mode);
} else if (ast->kind == AstNodeKind_cond_expr) {