diff options
author | dec05eba <dec05eba@protonmail.com> | 2019-09-09 01:08:34 +0200 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2020-07-25 14:36:46 +0200 |
commit | 16aaaa19a3ef4220726007d3e644ced0c9e06513 (patch) | |
tree | 6a7c2fc91bc362559b079afbb10dc247d7bcbae0 /include | |
parent | de48503aef098d855754ab6f85558402130188d7 (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.h | 34 | ||||
-rw-r--r-- | include/bytecode/bytecode.h | 46 | ||||
-rw-r--r-- | include/defs.h | 3 | ||||
-rw-r--r-- | include/parser.h | 10 | ||||
-rw-r--r-- | include/program.h | 11 | ||||
-rw-r--r-- | include/ssa/ssa.h | 18 | ||||
-rw-r--r-- | include/std/buffer.h | 2 | ||||
-rw-r--r-- | include/std/buffer_view.h | 2 | ||||
-rw-r--r-- | include/std/hash_map.h | 1 | ||||
-rw-r--r-- | include/std/log.h | 2 | ||||
-rw-r--r-- | include/std/mem.h | 2 | ||||
-rw-r--r-- | include/std/misc.h | 8 | ||||
-rw-r--r-- | include/std/thread.h | 4 |
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); |