aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2019-09-09 01:08:34 +0200
committerdec05eba <dec05eba@protonmail.com>2020-07-25 14:36:46 +0200
commit16aaaa19a3ef4220726007d3e644ced0c9e06513 (patch)
tree6a7c2fc91bc362559b079afbb10dc247d7bcbae0 /include
parentde48503aef098d855754ab6f85558402130188d7 (diff)
Allow referencing code in imported file (right now for function calls, allow calling a function in another file)
Diffstat (limited to 'include')
-rw-r--r--include/ast.h34
-rw-r--r--include/bytecode/bytecode.h46
-rw-r--r--include/defs.h3
-rw-r--r--include/parser.h10
-rw-r--r--include/program.h11
-rw-r--r--include/ssa/ssa.h18
-rw-r--r--include/std/buffer.h2
-rw-r--r--include/std/buffer_view.h2
-rw-r--r--include/std/hash_map.h1
-rw-r--r--include/std/log.h2
-rw-r--r--include/std/mem.h2
-rw-r--r--include/std/misc.h8
-rw-r--r--include/std/thread.h4
13 files changed, 116 insertions, 27 deletions
diff --git a/include/ast.h b/include/ast.h
index edf225b..0c34d0b 100644
--- a/include/ast.h
+++ b/include/ast.h
@@ -23,7 +23,6 @@ typedef struct FunctionParameter FunctionParameter;
typedef struct FunctionCall FunctionCall;
typedef struct StructDecl StructDecl;
typedef struct StructField StructField;
-typedef struct LhsExpr LhsExpr;
typedef struct AssignmentExpr AssignmentExpr;
typedef struct Import Import;
typedef struct String String;
@@ -147,10 +146,16 @@ typedef struct {
} VariableType;
struct FileScopeReference {
- Parser *parser;
+ Parser *parser; /* Borrowed, the parser that belongs to the same file as the FileScopeReference */
Buffer canonical_path;
};
+struct ParserFileScopeReference {
+ FileScopeReference *file_scope_ref;
+ /* Index in the parser import list. Used by bytecode to know which import an expression belongs to */
+ int import_index;
+};
+
struct Variable {
BufferView name;
ScopeNamedObject resolved_var;
@@ -177,7 +182,7 @@ struct FunctionSignature {
struct FunctionDecl {
LhsExpr *lhs_expr; /* Borrowed from the LhsExpr that owns this FunctionDecl if it exists, otherwise NULL */
- FunctionSignature *signature;
+ FunctionSignature *signature; /* TODO: Make this a non-pointer type? */
Scope body;
SsaFuncIndex ssa_func_index;
};
@@ -188,7 +193,15 @@ struct FunctionCall {
};
struct StructDecl {
+ /*
+ TODO: Instead of having a scope body, use a body with only structdecl. This improves performance
+ and simplifies the code.
+ */
Scope body;
+ /* The number of fields that are pointers or a type that is different on different platforms (i.e isize, usize, etc), recursive */
+ u32 fields_num_pointers;
+ /* The total size of all fields which are of a type that have the same size on all platforms (i.e u8, i32, etc), recursive */
+ u32 fields_fixed_size_bytes;
};
struct StructField {
@@ -232,7 +245,7 @@ struct AssignmentExpr {
struct Import {
BufferView path;
- FileScopeReference *file_scope;
+ ParserFileScopeReference *file_scope;
};
struct String {
@@ -279,6 +292,11 @@ struct ReturnExpr {
};
typedef struct {
+ u32 num_pointers;
+ u32 fixed_size;
+} TypeSize;
+
+typedef struct {
jmp_buf env;
amal_compiler *compiler; /* Borrowed */
Parser *parser; /* Borrowed. This is the parser that belongs to the thread */
@@ -303,6 +321,7 @@ 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);
CHECK_RESULT int structdecl_init(StructDecl *self, Scope *parent, ArenaAllocator *allocator);
+CHECK_RESULT int structdecl_add_field(StructDecl *self, StructField *field, ArenaAllocator *allocator);
LhsExpr* structdecl_get_field_by_name(StructDecl *self, BufferView field_name);
/* Copies @type */
void structfield_init(StructField *self, BufferView name, VariableType *type);
@@ -318,14 +337,13 @@ CHECK_RESULT int else_if_statement_init(ElseIfStatement *self, Scope *parent, Ar
CHECK_RESULT int while_statement_init(WhileStatement *self, Scope *parent, ArenaAllocator *allocator);
void return_expr_init(ReturnExpr *self, Ast *rhs_expr);
+TypeSize resolved_type_get_byte_size(AstResolvedType *self);
+
CHECK_RESULT int scope_init(Scope *self, Scope *parent, ArenaAllocator *allocator);
CHECK_RESULT int file_scope_reference_init(FileScopeReference *self, BufferView canonical_path, ArenaAllocator *allocator);
CHECK_RESULT int scope_add_child(Scope *self, Ast *child);
+
/* longjump to compiler env on failure */
void scope_resolve(Scope *self, AstCompilerContext *context);
-
-
-CHECK_RESULT bool resolved_type_is_func_decl(Ast *self);
-
#endif
diff --git a/include/bytecode/bytecode.h b/include/bytecode/bytecode.h
index b1b5dda..c495d7a 100644
--- a/include/bytecode/bytecode.h
+++ b/include/bytecode/bytecode.h
@@ -26,11 +26,15 @@
6.2 Opcode(u8) + register(i8) + intermediate(u16)\
6.3 Opcode(u8) + register(i8) + data(u16)\
6.4 Opcode(u8) + flags(u8) + num_local_var_reg(u16)
- 7. 5 bytes: Opcode(u8) + index(u16) + num_args(u8) + register(i8)
+ 7. 5 bytes: Opcode(u8) + index(u8) + index(u16) + num_args(u8)
# Registers
Registers have a range of 128. Local variables start from register 0 and increment while parameters start from -1
and decrement. Registers have the scope of functions and reset after instructions reach a new function (AMAL_OP_FUNC_START).
+
+ If import index for call and calle is 0, then that means the function resides in the same file the function call
+ is being called from. Which means that import index 1 is actually import index 0 into the import list.
*/
+/* Important: The number of fields in this enum can't exceed 255 */
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 */
@@ -46,16 +50,17 @@ typedef enum {
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_PUSH_RET, /* push_ret reg - Push register onto stack as a return value of the next function call */
+ AMAL_OP_CALL, /* call ii, fi, num_args - Call a function in imported file (ii, import index) using function index (fi) and num_args arguments. ii is u8, 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_CALLE, /* calle ii, efi, num_args - Call an extern function in imported file (ii, import index) using extern function index (efi) and num_args arguments. ii is u8, 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, label - Jump to label in the current function if reg is zero. label is u16 */
AMAL_OP_JMP, /* jmp label - Unconditional jump to label in the current function. label is u16 */
AMAL_OP_RET, /* ret reg - Return from the function with reg result */
AMAL_OP_FUNC_START, /* func_start flags, num_local_var_reg - Start of a function which has @num_local_var_reg local variable registers allocated and has the flag @flag. @flag 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 */
- AMAL_OP_LABEL, /* label - Label. This is the target of a jump instruction. Jump instructions only jump to labels in the same function scope */
+ AMAL_OP_LABEL /* label - Label. This is the target of a jump instruction. Jump instructions only jump to labels in the same function scope */
} AmalOpcode;
#define AMAL_BYTECODE_MAGIC_NUMBER (u32)0xdec05eba
@@ -63,6 +68,8 @@ typedef enum {
#define AMAL_BYTECODE_MINOR_VERSION 0
#define AMAL_BYTECODE_PATCH_VERSION 0
+#define AMAL_BYTECODE_SECTION_MAGIC_NUMBER (u32)0x004005e4 /* "section\0" in ascii */
+
#define AMAL_BYTECODE_NUM_REGISTERS 256
typedef enum {
@@ -72,13 +79,40 @@ typedef enum {
typedef u8 AmalOpcodeType;
+/* TODO: Make sure this pragma pack works on all platforms */
+#pragma pack(push, 1)
+typedef struct {
+ u32 func_offset;
+ u8 num_params;
+ u32 params_num_pointers;
+ u32 params_fixed_size;
+
+ u8 num_return_types;
+ u32 return_types_num_pointers;
+ u32 return_types_fixed_size;
+} BytecodeHeaderFunction;
+#pragma pack(pop)
+
+/* TODO: Make sure this pragma pack works on all platforms */
+#pragma pack(push, 1)
typedef struct {
+ u32 function_index;
+ #define parser_index function_index
+ u32 extern_function_index;
+} BytecodeHeaderImport;
+#pragma pack(pop)
+
+struct Bytecode {
Buffer/*<headers + instruction data>*/ data;
-} Bytecode;
+ usize import_index; /* Reference inside @data where imports start */
+ u32 funcs_index; /* Reference inside @data where funcs start */
+ u32 extern_funcs_index; /* Reference inside @data where extern funcs start */
+ u32 offset; /* Offset that this bytecode starts from in the final program (all bytecodes combined) */
+};
typedef struct {
jmp_buf env;
- Bytecode bytecode;
+ Bytecode *bytecode;
Parser *parser; /* borrowed */
} BytecodeCompilerContext;
diff --git a/include/defs.h b/include/defs.h
index 669d9c9..bb96421 100644
--- a/include/defs.h
+++ b/include/defs.h
@@ -5,8 +5,11 @@ typedef struct amal_compiler amal_compiler;
typedef struct Parser Parser;
typedef struct Scope Scope;
typedef struct FileScopeReference FileScopeReference;
+typedef struct ParserFileScopeReference ParserFileScopeReference;
typedef struct FunctionDecl FunctionDecl;
typedef struct FunctionSignature FunctionSignature;
+typedef struct LhsExpr LhsExpr;
typedef struct Tokenizer Tokenizer;
+typedef struct Bytecode Bytecode;
#endif
diff --git a/include/parser.h b/include/parser.h
index 81895e1..ae5cfa6 100644
--- a/include/parser.h
+++ b/include/parser.h
@@ -4,7 +4,6 @@
#include "std/buffer_view.h"
#include "std/arena_allocator.h"
#include "std/thread.h"
-#include "bytecode/bytecode.h"
#include "tokenizer.h"
#include "ast.h"
#include "defs.h"
@@ -36,7 +35,14 @@ struct Parser {
TokenizerError error;
ErrorContext error_context;
jmp_buf parse_env;
- Bytecode bytecode;
+ Bytecode *bytecode;
+ Buffer/*<ParserFileScopeReference*>*/ imports;
+ HashMapType(BufferView, usize) imports_by_name; /* The value is an index inside @imports */
+ /*
+ Index in the compilers list of parsers. Used by bytecodes import header
+ to point to the index that contains references to another files variables.
+ */
+ u32 index;
};
CHECK_RESULT int parser_init(Parser *self, amal_compiler *compiler, ArenaAllocator *allocator);
diff --git a/include/program.h b/include/program.h
index e3a4ac9..b398a3a 100644
--- a/include/program.h
+++ b/include/program.h
@@ -35,9 +35,13 @@
#define AMAL_PROGRAM_INVALID_EXPORTED_FUNCTIONS_SIZE -23
#define AMAL_PROGRAM_INSTRUCTION_INVALID_EXPORTED_FUNC_INDEX -24
#define AMAL_PROGRAM_NO_MAIN_FUNC -25
+#define AMAL_PROGRAM_INVALID_IMPORTS -26
+#define AMAL_PROGRAM_SECTION_ERROR -27
#define AMAL_PROGRAM_ARGS_SIZE_VARARGS -1
+#define AMAL_PROGRAM_MAX_RETURN_VALUES 128
+
typedef struct {
void *func;
int args_byte_size; /* -1 if varargs (AMAL_PROGRAM_ARGS_SIZE_VARARGS) */
@@ -49,9 +53,11 @@ typedef struct {
u32 *extern_func_indices;
u8 *intermediates_start; /* Reference inside @data */
u8 *strings_start; /* Reference inside @data */
+ u8 *funcs_start; /* Reference inside @data */
u8 *extern_funcs_start; /* Reference inside @data */
u8 *exported_funcs; /* Reference inside @data */
u8 *exported_funcs_end; /* Reference inside @data */
+ u8 *imports_start; /* Reference inside @data */
usize read_index;
u32 main_func_instruction_offset;
@@ -61,9 +67,14 @@ typedef struct {
u16 num_functions;
u16 num_extern_functions;
u16 num_exported_functions;
+ u8 num_imports;
ArenaAllocator allocator; /* Owned. Used by @extern_funcs_map */
HashMapType(BufferView, ProgramExternFunc) extern_funcs_map;
+ /* key=((func_index<<32)&funcs_start), value=Buffer<u32=current_code_index> */
+ HashMapType(u64, Buffer) deferred_func_calls;
+ i8 return_values_stack[AMAL_PROGRAM_MAX_RETURN_VALUES];
+ int return_value_index;
} amal_program;
CHECK_RESULT int amal_program_init(amal_program *self);
diff --git a/include/ssa/ssa.h b/include/ssa/ssa.h
index 9d6949d..0b6501b 100644
--- a/include/ssa/ssa.h
+++ b/include/ssa/ssa.h
@@ -10,6 +10,7 @@
#define SSA_ERR_EXTERN_FUNC_SIG_MISMATCH -20
+/* Important: The number of fields in this enum can't exceed 255 */
typedef enum {
SSA_ASSIGN_INTER,
SSA_ASSIGN_STRING,
@@ -24,6 +25,7 @@ typedef enum {
SSA_FUNC_START,
SSA_FUNC_END,
SSA_PUSH,
+ SSA_PUSH_RET,
SSA_CALL,
SSA_CALL_EXTERN,
SSA_JUMP_ZERO,
@@ -55,6 +57,10 @@ typedef struct {
BufferView name;
} SsaExportFunc;
+typedef struct {
+ FunctionSignature *func_sig;
+} SsaFunc;
+
typedef i16 JumpOffset;
typedef i16 SsaRegister;
typedef u16 SsaIntermediateIndex;
@@ -73,13 +79,15 @@ typedef struct {
HashMapType(BufferView, SsaExternFuncIndex) extern_funcs_map;
Buffer/*SsaExternFunc*/ extern_funcs;
Buffer/*SsaExportFunc*/ export_funcs;
+ Buffer/*SsaFunc*/ funcs;
+
SsaIntermediateIndex intermediate_counter;
SsaStringIndex string_counter;
SsaExternFuncIndex extern_func_counter;
SsaExportFuncIndex export_func_counter;
+ SsaFuncIndex func_counter;
SsaRegister reg_counter;
SsaRegister param_counter;
- SsaFuncIndex func_counter;
SsaLabelIndex label_counter;
Parser *parser; /* Borrowed */
} Ssa;
@@ -102,14 +110,14 @@ typedef struct {
typedef struct {
u8 num_args;
- SsaRegister result;
FunctionDecl *func_decl;
+ u8 import_index;
} SsaInsFuncCall;
typedef struct {
u8 num_args;
- SsaRegister result;
- SsaExternFuncIndex extern_func_index;
+ LhsExpr *func_decl_lhs;
+ int import_index;
} SsaInsFuncCallExtern;
typedef struct {
@@ -134,6 +142,8 @@ typedef struct {
jmp_buf env;
Ssa *ssa;
amal_compiler *compiler;
+ /* 0 if the current scope belongs to the file, otherwise ParserFileScopeReference's import_index (the import file that contains the scope) */
+ u8 import_index;
} SsaCompilerContext;
/* longjump to context->env on failure */
diff --git a/include/std/buffer.h b/include/std/buffer.h
index d194881..3c2d79c 100644
--- a/include/std/buffer.h
+++ b/include/std/buffer.h
@@ -32,6 +32,8 @@ void* buffer_get(Buffer *self, usize index, usize type_size);
CHECK_RESULT int buffer_pop(Buffer *self, void *data, usize size);
/* Set buffer size to 0, doesn't change the capacity */
void buffer_clear(Buffer *self);
+/* Also changes size if @new_capacity is less than buffer size */
+CHECK_RESULT int buffer_set_capacity(Buffer *self, usize new_capacity);
void* buffer_begin(Buffer *self);
void* buffer_end(Buffer *self);
usize __buffer_get_size(Buffer *self, usize type_size);
diff --git a/include/std/buffer_view.h b/include/std/buffer_view.h
index 59a97d3..9c0a722 100644
--- a/include/std/buffer_view.h
+++ b/include/std/buffer_view.h
@@ -8,7 +8,7 @@ typedef struct {
usize size;
} BufferView;
-BufferView create_buffer_view_null();
+BufferView create_buffer_view_null(void);
BufferView create_buffer_view(const char *data, usize size);
bool buffer_view_equals(const BufferView *self, const BufferView *other);
diff --git a/include/std/hash_map.h b/include/std/hash_map.h
index c9e5b51..05755ce 100644
--- a/include/std/hash_map.h
+++ b/include/std/hash_map.h
@@ -35,6 +35,7 @@ CHECK_RESULT int hash_map_insert(HashMap *self, BufferView key, void *value);
If @value is NULL, then the value is not copied and the functions works the same as @hash_map_contains
*/
CHECK_RESULT bool hash_map_get(HashMap *self, BufferView key, void *value);
+CHECK_RESULT bool hash_map_get_ref(HashMap *self, BufferView key, void **value);
CHECK_RESULT bool hash_map_contains(HashMap *self, BufferView key);
int hash_map_compare_string(const void *a, const void *b);
diff --git a/include/std/log.h b/include/std/log.h
index cd376c6..12b52e1 100644
--- a/include/std/log.h
+++ b/include/std/log.h
@@ -3,7 +3,7 @@
#include "defs.h"
-amal_mutex* amal_log_get_mutex();
+amal_mutex* amal_log_get_mutex(void);
void amal_log_debug(const char *fmt, ...);
void amal_log_error(const char *fmt, ...);
void amal_log_info(const char *fmt, ...);
diff --git a/include/std/mem.h b/include/std/mem.h
index 2afce0d..1cc06bf 100644
--- a/include/std/mem.h
+++ b/include/std/mem.h
@@ -9,6 +9,6 @@ int am_memcmp(const void *lhs, const void *rhs, usize size);
bool am_memeql(const void *lhs, const void *rhs, usize size);
void am_memset(void *dest, int value, usize size);
-long am_pagesize();
+long am_pagesize(void);
#endif
diff --git a/include/std/misc.h b/include/std/misc.h
index e89f1eb..a9bd5b6 100644
--- a/include/std/misc.h
+++ b/include/std/misc.h
@@ -21,8 +21,7 @@
#define return_if_error(result) \
do { \
- int return_if_result; \
- return_if_result = (result); \
+ int return_if_result = (result); \
if(return_if_result != 0) { \
return_if_debug_msg; \
return return_if_result; \
@@ -31,6 +30,11 @@
#define cleanup_if_error(result) do { if((result) != 0) { cleanup_if_debug_msg; goto cleanup; } } while(0)
+typedef struct {
+ int result;
+ void *data;
+} ResultMem;
+
#if defined(__GNUC__) && __GNUC__ >= 4
#define CHECK_RESULT __attribute__ ((warn_unused_result))
#elif defined(_MSC_VER) && _MSC_VER >= 1700
diff --git a/include/std/thread.h b/include/std/thread.h
index 2765204..ae8fe39 100644
--- a/include/std/thread.h
+++ b/include/std/thread.h
@@ -43,9 +43,9 @@ CHECK_RESULT int amal_thread_deinit(amal_thread *self);
CHECK_RESULT int amal_thread_detach(amal_thread *self);
CHECK_RESULT int amal_thread_join(amal_thread *self, void **result);
-bool amal_thread_is_main();
+bool amal_thread_is_main(void);
/* Returns 0 if the number of usable threads is unknown */
-int amal_get_usable_thread_count();
+int amal_get_usable_thread_count(void);
CHECK_RESULT int amal_mutex_init(amal_mutex *self);
void amal_mutex_deinit(amal_mutex *self);