aboutsummaryrefslogtreecommitdiff
path: root/src/ssa/ssa.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ssa/ssa.c')
-rw-r--r--src/ssa/ssa.c87
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 */