summaryrefslogtreecommitdiff
path: root/bxgen.c
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-11-22 12:56:34 +0100
committerMitya Selivanov <automainint@guattari.tech>2024-11-22 12:56:34 +0100
commit09e6e123d803c7587464e29532dc61a025f517d5 (patch)
tree7180bfaddd91b4130c46ceb8e711ab00635d15e5 /bxgen.c
parentb3c47026b79d0d9ce46bb1f1dbb4f7c6b652e758 (diff)
downloadbxgen-09e6e123d803c7587464e29532dc61a025f517d5.zip
Add addition tests
Diffstat (limited to 'bxgen.c')
-rwxr-xr-xbxgen.c1353
1 files changed, 1065 insertions, 288 deletions
diff --git a/bxgen.c b/bxgen.c
index aceaca2..98ddd30 100755
--- a/bxgen.c
+++ b/bxgen.c
@@ -346,9 +346,9 @@ typedef struct {
} Ret;
typedef struct {
- // NOTE
- // We may call a local procedure by it's id,
- // or a global procedure by name.
+ // NOTE
+ // 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;
@@ -377,20 +377,14 @@ typedef struct {
// and has a string name.
typedef struct {
- b8 emit_done;
- i64 offset;
-} Proc_Codegen;
-
-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;
- Proc_Codegen codegen;
+ 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;
} Proc;
// A compilation unit is a collection of procedures.
@@ -425,6 +419,27 @@ typedef struct {
};
} Entity;
+// Pool, a collection of all entities.
+//
+// NOTE
+// We use one single large memory block for *everything*.
+
+typedef struct {
+ i64 num_entities;
+ i64 capacity;
+ Entity *entities;
+} Pool;
+
+// TEMP Codegen and linker buffers
+// TODO Use string table for buffers also.
+
+typedef struct {
+ b8 emit_done;
+ i64 offset;
+ i64 reg;
+ u64 occupied_reg;
+} Codegen_Entity;
+
typedef struct {
u16 type;
i64 offset;
@@ -433,7 +448,7 @@ typedef struct {
i64 name_size;
c8 *name;
i64 proc;
-} Rel_Entry;
+} Codegen_Rel_Entry;
typedef struct {
i64 offset;
@@ -454,32 +469,19 @@ typedef struct {
i64 symbol;
} Link_Rel_Entry;
-// Pool, a collection of all entities.
-//
-// NOTE
-// We use one single large memory block for *everything*.
-
-typedef struct {
- i64 num_entities;
- i64 capacity;
- Entity *entities;
-} Pool;
-
-// TEMP Codegen and linker buffers
-// TODO Use string table for buffers also.
-
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;
- Rel_Entry *rels;
- u8 * buffer_code;
- u8 * buffer_ro_data;
+ 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;
} Codegen_Context;
typedef struct {
@@ -643,8 +645,13 @@ c8 * l_find(c8 *name, b8 silent);
} \
} while (0)
#else
-# define CHECK(condition, error_string, fail_result) \
- dispatch_assert((condition), error_string, __LINE__, __FILE__)
+# define CHECK(condition, error_string, fail_result) \
+ do { \
+ b8 ok_ = (condition); \
+ dispatch_assert(ok_, error_string, __LINE__, __FILE__); \
+ if (!ok_) \
+ return fail_result; \
+ } while (0)
#endif
#ifdef NDEBUG
@@ -812,6 +819,7 @@ i64 pool_add(Pool *pool, Entity data) {
data.is_enabled = 1,
pool->entities[id] = data;
+ CHECK(id != UNDEFINED, "Sanity", UNDEFINED);
return id;
}
@@ -889,10 +897,10 @@ i64 node_data_add(Pool *pool, Var x, Var y) {
}
u16 resolve_calling_convention(Pool *pool, i64 proc) {
- CHECK(pool != NULL, "Invalid arguments",);
- CHECK(proc != UNDEFINED, "Invalid arguments",);
- CHECK(pool->entities[proc].is_enabled, "No entity",);
- CHECK(pool->entities[proc].type == ENTITY_PROC, "No 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);
if (pool->entities[proc].proc.convention == CONV_UNKNOWN)
pool->entities[proc].proc.convention = CONV_CDECL;
@@ -1577,6 +1585,8 @@ enum {
X86_64_BASE_ADDRESS = 0x400000,
X86_64_ALIGNMENT = 8,
+
+ // NOTE For compatibility with Box64 on ARM
X86_64_PAGE_SIZE = 16 * 1024, // 4 * 1024
// ELF format constants
@@ -1830,22 +1840,25 @@ typedef struct {
void x86_64_emit_node(
Pool * pool,
Codegen_Context *codegen,
+ Codegen_Entity *proc,
i64 node,
u32 context
) {
- CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments", 0);
- CHECK(node != UNDEFINED && pool->entities[node].is_enabled, "No node", 0);
- CHECK(pool->entities[node].type == ENTITY_NODE, "Invalid entity", 0);
+ // 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 = &pool->entities[node].node;
u8 *begin = codegen->buffer_code + codegen->offset_code;
u8 *end = codegen->buffer_code + codegen->max_code_size;
- #define CHECK_NODE_(node) \
- CHECK((node) != UNDEFINED, "Internal", 0); \
- CHECK(pool->entities[(node)].is_enabled, "Internal", 0); \
- CHECK(pool->entities[(node)].type == ENTITY_NODE, "Internal", 0)
+ #define CHECK_NODE_(node_) \
+ CHECK((node_) != UNDEFINED, "Internal",); \
+ CHECK(pool->entities[(node_)].is_enabled, "Internal",); \
+ CHECK(pool->entities[(node_)].type == ENTITY_NODE, "Internal",)
switch (n->op) {
case DATA_PTR:
@@ -1856,35 +1869,713 @@ void x86_64_emit_node(
// Do nothing
break;
- case DATA_ADD:
+ case DATA_ADD: {
+ // NOTE Assuming static single-assignment form.
+
CHECK_NODE_(n->add[0]);
CHECK_NODE_(n->add[1]);
Node *x = &pool->entities[n->add[0]].node;
Node *y = &pool->entities[n->add[1]].node;
- if (x->op == DATA_I32) {
- write_u8 (LE, 0xb8, begin, end); // mov eax
- write_u32(LE, x->lit.as_u32[0], begin + 1, end);
- } else {
- FAIL("Not implemented",);
- }
+ i64 dst_reg = 1;
+ while (dst_reg <= 4 && ((1 << (dst_reg - 1)) & proc->occupied_reg) != 0)
+ ++dst_reg;
- if (y->op == DATA_I32) {
- write_u8 (LE, 0x05, begin + 5, end); // add eax
- write_u32(LE, y->lit.as_u32[0], begin + 6, end);
- } else {
- FAIL("Not implemented",);
+ switch (dst_reg) {
+ case 1: {
+ // eax
+
+ 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);
+
+ begin += 5;
+ codegen->offset_code += 5;
+ } break;
+
+ case DATA_ADD: {
+ i64 src_reg = codegen->entities[n->add[0]].reg;
+
+ switch (src_reg) {
+ case 1:
+ FAIL("Not implemented",);
+ // eax
+ break;
+
+ case 2:
+ FAIL("Not implemented",);
+ // ebx
+
+ write_u8(LE, 0x89, begin, end); // mov eax
+ write_u8(LE, 0xd8, begin + 1, end); // ebx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 3:
+ // ecx
+
+ write_u8(LE, 0x89, begin, end); // mov eax
+ write_u8(LE, 0xc8, begin + 1, end); // ecx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+
+ case 4:
+ // edx
+
+ write_u8(LE, 0x89, begin, end); // mov eax
+ write_u8(LE, 0xd0, begin + 1, end); // edx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+
+ codegen->entities[n->add[0]].reg = 0;
+ proc->occupied_reg &= ~(1 << (src_reg - 1));
+ } break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+
+ 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);
+
+ codegen->offset_code += 5;
+ } break;
+
+ case DATA_ADD: {
+ i64 src_reg = codegen->entities[n->add[1]].reg;
+
+ switch (src_reg) {
+ case 1:
+ FAIL("Not implemented",);
+ // eax
+
+ write_u8(LE, 0x01, begin, end); // add eax
+ write_u8(LE, 0xc0, begin + 1, end); // eax
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 2:
+ FAIL("Not implemented",);
+ // ebx
+
+ write_u8(LE, 0x01, begin, end); // add eax
+ write_u8(LE, 0xd8, begin + 1, end); // ebx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 3:
+ // ecx
+
+ write_u8(LE, 0x01, begin, end); // add eax
+ write_u8(LE, 0xc8, begin + 1, end); // ecx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 4:
+ // edx
+
+ write_u8(LE, 0x01, begin, end); // add eax
+ write_u8(LE, 0xd0, begin + 1, end); // edx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+
+ codegen->entities[n->add[1]].reg = 0;
+ proc->occupied_reg &= ~(1 << (src_reg - 1));
+ } break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+ } break;
+
+ case 2: {
+ // ebx
+
+ 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);
+
+ begin += 5;
+ codegen->offset_code += 5;
+ } break;
+
+ case DATA_ADD: {
+ i64 src_reg = codegen->entities[n->add[0]].reg;
+
+ switch (src_reg) {
+ case 1:
+ // eax
+
+ write_u8(LE, 0x89, begin, end); // mov ebx
+ write_u8(LE, 0xc3, begin + 1, end); // eax
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 2:
+ FAIL("Not implemented",);
+ // ebx
+ break;
+
+ case 3:
+ FAIL("Not implemented",);
+ // ecx
+
+ write_u8(LE, 0x89, begin, end); // mov ebx
+ write_u8(LE, 0xcb, begin + 1, end); // ecx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+
+ case 4:
+ // edx
+
+ write_u8(LE, 0x89, begin, end); // mov ebx
+ write_u8(LE, 0xd3, begin + 1, end); // edx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 5:
+ // esi
+
+ write_u8(LE, 0x89, begin, end); // mov ebx
+ write_u8(LE, 0xf3, begin + 1, end); // esi
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+
+ codegen->entities[n->add[0]].reg = 0;
+ proc->occupied_reg &= ~(1 << (src_reg - 1));
+ } break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+
+ switch (y->op) {
+ case DATA_I32: {
+ 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);
+
+ codegen->offset_code += 6;
+ } break;
+
+ case DATA_ADD: {
+ i64 src_reg = codegen->entities[n->add[1]].reg;
+
+ switch (src_reg) {
+ case 1:
+ // eax
+
+ write_u8(LE, 0x01, begin, end); // add ebx
+ write_u8(LE, 0xc3, begin + 1, end); // eax
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 2:
+ FAIL("Not implemented",);
+ // ebx
+
+ write_u8(LE, 0x01, begin, end); // add ebx
+ write_u8(LE, 0xdb, begin + 1, end); // ebx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 3:
+ FAIL("Not implemented",);
+ // ecx
+
+ write_u8(LE, 0x01, begin, end); // add ebx
+ write_u8(LE, 0xcb, begin + 1, end); // ecx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+
+ case 4:
+ FAIL("Not implemented",);
+ // edx
+
+ write_u8(LE, 0x01, begin, end); // add ebx
+ write_u8(LE, 0xd3, begin + 1, end); // edx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+
+ codegen->entities[n->add[1]].reg = 0;
+ proc->occupied_reg &= ~(1 << (src_reg - 1));
+ } break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+ } break;
+
+ case 3: {
+ // ecx
+
+ 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);
+
+ begin += 5;
+ codegen->offset_code += 5;
+ } break;
+
+ case DATA_ADD: {
+ i64 src_reg = codegen->entities[n->add[0]].reg;
+
+ switch (src_reg) {
+ case 1:
+ // eax
+
+ write_u8(LE, 0x89, begin, end); // mov ecx
+ write_u8(LE, 0xc1, begin + 1, end); // eax
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 2:
+ FAIL("Not implemented",);
+ // ebx
+
+ write_u8(LE, 0x89, begin, end); // mov ecx
+ write_u8(LE, 0xd9, begin + 1, end); // ebx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 3:
+ FAIL("Not implemented",);
+ // ecx
+ break;
+
+
+ case 4:
+ FAIL("Not implemented",);
+ // edx
+
+ write_u8(LE, 0x89, begin, end); // mov ecx
+ write_u8(LE, 0xd1, begin + 1, end); // edx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+
+ codegen->entities[n->add[0]].reg = 0;
+ proc->occupied_reg &= ~(1 << (src_reg - 1));
+ } break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+
+ 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);
+
+ codegen->offset_code += 6;
+ } break;
+
+ case DATA_ADD: {
+ i64 src_reg = codegen->entities[n->add[1]].reg;
+
+ switch (src_reg) {
+ case 1:
+ FAIL("Not implemented",);
+ // eax
+
+ write_u8(LE, 0x01, begin, end); // add ecx
+ write_u8(LE, 0xc1, begin + 1, end); // eax
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 2:
+ // ebx
+
+ write_u8(LE, 0x01, begin, end); // add ecx
+ write_u8(LE, 0xd9, begin + 1, end); // ebx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 3:
+ FAIL("Not implemented",);
+ // ecx
+
+ write_u8(LE, 0x01, begin, end); // add ecx
+ write_u8(LE, 0xc9, begin + 1, end); // ecx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+
+ case 4:
+ FAIL("Not implemented",);
+ // edx
+
+ write_u8(LE, 0x01, begin, end); // add ecx
+ write_u8(LE, 0xd1, begin + 1, end); // edx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+
+ codegen->entities[n->add[1]].reg = 0;
+ proc->occupied_reg &= ~(1 << (src_reg - 1));
+ } break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+ } break;
+
+ case 4: {
+ // edx
+
+ 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);
+
+ begin += 5;
+ codegen->offset_code += 5;
+ } break;
+
+ case DATA_ADD: {
+ i64 src_reg = codegen->entities[n->add[0]].reg;
+
+ switch (src_reg) {
+ case 1:
+ // eax
+
+ write_u8(LE, 0x89, begin, end); // mov edx
+ write_u8(LE, 0xc2, begin + 1, end); // eax
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 2:
+ FAIL("Not implemented",);
+ // ebx
+
+ write_u8(LE, 0x89, begin, end); // mov edx
+ write_u8(LE, 0xda, begin + 1, end); // ebx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 3:
+ FAIL("Not implemented",);
+ // ecx
+
+ write_u8(LE, 0x89, begin, end); // mov edx
+ write_u8(LE, 0xca, begin + 1, end); // ecx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 4:
+ FAIL("Not implemented",);
+ // edx
+ break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+
+ codegen->entities[n->add[0]].reg = 0;
+ proc->occupied_reg &= ~(1 << (src_reg - 1));
+ } break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+
+ 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);
+
+ codegen->offset_code += 6;
+ } break;
+
+ case DATA_ADD: {
+ i64 src_reg = codegen->entities[n->add[1]].reg;
+
+ switch (src_reg) {
+ case 1:
+ FAIL("Not implemented",);
+ // eax
+
+ write_u8(LE, 0x01, begin, end); // add edx
+ write_u8(LE, 0xc2, begin + 1, end); // eax
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 2:
+ // ebx
+
+ write_u8(LE, 0x01, begin, end); // add edx
+ write_u8(LE, 0xda, begin + 1, end); // ebx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 3:
+ FAIL("Not implemented",);
+ // ecx
+
+ write_u8(LE, 0x01, begin, end); // add edx
+ write_u8(LE, 0xca, begin + 1, end); // ecx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 4:
+ FAIL("Not implemented",);
+ // edx
+
+ write_u8(LE, 0x01, begin, end); // add edx
+ write_u8(LE, 0xd2, begin + 1, end); // edx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+
+ codegen->entities[n->add[1]].reg = 0;
+ proc->occupied_reg &= ~(1 << (src_reg - 1));
+ } break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+ } break;
+
+ case 5: {
+ // esi
+
+ switch (x->op) {
+ case DATA_I32: {
+ FAIL("Not implemented",);
+ } break;
+
+ case DATA_ADD: {
+ i64 src_reg = codegen->entities[n->add[0]].reg;
+
+ switch (src_reg) {
+ case 1:
+ // eax
+
+ write_u8(LE, 0x89, begin, end); // mov esi
+ write_u8(LE, 0xc6, begin + 1, end); // eax
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 2:
+ FAIL("Not implemented",);
+ // ebx
+
+ write_u8(LE, 0x89, begin, end); // mov esi
+ write_u8(LE, 0xde, begin + 1, end); // ebx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 3:
+ FAIL("Not implemented",);
+ // ecx
+
+ write_u8(LE, 0x89, begin, end); // mov esi
+ write_u8(LE, 0xce, begin + 1, end); // ecx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 4:
+ FAIL("Not implemented",);
+ // edx
+
+ write_u8(LE, 0x89, begin, end); // mov esi
+ write_u8(LE, 0xd6, begin + 1, end); // edx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+
+ codegen->entities[n->add[0]].reg = 0;
+ proc->occupied_reg &= ~(1 << (src_reg - 1));
+ } break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+
+ switch (y->op) {
+ case DATA_I32: {
+ FAIL("Not implemented",);
+ } break;
+
+ case DATA_ADD: {
+ i64 src_reg = codegen->entities[n->add[1]].reg;
+
+ switch (src_reg) {
+ case 1:
+ FAIL("Not implemented",);
+ // eax
+
+ write_u8(LE, 0x01, begin, end); // add esi
+ write_u8(LE, 0xc6, begin + 1, end); // eax
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 2:
+ // ebx
+
+ write_u8(LE, 0x01, begin, end); // add esi
+ write_u8(LE, 0xde, begin + 1, end); // ebx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 3:
+ FAIL("Not implemented",);
+ // ecx
+
+ write_u8(LE, 0x01, begin, end); // add esi
+ write_u8(LE, 0xce, begin + 1, end); // ecx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+
+ case 4:
+ FAIL("Not implemented",);
+ // edx
+
+ write_u8(LE, 0x01, begin, end); // add esi
+ write_u8(LE, 0xd6, begin + 1, end); // edx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+
+ codegen->entities[n->add[1]].reg = 0;
+ proc->occupied_reg &= ~(1 << (src_reg - 1));
+ } break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+ } break;
+
+ default:
+ FAIL("Not implemented",);
}
- codegen->offset_code += 10;
- break;
+ codegen->entities[node].reg = dst_reg;
+ proc->occupied_reg |= 1 << (dst_reg - 1);
+ } break;
case CTRL_CALL: {
- CHECK(n->call.convention == CONV_CDECL, "Not implemented", 0);
- CHECK(n->call.target_proc == UNDEFINED, "Not implemented", 0);
- CHECK(n->call.target_name_size > 0, "No proc name", 0);
- CHECK(codegen->num_rels + 2 <= codegen->max_num_rels, "Out of memory", 0);
+ 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",);
switch (n->call.num_args) {
case 1: {
@@ -1898,9 +2589,9 @@ void x86_64_emit_node(
//
Node *data = &pool->entities[arg->ref].node;
- CHECK(data->op == DATA_I8, "Not implemented", 0);
+ CHECK(data->op == DATA_I8, "Not implemented",);
- CHECK(codegen->offset_ro_data + data->lit.num_bytes <= codegen->max_ro_data_size, "Out of memory", 0);
+ 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);
@@ -1911,7 +2602,7 @@ 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++] = (Rel_Entry) {
+ codegen->rels[codegen->num_rels++] = (Codegen_Rel_Entry) {
.type = REL_ADD_RO_DATA_ADDRESS,
.offset = codegen->offset_code + 2,
.size = 8,
@@ -1922,7 +2613,7 @@ void x86_64_emit_node(
write_u8(LE, 0x48, begin + 10, end); // movabs
write_u8(LE, 0xb8, begin + 11, end); // rax
- codegen->rels[codegen->num_rels++] = (Rel_Entry) {
+ codegen->rels[codegen->num_rels++] = (Codegen_Rel_Entry) {
.type = REL_ADD_PROC_ADDRESS,
.offset = codegen->offset_code + 12,
.size = 8,
@@ -1944,7 +2635,7 @@ void x86_64_emit_node(
write_u8 (LE, 0x48, begin + 5, end); // movabs
write_u8 (LE, 0xb8, begin + 6, end); // rax
- codegen->rels[codegen->num_rels++] = (Rel_Entry) {
+ codegen->rels[codegen->num_rels++] = (Codegen_Rel_Entry) {
.type = REL_ADD_PROC_ADDRESS,
.offset = codegen->offset_code + 7,
.size = 8,
@@ -1975,12 +2666,12 @@ void x86_64_emit_node(
Node *arg_1 = &pool->entities[n_arg_1].node;
Node *arg_2 = &pool->entities[n_arg_2].node;
- CHECK(arg_0->op == DATA_PTR, "Not implemented", 0);
- CHECK(arg_1->op == DATA_PTR, "Not implemented", 0);
- CHECK(arg_2->op == DATA_PTR, "Not implemented", 0);
- CHECK(arg_0->lit.as_u64[0] == 0, "Not implemented", 0);
- CHECK(arg_1->lit.as_u64[0] == 0, "Not implemented", 0);
- CHECK(arg_2->lit.as_u64[0] == 0, "Not implemented", 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",);
write_u8(LE, 0x31, begin, end); // xor edx
write_u8(LE, 0xd2, begin + 1, end); // edx
@@ -1991,7 +2682,7 @@ 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++] = (Rel_Entry) {
+ codegen->rels[codegen->num_rels++] = (Codegen_Rel_Entry) {
.type = REL_ADD_PROC_ADDRESS,
.offset = codegen->offset_code + 8,
.size = 8,
@@ -2031,29 +2722,29 @@ void x86_64_emit_node(
Node *arg_5 = &pool->entities[n_arg_5].node;
Node *arg_6 = &pool->entities[n_arg_6].node;
- CHECK(arg_0->op == DATA_REFERENCE, "Not implemented", 0);
- CHECK(arg_1->op == DATA_I32, "Not implemented", 0);
- CHECK(arg_2->op == DATA_REFERENCE, "Not implemented", 0);
- CHECK(arg_3->op == DATA_PTR, "Not implemented", 0);
- CHECK(arg_4->op == DATA_PTR, "Not implemented", 0);
- CHECK(arg_5->op == DATA_PTR, "Not implemented", 0);
- CHECK(arg_6->op == DATA_PTR, "Not implemented", 0);
+ CHECK(arg_0->op == DATA_REFERENCE, "Not implemented",);
+ CHECK(arg_1->op == DATA_I32, "Not implemented",);
+ CHECK(arg_2->op == DATA_REFERENCE, "Not implemented",);
+ CHECK(arg_3->op == DATA_PTR, "Not implemented",);
+ CHECK(arg_4->op == DATA_PTR, "Not implemented",);
+ CHECK(arg_5->op == DATA_PTR, "Not implemented",);
+ CHECK(arg_6->op == DATA_PTR, "Not implemented",);
- CHECK(arg_0->ref != UNDEFINED, "Internal", 0);
- CHECK(pool->entities[arg_0->ref].is_enabled, "Internal", 0);
- CHECK(arg_2->ref != UNDEFINED, "Internal", 0);
- CHECK(pool->entities[arg_2->ref].is_enabled, "Internal", 0);
+ 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", 0);
- CHECK(pool->entities[arg_2->ref].type == ENTITY_NODE, "Not implemented", 0);
+ CHECK(pool->entities[arg_0->ref].type == ENTITY_PROC, "Not implemented",);
+ CHECK(pool->entities[arg_2->ref].type == ENTITY_NODE, "Not implemented",);
// Write data
//
Node *dat_2 = &pool->entities[arg_2->ref].node;
- CHECK(dat_2->op == DATA_PTR, "Not implemented", 0);
+ 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", 0);
+ 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);
@@ -2064,7 +2755,7 @@ 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++] = (Rel_Entry) {
+ codegen->rels[codegen->num_rels++] = (Codegen_Rel_Entry) {
.type = REL_ADD_PROC_ADDRESS,
.offset = codegen->offset_code + 2,
.size = 8,
@@ -2076,7 +2767,7 @@ void x86_64_emit_node(
write_u8 (LE, 0x48, begin + 15, end); // movabs
write_u8 (LE, 0xba, begin + 16, end); // rdx
- codegen->rels[codegen->num_rels++] = (Rel_Entry) {
+ codegen->rels[codegen->num_rels++] = (Codegen_Rel_Entry) {
.type = REL_ADD_RO_DATA_ADDRESS,
.offset = codegen->offset_code + 17,
.size = 8,
@@ -2108,7 +2799,7 @@ void x86_64_emit_node(
write_u8 (LE, 0x48, begin + 70, end); // movabs
write_u8 (LE, 0xb8, begin + 71, end); // rax
- codegen->rels[codegen->num_rels++] = (Rel_Entry) {
+ codegen->rels[codegen->num_rels++] = (Codegen_Rel_Entry) {
.type = REL_ADD_PROC_ADDRESS,
.offset = codegen->offset_code + 72,
.size = 8,
@@ -2152,15 +2843,15 @@ void x86_64_emit_node(
LOG(WARNING, "Some return values are ignored for node %lld", node);
i64 n_val = n->ret.vals[0];
- CHECK(n_val != UNDEFINED, "Internal", 0);
- CHECK(pool->entities[n_val].is_enabled, "Internal", 0);
- CHECK(pool->entities[n_val].type == ENTITY_NODE, "Internal", 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;
switch (val->op) {
case DATA_I64: {
- CHECK(val->lit.num_bytes == 8, "Not implemented", 0);
+ CHECK(val->lit.num_bytes == 8, "Not implemented",);
write_u8 (LE, 0xb8, begin, end); // mov eax
write_u32(LE, 60, begin + 1, end); // 60
@@ -2175,6 +2866,45 @@ void x86_64_emit_node(
} break;
case DATA_ADD: {
+ switch (codegen->entities[n_val].reg) {
+ case 1:
+ // eax
+ break;
+
+ case 2:
+ // ebx
+
+ write_u8 (LE, 0x89, begin, end); // mov eax
+ write_u8 (LE, 0xd8, begin + 1, end); // ebx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 3:
+ // ecx
+
+ write_u8 (LE, 0x89, begin, end); // mov eax
+ write_u8 (LE, 0xc8, begin + 1, end); // ecx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ case 4:
+ // edx
+
+ write_u8 (LE, 0x89, begin, end); // mov eax
+ write_u8 (LE, 0xd0, begin + 1, end); // edx
+
+ begin += 2;
+ codegen->offset_code += 2;
+ break;
+
+ default:
+ FAIL("Not implemented",);
+ }
+
write_u8 (LE, 0x89, begin, end); // mov edi
write_u32(LE, 0xc7, begin + 1, end); // eax
@@ -2192,18 +2922,18 @@ void x86_64_emit_node(
}
}
} else {
- CHECK(n->ret.num_vals == 1, "Not implemented", 0);
+ CHECK(n->ret.num_vals == 1, "Not implemented",);
i64 n_val = n->ret.vals[0];
- CHECK(n_val != UNDEFINED, "Internal", 0);
- CHECK(pool->entities[n_val].is_enabled, "Internal", 0);
- CHECK(pool->entities[n_val].type == ENTITY_NODE, "Internal", 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;
switch (val->op) {
case DATA_I32: {
- CHECK(val->lit.num_bytes == 4, "Not implemented", 0);
+ CHECK(val->lit.num_bytes == 4, "Not implemented",);
write_u8 (LE, 0xb8, begin, end); // mov eax
write_u32(LE, val->lit.as_u32[0], begin + 1, end);
@@ -2213,7 +2943,9 @@ void x86_64_emit_node(
} break;
case DATA_ADD: {
- write_u8(LE, 0xc3, begin + 5, end); // ret
+ CHECK(codegen->entities[n_val].reg == 1, "Not implemented",);
+
+ write_u8(LE, 0xc3, begin, end); // ret
codegen->offset_code += 1;
} break;
@@ -2238,16 +2970,16 @@ void emit_proc(
u16 arch,
u32 context
) {
- CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments", 0);
- CHECK(proc != UNDEFINED && pool->entities[proc].is_enabled, "No proc", 0);
- CHECK(pool->entities[proc].type == ENTITY_PROC, "Invalid entity", 0);
- CHECK(arch == ARCH_X86_64, "Target not supported", 0);
+ 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",);
Proc *p = &pool->entities[proc].proc;
- CHECK(p->codegen.emit_done == 0, "Emit already done", 0);
+ CHECK(codegen->entities[proc].emit_done == 0, "Emit already done",);
- p->codegen.offset = codegen->offset_code;
+ codegen->entities[proc].offset = codegen->offset_code;
// TODO Sort nodes in the sequential execution order.
//
@@ -2255,15 +2987,15 @@ void emit_proc(
// Now we assume that nodes are already sorted.
for (i64 i = 0; i < p->num_nodes; ++i)
- x86_64_emit_node(pool, codegen, p->nodes[i], context);
+ x86_64_emit_node(pool, codegen, codegen->entities + proc, p->nodes[i], context);
- p->codegen.emit_done = 1;
+ codegen->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", 0);
- CHECK(unit != UNDEFINED && pool->entities[unit].is_enabled, "No unit", 0);
- CHECK(pool->entities[unit].type == ENTITY_UNIT, "Invalid entity", 0);
+ 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",);
for (i64 i = 0; i < pool->entities[unit].unit.num_procs; ++i) {
u32 context = 0;
@@ -2650,13 +3382,13 @@ i64 unit_write_in_memory(
u16 format,
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", 0);
- CHECK(format == FORMAT_ELF && arch == ARCH_X86_64, "Target not supported",);
- CHECK(linker->obj_file_buffer != NULL, "No object file buffer",);
- CHECK(linker->dependencies_buffer != NULL, "No dependencies buffer",);
- CHECK(linker->obj_file_offsets != NULL, "No object file offsets buffer",);
+ 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);
emit_unit(pool, codegen, unit, arch);
@@ -2690,7 +3422,7 @@ i64 unit_write_in_memory(
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",);
+ 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);
@@ -2779,8 +3511,8 @@ i64 unit_write_in_memory(
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);
- CHECK(relx.symbol.section != 65521, "Sanity",);
- CHECK(relx.symbol.section != 65522, "Sanity",);
+ CHECK(relx.symbol.section != 65521, "Sanity", 0);
+ CHECK(relx.symbol.section != 65522, "Sanity", 0);
switch (relx.type) {
case R_X86_64_GOT32:
@@ -2808,7 +3540,7 @@ i64 unit_write_in_memory(
if (found)
break;
- CHECK(num_symbols < linker->max_num_symbols, "Out of memory",);
+ CHECK(num_symbols < linker->max_num_symbols, "Out of memory", 0);
linker->symbols[num_symbols++] = (Link_Sym_Entry) {
.name_size = relx.symbol.name.size,
.name = sym_name,
@@ -2855,7 +3587,7 @@ i64 unit_write_in_memory(
Offset_Num headers = elf_section_headers(buf);
for (i64 sec_index = 1; sec_index < headers.num; ++sec_index, ++sec_index_global) {
- CHECK(sec_index_global < num_sections_total, "Buffer overflow",);
+ CHECK(sec_index_global < num_sections_total, "Buffer overflow", 0);
Elf_Section_Header section = elf_section(buf, sec_index);
c8 * name = elf_name_from_offset(buf, section.name);
@@ -2936,7 +3668,7 @@ i64 unit_write_in_memory(
c8 * sym_name = elf_name_from_offset(buf, sym.name);
if (sym.type == SYM_TLS && sym.section != 0)
- CHECK(elf_section(buf, sym.section).tls, "Sanity",);
+ CHECK(elf_section(buf, sym.section).tls, "Sanity", 0);
if (sym.section == 0) // undefined symbol
continue;
@@ -2949,12 +3681,12 @@ i64 unit_write_in_memory(
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",);
- CHECK(linker->sections[sym_section].address != 0, "Sanity",);
+ 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(num_symbols < linker->max_num_symbols, "Too many symbols",);
+ CHECK(num_symbols < linker->max_num_symbols, "Too many symbols", 0);
linker->symbols[num_symbols++] = (Link_Sym_Entry) {
.name_size = sym.name.size,
@@ -2982,26 +3714,7 @@ 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_,); \
- CHECK(num_symbols < linker->max_num_symbols, "Too many symbols",); \
- linker->symbols[num_symbols++] = (Link_Sym_Entry) { \
- .name_size = sizeof name_ - 1, \
- .name = name_, \
- __VA_ARGS__ \
- }; \
- } while (0)
-
- #define ADD_IF_MISSING_(name_, ...) \
+ #define ADD_UNIQUE_(i_, name_, ...) \
do { \
b8 found_ = 0; \
for (i_ = 0; i_ < num_symbols; ++i_) \
@@ -3011,14 +3724,33 @@ i64 unit_write_in_memory(
found_ = 1; \
break; \
} \
- if (!found_) { \
- CHECK(num_symbols < linker->max_num_symbols, "Too many symbols",); \
- linker->symbols[num_symbols++] = (Link_Sym_Entry) { \
- .name_size = sizeof name_ - 1, \
- .name = name_, \
- __VA_ARGS__ \
- }; \
- } \
+ 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__ \
+ }; \
+ } 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__ \
+ }; \
+ } \
} while (0)
// ----------------------------------------------------------
@@ -3106,17 +3838,17 @@ 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",);
+ 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) {
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);
i64 sym_index_global = num_symbols;
- CHECK(relx.symbol.section != 65521, "Sanity",);
- CHECK(relx.symbol.section != 65522, "Sanity",);
+ CHECK(relx.symbol.section != 65521, "Sanity", 0);
+ CHECK(relx.symbol.section != 65522, "Sanity", 0);
- CHECK(num_symbols < linker->max_num_symbols, "Out of memory",);
+ CHECK(num_symbols < linker->max_num_symbols, "Out of memory", 0);
if (relx.symbol.section == 0) {
b8 found = 0;
@@ -3127,10 +3859,10 @@ i64 unit_write_in_memory(
str_eq(pool->entities[i].proc.name_size,
pool->entities[i].proc.name,
relx.symbol.name.size, sym_name)) {
- CHECK(pool->entities[i].proc.codegen.emit_done, "No proc code",);
+ CHECK(codegen->entities[i].emit_done, "No proc code", 0);
linker->symbols[num_symbols++] = (Link_Sym_Entry) {
- .address = rx_code_address + pool->entities[i].proc.codegen.offset,
+ .address = rx_code_address + codegen->entities[i].offset,
.size = relx.symbol.value.size,
};
@@ -3174,8 +3906,8 @@ i64 unit_write_in_memory(
if (sym_index_global >= num_symbols)
LOG(ERROR, "Symbol: %s", sym_name);
- CHECK(sym_index_global < num_symbols, "Symbol not found",);
- CHECK(rel_index_global < linker->max_num_rels, "Out of memory",);
+ CHECK(sym_index_global < num_symbols, "Symbol not found", 0);
+ CHECK(rel_index_global < linker->max_num_rels, "Out of memory", 0);
linker->rels[rel_index_global].symbol = sym_index_global;
@@ -3187,7 +3919,7 @@ i64 unit_write_in_memory(
if (!STR_EQ(relx.symbol.name.size, sym_name, "_DYNAMIC") &&
linker->symbols[sym_index_global].got_offset == 0) {
got_offset += ELF_GOT_ENTRY_SIZE;
- CHECK(got_offset < rw_got_size, "Sanity",);
+ CHECK(got_offset < rw_got_size, "Sanity", 0);
linker->symbols[sym_index_global].got_offset = got_offset;
}
break;
@@ -3218,7 +3950,7 @@ 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",);
+ 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) {
Elf_Relx_Entry relx = elf_relx(buf, symtab, strtab, src_sec.data, entry_index, src_sec.type == SEC_RELA);
@@ -3386,7 +4118,7 @@ i64 unit_write_in_memory(
#undef FIND_
for (i64 rel_index = 0; rel_index < codegen->num_rels; ++rel_index) {
- Rel_Entry rel = codegen->rels[rel_index];
+ Codegen_Rel_Entry rel = codegen->rels[rel_index];
u8 *begin = codegen->buffer_code + rel.offset;
u8 *end = codegen->buffer_code + codegen->offset_code;
@@ -3427,10 +4159,9 @@ i64 unit_write_in_memory(
} else {
CHECK(pool->entities[rel.proc].is_enabled, "No entity", 0);
CHECK(pool->entities[rel.proc].type == ENTITY_PROC, "No proc", 0);
- Proc *p = &pool->entities[rel.proc].proc;
- CHECK(p->codegen.emit_done, "No proc address", 0);
+ CHECK(codegen->entities[rel.proc].emit_done, "No proc address", 0);
- i64 value = rel.value + rx_code_address + p->codegen.offset;
+ i64 value = rel.value + rx_code_address + codegen->entities[rel.proc].offset;
write_i64(LE, value, begin, end);
found = 1;
@@ -3451,7 +4182,7 @@ 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",);
+ CHECK(output_size <= linker->max_output_size, "Out of memory", 0);
i64 entry = rx_code_address + codegen->entry_point;
@@ -3467,7 +4198,7 @@ i64 unit_write_in_memory(
break;
}
- CHECK(found, "Undefined symbol: _start",);
+ CHECK(found, "Undefined symbol: _start", 0);
}
LOG(VERBOSE, "Entry point: 0x%llx", entry);
@@ -3519,12 +4250,12 @@ i64 unit_write_in_memory(
// Program headers
//
- CHECK(rx_code_offset % X86_64_PAGE_SIZE == rx_code_address % X86_64_PAGE_SIZE, "Invalid alignment",);
- CHECK(rw_data_offset % X86_64_PAGE_SIZE == rw_data_address % X86_64_PAGE_SIZE, "Invalid alignment",);
- CHECK(ro_data_offset % X86_64_PAGE_SIZE == ro_data_address % X86_64_PAGE_SIZE, "Invalid alignment",);
- CHECK(rw_got_offset % X86_64_PAGE_SIZE == rw_got_address % X86_64_PAGE_SIZE, "Invalid alignemtn",);
- CHECK(rw_dynamic_offset % X86_64_PAGE_SIZE == rw_dynamic_address % X86_64_PAGE_SIZE, "Invalid alignemtn",);
- CHECK(rw_tls_data_offset % X86_64_PAGE_SIZE == rw_tls_data_address % X86_64_PAGE_SIZE, "Invalid alignment",);
+ CHECK(rx_code_offset % X86_64_PAGE_SIZE == rx_code_address % X86_64_PAGE_SIZE, "Invalid alignment", 0);
+ CHECK(rw_data_offset % X86_64_PAGE_SIZE == rw_data_address % X86_64_PAGE_SIZE, "Invalid alignment", 0);
+ CHECK(ro_data_offset % X86_64_PAGE_SIZE == ro_data_address % X86_64_PAGE_SIZE, "Invalid alignment", 0);
+ CHECK(rw_got_offset % X86_64_PAGE_SIZE == rw_got_address % X86_64_PAGE_SIZE, "Invalid alignemtn", 0);
+ CHECK(rw_dynamic_offset % X86_64_PAGE_SIZE == rw_dynamic_address % X86_64_PAGE_SIZE, "Invalid alignemtn", 0);
+ CHECK(rw_tls_data_offset % X86_64_PAGE_SIZE == rw_tls_data_address % X86_64_PAGE_SIZE, "Invalid alignment", 0);
u8 *h = o + ELF_HEADER_SIZE;
@@ -3644,8 +4375,8 @@ i64 unit_write_in_memory(
write_u16(LE, num_program_headers, o + 56, o_end);
- CHECK(h == o + ELF_HEADER_SIZE + num_program_headers * ELF_PROGRAM_HEADER_SIZE, "Invalid num program headers",);
- CHECK(rx_code_offset >= h - o, "Sanity",);
+ CHECK(h == o + ELF_HEADER_SIZE + num_program_headers * ELF_PROGRAM_HEADER_SIZE, "Invalid num program headers", 0);
+ CHECK(rx_code_offset >= h - o, "Sanity", 0);
// Code
//
@@ -3669,8 +4400,8 @@ i64 unit_write_in_memory(
section.data.size == 0)
continue;
u8 *p = o + offset;
- CHECK(p >= o + program_offset + codegen->offset_code, "Buffer overflow",);
- CHECK(p + section.data.size <= o + output_size, "Buffer overflow",);
+ CHECK(p >= o + program_offset + codegen->offset_code, "Buffer overflow", 0);
+ CHECK(p + section.data.size <= o + output_size, "Buffer overflow", 0);
mem_cpy(p, buf.begin + section.data.offset, section.data.size);
}
}
@@ -3685,7 +4416,7 @@ i64 unit_write_in_memory(
continue;
offset += ELF_GOT_ENTRY_SIZE;
- CHECK(offset < rw_got_size, "Sanity",);
+ CHECK(offset < rw_got_size, "Sanity", 0);
write_u64(LE, sym->address, o + rw_got_offset + offset, o_end);
}
@@ -3704,6 +4435,8 @@ void unit_write(
i64 io_out,
void * io_user_data
) {
+ CHECK(unit != UNDEFINED, "Invalid unit",);
+
// ==============================================================
//
// Reading dependencies
@@ -3825,6 +4558,7 @@ void unit_write(
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);
@@ -4093,7 +4827,8 @@ Codegen_Context g_codegen = {
.offset_code = 0,
.offset_ro_data = 0,
- .rels = (Rel_Entry[MAX_NUM_RELS]) {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},
};
@@ -4310,14 +5045,42 @@ c8 *l_find(c8 *name, b8 silent) {
#if HELPERS
-b8 link_with_libc(void) {
- // ============================================================
- //
- // Create the program semantic tree
-
- // Add a compilation unit.
- i64 u = u_new();
+#define ADD_TEST_(name_, res_, ...) \
+ b8 name_(void) { \
+ i64 u = u_new(); \
+ CHECK(u != UNDEFINED, "Sanity", 0); \
+ \
+ __VA_ARGS__ \
+ \
+ u_elf_x86_64(u, "test_" #name_); \
+ \
+ b8 success = 1; \
+ \
+ if (HOST_OS != OS_Linux) { \
+ LOG(INFO, "Skip running the executable. Host system is not compatible."); \
+ } else if (HO != LE) { \
+ LOG(INFO, "Skip running the executable. Host data ordering is not compatible."); \
+ } else { \
+ LOG(VERBOSE, "Running the executable"); \
+ \
+ i32 ret; \
+ \
+ if (LOG_LEVEL >= VERBOSE) \
+ ret = system("./test_" #name_); \
+ else \
+ ret = system("./test_" #name_ " >/dev/null"); \
+ \
+ if (WEXITSTATUS(ret) != res_) \
+ success = 0; \
+ } \
+ \
+ if (success) \
+ system("rm test_" #name_); \
+ \
+ return success; \
+ }
+ADD_TEST_(link_with_libc, 42,
// Add the main proc.
i64 mainproc = p_new(u, "main");
{
@@ -4335,12 +5098,6 @@ b8 link_with_libc(void) {
);
}
- // ============================================================
- //
- // Compile and link
- //
- // TODO
-
// Add dependencies
if (l_find("c_nonshared", 1)[0] != '\0')
@@ -4348,113 +5105,126 @@ b8 link_with_libc(void) {
else
l_static(u, "c");
l_object(u, "crt1");
+)
- // l_object(u, "crti");
- // l_object(u, "crtn");
-
- // Write the compilation unit into an executable file.
- u_elf_x86_64(u, "test_foo");
-
- // ============================================================
-
- b8 success = 1;
-
- if (HOST_OS != OS_Linux) {
- LOG(INFO, "Skip running the executable. Host system is not compatible.");
- } else if (HO != LE) {
- LOG(INFO, "Skip running the executable. Host data ordering is not compatible.");
- } else {
- LOG(VERBOSE, "Running the executable");
-
- i32 ret;
-
- if (LOG_LEVEL >= VERBOSE)
- ret = system("./test_foo");
- else
- ret = system("./test_foo >/dev/null");
-
- if (WEXITSTATUS(ret) != 42)
- success = 0;
- }
-
- system("rm test_foo");
-
- return success;
-}
+ADD_TEST_(math_two_plus_two, 4,
+ i64 mainproc = p_new_entry(u);
-b8 two_plus_two(void) {
- i64 u = u_new();
+ N_RET(
+ mainproc,
+ n_add(mainproc, n_i32(mainproc, 2), n_i32(mainproc, 2))
+ );
+)
+ADD_TEST_(math_sixty_nine, 69,
i64 mainproc = p_new_entry(u);
N_RET(
mainproc,
- n_add(mainproc, n_i32(mainproc, 2), n_i32(mainproc, 2))
+ n_add(mainproc, n_i32(mainproc, 27), n_i32(mainproc, 42))
);
+)
- u_elf_x86_64(u, "test_two_plus_two");
+ADD_TEST_(math_add_3, 1+2+3,
+ i64 mainproc = p_new_entry(u);
- b8 success = 1;
+ i64 a = n_add(mainproc, n_i32(mainproc, 1), n_i32(mainproc, 2));
+ i64 b = n_i32(mainproc, 3);
- if (HOST_OS != OS_Linux) {
- LOG(INFO, "Skip running the executable. Host system is not compatible.");
- } else if (HO != LE) {
- LOG(INFO, "Skip running the executable. Host data ordering is not compatible.");
- } else {
- LOG(VERBOSE, "Running the executable");
+ N_RET(
+ mainproc,
+ n_add(mainproc, a, b)
+ );
+)
- i32 ret;
+ADD_TEST_(math_add_4a, 1+2+3+4,
+ i64 mainproc = p_new_entry(u);
- if (LOG_LEVEL >= VERBOSE)
- ret = system("./test_two_plus_two");
- else
- ret = system("./test_two_plus_two >/dev/null");
+ i64 a = n_add(mainproc, n_i32(mainproc, 1), n_i32(mainproc, 2));
+ i64 b = n_add(mainproc, n_i32(mainproc, 3), n_i32(mainproc, 4));
- if (WEXITSTATUS(ret) != 4)
- success = 0;
- }
+ N_RET(
+ mainproc,
+ n_add(mainproc, a, b)
+ );
+)
- system("rm test_two_plus_two");
+ADD_TEST_(math_add_5, 1+2+3+4+5,
+ i64 mainproc = p_new_entry(u);
- return success;
-}
+ i64 a = n_add(mainproc, n_i32(mainproc, 1), n_i32(mainproc, 2));
+ i64 b = n_add(mainproc, n_i32(mainproc, 3), n_i32(mainproc, 4));
+ i64 c = n_i32(mainproc, 5);
+ i64 a_b = n_add(mainproc, a, b);
-b8 sixty_nine(void) {
- i64 u = u_new();
+ N_RET(
+ mainproc,
+ n_add(mainproc, a_b, c)
+ );
+)
+ADD_TEST_(math_add_6, 1+2+3+4+5+6,
i64 mainproc = p_new_entry(u);
+ i64 a = n_add(mainproc, n_i32(mainproc, 1), n_i32(mainproc, 2));
+ i64 b = n_add(mainproc, n_i32(mainproc, 3), n_i32(mainproc, 4));
+ i64 c = n_add(mainproc, n_i32(mainproc, 5), n_i32(mainproc, 6));
+ i64 a_b = n_add(mainproc, a, b);
+
N_RET(
mainproc,
- n_add(mainproc, n_i32(mainproc, 27), n_i32(mainproc, 42))
+ n_add(mainproc, a_b, c)
);
+)
- u_elf_x86_64(u, "test_sixty_nine");
+ADD_TEST_(math_add_7, 1+2+3+4+5+6+7,
+ i64 mainproc = p_new_entry(u);
- b8 success = 1;
+ i64 a = n_add(mainproc, n_i32(mainproc, 1), n_i32(mainproc, 2));
+ i64 b = n_add(mainproc, n_i32(mainproc, 3), n_i32(mainproc, 4));
+ i64 c = n_add(mainproc, n_i32(mainproc, 5), n_i32(mainproc, 6));
+ i64 d = n_i32(mainproc, 7);
+ i64 a_b = n_add(mainproc, a, b);
+ i64 c_d = n_add(mainproc, c, d);
- if (HOST_OS != OS_Linux) {
- LOG(INFO, "Skip running the executable. Host system is not compatible.");
- } else if (HO != LE) {
- LOG(INFO, "Skip running the executable. Host data ordering is not compatible.");
- } else {
- LOG(VERBOSE, "Running the executable");
+ N_RET(
+ mainproc,
+ n_add(mainproc, a_b, c_d)
+ );
+)
- i32 ret;
+ADD_TEST_(math_add_4b, 5+6+7+8,
+ i64 mainproc = p_new_entry(u);
- if (LOG_LEVEL >= VERBOSE)
- ret = system("./test_sixty_nine");
- else
- ret = system("./test_sixty_nine >/dev/null");
+ i64 a = n_add(mainproc, n_i32(mainproc, 1), n_i32(mainproc, 2));
+ i64 b = n_add(mainproc, n_i32(mainproc, 3), n_i32(mainproc, 4));
+ i64 c = n_add(mainproc, n_i32(mainproc, 5), n_i32(mainproc, 6));
+ i64 d = n_add(mainproc, n_i32(mainproc, 7), n_i32(mainproc, 8));
+ i64 a_b = n_add(mainproc, a, b);
+ i64 c_d = n_add(mainproc, c, d);
+ (void) a_b;
- if (WEXITSTATUS(ret) != 69)
- success = 0;
- }
+ N_RET(
+ mainproc,
+ c_d
+ );
+)
- system("rm test_sixty_nine");
+ADD_TEST_(math_add_8, 1+2+3+4+5+6+7+8,
+ i64 mainproc = p_new_entry(u);
- return success;
-}
+ i64 a = n_add(mainproc, n_i32(mainproc, 1), n_i32(mainproc, 2));
+ i64 b = n_add(mainproc, n_i32(mainproc, 3), n_i32(mainproc, 4));
+ i64 c = n_add(mainproc, n_i32(mainproc, 5), n_i32(mainproc, 6));
+ i64 d = n_add(mainproc, n_i32(mainproc, 7), n_i32(mainproc, 8));
+ i64 a_b = n_add(mainproc, a, b);
+ i64 c_d = n_add(mainproc, c, d);
+
+ N_RET(
+ mainproc,
+ n_add(mainproc, a_b, c_d)
+ );
+)
#endif // HELPERS
@@ -4524,8 +5294,15 @@ i32 main(i32 argc, c8 **argv) {
#if HELPERS
// RUN_TEST_(link_with_libc);
- RUN_TEST_(two_plus_two);
- RUN_TEST_(sixty_nine);
+ RUN_TEST_(math_two_plus_two);
+ RUN_TEST_(math_sixty_nine);
+ RUN_TEST_(math_add_3);
+ RUN_TEST_(math_add_4a);
+ RUN_TEST_(math_add_5);
+ RUN_TEST_(math_add_6);
+ RUN_TEST_(math_add_7);
+ RUN_TEST_(math_add_4b);
+ RUN_TEST_(math_add_8);
#endif
#undef RUN_TEST_