Outputing assembly now, :3

This commit is contained in:
2025-07-07 21:33:22 +03:00
parent 83a0cee3e3
commit e59f6a31ac
25 changed files with 1222 additions and 265 deletions

View File

@@ -0,0 +1,449 @@
#include "argparse.h"
#include "dynarray.h"
#include "parser/ast.h"
#include "token.h"
#include <stdio.h>
#include <string.h>
typedef struct comp_state_s {
char** strings;
} comp_state_t;
int write_op(ast_op_t* aop, FILE* f, comp_state_t state) {
switch (aop->type) {
case (AOT_OP): {
token_t op = aop->op;
switch (op.type) {
case (TT_PUSH_INT): {
}; break;
case (TT_PUSH_STR): {
fprintf(f, " mov rax, morph_str_%zu\n", dynarray_length(state.strings));
fprintf(f, " push rax\n");
fprintf(f, " mov rax, %zu\n", strlen(op.str_v));
fprintf(f, " push rax\n");
dynarray_push(state.strings, op.str_v);
}; break;
case (TT_PUSH_CSTR): {
fprintf(f, " mov rax, morph_str_%zu\n", dynarray_length(state.strings));
fprintf(f, " push rax\n");
dynarray_push(state.strings, op.str_v);
}; break;
case (TT_PUSH_BOOL): {
fprintf(f, " mov rax, %d\n", (int)op.bool_v);
fprintf(f, " push rax\n");
}; break;
case (TT_PUSH_CHAR): {
fprintf(f, " mov rax, %d ; '%c'\n", (int)op.char_v, op.char_v);
fprintf(f, " push rax\n");
}; break;
case (TT_PUSH_FLOAT): {
// TODO: do this
}; break;
case (TT_OP): {
switch (op.op_type) {
case (OP_ADD): {
fprintf(f, " ; -- OP_ADD --\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rbx\n");
fprintf(f, " add rax, rbx\n");
fprintf(f, " push rax\n");
}; break;
case (OP_SUB): {
fprintf(f, " ; -- OP_SUB --\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rbx\n");
fprintf(f, " sub rax, rbx\n");
fprintf(f, " push rax\n");
}; break;
case (OP_MUL): {
fprintf(f, " ; -- OP_MUL --\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rbx\n");
fprintf(f, " mul rbx\n");
fprintf(f, " push rax\n");
}; break;
case (OP_DIV): {
fprintf(f, " ; -- OP_DIV --\n");
fprintf(f, " xor rdx, rdx\n");
fprintf(f, " pop rbx\n");
fprintf(f, " pop rax\n");
fprintf(f, " div rbx\n");
fprintf(f, " push rax\n");
}; break;
case (OP_MOD): {
fprintf(f, " ; -- OP_MOD --\n");
fprintf(f, " xor rdx, rdx\n");
fprintf(f, " pop rbx\n");
fprintf(f, " pop rax\n");
fprintf(f, " div rbx\n");
fprintf(f, " push rbx\n");
}; break;
case (OP_EQ): {
fprintf(f, " ; -- OP_EQ --\n");
fprintf(f, " mov rcx, 0\n");
fprintf(f, " mov rdx, 1\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rbx\n");
fprintf(f, " cmp rax, rbx\n");
fprintf(f, " cmove rcx, rdx\n");
fprintf(f, " push rcx\n");
}; break;
case (OP_GT): {
fprintf(f, " ; -- OP_GT --\n");
fprintf(f, " mov rcx, 0\n");
fprintf(f, " mov rdx, 1\n");
fprintf(f, " pop rbx\n");
fprintf(f, " pop rax\n");
fprintf(f, " cmp rax, rbx\n");
fprintf(f, " cmovg rcx, rdx\n");
fprintf(f, " push rcx\n");
}; break;
case (OP_LT): {
fprintf(f, " ; -- OP_LT --\n");
fprintf(f, " mov rcx, 0\n");
fprintf(f, " mov rdx, 1\n");
fprintf(f, " pop rbx\n");
fprintf(f, " pop rax\n");
fprintf(f, " cmp rax, rbx\n");
fprintf(f, " cmovl rcx, rdx\n");
fprintf(f, " push rcx\n");
}; break;
case (OP_GE): {
fprintf(f, " ; -- OP_GE --\n");
fprintf(f, " mov rcx, 0\n");
fprintf(f, " mov rdx, 1\n");
fprintf(f, " pop rbx\n");
fprintf(f, " pop rax\n");
fprintf(f, " cmp rax, rbx\n");
fprintf(f, " cmovge rcx, rdx\n");
fprintf(f, " push rcx\n");
}; break;
case (OP_LE): {
fprintf(f, " ; -- OP_LE --\n");
fprintf(f, " mov rcx, 0\n");
fprintf(f, " mov rdx, 1\n");
fprintf(f, " pop rbx\n");
fprintf(f, " pop rax\n");
fprintf(f, " cmp rax, rbx\n");
fprintf(f, " cmovle rcx, rdx\n");
fprintf(f, " push rcx\n");
}; break;
case (OP_NE): {
fprintf(f, " ; -- OP_NE --\n");
fprintf(f, " mov rcx, 1\n");
fprintf(f, " mov rdx, 0\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rbx\n");
fprintf(f, " cmp rax, rbx\n");
fprintf(f, " cmove rcx, rdx\n");
fprintf(f, " push rcx\n");
}; break;
case (OP_AND): {
fprintf(f, " ; -- OP_AND --\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rbx\n");
fprintf(f, " test rax, rax\n");
fprintf(f, " setnz al\n");
fprintf(f, " test rbx, rbx\n");
fprintf(f, " setnz bl\n");
fprintf(f, " and al, bl\n");
fprintf(f, " movzx rbx, al\n");
fprintf(f, " push rbx\n");
}; break;
case (OP_OR): {
fprintf(f, " ; -- OP_OR --\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rbx\n");
fprintf(f, " test rax, rax\n");
fprintf(f, " setnz al\n");
fprintf(f, " test rbx, rbx\n");
fprintf(f, " setnz bl\n");
fprintf(f, " or al, bl\n");
fprintf(f, " movzx rbx, al\n");
fprintf(f, " push rbx\n");
}; break;
case (OP_SHR): {
fprintf(f, " ; -- OP_SHR --\n");
fprintf(f, " pop rcx\n");
fprintf(f, " pop rbx\n");
fprintf(f, " shr rbx, cl\n");
fprintf(f, " push rbx\n");
}; break;
case (OP_SHL): {
fprintf(f, " ; -- OP_SHL --\n");
fprintf(f, " pop rcx\n");
fprintf(f, " pop rbx\n");
fprintf(f, " shl rbx, cl\n");
fprintf(f, " push rbx\n");
}; break;
case (OP_BOR): {
fprintf(f, " ; -- OP_BOR --\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rbx\n");
fprintf(f, " or rbx, rax\n");
fprintf(f, " push rbx\n");
}; break;
case (OP_BAND): {
fprintf(f, " ; -- OP_BAND --\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rbx\n");
fprintf(f, " and rbx, rax\n");
fprintf(f, " push rbx\n");
}; break;
case (OP_NOT): {
fprintf(f, " ; -- OP_NOT --\n");
fprintf(f, " pop rax\n");
fprintf(f, " test rax, rax\n");
fprintf(f, " setz al\n");
fprintf(f, " movzx rbx, al\n");
fprintf(f, " push rbx\n");
}; break;
case (OP_DUP): {
fprintf(f, " ; -- OP_DUP --\n");
fprintf(f, " pop rax\n");
fprintf(f, " push rax\n");
fprintf(f, " push rax\n");
}; break;
case (OP_SWAP): {
fprintf(f, " ; -- OP_SWAP --\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rbx\n");
fprintf(f, " push rax\n");
fprintf(f, " push rbx\n");
}; break;
case (OP_DROP): {
fprintf(f, " ; -- OP_DROP --\n");
fprintf(f, " pop rax\n");
}; break;
case (OP_OVER): {
fprintf(f, " ; -- OP_OVER --\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rbx\n");
fprintf(f, " push rbx\n");
fprintf(f, " push rax\n");
fprintf(f, " push rbx\n");
}; break;
case (OP_ROT): {
fprintf(f, " ; -- OP_ROT --\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rbx\n");
fprintf(f, " pop rcx\n");
fprintf(f, " push rbx\n");
fprintf(f, " push rax\n");
fprintf(f, " push rcx\n");
}; break;
case (OP_LOAD8): {
fprintf(f, " ; -- OP_LOAD8 --\n");
fprintf(f, " pop rax\n");
fprintf(f, " xor rbx, rbx\n");
fprintf(f, " mov bl, byte [rax]\n");
fprintf(f, " push rbx\n");
}; break;
case (OP_STORE8): {
fprintf(f, " ; -- OP_STORE8 --\n");
fprintf(f, " pop rbx\n");
fprintf(f, " pop rax\n");
fprintf(f, " mov byte [rax], bl\n");
}; break;
case (OP_LOAD16): {
fprintf(f, " ; -- OP_LOAD16 --\n");
fprintf(f, " pop rax\n");
fprintf(f, " xor rbx, rbx\n");
fprintf(f, " mov bx, word [rax]\n");
fprintf(f, " push rbx\n");
}; break;
case (OP_STORE16): {
fprintf(f, " ; -- OP_STORE16 --\n");
fprintf(f, " pop rbx\n");
fprintf(f, " pop rax\n");
fprintf(f, " mov word [rax], bx\n");
}; break;
case (OP_LOAD32): {
fprintf(f, " ; -- OP_LOAD32 --\n");
fprintf(f, " pop rax\n");
fprintf(f, " xor rbx, rbx\n");
fprintf(f, " mov ebx, dword [rax]\n");
fprintf(f, " push rbx\n");
}; break;
case (OP_STORE32): {
fprintf(f, " ; -- OP_STORE32 --\n");
fprintf(f, " pop rbx\n");
fprintf(f, " pop rax\n");
fprintf(f, " mov dword[rax], ebx\n");
}; break;
case (OP_LOAD64): {
fprintf(f, " ; -- OP_LOAD64 --\n");
fprintf(f, " pop rax\n");
fprintf(f, " xor rbx, rbx\n");
fprintf(f, " mov rbx, qword [rax]\n");
fprintf(f, " push rbx\n");
}; break;
case (OP_STORE64): {
fprintf(f, " ; -- OP_STORE64 --\n");
fprintf(f, " pop rbx\n");
fprintf(f, " pop rax\n");
fprintf(f, " mov qword [rax], rbx\n");
}; break;
case (OP_SYSCALL0): {
fprintf(f, " ; -- OP_SYSCALL0 --\n");
fprintf(f, " pop rax\n");
fprintf(f, " syscall\n");
fprintf(f, " push rax\n");
}; break;
case (OP_SYSCALL1): {
fprintf(f, " ; -- OP_SYSCALL1 --\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rdi\n");
fprintf(f, " pop r9\n");
fprintf(f, " syscall\n");
fprintf(f, " push rax\n");
}; break;
case (OP_SYSCALL2): {
fprintf(f, " ; -- OP_SYSCALL2 --\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rdi\n");
fprintf(f, " pop rsi\n");
fprintf(f, " syscall\n");
fprintf(f, " push rax\n");
}; break;
case (OP_SYSCALL3): {
fprintf(f, " ; -- OP_SYSCALL3 --\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rdi\n");
fprintf(f, " pop rsi\n");
fprintf(f, " pop rdx\n");
fprintf(f, " syscall\n");
fprintf(f, " push rax\n");
}; break;
case (OP_SYSCALL4): {
fprintf(f, " ; -- OP_SYSCALL4 --\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rdi\n");
fprintf(f, " pop rsi\n");
fprintf(f, " pop rdx\n");
fprintf(f, " pop r10\n");
fprintf(f, " syscall\n");
fprintf(f, " push rax\n");
}; break;
case (OP_SYSCALL5): {
fprintf(f, " ; -- OP_SYSCALL5 --\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rdi\n");
fprintf(f, " pop rsi\n");
fprintf(f, " pop rdx\n");
fprintf(f, " pop r10\n");
fprintf(f, " pop r8\n");
fprintf(f, " syscall\n");
fprintf(f, " push rax\n");
}; break;
case (OP_SYSCALL6): {
fprintf(f, " ; -- OP_SYSCALL6 --\n");
fprintf(f, " pop rax\n");
fprintf(f, " pop rdi\n");
fprintf(f, " pop rsi\n");
fprintf(f, " pop rdx\n");
fprintf(f, " pop r10\n");
fprintf(f, " pop r8\n");
fprintf(f, " pop r9\n");
fprintf(f, " syscall\n");
fprintf(f, " push rax\n");
}; break;
case (OP_ARGC): {
}; break;
case (OP_ARGV): {
}; break;
case (OP_HERE): {
char* pos = malloc(1024*2);
snprintf(pos, 2048, "%s:%d:%d", op.loc.file, op.loc.line, op.loc.col);
fprintf(f, " mov rax, str_%zu\n", dynarray_length(state.strings));
fprintf(f, " push rax\n");
fprintf(f, " mov rax, %zu\n", strlen(op.str_v));
fprintf(f, " push rax\n");
dynarray_push(state.strings, op.str_v);
}; break;
case (OP_PRINT): {
}; break;
}
}; break;
case (TT_KW):
case (TT_IDENT): {
// unreachable
} break;
}
}
case (AOT_IF): {
}; break;
case (AOT_WHILE): {
}; break;
case (AOT_USE_CONST): {
}; break;
case (AOT_USE_MEMORY): {
}; break;
case (AOT_CALL_FUNC): {
}; break;
}
return 0;
}
int compile_x86_64_linux_nasm(args_t* args, program_t* prog) {
FILE* f = fopen(args->asm_file, "w");
comp_state_t state = {0};
state.strings = dynarray_create(char*);
fprintf(f, "bits 64\n");
fprintf(f, "section .text\n");
fprintf(f, "global _start\n");
fprintf(f, "_start:\n");
fprintf(f, " call morph_f_main\n");
fprintf(f, " mov rax, 60\n");
fprintf(f, " mov rdi, 0\n");
fprintf(f, " syscall\n");
for (int i = 0; i < dynarray_length(prog->funcs); i++) {
function_t func = prog->funcs[i];
fprintf(f, "morph_f_%s:\n", func.name);
for (int y = 0; y < dynarray_length(func.body); y++) {
ast_op_t aop = func.body[y];
if (write_op(&aop, f, state)) {
return 1;
}
}
fprintf(f, " ret\n");
}
fprintf(f, "section .bss\n");
for (int i = 0; i < dynarray_length(prog->memories); i++) {
memory_t mem = prog->memories[i];
fprintf(f, "morph_memory_%d: resb %zu ; Memory %s\n", i, mem.size, mem.name);
}
fprintf(f, "section .rodata\n");
for (int i = 0; i < dynarray_length(state.strings); i++) {
fprintf(f, "morph_str_%d: db \"%s\"\n", i, state.strings[i]);
}
for (int i = 0; i < dynarray_length(prog->const_vars); i++) {
const_t* v = &prog->const_vars[i];
fprintf(f, "morph_const_%d: ", i);
switch (v->val.type) {
case (TT_PUSH_INT): {
fprintf(f, "dq %zu\n", v->val.int_v);
}; break;
case (TT_PUSH_CSTR):
case (TT_PUSH_STR): {
fprintf(f, "db %s\n", v->val.str_v);
}; break;
case (TT_PUSH_CHAR):
fprintf(f, "db %c\n", v->val.char_v);
case (TT_PUSH_BOOL):
fprintf(f, "db %d\n", (int)v->val.bool_v);
default:
}
}
return 0;
}