static void gen_fn(CTX *ctx, struct ir_function *fn, char *name, bool visible) { assert(!ctx->writing_types); if (!fn->parent) fn_complete_nested_calls(fn); for (int n = 0; n < fn->nested_functions_count; n++) { struct ir_function *nfn = fn->nested_functions[n]; ctx->writing_types = true; char *nname = def_nested_fn(ctx, nfn); ctx->writing_types = false; gen_fn(ctx, nfn, nname, false); } fn_remove_global_ssa(fn); fn_verify(fn); //dump_fn(stderr, fn); for (int b = 0; b < fn->blocks_count; b++) { for (struct ir_inst *in = fn->blocks[b]->first; in; in = in->next) in->scratch1_i = -1; } // add all C types and function declarations needed for this function ctx->writing_types = true; do_fn_types(ctx, fn->type); for (int n = 0; n < fn->vars_count; n++) def_type(ctx, fn->vars[n]->type); for (int b = 0; b < fn->blocks_count; b++) { struct ir_bb *bb = fn->blocks[b]; for (struct ir_inst *in = bb->first; in; in = in->next) { def_type(ctx, in->result_type); if (in->op == IR_OP_CALL || in->op == IR_OP_FN_PTR) { def_fn(ctx, in->fn); } } } ctx->writing_types = false; set_loc(ctx, fn->loc); if (!visible) fprintf(ctx->f, "static "); write_fn_type(ctx, fn->type, false, name); wf(ctx, " {"); indent_in(ctx); for (int n = 0; n < fn->vars_count; n++) { struct ir_var *v = fn->vars[n]; set_loc(ctx, v->loc); indent(ctx); P(ctx, "%s V%d", type(ctx, v->type), n); // void values are never assigned to (to avoid clashes with C's void); // since they have only one value, there's no need to. Initialize them // to avoid C warnings, though. if (type_is_void(v->type)) P(ctx, " = {0}"); P(ctx, ";\n"); } indent(ctx); P(ctx, "goto B%d;\n", fn->entry->index); for (int b = 0; b < fn->blocks_count; b++) { struct ir_bb *bb = fn->blocks[b]; indent(ctx); P(ctx, "B%d: {\n", b); indent_in(ctx); ctx->reg = 0; for (struct ir_inst *in = bb->first; in; in = in->next) gen_inst(ctx, in); indent_out(ctx); wf(ctx, "}"); } indent_out(ctx); wf(ctx, "}"); }
/* gen_main -- generate the main program */ static void gen_main(void) { int i; char buf[128]; if (known("MAIN")) return; err_file = (char *) "main program"; /* For completeness, generate a header listing all loaded modules. */ gen_inst("MODULE %%Main 0 0"); for (i = 0; i < nmodules; i++) { if (strcmp(module[i].m_name, "_Builtin") == 0 || !module[i].m_needed) continue; gen_inst("IMPORT %s %#x", module[i].m_name, module[i].m_check); } gen_inst("ENDHDR"); gen_inst("PROC MAIN 0 4 0"); /* Code to call each module body */ for (i = 0; i < nmodules; i++) { if (!module[i].m_needed) continue; sprintf(buf, "%s.%%main", module[i].m_name); if (known(buf)) { gen_inst("CONST %s", buf); gen_inst("CALL 0"); } } gen_inst("RETURN"); gen_inst("END"); /* Make global pointer map */ gen_inst("DEFINE GCMAP"); for (i = 0; i < nmodules; i++) { if (!module[i].m_needed) continue; sprintf(buf, "%s.%%gcmap", module[i].m_name); if (known(buf)) { gen_inst("WORD GC_MAP"); gen_inst("WORD %s", buf); } } gen_inst("WORD GC_END"); }