diff options
| author | Johnny Richard <johnny@johnnyrichard.com> | 2024-10-30 22:58:03 +0100 |
|---|---|---|
| committer | Johnny Richard <johnny@johnnyrichard.com> | 2025-12-14 09:53:52 +0100 |
| commit | 10bb8a05088f1d3bb24f7167f609b5f6fb0ba026 (patch) | |
| tree | 7a4b3f69a461301c45204ed856b61f92a7d42233 /src/x86_64/codegen.c | |
Signed-off-by: Johnny Richard <johnny@johnnyrichard.com>
Diffstat (limited to 'src/x86_64/codegen.c')
| -rw-r--r-- | src/x86_64/codegen.c | 152 |
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); +} |
