diff options
author | Mitya Selivanov <automainint@guattari.tech> | 2024-06-11 06:54:43 +0200 |
---|---|---|
committer | Mitya Selivanov <automainint@guattari.tech> | 2024-06-11 06:54:43 +0200 |
commit | b8ab04e26e8d1352e5a6cbd51e640c7d799e2eb3 (patch) | |
tree | ea40adc514cfc027cfbb343a08fa3cd06d9a49b2 | |
parent | b76549bb7bb94832ed0c7a3985cd304ab38d6cd2 (diff) | |
download | bxgen-b8ab04e26e8d1352e5a6cbd51e640c7d799e2eb3.zip |
Implement IO dispatch
-rwxr-xr-x | bxgen.c | 188 |
1 files changed, 146 insertions, 42 deletions
@@ -59,6 +59,7 @@ exit $? // Done features // // - ELF header +// - IO static dispatch // // ================================================================ // @@ -76,8 +77,6 @@ exit $? // // ================================================================ -#include <stdio.h> - typedef signed char i8; typedef signed short i16; typedef signed int i32; @@ -176,6 +175,15 @@ enum { MAX_LINK_COUNT = 20, MAX_ARG_COUNT = 20, MAX_ENTITY_COUNT = 16384, + + // IO dispatch operations + // + + IO_OPEN = 0, + IO_CLOSE, + IO_READ, + IO_WRITE, + IO_CHMOD_EXE, }; // A semantic node is an operation with optional data @@ -302,13 +310,13 @@ i64 node_init(pool_t *pool, node_t data); void node_destroy(pool_t *pool, i64 node); i64 node_data_i64(pool_t *pool, i64 value); i64 node_ctrl_call(pool_t *pool, i16 convention, i64 target_proc, i64 arg_count, var_t *args); -i64 node_ctrl_call_by_name(pool_t *pool, i16 convention, i64 name_size, c8 const *name, i64 arg_count, var_t *args); +i64 node_ctrl_call_by_name(pool_t *pool, i16 convention, i64 name_size, c8 *name, i64 arg_count, var_t *args); i64 node_ctrl_ret(pool_t *pool, i64 value_count, var_t *values); i64 proc_init(pool_t *pool); void proc_destroy(pool_t *pool, i64 proc); void proc_set_convention(pool_t *pool, i64 proc, i16 convention); -void proc_set_name(pool_t *pool, i64 proc, i64 name_size, c8 const *name); +void proc_set_name(pool_t *pool, i64 proc, i64 name_size, c8 *name); void proc_node_add(pool_t *pool, i64 proc, i64 node); void proc_node_remove(pool_t *pool, i64 proc, i64 node); @@ -318,24 +326,32 @@ void unit_proc_add(pool_t *pool, i64 unit, i64 proc); void unit_proc_remove(pool_t *pool, i64 unit, i64 proc); void unit_link_add(pool_t *pool, i64 unit, i64 link_unit); void unit_link_remove(pool_t *pool, i64 unit, i64 link_unit); -void unit_set_name(pool_t *pool, i64 unit, i64 name_size, c8 const *name); +void unit_set_name(pool_t *pool, i64 unit, i64 name_size, c8 *name); void unit_set_entry_point(pool_t *pool, i64 unit, i64 entry_point_proc); -void unit_write(pool_t *pool, i64 unit, u16 target, FILE *out); +void unit_write(pool_t *pool, i64 unit, u16 target, i64 io_id, void *io_user_data); + +i64 io_open(i64 name_size, c8 *name, void *user_data); +void io_close(i64 f, void *user_data); +i64 io_read(i64 f, i64 size, void *data, void *user_data); +i64 io_write(i64 f, i64 size, void *data, void *user_data); +void io_chmod_exe(i64 f, void *user_data); + +void io_dispatch(i16 op, i64 *id, i64 *size, void *data, void *user_data); #ifndef DISABLE_HELPERS i64 n_i64(i64 value); i64 n_call(i16 convention, i64 target_proc, i64 arg_count, var_t *args); -i64 n_call_by_name(i16 convention, c8 const *name, i64 arg_count, var_t *args); +i64 n_call_by_name(i16 convention, c8 *name, i64 arg_count, var_t *args); i64 n_ret(i64 val_count, var_t *vals); -i64 p_new(c8 const *name); +i64 p_new(c8 *name); void p_add(i64 proc, i64 node); i64 u_new(); void u_add(i64 unit, i64 proc); void u_entry_point(i64 unit, i64 proc); -void u_elf_x86_64(i64 unit, c8 const *output_file_name); +void u_elf_x86_64(i64 unit, c8 *output_file_name); void l_code(i64 unit, i64 link_unit); -void l_object(i64 unit, c8 const *object_library); -void l_static(i64 unit, c8 const *static_library); +void l_object(i64 unit, c8 *object_library); +void l_static(i64 unit, c8 *static_library); #endif #ifdef __cplusplus @@ -418,7 +434,7 @@ i64 node_ctrl_call(pool_t *pool, i16 convention, i64 target_proc, i64 arg_count, }); } -i64 node_ctrl_call_by_name(pool_t *pool, i16 convention, i64 name_size, c8 const *name, i64 arg_count, var_t *args) { +i64 node_ctrl_call_by_name(pool_t *pool, i16 convention, i64 name_size, c8 *name, i64 arg_count, var_t *args) { assert(arg_count <= MAX_ARG_COUNT); call_t call = { @@ -475,7 +491,7 @@ void proc_set_convention(pool_t *pool, i64 proc, i16 convention) { pool->entities[proc].proc.convention = convention; } -void proc_set_name(pool_t *pool, i64 proc, i64 name_size, c8 const *name) { +void proc_set_name(pool_t *pool, i64 proc, i64 name_size, c8 *name) { assert(pool != NULL && pool->entities != NULL); assert(pool->entities[proc].is_enabled); assert(pool->entities[proc].type == ENTITY_PROC); @@ -645,7 +661,7 @@ void unit_link_remove(pool_t *pool, i64 unit, i64 link_unit) { assert(0); } -void unit_set_name(pool_t *pool, i64 unit, i64 name_size, c8 const *name) { +void unit_set_name(pool_t *pool, i64 unit, i64 name_size, c8 *name) { assert(pool != NULL && pool->entities != NULL); assert(pool->entities[unit].is_enabled); assert(pool->entities[unit].type == ENTITY_UNIT); @@ -689,17 +705,13 @@ void unit_set_entry_point(pool_t *pool, i64 unit, i64 entry_point_proc) { // Code generation proc // -void unit_write(pool_t *pool, i64 unit, u16 target, FILE *out) { - // TODO - // Use callback instead of `FILE` to not depend on `stdio.h` here. - +void unit_write(pool_t *pool, i64 unit, u16 target, i64 io_out, void *io_user_data) { assert(pool != NULL && pool->entities != NULL); assert(pool->entities[unit].is_enabled); assert(pool->entities[unit].unit.entry_point_index != UNDEFINED); - assert(out != NULL); assert(target == (FORMAT_ELF | ARCH_X86_64)); - printf("Writing ELF x86_64 executable...\n"); +// unit_t *u = u16 ehs = 64; u16 shs = 0; @@ -724,11 +736,12 @@ void unit_write(pool_t *pool, i64 unit, u16 target, FILE *out) { // ELF header // - #define WRITE_V(...) fwrite(&(u8[]) {__VA_ARGS__}, 1, sizeof((u8[]) {__VA_ARGS__}), out) - #define WRITE_DUP(x, n) fwrite( (u8[n]) { 0 }, 1, n, out) - #define WRITE_2(x) fwrite(&(u16) { x }, 2, 1, out) - #define WRITE_4(x) fwrite(&(u32) { x }, 4, 1, out) - #define WRITE_8(x) fwrite(&(u64) { x }, 8, 1, out) + #define WRITE(x, n) io_write( io_out, n, x, io_user_data ) + #define WRITE_V(...) io_write( io_out, sizeof((u8[]) {__VA_ARGS__}), (u8[]) {__VA_ARGS__}, io_user_data ) + #define WRITE_DUP(x, n) io_write( io_out, n, (u8[n]) { 0 }, io_user_data ) + #define WRITE_2(x) io_write( io_out, 2, &(u16) { x }, io_user_data ) + #define WRITE_4(x) io_write( io_out, 4, &(u32) { x }, io_user_data ) + #define WRITE_8(x) io_write( io_out, 8, &(u64) { x }, io_user_data ) WRITE_V( 0x7f, 'E', 'L', 'F' ); // magic @@ -766,18 +779,44 @@ void unit_write(pool_t *pool, i64 unit, u16 target, FILE *out) { WRITE_8( code_size ); // memsz WRITE_8( 8 ); // align + // Code + // + + for (i64 i = code_offset - ehs - phs; i > 0; --i) + WRITE_V( 0 ); + + WRITE( code, code_size ); + #undef WRITE_V #undef WRITE_DUP #undef WRITE_32 #undef WRITE_64 - // Code - // + #undef WRITE +} - for (i64 i = code_offset - ehs - phs; i > 0; --i) - fwrite(&(u8) { 0 }, 1, 1, out); +i64 io_open(i64 name_size, c8 *name, void *user_data) { + i64 f; + io_dispatch(IO_OPEN, &f, &name_size, name, user_data); + return f; +} - fwrite(code, 1, code_size, out); +void io_close(i64 f, void *user_data) { + io_dispatch(IO_CLOSE, &f, NULL, NULL, user_data); +} + +i64 io_read(i64 f, i64 size, void *data, void *user_data) { + io_dispatch(IO_READ, &f, &size, data, user_data); + return size; +} + +i64 io_write(i64 f, i64 size, void *data, void *user_data) { + io_dispatch(IO_WRITE, &f, &size, data, user_data); + return size; +} + +void io_chmod_exe(i64 f, void *user_data) { + io_dispatch(IO_CHMOD_EXE, &f, NULL, NULL, user_data); } // ================================================================ @@ -788,11 +827,75 @@ void unit_write(pool_t *pool, i64 unit, u16 target, FILE *out) { #ifndef DISABLE_HELPERS +#include <stdio.h> + #ifdef __unix__ #include <sys/types.h> #include <sys/stat.h> #endif +// IO dispatch procedure +// + +void io_dispatch(i16 op, i64 *id, i64 *size, void *data, void *user_data) { + assert(id != NULL); + + (void) user_data; + + FILE **f = (FILE **) id; + c8 buf[MAX_NAME_SIZE] = { 0 }; + + switch (op) { + case IO_OPEN: + assert(size != NULL); + assert(*size > 0 && *size < MAX_NAME_SIZE); + assert(data != NULL); + + memcpy(buf, data, *size); + *f = fopen(buf, "rb"); + assert(*f != NULL); + break; + + case IO_CLOSE: + assert(*f != NULL); + assert(size == NULL); + assert(data == NULL); + + fclose(*f); + break; + + case IO_READ: + assert(*f != NULL); + assert(size != NULL); + assert(data != NULL); + assert(*size > 0); + + *size = fread(data, 1, *size, *f); + break; + + case IO_WRITE: + assert(*f != NULL); + assert(size != NULL); + assert(data != NULL); + assert(*size > 0); + + *size = fwrite(data, 1, *size, *f); + break; + + case IO_CHMOD_EXE: + assert(*f != NULL); + assert(size == NULL); + +#ifdef __unix__ + fchmod(fileno(*f), 0775); +#endif + break; + + default: + assert(0); + } +} + // Global state // @@ -817,7 +920,7 @@ i64 n_call(i16 convention, i64 target_proc, i64 arg_count, var_t *args) { return node_ctrl_call(&g_pool, convention, target_proc, arg_count, args); } -i64 n_call_by_name(i16 convention, c8 const *name, i64 arg_count, var_t *args) { +i64 n_call_by_name(i16 convention, c8 *name, i64 arg_count, var_t *args) { return node_ctrl_call_by_name(&g_pool, convention, strlen(name), name, arg_count, args); } @@ -825,7 +928,7 @@ i64 n_ret(i64 val_count, var_t *vals) { return node_ctrl_ret(&g_pool, val_count, vals); } -i64 p_new(c8 const *name) { +i64 p_new(c8 *name) { i64 p = proc_init(&g_pool); proc_set_name(&g_pool, p, strlen(name), name); return p; @@ -847,27 +950,28 @@ 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); -#ifdef __unix__ - fchmod(fileno(f), 0775); -#endif - fclose(f); +void u_elf_x86_64(i64 unit, c8 *output_file_name) { + printf("Writing ELF x86_64 executable...\n"); + + i64 out = io_open(strlen(output_file_name), output_file_name, NULL); + + unit_write(&g_pool, unit, FORMAT_ELF | ARCH_X86_64, out, NULL); + + io_chmod_exe(out, NULL); + io_close(out, NULL); } void l_code(i64 unit, i64 link_unit) { unit_link_add(&g_pool, unit, link_unit); } -void l_object(i64 unit, c8 const *object_library) { +void l_object(i64 unit, c8 *object_library) { i64 l = unit_init(&g_pool, UNIT_LIBRARY_OBJECT); unit_set_name(&g_pool, l, strlen(object_library), object_library); unit_link_add(&g_pool, unit, l); } -void l_static(i64 unit, c8 const *static_library) { +void l_static(i64 unit, c8 *static_library) { i64 l = unit_init(&g_pool, UNIT_LIBRARY_STATIC); unit_set_name(&g_pool, l, strlen(static_library), static_library); unit_link_add(&g_pool, unit, l); |