From c1bea102df3f2907f345b89ff0f66f5055ac4767 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 18 Aug 2019 06:25:52 +0200 Subject: Add extern funcs, parameter registers, fix asm_rm RSP bug --- include/ast.h | 6 ++++- include/bytecode/bytecode.h | 66 ++++++++++++++++++++++++--------------------- include/defs.h | 1 + include/program.h | 28 ++++++++++++++++--- include/ssa/ssa.h | 27 ++++++++++++++++--- include/std/hash_map.h | 2 +- 6 files changed, 91 insertions(+), 39 deletions(-) (limited to 'include') diff --git a/include/ast.h b/include/ast.h index 1198a98..bdab6c3 100644 --- a/include/ast.h +++ b/include/ast.h @@ -20,7 +20,6 @@ typedef struct Ast Ast; typedef struct FunctionParameter FunctionParameter; -typedef struct FunctionSignature FunctionSignature; typedef struct FunctionCall FunctionCall; typedef struct StructDecl StructDecl; typedef struct StructField StructField; @@ -87,6 +86,7 @@ typedef enum { typedef struct { union { + void *data; LhsExpr *lhs_expr; FunctionSignature *func_sig; } value; @@ -107,6 +107,7 @@ typedef enum { typedef struct { union { + void *data; LhsExpr *lhs_expr; FunctionParameter *func_param; } value; @@ -218,6 +219,7 @@ struct LhsExpr { BufferView var_name; VariableType type; nullable Ast *rhs_expr; + u16 extern_index; /* Index to extern func, extern variable, etc; if applicable */ }; #define LHS_EXPR_IS_EXTERN(expr) ((expr)->decl_flags & DECL_FLAG_EXTERN) @@ -297,6 +299,8 @@ CHECK_RESULT int function_signature_init(FunctionSignature *self, ArenaAllocator CHECK_RESULT int function_signature_add_parameter(FunctionSignature *self, const FunctionParameter *param); /* Adds a copy of @return_type to the function signature return type list */ CHECK_RESULT int function_signature_add_return_type(FunctionSignature *self, const VariableType *return_type); +CHECK_RESULT bool function_signature_equals(FunctionSignature *self, FunctionSignature *other); + void function_parameter_init(FunctionParameter *self); CHECK_RESULT int funcdecl_init(FunctionDecl *self, FunctionSignature *signature, Scope *parent, ArenaAllocator *allocator); CHECK_RESULT int funccall_init(FunctionCall *self, BufferView name, ArenaAllocator *allocator); diff --git a/include/bytecode/bytecode.h b/include/bytecode/bytecode.h index adad291..1e4c35d 100644 --- a/include/bytecode/bytecode.h +++ b/include/bytecode/bytecode.h @@ -9,48 +9,52 @@ #include /*doc(Opcode) - Variable length opcodes. Sizes range from 1 to 4 bytes. + Variable length opcodes. Sizes range from 1 to 5 bytes. # Instruction formats Instructions can be in 7 different formats: 1. 1 byte: Opcode(u8) - 2. 2 bytes: Opcode(u8) + register(u8) - 3. 3 bytes: Opcode(u8) + register(u8) + register(u8) + 2. 2 bytes: Opcode(u8) + register(i8) + 3. 3 bytes: Opcode(u8) + register(i8) + register(i8) 4. 3 bytes:\ 4.1 Opcode(u8) + intermediate(u16)\ 4.2 Opcode(u8) + data(u16)\ 4.3 Opcode(u8) + offset(i16)\ - 4.4 Opcode(u8) + num_reg(u16)\ - 4.5 Opcode(u8) + register(u8) + num_args(u8) - 5. 4 bytes: Opcode(u8) + register(u8) + register(u8) + register(u8) + 4.4 Opcode(u8) + register(i8) + num_args(u8) + 5. 4 bytes: Opcode(u8) + register(i8) + register(i8) + register(i8) 6. 4 bytes:\ - 6.1 Opcode(u8) + register(u8) + offset(i16)\ - 6.2 Opcode(u8) + register(u8) + intermediate(u16)\ - 6.3 Opcode(u8) + register(u8) + data(u16) - 7. 4 bytes: Opcode(u8) + index(u16) + num_args(u8) + 6.1 Opcode(u8) + register(i8) + offset(i16)\ + 6.2 Opcode(u8) + register(i8) + intermediate(u16)\ + 6.3 Opcode(u8) + register(i8) + data(u16)\ + 6.4 Opcode(u8) + num_param_reg(u8) + num_local_var_reg(u16) + 7. 5 bytes: Opcode(u8) + index(u16) + num_args(u8) + register(i8) + # Registers + Registers have a range of 128. Local variables start from register 0 and increment while parameters start from -1 + and decrement. */ typedef enum { AMAL_OP_NOP, /* No operation (do nothing). This can be used for patching code */ - AMAL_OP_SETZ, /* setz reg - Set register value to 0 */ - AMAL_OP_MOV, /* mov dst, src - Move src register to dst register */ - AMAL_OP_MOVI, /* movi dst, src - Move src intermediate to dst register */ - AMAL_OP_MOVD, /* movd dst, src - Move src data to dst register */ - AMAL_OP_ADD, /* add dst, reg1, reg2 - Add reg1 and reg2 and put the result in dst */ - AMAL_OP_SUB, /* sub dst, reg1, reg2 - Substract reg2 from reg1 and put the result in dst */ - AMAL_OP_IMUL, /* imul dst, reg1, reg2 - Signed multiplication */ - AMAL_OP_MUL, /* mul dst, reg1, reg2 - Unsigned multiplication */ - AMAL_OP_IDIV, /* idiv dst, reg1, reg2 - Signed division */ - AMAL_OP_DIV, /* div dst, reg1, reg2 - Unsigned division */ - AMAL_OP_PUSH, /* push reg - Push register onto stack */ - AMAL_OP_PUSHI, /* pushi int - Push intermediate onto stack */ - AMAL_OP_PUSHD, /* pushd data - Push data onto stack */ - AMAL_OP_CALL, /* call fi, num_args - Call a function using function index (fi) and num_args arguments. fi is u16 and num_args is u8 */ - AMAL_OP_CALLR, /* callr reg, num_args - Call a function using a register. Used for function pointers. num_args is u8 */ - AMAL_OP_CMP, /* cmp dst, reg1, reg2 - Set dst to 1 if reg1 equals reg2, otherwise set it to 0 */ - AMAL_OP_JZ, /* jz reg, offset - Jump to offset if reg is zero. offset is i16 */ - AMAL_OP_JMP, /* jmp offset - Unconditional jump to offset. offset is i16 */ - AMAL_OP_RET, /* ret reg - Return from the function with reg result */ - AMAL_OP_FUNC_START, /* func_start num_reg - Start of a function which has num_reg registers allocated. num_reg is a u16 */ - AMAL_OP_FUNC_END /* func_end - End of a function. Implementation should do a ret here */ + AMAL_OP_SETZ, /* setz reg - Set register value to 0 */ + AMAL_OP_MOV, /* mov dst, src - Move src register to dst register */ + AMAL_OP_MOVI, /* movi dst, src - Move src intermediate to dst register */ + AMAL_OP_MOVD, /* movd dst, src - Move src data to dst register */ + AMAL_OP_ADD, /* add dst, reg1, reg2 - Add reg1 and reg2 and put the result in dst */ + AMAL_OP_SUB, /* sub dst, reg1, reg2 - Substract reg2 from reg1 and put the result in dst */ + AMAL_OP_IMUL, /* imul dst, reg1, reg2 - Signed multiplication */ + AMAL_OP_MUL, /* mul dst, reg1, reg2 - Unsigned multiplication */ + AMAL_OP_IDIV, /* idiv dst, reg1, reg2 - Signed division */ + AMAL_OP_DIV, /* div dst, reg1, reg2 - Unsigned division */ + AMAL_OP_PUSH, /* push reg - Push register onto stack */ + AMAL_OP_PUSHI, /* pushi int - Push intermediate onto stack */ + AMAL_OP_PUSHD, /* pushd data - Push data onto stack */ + AMAL_OP_CALL, /* call fi, num_args, dst - Call a function using function index (fi) and num_args arguments. The result is stored in register dst. fi is u16 and num_args is u8 */ + AMAL_OP_CALLR, /* callr reg, num_args - Call a function using a register. Used for function pointers. num_args is u8 */ + AMAL_OP_CALLE, /* calle efi, num_args, dst - Call an extern function using extern function index (efi) and num_args arguments. The result is stored in register dst. efi is u16 and num_args is u8 */ + AMAL_OP_CMP, /* cmp dst, reg1, reg2 - Set dst to 1 if reg1 equals reg2, otherwise set it to 0 */ + AMAL_OP_JZ, /* jz reg, offset - Jump to offset if reg is zero. offset is i16 */ + AMAL_OP_JMP, /* jmp offset - Unconditional jump to offset. offset is i16 */ + AMAL_OP_RET, /* ret reg - Return from the function with reg result */ + AMAL_OP_FUNC_START, /* func_start num_param_reg, num_local_var_reg - Start of a function which has num_param_reg parameter registers allocated and num_local_var_reg local variable registers allocated. num_param_reg is u8 and num_local_var_reg is u16 */ + AMAL_OP_FUNC_END /* func_end - End of a function. Implementation should do a ret here */ } AmalOpcode; typedef u8 AmalOpcodeType; diff --git a/include/defs.h b/include/defs.h index d7f6692..8cd9d39 100644 --- a/include/defs.h +++ b/include/defs.h @@ -7,5 +7,6 @@ typedef struct Parser Parser; typedef struct Scope Scope; typedef struct FileScopeReference FileScopeReference; typedef struct FunctionDecl FunctionDecl; +typedef struct FunctionSignature FunctionSignature; #endif diff --git a/include/program.h b/include/program.h index 6603c63..543b38d 100644 --- a/include/program.h +++ b/include/program.h @@ -2,9 +2,12 @@ #define AMAL_PROGRAM_H #include "std/buffer.h" +#include "std/hash_map.h" +#include "std/arena_allocator.h" #include "bytecode/bytecode.h" #include "../executor/executor.h" +/* TODO: Remove all these errors and move program decoding and execution to another process (crash sandbox) */ #define AMAL_PROGRAM_OK 0 #define AMAL_PROGRAM_ERR -1 #define AMAL_PROGRAM_INVALID_HEADER -16 @@ -14,7 +17,7 @@ #define AMAL_PROGRAM_INVALID_INTERMEDIATES_SIZE -5 #define AMAL_PROGRAM_INVALID_STRINGS -6 #define AMAL_PROGRAM_INVALID_STRINGS_SIZE -7 -#define AMAL_PROGRAM_STRING_ALLOC_FAILURE -8 +#define AMAL_PROGRAM_ALLOC_FAILURE -8 #define AMAL_PROGRAM_INVALID_INSTRUCTIONS_SIZE -9 #define AMAL_PROGRAM_INVALID_INSTRUCTION -10 #define AMAL_PROGRAM_INSTRUCTION_INVALID_INTERMEDIATE_INDEX -11 @@ -23,6 +26,10 @@ #define AMAL_PROGRAM_INSTRUCTION_STACK_OOM -14 #define AMAL_PROGRAM_INSTRUCTION_ILLEGAL_JUMP_TARGET -15 #define AMAL_PROGRAM_INVALID_FUNCTIONS -16 +#define AMAL_PROGRAM_INVALID_EXTERNAL_FUNCTIONS -17 +#define AMAL_PROGRAM_INVALID_EXTERNAL_FUNCTIONS_SIZE -18 +#define AMAL_PROGRAM_INSTRUCTION_INVALID_EXTERN_FUNC_INDEX -19 +#define AMAL_PROGRAM_NO_SUCH_EXTERNAL_FUNCTION -20 #define AMAL_PROGRAM_MAGIC_NUMBER (u32)0xdec05eba #define AMAL_PROGRAM_MAJOR_VERSION 1 @@ -31,21 +38,36 @@ #define AMAL_PROGRAM_NUM_REGISTERS 256 +#define AMAL_PROGRAM_ARGS_SIZE_VARARGS -1 + +typedef struct { + void *func; + int args_byte_size; /* -1 if varargs (AMAL_PROGRAM_ARGS_SIZE_VARARGS) */ +} ProgramExternFunc; + typedef struct { Buffer/*<...>*/ data; u32 *string_indices; - char *intermediates_start; /* Reference inside @data */ - char *strings_start; /* Reference inside @data */ + u32 *extern_func_indices; + u8 *intermediates_start; /* Reference inside @data */ + u8 *strings_start; /* Reference inside @data */ + u8 *extern_funcs_start; /* Reference inside @data */ usize read_index; u16 num_intermediates; u16 num_strings; u16 num_functions; + u16 num_extern_functions; + + ArenaAllocator allocator; /* Owned. Used by @extern_funcs_map */ + HashMapType(BufferView, ProgramExternFunc) extern_funcs_map; } amal_program; CHECK_RESULT int amal_program_init(amal_program *self); void amal_program_deinit(amal_program *self); +CHECK_RESULT int amal_program_add_extern_func(amal_program *self, BufferView name, void *func_ptr, int args_byte_size); + CHECK_RESULT int amal_program_append_bytecode(amal_program *self, Bytecode *bytecode); CHECK_RESULT int amal_program_run(amal_program *self); CHECK_RESULT int amal_program_save(amal_program *self, const char *filepath); diff --git a/include/ssa/ssa.h b/include/ssa/ssa.h index 21d7f40..b2c8065 100644 --- a/include/ssa/ssa.h +++ b/include/ssa/ssa.h @@ -8,6 +8,8 @@ #include +#define SSA_ERR_EXTERN_FUNC_SIG_MISMATCH -20 + typedef enum { SSA_ASSIGN_INTER, SSA_ASSIGN_STRING, @@ -23,6 +25,7 @@ typedef enum { SSA_FUNC_END, SSA_PUSH, SSA_CALL, + SSA_CALL_EXTERN, SSA_JUMP_ZERO, SSA_JUMP, SSA_RET @@ -41,10 +44,16 @@ typedef struct { SsaNumberType type; } SsaNumber; +typedef struct { + FunctionSignature *func_sig; + BufferView name; +} SsaExternFunc; + typedef i16 JumpOffset; -typedef u16 SsaRegister; +typedef i16 SsaRegister; typedef u16 SsaIntermediateIndex; typedef u16 SsaStringIndex; +typedef u16 SsaExternFuncIndex; typedef u16 SsaFuncIndex; typedef struct { @@ -53,10 +62,15 @@ typedef struct { Buffer/*SsaNumber*/ intermediates; HashMapType(BufferView, SsaStringIndex) strings_map; Buffer/*BufferView*/ strings; + HashMapType(BufferView, SsaExternFuncIndex) extern_funcs_map; + Buffer/*SsaExternFunc*/ extern_funcs; SsaIntermediateIndex intermediate_counter; SsaStringIndex string_counter; + SsaExternFuncIndex extern_func_counter; SsaRegister reg_counter; + SsaRegister param_counter; SsaFuncIndex func_counter; + Parser *parser; /* Borrowed */ } Ssa; typedef struct { @@ -72,7 +86,8 @@ typedef struct { typedef struct { SsaFuncIndex func_index; - u16 num_registers; + u16 num_params_regs; + u16 num_local_vars_regs; } SsaInsFuncStart; typedef struct { @@ -81,6 +96,12 @@ typedef struct { FunctionDecl *func_decl; } SsaInsFuncCall; +typedef struct { + u8 num_args; + SsaRegister result; + SsaExternFuncIndex extern_func_index; +} SsaInsFuncCallExtern; + typedef struct { SsaRegister condition_reg; JumpOffset jump_offset; @@ -97,7 +118,7 @@ SsaNumber create_ssa_float(f64 value); SsaNumber ssa_get_intermediate(Ssa *self, SsaIntermediateIndex index); BufferView ssa_get_string(Ssa *self, SsaStringIndex index); -CHECK_RESULT int ssa_init(Ssa *self, ArenaAllocator *allocator); +CHECK_RESULT int ssa_init(Ssa *self, Parser *parser); typedef struct { jmp_buf env; diff --git a/include/std/hash_map.h b/include/std/hash_map.h index 020748b..d789db4 100644 --- a/include/std/hash_map.h +++ b/include/std/hash_map.h @@ -23,7 +23,7 @@ struct HashMap { #define HashMapType(key_type, value_type) __attribute__((annotate(#key_type", "#value_type))) HashMap -CHECK_RESULT int hash_map_init(HashMap *self, ArenaAllocator *allocator, usize value_type_size, HashMapCompare compare_func, HashMapHash hash_func); +CHECK_RESULT int hash_map_init(HashMap *self, ArenaAllocator *allocator, usize value_type_size, HashMapCompare key_compare_func, HashMapHash key_hash_func); /* Not thread-safe. Expected @value size to be @self->value_type_size. -- cgit v1.2.3