summaryrefslogtreecommitdiff
path: root/src/x86_64
diff options
context:
space:
mode:
Diffstat (limited to 'src/x86_64')
-rw-r--r--src/x86_64/codegen.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/src/x86_64/codegen.c b/src/x86_64/codegen.c
new file mode 100644
index 0000000..6cafda0
--- /dev/null
+++ b/src/x86_64/codegen.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2025 Johnny Richard <johnny@johnnyrichard.com>
+ *
+ * SPDX-License-Identifier: LGPL-3.0-or-later
+ *
+ * This file is part of obe.
+ *
+ * obe is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * obe is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with obe. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <obe/arena.h>
+#include <obe/array.h>
+#include <obe/ir.h>
+#include <obe/x86_64/codegen.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static void
+obe_x86_64_codegen_emit_function(obe_ir_function_t *fn, FILE *out)
+{
+ fprintf(out, PRIs ":\n", PRIsARG(fn->name));
+ fprintf(out, "\tpush %%rbp\n");
+ fprintf(out, "\tmov %%rsp, %%rbp\n");
+
+ size_t insts_length = obe_array_length(fn->instrs);
+ for (size_t i = 0; i < insts_length; ++i) {
+ obe_ir_inst_t inst = fn->instrs[i];
+ switch (inst.kind) {
+ case OBE_IR_INST_RETURN:
+ {
+ if (inst.operand1.kind == OBE_IR_OPERAND_LITERAL) {
+ fprintf(out, "\tmov $%s, %%rax\n", inst.operand1.value);
+ } else {
+ fprintf(stderr, "Operation kind not supported\n");
+ exit(EXIT_FAILURE);
+ }
+ } break;
+ default:
+ {
+ fprintf(stderr, "Instruction not supported\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ fprintf(out, "\tleave\n");
+ fprintf(out, "\tret\n");
+}
+
+void
+_obe_x86_64_codegen_emit(obe_ir_translation_unit_t* tu, FILE *out)
+{
+ // FIXME: Add syntax to configure globl
+ fprintf(out, ".globl main\n");
+
+ fprintf(out, ".text\n");
+ size_t funcs_length = obe_array_length(tu->funcs);
+ for (size_t i = 0; i < funcs_length; ++i) {
+ obe_ir_function_t fn = tu->funcs[i];
+ obe_x86_64_codegen_emit_function(&fn, out);
+ }
+}
+
+typedef struct obe_basic_block obe_basic_block_t;
+typedef struct obe_cfg obe_cfg_t;
+typedef struct obe_int_graph obe_int_graph_t;
+
+struct obe_basic_block {
+ obe_string_t id;
+ obe_ir_inst_t *instrs;
+ struct obe_basic_block *pred;
+ struct obe_basic_block *succ;
+};
+
+struct obe_cfg {
+ obe_basic_block_t *init_block;
+ obe_basic_block_t *curr_block;
+};
+
+
+typedef struct obe_int_edge {
+ size_t v1;
+ size_t v2;
+} obe_int_edge_t;
+
+struct obe_int_graph {
+ obe_int_edge_t *edges;
+};
+
+obe_int_graph_t
+create_interference_graph(obe_cfg_t *cfg, obe_arena_t *arena)
+{
+ obe_int_graph_t graph = {0};
+ graph.edges = obe_array(arena, obe_int_edge_t);
+
+ return graph;
+}
+
+void
+obe_x86_64_codegen_emit(obe_ir_translation_unit_t* tu, FILE *out)
+{
+ // FIXME: Create a valid CFG
+ obe_arena_t arena = {0};
+ obe_cfg_t cfg = {0};
+if (cfg.init_block == NULL) {
+ cfg.init_block = obe_arena_alloc(&arena, sizeof(obe_basic_block_t));
+ cfg.curr_block = cfg.init_block;
+ cfg.curr_block->instrs = obe_array(&arena, obe_ir_inst_t);
+ }
+
+ size_t funcs_length = obe_array_length(tu->funcs);
+ for (size_t i = 0; i < funcs_length; ++i) {
+ obe_ir_function_t fn = tu->funcs[i];
+
+ size_t instrs_length = obe_array_length(fn.instrs);
+ for (size_t j = 0; j < instrs_length; ++j) {
+ obe_ir_inst_t inst = fn.instrs[j];
+ switch (inst.kind) {
+ default:
+ {
+ obe_array_append(cfg.curr_block->instrs, inst);
+ }
+ }
+ }
+ }
+
+ // TODO: Register Allocation
+ // liveness analysis (create interference graph)
+ size_t instrs_length = obe_array_length(cfg.init_block->instrs);
+ for (size_t i = 0; i < instrs_length; ++i) {
+ obe_ir_inst_t inst = cfg.init_block->instrs[i];
+ // asm("int3");
+ printf("inst = %d\n", inst.kind);
+ }
+ // TODO: create_interference_graph(&cfg, &arena);
+
+
+ // TODO: Emit assembly code
+
+ obe_arena_free(&arena);
+}