aboutsummaryrefslogtreecommitdiff
path: root/executor/x86_64/executor.c
diff options
context:
space:
mode:
Diffstat (limited to 'executor/x86_64/executor.c')
-rw-r--r--executor/x86_64/executor.c77
1 files changed, 25 insertions, 52 deletions
diff --git a/executor/x86_64/executor.c b/executor/x86_64/executor.c
index 9083e14..c442da8 100644
--- a/executor/x86_64/executor.c
+++ b/executor/x86_64/executor.c
@@ -1,6 +1,7 @@
#include "../executor.h"
#include "../../include/std/alloc.h"
#include "../../include/std/buffer.h"
+#include "../../include/std/log.h"
#include "asm.h"
#include <assert.h>
@@ -19,29 +20,23 @@
typedef struct {
u32 asm_index;
- u16 func_index;
-} CallDefer;
-
-typedef struct {
- u32 asm_index;
u16 target_label;
bool condition;
} JumpDefer;
typedef struct {
Asm asm;
- usize *function_indices;
- u16 num_functions;
u16 func_counter;
- Buffer/*CallDefer*/ call_defer;
Buffer/*JumpDefer*/ jump_defer;
u32 label_asm_index[MAX_LABELS];
int label_counter;
} amal_executor_impl;
+#define ASM_ENSURE_CAPACITY return_if_error(asm_ensure_capacity(&impl->asm, 256));
+
#define IMPL_START \
amal_executor_impl *impl = (amal_executor_impl*)self; \
- return_if_error(asm_ensure_capacity(&impl->asm, 256));
+ ASM_ENSURE_CAPACITY
/*
@reg will be a positive value when accessing local variables, in which case the first
@@ -64,10 +59,7 @@ int amal_executor_init(amal_executor **self) {
impl = (amal_executor_impl**)self;
*impl = NULL;
return_if_error(am_malloc(sizeof(amal_executor_impl), (void**)impl));
- (*impl)->function_indices = NULL;
- (*impl)->num_functions = 0;
(*impl)->func_counter = 0;
- ignore_result_int(buffer_init(&(*impl)->call_defer, NULL));
ignore_result_int(buffer_init(&(*impl)->jump_defer, NULL));
(*impl)->label_counter = 0;
return asm_init(&(*impl)->asm);
@@ -76,8 +68,6 @@ int amal_executor_init(amal_executor **self) {
void amal_executor_deinit(amal_executor *self) {
amal_executor_impl *impl = (amal_executor_impl*)self;
buffer_deinit(&impl->jump_defer);
- buffer_deinit(&impl->call_defer);
- am_free(impl->function_indices);
asm_deinit(&impl->asm);
am_free(impl);
}
@@ -93,26 +83,13 @@ u32 amal_exec_get_code_offset(amal_executor *self) {
}
int amal_executor_instructions_start(amal_executor *self, u16 num_functions) {
- amal_executor_impl *impl = (amal_executor_impl*)self;
- return_if_error(am_realloc(impl->function_indices, num_functions * sizeof(usize), (void**)&impl->function_indices));
- impl->num_functions = num_functions;
+ (void)self;
+ (void)num_functions;
return 0;
}
int amal_executor_instructions_end(amal_executor *self) {
amal_executor_impl *impl = (amal_executor_impl*)self;
- CallDefer *call_defer = buffer_begin(&impl->call_defer);
- CallDefer *call_defer_end = buffer_end(&impl->call_defer);
- for(; call_defer != call_defer_end; ++call_defer) {
- i32 func_offset;
- if(call_defer->func_index >= impl->num_functions) {
- amal_log_error("Program attempted to call a function that doesn't exist (index %u, while there are only %u functions)", call_defer->func_index, impl->num_functions);
- return -1;
- }
- func_offset = (isize)impl->function_indices[call_defer->func_index] - (isize)call_defer->asm_index;
- asm_override_call_rel32(&impl->asm, call_defer->asm_index, func_offset);
- }
- buffer_clear(&impl->call_defer);
impl->func_counter = 0;
return 0;
}
@@ -299,25 +276,16 @@ int amal_exec_pushd(amal_executor *self, BufferView data) {
return 0;
}
-int amal_exec_call(amal_executor *self, u16 func_index, u8 num_args, i8 dst_reg) {
- IMPL_START
+int amal_exec_call(amal_executor *self, u32 code_offset, u8 num_args, i8 dst_reg) {
+ amal_executor_impl *impl = (amal_executor_impl*)self;
/* TODO: Preserve necessary registers before call? */
/* TODO: This assumes all arguments are isize */
/* Do the function call */
isize asm_offset = asm_get_size(&impl->asm);
- if(func_index < impl->func_counter) {
- asm_call_rel32(&impl->asm, (isize)impl->function_indices[func_index] - asm_offset);
- } else {
- /*
- The location of the function has not been defined yet. Use call instruction with dummy data and change
- the location once the location to the function is known
- */
- CallDefer call_defer;
- call_defer.asm_index = asm_offset;
- call_defer.func_index = func_index;
- return_if_error(buffer_append(&impl->call_defer, &call_defer, sizeof(call_defer)));
- asm_call_rel32(&impl->asm, 0);
- }
+ ASM_ENSURE_CAPACITY
+
+ assert(code_offset < asm_offset);
+ asm_call_rel32(&impl->asm, (isize)code_offset - asm_offset);
/* Handle function result and cleanup */
{
@@ -331,6 +299,11 @@ int amal_exec_call(amal_executor *self, u16 func_index, u8 num_args, i8 dst_reg)
return 0;
}
+void amal_exec_call_overwrite(amal_executor *self, u32 call_code_offset, i32 new_target_rel32) {
+ amal_executor_impl *impl = (amal_executor_impl*)self;
+ asm_overwrite_call_rel32(&impl->asm, call_code_offset, new_target_rel32);
+}
+
const Reg64 SYS_V_PARAM_REGS[] = { RDI, RSI, RDX, RCX };
/*
@@ -379,9 +352,9 @@ int amal_exec_callr(i8 dst_reg, BufferView data) {
*/
int amal_exec_cmp(amal_executor *self, i8 dst_reg, i8 src_reg1, i8 src_reg2) {
+ AsmPtr dst, src1, src2;
IMPL_START
- AsmPtr dst, src1, src2;
asm_ptr_init_disp(&dst, RBP, get_register_stack_offset(dst_reg));
asm_ptr_init_disp(&src1, RBP, get_register_stack_offset(src_reg1));
asm_ptr_init_disp(&src2, RBP, get_register_stack_offset(src_reg2));
@@ -424,8 +397,9 @@ int amal_exec_jz(amal_executor *self, i8 reg, u16 target_label) {
}
int amal_exec_jmp(amal_executor *self, u16 target_label) {
- IMPL_START
+ amal_executor_impl *impl = (amal_executor_impl*)self;
u32 asm_offset = asm_get_size(&impl->asm);
+ ASM_ENSURE_CAPACITY
if(target_label < impl->label_counter) {
asm_jmp(&impl->asm, (i32)impl->label_asm_index[target_label] - (i32)asm_offset);
return 0;
@@ -466,7 +440,6 @@ int amal_exec_func_start(amal_executor *self, u16 num_regs) {
64-bit Linux,BSD,Mac: RBX, RBP, R12-R15
*/
IMPL_START
- impl->function_indices[impl->func_counter++] = asm_get_size(&impl->asm);
asm_pushr(&impl->asm, RBX);
asm_pushr(&impl->asm, RBP);
asm_mov_rr(&impl->asm, RBP, RSP);
@@ -475,10 +448,10 @@ int amal_exec_func_start(amal_executor *self, u16 num_regs) {
}
int amal_exec_func_end(amal_executor *self) {
- IMPL_START
-
+ amal_executor_impl *impl = (amal_executor_impl*)self;
JumpDefer *jump_defer = buffer_begin(&impl->jump_defer);
JumpDefer *jump_defer_end = buffer_end(&impl->jump_defer);
+ ASM_ENSURE_CAPACITY
for(; jump_defer != jump_defer_end; ++jump_defer) {
i32 jump_offset;
if(jump_defer->target_label >= impl->label_counter) {
@@ -487,9 +460,9 @@ int amal_exec_func_end(amal_executor *self) {
}
jump_offset = (isize)impl->label_asm_index[jump_defer->target_label] - (isize)jump_defer->asm_index;
if(jump_defer->condition)
- asm_override_jcc_rel32(&impl->asm, jump_defer->asm_index, jump_offset);
+ asm_overwrite_jcc_rel32(&impl->asm, jump_defer->asm_index, jump_offset);
else
- asm_override_jmp_rel32(&impl->asm, jump_defer->asm_index, jump_offset);
+ asm_overwrite_jmp_rel32(&impl->asm, jump_defer->asm_index, jump_offset);
}
buffer_clear(&impl->jump_defer);
impl->label_counter = 0;
@@ -502,7 +475,7 @@ int amal_exec_func_end(amal_executor *self) {
}
int amal_exec_label(amal_executor *self) {
- IMPL_START
+ amal_executor_impl *impl = (amal_executor_impl*)self;
assert(impl->label_counter < MAX_LABELS);
impl->label_asm_index[impl->label_counter++] = asm_get_size(&impl->asm);
return 0;