diff options
Diffstat (limited to 'src/ssa')
-rw-r--r-- | src/ssa/ssa.c | 87 |
1 files changed, 60 insertions, 27 deletions
diff --git a/src/ssa/ssa.c b/src/ssa/ssa.c index 500555a..940f636 100644 --- a/src/ssa/ssa.c +++ b/src/ssa/ssa.c @@ -61,9 +61,11 @@ int ssa_init(Ssa *self, Parser *parser) { return_if_error(buffer_init(&self->strings, parser->allocator)); return_if_error(hash_map_init(&self->extern_funcs_map, parser->allocator, sizeof(SsaExternFuncIndex), hash_map_compare_string, amal_hash_string)); return_if_error(buffer_init(&self->extern_funcs, parser->allocator)); + return_if_error(buffer_init(&self->export_funcs, parser->allocator)); self->intermediate_counter = 0; self->string_counter = 0; self->extern_func_counter = 0; + self->export_func_counter = 0; self->reg_counter = 0; self->param_counter = 0; self->func_counter = 0; @@ -192,6 +194,29 @@ static CHECK_RESULT int ssa_try_add_extern_func(Ssa *self, FunctionSignature *fu } } +/* + Exported functions with the same name are allowed to exist in different files, but not in the same file. + There is no need to check if there are two exported functions with the same name in the same file + as that is already checked in the AST stage, as you are not allowed to have multiple variables of the same name in the same scope, + exported or not. +*/ +static CHECK_RESULT int ssa_try_add_export_func(Ssa *self, FunctionSignature *func_sig, BufferView name) { + /* Overflow */ + if(self->export_func_counter + 1 <= self->export_func_counter) { + amal_log_error("Ssa too many exported closures!"); + return -1; + } + + amal_log_debug("ef%u = \"%.*s\"", self->export_func_counter, name.size, name.data); + ++self->export_func_counter; + { + SsaExportFunc export_func; + export_func.func_sig = func_sig; + export_func.name = name; + return buffer_append(&self->export_funcs, &export_func, sizeof(export_func)); + } +} + static CHECK_RESULT int ssa_add_ins_form1(Ssa *self, SsaInstruction ins_type, SsaRegister lhs, u16 rhs) { SsaInsForm1 ins_form_1; ins_form_1.lhs = lhs; @@ -247,7 +272,7 @@ static CHECK_RESULT int ssa_ins_binop(Ssa *self, SsaInstruction binop_type, SsaR return ssa_add_ins_form2(self, binop_type, lhs, rhs, result); } -static CHECK_RESULT int ssa_ins_func_start(Ssa *self, SsaRegister num_reg_params, SsaFuncIndex *result, usize *func_metadata_index) { +static CHECK_RESULT int ssa_ins_func_start(Ssa *self, u8 func_flags, SsaFuncIndex *result, usize *func_metadata_index) { const u8 ins_type = SSA_FUNC_START; SsaInsFuncStart ins_func_start; @@ -258,14 +283,13 @@ static CHECK_RESULT int ssa_ins_func_start(Ssa *self, SsaRegister num_reg_params } *result = self->func_counter++; - ins_func_start.func_index = *result; - ins_func_start.num_params_regs = num_reg_params; + ins_func_start.flags = func_flags; /* Dont set number of local registers yet. That will be set by @func_metadata_index later when it's known */ /*ins_func_start.num_local_vars_regs = ---*/ return_if_error(buffer_append(&self->instructions, &ins_type, 1)); return_if_error(buffer_append(&self->instructions, &ins_func_start, sizeof(ins_func_start))); *func_metadata_index = self->instructions.size - sizeof(ins_func_start.num_local_vars_regs); - amal_log_debug("FUNC_START f%u, %d", *result, num_reg_params); + amal_log_debug("FUNC_START f%u", *result); return 0; } @@ -428,6 +452,16 @@ static CHECK_RESULT SsaRegister lhsexpr_extern_generate_ssa(LhsExpr *self, SsaCo return 0; } +static CHECK_RESULT SsaRegister lhsexpr_export_generate_ssa(LhsExpr *self, SsaCompilerContext *context) { + /* TODO: SsaRegister should be extended to include static and export data */ + if(self->rhs_expr->type == AST_FUNCTION_DECL) { + throw_if_error(ssa_try_add_export_func(context->ssa, self->rhs_expr->value.func_decl->signature, self->var_name)); + } else { + assert(bool_false && "TODO: Implement lhsexpr_export_generate_ssa for other data than functions"); + } + return 0; +} + static CHECK_RESULT SsaRegister lhsexpr_generate_ssa(LhsExpr *self, AstResolveData *resolve_data, SsaCompilerContext *context) { SsaRegister reg; @@ -438,6 +472,10 @@ static CHECK_RESULT SsaRegister lhsexpr_generate_ssa(LhsExpr *self, AstResolveDa Ast *rhs_expr = self->rhs_expr; SsaRegister rhs_reg; rhs_reg = ast_generate_ssa(rhs_expr, context); + + if(LHS_EXPR_IS_EXPORT(self)) + return lhsexpr_export_generate_ssa(self, context); + /* Declarations (struct and function declaration) resolves to itself and in that case this expression is just a compile-time name for the declaration. @@ -513,15 +551,13 @@ in any order. static CHECK_RESULT SsaRegister funcdecl_generate_ssa(FunctionDecl *self, SsaCompilerContext *context) { /* TODO: Implement */ /* - Reset reg counter in each function, because each function has a separate register context - that is reset after function end + Reset reg counter in each function, because each function has a separate register context + that is reset after function end */ - SsaRegister prev_reg_counter; - SsaRegister prev_param_counter; usize func_metadata_index; - - prev_reg_counter = context->ssa->reg_counter; - prev_param_counter = context->ssa->param_counter; + 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; /* @@ -533,7 +569,12 @@ static CHECK_RESULT SsaRegister funcdecl_generate_ssa(FunctionDecl *self, SsaCom context->ssa->reg_counter = 0; amal_log_debug("SSA funcdecl %p", self); - throw_if_error(ssa_ins_func_start(context->ssa, context->ssa->param_counter, &self->ssa_func_index, &func_metadata_index)); + /* Anonymous closure doesn't have lhs_expr, and neither can it have any flags (extern, export etc) */ + if(self->lhs_expr) { + if(LHS_EXPR_IS_EXPORT(self->lhs_expr)) + func_flags |= FUNC_FLAG_EXPORTED; + } + throw_if_error(ssa_ins_func_start(context->ssa, func_flags, &self->ssa_func_index, &func_metadata_index)); scope_generate_ssa(&self->body, context); throw_if_error(ssa_ins_func_end(context->ssa)); @@ -585,7 +626,7 @@ static CHECK_RESULT SsaRegister structdecl_generate_ssa(StructDecl *self, SsaCom static CHECK_RESULT SsaRegister structfield_generate_ssa(StructField *self, SsaCompilerContext *context) { /* TODO: Implement */ - /*assert(bool_false);*/ + assert(bool_false); (void)self; (void)context; return 0; @@ -644,8 +685,7 @@ static CHECK_RESULT SsaRegister binop_generate_ssa(Binop *self, SsaCompilerConte } static void else_if_statement_generate_ssa(ElseIfStatement *else_if_stmt, SsaCompilerContext *context) { - usize jump_ins_index; - jump_ins_index = 0; + usize jump_ins_index = 0; if(else_if_stmt->condition) { SsaRegister condition_reg; condition_reg = ast_generate_ssa(else_if_stmt->condition, context); @@ -660,11 +700,8 @@ static void else_if_statement_generate_ssa(ElseIfStatement *else_if_stmt, SsaCom } 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); + 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)); scope_generate_ssa(&if_stmt->body, context); throw_if_error(ssa_ins_jump_set_target(context->ssa, jump_ins_index)); @@ -673,14 +710,10 @@ static void if_statement_generate_ssa(IfStatement *if_stmt, SsaCompilerContext * } 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); + usize jump_back_ins_index = ssa_ins_get_index(context->ssa); + 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)); scope_generate_ssa(&while_stmt->body, context); /* Jump back and check condition again before running the content of the loop again */ |