diff options
author | dec05eba <dec05eba@protonmail.com> | 2019-08-24 23:31:14 +0200 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2020-07-25 14:36:46 +0200 |
commit | d9f652919961a2947452ad3c4af4659f3d2fb330 (patch) | |
tree | 2db541db311a9b5a83d3f2c9b199f6d5c3341555 /src/ssa | |
parent | 40652d7dbf701eda83fa8323b42a6b5bf0ca6bdd (diff) |
Add if/else/elseif/while, including the final assembly
Diffstat (limited to 'src/ssa')
-rw-r--r-- | src/ssa/ssa.c | 162 |
1 files changed, 110 insertions, 52 deletions
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) { |