diff options
author | dec05eba <dec05eba@protonmail.com> | 2019-06-07 10:47:47 +0200 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2020-07-25 14:36:46 +0200 |
commit | 53a331bc8b2fc33bd2b7e25a23b4128f89ee0b52 (patch) | |
tree | 2e5c0f4cda85b2afdb6142145fa7ded61d100f02 /src/ssa | |
parent | 1b68fdcf5aebf2bc53bbd9234c77aea243c0decd (diff) |
Add assignment, while, extern, function signature type, start on bytecode
Diffstat (limited to 'src/ssa')
-rw-r--r-- | src/ssa/ssa.c | 233 |
1 files changed, 185 insertions, 48 deletions
diff --git a/src/ssa/ssa.c b/src/ssa/ssa.c index c4ed0d3..91ba185 100644 --- a/src/ssa/ssa.c +++ b/src/ssa/ssa.c @@ -4,6 +4,7 @@ #include "../../include/std/hash.h" #include "../../include/std/thread.h" #include "../../include/ast.h" +#include "../../include/compiler.h" #include <assert.h> #define throw(result) do { longjmp(context->env, (result)); } while(0) @@ -59,7 +60,7 @@ int ssa_init(Ssa *self, ScopedAllocator *allocator) { return 0; } -int ssa_get_unique_reg(Ssa *self, SsaRegister *result) { +static CHECK_RESULT int ssa_get_unique_reg(Ssa *self, SsaRegister *result) { /* Overflow */ if(self->reg_counter + 1 < self->reg_counter) return -1; @@ -144,12 +145,13 @@ static CHECK_RESULT int ssa_add_ins_form1(Ssa *self, SsaInstruction ins_type, Ss } static const char* binop_type_to_string(SsaInstruction binop_type) { - assert(binop_type >= SSA_ADD && binop_type <= SSA_DIV); + assert(binop_type >= SSA_ADD && binop_type <= SSA_EQUALS); switch(binop_type) { case SSA_ADD: return "+"; case SSA_SUB: return "-"; case SSA_MUL: return "*"; case SSA_DIV: return "/"; + case SSA_EQUALS: return "=="; default: return ""; } } @@ -173,31 +175,31 @@ static CHECK_RESULT int ssa_add_ins_form2(Ssa *self, SsaInstruction ins_type, Ss return 0; } -int ssa_ins_assign_inter(Ssa *self, SsaRegister dest, SsaNumber number) { +static CHECK_RESULT int ssa_ins_assign_inter(Ssa *self, SsaRegister dest, SsaNumber number) { SsaIntermediateIndex index; return_if_error(ssa_try_add_intermediate(self, number, &index)); amal_log_debug("r%u = i%u", dest, index); return ssa_add_ins_form1(self, SSA_ASSIGN_INTER, dest, index); } -int ssa_ins_assign_string(Ssa *self, SsaRegister dest, BufferView str) { +static CHECK_RESULT int ssa_ins_assign_string(Ssa *self, SsaRegister dest, BufferView str) { SsaStringIndex index; return_if_error(ssa_try_add_string(self, str, &index)); amal_log_debug("r%u = s%u", dest, index); return ssa_add_ins_form1(self, SSA_ASSIGN_STRING, dest, index); } -int ssa_ins_assign_reg(Ssa *self, SsaRegister dest, SsaRegister src) { +static CHECK_RESULT int ssa_ins_assign_reg(Ssa *self, SsaRegister dest, SsaRegister src) { amal_log_debug("r%u = r%u", dest, src); return ssa_add_ins_form1(self, SSA_ASSIGN_REG, dest, src); } -int ssa_ins_binop(Ssa *self, SsaInstruction binop_type, SsaRegister lhs, SsaRegister rhs, SsaRegister *result) { - assert(binop_type >= SSA_ADD && binop_type <= SSA_DIV); +static CHECK_RESULT int ssa_ins_binop(Ssa *self, SsaInstruction binop_type, SsaRegister lhs, SsaRegister rhs, SsaRegister *result) { + assert(binop_type >= SSA_ADD && binop_type <= SSA_EQUALS); return ssa_add_ins_form2(self, binop_type, lhs, rhs, result); } -int ssa_ins_func_start(Ssa *self, u8 num_args, SsaFuncIndex *result) { +static CHECK_RESULT int ssa_ins_func_start(Ssa *self, u8 num_args, SsaFuncIndex *result) { usize index; index = self->instructions.size; @@ -214,14 +216,14 @@ int ssa_ins_func_start(Ssa *self, u8 num_args, SsaFuncIndex *result) { return 0; } -int ssa_ins_func_end(Ssa *self) { +static CHECK_RESULT int ssa_ins_func_end(Ssa *self) { u8 ins; ins = SSA_FUNC_END; amal_log_debug("FUNC_END"); return buffer_append(&self->instructions, &ins, 1); } -int ssa_ins_push(Ssa *self, SsaRegister reg) { +static CHECK_RESULT int ssa_ins_push(Ssa *self, SsaRegister reg) { usize index; index = self->instructions.size; @@ -232,7 +234,7 @@ int ssa_ins_push(Ssa *self, SsaRegister reg) { return 0; } -int ssa_ins_call(Ssa *self, FunctionDecl *func_decl, SsaRegister *result) { +static CHECK_RESULT int ssa_ins_call(Ssa *self, FunctionDecl *func_decl, SsaRegister *result) { usize index; index = self->instructions.size; @@ -249,31 +251,88 @@ int ssa_ins_call(Ssa *self, FunctionDecl *func_decl, SsaRegister *result) { return 0; } +static CHECK_RESULT int ssa_ins_jumpzero(Ssa *self, SsaRegister condition_reg, JumpOffset jump_offset) { + usize index; + index = self->instructions.size; + + return_if_error(buffer_append_empty(&self->instructions, sizeof(u8) + sizeof(SsaRegister) + sizeof(JumpOffset))); + self->instructions.data[index + 0] = SSA_JUMP_ZERO; + am_memcpy(self->instructions.data + index + 1, &condition_reg, sizeof(SsaRegister)); + am_memcpy(self->instructions.data + index + 1 + sizeof(SsaRegister), &jump_offset, sizeof(JumpOffset)); + if(jump_offset == 0) + amal_log_debug("JUMP_ZERO r%u, DUMMY", condition_reg); + else + amal_log_debug("JUMP_ZERO r%u, %d", condition_reg, jump_offset); + return 0; +} + +static CHECK_RESULT int ssa_ins_jump(Ssa *self, JumpOffset jump_offset) { + usize index; + index = self->instructions.size; + + return_if_error(buffer_append_empty(&self->instructions, sizeof(u8) + sizeof(JumpOffset))); + self->instructions.data[index + 0] = SSA_JUMP; + am_memcpy(self->instructions.data + index + 1, &jump_offset, sizeof(JumpOffset)); + amal_log_debug("JUMP %d", jump_offset); + return 0; +} + +static usize ssa_ins_get_index(Ssa *self) { + return self->instructions.size; +} + +/* Set target of jump instruction to current location */ +static CHECK_RESULT int ssa_ins_jump_set_target(Ssa *self, usize jump_ins_index) { + 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 + sizeof(SsaRegister), &jump_offset, sizeof(JumpOffset)); + break; + } + default: + assert(bool_false && "Unexpected error... jump_ins_index doesn't point to a valid index to a jump instruction"); + break; + } + return 0; +} + static CHECK_RESULT SsaRegister ast_generate_ssa(Ast *self, SsaCompilerContext *context); static CHECK_RESULT SsaRegister number_generate_ssa(Number *self, SsaCompilerContext *context) { SsaRegister reg; SsaNumber number; - if(self->is_integer) { + if(self->is_integer) number = create_ssa_integer(self->value.integer); - throw_if_error(ssa_get_unique_reg(context->ssa, ®)); - throw_if_error(ssa_ins_assign_inter(context->ssa, reg, number)); - } else { + else number = create_ssa_float(self->value.floating); - throw_if_error(ssa_get_unique_reg(context->ssa, ®)); - throw_if_error(ssa_ins_assign_inter(context->ssa, reg, number)); - } + throw_if_error(ssa_get_unique_reg(context->ssa, ®)); + throw_if_error(ssa_ins_assign_inter(context->ssa, reg, number)); return reg; } +static CHECK_RESULT SsaRegister lhsexpr_extern_generate_ssa(LhsExpr *self, SsaCompilerContext *context) { + /* TODO: SsaRegister should be extended to include static and extern data */ + (void)self; + (void)context; + amal_log_error("TODO: Implement lhsexpr_extern_generate_ssa"); + return 0; +} + static CHECK_RESULT SsaRegister lhsexpr_generate_ssa(Ast *self, SsaCompilerContext *context) { - /* TODO: Implement */ LhsExpr *lhs_expr; SsaRegister reg; assert(self->type == AST_LHS); lhs_expr = self->value.lhs_expr; + if(lhs_expr->is_extern) + return lhsexpr_extern_generate_ssa(lhs_expr, context); + if(lhs_expr->rhs_expr) { SsaRegister rhs_reg; rhs_reg = ast_generate_ssa(lhs_expr->rhs_expr, context); @@ -283,8 +342,10 @@ static CHECK_RESULT SsaRegister lhsexpr_generate_ssa(Ast *self, SsaCompilerConte 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(self->resolve_data.type == lhs_expr || lhs_expr->rhs_expr->type == AST_IMPORT) + if(self->resolve_data.type == lhs_expr || lhs_expr->rhs_expr->type == AST_IMPORT) { + /*assert(bool_false);*/ return 0; + } throw_if_error(ssa_get_unique_reg(context->ssa, ®)); if(reg == rhs_reg) { amal_log_error("rhs_expr is same as reg.. rhs type: %d", lhs_expr->rhs_expr->type); @@ -292,12 +353,33 @@ static CHECK_RESULT SsaRegister lhsexpr_generate_ssa(Ast *self, SsaCompilerConte assert(reg != rhs_reg); throw_if_error(ssa_ins_assign_reg(context->ssa, reg, rhs_reg)); } else { - /* TODO: assign default value to reg depending on LhsExpr type */ - reg = 0; + /* TODO: Do not assign if we dont want default value */ + SsaNumber number; + if(self->resolve_data.type == context->compiler->default_types.i64) + number = create_ssa_integer(0); + else if(self->resolve_data.type == context->compiler->default_types.f64) + number = create_ssa_float(0.0); + else + assert(bool_false && "TODO: assign default value to reg depending on LhsExpr type"); + throw_if_error(ssa_get_unique_reg(context->ssa, ®)); + throw_if_error(ssa_ins_assign_inter(context->ssa, reg, number)); } return reg; } +static CHECK_RESULT SsaRegister assignmentexpr_generate_ssa(Ast *ast, SsaCompilerContext *context) { + AssignmentExpr *self; + SsaRegister lhs_reg, rhs_reg; + + assert(ast->type == AST_ASSIGN); + self = ast->value.assign_expr; + + lhs_reg = ast_generate_ssa(self->lhs_expr, context); + rhs_reg = ast_generate_ssa(self->rhs_expr, context); + throw_if_error(ssa_ins_assign_reg(context->ssa, lhs_reg, rhs_reg)); + return lhs_reg; +} + /* TODO: Each function declaration should be in separate SSA instances so ast can be converted into ssa in any order. @@ -314,6 +396,7 @@ static CHECK_RESULT SsaRegister funcdecl_generate_ssa(FunctionDecl *self, SsaCom throw_if_error(ssa_ins_func_end(context->ssa)); context->ssa->reg_counter = prev_reg_counter; + /*assert(bool_false);*/ return 0; } @@ -348,12 +431,14 @@ static CHECK_RESULT SsaRegister funccall_generate_ssa(Ast *self, SsaCompilerCont static CHECK_RESULT SsaRegister structdecl_generate_ssa(StructDecl *self, SsaCompilerContext *context) { /* TODO: Implement */ + /*assert(bool_false);*/ scope_generate_ssa(&self->body, context); return 0; } static CHECK_RESULT SsaRegister structfield_generate_ssa(StructField *self, SsaCompilerContext *context) { /* TODO: Implement */ + /*assert(bool_false);*/ (void)self; (void)context; return 0; @@ -367,10 +452,10 @@ static CHECK_RESULT SsaRegister string_generate_ssa(String *self, SsaCompilerCon } static CHECK_RESULT SsaRegister variable_generate_ssa(Variable *self, SsaCompilerContext *context) { - /* TODO: Implement, and with cross field references */ - (void)self; - (void)context; - return 0; + /* TODO: If resolved_var refers to a variable in another file, use a cross file reference that requires no locking (not yet implemented) */ + /* This is not thread-safe:*/ + assert(self->resolved_var); + return ast_generate_ssa(self->resolved_var, context); } static SsaInstruction binop_type_to_ssa_type(BinopType binop_type) { @@ -386,6 +471,8 @@ static SsaInstruction binop_type_to_ssa_type(BinopType binop_type) { case BINOP_DOT: assert(bool_false && "Binop dot not valid for arithmetic operation and requires special functionality"); return 0; + case BINOP_EQUALS: + return SSA_EQUALS; } return 0; } @@ -405,7 +492,57 @@ static CHECK_RESULT SsaRegister binop_generate_ssa(Binop *self, SsaCompilerConte return reg; } -CHECK_RESULT SsaRegister ast_generate_ssa(Ast *self, SsaCompilerContext *context) { +static void else_if_statement_generate_ssa(ElseIfStatement *else_if_stmt, SsaCompilerContext *context) { + usize jump_ins_index; + 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)); + } + 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); +} + +static void if_statement_generate_ssa(IfStatement *if_stmt, SsaCompilerContext *context) { + SsaRegister condition_reg; + usize jump_ins_index; + + condition_reg = ast_generate_ssa(if_stmt->condition, context); + jump_ins_index = ssa_ins_get_index(context->ssa); + throw_if_error(ssa_ins_jumpzero(context->ssa, condition_reg, 0)); + 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); +} + +static void while_statement_generate_ssa(WhileStatement *while_stmt, SsaCompilerContext *context) { + SsaRegister condition_reg; + usize jump_back_ins_index; + usize jump_condition_ins_index; + isize jump_offset; + + jump_back_ins_index = ssa_ins_get_index(context->ssa); + condition_reg = ast_generate_ssa(while_stmt->condition, context); + jump_condition_ins_index = ssa_ins_get_index(context->ssa); + throw_if_error(ssa_ins_jumpzero(context->ssa, condition_reg, 0)); + 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)); +} + +static CHECK_RESULT SsaRegister ast_generate_ssa(Ast *self, SsaCompilerContext *context) { assert(self); #ifdef DEBUG if(self->resolve_data.status != AST_RESOLVED && self->resolve_data.status != AST_SSA_RESOLVED) { @@ -420,48 +557,48 @@ CHECK_RESULT SsaRegister ast_generate_ssa(Ast *self, SsaCompilerContext *context switch(self->type) { case AST_NUMBER: self->ssa_reg = number_generate_ssa(self->value.number, context); - self->resolve_data.status = AST_SSA_RESOLVED; - return self->ssa_reg; + break; case AST_FUNCTION_DECL: self->ssa_reg = funcdecl_generate_ssa(self->value.func_decl, context); - self->resolve_data.status = AST_SSA_RESOLVED; - return self->ssa_reg; + break; case AST_FUNCTION_CALL: self->ssa_reg = funccall_generate_ssa(self, context); - self->resolve_data.status = AST_SSA_RESOLVED; - return self->ssa_reg; + break; case AST_STRUCT_DECL: self->ssa_reg = structdecl_generate_ssa(self->value.struct_decl, context); - self->resolve_data.status = AST_SSA_RESOLVED; - return self->ssa_reg; + break; case AST_STRUCT_FIELD: self->ssa_reg = structfield_generate_ssa(self->value.struct_field, context); - self->resolve_data.status = AST_SSA_RESOLVED; - return self->ssa_reg; + break; case AST_LHS: self->ssa_reg = lhsexpr_generate_ssa(self, context); - self->resolve_data.status = AST_SSA_RESOLVED; - return self->ssa_reg; + break; + case AST_ASSIGN: + self->ssa_reg = assignmentexpr_generate_ssa(self, context); + break; case AST_IMPORT: /* TODO: Implement cross file references */ self->ssa_reg = 0; - self->resolve_data.status = AST_SSA_RESOLVED; - return self->ssa_reg; + break; case AST_STRING: self->ssa_reg = string_generate_ssa(self->value.string, context); - self->resolve_data.status = AST_SSA_RESOLVED; - return self->ssa_reg; + break; case AST_VARIABLE: self->ssa_reg = variable_generate_ssa(self->value.variable, context); - self->resolve_data.status = AST_SSA_RESOLVED; - return self->ssa_reg; + break; case AST_BINOP: self->ssa_reg = binop_generate_ssa(self->value.binop, context); - self->resolve_data.status = AST_SSA_RESOLVED; - return self->ssa_reg; + break; + case AST_IF_STATEMENT: + if_statement_generate_ssa(self->value.if_stmt, context); + break; + case AST_WHILE_STATEMENT: + while_statement_generate_ssa(self->value.while_stmt, context); + break; } - return 0; + self->resolve_data.status = AST_SSA_RESOLVED; + return self->ssa_reg; } void scope_generate_ssa(Scope *self, SsaCompilerContext *context) { |