diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bytecode/bytecode.c | 20 | ||||
-rw-r--r-- | src/parser.c | 22 | ||||
-rw-r--r-- | src/program.c | 20 | ||||
-rw-r--r-- | src/ssa/ssa.c | 162 |
4 files changed, 156 insertions, 68 deletions
diff --git a/src/bytecode/bytecode.c b/src/bytecode/bytecode.c index fe3dc0f..47d492c 100644 --- a/src/bytecode/bytecode.c +++ b/src/bytecode/bytecode.c @@ -77,6 +77,7 @@ static void add_intermediates(BytecodeCompilerContext *self) { Buffer *instructions = &self->bytecode.data; SsaNumber *intermediate = buffer_begin(&ssa->intermediates); SsaNumber *intermediates_end = buffer_end(&ssa->intermediates); + int i = 0; u32 intemediates_size = (sizeof(u8) + sizeof(u64)) * buffer_get_size(&ssa->intermediates, SsaNumber); throw_if_error(buffer_expand(instructions, sizeof(u32) + intemediates_size)); @@ -85,6 +86,7 @@ static void add_intermediates(BytecodeCompilerContext *self) { throw_if_error(buffer_append(instructions, &intermediate->type, sizeof(u8))); /* TODO: Store value using an encoding that will save space when using low numbers */ throw_if_error(buffer_append(instructions, &intermediate->value.integer, sizeof(u64))); + fprintf(stderr, "i%d = %ld\n", i++, intermediate->value.integer); } } @@ -228,11 +230,12 @@ static void add_export_functions(BytecodeCompilerContext *self) { 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); - fputc('\n', stderr); + if(fmt) { + fprintf(stderr, fmt); + fputc('\n', stderr); + } } - static void add_ins2(BytecodeCompilerContext *self, AmalOpcode opcode, i8 reg, const char *fmt) { Buffer *instructions = &self->bytecode.data; size_t index = instructions->size; @@ -325,6 +328,7 @@ static void add_instructions(BytecodeCompilerContext *self) { Ssa *ssa = self->parser->ssa; u8 *instruction = buffer_begin(&ssa->instructions); u8 *instructions_end = buffer_end(&ssa->instructions); + u16 label_counter = 0; u32 num_instructions_index = self->bytecode.data.size; throw_if_error(buffer_append_empty(&self->bytecode.data, sizeof(num_instructions_index))); @@ -386,6 +390,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.flags, ssa_ins_func_start.num_local_vars_regs, "func_start 0x%02x, %u"); + label_counter = 0; break; } case SSA_FUNC_END: { @@ -419,12 +424,12 @@ static void add_instructions(BytecodeCompilerContext *self) { } case SSA_JUMP_ZERO: { instruction += ssa_extract_data(instruction, &ssa_ins_jump_zero, sizeof(ssa_ins_jump_zero)); - add_ins6(self, AMAL_OP_JZ, ssa_ins_jump_zero.condition_reg, ssa_ins_jump_zero.jump_offset, "jz r%d, %d"); + add_ins6(self, AMAL_OP_JZ, ssa_ins_jump_zero.condition_reg, ssa_ins_jump_zero.target_label, "jz r%d, l%d"); break; } case SSA_JUMP: { instruction += ssa_extract_data(instruction, &ssa_ins_jump, sizeof(ssa_ins_jump)); - add_ins4(self, AMAL_OP_JMP, ssa_ins_jump.jump_offset, "jmp %d"); + add_ins4(self, AMAL_OP_JMP, ssa_ins_jump.target_label, "jmp l%d"); break; } case SSA_RET: { @@ -434,6 +439,11 @@ static void add_instructions(BytecodeCompilerContext *self) { add_ins2(self, AMAL_OP_RET, reg, "ret r%d"); break; } + case SSA_LABEL: { + add_ins1(self, AMAL_OP_LABEL, NULL); + fprintf(stderr, "label l%d\n", label_counter++); + break; + } } } diff --git a/src/parser.c b/src/parser.c index ff34663..a6b4ecf 100644 --- a/src/parser.c +++ b/src/parser.c @@ -48,6 +48,10 @@ int parser_init(Parser *self, amal_compiler *compiler, ArenaAllocator *allocator return PARSER_OK; } +static bool parser_is_current_scope_file_scope(Parser *self) { + return self->current_scope == &self->struct_decl.body; +} + /* BODY_LOOP = BODY* @end_token */ @@ -359,6 +363,12 @@ static CHECK_RESULT FunctionDecl* parser_parse_closure(Parser *self) { if(!signature) return NULL; + /* + TODO: Implement function declaration inside other functions. + Such functions should be moved to the file scope in the bytecode generation + */ + assert(parser_is_current_scope_file_scope(self)); + throw_if_error(arena_allocator_alloc(self->allocator, sizeof(FunctionDecl), (void**)&result)); throw_if_error(funcdecl_init(result, signature, self->current_scope, self->allocator)); signature->func_decl = result; @@ -500,16 +510,20 @@ static CHECK_RESULT ElseIfStatement* parser_parse_else_if_statement(Parser *self } static void parser_parse_else_if_statement_loop(Parser *self, IfStatement *if_stmt) { - ElseIfStatement *else_if_stmt; - else_if_stmt = if_stmt->else_if_stmt; + ElseIfStatement *else_if_stmt = NULL; for(;;) { ElseIfStatement *next_else_if; next_else_if = parser_parse_else_if_statement(self); if(!next_else_if) break; - else_if_stmt->next_else_if_stmt = next_else_if; + + if(!else_if_stmt) + if_stmt->else_if_stmt = next_else_if; + else + else_if_stmt->next_else_if_stmt = next_else_if; + /* else statement that has no condition can't be followed by another else statement */ - if(!else_if_stmt->condition) + if(!next_else_if->condition) break; else_if_stmt = next_else_if; } diff --git a/src/program.c b/src/program.c index 55bfda4..eef49b6 100644 --- a/src/program.c +++ b/src/program.c @@ -125,7 +125,7 @@ static CHECK_RESULT int amal_program_set_exported_function_instruction_offset_ad num_args = self->exported_funcs[sizeof(instruction_offset)]; func_name_size = self->exported_funcs[sizeof(instruction_offset) + sizeof(num_args)]; self->exported_funcs += sizeof(instruction_offset) + sizeof(num_args) + sizeof(func_name_size); - if(self->main_func_instruction_offset == ~0U && am_memeql(self->exported_funcs, "main", 4)) + if(self->main_func_instruction_offset == ~0U && func_name_size == 4 && am_memeql(self->exported_funcs, "main", 4)) self->main_func_instruction_offset = instruction_offset; /* +1 to skip null-termination character */ @@ -521,16 +521,18 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ break; } case AMAL_OP_JZ: { - i16 jump_offset; - am_memcpy(&jump_offset, &self->data.data[self->read_index + sizeof(i8)], sizeof(jump_offset)); - return_if_error(amal_exec_jz(executor, self->data.data[self->read_index], jump_offset)); + i8 reg; + u16 target_label; + reg = self->data.data[self->read_index]; + am_memcpy(&target_label, self->data.data + self->read_index + sizeof(reg), sizeof(target_label)); + return_if_error(amal_exec_jz(executor, reg, target_label)); self->read_index += 3; break; } case AMAL_OP_JMP: { - i16 jump_offset; - am_memcpy(&jump_offset, &self->data.data[self->read_index], sizeof(jump_offset)); - return_if_error(amal_exec_jmp(executor, jump_offset)); + u16 target_label; + am_memcpy(&target_label, self->data.data + self->read_index, sizeof(target_label)); + return_if_error(amal_exec_jmp(executor, target_label)); self->read_index += 2; break; } @@ -564,6 +566,10 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ return_if_error(amal_exec_func_end(executor)); break; } + case AMAL_OP_LABEL: { + return_if_error(amal_exec_label(executor)); + break; + } } } diff --git a/src/ssa/ssa.c b/src/ssa/ssa.c index 940f636..5c625b2 100644 --- a/src/ssa/ssa.c +++ b/src/ssa/ssa.c @@ -69,6 +69,7 @@ int ssa_init(Ssa *self, Parser *parser) { self->reg_counter = 0; self->param_counter = 0; self->func_counter = 0; + self->label_counter = 0; self->parser = parser; return 0; } @@ -80,6 +81,7 @@ static CHECK_RESULT int ssa_get_unique_reg(Ssa *self, SsaRegister *result) { amal_log_error("Ssa too many registers!"); return -1; } + assert(self->reg_counter <= INT8_MAX && "TODO: Implement usage of reg higher than 128"); *result = self->reg_counter++; return 0; } @@ -331,24 +333,33 @@ static CHECK_RESULT int ssa_ins_call_extern(Ssa *self, SsaExternFuncIndex extern return buffer_append(&self->instructions, &ins_func_call_extern, sizeof(ins_func_call_extern)); } -static CHECK_RESULT int ssa_ins_jumpzero(Ssa *self, SsaRegister condition_reg, JumpOffset jump_offset) { +static CHECK_RESULT int ssa_ins_jumpzero(Ssa *self, SsaRegister condition_reg, SsaLabelIndex target_label, usize *instruction_offset) { const u8 ins_type = SSA_JUMP_ZERO; SsaInsJumpZero ins_jump_zero; ins_jump_zero.condition_reg = condition_reg; - ins_jump_zero.jump_offset = jump_offset; - if(jump_offset == 0) + ins_jump_zero.target_label = target_label; + if(target_label == 0) amal_log_debug("JUMP_ZERO r%d, DUMMY", condition_reg); else - amal_log_debug("JUMP_ZERO r%d, %d", condition_reg, jump_offset); + amal_log_debug("JUMP_ZERO r%d, l%d", condition_reg, target_label); + *instruction_offset = self->instructions.size; return_if_error(buffer_append(&self->instructions, &ins_type, 1)); return buffer_append(&self->instructions, &ins_jump_zero, sizeof(ins_jump_zero)); } -static CHECK_RESULT int ssa_ins_jump(Ssa *self, JumpOffset jump_offset) { +static CHECK_RESULT int ssa_ins_jump(Ssa *self, SsaLabelIndex target_label, usize *instruction_offset) { const u8 ins_type = SSA_JUMP; SsaInsJump ins_jump; - ins_jump.jump_offset = jump_offset; - amal_log_debug("JUMP %d", jump_offset); + ins_jump.target_label = target_label; + + if(target_label == 0) + amal_log_debug("JUMP DUMMY"); + else + amal_log_debug("JUMP l%d", target_label); + + if(instruction_offset) + *instruction_offset = self->instructions.size; + return_if_error(buffer_append(&self->instructions, &ins_type, 1)); return buffer_append(&self->instructions, &ins_jump, sizeof(ins_jump)); } @@ -359,21 +370,28 @@ static CHECK_RESULT int ssa_ins_return(Ssa *self, SsaRegister reg) { return buffer_append(&self->instructions, ®, sizeof(reg)); } -static usize ssa_ins_get_index(Ssa *self) { - return self->instructions.size; +static CHECK_RESULT int ssa_ins_label(Ssa *self, u16 *label_index) { + const u8 ins_type = SSA_LABEL; + /* Overflow */ + if(self->label_counter + 1 <= self->label_counter) { + amal_log_error("Ssa too many labels!"); + return -1; + } + *label_index = self->label_counter; + ++self->label_counter; + return buffer_append(&self->instructions, &ins_type, 1); } -/* Set target of jump instruction to current location */ -static CHECK_RESULT int ssa_ins_jump_set_target(Ssa *self, usize jump_ins_index) { +static CHECK_RESULT int ssa_set_jump_label(Ssa *self, usize jump_ins_index, SsaLabelIndex label) { switch(self->instructions.data[jump_ins_index]) { case SSA_JUMP_ZERO: { - isize jump_offset = (isize)ssa_ins_get_index(self) - (isize)jump_ins_index; - /* TODO: Should something be done about this? */ - if(jump_offset < -0x7FFF || jump_offset > 0x7FFF) { - amal_log_error("Unexpected error. Jump offset has to be less than +-32767, was %d", jump_offset); - return -1; - } - am_memcpy(self->instructions.data + jump_ins_index + 1 + offsetof(SsaInsJumpZero, jump_offset), &jump_offset, sizeof(JumpOffset)); + /* +1 to skip instruction opcode */ + am_memcpy(self->instructions.data + jump_ins_index + 1 + offsetof(SsaInsJumpZero, target_label), &label, sizeof(SsaLabelIndex)); + break; + } + case SSA_JUMP: { + /* +1 to skip instruction opcode */ + am_memcpy(self->instructions.data + jump_ins_index + 1 + offsetof(SsaInsJump, target_label), &label, sizeof(SsaLabelIndex)); break; } default: @@ -386,6 +404,7 @@ static CHECK_RESULT int ssa_ins_jump_set_target(Ssa *self, usize jump_ins_index) static CHECK_RESULT SsaRegister ast_generate_ssa(Ast *self, SsaCompilerContext *context); static CHECK_RESULT SsaRegister scope_named_object_generate_ssa(ScopeNamedObject *self, SsaCompilerContext *context); +#if 0 static bool ast_resolved_type_is_decl(AstResolvedType *self) { /* TODO: Add more types as they are introduced */ LhsExpr *lhs_expr; @@ -406,6 +425,24 @@ static bool ast_resolved_type_is_decl(AstResolvedType *self) { assert(lhs_expr->rhs_expr); return lhs_expr->rhs_expr->type == AST_FUNCTION_DECL || lhs_expr->rhs_expr->type == AST_STRUCT_DECL; } +#endif +static bool lhs_expr_is_decl(LhsExpr *self) { + if(self->rhs_expr) { + return self->rhs_expr->type == AST_FUNCTION_DECL || self->rhs_expr->type == AST_STRUCT_DECL; + } else { + switch(self->type.type) { + case VARIABLE_TYPE_NONE: + assert(bool_false); + return 0; + case VARIABLE_TYPE_VARIABLE: + return bool_false; + case VARIABLE_TYPE_SIGNATURE: + /* TODO: This should return bool_false when it's possible to use signature in expressions */ + return bool_true; + } + return 0; + } +} static CHECK_RESULT SsaRegister number_generate_ssa(Number *self, SsaCompilerContext *context) { SsaRegister reg; @@ -482,7 +519,7 @@ static CHECK_RESULT SsaRegister lhsexpr_generate_ssa(LhsExpr *self, AstResolveDa Import expression also has no meaning in SSA until it's used. TODO: Shouldn't lhsexpr that have struct/function declaration as rhs be different ast expression types? */ - if(ast_resolved_type_is_decl(&resolve_data->type) || rhs_expr->type == AST_IMPORT) { + if(lhs_expr_is_decl(self) || rhs_expr->type == AST_IMPORT) { /*assert(bool_false);*/ return 0; } @@ -528,6 +565,7 @@ static CHECK_RESULT SsaRegister function_parameter_generate_ssa(FunctionParamete throw(-1); } reg = -1 - reg; + assert(reg >= INT8_MIN && "TODO: Implement more than 128 params"); self->resolve_data.status = AST_SSA_RESOLVED; self->resolve_data.ssa_reg = reg; return reg; @@ -555,10 +593,9 @@ static CHECK_RESULT SsaRegister funcdecl_generate_ssa(FunctionDecl *self, SsaCom that is reset after function end */ usize func_metadata_index; - SsaRegister prev_reg_counter = context->ssa->reg_counter; - SsaRegister prev_param_counter = context->ssa->param_counter; u8 func_flags = 0; context->ssa->reg_counter = 0; + context->ssa->label_counter = 0; /* Parameters need to have generated ssa so the first ssa registers belong to the function. @@ -580,9 +617,6 @@ static CHECK_RESULT SsaRegister funcdecl_generate_ssa(FunctionDecl *self, SsaCom /* Add the number of registers used to the function metadata (FUNC_START) */ am_memcpy(context->ssa->instructions.data + func_metadata_index, &context->ssa->reg_counter, sizeof(u16)); - - context->ssa->param_counter = prev_param_counter; - context->ssa->reg_counter = prev_reg_counter; return 0; } @@ -684,47 +718,71 @@ static CHECK_RESULT SsaRegister binop_generate_ssa(Binop *self, SsaCompilerConte return reg; } -static void else_if_statement_generate_ssa(ElseIfStatement *else_if_stmt, SsaCompilerContext *context) { - usize jump_ins_index = 0; +static void else_if_statement_generate_ssa(ElseIfStatement *else_if_stmt, SsaCompilerContext *context, SsaLabelIndex *skip_other_else_statements_label) { if(else_if_stmt->condition) { - SsaRegister condition_reg; - condition_reg = ast_generate_ssa(else_if_stmt->condition, context); - jump_ins_index = ssa_ins_get_index(context->ssa); - throw_if_error(ssa_ins_jumpzero(context->ssa, condition_reg, 0)); + usize jump_ins_index; + usize jump_skip_else_index; + SsaLabelIndex skip_body_label; + SsaRegister condition_reg = ast_generate_ssa(else_if_stmt->condition, context); + throw_if_error(ssa_ins_jumpzero(context->ssa, condition_reg, 0, &jump_ins_index)); + scope_generate_ssa(&else_if_stmt->body, context); + if(else_if_stmt->next_else_if_stmt) + throw_if_error(ssa_ins_jump(context->ssa, 0, &jump_skip_else_index)); + + throw_if_error(ssa_ins_label(context->ssa, &skip_body_label)); + throw_if_error(ssa_set_jump_label(context->ssa, jump_ins_index, skip_body_label)); + if(else_if_stmt->next_else_if_stmt) { + else_if_statement_generate_ssa(else_if_stmt->next_else_if_stmt, context, skip_other_else_statements_label); + /* Skip over all other else if statements, since else_if_statement_generate_ssa is recursive */ + throw_if_error(ssa_set_jump_label(context->ssa, jump_skip_else_index, *skip_other_else_statements_label)); + return; + } + } else { + assert(!else_if_stmt->next_else_if_stmt); + scope_generate_ssa(&else_if_stmt->body, context); } - scope_generate_ssa(&else_if_stmt->body, context); - if(else_if_stmt->condition) - throw_if_error(ssa_ins_jump_set_target(context->ssa, jump_ins_index)); - if(else_if_stmt->next_else_if_stmt) - else_if_statement_generate_ssa(else_if_stmt->next_else_if_stmt, context); + + /* Note: The last else if statement doesn't need a jump */ + throw_if_error(ssa_ins_label(context->ssa, skip_other_else_statements_label)); } static void if_statement_generate_ssa(IfStatement *if_stmt, SsaCompilerContext *context) { + usize jump_ins_index; + usize jump_skip_else_index; + SsaLabelIndex skip_body_label; + SsaLabelIndex skip_else_statements_label; + SsaRegister condition_reg = ast_generate_ssa(if_stmt->condition, context); - usize jump_ins_index = ssa_ins_get_index(context->ssa); - throw_if_error(ssa_ins_jumpzero(context->ssa, condition_reg, 0)); + throw_if_error(ssa_ins_jumpzero(context->ssa, condition_reg, 0, &jump_ins_index)); scope_generate_ssa(&if_stmt->body, context); - throw_if_error(ssa_ins_jump_set_target(context->ssa, jump_ins_index)); if(if_stmt->else_if_stmt) - else_if_statement_generate_ssa(if_stmt->else_if_stmt, context); + throw_if_error(ssa_ins_jump(context->ssa, 0, &jump_skip_else_index)); + + throw_if_error(ssa_ins_label(context->ssa, &skip_body_label)); + throw_if_error(ssa_set_jump_label(context->ssa, jump_ins_index, skip_body_label)); + if(if_stmt->else_if_stmt) { + else_if_statement_generate_ssa(if_stmt->else_if_stmt, context, &skip_else_statements_label); + /* + Skip over all else if statements, since else_if_statement_generate_ssa is recursive. + We want to jump since we want to skip the else if statements if we are inside the first if-statement + */ + throw_if_error(ssa_set_jump_label(context->ssa, jump_skip_else_index, skip_else_statements_label)); + } } static void while_statement_generate_ssa(WhileStatement *while_stmt, SsaCompilerContext *context) { - isize jump_offset; - usize jump_back_ins_index = ssa_ins_get_index(context->ssa); + SsaLabelIndex before_condition_label; + SsaLabelIndex skip_body_label; + usize jump_after_condition_index; + + throw_if_error(ssa_ins_label(context->ssa, &before_condition_label)); SsaRegister condition_reg = ast_generate_ssa(while_stmt->condition, context); - usize jump_condition_ins_index = ssa_ins_get_index(context->ssa); - throw_if_error(ssa_ins_jumpzero(context->ssa, condition_reg, 0)); + throw_if_error(ssa_ins_jumpzero(context->ssa, condition_reg, 0, &jump_after_condition_index)); scope_generate_ssa(&while_stmt->body, context); - /* Jump back and check condition again before running the content of the loop again */ - jump_offset = (isize)jump_back_ins_index - (isize)ssa_ins_get_index(context->ssa); - /* TODO: Should something be done about this? */ - if(jump_offset < -0x7FFF || jump_offset > 0x7FFF) { - amal_log_error("Unexpected error. Jump offset has to be less than +-32767, was %d", jump_offset); - throw(1); - } - throw_if_error(ssa_ins_jump(context->ssa, (JumpOffset)jump_offset)); - throw_if_error(ssa_ins_jump_set_target(context->ssa, jump_condition_ins_index)); + + throw_if_error(ssa_ins_jump(context->ssa, before_condition_label, NULL)); + throw_if_error(ssa_ins_label(context->ssa, &skip_body_label)); + throw_if_error(ssa_set_jump_label(context->ssa, jump_after_condition_index, skip_body_label)); } static void return_expr_generate_ssa(ReturnExpr *self, SsaCompilerContext *context) { |