Esempio n. 1
0
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, "}");
}
Esempio n. 2
0
/* 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");
}