summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-11-23 15:20:54 +0100
committerMitya Selivanov <automainint@guattari.tech>2024-11-23 15:20:54 +0100
commita059440035093f0a649db4bc8af83fae208f746d (patch)
tree7fde7619b96ea0c044cc350df6ffe1bc8eab4998
parent66d7b0398ef5cad84d474f5db1fcccd1f36c0e88 (diff)
downloadbxgen-a059440035093f0a649db4bc8af83fae208f746d.zip
Impl chunk table
-rwxr-xr-xbxgen.c1770
1 files changed, 940 insertions, 830 deletions
diff --git a/bxgen.c b/bxgen.c
index e8883c9..708b0a7 100755
--- a/bxgen.c
+++ b/bxgen.c
@@ -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 { \