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 --- src/bytecode/bytecode.c | 107 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 81 insertions(+), 26 deletions(-) (limited to 'src/bytecode') diff --git a/src/bytecode/bytecode.c b/src/bytecode/bytecode.c index 8a41900..edc8dba 100644 --- a/src/bytecode/bytecode.c +++ b/src/bytecode/bytecode.c @@ -3,6 +3,7 @@ #include "../../include/std/log.h" #include "../../include/ssa/ssa.h" #include "../../include/parser.h" +#include "../../include/ast.h" #include "../../include/compiler.h" #include #include /* TODO: Remove this */ @@ -37,8 +38,9 @@ static CHECK_RESULT usize ssa_extract_form2(u8 *instruction_data, SsaInsForm2 *r static CHECK_RESULT usize ssa_extract_func_start(u8 *instruction_data, SsaInsFuncStart *result) { am_memcpy(&result->func_index, instruction_data, sizeof(result->func_index)); - am_memcpy(&result->num_registers, instruction_data + sizeof(result->func_index), sizeof(result->num_registers)); - return sizeof(result->func_index) + sizeof(result->num_registers); + am_memcpy(&result->num_params_regs, instruction_data + sizeof(result->func_index), sizeof(result->num_params_regs)); + am_memcpy(&result->num_local_vars_regs, instruction_data + sizeof(result->func_index) + sizeof(result->num_params_regs), sizeof(result->num_local_vars_regs)); + return sizeof(result->func_index) + sizeof(result->num_params_regs) + sizeof(result->num_local_vars_regs); } static CHECK_RESULT usize ssa_extract_func_call(u8 *instruction_data, SsaInsFuncCall *result) { @@ -48,6 +50,13 @@ static CHECK_RESULT usize ssa_extract_func_call(u8 *instruction_data, SsaInsFunc return sizeof(u8) + sizeof(result->result) + sizeof(result->func_decl); } +static CHECK_RESULT usize ssa_extract_func_call_extern(u8 *instruction_data, SsaInsFuncCallExtern *result) { + result->num_args = instruction_data[0]; + am_memcpy(&result->result, instruction_data + 1, sizeof(result->result)); + am_memcpy(&result->extern_func_index, instruction_data + 1 + sizeof(result->result), sizeof(result->extern_func_index)); + return sizeof(u8) + sizeof(result->result) + sizeof(result->extern_func_index); +} + static CHECK_RESULT usize ssa_extract_jump_zero(u8 *instruction_data, SsaInsJumpZero *result) { am_memcpy(&result->condition_reg, instruction_data, sizeof(result->condition_reg)); am_memcpy(&result->jump_offset, instruction_data + sizeof(result->condition_reg), sizeof(result->jump_offset)); @@ -107,7 +116,7 @@ static void add_strings(BytecodeCompilerContext *self) { # String |Type|Field|Description | |----|----|----------------------------------------------------------------------------------------| - |u16 |Size|The size of the string, in bytes. | + |u16 |Size|The size of the string, in bytes. Excluding the null-terminate character. | |u8* |Data|The data of the string, where the size is defined by @Size. Strings are null-terminated.| */ @@ -115,18 +124,12 @@ static void add_strings(BytecodeCompilerContext *self) { Buffer *instructions; BufferView *string; BufferView *strings_end; - u16 num_strings; u32 strings_size; ssa = self->parser->ssa; instructions = &self->bytecode.data; string = buffer_begin(&ssa->strings); strings_end = buffer_end(&ssa->strings); - if(strings_end - string > UINT16_MAX) { - amal_log_error("Too many strings in the program"); - throw(-1); - } - num_strings = strings_end - string; strings_size = 0; for(; string != strings_end; ++string) { @@ -135,10 +138,10 @@ static void add_strings(BytecodeCompilerContext *self) { string = buffer_begin(&ssa->strings); throw_if_error(buffer_expand(instructions, sizeof(u16) + sizeof(u32) + strings_size)); - throw_if_error(buffer_append(instructions, &num_strings, sizeof(u16))); + throw_if_error(buffer_append(instructions, &ssa->string_counter, sizeof(u16))); throw_if_error(buffer_append(instructions, &strings_size, sizeof(u32))); for(; string != strings_end; ++string) { - char null_s = '\0'; + const char null_s = '\0'; throw_if_error(buffer_append(instructions, &string->size, sizeof(u16))); throw_if_error(buffer_append(instructions, string->data, string->size)); throw_if_error(buffer_append(instructions, &null_s, sizeof(char))); @@ -157,6 +160,55 @@ static void add_functions(BytecodeCompilerContext *self) { throw_if_error(buffer_append(&self->bytecode.data, &self->parser->ssa->func_counter, sizeof(u16))); } +static void add_extern_functions(BytecodeCompilerContext *self) { + /*doc(Bytecode external functions) + # External functions layout + |Type |Field |Description | + |------------------|------------------|-----------------------------------------------------------------------------------------| + |u16 |num_extern_func |The number of external functions. | + |u32 |extern_funcs_size |The size of the external functions section, in bytes. | + |External function*|External functions|Multiple external functions, where the number of functions is defined by @num_extern_func| + + # External function + |Type|Field |Description | + |----|--------|-----------------------------------------------------------------------------------------------------| + |u8 |num_args|The number of arguments the functions has. | + |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; + + 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 */ + } + extern_func = buffer_begin(&ssa->extern_funcs); + + throw_if_error(buffer_expand(instructions, sizeof(u16) + sizeof(u32) + extern_funcs_size)); + throw_if_error(buffer_append(instructions, &ssa->extern_func_counter, sizeof(u16))); + 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); + throw_if_error(buffer_append(instructions, &num_args, sizeof(num_args))); + 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))); + } + + assert(sizeof(SsaExternFuncIndex) == sizeof(u16) && "Program decoder needs to be updated since size of extern 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); @@ -164,7 +216,7 @@ static void add_ins1(BytecodeCompilerContext *self, AmalOpcode opcode, const cha } -static void add_ins2(BytecodeCompilerContext *self, AmalOpcode opcode, u8 reg, const char *fmt) { +static void add_ins2(BytecodeCompilerContext *self, AmalOpcode opcode, i8 reg, const char *fmt) { Buffer *instructions; size_t index; instructions = &self->bytecode.data; @@ -177,7 +229,7 @@ static void add_ins2(BytecodeCompilerContext *self, AmalOpcode opcode, u8 reg, c fputc('\n', stderr); } -static void add_ins3(BytecodeCompilerContext *self, AmalOpcode opcode, u8 dst_reg, u8 src_reg, const char *fmt) { +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; @@ -204,7 +256,7 @@ static void add_ins4(BytecodeCompilerContext *self, AmalOpcode opcode, u16 data, fputc('\n', stderr); } -static void add_ins5(BytecodeCompilerContext *self, AmalOpcode opcode, u8 dst_reg, u8 reg1, u8 reg2, const char *fmt) { +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; @@ -219,7 +271,7 @@ static void add_ins5(BytecodeCompilerContext *self, AmalOpcode opcode, u8 dst_re fputc('\n', stderr); } -static void add_ins6(BytecodeCompilerContext *self, AmalOpcode opcode, u8 dst_reg, u16 data, const char *fmt) { +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; @@ -233,17 +285,18 @@ static void add_ins6(BytecodeCompilerContext *self, AmalOpcode opcode, u8 dst_re fputc('\n', stderr); } -static void add_ins7(BytecodeCompilerContext *self, AmalOpcode opcode, u16 idx, u8 arg, const char *fmt) { +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; - throw_if_error(buffer_append_empty(instructions, sizeof(AmalOpcodeType) + sizeof(idx) + sizeof(arg))); + throw_if_error(buffer_append_empty(instructions, sizeof(AmalOpcodeType) + sizeof(idx) + sizeof(num_args) + sizeof(dst_reg))); instructions->data[index] = opcode; memcpy(instructions->data + index + sizeof(AmalOpcodeType), &idx, sizeof(idx)); - instructions->data[index + sizeof(AmalOpcodeType) + sizeof(idx)] = arg; - fprintf(stderr, fmt, idx, arg); + instructions->data[index + sizeof(AmalOpcodeType) + sizeof(idx)] = num_args; + instructions->data[index + sizeof(AmalOpcodeType) + sizeof(idx) + sizeof(num_args)] = dst_reg; + fprintf(stderr, fmt, idx, num_args, dst_reg); fputc('\n', stderr); } @@ -283,6 +336,7 @@ static void add_instructions(BytecodeCompilerContext *self) { SsaInsForm2 ssa_ins_form2; SsaInsFuncStart ssa_ins_func_start; SsaInsFuncCall ssa_ins_func_call; + SsaInsFuncCallExtern ssa_ins_func_call_extern; SsaInsJumpZero ssa_ins_jump_zero; SsaInsJump ssa_ins_jump; @@ -490,7 +544,7 @@ static void add_instructions(BytecodeCompilerContext *self) { } case SSA_FUNC_START: { instruction += ssa_extract_func_start(instruction, &ssa_ins_func_start); - add_ins4(self, AMAL_OP_FUNC_START, ssa_ins_func_start.num_registers, "func_start %u"); + 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"); break; } case SSA_FUNC_END: { @@ -505,10 +559,6 @@ static void add_instructions(BytecodeCompilerContext *self) { break; } case SSA_CALL: { - /* - TODO: Pass return register to function. The register should be a pointer that - has the size of the function return values so the return values can fit in it. - */ /* TODO: Using ssa_func_index only works correctly if the function was defined in the same file as the function call. To make this work with calling functions in other files, @@ -518,8 +568,12 @@ static void add_instructions(BytecodeCompilerContext *self) { is defined as the size of all previous files' number of functions. */ instruction += ssa_extract_func_call(instruction, &ssa_ins_func_call); - add_ins7(self, AMAL_OP_CALL, ssa_ins_func_call.func_decl->ssa_func_index, ssa_ins_func_call.num_args, "call %d, %d"); - assert(bool_false && "TODO: Assign function result (RAX for x86_64) to ssa_ins_func_call.result reg"); + add_ins7(self, AMAL_OP_CALL, ssa_ins_func_call.func_decl->ssa_func_index, ssa_ins_func_call.num_args, ssa_ins_func_call.result, "call f%d, %d, r%d"); + break; + } + case SSA_CALL_EXTERN: { + instruction += ssa_extract_func_call_extern(instruction, &ssa_ins_func_call_extern); + add_ins7(self, AMAL_OP_CALLE, ssa_ins_func_call_extern.extern_func_index, ssa_ins_func_call_extern.num_args, ssa_ins_func_call_extern.result, "calle ef%d, %d, r%d"); break; } case SSA_JUMP_ZERO: { @@ -558,5 +612,6 @@ void generate_bytecode_from_ssa(BytecodeCompilerContext *self) { add_intermediates(self); add_strings(self); add_functions(self); + add_extern_functions(self); add_instructions(self); } -- cgit v1.2.3