aboutsummaryrefslogtreecommitdiff
path: root/src/ssa
diff options
context:
space:
mode:
Diffstat (limited to 'src/ssa')
-rw-r--r--src/ssa/ssa.c162
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, &reg, 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) {