2#include "multiarch_codegen.h"
8 {
"rax", REG_GENERAL, 8,
false}, {
"rbx", REG_GENERAL, 8,
true},
9 {
"rcx", REG_GENERAL, 8,
false}, {
"rdx", REG_GENERAL, 8,
false},
10 {
"rsi", REG_GENERAL, 8,
false}, {
"rdi", REG_GENERAL, 8,
false},
11 {
"r8", REG_GENERAL, 8,
false}, {
"r9", REG_GENERAL, 8,
false},
12 {
"r10", REG_GENERAL, 8,
false}, {
"r11", REG_GENERAL, 8,
false},
13 {
"r12", REG_GENERAL, 8,
true}, {
"r13", REG_GENERAL, 8,
true},
14 {
"r14", REG_GENERAL, 8,
true}, {
"r15", REG_GENERAL, 8,
true},
15 {
"rsp", REG_SPECIAL, 8,
true}, {
"rbp", REG_SPECIAL, 8,
true}
19 {
"xmm0", REG_FLOAT, 16,
false}, {
"xmm1", REG_FLOAT, 16,
false},
20 {
"xmm2", REG_FLOAT, 16,
false}, {
"xmm3", REG_FLOAT, 16,
false},
21 {
"xmm4", REG_FLOAT, 16,
false}, {
"xmm5", REG_FLOAT, 16,
false},
22 {
"xmm6", REG_FLOAT, 16,
false}, {
"xmm7", REG_FLOAT, 16,
false}
27 {
"x0", REG_GENERAL, 8,
false}, {
"x1", REG_GENERAL, 8,
false},
28 {
"x2", REG_GENERAL, 8,
false}, {
"x3", REG_GENERAL, 8,
false},
29 {
"x4", REG_GENERAL, 8,
false}, {
"x5", REG_GENERAL, 8,
false},
30 {
"x6", REG_GENERAL, 8,
false}, {
"x7", REG_GENERAL, 8,
false},
31 {
"x8", REG_GENERAL, 8,
false}, {
"x9", REG_GENERAL, 8,
false},
32 {
"x10", REG_GENERAL, 8,
false}, {
"x11", REG_GENERAL, 8,
false},
33 {
"x12", REG_GENERAL, 8,
false}, {
"x13", REG_GENERAL, 8,
false},
34 {
"x14", REG_GENERAL, 8,
false}, {
"x15", REG_GENERAL, 8,
false},
35 {
"x19", REG_GENERAL, 8,
true}, {
"x20", REG_GENERAL, 8,
true},
36 {
"x21", REG_GENERAL, 8,
true}, {
"x22", REG_GENERAL, 8,
true},
37 {
"x29", REG_SPECIAL, 8,
true}, {
"x30", REG_SPECIAL, 8,
true},
38 {
"sp", REG_SPECIAL, 8,
true}
42 {
"v0", REG_FLOAT, 16,
false}, {
"v1", REG_FLOAT, 16,
false},
43 {
"v2", REG_FLOAT, 16,
false}, {
"v3", REG_FLOAT, 16,
false},
44 {
"v4", REG_FLOAT, 16,
false}, {
"v5", REG_FLOAT, 16,
false},
45 {
"v6", REG_FLOAT, 16,
false}, {
"v7", REG_FLOAT, 16,
false}
49static const char *x86_64_sysv_param_regs[] = {
"rdi",
"rsi",
"rdx",
"rcx",
"r8",
"r9"};
50static const char *x86_64_sysv_return_regs[] = {
"rax",
"rdx"};
52static const char *arm64_param_regs[] = {
"x0",
"x1",
"x2",
"x3",
"x4",
"x5",
"x6",
"x7"};
53static const char *arm64_return_regs[] = {
"x0",
"x1"};
57TargetArch detect_host_architecture(
void) {
58#if defined(__x86_64__) || defined(_M_X64)
60#elif defined(__aarch64__) || defined(_M_ARM64)
67TargetPlatform detect_host_platform(
void) {
69 return PLATFORM_LINUX;
70#elif defined(__APPLE__)
71 return PLATFORM_MACOS;
73 return PLATFORM_UNKNOWN;
77TargetConfig *target_config_create(TargetArch arch, TargetPlatform platform) {
79 if (!config)
return NULL;
82 config->platform = platform;
87 config->arch_name =
"x86_64";
88 config->pointer_size = 8;
89 config->stack_alignment = 16;
90 config->general_regs = x86_64_general_regs;
91 config->float_regs = x86_64_float_regs;
92 config->num_general_regs =
sizeof(x86_64_general_regs) /
sizeof(
RegisterInfo);
93 config->num_float_regs =
sizeof(x86_64_float_regs) /
sizeof(
RegisterInfo);
94 config->calling_conv = CALL_CONV_SYSV;
95 config->param_regs = x86_64_sysv_param_regs;
96 config->return_regs = x86_64_sysv_return_regs;
97 config->num_param_regs = 6;
98 config->num_return_regs = 2;
99 config->syscall_reg =
"rax";
100 config->syscall_instruction =
"syscall";
101 config->comment_prefix =
"#";
102 config->att_syntax =
true;
106 config->arch_name =
"arm64";
107 config->pointer_size = 8;
108 config->stack_alignment = 16;
109 config->general_regs = arm64_general_regs;
110 config->float_regs = arm64_float_regs;
111 config->num_general_regs =
sizeof(arm64_general_regs) /
sizeof(
RegisterInfo);
112 config->num_float_regs =
sizeof(arm64_float_regs) /
sizeof(
RegisterInfo);
113 config->calling_conv = CALL_CONV_AARCH64;
114 config->param_regs = arm64_param_regs;
115 config->return_regs = arm64_return_regs;
116 config->num_param_regs = 8;
117 config->num_return_regs = 2;
118 config->syscall_reg =
"x8";
119 config->syscall_instruction =
"svc #0";
120 config->comment_prefix =
"//";
121 config->att_syntax =
false;
132 config->platform_name =
"linux";
133 config->global_directive =
".globl";
134 config->section_text =
".text";
135 config->section_data =
".data";
139 config->platform_name =
"macos";
140 config->global_directive =
".globl";
141 config->section_text =
".text";
142 config->section_data =
".data";
162MultiArchCodegen *multiarch_codegen_create(
const char *output_file, TargetArch arch, TargetPlatform platform) {
164 if (!codegen)
return NULL;
166 codegen->output_file = fopen(output_file,
"w");
167 if (!codegen->output_file) {
172 codegen->target = target_config_create(arch, platform);
173 if (!codegen->target) {
174 fclose(codegen->output_file);
179 codegen->label_counter = 0;
180 codegen->temp_counter = 0;
181 codegen->current_function_locals = 0;
182 codegen->stack_offset = 0;
183 codegen->local_var_count = 0;
184 codegen->in_function =
false;
185 codegen->stack_size = 0;
192 if (codegen->output_file) {
193 fclose(codegen->output_file);
195 target_config_destroy(codegen->target);
202 va_start(args, format);
203 vfprintf(codegen->output_file, format, args);
205 fprintf(codegen->output_file,
"\n");
208void multiarch_emit_comment(
MultiArchCodegen *codegen,
const char *comment) {
209 multiarch_emit(codegen,
"%s %s", codegen->target->comment_prefix, comment);
213 multiarch_emit(codegen,
"%s:", label);
216void multiarch_emit_directive(
MultiArchCodegen *codegen,
const char *directive,
const char *args) {
218 multiarch_emit(codegen,
"%s %s", directive, args);
220 multiarch_emit(codegen,
"%s", directive);
226void multiarch_load_immediate(
MultiArchCodegen *codegen,
const char *dest_reg,
long value) {
227 switch (codegen->target->arch) {
229 multiarch_emit(codegen,
" movq $%ld, %%%s", value, dest_reg);
232 if (value >= 0 && value < 65536) {
233 multiarch_emit(codegen,
" mov %s, #%ld", dest_reg, value);
235 multiarch_emit(codegen,
" mov %s, #%ld", dest_reg, value & 0xFFFF);
237 multiarch_emit(codegen,
" movk %s, #%ld, lsl #16", dest_reg, (value >> 16) & 0xFFFF);
239 if (value > 0xFFFFFFFF) {
240 multiarch_emit(codegen,
" movk %s, #%ld, lsl #32", dest_reg, (value >> 32) & 0xFFFF);
241 multiarch_emit(codegen,
" movk %s, #%ld, lsl #48", dest_reg, (value >> 48) & 0xFFFF);
250void multiarch_add(
MultiArchCodegen *codegen,
const char *dest,
const char *src1,
const char *src2) {
251 switch (codegen->target->arch) {
253 if (strcmp(dest, src1) == 0) {
254 multiarch_emit(codegen,
" addq %%%s, %%%s", src2, dest);
256 multiarch_emit(codegen,
" movq %%%s, %%%s", src1, dest);
257 multiarch_emit(codegen,
" addq %%%s, %%%s", src2, dest);
261 multiarch_emit(codegen,
" add %s, %s, %s", dest, src1, src2);
268void multiarch_sub(
MultiArchCodegen *codegen,
const char *dest,
const char *src1,
const char *src2) {
269 switch (codegen->target->arch) {
271 if (strcmp(dest, src1) == 0) {
272 multiarch_emit(codegen,
" subq %%%s, %%%s", src2, dest);
274 multiarch_emit(codegen,
" movq %%%s, %%%s", src1, dest);
275 multiarch_emit(codegen,
" subq %%%s, %%%s", src2, dest);
279 multiarch_emit(codegen,
" sub %s, %s, %s", dest, src1, src2);
286void multiarch_mul(
MultiArchCodegen *codegen,
const char *dest,
const char *src1,
const char *src2) {
287 switch (codegen->target->arch) {
289 if (strcmp(dest, src1) == 0) {
290 multiarch_emit(codegen,
" imulq %%%s, %%%s", src2, dest);
292 multiarch_emit(codegen,
" movq %%%s, %%%s", src1, dest);
293 multiarch_emit(codegen,
" imulq %%%s, %%%s", src2, dest);
297 multiarch_emit(codegen,
" mul %s, %s, %s", dest, src1, src2);
304void multiarch_div(
MultiArchCodegen *codegen,
const char *dest,
const char *src1,
const char *src2) {
305 switch (codegen->target->arch) {
308 multiarch_emit(codegen,
" movq %%%s, %%rax", src1);
309 multiarch_emit(codegen,
" cqo");
310 multiarch_emit(codegen,
" idivq %%%s", src2);
311 if (strcmp(dest,
"rax") != 0) {
312 multiarch_emit(codegen,
" movq %%rax, %%%s", dest);
316 multiarch_emit(codegen,
" sdiv %s, %s, %s", dest, src1, src2);
323void multiarch_compare(
MultiArchCodegen *codegen,
const char *reg1,
const char *reg2) {
324 switch (codegen->target->arch) {
326 multiarch_emit(codegen,
" cmpq %%%s, %%%s", reg2, reg1);
329 multiarch_emit(codegen,
" cmp %s, %s", reg1, reg2);
337 switch (codegen->target->arch) {
339 multiarch_emit(codegen,
" jmp %s", label);
342 multiarch_emit(codegen,
" b %s", label);
350 switch (codegen->target->arch) {
352 multiarch_emit(codegen,
" jz %s", label);
355 multiarch_emit(codegen,
" b.eq %s", label);
363 multiarch_jump_if_zero(codegen, label);
366void multiarch_jump_if_not_equal(
MultiArchCodegen *codegen,
const char *label) {
367 switch (codegen->target->arch) {
369 multiarch_emit(codegen,
" jnz %s", label);
372 multiarch_emit(codegen,
" b.ne %s", label);
380 switch (codegen->target->arch) {
382 multiarch_emit(codegen,
" jl %s", label);
385 multiarch_emit(codegen,
" b.lt %s", label);
392void multiarch_jump_if_greater(
MultiArchCodegen *codegen,
const char *label) {
393 switch (codegen->target->arch) {
395 multiarch_emit(codegen,
" jg %s", label);
398 multiarch_emit(codegen,
" b.gt %s", label);
405void multiarch_function_prologue(
MultiArchCodegen *codegen,
const char *func_name,
int param_count) {
406 codegen->in_function =
true;
407 strncpy(codegen->current_function, func_name,
sizeof(codegen->current_function) - 1);
408 codegen->local_var_count = 0;
409 codegen->stack_offset = 0;
412 if (codegen->target->platform == PLATFORM_MACOS) {
413 multiarch_emit_label(codegen, func_name);
415 multiarch_emit_label(codegen, func_name);
418 switch (codegen->target->arch) {
420 multiarch_emit(codegen,
" pushq %%rbp");
421 multiarch_emit(codegen,
" movq %%rsp, %%rbp");
425 multiarch_emit(codegen,
" stp x29, x30, [sp, #-16]!");
426 multiarch_emit(codegen,
" mov x29, sp");
434 switch (codegen->target->arch) {
436 multiarch_emit(codegen,
" movq %%rbp, %%rsp");
437 multiarch_emit(codegen,
" popq %%rbp");
438 multiarch_emit(codegen,
" ret");
441 multiarch_emit(codegen,
" ldp x29, x30, [sp], #16");
442 multiarch_emit(codegen,
" ret");
448 codegen->in_function =
false;
454 multiarch_load_immediate(codegen, multiarch_get_return_reg(codegen), 0);
456 multiarch_function_epilogue(codegen);
459void multiarch_function_call(
MultiArchCodegen *codegen,
const char *func_name,
int arg_count) {
460 switch (codegen->target->arch) {
463 multiarch_emit(codegen,
" call %s", func_name);
466 int stack_cleanup = (arg_count - 6) * 8;
467 multiarch_emit(codegen,
" addq $%d, %%rsp", stack_cleanup);
471 multiarch_emit(codegen,
" bl %s", func_name);
479 switch (codegen->target->arch) {
481 multiarch_emit(codegen,
" pushq %%%s", reg);
484 multiarch_emit(codegen,
" str %s, [sp, #-16]!", reg);
492 switch (codegen->target->arch) {
494 multiarch_emit(codegen,
" popq %%%s", reg);
497 multiarch_emit(codegen,
" ldr %s, [sp], #16", reg);
504const char *multiarch_get_param_reg(
MultiArchCodegen *codegen,
int param_index) {
505 if (param_index < codegen->target->num_param_regs) {
506 return codegen->target->param_regs[param_index];
512 return codegen->target->return_regs[0];
516 switch (codegen->target->arch) {
519 case 0:
return "r10";
520 case 1:
return "r11";
521 default:
return "rax";
526 case 1:
return "x10";
527 case 2:
return "x11";
528 default:
return "x0";
536 switch (codegen->target->arch) {
547 switch (codegen->target->arch) {
557void multiarch_load_memory(
MultiArchCodegen *codegen,
const char *dest_reg,
const char *src_addr,
int size) {
558 switch (codegen->target->arch) {
561 multiarch_emit(codegen,
" movq %s, %%%s", src_addr, dest_reg);
562 }
else if (size == 4) {
563 multiarch_emit(codegen,
" movl %s, %%%s", src_addr, dest_reg);
564 }
else if (size == 1) {
565 multiarch_emit(codegen,
" movb %s, %%%s", src_addr, dest_reg);
570 multiarch_emit(codegen,
" ldr %s, %s", dest_reg, src_addr);
571 }
else if (size == 4) {
572 multiarch_emit(codegen,
" ldr w%s, %s", dest_reg + 1, src_addr);
573 }
else if (size == 1) {
574 multiarch_emit(codegen,
" ldrb w%s, %s", dest_reg + 1, src_addr);
582void multiarch_store_memory(
MultiArchCodegen *codegen,
const char *src_reg,
const char *dest_addr,
int size) {
583 switch (codegen->target->arch) {
586 multiarch_emit(codegen,
" movq %%%s, %s", src_reg, dest_addr);
587 }
else if (size == 4) {
588 multiarch_emit(codegen,
" movl %%%s, %s", src_reg, dest_addr);
589 }
else if (size == 1) {
590 multiarch_emit(codegen,
" movb %%%s, %s", src_reg, dest_addr);
595 multiarch_emit(codegen,
" str %s, %s", src_reg, dest_addr);
596 }
else if (size == 4) {
597 multiarch_emit(codegen,
" str w%s, %s", src_reg + 1, dest_addr);
598 }
else if (size == 1) {
599 multiarch_emit(codegen,
" strb w%s, %s", src_reg + 1, dest_addr);
607void multiarch_syscall(
MultiArchCodegen *codegen,
int syscall_num,
int arg_count) {
608 multiarch_load_immediate(codegen, codegen->target->syscall_reg, syscall_num);
609 multiarch_emit(codegen,
" %s", codegen->target->syscall_instruction);
613 const char *return_reg = multiarch_get_return_reg(codegen);
614 multiarch_load_immediate(codegen, return_reg, exit_code);
616 switch (codegen->target->platform) {
618 if (codegen->target->arch == ARCH_X86_64) {
619 multiarch_syscall(codegen, 60, 1);
620 }
else if (codegen->target->arch == ARCH_ARM64) {
621 multiarch_syscall(codegen, 93, 1);
625 if (codegen->target->arch == ARCH_X86_64) {
626 multiarch_syscall(codegen, 0x2000001, 1);
627 }
else if (codegen->target->arch == ARCH_ARM64) {
628 multiarch_syscall(codegen, 1, 1);
637 char *label = malloc(32);
638 snprintf(label, 32,
"L%d", codegen->label_counter++);
643 char *temp = malloc(32);
644 snprintf(temp, 32,
"t%d", codegen->temp_counter++);
648void multiarch_declare_local_var(
MultiArchCodegen *codegen,
const char *name,
int size) {
649 if (codegen->local_var_count >= 256)
return;
652 int alignment = (size >= 8) ? 8 : size;
653 codegen->stack_offset = (codegen->stack_offset + alignment - 1) & ~(alignment - 1);
654 codegen->stack_offset += size;
657 strncpy(codegen->local_vars[codegen->local_var_count].name, name, 63);
658 codegen->local_vars[codegen->local_var_count].name[63] =
'\0';
659 codegen->local_vars[codegen->local_var_count].offset = -codegen->stack_offset;
660 codegen->local_vars[codegen->local_var_count].size = size;
661 codegen->local_var_count++;
664int multiarch_get_local_var_offset(
MultiArchCodegen *codegen,
const char *name) {
665 for (
int i = 0; i < codegen->local_var_count; i++) {
666 if (strcmp(codegen->local_vars[i].name, name) == 0) {
667 return codegen->local_vars[i].offset;
673void multiarch_load_local_var(
MultiArchCodegen *codegen,
const char *dest_reg,
const char *var_name) {
674 int offset = multiarch_get_local_var_offset(codegen, var_name);
675 const char *fp = multiarch_get_frame_pointer(codegen);
677 switch (codegen->target->arch) {
679 multiarch_emit(codegen,
" movq %d(%%%s), %%%s", offset, fp, dest_reg);
682 multiarch_emit(codegen,
" ldr %s, [%s, #%d]", dest_reg, fp, offset);
689void multiarch_store_local_var(
MultiArchCodegen *codegen,
const char *src_reg,
const char *var_name) {
690 int offset = multiarch_get_local_var_offset(codegen, var_name);
691 const char *fp = multiarch_get_frame_pointer(codegen);
693 switch (codegen->target->arch) {
695 multiarch_emit(codegen,
" movq %%%s, %d(%%%s)", src_reg, offset, fp);
698 multiarch_emit(codegen,
" str %s, [%s, #%d]", src_reg, fp, offset);
708 if (!codegen || !ast)
return false;
711 multiarch_emit_comment(codegen,
"Generated by KCC Multi-Architecture Compiler");
712 multiarch_emit_comment(codegen,
"Target: %s-%s", codegen->target->arch_name, codegen->target->platform_name);
713 multiarch_emit(codegen,
"");
716 multiarch_emit_directive(codegen, codegen->target->section_text, NULL);
717 multiarch_emit(codegen,
"");
720 multiarch_codegen_program(codegen, ast);
723 if (codegen->target->platform == PLATFORM_LINUX) {
724 multiarch_emit(codegen,
"");
725 multiarch_emit_directive(codegen, codegen->target->global_directive,
"_start");
726 multiarch_emit_label(codegen,
"_start");
727 multiarch_function_call(codegen,
"main", 0);
728 multiarch_exit_program(codegen, 0);
729 }
else if (codegen->target->platform == PLATFORM_MACOS) {
730 multiarch_emit(codegen,
"");
731 multiarch_emit_directive(codegen, codegen->target->global_directive,
"_main");
739 if (node->type != AST_PROGRAM)
return;
741 for (
int i = 0; i < node->data.program.declaration_count; i++) {
742 struct ASTNode *decl = node->data.program.declarations[i];
744 if (decl->type == AST_FUNCTION_DECL) {
745 multiarch_codegen_function_declaration(codegen, decl);
746 }
else if (decl->type == AST_VAR_DECL) {
747 multiarch_codegen_variable_declaration(codegen, decl);
753 if (node->type != AST_FUNCTION_DECL)
return;
755 multiarch_emit(codegen,
"");
756 multiarch_emit_comment(codegen,
"Function: %s", node->data.function_decl.name);
759 if (strcmp(node->data.function_decl.name,
"main") == 0) {
760 if (codegen->target->platform == PLATFORM_MACOS) {
761 multiarch_emit_directive(codegen, codegen->target->global_directive,
"_main");
763 multiarch_emit_directive(codegen, codegen->target->global_directive,
"main");
767 multiarch_function_prologue(codegen, node->data.function_decl.name, node->data.function_decl.parameter_count);
770 if (codegen->stack_offset > 0) {
771 multiarch_stack_alloc(codegen, codegen->stack_offset);
775 if (node->data.function_decl.body) {
776 multiarch_codegen_statement(codegen, node->data.function_decl.body);
780 multiarch_function_return(codegen,
false);
784 if (node->type != AST_VAR_DECL)
return;
786 multiarch_emit_comment(codegen,
"Variable: %s", node->data.var_decl.name);
789 if (codegen->in_function) {
791 multiarch_declare_local_var(codegen, node->data.var_decl.name, size);
793 if (node->data.var_decl.initializer) {
795 multiarch_codegen_expression(codegen, node->data.var_decl.initializer);
797 multiarch_store_local_var(codegen, multiarch_get_return_reg(codegen), node->data.var_decl.name);
803 switch (node->type) {
804 case AST_COMPOUND_STMT:
805 for (
int i = 0; i < node->data.compound_stmt.statement_count; i++) {
806 multiarch_codegen_statement(codegen, node->data.compound_stmt.statements[i]);
810 case AST_EXPRESSION_STMT:
811 if (node->data.expression_stmt.expression) {
812 multiarch_codegen_expression(codegen, node->data.expression_stmt.expression);
816 case AST_RETURN_STMT:
817 multiarch_codegen_return_stmt(codegen, node);
821 multiarch_codegen_if_stmt(codegen, node);
825 multiarch_codegen_while_stmt(codegen, node);
829 multiarch_codegen_variable_declaration(codegen, node);
833 multiarch_emit_comment(codegen,
"Unsupported statement type");
839 switch (node->type) {
841 multiarch_load_immediate(codegen, multiarch_get_return_reg(codegen), node->data.number.value);
845 multiarch_load_local_var(codegen, multiarch_get_return_reg(codegen), node->data.identifier.name);
848 case AST_BINARY_EXPR:
849 multiarch_codegen_binary_expr(codegen, node);
853 multiarch_codegen_call_expr(codegen, node);
857 multiarch_emit_comment(codegen,
"Unsupported expression type");
863 if (node->type != AST_BINARY_EXPR)
return;
866 multiarch_codegen_expression(codegen, node->data.binary_expr.left);
867 multiarch_push(codegen, multiarch_get_return_reg(codegen));
870 multiarch_codegen_expression(codegen, node->data.binary_expr.right);
871 const char *right_reg = multiarch_get_return_reg(codegen);
872 const char *temp_reg = multiarch_get_temp_reg(codegen, 0);
873 multiarch_pop(codegen, temp_reg);
876 switch (node->data.binary_expr.operator) {
878 multiarch_add(codegen, right_reg, temp_reg, right_reg);
881 multiarch_sub(codegen, right_reg, temp_reg, right_reg);
884 multiarch_mul(codegen, right_reg, temp_reg, right_reg);
887 multiarch_div(codegen, right_reg, temp_reg, right_reg);
890 multiarch_emit_comment(codegen,
"Unsupported binary operator");
896 if (node->data.return_stmt.expression) {
897 multiarch_codegen_expression(codegen, node->data.return_stmt.expression);
899 multiarch_function_return(codegen, node->data.return_stmt.expression != NULL);
903 if (node->type != AST_CALL_EXPR)
return;
906 for (
int i = 0; i < node->data.call_expr.argument_count && i < codegen->target->num_param_regs; i++) {
907 multiarch_codegen_expression(codegen, node->data.call_expr.arguments[i]);
908 const char *param_reg = multiarch_get_param_reg(codegen, i);
909 const char *return_reg = multiarch_get_return_reg(codegen);
911 if (strcmp(param_reg, return_reg) != 0) {
913 switch (codegen->target->arch) {
915 multiarch_emit(codegen,
" movq %%%s, %%%s", return_reg, param_reg);
918 multiarch_emit(codegen,
" mov %s, %s", param_reg, return_reg);
926 multiarch_function_call(codegen, node->data.call_expr.function_name, node->data.call_expr.argument_count);
930 if (node->type != AST_IF_STMT)
return;
932 char *else_label = multiarch_new_label(codegen);
933 char *end_label = multiarch_new_label(codegen);
936 multiarch_codegen_expression(codegen, node->data.if_stmt.condition);
939 const char *return_reg = multiarch_get_return_reg(codegen);
940 switch (codegen->target->arch) {
942 multiarch_emit(codegen,
" testq %%%s, %%%s", return_reg, return_reg);
945 multiarch_emit(codegen,
" cmp %s, #0", return_reg);
951 multiarch_jump_if_zero(codegen, else_label);
954 multiarch_codegen_statement(codegen, node->data.if_stmt.then_stmt);
955 multiarch_jump(codegen, end_label);
958 multiarch_emit_label(codegen, else_label);
959 if (node->data.if_stmt.else_stmt) {
960 multiarch_codegen_statement(codegen, node->data.if_stmt.else_stmt);
963 multiarch_emit_label(codegen, end_label);
970 if (node->type != AST_WHILE_STMT)
return;
972 char *loop_label = multiarch_new_label(codegen);
973 char *end_label = multiarch_new_label(codegen);
975 multiarch_emit_label(codegen, loop_label);
978 multiarch_codegen_expression(codegen, node->data.while_stmt.condition);
981 const char *return_reg = multiarch_get_return_reg(codegen);
982 switch (codegen->target->arch) {
984 multiarch_emit(codegen,
" testq %%%s, %%%s", return_reg, return_reg);
987 multiarch_emit(codegen,
" cmp %s, #0", return_reg);
993 multiarch_jump_if_zero(codegen, end_label);
996 multiarch_codegen_statement(codegen, node->data.while_stmt.body);
997 multiarch_jump(codegen, loop_label);
999 multiarch_emit_label(codegen, end_label);
1007 bytes = (bytes + codegen->target->stack_alignment - 1) & ~(codegen->target->stack_alignment - 1);
1009 switch (codegen->target->arch) {
1011 multiarch_emit(codegen,
" subq $%d, %%rsp", bytes);
1014 multiarch_emit(codegen,
" sub sp, sp, #%d", bytes);
1023 bytes = (bytes + codegen->target->stack_alignment - 1) & ~(codegen->target->stack_alignment - 1);
1025 switch (codegen->target->arch) {
1027 multiarch_emit(codegen,
" addq $%d, %%rsp", bytes);
1030 multiarch_emit(codegen,
" add sp, sp, #%d", bytes);