aboutsummaryrefslogtreecommitdiff
path: root/src/ssa/proc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ssa/proc.cpp')
-rw-r--r--src/ssa/proc.cpp124
1 files changed, 124 insertions, 0 deletions
diff --git a/src/ssa/proc.cpp b/src/ssa/proc.cpp
new file mode 100644
index 000000000..6d9c75b5d
--- /dev/null
+++ b/src/ssa/proc.cpp
@@ -0,0 +1,124 @@
+void ssa_begin_procedure_body(ssaProcedure *proc) {
+ array_init(&proc->blocks, heap_allocator());
+ array_init(&proc->defer_stmts, heap_allocator());
+ array_init(&proc->children, heap_allocator());
+
+ proc->decl_block = ssa_add_block(proc, proc->type_expr, "decls");
+ proc->entry_block = ssa_add_block(proc, proc->type_expr, "entry");
+ proc->curr_block = proc->entry_block;
+
+ if (proc->type->Proc.params != NULL) {
+ auto *params = &proc->type->Proc.params->Tuple;
+ for (isize i = 0; i < params->variable_count; i++) {
+ Entity *e = params->variables[i];
+ ssa_add_param(proc, e);
+ }
+ }
+}
+
+
+void ssa_end_procedure_body(ssaProcedure *proc) {
+ if (proc->type->Proc.result_count == 0) {
+ ssa_emit_return(proc, NULL);
+ }
+
+ if (proc->curr_block->instrs.count == 0) {
+ ssa_emit_unreachable(proc);
+ }
+
+ proc->curr_block = proc->decl_block;
+ ssa_emit_jump(proc, proc->entry_block);
+
+#if 0
+ ssa_optimize_blocks(proc);
+ ssa_build_referrers(proc);
+ ssa_build_dom_tree(proc);
+
+ // TODO(bill): mem2reg optimization
+ // [ ] Local never loaded? Eliminate
+ // [ ] Local never stored? Replace all loads with `Nil`
+ // [ ] Local stored once? Replace loads with dominating store
+ // [ ] Convert to phi nodes
+ ssa_opt_mem2reg(proc);
+#endif
+
+// Number registers
+ i32 reg_index = 0;
+ for_array(i, proc->blocks) {
+ ssaBlock *b = proc->blocks[i];
+ b->index = i;
+ for_array(j, b->instrs) {
+ ssaValue *value = b->instrs[j];
+ GB_ASSERT(value->kind == ssaValue_Instr);
+ ssaInstr *instr = &value->Instr;
+ if (ssa_instr_type(instr) == NULL) { // NOTE(bill): Ignore non-returning instructions
+ continue;
+ }
+ value->index = reg_index;
+ reg_index++;
+ }
+ }
+}
+
+
+void ssa_insert_code_before_proc(ssaProcedure* proc, ssaProcedure *parent) {
+ if (parent == NULL) {
+ if (proc->name == "main") {
+ ssa_emit_startup_runtime(proc);
+ }
+ }
+}
+
+void ssa_build_proc(ssaValue *value, ssaProcedure *parent) {
+ ssaProcedure *proc = &value->Proc;
+
+ proc->parent = parent;
+
+ if (proc->entity != NULL) {
+ ssaModule *m = proc->module;
+ CheckerInfo *info = m->info;
+ Entity *e = proc->entity;
+ String filename = e->token.pos.file;
+ AstFile **found = map_get(&info->files, hash_string(filename));
+ GB_ASSERT(found != NULL);
+ AstFile *f = *found;
+ ssaDebugInfo *di_file = NULL;
+
+ ssaDebugInfo **di_file_found = map_get(&m->debug_info, hash_pointer(f));
+ if (di_file_found) {
+ di_file = *di_file_found;
+ GB_ASSERT(di_file->kind == ssaDebugInfo_File);
+ } else {
+ di_file = ssa_add_debug_info_file(proc, f);
+ }
+
+ ssa_add_debug_info_proc(proc, e, proc->name, di_file);
+ }
+
+ if (proc->body != NULL) {
+ u32 prev_stmt_state_flags = proc->module->stmt_state_flags;
+ defer (proc->module->stmt_state_flags = prev_stmt_state_flags);
+
+ if (proc->tags != 0) {
+ u32 in = proc->tags;
+ u32 out = proc->module->stmt_state_flags;
+ defer (proc->module->stmt_state_flags = out);
+
+ if (in & ProcTag_bounds_check) {
+ out |= StmtStateFlag_bounds_check;
+ out &= ~StmtStateFlag_no_bounds_check;
+ } else if (in & ProcTag_no_bounds_check) {
+ out |= StmtStateFlag_no_bounds_check;
+ out &= ~StmtStateFlag_bounds_check;
+ }
+ }
+
+
+ ssa_begin_procedure_body(proc);
+ ssa_insert_code_before_proc(proc, parent);
+ ssa_build_stmt(proc, proc->body);
+ ssa_end_procedure_body(proc);
+ }
+}
+
+