diff options
author | Mitya Selivanov <automainint@guattari.tech> | 2024-11-23 15:20:54 +0100 |
---|---|---|
committer | Mitya Selivanov <automainint@guattari.tech> | 2024-11-23 15:20:54 +0100 |
commit | a059440035093f0a649db4bc8af83fae208f746d (patch) | |
tree | 7fde7619b96ea0c044cc350df6ffe1bc8eab4998 | |
parent | 66d7b0398ef5cad84d474f5db1fcccd1f36c0e88 (diff) | |
download | bxgen-a059440035093f0a649db4bc8af83fae208f746d.zip |
Impl chunk table
-rwxr-xr-x | bxgen.c | 1770 |
1 files changed, 940 insertions, 830 deletions
@@ -30,7 +30,6 @@ #/ - Simplify #/ - Factor out checks #/ - Allow to format the message in CHECK and FAIL macros -#/ - String table for names and arrays #/ - Library #/ - Terminal color option #/ - Proper prefixes for identifiers @@ -94,6 +93,7 @@ #/ #/ - Simplify #/ - Use 0 for UNDEFINED. Make the zero value useful +#/ - Chunk table for names and arrays #/ - Library #/ - IO static dispatch #/ - Correct serialization for endianness @@ -194,27 +194,10 @@ enum { // Limits // - STRING_TABLE_ALIGNMENT = 16, // TODO - - // TEMP - MAX_NUM_OBJECT_FILES = 10 * 1024, - MAX_NUM_SECTIONS = 2 * 1024 * 1024, - MAX_NUM_SYMBOLS = 2 * 1024 * 1024, - MAX_NUM_RELS = 100 * 1024, - MAX_NUM_LINK_RELS = 2 * 1024 * 1024, - MAX_OBJECT_FILE_SIZE = 10 * 1024 * 1024, // 10 MB - MAX_DEPENDENCIES_SIZE = 50 * 1024 * 1024, // 50 MB - MAX_CODE_SIZE = 100 * 1024, // 100 KB - MAX_OUTPUT_SIZE = 20 * 1024 * 1024, // 20 MB - - MAX_PATH_SIZE = 10 * 1024, - MAX_LITERAL_SIZE = 400, - MAX_NAME_SIZE = 80, - MAX_NUM_PROCS = 40, - MAX_NUM_NODES = 60, - MAX_NUM_LINKS = 20, - MAX_NUM_ARGS = 20, - MAX_NUM_ENTITIES = 16 * 1024, + CHUNK_TABLE_ALIGNMENT = 16, + + POOL_CAPACITY = 10 * 1024 * 1024, + MAX_STRING_SIZE = 1024 * 1024, // For indices UNDEFINED = 0, @@ -311,37 +294,12 @@ enum { typedef struct { i64 size; i64 offset; -} String_Handle; - -typedef struct { - i64 size; - i64 capacity; - u8 *data; -} String_Table; +} Chunk_Handle; typedef i64 Var; typedef struct { - i64 address; - i64 num_bytes; - union { - // TODO use string table - i8 as_i8 [MAX_LITERAL_SIZE]; - i16 as_i16[MAX_LITERAL_SIZE / 2]; - i32 as_i32[MAX_LITERAL_SIZE / 4]; - i64 as_i64[MAX_LITERAL_SIZE / 8]; - u8 as_u8 [MAX_LITERAL_SIZE]; - u16 as_u16[MAX_LITERAL_SIZE / 2]; - u32 as_u32[MAX_LITERAL_SIZE / 4]; - u64 as_u64[MAX_LITERAL_SIZE / 8]; - f32 as_f32[MAX_LITERAL_SIZE / sizeof(f32)]; - f64 as_f64[MAX_LITERAL_SIZE / sizeof(f64)]; - }; -} Literal; - -typedef struct { - i16 num_vals; - Var vals[MAX_NUM_ARGS]; + Chunk_Handle vals; } Ret; typedef struct { @@ -349,12 +307,10 @@ typedef struct { // We may call a local procedure by it's id, // or a global procedure by name. - u16 convention; // can be implicitly retrieved from the procedure - i64 target_proc; - i64 target_name_size; - c8 target_name[MAX_NAME_SIZE]; // TODO use string table - i64 num_args; - Var args[MAX_NUM_ARGS]; + u16 convention; // can be implicitly retrieved from the procedure + i64 target_proc; + Chunk_Handle target_name; + Chunk_Handle args; } Call; // A semantic node is an operation with optional data @@ -364,12 +320,12 @@ typedef struct { u16 op; i64 index_in_proc; union { - Literal lit; - Var ref; - Ret ret; - Call call; - Var add[2]; - Var sub[2]; + Chunk_Handle lit; + Var ref; + Ret ret; + Call call; + Var add[2]; + Var sub[2]; }; } Node; @@ -377,28 +333,23 @@ typedef struct { // and has a string name. typedef struct { - u16 convention; - i64 name_size; - c8 name[MAX_NAME_SIZE]; // TODO use string table - i64 num_nodes; - i64 nodes[MAX_NUM_NODES]; - i64 ret_index; - i64 unit; - i64 index_in_unit; + u16 convention; + Chunk_Handle name; + Chunk_Handle nodes; + i64 ret_index; + i64 unit; + i64 index_in_unit; } Proc; // A compilation unit is a collection of procedures. // typedef struct { - u16 type; - i64 entry_point_index; - i64 name_size; - c8 name[MAX_NAME_SIZE]; // TODO use string table - i64 num_procs; - i64 procs[MAX_NUM_PROCS]; - i64 num_links; - i64 links[MAX_NUM_LINKS]; + u16 type; + i64 entry_point_index; + Chunk_Handle name; + Chunk_Handle procs; + Chunk_Handle links; } Unit; // An entity can be any of: @@ -425,15 +376,12 @@ typedef struct { // We use one single large memory block for *everything*. typedef struct { - i64 num_entities; + i64 size; i64 capacity; - Entity * entities; - String_Table str_table; + u8 * data; + Chunk_Handle entities; } Pool; -// TEMP Codegen and linker buffers -// TODO Use string table for buffers also. - typedef struct { b8 emit_done; i64 offset; @@ -471,38 +419,26 @@ typedef struct { } Link_Rel_Entry; typedef struct { - i64 max_num_rels; - i64 max_code_size; - i64 max_ro_data_size; - b8 has_entry; - i64 entry_point; - i64 num_rels; - i64 offset_code; - i64 offset_ro_data; - Codegen_Entity * entities; - Codegen_Rel_Entry *rels; - u8 * buffer_code; - u8 * buffer_ro_data; + b8 has_entry; + i64 entry_point; + i64 offset_code; + i64 offset_ro_data; + Chunk_Handle entities; + Chunk_Handle rels; + Chunk_Handle buffer_code; + Chunk_Handle buffer_ro_data; } Codegen_Context; typedef struct { - i64 max_obj_file_size; - i64 max_dependencies_size; - i64 max_num_obj_files; - i64 max_num_sections; - i64 max_num_symbols; - i64 max_num_rels; - i64 max_output_size; - i64 num_obj_files; - u8 * obj_file_buffer; - u8 * dependencies_buffer; - i64 * obj_file_offsets; - Link_Sec_Entry *sections; - Link_Sym_Entry *symbols; - Link_Rel_Entry *rels; - u8 * output_buffer; + Chunk_Handle obj_file_buffer; + Chunk_Handle dependencies_buffer; + Chunk_Handle obj_file_offsets; + Chunk_Handle sections; + Chunk_Handle symbols; + Chunk_Handle rels; + Chunk_Handle output_buffer; } Linker_Context; // ================================================================ @@ -562,7 +498,7 @@ void unit_link_add(Pool *pool, i64 unit, i64 link_unit); void unit_link_remove(Pool *pool, i64 unit, i64 link_unit); void unit_set_name(Pool *pool, i64 unit, i64 name_size, c8 *name); void unit_set_entry_point(Pool *pool, i64 unit, i64 entry_point_proc); -void unit_write(Pool *pool, Codegen_Context *codegen, Linker_Context *linker, i64 unit, u16 format, u16 arch, i64 io_id, void *io_user_data); +void unit_write(Pool *pool, i64 unit, u16 format, u16 arch, i64 io_id, void *io_user_data); i64 io_open_read(i64 name_size, c8 *name, void *user_data); i64 io_open_write(i64 name_size, c8 *name, void *user_data); @@ -807,79 +743,101 @@ u64 u64_from_dec_str(c8 *s, c8 *s_end) { // ================================================================ // -// * String table +// * Chunk table // // ================================================================ -String_Handle table_add(Pool *pool, i64 size, u8 *data) { - CHECK(pool != NULL, "Invalid arguments", (String_Handle) {0}); - CHECK(size > 0, "Invalid arguments", (String_Handle) {0}); - CHECK(data != NULL, "Invalid arguments", (String_Handle) {0}); +Chunk_Handle chunk_add(Pool *pool, i64 size, void *data) { + CHECK(pool != NULL, "Invalid arguments", (Chunk_Handle) {0}); + CHECK(size > 0, "Invalid arguments", (Chunk_Handle) {0}); + CHECK(data != NULL, "Invalid arguments", (Chunk_Handle) {0}); + + i64 chunk_size = align(size, CHUNK_TABLE_ALIGNMENT); - CHECK(pool->str_table.size + size <= pool->str_table.capacity, "Out of memory", (String_Handle) {0}); + CHECK(pool->size + chunk_size <= pool->capacity, "Out of memory", (Chunk_Handle) {0}); - String_Handle h = { + Chunk_Handle h = { .size = size, - .offset = pool->str_table.size, + .offset = pool->size, }; - mem_cpy(pool->str_table.data + h.offset, data, size); + mem_cpy(pool->data + h.offset, data, size); - pool->str_table.size += size; + pool->size += chunk_size; return h; } -void table_remove(Pool *pool, String_Handle h) { +void chunk_remove(Pool *pool, Chunk_Handle h) { (void) pool; (void) h; } -u8 *table_data(Pool *pool, String_Handle h) { - CHECK(pool != NULL, "Invalid arguments", NULL); - CHECK(h.offset >= 0 && h.size > 0, "Invalid arguments", NULL); - CHECK(h.offset + h.size <= pool->str_table.size, "Invalid handle", NULL); - - return pool->str_table.data + h.offset; -} +#ifdef __GNUC__ +__attribute__ ((warn_unused_result)) +#endif +Chunk_Handle chunk_resize(Pool *pool, Chunk_Handle h, i64 size) { + CHECK(pool != NULL, "Invalid arguments", (Chunk_Handle) {0}); + CHECK(size > 0, "Invalid arguments", (Chunk_Handle) {0}); + CHECK(h.offset >= 0 && h.size >= 0, "Invalid arguments", (Chunk_Handle) {0}); + CHECK(h.offset + h.size <= pool->size, "Invalid handle", (Chunk_Handle) {0}); -String_Handle table_resize(Pool *pool, String_Handle h, i64 size) { - CHECK(pool != NULL, "Invalid arguments", (String_Handle) {0}); - CHECK(size > 0, "Invalid arguments", (String_Handle) {0}); - CHECK(h.offset >= 0 && h.size > 0, "Invalid arguments", (String_Handle) {0}); - CHECK(h.offset + h.size <= pool->str_table.size, "Invalid handle", (String_Handle) {0}); + i64 chunk_size = align(size, CHUNK_TABLE_ALIGNMENT); + i64 prev_size = align(h.size, CHUNK_TABLE_ALIGNMENT); - if (h.size <= size) - return (String_Handle) { + if (chunk_size <= prev_size) + return (Chunk_Handle) { .size = size, .offset = h.offset, }; - if (h.offset + h.size == pool->str_table.size) { - CHECK(pool->str_table.size + size - h.size <= pool->str_table.capacity, "Out of memory", (String_Handle) {0}); + if (h.offset + h.size == pool->size) { + CHECK(pool->size + chunk_size - h.size <= pool->capacity, "Out of memory", (Chunk_Handle) {0}); - pool->str_table.size += size - h.size; + pool->size += chunk_size - prev_size; - return (String_Handle) { + return (Chunk_Handle) { .size = size, .offset = h.offset, }; } - CHECK(pool->str_table.size + size <= pool->str_table.capacity, "Out of memory", (String_Handle) {0}); + CHECK(pool->size + chunk_size <= pool->capacity, "Out of memory", (Chunk_Handle) {0}); - String_Handle dst = { + Chunk_Handle dst = { .size = size, - .offset = pool->str_table.size, + .offset = pool->size, }; - mem_cpy(pool->str_table.data + dst.offset, pool->str_table.data + h.offset, h.size); + mem_cpy(pool->data + dst.offset, pool->data + h.offset, h.size); - pool->str_table.size += size; + pool->size += chunk_size; return dst; } +u8 *chunk(Pool *pool, Chunk_Handle h) { + CHECK(pool != NULL, "Invalid arguments", NULL); + CHECK(h.offset >= 0 && h.size >= 0, "Invalid arguments", pool->data); + CHECK(h.offset + h.size <= pool->size, "Invalid handle", pool->data); + + if (h.size == 0) + return pool->data; + + return pool->data + h.offset; +} + +#define CHUNK(pool_, handle_, type_) ((type_ *) chunk((pool_), (handle_))) + +b8 entity_enabled(Pool *pool, i64 id) { + CHECK(pool != NULL, "Invalid arguments", 0); + CHECK(id != UNDEFINED, "Undefined", 0); + CHECK(id > 0 && id < pool->entities.size / (i64) sizeof(Entity), "Invalid id", 0); + Entity *entities = CHUNK(pool, pool->entities, Entity); + CHECK(entities != NULL, "Internal", 0); + return entities[id].is_enabled; +} + // ================================================================ // // * Semantic graph @@ -890,27 +848,83 @@ String_Handle table_resize(Pool *pool, String_Handle h, i64 size) { // i64 pool_add(Pool *pool, Entity data) { - if (pool->num_entities == 0) - ++pool->num_entities; + CHECK(pool != NULL && pool->data != NULL, "Invalid arguments", UNDEFINED); + + i64 num_entities = pool->entities.size / sizeof(Entity); + if (num_entities == UNDEFINED) + ++num_entities; - CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments", UNDEFINED); - CHECK(pool->num_entities < pool->capacity, "Out of memory", UNDEFINED); + i64 id = num_entities++; + data.is_enabled = 1; - i64 id = pool->num_entities++; - data.is_enabled = 1, - pool->entities[id] = data; + pool->entities = chunk_resize(pool, pool->entities, num_entities * sizeof(Entity)); + + CHECK(id != UNDEFINED, "Undefined", UNDEFINED); + CHECK(id < pool->entities.size / (i64) sizeof(Entity), "Buffer overflow", UNDEFINED); + + CHUNK(pool, pool->entities, Entity)[id] = data; - CHECK(id != UNDEFINED, "Sanity", UNDEFINED); return id; } void pool_remove(Pool *pool, i64 entity, u16 type) { - CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments",); - CHECK(entity >= 0 && entity < pool->num_entities, "Buffer overflow",); - CHECK(pool->entities[entity].is_enabled, "Entity already removed",); - CHECK(pool->entities[entity].type == type, "Invalid entity type",); + CHECK(pool != NULL && pool->data != NULL, "Invalid arguments",); + + i64 num_entities = pool->entities.size / sizeof(Entity); + Entity *entities = CHUNK(pool, pool->entities, Entity); + + CHECK(entity > UNDEFINED, "Undefined",); + CHECK(entity < num_entities, "Buffer overflow",); + + CHECK(entities[entity].is_enabled, "Entity already removed",); + CHECK(entities[entity].type == type, "Invalid entity type",); + + entities[entity] = (Entity) {0}; +} + +Node *node_by_id(Pool *pool, i64 id) { + CHECK(pool != NULL && pool->data != NULL, "Invalid arguments", NULL); + + i64 num_entities = pool->entities.size / sizeof(Entity); + Entity *entities = CHUNK(pool, pool->entities, Entity); + + CHECK(id != UNDEFINED, "Undefined", &entities->node); + CHECK(id > UNDEFINED && id < num_entities, "Buffer overflow", &entities->node); + + CHECK(entities[id].is_enabled, "No node", &entities->node); + CHECK(entities[id].type == ENTITY_NODE, "Invalid entity type", &entities->node); + + return &entities[id].node; +} - pool->entities[entity].is_enabled = 0; +Proc *proc_by_id(Pool *pool, i64 id) { + CHECK(pool != NULL && pool->data != NULL, "Invalid arguments", NULL); + + i64 num_entities = pool->entities.size / sizeof(Entity); + Entity *entities = CHUNK(pool, pool->entities, Entity); + + CHECK(id != UNDEFINED, "Undefined", &entities->proc); + CHECK(id > UNDEFINED && id < num_entities, "Buffer overflow", &entities->proc); + + CHECK(entities[id].is_enabled, "No proc", &entities->proc); + CHECK(entities[id].type == ENTITY_PROC, "Invalid entity type", &entities->proc); + + return &entities[id].proc; +} + +Unit *unit_by_id(Pool *pool, i64 id) { + CHECK(pool != NULL && pool->data != NULL, "Invalid arguments", NULL); + + i64 num_entities = pool->entities.size / sizeof(Entity); + Entity *entities = CHUNK(pool, pool->entities, Entity); + + CHECK(id != UNDEFINED, "Undefined", &entities->unit); + CHECK(id > UNDEFINED && id < num_entities, "Buffer overflow", &entities->unit); + + CHECK(entities[id].is_enabled, "No unit", &entities->unit); + CHECK(entities[id].type == ENTITY_UNIT, "Invalid entity type", &entities->unit); + + return &entities[id].unit; } i64 node_init(Pool *pool, Node data) { @@ -923,6 +937,7 @@ i64 node_init(Pool *pool, Node data) { } void node_destroy(Pool *pool, i64 node) { + // TODO pool_remove(pool, node, ENTITY_NODE); } @@ -934,36 +949,30 @@ i64 node_data_reference(Pool *pool, i64 node) { } i64 node_data_array_c8(Pool *pool, i64 size, c8 *data) { - CHECK(size < MAX_LITERAL_SIZE, "Too big", UNDEFINED); - Node node_entry = { - .op = DATA_I8, - .lit.num_bytes = size - }; - mem_cpy(node_entry.lit.as_u8, data, size); - return node_init(pool, node_entry); + return node_init(pool, (Node) { + .op = DATA_I8, + .lit = chunk_add(pool, size, data), + }); } i64 node_data_ptr(Pool *pool, u64 address) { return node_init(pool, (Node) { - .op = DATA_PTR, - .lit.num_bytes = sizeof address, - .lit.as_u64 = address, + .op = DATA_PTR, + .lit = chunk_add(pool, sizeof address, &address), }); } i64 node_data_i32(Pool *pool, i32 value) { return node_init(pool, (Node) { - .op = DATA_I32, - .lit.num_bytes = sizeof value, - .lit.as_i32 = value, + .op = DATA_I32, + .lit = chunk_add(pool, sizeof value, &value), }); } i64 node_data_i64(Pool *pool, i64 value) { return node_init(pool, (Node) { - .op = DATA_I64, - .lit.num_bytes = sizeof value, - .lit.as_i64 = value, + .op = DATA_I64, + .lit = chunk_add(pool, sizeof value, &value), }); } @@ -988,67 +997,44 @@ i64 node_data_sub(Pool *pool, Var x, Var y) { } u16 resolve_calling_convention(Pool *pool, i64 proc) { - CHECK(pool != NULL, "Invalid arguments", 0); - CHECK(proc != UNDEFINED, "Invalid arguments", 9); - CHECK(pool->entities[proc].is_enabled, "No entity", 0); - CHECK(pool->entities[proc].type == ENTITY_PROC, "No proc", 0); + Proc *p = proc_by_id(pool, proc); + CHECK(p != NULL, "No proc", CONV_UNKNOWN); - if (pool->entities[proc].proc.convention == CONV_UNKNOWN) - pool->entities[proc].proc.convention = CONV_CDECL; + if (p->convention == CONV_UNKNOWN) + p->convention = CONV_CDECL; - return pool->entities[proc].proc.convention; + return p->convention; } i64 node_ctrl_call(Pool *pool, i64 target_proc, i64 num_args, Var *args) { - CHECK(num_args <= MAX_NUM_ARGS, "Array too big", UNDEFINED); - - Call call = { - .convention = resolve_calling_convention(pool, target_proc), - .target_proc = target_proc, - .num_args = num_args, - }; - - if (num_args > 0) - mem_cpy(call.args, args, num_args * sizeof *args); - return node_init(pool, (Node) { .op = CTRL_CALL, - .call = call, + .call = { + .convention = resolve_calling_convention(pool, target_proc), + .target_proc = target_proc, + .args = chunk_add(pool, num_args * sizeof *args, args), + }, }); } i64 node_ctrl_call_by_name(Pool *pool, i64 name_size, c8 *name, i64 num_args, Var *args) { - CHECK(num_args <= MAX_NUM_ARGS, "Array too big", UNDEFINED); - - Call call = { - .convention = CONV_CDECL, - .target_proc = UNDEFINED, - .target_name_size = name_size, - .num_args = num_args, - }; - - if (name_size > 0) - mem_cpy(call.target_name, name, name_size); - if (num_args > 0) - mem_cpy(call.args, args, num_args * sizeof *args); - return node_init(pool, (Node) { .op = CTRL_CALL, - .call = call, + .call = { + .convention = CONV_CDECL, + .target_proc = UNDEFINED, + .target_name = chunk_add(pool, name_size, name), + .args = chunk_add(pool, num_args * sizeof *args, args), + }, }); } i64 node_ctrl_ret(Pool *pool, i64 num_values, Var *values) { - CHECK(num_values <= MAX_NUM_ARGS, "Array too big", UNDEFINED); - - Ret ret = { .num_vals = num_values, }; - - if (num_values > 0) - mem_cpy(ret.vals, values, num_values * sizeof *values); - return node_init(pool, (Node) { .op = CTRL_RET, - .ret = ret, + .ret = { + .vals = chunk_add(pool, num_values * sizeof *values, values) + }, }); } @@ -1063,89 +1049,77 @@ i64 proc_init(Pool *pool) { } void proc_destroy(Pool *pool, i64 proc) { + // TODO pool_remove(pool, proc, ENTITY_PROC); } void proc_set_convention(Pool *pool, i64 proc, u16 convention) { - CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments",); - CHECK(proc >= 0 && proc < pool->num_entities, "Buffer overflow",); - CHECK(pool->entities[proc].is_enabled, "Entity does not exist",); - CHECK(pool->entities[proc].type == ENTITY_PROC, "Invalid entity type",); + Proc *p = proc_by_id(pool, proc); + CHECK(p != NULL, "No proc",); - pool->entities[proc].proc.convention = convention; + p->convention = convention; } void proc_set_name(Pool *pool, i64 proc, i64 name_size, c8 *name) { - CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments",); - CHECK(proc >= 0 && proc < pool->num_entities, "Buffer overflow",); - CHECK(pool->entities[proc].is_enabled, "Entity does not exist",); - CHECK(pool->entities[proc].type == ENTITY_PROC, "Invalid entity type",); - - CHECK(name_size <= MAX_NAME_SIZE, "Name too big",); - CHECK(name_size >= 0, "Invalid arguments",); + Proc *p = proc_by_id(pool, proc); + CHECK(p != NULL, "No proc",); - Proc *p = &pool->entities[proc].proc; - p->name_size = name_size; - - if (name_size > 0) - mem_cpy(p->name, name, name_size); + p->name = chunk_resize(pool, p->name, name_size); + mem_cpy(chunk(pool, p->name), name, p->name.size); } void proc_node_add(Pool *pool, i64 proc, i64 node) { - CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments",); - CHECK(proc >= 0 && proc < pool->num_entities, "Buffer overflow",); - CHECK(pool->entities[proc].is_enabled, "Proc does not exist",); - CHECK(pool->entities[proc].type == ENTITY_PROC, "Invalid entity type",); - CHECK(pool->entities[node].is_enabled, "Node does not exist",); - CHECK(pool->entities[node].type == ENTITY_NODE, "Invalid entity type",); + Proc *p = proc_by_id(pool, proc); + Node *n = node_by_id(pool, node); - Proc *p = &pool->entities[proc].proc; - Node *n = &pool->entities[node].node; + CHECK(p != NULL, "No proc",); + CHECK(n != NULL, "No node",); CHECK(n->index_in_proc == UNDEFINED, "Internal",); - if (p->num_nodes == UNDEFINED) - ++p->num_nodes; + i64 num_nodes = p->nodes.size / sizeof(i64); - i64 index = p->num_nodes; + if (num_nodes == UNDEFINED) + ++num_nodes; - if (n->op == CTRL_RET) - { - // Only one return node is allowed. - // + i64 index = num_nodes++; + if (n->op == CTRL_RET) { + // Only one return node is allowed. CHECK(p->ret_index == UNDEFINED, "Internal",); p->ret_index = index; } - CHECK(index < MAX_NUM_NODES, "Out of memory",); - n->index_in_proc = index; - p->nodes[index] = node; - ++p->num_nodes; + + p->nodes = chunk_resize(pool, p->nodes, num_nodes * sizeof(i64)); + + CHECK(index != UNDEFINED, "Undefined",); + CHECK(index < p->nodes.size / (i64) sizeof(i64), "Buffer overflow",); + + CHUNK(pool, p->nodes, i64)[index] = node; } void proc_node_remove(Pool *pool, i64 proc, i64 node) { - CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments",); - CHECK(proc >= 0 && proc < pool->num_entities, "Buffer overflow",); - CHECK(node >= 0 && node < pool->num_entities, "Buffer overflow",); - CHECK(pool->entities[proc].is_enabled, "Entity does not exist",); - CHECK(pool->entities[proc].type == ENTITY_PROC, "Invalid entity type",); - CHECK(pool->entities[node].type == ENTITY_NODE, "Invalid entity type",); + Proc *p = proc_by_id(pool, proc); + Node *n = node_by_id(pool, node); - Proc *p = &pool->entities[proc].proc; - Node *n = &pool->entities[node].node; + CHECK(p != NULL, "No proc",); + CHECK(n != NULL, "No node",); - CHECK(n->index_in_proc != UNDEFINED, "Internal",); - CHECK(p->nodes[n->index_in_proc] == node, "Internal",); + i64 *nodes = CHUNK(pool, p->nodes, i64); + + CHECK(n->index_in_proc != UNDEFINED, "Undefined",); + CHECK(n->index_in_proc < p->nodes.size / (i64) sizeof(i64), "Buffer overflow",); + CHECK(nodes[n->index_in_proc] == node, "Internal",); if (n->op == CTRL_RET) { CHECK(p->ret_index != UNDEFINED, "Internal",); p->ret_index = UNDEFINED; } - p->nodes[n->index_in_proc] = UNDEFINED; - n->index_in_proc = UNDEFINED; + nodes[n->index_in_proc] = UNDEFINED; + n->index_in_proc = UNDEFINED; } i64 unit_init(Pool *pool, u16 type) { @@ -1163,84 +1137,93 @@ void unit_destroy(Pool *pool, i64 unit) { } void unit_proc_add(Pool *pool, i64 unit, i64 proc) { - CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments",); - CHECK(unit >= 0 && unit < pool->num_entities, "Buffer overflow",); - CHECK(proc >= 0 && proc < pool->num_entities, "Buffer overflow",); - CHECK(pool->entities[unit].is_enabled, "Unit does not exist",); - CHECK(pool->entities[unit].type == ENTITY_UNIT, "Invalid entity type",); - CHECK(pool->entities[proc].is_enabled, "Proc does not exist",); - CHECK(pool->entities[proc].type == ENTITY_PROC, "Invalid proc type",); + Unit *u = unit_by_id(pool, unit); + Proc *p = proc_by_id(pool, proc); - Unit *u = &pool->entities[unit].unit; - Proc *p = &pool->entities[proc].proc; + CHECK(u != NULL, "No unit",); + CHECK(p != NULL, "No proc",); CHECK(p->index_in_unit == UNDEFINED, "Internal",); - if (u->num_procs == UNDEFINED) - ++u->num_procs; + i64 num_procs = u->procs.size / sizeof(i64); + + i64 *procs = CHUNK(pool, u->procs, i64); + CHECK(procs != NULL, "Internal",); + + for (i64 i = 1; i < num_procs; ++i) + if (procs[i] == proc) + return; - i64 index = u->num_procs; + if (num_procs == UNDEFINED) + ++num_procs; - CHECK(index < MAX_NUM_PROCS, "Out of memory",); + i64 index = num_procs++; p->index_in_unit = index; - u->procs[index] = proc; - ++u->num_procs; + u->procs = chunk_resize(pool, u->procs, num_procs * sizeof(i64)); + + CHECK(index != UNDEFINED, "Undefined",); + CHECK(index < u->procs.size / (i64) sizeof(i64), "Buffer overflow",); + + CHUNK(pool, u->procs, i64)[index] = proc; } void unit_proc_remove(Pool *pool, i64 unit, i64 proc) { - CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments",); - CHECK(unit >= 0 && unit < pool->num_entities, "Buffer overflow",); - CHECK(proc >= 0 && proc < pool->num_entities, "Buffer overflow",); - CHECK(pool->entities[unit].is_enabled, "Unit does not exist",); - CHECK(pool->entities[unit].type == ENTITY_UNIT, "Invalid entity type",); - CHECK(pool->entities[proc].type == ENTITY_PROC, "Invalid entity type",); + Unit *u = unit_by_id(pool, unit); + Proc *p = proc_by_id(pool, proc); - Unit *u = &pool->entities[unit].unit; - Proc *p = &pool->entities[proc].proc; + CHECK(u != NULL, "No unit",); + CHECK(p != NULL, "No proc",); - CHECK(p->index_in_unit != UNDEFINED, "Internal",); - CHECK(u->procs[p->index_in_unit] == proc, "Internal",); + i64 *procs = CHUNK(pool, u->procs, i64); + + CHECK(p->index_in_unit != UNDEFINED, "Undefined",); + CHECK(p->index_in_unit < u->procs.size / (i64) sizeof(i64), "Buffer overflow",); + CHECK(procs[p->index_in_unit] == proc, "Internal",); if (u->entry_point_index == p->index_in_unit) u->entry_point_index = UNDEFINED; - u->procs[p->index_in_unit] = UNDEFINED; - p->index_in_unit = UNDEFINED; + procs[p->index_in_unit] = UNDEFINED; + p->index_in_unit = UNDEFINED; } void unit_link_add(Pool *pool, i64 unit, i64 link_unit) { - CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments",); - CHECK(unit >= 0 && unit < pool->num_entities, "Buffer overflow",); - CHECK(link_unit >= 0 && link_unit < pool->num_entities, "Buffer overflow",); - CHECK(pool->entities[unit].is_enabled, "Unit does not exist",); - CHECK(pool->entities[unit].type == ENTITY_UNIT, "Invalid entity type",); - CHECK(pool->entities[link_unit].is_enabled, "Link does not exist",); - CHECK(pool->entities[link_unit].type == ENTITY_UNIT, "Invalid entity type",); - - Unit *u = &pool->entities[unit].unit; - - for (i64 i = 0; i < u->num_links; ++i) - if (u->links[i] == link_unit) + Unit *u = unit_by_id(pool, unit); + CHECK(u != NULL, "No unit",); + + i64 num_links = u->links.size / sizeof(i64); + + i64 *links = CHUNK(pool, u->links, i64); + CHECK(links != NULL, "Internal",); + + for (i64 i = 1; i < num_links; ++i) + if (links[i] == link_unit) return; - CHECK(u->num_links < MAX_NUM_LINKS, "Internal",); - u->links[u->num_links++] = link_unit; + if (num_links == UNDEFINED) + ++num_links; + + i64 index = num_links++; + + u->links = chunk_resize(pool, u->links, num_links * sizeof(i64)); + + CHECK(index != UNDEFINED, "Undefined",); + CHECK(index < u->links.size / (i64) sizeof(i64), "Buffer overflow",); + + CHUNK(pool, u->links, i64)[index] = link_unit; } void unit_link_remove(Pool *pool, i64 unit, i64 link_unit) { - CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments",); - CHECK(unit >= 0 && unit < pool->num_entities, "Buffer overflow",); - CHECK(link_unit >= 0 && link_unit < pool->num_entities, "Buffer overflow",); - CHECK(pool->entities[unit].is_enabled, "Unit does not exist",); - CHECK(pool->entities[unit].type == ENTITY_UNIT, "Invalid entity type",); - CHECK(pool->entities[link_unit].type == ENTITY_UNIT, "Invalid entity type",); - - Unit *u = &pool->entities[unit].unit; - - for (i64 i = 0; i < u->num_links; ++i) - if (u->links[i] == link_unit) { - u->links[i] = UNDEFINED; + Unit *u = unit_by_id(pool, unit); + CHECK(u != NULL, "No unit",); + + i64 num_links = u->links.size / sizeof(i64); + i64 *links = CHUNK(pool, u->links, i64); + + for (i64 i = 1; i < num_links; ++i) + if (links[i] == link_unit) { + links[i] = UNDEFINED; return; } @@ -1248,44 +1231,31 @@ void unit_link_remove(Pool *pool, i64 unit, i64 link_unit) { } void unit_set_name(Pool *pool, i64 unit, i64 name_size, c8 *name) { - CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments",); - CHECK(unit >= 0 && unit < pool->num_entities, "Buffer overflow",); - CHECK(pool->entities[unit].is_enabled, "Unit does not exist",); - CHECK(pool->entities[unit].type == ENTITY_UNIT, "Invalid entity type",); + Unit *u = unit_by_id(pool, unit); + CHECK(u != NULL, "No unit",); - CHECK(name_size <= MAX_NAME_SIZE, "Name too big",); - CHECK(name_size >= 0, "Invalid arguments",); - - Unit *u = &pool->entities[unit].unit; - u->name_size = name_size; - - if (name_size > 0) - mem_cpy(u->name, name, name_size); + u->name = chunk_resize(pool, u->name, name_size); + CHECK(u->name.size == name_size, "Internal",); + mem_cpy(CHUNK(pool, u->name, c8), name, u->name.size); } void unit_set_entry_point(Pool *pool, i64 unit, i64 entry_point_proc) { - CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments",); - CHECK(unit >= 0 && unit < pool->num_entities, "Buffer overflow",); - CHECK(pool->entities[unit].is_enabled, "Unit does not exist",); - CHECK(pool->entities[unit].type == ENTITY_UNIT, "Invalid unit type",); - - Unit *u = &pool->entities[unit].unit; + Unit *u = unit_by_id(pool, unit); + CHECK(u != NULL, "No unit",); if (entry_point_proc == UNDEFINED) { u->entry_point_index = UNDEFINED; return; } - CHECK(entry_point_proc >= 0 && entry_point_proc < pool->num_entities, "Buffer overflow",); - CHECK(pool->entities[entry_point_proc].is_enabled, "Internal",); - CHECK(pool->entities[entry_point_proc].type == ENTITY_PROC, "Internal",); + Proc *p = proc_by_id(pool, entry_point_proc); + CHECK(p != NULL, "No proc",); - Proc *p = &pool->entities[entry_point_proc].proc; - - CHECK(p->index_in_unit != UNDEFINED, "Internal",); - CHECK(u->procs[p->index_in_unit] == entry_point_proc, "Internal",); + CHECK(p->index_in_unit != UNDEFINED, "Internal",); + CHECK(p->index_in_unit < u->procs.size / (i64) sizeof(i64), "Buffer overflow",); + CHECK(CHUNK(pool, u->procs, i64)[p->index_in_unit] == entry_point_proc, "Internal",); - pool->entities[unit].unit.entry_point_index = p->index_in_unit; + u->entry_point_index = p->index_in_unit; } // ================================================================ @@ -1934,6 +1904,18 @@ typedef struct { // Codegen // +void codegen_add_rel(Pool *pool, Codegen_Context *codegen, Codegen_Rel_Entry rel) { + CHECK(pool != NULL, "Invalid arguments",); + CHECK(codegen != NULL, "Invalid arguments",); + + i64 n = codegen->rels.size / sizeof(Codegen_Rel_Entry); + codegen->rels = chunk_resize(pool, codegen->rels, (n + 1) * sizeof(Codegen_Rel_Entry)); + CHECK(n < codegen->rels.size / (i64) sizeof(Codegen_Rel_Entry), "Buffer overflow",); + Codegen_Rel_Entry *rels = CHUNK(pool, codegen->rels, Codegen_Rel_Entry); + CHECK(rels != NULL, "Internal",); + rels[n] = rel; +} + void x86_64_emit_node( Pool * pool, Codegen_Context *codegen, @@ -1944,19 +1926,25 @@ void x86_64_emit_node( // FIXME Return success status. // TODO Log generated asm. - CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments",); - CHECK(node != UNDEFINED && pool->entities[node].is_enabled, "No node",); - CHECK(pool->entities[node].type == ENTITY_NODE, "Invalid entity",); + Node *n = node_by_id(pool, node); + CHECK(n != NULL, "No node",); + + codegen->buffer_code = chunk_resize(pool, codegen->buffer_code, codegen->offset_code + 64); - Node *n = &pool->entities[node].node; + u8 *begin = CHUNK(pool, codegen->buffer_code, u8) + codegen->offset_code; + u8 *end = begin + codegen->buffer_code.size; - u8 *begin = codegen->buffer_code + codegen->offset_code; - u8 *end = codegen->buffer_code + codegen->max_code_size; + CHECK(begin != NULL, "Internal",); + CHECK(end != NULL, "Internal",); - #define CHECK_NODE_(node_) \ - CHECK((node_) != UNDEFINED, "Internal",); \ - CHECK(pool->entities[(node_)].is_enabled, "Internal",); \ - CHECK(pool->entities[(node_)].type == ENTITY_NODE, "Internal",) + i64 num_entities = pool->entities.size / (i64) sizeof(Entity); + + if (codegen->entities.size / (i64) sizeof(Codegen_Entity) != num_entities) + codegen->entities = chunk_resize(pool, codegen->entities, num_entities * sizeof(Codegen_Entity)); + CHECK(num_entities == codegen->entities.size / (i64) sizeof(Codegen_Entity), "Buffer overflow",); + + Codegen_Entity *entities = CHUNK(pool, codegen->entities, Codegen_Entity); + CHECK(entities != NULL, "Internal",); switch (n->op) { case DATA_PTR: @@ -1970,11 +1958,11 @@ void x86_64_emit_node( case DATA_ADD: { // NOTE Assuming static single-assignment form. - CHECK_NODE_(n->add[0]); - CHECK_NODE_(n->add[1]); + Node *x = node_by_id(pool, n->add[0]); + Node *y = node_by_id(pool, n->add[1]); - Node *x = &pool->entities[n->add[0]].node; - Node *y = &pool->entities[n->add[1]].node; + CHECK(x != NULL, "No node",); + CHECK(y != NULL, "No node",); i64 dst_reg = 1; while (dst_reg <= 4 && ((1 << (dst_reg - 1)) & proc->occupied_reg) != 0) @@ -1986,15 +1974,17 @@ void x86_64_emit_node( switch (x->op) { case DATA_I32: { - write_u8 (LE, 0xb8, begin, end); // mov eax - write_u32(LE, x->lit.as_u32[0], begin + 1, end); + u32 val = CHUNK(pool, x->lit, u32)[0]; + + write_u8 (LE, 0xb8, begin, end); // mov eax + write_u32(LE, val, begin + 1, end); begin += 5; codegen->offset_code += 5; } break; case DATA_ADD: { - i64 src_reg = codegen->entities[n->add[0]].reg; + i64 src_reg = entities[n->add[0]].reg; switch (src_reg) { case 1: @@ -2038,7 +2028,7 @@ void x86_64_emit_node( FAIL("Not implemented",); } - codegen->entities[n->add[0]].reg = 0; + entities[n->add[0]].reg = 0; proc->occupied_reg &= ~(1 << (src_reg - 1)); } break; @@ -2048,14 +2038,16 @@ void x86_64_emit_node( switch (y->op) { case DATA_I32: { - write_u8 (LE, 0x05, begin, end); // add eax - write_u32(LE, y->lit.as_u32[0], begin + 1, end); + u32 val = CHUNK(pool, y->lit, u32)[0]; + + write_u8 (LE, 0x05, begin, end); // add eax + write_u32(LE, val, begin + 1, end); codegen->offset_code += 5; } break; case DATA_ADD: { - i64 src_reg = codegen->entities[n->add[1]].reg; + i64 src_reg = entities[n->add[1]].reg; switch (src_reg) { case 1: @@ -2104,7 +2096,7 @@ void x86_64_emit_node( FAIL("Not implemented",); } - codegen->entities[n->add[1]].reg = 0; + entities[n->add[1]].reg = 0; proc->occupied_reg &= ~(1 << (src_reg - 1)); } break; @@ -2118,8 +2110,10 @@ void x86_64_emit_node( switch (x->op) { case DATA_I32: { - write_u8 (LE, 0xbb, begin, end); // mov ebx - write_u32(LE, x->lit.as_u32[0], begin + 1, end); + u32 val = CHUNK(pool, x->lit, u32)[0]; + + write_u8 (LE, 0xbb, begin, end); // mov ebx + write_u32(LE, val, begin + 1, end); begin += 5; codegen->offset_code += 5; @@ -2127,7 +2121,7 @@ void x86_64_emit_node( case DATA_ADD: case DATA_SUB: { - i64 src_reg = codegen->entities[n->add[0]].reg; + i64 src_reg = entities[n->add[0]].reg; switch (src_reg) { case 1: @@ -2181,8 +2175,8 @@ void x86_64_emit_node( FAIL("Not implemented",); } - codegen->entities[n->add[0]].reg = 0; - proc->occupied_reg &= ~(1 << (src_reg - 1)); + entities[n->add[0]].reg = 0; + proc->occupied_reg &= ~(1 << (src_reg - 1)); } break; default: @@ -2191,15 +2185,17 @@ void x86_64_emit_node( switch (y->op) { case DATA_I32: { + u32 val = CHUNK(pool, y->lit, u32)[0]; + write_u8 (LE, 0x81, begin, end); // add ebx - write_u8 (LE, 0xc3, begin + 1, end); - write_u32(LE, y->lit.as_u32[0], begin + 2, end); + write_u8 (LE, 0xc3, begin + 1, end); + write_u32(LE, val, begin + 2, end); codegen->offset_code += 6; } break; case DATA_ADD: { - i64 src_reg = codegen->entities[n->add[1]].reg; + i64 src_reg = entities[n->add[1]].reg; switch (src_reg) { case 1: @@ -2250,8 +2246,8 @@ void x86_64_emit_node( FAIL("Not implemented",); } - codegen->entities[n->add[1]].reg = 0; - proc->occupied_reg &= ~(1 << (src_reg - 1)); + entities[n->add[1]].reg = 0; + proc->occupied_reg &= ~(1 << (src_reg - 1)); } break; default: @@ -2264,15 +2260,17 @@ void x86_64_emit_node( switch (x->op) { case DATA_I32: { - write_u8 (LE, 0xb9, begin, end); // mov ecx - write_u32(LE, x->lit.as_u32[0], begin + 1, end); + u32 val = CHUNK(pool, x->lit, u32)[0]; + + write_u8 (LE, 0xb9, begin, end); // mov ecx + write_u32(LE, val, begin + 1, end); begin += 5; codegen->offset_code += 5; } break; case DATA_ADD: { - i64 src_reg = codegen->entities[n->add[0]].reg; + i64 src_reg = entities[n->add[0]].reg; switch (src_reg) { case 1: @@ -2286,7 +2284,7 @@ void x86_64_emit_node( break; case 2: - FAIL("Not implemented",); + // FAIL("Not implemented",); // ebx write_u8(LE, 0x89, begin, end); // mov ecx @@ -2317,8 +2315,8 @@ void x86_64_emit_node( FAIL("Not implemented",); } - codegen->entities[n->add[0]].reg = 0; - proc->occupied_reg &= ~(1 << (src_reg - 1)); + entities[n->add[0]].reg = 0; + proc->occupied_reg &= ~(1 << (src_reg - 1)); } break; default: @@ -2327,15 +2325,17 @@ void x86_64_emit_node( switch (y->op) { case DATA_I32: { - write_u8 (LE, 0x81, begin, end); // add ecx - write_u8 (LE, 0xc1, begin + 1, end); - write_u32(LE, y->lit.as_u32[0], begin + 2, end); + u32 val = CHUNK(pool, y->lit, u32)[0]; + + write_u8 (LE, 0x81, begin, end); // add ecx + write_u8 (LE, 0xc1, begin + 1, end); + write_u32(LE, val, begin + 2, end); codegen->offset_code += 6; } break; case DATA_ADD: { - i64 src_reg = codegen->entities[n->add[1]].reg; + i64 src_reg = entities[n->add[1]].reg; switch (src_reg) { case 1: @@ -2386,8 +2386,8 @@ void x86_64_emit_node( FAIL("Not implemented",); } - codegen->entities[n->add[1]].reg = 0; - proc->occupied_reg &= ~(1 << (src_reg - 1)); + entities[n->add[1]].reg = 0; + proc->occupied_reg &= ~(1 << (src_reg - 1)); } break; default: @@ -2400,15 +2400,17 @@ void x86_64_emit_node( switch (x->op) { case DATA_I32: { - write_u8 (LE, 0xba, begin, end); // mov edx - write_u32(LE, x->lit.as_u32[0], begin + 1, end); + u32 val = CHUNK(pool, x->lit, u32)[0]; + + write_u8 (LE, 0xba, begin, end); // mov edx + write_u32(LE, val, begin + 1, end); begin += 5; codegen->offset_code += 5; } break; case DATA_ADD: { - i64 src_reg = codegen->entities[n->add[0]].reg; + i64 src_reg = entities[n->add[0]].reg; switch (src_reg) { case 1: @@ -2422,7 +2424,7 @@ void x86_64_emit_node( break; case 2: - FAIL("Not implemented",); + // FAIL("Not implemented",); // ebx write_u8(LE, 0x89, begin, end); // mov edx @@ -2452,8 +2454,8 @@ void x86_64_emit_node( FAIL("Not implemented",); } - codegen->entities[n->add[0]].reg = 0; - proc->occupied_reg &= ~(1 << (src_reg - 1)); + entities[n->add[0]].reg = 0; + proc->occupied_reg &= ~(1 << (src_reg - 1)); } break; default: @@ -2462,15 +2464,17 @@ void x86_64_emit_node( switch (y->op) { case DATA_I32: { - write_u8 (LE, 0x81, begin, end); // add edx - write_u8 (LE, 0xc2, begin + 1, end); - write_u32(LE, y->lit.as_u32[0], begin + 2, end); + u32 val = CHUNK(pool, y->lit, u32)[0]; + + write_u8 (LE, 0x81, begin, end); // add edx + write_u8 (LE, 0xc2, begin + 1, end); + write_u32(LE, val, begin + 2, end); codegen->offset_code += 6; } break; case DATA_ADD: { - i64 src_reg = codegen->entities[n->add[1]].reg; + i64 src_reg = entities[n->add[1]].reg; switch (src_reg) { case 1: @@ -2495,7 +2499,7 @@ void x86_64_emit_node( break; case 3: - FAIL("Not implemented",); + // FAIL("Not implemented",); // ecx write_u8(LE, 0x01, begin, end); // add edx @@ -2520,8 +2524,8 @@ void x86_64_emit_node( FAIL("Not implemented",); } - codegen->entities[n->add[1]].reg = 0; - proc->occupied_reg &= ~(1 << (src_reg - 1)); + entities[n->add[1]].reg = 0; + proc->occupied_reg &= ~(1 << (src_reg - 1)); } break; default: @@ -2538,7 +2542,7 @@ void x86_64_emit_node( } break; case DATA_ADD: { - i64 src_reg = codegen->entities[n->add[0]].reg; + i64 src_reg = entities[n->add[0]].reg; switch (src_reg) { case 1: @@ -2588,8 +2592,8 @@ void x86_64_emit_node( FAIL("Not implemented",); } - codegen->entities[n->add[0]].reg = 0; - proc->occupied_reg &= ~(1 << (src_reg - 1)); + entities[n->add[0]].reg = 0; + proc->occupied_reg &= ~(1 << (src_reg - 1)); } break; default: @@ -2602,7 +2606,7 @@ void x86_64_emit_node( } break; case DATA_ADD: { - i64 src_reg = codegen->entities[n->add[1]].reg; + i64 src_reg = entities[n->add[1]].reg; switch (src_reg) { case 1: @@ -2653,8 +2657,8 @@ void x86_64_emit_node( FAIL("Not implemented",); } - codegen->entities[n->add[1]].reg = 0; - proc->occupied_reg &= ~(1 << (src_reg - 1)); + entities[n->add[1]].reg = 0; + proc->occupied_reg &= ~(1 << (src_reg - 1)); } break; default: @@ -2666,18 +2670,18 @@ void x86_64_emit_node( FAIL("Not implemented",); } - codegen->entities[node].reg = dst_reg; - proc->occupied_reg |= 1 << (dst_reg - 1); + entities[node].reg = dst_reg; + proc->occupied_reg |= 1 << (dst_reg - 1); } break; case DATA_SUB: { // NOTE Assuming static single-assignment form. - CHECK_NODE_(n->sub[0]); - CHECK_NODE_(n->sub[1]); + Node *x = node_by_id(pool, n->sub[0]); + Node *y = node_by_id(pool, n->sub[1]); - Node *x = &pool->entities[n->sub[0]].node; - Node *y = &pool->entities[n->sub[1]].node; + CHECK(x != NULL, "No node",); + CHECK(y != NULL, "No node",); i64 dst_reg = 1; while (dst_reg <= 4 && ((1 << (dst_reg - 1)) & proc->occupied_reg) != 0) @@ -2689,8 +2693,10 @@ void x86_64_emit_node( switch (x->op) { case DATA_I32: { - write_u8 (LE, 0xb8, begin, end); // mov eax - write_u32(LE, x->lit.as_u32[0], begin + 1, end); + u32 val = CHUNK(pool, x->lit, u32)[0]; + + write_u8 (LE, 0xb8, begin, end); // mov eax + write_u32(LE, val, begin + 1, end); begin += 5; codegen->offset_code += 5; @@ -2707,8 +2713,10 @@ void x86_64_emit_node( switch (y->op) { case DATA_I32: { - write_u8 (LE, 0x2d, begin, end); // sub eax - write_u32(LE, y->lit.as_u32[0], begin + 1, end); + u32 val = CHUNK(pool, y->lit, u32)[0]; + + write_u8 (LE, 0x2d, begin, end); // sub eax + write_u32(LE, val, begin + 1, end); codegen->offset_code += 5; } break; @@ -2728,8 +2736,10 @@ void x86_64_emit_node( switch (x->op) { case DATA_I32: { - write_u8 (LE, 0xbb, begin, end); // mov ebx - write_u32(LE, x->lit.as_u32[0], begin + 1, end); + u32 val = CHUNK(pool, x->lit, u32)[0]; + + write_u8 (LE, 0xbb, begin, end); // mov ebx + write_u32(LE, val, begin + 1, end); begin += 5; codegen->offset_code += 5; @@ -2737,7 +2747,7 @@ void x86_64_emit_node( case DATA_ADD: case DATA_SUB: { - i64 src_reg = codegen->entities[n->add[0]].reg; + i64 src_reg = entities[n->add[0]].reg; switch (src_reg) { case 1: @@ -2791,8 +2801,8 @@ void x86_64_emit_node( FAIL("Not implemented",); } - codegen->entities[n->add[0]].reg = 0; - proc->occupied_reg &= ~(1 << (src_reg - 1)); + entities[n->add[0]].reg = 0; + proc->occupied_reg &= ~(1 << (src_reg - 1)); } break; default: @@ -2801,9 +2811,11 @@ void x86_64_emit_node( switch (y->op) { case DATA_I32: { - write_u8 (LE, 0x81, begin, end); // sub ebx - write_u8 (LE, 0xeb, begin + 1, end); - write_u32(LE, y->lit.as_u32[0], begin + 2, end); + u32 val = CHUNK(pool, y->lit, u32)[0]; + + write_u8 (LE, 0x81, begin, end); // sub ebx + write_u8 (LE, 0xeb, begin + 1, end); + write_u32(LE, val, begin + 2, end); codegen->offset_code += 6; } break; @@ -2837,34 +2849,38 @@ void x86_64_emit_node( FAIL("Not implemented",); } - codegen->entities[node].reg = dst_reg; - proc->occupied_reg |= 1 << (dst_reg - 1); + entities[node].reg = dst_reg; + proc->occupied_reg |= 1 << (dst_reg - 1); } break; case CTRL_CALL: { - CHECK(n->call.convention == CONV_CDECL, "Not implemented",); - CHECK(n->call.target_proc == UNDEFINED, "Not implemented",); - CHECK(n->call.target_name_size > 0, "No proc name",); - CHECK(codegen->num_rels + 2 <= codegen->max_num_rels, "Out of memory",); + CHECK(n->call.convention == CONV_CDECL, "Not implemented",); + CHECK(n->call.target_proc == UNDEFINED, "Not implemented",); + CHECK(n->call.target_name.size > 0, "No proc name",); - switch (n->call.num_args) { - case 1: { - i64 n_arg = n->call.args[0]; - CHECK_NODE_(n_arg); + i64 num_args = n->call.args.size / sizeof(i64); + i64 *args = CHUNK(pool, n->call.args, i64); + CHECK(args != NULL, "Internal",); - Node *arg = &pool->entities[n_arg].node; + switch (num_args) { + case 1: { + Node *arg = node_by_id(pool, args[0]); + CHECK(arg != NULL, "No node",); if (arg->op == DATA_REFERENCE) { // Write data // - Node *data = &pool->entities[arg->ref].node; + Node *data = node_by_id(pool, arg->ref); CHECK(data->op == DATA_I8, "Not implemented",); - CHECK(codegen->offset_ro_data + data->lit.num_bytes <= codegen->max_ro_data_size, "Out of memory",); - i64 arg_offset = codegen->offset_ro_data; - mem_cpy(codegen->buffer_ro_data + arg_offset, data->lit.as_u8, data->lit.num_bytes); + codegen->buffer_ro_data = chunk_resize(pool, codegen->buffer_ro_data, arg_offset + data->lit.size); + u8 *buf = CHUNK(pool, codegen->buffer_ro_data, u8); + CHECK(buf != NULL, "Internal",); + CHECK(arg_offset + data->lit.size <= codegen->buffer_ro_data.size, "Buffer overflow",); + + mem_cpy(buf + arg_offset, CHUNK(pool, data->lit, u8), data->lit.size); // Write code and relocations // @@ -2872,44 +2888,46 @@ void x86_64_emit_node( write_u8(LE, 0x48, begin, end); // movabs write_u8(LE, 0xbf, begin + 1, end); // rdi - codegen->rels[codegen->num_rels++] = (Codegen_Rel_Entry) { + codegen_add_rel(pool, codegen, (Codegen_Rel_Entry) { .type = REL_ADD_RO_DATA_ADDRESS, .offset = codegen->offset_code + 2, .size = 8, .value = arg_offset, - }; + }); write_u8(LE, 0x48, begin + 10, end); // movabs write_u8(LE, 0xb8, begin + 11, end); // rax - codegen->rels[codegen->num_rels++] = (Codegen_Rel_Entry) { + codegen_add_rel(pool, codegen, (Codegen_Rel_Entry) { .type = REL_ADD_PROC_ADDRESS, .offset = codegen->offset_code + 12, .size = 8, - .name_size = n->call.target_name_size, - .name = n->call.target_name, - }; + .name_size = n->call.target_name.size, + .name = CHUNK(pool, n->call.target_name, c8), + }); write_u8(LE, 0xff, begin + 20, end); // call write_u8(LE, 0xd0, begin + 21, end); // rax codegen->offset_code += 22; - codegen->offset_ro_data += data->lit.num_bytes; + codegen->offset_ro_data += data->lit.size; } else if (arg->op == DATA_I32) { - CHECK(arg->lit.num_bytes == 4, "Not implemented",); + CHECK(arg->lit.size == 4, "Not implemented",); - write_u8 (LE, 0xbf, begin, end); // mov edi - write_i32(LE, arg->lit.as_i32[0], begin + 1, end); - write_u8 (LE, 0x48, begin + 5, end); // movabs - write_u8 (LE, 0xb8, begin + 6, end); // rax + i32 val = CHUNK(pool, arg->lit, i32)[0]; - codegen->rels[codegen->num_rels++] = (Codegen_Rel_Entry) { + write_u8 (LE, 0xbf, begin, end); // mov edi + write_i32(LE, val, begin + 1, end); + write_u8 (LE, 0x48, begin + 5, end); // movabs + write_u8 (LE, 0xb8, begin + 6, end); // rax + + codegen_add_rel(pool, codegen, (Codegen_Rel_Entry) { .type = REL_ADD_PROC_ADDRESS, .offset = codegen->offset_code + 7, .size = 8, - .name_size = n->call.target_name_size, - .name = n->call.target_name, - }; + .name_size = n->call.target_name.size, + .name = CHUNK(pool, n->call.target_name, c8), + }); write_u8(LE, 0xff, begin + 11, end); // call write_u8(LE, 0xd0, begin + 12, end); // rax @@ -2921,24 +2939,21 @@ void x86_64_emit_node( } break; case 3: { - i64 n_arg_0 = n->call.args[0]; - i64 n_arg_1 = n->call.args[1]; - i64 n_arg_2 = n->call.args[2]; + Node *arg_0 = node_by_id(pool, args[0]); + Node *arg_1 = node_by_id(pool, args[1]); + Node *arg_2 = node_by_id(pool, args[2]); - CHECK_NODE_(n_arg_0); - CHECK_NODE_(n_arg_1); - CHECK_NODE_(n_arg_2); + CHECK(arg_0->op == DATA_PTR, "Not implemented",); + CHECK(arg_1->op == DATA_PTR, "Not implemented",); + CHECK(arg_2->op == DATA_PTR, "Not implemented",); - Node *arg_0 = &pool->entities[n_arg_0].node; - Node *arg_1 = &pool->entities[n_arg_1].node; - Node *arg_2 = &pool->entities[n_arg_2].node; + u64 val_0 = CHUNK(pool, arg_0->lit, u64)[0]; + u64 val_1 = CHUNK(pool, arg_1->lit, u64)[0]; + u64 val_2 = CHUNK(pool, arg_2->lit, u64)[0]; - CHECK(arg_0->op == DATA_PTR, "Not implemented",); - CHECK(arg_1->op == DATA_PTR, "Not implemented",); - CHECK(arg_2->op == DATA_PTR, "Not implemented",); - CHECK(arg_0->lit.as_u64[0] == 0, "Not implemented",); - CHECK(arg_1->lit.as_u64[0] == 0, "Not implemented",); - CHECK(arg_2->lit.as_u64[0] == 0, "Not implemented",); + CHECK(val_0 == 0, "Not implemented",); + CHECK(val_1 == 0, "Not implemented",); + CHECK(val_2 == 0, "Not implemented",); write_u8(LE, 0x31, begin, end); // xor edx write_u8(LE, 0xd2, begin + 1, end); // edx @@ -2949,13 +2964,13 @@ void x86_64_emit_node( write_u8(LE, 0x48, begin + 6, end); // movabs write_u8(LE, 0xb8, begin + 7, end); // rax - codegen->rels[codegen->num_rels++] = (Codegen_Rel_Entry) { + codegen_add_rel(pool, codegen, (Codegen_Rel_Entry) { .type = REL_ADD_PROC_ADDRESS, .offset = codegen->offset_code + 8, .size = 8, - .name_size = n->call.target_name_size, - .name = n->call.target_name, - }; + .name_size = n->call.target_name.size, + .name = CHUNK(pool, n->call.target_name, c8), + }); write_u8(LE, 0xff, begin + 16, end); // call write_u8(LE, 0xd0, begin + 17, end); // rax @@ -2964,29 +2979,13 @@ void x86_64_emit_node( } break; case 7: { - i64 n_arg_0 = n->call.args[0]; - i64 n_arg_1 = n->call.args[1]; - i64 n_arg_2 = n->call.args[2]; - i64 n_arg_3 = n->call.args[3]; - i64 n_arg_4 = n->call.args[4]; - i64 n_arg_5 = n->call.args[5]; - i64 n_arg_6 = n->call.args[6]; - - CHECK_NODE_(n_arg_0); - CHECK_NODE_(n_arg_1); - CHECK_NODE_(n_arg_2); - CHECK_NODE_(n_arg_3); - CHECK_NODE_(n_arg_4); - CHECK_NODE_(n_arg_5); - CHECK_NODE_(n_arg_6); - - Node *arg_0 = &pool->entities[n_arg_0].node; - Node *arg_1 = &pool->entities[n_arg_1].node; - Node *arg_2 = &pool->entities[n_arg_2].node; - Node *arg_3 = &pool->entities[n_arg_3].node; - Node *arg_4 = &pool->entities[n_arg_4].node; - Node *arg_5 = &pool->entities[n_arg_5].node; - Node *arg_6 = &pool->entities[n_arg_6].node; + Node *arg_0 = node_by_id(pool, args[0]); + Node *arg_1 = node_by_id(pool, args[1]); + Node *arg_2 = node_by_id(pool, args[2]); + Node *arg_3 = node_by_id(pool, args[3]); + Node *arg_4 = node_by_id(pool, args[4]); + Node *arg_5 = node_by_id(pool, args[5]); + Node *arg_6 = node_by_id(pool, args[6]); CHECK(arg_0->op == DATA_REFERENCE, "Not implemented",); CHECK(arg_1->op == DATA_I32, "Not implemented",); @@ -2996,24 +2995,23 @@ void x86_64_emit_node( CHECK(arg_5->op == DATA_PTR, "Not implemented",); CHECK(arg_6->op == DATA_PTR, "Not implemented",); - CHECK(arg_0->ref != UNDEFINED, "Internal",); - CHECK(pool->entities[arg_0->ref].is_enabled, "Internal",); - CHECK(arg_2->ref != UNDEFINED, "Internal",); - CHECK(pool->entities[arg_2->ref].is_enabled, "Internal",); - - CHECK(pool->entities[arg_0->ref].type == ENTITY_PROC, "Not implemented",); - CHECK(pool->entities[arg_2->ref].type == ENTITY_NODE, "Not implemented",); + Proc *dat_0 = proc_by_id(pool, arg_0->ref); + CHECK(dat_0 != NULL, "No proc",); // Write data // - Node *dat_2 = &pool->entities[arg_2->ref].node; + Node *dat_2 = node_by_id(pool, arg_2->ref); + CHECK(dat_2 != NULL, "No node",); CHECK(dat_2->op == DATA_PTR, "Not implemented",); - CHECK(codegen->offset_ro_data + dat_2->lit.num_bytes <= codegen->max_ro_data_size, "Out of memory",); - i64 arg_2_offset = codegen->offset_ro_data; - mem_cpy(codegen->buffer_ro_data + arg_2_offset, dat_2->lit.as_u8, dat_2->lit.num_bytes); + codegen->buffer_ro_data = chunk_resize(pool, codegen->buffer_ro_data, arg_2_offset + dat_2->lit.size); + u8 *buf = CHUNK(pool, codegen->buffer_ro_data, u8); + CHECK(buf != NULL, "Internal",); + CHECK(arg_2_offset + dat_2->lit.size <= codegen->buffer_ro_data.size, "Buffer overflow",); + + mem_cpy(buf + arg_2_offset, CHUNK(pool, dat_2->lit, u8), dat_2->lit.size); // Write code and relocations // @@ -3021,34 +3019,40 @@ void x86_64_emit_node( write_u8 (LE, 0x48, begin, end); // movabs write_u8 (LE, 0xbf, begin + 1, end); // rdi - codegen->rels[codegen->num_rels++] = (Codegen_Rel_Entry) { - .type = REL_ADD_PROC_ADDRESS, - .offset = codegen->offset_code + 2, - .size = 8, - .proc = arg_0->ref, - }; + codegen_add_rel(pool, codegen, (Codegen_Rel_Entry) { + .type = REL_ADD_PROC_ADDRESS, + .offset = codegen->offset_code + 2, + .size = 8, + .proc = arg_0->ref, + }); + + u32 val_1 = CHUNK(pool, arg_1->lit, u32)[0]; - write_u8 (LE, 0xbe, begin + 10, end); // mov esi - write_u32(LE, arg_1->lit.as_u32[0], begin + 11, end); - write_u8 (LE, 0x48, begin + 15, end); // movabs - write_u8 (LE, 0xba, begin + 16, end); // rdx + write_u8 (LE, 0xbe, begin + 10, end); // mov esi + write_u32(LE, val_1, begin + 11, end); + write_u8 (LE, 0x48, begin + 15, end); // movabs + write_u8 (LE, 0xba, begin + 16, end); // rdx - codegen->rels[codegen->num_rels++] = (Codegen_Rel_Entry) { + codegen_add_rel(pool, codegen, (Codegen_Rel_Entry) { .type = REL_ADD_RO_DATA_ADDRESS, .offset = codegen->offset_code + 17, .size = 8, .value = arg_2_offset, - }; - - write_u8 (LE, 0x48, begin + 25, end); // movabs - write_u8 (LE, 0xb9, begin + 26, end); // rcx - write_u64(LE, arg_3->lit.as_u64[0], begin + 27, end); - write_u8 (LE, 0x48, begin + 35, end); // movabs - write_u8 (LE, 0xb8, begin + 36, end); // r8 - write_u64(LE, arg_4->lit.as_u64[0], begin + 37, end); - write_u8 (LE, 0x48, begin + 45, end); // movabs - write_u8 (LE, 0xb9, begin + 46, end); // r9 - write_u64(LE, arg_5->lit.as_u64[0], begin + 47, end); + }); + + u64 val_3 = CHUNK(pool, arg_3->lit, u64)[0]; + u64 val_4 = CHUNK(pool, arg_4->lit, u64)[0]; + u64 val_5 = CHUNK(pool, arg_5->lit, u64)[0]; + + write_u8 (LE, 0x48, begin + 25, end); // movabs + write_u8 (LE, 0xb9, begin + 26, end); // rcx + write_u64(LE, val_3, begin + 27, end); + write_u8 (LE, 0x48, begin + 35, end); // movabs + write_u8 (LE, 0xb8, begin + 36, end); // r8 + write_u64(LE, val_4, begin + 37, end); + write_u8 (LE, 0x48, begin + 45, end); // movabs + write_u8 (LE, 0xb9, begin + 46, end); // r9 + write_u64(LE, val_5, begin + 47, end); // rsp alignment write_u8(LE, 0x48, begin + 55, end); // sub rsp @@ -3056,21 +3060,23 @@ void x86_64_emit_node( write_u8(LE, 0xec, begin + 57, end); // write_u8(LE, 8, begin + 58, end); // 8 - write_u8 (LE, 0x48, begin + 59, end); // movabs - write_u8 (LE, 0xb8, begin + 60, end); // rax - write_u64(LE, arg_6->lit.as_u64[0], begin + 61, end); - write_u8 (LE, 0x50, begin + 69, end); // push rax + u64 val_6 = CHUNK(pool, arg_6->lit, u64)[0]; + + write_u8 (LE, 0x48, begin + 59, end); // movabs + write_u8 (LE, 0xb8, begin + 60, end); // rax + write_u64(LE, val_6, begin + 61, end); + write_u8 (LE, 0x50, begin + 69, end); // push rax write_u8 (LE, 0x48, begin + 70, end); // movabs write_u8 (LE, 0xb8, begin + 71, end); // rax - codegen->rels[codegen->num_rels++] = (Codegen_Rel_Entry) { + codegen_add_rel(pool, codegen, (Codegen_Rel_Entry) { .type = REL_ADD_PROC_ADDRESS, .offset = codegen->offset_code + 72, .size = 8, - .name_size = n->call.target_name_size, - .name = n->call.target_name, - }; + .name_size = n->call.target_name.size, + .name = CHUNK(pool, n->call.target_name, c8), + }); write_u8(LE, 0xff, begin + 80, end); // call write_u8(LE, 0xd0, begin + 81, end); // rax @@ -3081,7 +3087,7 @@ void x86_64_emit_node( write_u8(LE, 16, begin + 85, end); // 16 codegen->offset_code += 86; - codegen->offset_ro_data += dat_2->lit.num_bytes; + codegen->offset_ro_data += dat_2->lit.size; } break; default: @@ -3090,8 +3096,12 @@ void x86_64_emit_node( } break; case CTRL_RET: { + i64 num_vals = n->ret.vals.size / sizeof(i64); + i64 *vals = CHUNK(pool, n->ret.vals, i64); + CHECK(vals != NULL, "Internal",); + if ((context & EMIT_ENTRY_PROC) != 0) { - if (n->ret.num_vals == 0) { + if (num_vals == 0) { write_u8 (LE, 0xb8, begin, end); // mov eax write_u32(LE, 60, begin + 1, end); // 60 @@ -3103,35 +3113,33 @@ void x86_64_emit_node( codegen->offset_code += 12; } else { - if (n->ret.num_vals > 1) + if (num_vals > 1) LOG(WARNING, "Some return values are ignored for node %lld", node); - i64 n_val = n->ret.vals[0]; - CHECK(n_val != UNDEFINED, "Internal",); - CHECK(pool->entities[n_val].is_enabled, "Internal",); - CHECK(pool->entities[n_val].type == ENTITY_NODE, "Internal",); - - Node *val = &pool->entities[n_val].node; + Node *val = node_by_id(pool, vals[0]); + CHECK(val != NULL, "No node",); switch (val->op) { case DATA_I64: { - CHECK(val->lit.num_bytes == 8, "Not implemented",); + CHECK(val->lit.size == 8, "Not implemented",); - write_u8 (LE, 0xb8, begin, end); // mov eax - write_u32(LE, 60, begin + 1, end); // 60 + u32 a = CHUNK(pool, val->lit, u32)[0]; - write_u8 (LE, 0xbf, begin + 5, end); // mov edi - write_u32(LE, val->lit.as_u32[0], begin + 6, end); + write_u8 (LE, 0xb8, begin, end); // mov eax + write_u32(LE, 60, begin + 1, end); // 60 - write_u8 (LE, 0x0f, begin + 10, end); // syscall - write_u8 (LE, 0x05, begin + 11, end); + write_u8 (LE, 0xbf, begin + 5, end); // mov edi + write_u32(LE, a, begin + 6, end); + + write_u8 (LE, 0x0f, begin + 10, end); // syscall + write_u8 (LE, 0x05, begin + 11, end); codegen->offset_code += 12; } break; case DATA_ADD: case DATA_SUB: { - switch (codegen->entities[n_val].reg) { + switch (entities[vals[0]].reg) { case 1: // eax break; @@ -3187,28 +3195,25 @@ void x86_64_emit_node( } } } else { - CHECK(n->ret.num_vals == 1, "Not implemented",); - - i64 n_val = n->ret.vals[0]; - CHECK(n_val != UNDEFINED, "Internal",); - CHECK(pool->entities[n_val].is_enabled, "Internal",); - CHECK(pool->entities[n_val].type == ENTITY_NODE, "Internal",); + CHECK(num_vals == 1, "Not implemented",); - Node *val = &pool->entities[n_val].node; + Node *val = node_by_id(pool, vals[0]); switch (val->op) { case DATA_I32: { - CHECK(val->lit.num_bytes == 4, "Not implemented",); + CHECK(val->lit.size == 4, "Not implemented",); - write_u8 (LE, 0xb8, begin, end); // mov eax - write_u32(LE, val->lit.as_u32[0], begin + 1, end); - write_u8 (LE, 0xc3, begin + 5, end); // ret + u32 a = CHUNK(pool, val->lit, u32)[0]; + + write_u8 (LE, 0xb8, begin, end); // mov eax + write_u32(LE, a, begin + 1, end); + write_u8 (LE, 0xc3, begin + 5, end); // ret codegen->offset_code += 6; } break; case DATA_ADD: { - CHECK(codegen->entities[n_val].reg == 1, "Not implemented",); + CHECK(entities[vals[0]].reg == 1, "Not implemented",); write_u8(LE, 0xc3, begin, end); // ret @@ -3235,44 +3240,61 @@ void emit_proc( u16 arch, u32 context ) { - CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments",); - CHECK(proc != UNDEFINED && pool->entities[proc].is_enabled, "No proc",); - CHECK(pool->entities[proc].type == ENTITY_PROC, "Invalid entity",); - CHECK(arch == ARCH_X86_64, "Target not supported",); + CHECK(arch == ARCH_X86_64, "Target not supported",); + + Proc *p = proc_by_id(pool, proc); + CHECK(p != NULL, "No proc",); - Proc *p = &pool->entities[proc].proc; + i64 num_entities = pool->entities.size / (i64) sizeof(Entity); + if (codegen->entities.size / (i64) sizeof(Codegen_Entity) < num_entities) + codegen->entities = chunk_resize(pool, codegen->entities, num_entities * sizeof(Codegen_Entity)); + CHECK(codegen->entities.size / (i64) sizeof(Codegen_Entity) >= num_entities, "Buffer overflow",); - CHECK(codegen->entities[proc].emit_done == 0, "Emit already done",); + Codegen_Entity *entities = CHUNK(pool, codegen->entities, Codegen_Entity); + CHECK(entities != NULL, "Internal",); + CHECK(proc < codegen->entities.size / (i64) sizeof(Codegen_Entity), "Buffer overflow",); + CHECK(entities[proc].emit_done == 0, "Emit already done",); - codegen->entities[proc].offset = codegen->offset_code; + entities[proc].offset = codegen->offset_code; // TODO Sort nodes in the sequential execution order. // // NOTE // Now we assume that nodes are already sorted. - for (i64 i = 1; i < p->num_nodes; ++i) - x86_64_emit_node(pool, codegen, codegen->entities + proc, p->nodes[i], context); + i64 num_nodes = p->nodes.size / sizeof(i64); + i64 *nodes = CHUNK(pool, p->nodes, i64); + CHECK(nodes != NULL, "Internal",); + + for (i64 i = 1; i < num_nodes; ++i) + if (entity_enabled(pool, nodes[i])) + x86_64_emit_node(pool, codegen, entities + proc, nodes[i], context); - codegen->entities[proc].emit_done = 1; + entities[proc].emit_done = 1; } void emit_unit(Pool *pool, Codegen_Context *codegen, i64 unit, u16 arch) { - CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments",); - CHECK(unit != UNDEFINED && pool->entities[unit].is_enabled, "No unit",); - CHECK(pool->entities[unit].type == ENTITY_UNIT, "Invalid entity",); + Unit *u = unit_by_id(pool, unit); + CHECK(u != NULL, "No unit",); + + i64 num_procs = u->procs.size / sizeof(i64); + i64 *procs = CHUNK(pool, u->procs, i64); + CHECK(procs != NULL, "Internal",); + + for (i64 i = 1; i < num_procs; ++i) { + if (!entity_enabled(pool, procs[i])) + continue; - for (i64 i = 1; i < pool->entities[unit].unit.num_procs; ++i) { u32 context = 0; - if (i == pool->entities[unit].unit.entry_point_index) { + if (i == u->entry_point_index) { CHECK(!codegen->has_entry, "Multiple entry points",); codegen->entry_point = codegen->offset_code; codegen->has_entry = 1; context |= EMIT_ENTRY_PROC; } - emit_proc(pool, codegen, pool->entities[unit].unit.procs[i], arch, context); + emit_proc(pool, codegen, procs[i], arch, context); } } @@ -3281,6 +3303,18 @@ void emit_unit(Pool *pool, Codegen_Context *codegen, i64 unit, u16 arch) { // Linking // +void link_add_symbol(Pool *pool, Linker_Context *linker, Link_Sym_Entry sym) { + CHECK(pool != NULL, "Invalid arguments",); + CHECK(linker != NULL, "Invalid arguments",); + + i64 n = linker->symbols.size / sizeof(Link_Sym_Entry); + linker->symbols = chunk_resize(pool, linker->symbols, (n + 1) * sizeof(Link_Sym_Entry)); + Link_Sym_Entry *syms = CHUNK(pool, linker->symbols, Link_Sym_Entry); + CHECK(syms != NULL, "Internal",); + CHECK(n < linker->symbols.size / (i64) sizeof(Link_Sym_Entry), "Buffer overflow",); + syms[n] = sym; +} + i64 ar_find_symbol_offset_by_name( u8 *ar_symbol_table, u8 *ar_end, @@ -3314,16 +3348,23 @@ i64 ar_find_symbol_offset_by_name( } Buffer_Context elf_buffer_context( + Pool * pool, Linker_Context *linker, i64 num_obj_files, i64 elf_index ) { + u8 * dependencies_buffer = CHUNK(pool, linker->dependencies_buffer, u8); + i64 *obj_file_offsets = CHUNK(pool, linker->obj_file_offsets, i64); + + CHECK(num_obj_files < linker->obj_file_offsets.size / (i64) sizeof(i64), "Buffer overflow", (Buffer_Context) {0}); + CHECK(obj_file_offsets[num_obj_files] < linker->dependencies_buffer.size, "Buffer overflow", (Buffer_Context) {0}); + return (Buffer_Context) { - .begin = linker->dependencies_buffer, - .end = linker->dependencies_buffer + linker->obj_file_offsets[num_obj_files], + .begin = dependencies_buffer, + .end = dependencies_buffer + obj_file_offsets[num_obj_files], .elf = { - .offset = linker->obj_file_offsets[elf_index], - .size = linker->obj_file_offsets[elf_index + 1] - linker->obj_file_offsets[elf_index], + .offset = obj_file_offsets[elf_index], + .size = obj_file_offsets[elf_index + 1] - obj_file_offsets[elf_index], }, .obj_index = elf_index, }; @@ -3647,13 +3688,7 @@ i64 unit_write_in_memory( u16 format, u16 arch ) { - CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments", 0); - CHECK(unit != UNDEFINED && pool->entities[unit].is_enabled, "No unit", 0); - CHECK(pool->entities[unit].type == ENTITY_UNIT, "Invalid entity", 0); - CHECK(format == FORMAT_ELF && arch == ARCH_X86_64, "Target not supported", 0); - CHECK(linker->obj_file_buffer != NULL, "No object file buffer", 0); - CHECK(linker->dependencies_buffer != NULL, "No dependencies buffer", 0); - CHECK(linker->obj_file_offsets != NULL, "No object file offsets buffer", 0); + CHECK(format == FORMAT_ELF && arch == ARCH_X86_64, "Target not supported", 0); emit_unit(pool, codegen, unit, arch); @@ -3680,15 +3715,13 @@ i64 unit_write_in_memory( // Calculate section offsets for (i64 elf_index = 0; elf_index < linker->num_obj_files; ++elf_index) { - Buffer_Context buf = elf_buffer_context(linker, linker->num_obj_files, elf_index); + Buffer_Context buf = elf_buffer_context(pool, linker, linker->num_obj_files, elf_index); elf_checks(buf); Offset_Num headers = elf_section_headers(buf); for (i64 sec_index = 1; sec_index < headers.num; ++sec_index, ++num_sections_total) { - CHECK(num_sections_total < linker->max_num_sections, "Too many sections", 0); - Elf_Section_Header section = elf_section(buf, sec_index); c8 * name = elf_name_from_offset(buf, section.name); @@ -3705,16 +3738,21 @@ i64 unit_write_in_memory( if (!section.alloc || section.data.size == 0) continue; + linker->sections = chunk_resize(pool, linker->sections, (num_sections_total + 1) * sizeof(Link_Sec_Entry)); + Link_Sec_Entry *sections = CHUNK(pool, linker->sections, Link_Sec_Entry); + CHECK(sections != NULL, "Internal", 0); + CHECK(num_sections_total < linker->sections.size / (i64) sizeof(Link_Sec_Entry), "Buffer overflow", 0); + if (section.tls) { if (section.type == SEC_PROGBITS) { - linker->sections[num_sections_total].offset = rw_tls_data_size; - linker->sections[num_sections_total].address = rw_tls_data_size; + sections[num_sections_total].offset = rw_tls_data_size; + sections[num_sections_total].address = rw_tls_data_size; rw_tls_data_size += align(section.data.size, X86_64_ALIGNMENT); continue; } if (section.type == SEC_NOBITS) { - linker->sections[num_sections_total].address = rw_tls_zval_size; + sections[num_sections_total].address = rw_tls_zval_size; rw_tls_zval_size += align(section.data.size, X86_64_ALIGNMENT); continue; } @@ -3729,27 +3767,27 @@ i64 unit_write_in_memory( if (section.exec) { CHECK(!section.write, "Not implemented", 0); - linker->sections[num_sections_total].offset = rx_code_size; - linker->sections[num_sections_total].address = rx_code_size; + sections[num_sections_total].offset = rx_code_size; + sections[num_sections_total].address = rx_code_size; rx_code_size += align(section.data.size, X86_64_ALIGNMENT); continue; } if (section.write && section.type == SEC_NOBITS) { - linker->sections[num_sections_total].address = rw_zval_size; + sections[num_sections_total].address = rw_zval_size; rw_zval_size += align(section.data.size, X86_64_ALIGNMENT); continue; } if (section.write) { - linker->sections[num_sections_total].offset = rw_data_size; - linker->sections[num_sections_total].address = rw_data_size; + sections[num_sections_total].offset = rw_data_size; + sections[num_sections_total].address = rw_data_size; rw_data_size += align(section.data.size, X86_64_ALIGNMENT); continue; } - linker->sections[num_sections_total].offset = ro_data_size; - linker->sections[num_sections_total].address = ro_data_size; + sections[num_sections_total].offset = ro_data_size; + sections[num_sections_total].address = ro_data_size; ro_data_size += align(section.data.size, X86_64_ALIGNMENT); } } @@ -3761,7 +3799,7 @@ i64 unit_write_in_memory( i64 prev_num_symbols = num_symbols; for (i64 elf_index = 0; elf_index < linker->num_obj_files; ++elf_index) { - Buffer_Context buf = elf_buffer_context(linker, linker->num_obj_files, elf_index); + Buffer_Context buf = elf_buffer_context(pool, linker, linker->num_obj_files, elf_index); i64 num_sections = elf_section_headers(buf).num; Offset_Size strtab = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data; @@ -3787,16 +3825,20 @@ i64 unit_write_in_memory( if (!STR_EQ(relx.symbol.name.size, sym_name, "_DYNAMIC")) { b8 found = 0; + Link_Sym_Entry *symbols = CHUNK(pool, linker->symbols, Link_Sym_Entry); + CHECK(symbols != NULL, "Internal", 0); + CHECK(num_symbols <= linker->symbols.size / (i64) sizeof(Link_Sym_Entry), "Buffer overflow", 0); + for (i64 i = 0; i < num_symbols; ++i) if (relx.symbol.name.size > 0) { - if (str_eq(linker->symbols[i].name_size, linker->symbols[i].name, relx.symbol.name.size, sym_name)) { + if (str_eq(symbols[i].name_size, symbols[i].name, relx.symbol.name.size, sym_name)) { found = 1; break; } } else { - if (linker->symbols[i].obj_index == relx.symbol.obj_index && - linker->symbols[i].sec_index == relx.symbol.section && - linker->symbols[i].address == relx.symbol.value.offset) { + if (symbols[i].obj_index == relx.symbol.obj_index && + symbols[i].sec_index == relx.symbol.section && + symbols[i].address == relx.symbol.value.offset) { found = 1; break; } @@ -3805,14 +3847,14 @@ i64 unit_write_in_memory( if (found) break; - CHECK(num_symbols < linker->max_num_symbols, "Out of memory", 0); - linker->symbols[num_symbols++] = (Link_Sym_Entry) { + link_add_symbol(pool, linker, (Link_Sym_Entry) { .name_size = relx.symbol.name.size, .name = sym_name, .address = relx.symbol.value.offset, .obj_index = relx.symbol.obj_index, .sec_index = relx.symbol.section, - }; + }); + rw_got_size += ELF_GOT_ENTRY_SIZE; } break; @@ -3848,7 +3890,7 @@ i64 unit_write_in_memory( // ---------------------------------------------------------- for (i64 elf_index = 0, sec_index_global = 0; elf_index < linker->num_obj_files; ++elf_index) { - Buffer_Context buf = elf_buffer_context(linker, linker->num_obj_files, elf_index); + Buffer_Context buf = elf_buffer_context(pool, linker, linker->num_obj_files, elf_index); Offset_Num headers = elf_section_headers(buf); for (i64 sec_index = 1; sec_index < headers.num; ++sec_index, ++sec_index_global) { @@ -3870,15 +3912,19 @@ i64 unit_write_in_memory( if (!section.alloc || section.data.size == 0) continue; + Link_Sec_Entry *sections = CHUNK(pool, linker->sections, Link_Sec_Entry); + CHECK(sections != NULL, "Internal", 0); + CHECK(sec_index_global < linker->sections.size / (i64) sizeof(Link_Sec_Entry), "Buffer overflow", 0); + if (section.tls) { if (section.type == SEC_PROGBITS) { - linker->sections[sec_index_global].offset += rw_tls_data_offset; - linker->sections[sec_index_global].address += rw_tls_data_address; + sections[sec_index_global].offset += rw_tls_data_offset; + sections[sec_index_global].address += rw_tls_data_address; continue; } if (section.type == SEC_NOBITS) { - linker->sections[sec_index_global].address += rw_tls_zval_address; + sections[sec_index_global].address += rw_tls_zval_address; continue; } @@ -3892,24 +3938,24 @@ i64 unit_write_in_memory( if (section.exec) { CHECK(!section.write, "Not implemented", 0); - linker->sections[sec_index_global].offset += rx_code_offset + codegen->offset_code; - linker->sections[sec_index_global].address += rx_code_address + codegen->offset_code; + sections[sec_index_global].offset += rx_code_offset + codegen->offset_code; + sections[sec_index_global].address += rx_code_address + codegen->offset_code; continue; } if (section.write && section.type == SEC_NOBITS) { - linker->sections[sec_index_global].address += rw_zval_address; + sections[sec_index_global].address += rw_zval_address; continue; } if (section.write) { - linker->sections[sec_index_global].offset += rw_data_offset; - linker->sections[sec_index_global].address += rw_data_address; + sections[sec_index_global].offset += rw_data_offset; + sections[sec_index_global].address += rw_data_address; continue; } - linker->sections[sec_index_global].offset += ro_data_offset + codegen->offset_ro_data; - linker->sections[sec_index_global].address += ro_data_address + codegen->offset_ro_data; + sections[sec_index_global].offset += ro_data_offset + codegen->offset_ro_data; + sections[sec_index_global].address += ro_data_address + codegen->offset_ro_data; } } @@ -3918,7 +3964,7 @@ i64 unit_write_in_memory( // Relocate defined symbols for (i64 elf_index = 0, sec_index_global = 0; elf_index < linker->num_obj_files; ++elf_index) { - Buffer_Context buf = elf_buffer_context(linker, linker->num_obj_files, elf_index); + Buffer_Context buf = elf_buffer_context(pool, linker, linker->num_obj_files, elf_index); Offset_Num headers = elf_section_headers(buf); Offset_Size strtab = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data; @@ -3944,21 +3990,23 @@ i64 unit_write_in_memory( i64 sym_address = sym.value.offset; + Link_Sec_Entry *sections = CHUNK(pool, linker->sections, Link_Sec_Entry); + CHECK(sections != NULL, "Internal", 0); + if (sym.section != 65521 && elf_section(buf, sym.section).alloc) { i64 sym_section = sec_index_global + sym.section - 1; - CHECK(sym_section < num_sections_total, "Buffer overflow", 0); - CHECK(linker->sections[sym_section].address != 0, "Sanity", 0); - sym_address += linker->sections[sym_section].address; + CHECK(sym_section < linker->sections.size / (i64) sizeof(Link_Sec_Entry), "Buffer overflow", 0); + CHECK(sym_section < num_sections_total, "Buffer overflow", 0); + CHECK(sections[sym_section].address != 0, "Sanity", 0); + sym_address += sections[sym_section].address; } - CHECK(num_symbols < linker->max_num_symbols, "Too many symbols", 0); - - linker->symbols[num_symbols++] = (Link_Sym_Entry) { + link_add_symbol(pool, linker, (Link_Sym_Entry) { .name_size = sym.name.size, .name = sym_name, .address = sym_address, .size = sym.value.size, - }; + }); u8 *begin = buf.begin + tab.data.offset + sym_index * ELF_SYMBOL_ENTRY_SIZE; u8 *end = begin + tab.data.size; @@ -3979,43 +4027,55 @@ i64 unit_write_in_memory( // // Add runtime library symbols - #define ADD_UNIQUE_(i_, name_, ...) \ - do { \ - b8 found_ = 0; \ - for (i_ = 0; i_ < num_symbols; ++i_) \ - if (STR_EQ(linker->symbols[i_].name_size, \ - linker->symbols[i_].name, \ - name_)) { \ - found_ = 1; \ - break; \ - } \ - CHECK(!found_, "Forbidden symbol: " name_, 0); \ - CHECK(num_symbols < linker->max_num_symbols, "Too many symbols", 0); \ - linker->symbols[num_symbols++] = (Link_Sym_Entry) { \ - .name_size = sizeof name_ - 1, \ - .name = name_, \ - __VA_ARGS__ \ - }; \ + #define ADD_UNIQUE_(i_, name_, ...) \ + do { \ + b8 found_ = 0; \ + Link_Sym_Entry *symbols_ = \ + CHUNK(pool, linker->symbols, Link_Sym_Entry); \ + CHECK(symbols_ != NULL, "Internal", 0); \ + CHECK(num_symbols <= \ + linker->symbols.size / \ + (i64) sizeof(Link_Sym_Entry), \ + "Buffer overflow", 0); \ + for (i_ = 0; i_ < num_symbols; ++i_) \ + if (STR_EQ(symbols_[i_].name_size, \ + symbols_[i_].name, \ + name_)) { \ + found_ = 1; \ + break; \ + } \ + CHECK(!found_, "Forbidden symbol: " name_, 0); \ + link_add_symbol(pool, linker, (Link_Sym_Entry) { \ + .name_size = sizeof name_ - 1, \ + .name = name_, \ + __VA_ARGS__ \ + }); \ } while (0) - #define ADD_IF_MISSING_(name_, ...) \ - do { \ - b8 found_ = 0; \ - for (i_ = 0; i_ < num_symbols; ++i_) \ - if (STR_EQ(linker->symbols[i_].name_size, \ - linker->symbols[i_].name, \ - name_)) { \ - found_ = 1; \ - break; \ - } \ - if (!found_) { \ - CHECK(num_symbols < linker->max_num_symbols, "Too many symbols", 0); \ - linker->symbols[num_symbols++] = (Link_Sym_Entry) { \ - .name_size = sizeof name_ - 1, \ - .name = name_, \ - __VA_ARGS__ \ - }; \ - } \ + #define ADD_IF_MISSING_(name_, ...) \ + do { \ + b8 found_ = 0; \ + Link_Sym_Entry *symbols_ = \ + CHUNK(pool, linker->symbols, Link_Sym_Entry); \ + CHECK(symbols_ != NULL, "Internal", 0); \ + CHECK(num_symbols <= \ + linker->symbols.size / \ + (i64) sizeof(Link_Sym_Entry), \ + "Buffer overflow", 0); \ + for (i_ = 0; i_ < num_symbols; ++i_) \ + if (STR_EQ(symbols_[i_].name_size, \ + symbols_[i_].name, \ + name_)) { \ + found_ = 1; \ + break; \ + } \ + if (!found_) { \ + link_add_symbol(pool, linker, (Link_Sym_Entry) { \ + .name_size = sizeof name_ - 1, \ + .name = name_, \ + __VA_ARGS__ \ + }); \ + } \ } while (0) // ---------------------------------------------------------- @@ -4090,7 +4150,7 @@ i64 unit_write_in_memory( rel_index_global = 0, got_offset = 0; elf_index < linker->num_obj_files; ++elf_index) { - Buffer_Context buf = elf_buffer_context(linker, linker->num_obj_files, elf_index); + Buffer_Context buf = elf_buffer_context(pool, linker, linker->num_obj_files, elf_index); i64 num_sections = elf_section_headers(buf).num; Offset_Size strtab = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data; @@ -4101,9 +4161,8 @@ i64 unit_write_in_memory( if (src_sec.type != SEC_REL && src_sec.type != SEC_RELA) continue; - i64 dst_index = elf_find_related_section_index(buf, sec_index); - i64 dst_index_global = sec_index_global + dst_index - 1; - CHECK(dst_index_global >= 0 && dst_index_global < linker->max_num_sections, "Buffer overflow", 0); + // i64 dst_index = elf_find_related_section_index(buf, sec_index); + // i64 dst_index_global = sec_index_global + dst_index - 1; for (i64 entry_index = 0; entry_index < src_sec.num_entries; ++entry_index, ++rel_index_global) { Elf_Relx_Entry relx = elf_relx(buf, symtab, strtab, src_sec.data, entry_index, src_sec.type == SEC_RELA); @@ -4113,31 +4172,41 @@ i64 unit_write_in_memory( CHECK(relx.symbol.section != 65521, "Sanity", 0); CHECK(relx.symbol.section != 65522, "Sanity", 0); - CHECK(num_symbols < linker->max_num_symbols, "Out of memory", 0); - if (relx.symbol.section == 0) { b8 found = 0; - for (i64 i = 0; i < pool->num_entities; ++i) - if (pool->entities[i].is_enabled && - pool->entities[i].type == ENTITY_PROC && - str_eq(pool->entities[i].proc.name_size, - pool->entities[i].proc.name, + i64 num_entities = pool->entities.size / sizeof(Entity); + Entity *entities = CHUNK(pool, pool->entities, Entity); + CHECK(entities != NULL, "Internal", 0); + + Codegen_Entity *codegen_entities = CHUNK(pool, codegen->entities, Codegen_Entity); + CHECK(codegen_entities != NULL, "Internal", 0); + CHECK(codegen->entities.size / (i64) sizeof(Codegen_Entity) >= num_entities, "Buffer overflow", 0); + + for (i64 i = 0; i < num_entities; ++i) + if (entities[i].is_enabled && + entities[i].type == ENTITY_PROC && + str_eq(entities[i].proc.name.size, + CHUNK(pool, entities[i].proc.name, c8), relx.symbol.name.size, sym_name)) { - CHECK(codegen->entities[i].emit_done, "No proc code", 0); + CHECK(codegen_entities[i].emit_done, "No proc code", 0); - linker->symbols[num_symbols++] = (Link_Sym_Entry) { - .address = rx_code_address + codegen->entities[i].offset, + link_add_symbol(pool, linker, (Link_Sym_Entry) { + .address = rx_code_address + codegen_entities[i].offset, .size = relx.symbol.value.size, - }; + }); found = 1; break; } + Link_Sym_Entry *symbols = CHUNK(pool, linker->symbols, Link_Sym_Entry); + CHECK(symbols != NULL, "Internal", 0); + CHECK(num_symbols <= linker->symbols.size / (i64) sizeof(Link_Sym_Entry), "Buffer overflow", 0); + if (!found) for (i64 i = 0; i < num_symbols; ++i) - if (str_eq(linker->symbols[i].name_size, linker->symbols[i].name, relx.symbol.name.size, sym_name)) { + if (str_eq(symbols[i].name_size, symbols[i].name, relx.symbol.name.size, sym_name)) { sym_index_global = i; found = 1; break; @@ -4150,44 +4219,63 @@ i64 unit_write_in_memory( } else { i64 const SEARCH_RANGE = 1024; + Link_Sec_Entry *sections = CHUNK(pool, linker->sections, Link_Sec_Entry); + CHECK(sections != NULL, "Internal", 0); + CHECK(sec_index_global < linker->sections.size / (i64) sizeof(Link_Sec_Entry), "Buffer overflow", 0); + + Link_Sym_Entry *symbols = CHUNK(pool, linker->symbols, Link_Sym_Entry); + CHECK(symbols != NULL, "Internal", 0); + CHECK(num_symbols <= linker->symbols.size / (i64) sizeof(Link_Sym_Entry), "Buffer overflow", 0); + i64 src_index_global = sec_index_global + relx.symbol.section - 1; - i64 address = relx.symbol.value.offset + linker->sections[src_index_global].address; + i64 address = relx.symbol.value.offset + sections[src_index_global].address; b8 found = 0; for (i64 k = 1; k <= num_symbols && k <= SEARCH_RANGE; ++k) - if (linker->symbols[num_symbols - k].address == address) { + if (symbols[num_symbols - k].address == address) { sym_index_global = num_symbols - k; found = 1; break; } if (!found) - linker->symbols[num_symbols++] = (Link_Sym_Entry) { + link_add_symbol(pool, linker, (Link_Sym_Entry) { .address = address, .size = relx.symbol.value.size, - }; + }); } if (sym_index_global >= num_symbols) LOG(ERROR, "Symbol: %s", sym_name); - CHECK(sym_index_global < num_symbols, "Symbol not found", 0); - CHECK(rel_index_global < linker->max_num_rels, "Out of memory", 0); + CHECK(sym_index_global < num_symbols, "Symbol not found", 0); - linker->rels[rel_index_global].symbol = sym_index_global; + i64 num_rels = linker->rels.size / sizeof(Link_Rel_Entry); + if (rel_index_global >= num_rels) { + num_rels = rel_index_global + 1; + linker->rels = chunk_resize(pool, linker->rels, num_rels * sizeof(Link_Rel_Entry)); + } + Link_Rel_Entry *rels = CHUNK(pool, linker->rels, Link_Rel_Entry); + CHECK(rels != NULL, "Internal", 0); + CHECK(rel_index_global < linker->rels.size / (i64) sizeof(Link_Rel_Entry), "Buffer overflow", 0); + + rels[rel_index_global].symbol = sym_index_global; switch (relx.type) { case R_X86_64_GOT32: case R_X86_64_GOTPCREL: case R_X86_64_GOTPCRELX: - case R_X86_64_REX_GOTPCRELX: + case R_X86_64_REX_GOTPCRELX: { + Link_Sym_Entry *symbols = CHUNK(pool, linker->symbols, Link_Sym_Entry); + CHECK(symbols != NULL, "Internal", 0); + if (!STR_EQ(relx.symbol.name.size, sym_name, "_DYNAMIC") && - linker->symbols[sym_index_global].got_offset == 0) { + symbols[sym_index_global].got_offset == 0) { got_offset += ELF_GOT_ENTRY_SIZE; CHECK(got_offset < rw_got_size, "Sanity", 0); - linker->symbols[sym_index_global].got_offset = got_offset; + symbols[sym_index_global].got_offset = got_offset; } - break; + } break; default:; } @@ -4202,7 +4290,7 @@ i64 unit_write_in_memory( // Apply relocations for (i64 elf_index = 0, sec_index_global = 0, rel_index_global = 0; elf_index < linker->num_obj_files; ++elf_index) { - Buffer_Context buf = elf_buffer_context(linker, linker->num_obj_files, elf_index); + Buffer_Context buf = elf_buffer_context(pool, linker, linker->num_obj_files, elf_index); i64 num_sections = elf_section_headers(buf).num; Offset_Size strtab = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data; @@ -4215,12 +4303,19 @@ i64 unit_write_in_memory( i64 dst_index = elf_find_related_section_index(buf, sec_index); i64 dst_index_global = sec_index_global + dst_index - 1; - CHECK(dst_index_global >= 0 && dst_index_global < linker->max_num_sections, "Buffer overflow", 0); for (i64 entry_index = 0; entry_index < src_sec.num_entries; ++entry_index, ++rel_index_global) { + Link_Rel_Entry *rels = CHUNK(pool, linker->rels, Link_Rel_Entry); + Link_Sym_Entry *symbols = CHUNK(pool, linker->symbols, Link_Sym_Entry); + Link_Sec_Entry *sections = CHUNK(pool, linker->sections, Link_Sec_Entry); + + CHECK(rels != NULL, "Internal", 0); + CHECK(symbols != NULL, "Internal", 0); + CHECK(sections != NULL, "Internal", 0); + Elf_Relx_Entry relx = elf_relx(buf, symtab, strtab, src_sec.data, entry_index, src_sec.type == SEC_RELA); c8 * sym_name = elf_name_from_offset(buf, relx.symbol.name); - Link_Sym_Entry symbol = linker->symbols[linker->rels[rel_index_global].symbol]; + Link_Sym_Entry symbol = symbols[rels[rel_index_global].symbol]; u8 *dst = buf.begin + elf_section(buf, dst_index).data.offset + relx.offset; @@ -4230,10 +4325,10 @@ i64 unit_write_in_memory( i64 A = relx.addent; // Represents the base address at which a shared object has been loaded into memory during execution. Generally, a shared object is built with a 0 base virtual address, but the execution address will be different. - i64 B = linker->sections[dst_index_global].address; + i64 B = sections[dst_index_global].address; // Represents the place (section offset or address) of the storage unit being relocated (computed using r_offset). - i64 P = linker->sections[dst_index_global].address + relx.offset; + i64 P = sections[dst_index_global].address + relx.offset; // Represents the value of the symbol whose index resides in the relocation entry. i64 S = symbol.address; @@ -4367,12 +4462,16 @@ i64 unit_write_in_memory( // // Apply internal relocations - #define FIND_(x) \ - do { for (i64 i = 0; i < num_symbols; ++i) \ - if (STR_EQ(linker->symbols[i].name_size, linker->symbols[i].name, #x)) { \ - LOG(INFO, "Found " #x ": 0x%llx", linker->symbols[i].address); \ - break; \ - } } while (0) + #define FIND_(x) \ + do { \ + Link_Sym_Entry *symbols_ = CHUNK(pool, linker->symbols, Link_Sym_Entry); \ + CHECK(symbols_ != NULL, "Internal", 0); \ + for (i64 i = 0; i < num_symbols; ++i) \ + if (STR_EQ(symbols_[i].name_size, symbols_[i].name, #x)) { \ + LOG(INFO, "Found " #x ": 0x%llx", symbols_[i].address); \ + break; \ + } \ + } while (0) FIND_(_start); FIND_(__libc_start_main); @@ -4382,11 +4481,18 @@ i64 unit_write_in_memory( #undef FIND_ - for (i64 rel_index = 0; rel_index < codegen->num_rels; ++rel_index) { - Codegen_Rel_Entry rel = codegen->rels[rel_index]; + i64 num_rels = codegen->rels.size / sizeof(Codegen_Rel_Entry); + Codegen_Rel_Entry *rels = CHUNK(pool, codegen->rels, Codegen_Rel_Entry); + CHECK(rels != NULL, "Internal", 0); + + for (i64 rel_index = 0; rel_index < num_rels; ++rel_index) { + Codegen_Rel_Entry rel = rels[rel_index]; - u8 *begin = codegen->buffer_code + rel.offset; - u8 *end = codegen->buffer_code + codegen->offset_code; + u8 *buffer_code = CHUNK(pool, codegen->buffer_code, u8); + CHECK(buffer_code != NULL, "Internal", 0); + + u8 *begin = buffer_code + rel.offset; + u8 *end = buffer_code + codegen->offset_code; switch (rel.type) { case REL_ADD_INSTRUCTION_ADDRESS: { @@ -4409,12 +4515,15 @@ i64 unit_write_in_memory( if (rel.proc == UNDEFINED) { CHECK(rel.name_size > 0 && rel.name != NULL, "No proc name", 0); + Link_Sym_Entry *symbols = CHUNK(pool, linker->symbols, Link_Sym_Entry); + CHECK(symbols != NULL, "Internal", 0); + for (i64 i = 0; i < num_symbols; ++i) - if (linker->symbols[i].address != 0 && - str_eq(linker->symbols[i].name_size, - linker->symbols[i].name, + if (symbols[i].address != 0 && + str_eq(symbols[i].name_size, + symbols[i].name, rel.name_size, rel.name)) { - i64 value = rel.value + linker->symbols[i].address; + i64 value = rel.value + symbols[i].address; write_i64(LE, value, begin, end); found = 1; @@ -4422,11 +4531,20 @@ i64 unit_write_in_memory( break; } } else { - CHECK(pool->entities[rel.proc].is_enabled, "No entity", 0); - CHECK(pool->entities[rel.proc].type == ENTITY_PROC, "No proc", 0); - CHECK(codegen->entities[rel.proc].emit_done, "No proc address", 0); + i64 num_entities = pool->entities.size / sizeof(Entity); + Entity *entities = CHUNK(pool, pool->entities, Entity); + + Codegen_Entity *codegen_entities = CHUNK(pool, codegen->entities, Codegen_Entity); + CHECK(codegen_entities != NULL, "Internal", 0); + + CHECK(rel.proc != UNDEFINED, "Undefined", 0); + CHECK(rel.proc > 0 && rel.proc < num_entities, "Buffer overflow", 0); + CHECK(entities != NULL, "Internal", 0); + CHECK(entities[rel.proc].is_enabled, "No entity", 0); + CHECK(entities[rel.proc].type == ENTITY_PROC, "No proc", 0); + CHECK(codegen_entities[rel.proc].emit_done, "No proc address", 0); - i64 value = rel.value + rx_code_address + codegen->entities[rel.proc].offset; + i64 value = rel.value + rx_code_address + codegen_entities[rel.proc].offset; write_i64(LE, value, begin, end); found = 1; @@ -4447,7 +4565,6 @@ i64 unit_write_in_memory( // i64 output_size = align(rw_tls_data_offset + rw_tls_data_size, X86_64_PAGE_SIZE); - CHECK(output_size <= linker->max_output_size, "Out of memory", 0); i64 entry = rx_code_address + codegen->entry_point; @@ -4456,9 +4573,12 @@ i64 unit_write_in_memory( b8 found = 0; + Link_Sym_Entry *symbols = CHUNK(pool, linker->symbols, Link_Sym_Entry); + CHECK(symbols != NULL, "Internal", 0); + for (i64 sym_index = 0; sym_index < num_symbols; ++sym_index) - if (STR_EQ(linker->symbols[sym_index].name_size, linker->symbols[sym_index].name, "_start")) { - entry = linker->symbols[sym_index].address; + if (STR_EQ(symbols[sym_index].name_size, symbols[sym_index].name, "_start")) { + entry = symbols[sym_index].address; found = 1; break; } @@ -4483,8 +4603,10 @@ i64 unit_write_in_memory( LOG(VERBOSE, "Writing ELF x86_64 executable"); - u8 *o = linker->output_buffer; - u8 *o_end = o + linker->max_output_size; + linker->output_buffer = chunk_resize(pool, linker->output_buffer, output_size); + + u8 *o = CHUNK(pool, linker->output_buffer, u8); + u8 *o_end = o + linker->output_buffer.size; // ELF header // @@ -4646,20 +4768,29 @@ i64 unit_write_in_memory( // Code // - mem_cpy(o + rx_code_offset, codegen->buffer_code, codegen->offset_code); - mem_cpy(o + ro_data_offset, codegen->buffer_ro_data, codegen->offset_ro_data); + u8 *buffer_code = CHUNK(pool, codegen->buffer_code, u8); + u8 *buffer_ro_data = CHUNK(pool, codegen->buffer_ro_data, u8); + + CHECK(buffer_code != NULL, "Internal", 0); + CHECK(buffer_ro_data != NULL, "Internal", 0); + + mem_cpy(o + rx_code_offset, buffer_code, codegen->offset_code); + mem_cpy(o + ro_data_offset, buffer_ro_data, codegen->offset_ro_data); // ============================================================== // // Write sections into the output buffer + Link_Sec_Entry *sections = CHUNK(pool, linker->sections, Link_Sec_Entry); + CHECK(sections != NULL, "Internal", 0); + for (i64 elf_index = 0, sec_index_global = 0; elf_index < linker->num_obj_files; ++elf_index) { - Buffer_Context buf = elf_buffer_context(linker, linker->num_obj_files, elf_index); + Buffer_Context buf = elf_buffer_context(pool, linker, linker->num_obj_files, elf_index); Offset_Num headers = elf_section_headers(buf); for (i64 sec_index = 1; sec_index < headers.num; ++sec_index, ++sec_index_global) { Elf_Section_Header section = elf_section(buf, sec_index); - i64 offset = linker->sections[sec_index_global].offset; + i64 offset = sections[sec_index_global].offset; if (offset == 0 || !section.alloc || section.data.size == 0) @@ -4675,8 +4806,11 @@ i64 unit_write_in_memory( write_u64(LE, rw_dynamic_address, o + rw_got_offset, o_end); + Link_Sym_Entry *symbols = CHUNK(pool, linker->symbols, Link_Sym_Entry); + CHECK(symbols != NULL, "Internal", 0); + for (i64 i = 0, offset = 0; i < num_symbols; ++i) { - Link_Sym_Entry *sym = linker->symbols + i; + Link_Sym_Entry *sym = symbols + i; if (sym->got_offset == 0) continue; @@ -4692,14 +4826,15 @@ i64 unit_write_in_memory( void unit_write( Pool * pool, - Codegen_Context *codegen, - Linker_Context * linker, i64 unit, u16 format, u16 arch, i64 io_out, void * io_user_data ) { + Codegen_Context codegen = {0}; + Linker_Context linker = {0}; + CHECK(unit != UNDEFINED, "Invalid unit",); // ============================================================== @@ -4708,47 +4843,58 @@ void unit_write( i64 obj_files_size = 0; - Unit *u = &pool->entities[unit].unit; + Unit *u = unit_by_id(pool, unit); - for (i64 link_index = 0; link_index < u->num_links; ++link_index) { - i64 id = u->links[link_index]; + i64 num_links = u->links.size / sizeof(i64); + i64 *links = CHUNK(pool, u->links, i64); + CHECK(links != NULL, "Internal",); + + for (i64 link_index = 1; link_index < num_links; ++link_index) { + i64 id = links[link_index]; if (id == UNDEFINED) continue; - Unit *l = &pool->entities[id].unit; - CHECK(pool->entities[id].is_enabled, "Internal",); - CHECK(l->name_size > 0, "No link name",); - CHECK(l->name_size <= MAX_NAME_SIZE, "Link name too big",); + Unit *l = unit_by_id(pool, id); + CHECK(entity_enabled(pool, id), "Internal",); + CHECK(l->name.size > 0, "No link name",); switch (l->type) { case UNIT_LIBRARY_OBJECT: { - i64 f = io_open_read(l->name_size, l->name, io_user_data); + i64 f = io_open_read(l->name.size, CHUNK(pool, l->name, c8), io_user_data); io_seek(f, 0, IO_SEEK_END, io_user_data); i64 in_size = io_tell(f, io_user_data); - CHECK(in_size <= linker->max_obj_file_size, "Object file too big",); - CHECK(obj_files_size + in_size < linker->max_dependencies_size, "Out of memory",); - CHECK(linker->num_obj_files + 1 < linker->max_num_obj_files, "Out of memory",); + + linker.dependencies_buffer = chunk_resize(pool, linker.dependencies_buffer, obj_files_size + in_size); + u8 *dependencies_buffer = CHUNK(pool, linker.dependencies_buffer, u8); + CHECK(dependencies_buffer != NULL, "Internal",); io_seek(f, 0, IO_SEEK_BEGIN, io_user_data); - i64 n = io_read(f, in_size, linker->dependencies_buffer + obj_files_size, io_user_data); + i64 n = io_read(f, in_size, dependencies_buffer + obj_files_size, io_user_data); CHECK(n == in_size, "Read failed",); io_close(f, io_user_data); - linker->obj_file_offsets[linker->num_obj_files] = obj_files_size; - obj_files_size += align(in_size, X86_64_ALIGNMENT); - linker->obj_file_offsets[++linker->num_obj_files] = obj_files_size; + linker.obj_file_offsets = chunk_resize(pool, linker.obj_file_offsets, (linker.num_obj_files + 2) * sizeof(i64)); + i64 *obj_file_offsets = CHUNK(pool, linker.obj_file_offsets, i64); + CHECK(obj_file_offsets != NULL, "Internal",); + + obj_file_offsets[linker.num_obj_files] = obj_files_size; + obj_files_size += align(in_size, X86_64_ALIGNMENT); + obj_file_offsets[++linker.num_obj_files] = obj_files_size; } break; case UNIT_LIBRARY_STATIC: { - i64 f = io_open_read(l->name_size, l->name, io_user_data); + i64 f = io_open_read(l->name.size, CHUNK(pool, l->name, c8), io_user_data); io_seek(f, 0, IO_SEEK_END, io_user_data); i64 in_size = io_tell(f, io_user_data); - CHECK(in_size <= linker->max_obj_file_size, "AR file too big",); + + linker.obj_file_buffer = chunk_resize(pool, linker.obj_file_buffer, in_size); + u8 *obj_file_buffer = CHUNK(pool, linker.obj_file_buffer, u8); + CHECK(obj_file_buffer != NULL, "Internal",); io_seek(f, 0, IO_SEEK_BEGIN, io_user_data); - i64 n = io_read(f, in_size, linker->obj_file_buffer, io_user_data); + i64 n = io_read(f, in_size, obj_file_buffer, io_user_data); CHECK(n == in_size, "Read failed",); io_close(f, io_user_data); @@ -4757,8 +4903,8 @@ void unit_write( // // Read AR library - u8 *ar_begin = linker->obj_file_buffer; - u8 *ar_end = linker->obj_file_buffer + in_size; + u8 *ar_begin = obj_file_buffer; + u8 *ar_end = obj_file_buffer + in_size; CHECK(mem_eq(ar_begin, AR_MAGIC, 8), "Invalid AR file",); @@ -4783,14 +4929,17 @@ void unit_write( i64 delta_size = align(size, X86_64_ALIGNMENT); - CHECK(obj_files_size + delta_size < linker->max_dependencies_size, "Out of memory",); - CHECK(linker->num_obj_files + 1 < linker->max_num_obj_files, "Out of memory",); + u8 *dependencies_buffer = CHUNK(pool, linker.dependencies_buffer, u8); + CHECK(dependencies_buffer != NULL, "Internal",); + + mem_cpy(dependencies_buffer + obj_files_size, f_data, size); - mem_cpy(linker->dependencies_buffer + obj_files_size, f_data, size); + i64 *obj_file_offsets = CHUNK(pool, linker.obj_file_offsets, i64); + CHECK(obj_file_offsets != NULL, "Internal",); - linker->obj_file_offsets[linker->num_obj_files] = obj_files_size; - obj_files_size += delta_size; - linker->obj_file_offsets[++linker->num_obj_files] = obj_files_size; + obj_file_offsets[linker.num_obj_files] = obj_files_size; + obj_files_size += delta_size; + obj_file_offsets[++linker.num_obj_files] = obj_files_size; } f_begin = f_data + size; @@ -4804,36 +4953,33 @@ void unit_write( // ============================================================== - i64 output_size = unit_write_in_memory(pool, codegen, linker, unit, format, arch); + i64 output_size = unit_write_in_memory(pool, &codegen, &linker, unit, format, arch); // ============================================================== // // Write the output buffer into the file - io_write(io_out, output_size, linker->output_buffer, io_user_data); + u8 *output_buffer = CHUNK(pool, linker.output_buffer, u8); + CHECK(output_buffer != NULL, "Internal",); + + io_write(io_out, output_size, output_buffer, io_user_data); // ============================================================== // // Cleanup - codegen->has_entry = 0; - codegen->entry_point = 0; - codegen->num_rels = 0; - codegen->offset_code = 0; - codegen->offset_ro_data = 0; - linker->num_obj_files = 0; - - mem_set(codegen->entities, 0, MAX_NUM_ENTITIES * sizeof *codegen->entities); - mem_set(codegen->rels, 0, codegen->max_num_rels * sizeof *codegen->rels); - mem_set(codegen->buffer_code, 0, codegen->max_code_size); - mem_set(codegen->buffer_ro_data, 0, codegen->max_ro_data_size); - mem_set(linker->obj_file_buffer, 0, linker->max_obj_file_size); - mem_set(linker->dependencies_buffer, 0, linker->max_dependencies_size); - mem_set(linker->obj_file_offsets, 0, linker->max_num_obj_files * sizeof *linker->obj_file_offsets); - mem_set(linker->sections, 0, linker->max_num_sections * sizeof *linker->sections); - mem_set(linker->symbols, 0, linker->max_num_symbols * sizeof *linker->symbols); - mem_set(linker->rels, 0, linker->max_num_rels * sizeof *linker->rels); - mem_set(linker->output_buffer, 0, linker->max_output_size); + chunk_remove(pool, codegen.entities); + chunk_remove(pool, codegen.rels); + chunk_remove(pool, codegen.buffer_code); + chunk_remove(pool, codegen.buffer_ro_data); + + chunk_remove(pool, linker.obj_file_buffer); + chunk_remove(pool, linker.dependencies_buffer); + chunk_remove(pool, linker.obj_file_offsets); + chunk_remove(pool, linker.sections); + chunk_remove(pool, linker.symbols); + chunk_remove(pool, linker.rels); + chunk_remove(pool, linker.output_buffer); } i64 io_open_read(i64 name_size, c8 *name, void *user_data) { @@ -4984,15 +5130,15 @@ void dispatch_io(u16 op, i64 *id, i64 *size, void *data, void *user_data) { (void) user_data; - FILE **f = (FILE **) id; - c8 buf[MAX_NAME_SIZE] = { 0 }; + FILE **f = (FILE **) id; + c8 buf[1024 * 4] = { 0 }; switch (op) { case IO_OPEN_READ: case IO_OPEN_WRITE: - CHECK(size != NULL, "Invalid arguments",); - CHECK(*size > 0 && *size < MAX_NAME_SIZE, "Invalid arguments",); - CHECK(data != NULL, "Invalid arguments",); + CHECK(size != NULL, "Invalid arguments",); + CHECK(*size > 0 && *size < (i64) sizeof buf, "Invalid arguments",); + CHECK(data != NULL, "Invalid arguments",); mem_cpy(buf, data, *size); *f = fopen(buf, op == IO_OPEN_READ ? "rb" : "wb"); @@ -5078,44 +5224,8 @@ Pool g_pool = { // Statically allocate a large memory block. // TODO Reallocate the memory block when necessary. - .capacity = MAX_NUM_ENTITIES, - .entities = (Entity[MAX_NUM_ENTITIES]) {0}, -}; - -Codegen_Context g_codegen = { - .max_num_rels = MAX_NUM_RELS, - .max_code_size = MAX_CODE_SIZE, - .max_ro_data_size = MAX_CODE_SIZE, - - .entry_point = 0, - .num_rels = 0, - .offset_code = 0, - .offset_ro_data = 0, - - .entities = (Codegen_Entity[MAX_NUM_ENTITIES]) {0}, - .rels = (Codegen_Rel_Entry[MAX_NUM_RELS]) {0}, - .buffer_code = (u8[MAX_CODE_SIZE]) {0}, - .buffer_ro_data = (u8[MAX_CODE_SIZE]) {0}, -}; - -Linker_Context g_linker = { - .max_obj_file_size = MAX_OBJECT_FILE_SIZE, - .max_dependencies_size = MAX_DEPENDENCIES_SIZE, - .max_num_obj_files = MAX_NUM_OBJECT_FILES, - .max_num_sections = MAX_NUM_SECTIONS, - .max_num_symbols = MAX_NUM_SYMBOLS, - .max_num_rels = MAX_NUM_LINK_RELS, - .max_output_size = MAX_OUTPUT_SIZE, - - .num_obj_files = 0, - - .obj_file_buffer = (u8[MAX_OBJECT_FILE_SIZE]) {0}, - .dependencies_buffer = (u8[MAX_DEPENDENCIES_SIZE]) {0}, - .obj_file_offsets = (i64[MAX_NUM_OBJECT_FILES]) {0}, - .sections = (Link_Sec_Entry[MAX_NUM_SECTIONS]) {0}, - .symbols = (Link_Sym_Entry[MAX_NUM_SYMBOLS]) {0}, - .rels = (Link_Rel_Entry[MAX_NUM_LINK_RELS]) {0}, - .output_buffer = (u8[MAX_OUTPUT_SIZE]) {0}, + .capacity = POOL_CAPACITY, + .data = (u8[POOL_CAPACITY]) {0}, }; // Handy procedures @@ -5134,7 +5244,7 @@ i64 n_ptr(i64 proc, u64 address) { } i64 n_str(i64 proc, c8 *value) { - i64 len = str_len(value, value + MAX_LITERAL_SIZE - 1); + i64 len = str_len(value, value + MAX_STRING_SIZE - 1); i64 n_data = node_data_array_c8(&g_pool, len + 1, value); i64 n_ref = node_data_reference(&g_pool, n_data); p_add(proc, n_data); @@ -5161,7 +5271,7 @@ i64 n_call(i64 proc, i64 target_proc, i64 num_args, Var *args) { } i64 n_call_by_name(i64 proc, c8 *name, i64 num_args, Var *args) { - i64 n = node_ctrl_call_by_name(&g_pool, str_len(name, name + MAX_NAME_SIZE), name, num_args, args); + i64 n = node_ctrl_call_by_name(&g_pool, str_len(name, name + MAX_STRING_SIZE), name, num_args, args); p_add(proc, n); return n; } @@ -5186,7 +5296,7 @@ i64 n_ret(i64 proc, i64 num_vals, Var *vals) { i64 p_new(i64 unit, c8 *name) { i64 p = proc_init(&g_pool); - i64 len = str_len(name, name + MAX_NAME_SIZE); + i64 len = str_len(name, name + MAX_STRING_SIZE); if (len > 0) proc_set_name(&g_pool, p, len, name); u_add(unit, p); @@ -5216,10 +5326,10 @@ void u_entry_point(i64 unit, i64 proc) { } void u_elf_x86_64(i64 unit, c8 *output_file_name) { - i64 name_len = str_len(output_file_name, output_file_name + MAX_PATH_SIZE); + i64 name_len = str_len(output_file_name, output_file_name + MAX_STRING_SIZE); i64 out = io_open_write(name_len, output_file_name, NULL); - unit_write(&g_pool, &g_codegen, &g_linker, unit, FORMAT_ELF, ARCH_X86_64, out, NULL); + unit_write(&g_pool, unit, FORMAT_ELF, ARCH_X86_64, out, NULL); io_chmod_exe(out, NULL); io_close(out, NULL); @@ -5232,7 +5342,7 @@ void l_code(i64 unit, i64 link_unit) { void l_object(i64 unit, c8 *object_library) { i64 l = unit_init(&g_pool, UNIT_LIBRARY_OBJECT); c8 *path = l_find(object_library, 0); - i64 len = str_len(path, path + MAX_PATH_SIZE); + i64 len = str_len(path, path + MAX_STRING_SIZE); unit_set_name(&g_pool, l, len, path); unit_link_add(&g_pool, unit, l); } @@ -5240,7 +5350,7 @@ void l_object(i64 unit, c8 *object_library) { void l_static(i64 unit, c8 *static_library) { i64 l = unit_init(&g_pool, UNIT_LIBRARY_STATIC); c8 *path = l_find(static_library, 0); - i64 len = str_len(path, path + MAX_PATH_SIZE); + i64 len = str_len(path, path + MAX_STRING_SIZE); unit_set_name(&g_pool, l, len, path); unit_link_add(&g_pool, unit, l); } @@ -5252,11 +5362,11 @@ c8 *l_find(c8 *name, b8 silent) { CHECK(name != NULL, "Invalid argument", ""); - i64 len = str_len(name, name + MAX_PATH_SIZE); + i64 len = str_len(name, name + MAX_STRING_SIZE); - CHECK(len < MAX_PATH_SIZE, "Invalid argument", ""); + CHECK(len < MAX_STRING_SIZE, "Invalid argument", ""); - static c8 buf[MAX_PATH_SIZE]; // FIXME + static c8 buf[MAX_STRING_SIZE]; // FIXME #define TRY_(template) \ do { \ |