aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2019-08-18 06:25:52 +0200
committerdec05eba <dec05eba@protonmail.com>2020-07-25 14:36:46 +0200
commitc1bea102df3f2907f345b89ff0f66f5055ac4767 (patch)
tree309d26329d190e24e9b4ebc36e89c42e369f0560 /include
parent81c5f8e750fcda6a2451fb54604130431434f88f (diff)
Add extern funcs, parameter registers, fix asm_rm RSP bug
Diffstat (limited to 'include')
-rw-r--r--include/ast.h6
-rw-r--r--include/bytecode/bytecode.h66
-rw-r--r--include/defs.h1
-rw-r--r--include/program.h28
-rw-r--r--include/ssa/ssa.h27
-rw-r--r--include/std/hash_map.h2
6 files changed, 91 insertions, 39 deletions
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 <setjmp.h>
/*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 <setjmp.h>
+#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 {
@@ -82,6 +97,12 @@ typedef struct {
} SsaInsFuncCall;
typedef struct {
+ u8 num_args;
+ SsaRegister result;
+ SsaExternFuncIndex extern_func_index;
+} SsaInsFuncCallExtern;
+
+typedef struct {
SsaRegister condition_reg;
JumpOffset jump_offset;
} SsaInsJumpZero;
@@ -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.