diff options
Diffstat (limited to 'src/ssa/proc.cpp')
| -rw-r--r-- | src/ssa/proc.cpp | 124 |
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); + } +} + + |