#include "bf_compiler.h" #include #include #include static void fwrite_str(char *str, FILE *f) { fwrite(str, strlen(str), 1, f); } static void fwrite_str_line(char *str, FILE *f) { fwrite_str(str, f); fwrite_str("\n", f); } static int bf_compiler_compile_nasm(struct bf_compiler *compiler, const char *output_filename, const char *program, size_t program_len) { int rc = -1; FILE *f = NULL; if (compiler->cell_size != 8) { return -1; } // TODO: Write to temp directory f = fopen("tmp.asm", "w"); if (!f) { goto err; } fwrite_str_line("section .bss", f); char data_define[128] = { 0 }; snprintf(data_define, sizeof(data_define), "data resb %d", compiler->data_len); fwrite_str_line(data_define, f); fwrite_str_line("section .text", f); fwrite_str_line("global _start", f); fwrite_str_line("_start:", f); fwrite_str_line("mov bl, 0", f); uint32_t loop_stack[128] = { 0 }; uint32_t loop_stack_len = 0; uint32_t last_loop_index = 0; for (int i = 0; i < program_len; i++) { char inst = program[i]; if (inst == '>') { fwrite_str_line("; >", f); fwrite_str_line("inc bl", f); } else if (inst == '<') { fwrite_str_line("; <", f); fwrite_str_line("dec bl", f); } else if (inst == '+') { fwrite_str_line("; +", f); fwrite_str_line("inc byte [data + rbx]", f); } else if (inst == '-') { fwrite_str_line("; -", f); fwrite_str_line("dec byte [data + rbx]", f); } else if (inst == '.') { fwrite_str_line("; .", f); // sys_write fwrite_str_line("mov rax, 1", f); // Syscall id fwrite_str_line("mov rdi, 1", f); // fd fwrite_str_line("lea rsi, byte [data + rbx]", f); // buff fwrite_str_line("mov rdx, 1", f); // count fwrite_str_line("syscall", f); } else if (inst == ',') { fwrite_str_line("; ,", f); // sys_read fwrite_str_line("mov rax, 0", f); // Syscall id fwrite_str_line("mov rdi, 0", f); // fd fwrite_str_line("lea rsi, byte [data + rbx]", f); // buff fwrite_str_line("mov rdx, 1", f); // count fwrite_str_line("syscall", f); } else if (inst == '[') { fwrite_str_line("; [", f); uint32_t loop_index = last_loop_index; last_loop_index++; loop_stack[loop_stack_len++] = loop_index; char start_label[128] = { 0 }; snprintf(start_label, sizeof(start_label), "S%d_start:", loop_index); fwrite_str_line(start_label, f); fwrite_str_line("cmp byte [data + rbx], 0", f); char jump_inst[128] = { 0 }; snprintf(jump_inst, sizeof(jump_inst), "jz S%d_end", loop_index); fwrite_str_line(jump_inst, f); } else if (inst == ']') { fwrite_str_line("; ]", f); uint32_t loop_index = loop_stack[--loop_stack_len]; char jump_to_start[128] = { 0 }; snprintf(jump_to_start, sizeof(jump_to_start), "jmp S%d_start", loop_index); fwrite_str_line(jump_to_start, f); char end_label[128] = { 0 }; snprintf(end_label, sizeof(end_label), "S%d_end:", loop_index); fwrite_str_line(end_label, f); } } fwrite_str_line("; exit(0)", f); fwrite_str_line("mov rax, 60", f); fwrite_str_line("mov rdi, 0", f); fwrite_str_line("syscall", f); fclose(f); f = NULL; // TODO: Use exec instead of system // TODO: Don't hardcode the platform system("nasm -felf64 tmp.asm -o tmp.o"); char ld_command[256] = { 0 }; snprintf(ld_command, sizeof(ld_command), "ld tmp.o -o %s", output_filename); system(ld_command); rc = 0; err: if (f) fclose(f); return rc; }