From 7212ea877ed85d3b85af90c902639df44fc493f2 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 24 Aug 2019 00:48:40 +0200 Subject: Add exported variable (only functions for now), export main func, start execution from main func --- src/bytecode/bytecode.c | 185 +++++++++++++++++++++++++++--------------------- 1 file changed, 106 insertions(+), 79 deletions(-) (limited to 'src/bytecode') diff --git a/src/bytecode/bytecode.c b/src/bytecode/bytecode.c index 80cc95b..fe3dc0f 100644 --- a/src/bytecode/bytecode.c +++ b/src/bytecode/bytecode.c @@ -23,6 +23,36 @@ int bytecode_init(Bytecode *self, ArenaAllocator *allocator) { return buffer_init(&self->data, allocator); } +/*doc(Bytecode) +The layout of the full bytecode is: Header (Intermediates Strings Functions External_Functions Exported_Functions Instructions)* +*/ + +CHECK_RESULT int buffer_append_header(Buffer *program_data) { + /*doc(Bytecode header) + # Header layout + |Type|Field |Description | + |----|-------------|----------------------------------------------------------------------------| + |u32 |Magic number |The magic number used to identify an amalgam bytecode file. | + |u8 |Major version|The major version of the bytecode. Updates in this is a breaking change. | + |u8 |Minor version|The minor version of the bytecode. Updates in this are backwards compatible.| + |u8 |Patch version|The patch version of the bytecode. Updates in this are only minor bug fixes.| + + The versions in the header only changes for every release, not every change. + */ + + const u32 magic_number = AMAL_BYTECODE_MAGIC_NUMBER; + const u8 major_version = AMAL_BYTECODE_MAJOR_VERSION; + const u8 minor_version = AMAL_BYTECODE_MINOR_VERSION; + const u8 patch_version = AMAL_BYTECODE_PATCH_VERSION; + + return_if_error(buffer_append(program_data, &magic_number, 4)); + return_if_error(buffer_append(program_data, &major_version, 1)); + return_if_error(buffer_append(program_data, &minor_version, 1)); + return_if_error(buffer_append(program_data, &patch_version, 1)); + + return 0; +} + static CHECK_RESULT usize ssa_extract_data(u8 *instruction_data, void *result, usize size) { am_memcpy(result, instruction_data, size); return size; @@ -43,18 +73,12 @@ static void add_intermediates(BytecodeCompilerContext *self) { |u64 |Value|The type of the value depends on the value of @Type.| */ - Ssa *ssa; - Buffer *instructions; - SsaNumber *intermediate; - SsaNumber *intermediates_end; - u32 intemediates_size; - - ssa = self->parser->ssa; - instructions = &self->bytecode.data; - intermediate = buffer_begin(&ssa->intermediates); - intermediates_end = buffer_end(&ssa->intermediates); + Ssa *ssa = self->parser->ssa; + Buffer *instructions = &self->bytecode.data; + SsaNumber *intermediate = buffer_begin(&ssa->intermediates); + SsaNumber *intermediates_end = buffer_end(&ssa->intermediates); - intemediates_size = (sizeof(u8) + sizeof(u64)) * buffer_get_size(&ssa->intermediates, SsaNumber); + u32 intemediates_size = (sizeof(u8) + sizeof(u64)) * buffer_get_size(&ssa->intermediates, SsaNumber); throw_if_error(buffer_expand(instructions, sizeof(u32) + intemediates_size)); throw_if_error(buffer_append(instructions, &intemediates_size, sizeof(u32))); for(; intermediate != intermediates_end; ++intermediate) { @@ -80,17 +104,11 @@ static void add_strings(BytecodeCompilerContext *self) { |u8* |Data|The data of the string, where the size is defined by @Size. Strings are null-terminated.| */ - Ssa *ssa; - Buffer *instructions; - BufferView *string; - BufferView *strings_end; - u32 strings_size; - - ssa = self->parser->ssa; - instructions = &self->bytecode.data; - string = buffer_begin(&ssa->strings); - strings_end = buffer_end(&ssa->strings); - strings_size = 0; + Ssa *ssa = self->parser->ssa; + Buffer *instructions = &self->bytecode.data; + BufferView *string = buffer_begin(&ssa->strings); + BufferView *strings_end = buffer_end(&ssa->strings); + u32 strings_size = 0; for(; string != strings_end; ++string) { strings_size += sizeof(u16) + string->size + 1; /* +1 for null-termination of string */ @@ -136,17 +154,11 @@ static void add_extern_functions(BytecodeCompilerContext *self) { |u8 |name_len|The length of the external function name, in bytes. Excluding the null-terminate character. | |u8* |name |The name of the external function, where the size is defined by @name_len. Names are null-terminated.| */ - - Ssa *ssa; - Buffer *instructions; - SsaExternFunc *extern_func, *extern_func_end; - u32 extern_funcs_size; - - ssa = self->parser->ssa; - instructions = &self->bytecode.data; - extern_func = buffer_begin(&ssa->extern_funcs); - extern_func_end = buffer_end(&ssa->extern_funcs); - extern_funcs_size = 0; + Ssa *ssa = self->parser->ssa; + Buffer *instructions = &self->bytecode.data; + SsaExternFunc *extern_func = buffer_begin(&ssa->extern_funcs); + SsaExternFunc *extern_func_end = buffer_end(&ssa->extern_funcs); + u32 extern_funcs_size = 0; for(; extern_func != extern_func_end; ++extern_func) { extern_funcs_size += sizeof(u8) + sizeof(u8) + extern_func->name.size + 1; /* +1 for null-termination of string */ @@ -158,9 +170,9 @@ static void add_extern_functions(BytecodeCompilerContext *self) { throw_if_error(buffer_append(instructions, &extern_funcs_size, sizeof(u32))); for(; extern_func != extern_func_end; ++extern_func) { const char null_s = '\0'; - u8 num_args; - num_args = buffer_get_size(&extern_func->func_sig->parameters, FunctionParameter); + u8 num_args = buffer_get_size(&extern_func->func_sig->parameters, FunctionParameter); throw_if_error(buffer_append(instructions, &num_args, sizeof(num_args))); + /* TODO: Add namespace to the function name */ throw_if_error(buffer_append(instructions, &extern_func->name.size, sizeof(u8))); throw_if_error(buffer_append(instructions, extern_func->name.data, extern_func->name.size)); throw_if_error(buffer_append(instructions, &null_s, sizeof(char))); @@ -169,6 +181,51 @@ static void add_extern_functions(BytecodeCompilerContext *self) { assert(sizeof(SsaExternFuncIndex) == sizeof(u16) && "Program decoder needs to be updated since size of extern func index has changed"); } +static void add_export_functions(BytecodeCompilerContext *self) { + /*doc(Bytecode exported functions) + # Exported functions layout + |Type |Field |Description | + |-----------------|------------------|-----------------------------------------------------------------------------------------| + |u16 |num_export_func |The number of exported functions. | + |u32 |export_funcs_size |The size of the exported functions section, in bytes. | + |Exported function|Exported functions|Multiple exported functions, where the number of functions is defined by @num_export_func| + + # Exported function + |Type|Field |Description | + |----|------------------|--------------------------------------------------------------------------------------------------------------------------| + |u32 |instruction_offset|The offset in the instruction data where the exported function is defined. Is always 0 until the program has been started.| + |u8 |num_args |The number of arguments the functions has. | + |u8 |name_len |The length of the exported function name, in bytes. Excluding the null-terminate character. | + |u8* |name |The name of the exported function, where the size is defined by @name_len. Names are null-terminated. | + */ + Ssa *ssa = self->parser->ssa; + Buffer *instructions = &self->bytecode.data; + SsaExportFunc *export_func = buffer_begin(&ssa->export_funcs); + SsaExportFunc *export_func_end = buffer_end(&ssa->export_funcs); + u32 export_funcs_size = 0; + + for(; export_func != export_func_end; ++export_func) { + export_funcs_size += sizeof(u32) + sizeof(u8) + sizeof(u8) + export_func->name.size + 1; /* +1 for null-termination of string */ + } + export_func = buffer_begin(&ssa->export_funcs); + + throw_if_error(buffer_expand(instructions, sizeof(u16) + sizeof(u32) + export_funcs_size)); + throw_if_error(buffer_append(instructions, &ssa->export_func_counter, sizeof(u16))); + throw_if_error(buffer_append(instructions, &export_funcs_size, sizeof(u32))); + for(; export_func != export_func_end; ++export_func) { + const char null_s = '\0'; + const u32 instruction_offset = 0; + u8 num_args = buffer_get_size(&export_func->func_sig->parameters, FunctionParameter); + throw_if_error(buffer_append(instructions, &instruction_offset, sizeof(instruction_offset))); + throw_if_error(buffer_append(instructions, &num_args, sizeof(num_args))); + throw_if_error(buffer_append(instructions, &export_func->name.size, sizeof(u8))); + throw_if_error(buffer_append(instructions, export_func->name.data, export_func->name.size)); + throw_if_error(buffer_append(instructions, &null_s, sizeof(char))); + } + + assert(sizeof(SsaExportFuncIndex) == sizeof(u16) && "Program decoder needs to be updated since size of export func index has changed"); +} + static void add_ins1(BytecodeCompilerContext *self, AmalOpcode opcode, const char *fmt) { throw_if_error(buffer_append(&self->bytecode.data, &opcode, sizeof(AmalOpcodeType))); fprintf(stderr, fmt); @@ -177,10 +234,8 @@ static void add_ins1(BytecodeCompilerContext *self, AmalOpcode opcode, const cha static void add_ins2(BytecodeCompilerContext *self, AmalOpcode opcode, i8 reg, const char *fmt) { - Buffer *instructions; - size_t index; - instructions = &self->bytecode.data; - index = instructions->size; + Buffer *instructions = &self->bytecode.data; + size_t index = instructions->size; throw_if_error(buffer_append_empty(instructions, sizeof(AmalOpcodeType) + sizeof(reg))); instructions->data[index] = opcode; @@ -190,10 +245,8 @@ static void add_ins2(BytecodeCompilerContext *self, AmalOpcode opcode, i8 reg, c } static void add_ins3(BytecodeCompilerContext *self, AmalOpcode opcode, i8 dst_reg, i8 src_reg, const char *fmt) { - Buffer *instructions; - size_t index; - instructions = &self->bytecode.data; - index = instructions->size; + Buffer *instructions = &self->bytecode.data; + size_t index = instructions->size; throw_if_error(buffer_append_empty(instructions, sizeof(AmalOpcodeType) + sizeof(dst_reg) + sizeof(src_reg))); instructions->data[index] = opcode; @@ -204,10 +257,8 @@ static void add_ins3(BytecodeCompilerContext *self, AmalOpcode opcode, i8 dst_re } static void add_ins4(BytecodeCompilerContext *self, AmalOpcode opcode, u16 data, const char *fmt) { - Buffer *instructions; - size_t index; - instructions = &self->bytecode.data; - index = instructions->size; + Buffer *instructions = &self->bytecode.data; + size_t index = instructions->size; throw_if_error(buffer_append_empty(instructions, sizeof(AmalOpcodeType) + sizeof(data))); instructions->data[index] = opcode; @@ -217,10 +268,8 @@ static void add_ins4(BytecodeCompilerContext *self, AmalOpcode opcode, u16 data, } static void add_ins5(BytecodeCompilerContext *self, AmalOpcode opcode, i8 dst_reg, i8 reg1, i8 reg2, const char *fmt) { - Buffer *instructions; - size_t index; - instructions = &self->bytecode.data; - index = instructions->size; + Buffer *instructions = &self->bytecode.data; + size_t index = instructions->size; throw_if_error(buffer_append_empty(instructions, sizeof(AmalOpcodeType) + sizeof(dst_reg) + sizeof(reg1) + sizeof(reg2))); instructions->data[index] = opcode; @@ -232,10 +281,8 @@ static void add_ins5(BytecodeCompilerContext *self, AmalOpcode opcode, i8 dst_re } static void add_ins6(BytecodeCompilerContext *self, AmalOpcode opcode, i8 dst_reg, u16 data, const char *fmt) { - Buffer *instructions; - size_t index; - instructions = &self->bytecode.data; - index = instructions->size; + Buffer *instructions = &self->bytecode.data; + size_t index = instructions->size; throw_if_error(buffer_append_empty(instructions, sizeof(AmalOpcodeType) + sizeof(dst_reg) + sizeof(data))); instructions->data[index] = opcode; @@ -246,10 +293,8 @@ static void add_ins6(BytecodeCompilerContext *self, AmalOpcode opcode, i8 dst_re } static void add_ins7(BytecodeCompilerContext *self, AmalOpcode opcode, u16 idx, i8 num_args, i8 dst_reg, const char *fmt) { - Buffer *instructions; - size_t index; - instructions = &self->bytecode.data; - index = instructions->size; + Buffer *instructions = &self->bytecode.data; + size_t index = instructions->size; throw_if_error(buffer_append_empty(instructions, sizeof(AmalOpcodeType) + sizeof(idx) + sizeof(num_args) + sizeof(dst_reg))); instructions->data[index] = opcode; @@ -260,25 +305,6 @@ static void add_ins7(BytecodeCompilerContext *self, AmalOpcode opcode, u16 idx, fputc('\n', stderr); } -#if 0 -#define NUM_MAX_REGS 256 -#define NUM_MAX_FUNC_ARGS 32 - -static const char* lhs_expr_get_c_name(BytecodeCompilerContext *self, LhsExpr *lhs_expr) { - if(lhs_expr == self->parser->compiler->default_types.i64) { - return "i64"; - } else if(lhs_expr == self->parser->compiler->default_types.f64) { - return "f64"; - } else if(lhs_expr == self->parser->compiler->default_types.str) { - return"const char*"; - } else { - amal_log_error("Invalid rhs type %p", lhs_expr); - assert(bool_false && "TODO: Implement"); - return ""; - } -} -#endif - static void add_instructions(BytecodeCompilerContext *self) { /*doc(Bytecode instructions) # Instructions layout @@ -359,7 +385,7 @@ static void add_instructions(BytecodeCompilerContext *self) { } case SSA_FUNC_START: { instruction += ssa_extract_data(instruction, &ssa_ins_func_start, sizeof(ssa_ins_func_start)); - add_ins6(self, AMAL_OP_FUNC_START, ssa_ins_func_start.num_params_regs, ssa_ins_func_start.num_local_vars_regs, "func_start %d, %u"); + add_ins6(self, AMAL_OP_FUNC_START, ssa_ins_func_start.flags, ssa_ins_func_start.num_local_vars_regs, "func_start 0x%02x, %u"); break; } case SSA_FUNC_END: { @@ -424,5 +450,6 @@ void generate_bytecode_from_ssa(BytecodeCompilerContext *self) { add_strings(self); add_functions(self); add_extern_functions(self); + add_export_functions(self); add_instructions(self); } -- cgit v1.2.3