diff options
author | Mitya Selivanov <automainint@guattari.tech> | 2024-06-09 02:22:33 +0200 |
---|---|---|
committer | Mitya Selivanov <automainint@guattari.tech> | 2024-06-09 02:22:33 +0200 |
commit | 924558d3c9d8363d80136cb7599bd98b19c93f48 (patch) | |
tree | 19b5aae7a340e4c0c23a404dac489a24fe3dd988 | |
parent | 9e9027cc63e63e80dc8fcb82f2f2c3b60acf95f7 (diff) | |
download | bxgen-924558d3c9d8363d80136cb7599bd98b19c93f48.zip |
Add semantic tree example
-rw-r--r-- | .gitignore | 2 | ||||
-rwxr-xr-x | binary_code_generation.c | 136 |
2 files changed, 117 insertions, 21 deletions
@@ -1 +1 @@ - +test_* diff --git a/binary_code_generation.c b/binary_code_generation.c index 0f0d374..3735b2c 100755 --- a/binary_code_generation.c +++ b/binary_code_generation.c @@ -9,7 +9,7 @@ exit $? // // Binary code generation compiler backend // -// Traits +// Qualities // // - Single source file // - Simple and flexible API @@ -27,6 +27,8 @@ exit $? // - Sea of Nodes // - Optimization layers // - Multithreading +// - COFF, PE, OMF, Mach-O +// - i386, RISC-V, ARM // // ================================================================ // @@ -66,6 +68,23 @@ enum { // For indices UNDEFINED = -1, + // Formats + // + + FORMAT_ELF = 1, + FORMAT_COFF, + FORMAT_PE, + FORMAT_OMF, + FORMAT_MATCH_O, + + // Architecture + // + + ARCH_RISC_V = 64, + ARCH_I386, + ARCH_X86_64, + ARCH_ARM, + // Sea of Nodes flow type // @@ -99,15 +118,15 @@ enum { // (see `entity_t::tail`), except for `MAX_ENTITY_COUNT`. // - MAX_LITERAL_SIZE = 512, + MAX_LITERAL_SIZE = 400, MAX_NAME_SIZE = 128, - MAX_PROC_COUNT = 126, - MAX_NODE_COUNT = 110, + MAX_PROC_COUNT = 80, + MAX_NODE_COUNT = 60, MAX_ENTITY_COUNT = 16384, }; -// A semantic node is an operation with -// possible references to other nodes. +// A semantic node is an operation with optional data +// and possible references to other nodes. // typedef struct { @@ -136,6 +155,7 @@ typedef struct { typedef struct { i16 type; + i64 entry_point; i64 proc_count; i64 procs[MAX_PROC_COUNT]; } unit_t; @@ -206,6 +226,22 @@ void node_destroy(entity_pool_t *pool, i64 node) { pool_entity_remove(pool, node, TYPE_NODE); } +i64 node_op_i64(entity_pool_t *pool, i64 value) { + return node_init(pool, (node_t) { + .op = OP_I64, + .flow = FLOW_DATA, + .lit_int = value, + }); +} + +i64 node_op_ret(entity_pool_t *pool, i64 node_return_value) { + return node_init(pool, (node_t) { + .op = OP_RET, + .flow = FLOW_CONTROL, + .ref_node = node_return_value, + }); +} + i64 proc_init(entity_pool_t *pool) { return pool_entity_add(pool, (entity_t) { .type = TYPE_PROC, @@ -217,7 +253,7 @@ void proc_destroy(entity_pool_t *pool, i64 proc) { pool_entity_remove(pool, proc, TYPE_PROC); } -void proc_set_name(entity_pool_t *pool, i64 proc, i64 name_size, c8 *name) { +void proc_set_name(entity_pool_t *pool, i64 proc, i64 name_size, c8 const *name) { assert(pool != NULL); assert(pool->entities[proc].is_enabled); assert(pool->entities[proc].type == TYPE_PROC); @@ -261,6 +297,9 @@ i64 unit_init(entity_pool_t *pool) { return pool_entity_add(pool, (entity_t) { .type = TYPE_UNIT, .tail = UNDEFINED, + .unit = (unit_t) { + .entry_point = UNDEFINED, + } }); } @@ -293,28 +332,75 @@ void unit_proc_remove(entity_pool_t *pool, i64 unit, i64 proc) { pool->entities[unit].unit.procs[proc] = UNDEFINED; } +void unit_set_entry_point(entity_pool_t *pool, i64 unit, i64 entry_point_proc) { + assert(pool != NULL); + assert(pool->entities[unit].is_enabled); + assert(pool->entities[unit].type == TYPE_UNIT); + assert(pool->entities[entry_point_proc].type == TYPE_PROC); + + pool->entities[unit].unit.entry_point = entry_point_proc; +} + +void unit_write(entity_pool_t *pool, i64 unit, i16 target, FILE *out) { + assert(pool != NULL); + assert(pool->entities[unit].is_enabled); + assert(pool->entities[unit].unit.entry_point != UNDEFINED); + assert(out != NULL); + assert(target == (FORMAT_ELF | ARCH_X86_64)); + + // TODO + printf("[TODO] Writing ELF x86_64 executable..."); +} + +// ================================================================ +// +// Helpers +// +// ================================================================ + // Global state // static entity_pool_t g_pool = { 0 }; -// Helper functions +// Handy procedures // -i64 op_i64(i64 value) { - return node_init(&g_pool, (node_t) { - .op = OP_I64, - .flow = FLOW_DATA, - .lit_int = value, - }); +i64 n_i64(i64 value) { + return node_op_i64(&g_pool, value); } -i64 op_ret(i64 node_return_value) { - return node_init(&g_pool, (node_t) { - .op = OP_RET, - .flow = FLOW_CONTROL, - .ref_node = node_return_value, - }); +i64 n_ret(i64 node_return_value) { + return node_op_ret(&g_pool, node_return_value); +} + +i64 p_new(c8 const *name) { + i64 p = proc_init(&g_pool); + proc_set_name(&g_pool, p, strlen(name), name); + return p; +} + +void p_add(i64 proc, i64 node) { + proc_node_add(&g_pool, proc, node); +} + +i64 u_new() { + return unit_init(&g_pool); +} + +void u_add(i64 unit, i64 proc) { + unit_proc_add(&g_pool, unit, proc); +} + +void u_entry_point(i64 unit, i64 proc) { + unit_set_entry_point(&g_pool, unit, proc); +} + +void u_elf_x86_64(i64 unit, c8 const *output_file_name) { + FILE *f = fopen(output_file_name, "wb"); + assert(f != NULL); + unit_write(&g_pool, unit, FORMAT_ELF | ARCH_X86_64, f); + fclose(f); } // ================================================================ @@ -328,6 +414,16 @@ int main(int argc, char **argv) { printf("proc - %d bytes\n", (i32) sizeof(proc_t)); printf("unit - %d bytes\n", (i32) sizeof(unit_t)); + i64 main = p_new("main"); + i64 n0 = n_i64(42); + p_add(main, n0); + p_add(main, n_ret(n0)); + + i64 u = u_new(); + u_add(u, main); + u_entry_point(u, main); + u_elf_x86_64(u, "test_foo"); + printf("\nBye!\n"); return 0; } |