static void write_fn_type(CTX *ctx, struct ir_fn_type *fnt, bool as_ptr, char *name) { fprintf(ctx->f, "%s ", ret_type(ctx, fnt->ret_type)); if (as_ptr) { fprintf(ctx->f, "(*%s)", name); } else { fprintf(ctx->f, "%s", name); } fprintf(ctx->f, "("); for (int n = 0; n < fnt->args->members_count; n++) { struct ir_struct_member *m = fnt->args->members[n]; if (n > 0) fprintf(ctx->f, ", "); P(ctx, "%s A%d", def_type(ctx, m->type), n); } if (fnt->vararg == IR_VARARG_C) { if (fnt->args->members_count) fprintf(ctx->f, ", "); fprintf(ctx->f, "..."); } else if (fnt->args->members_count == 0) { fprintf(ctx->f, "void"); } fprintf(ctx->f, ")"); }
static char *def_tuple(CTX *ctx, struct ir_struct_type *st, bool add_names) { // NOTE: we use the same C type for empty tuples and compounds; should be ok if (st->members_count == 0) return VOID_MANGLE; char *m = get_mangle(ctx, st); if (m) return m; assert(ctx->writing_types); m = talloc_strdup(ctx, MANGLE_PREFIX "tuple_"); for (int n = 0; n < st->members_count; n++) { struct ir_struct_member *sm = st->members[n]; mangle_append_sub(&m, def_type(ctx, sm->type)); assert(add_names == (sm->name[0])); if (sm->name) m = talloc_asprintf_append_buffer(m, "n%zd_%s_", strlen(sm->name), sm->name); } if (use_anon_mangle_for_tuples) { char *new_mangle = HT_GET_DEF(dstr, dstr, ctx->tuple_abbrev, m, NULL); if (!new_mangle) { new_mangle = gen_anon_mangle(ctx, "tuple"); HT_INSERT(dstr, dstr, ctx->tuple_abbrev, m, new_mangle); } m = new_mangle; } add_mangle(ctx, st, m); if (!check_redef(ctx, m)) write_struct(ctx, st, m); return m; }
static char *def_array_type(CTX *ctx, struct ir_array_type *at) { char *m = get_mangle(ctx, at); if (m) return m; assert(ctx->writing_types); m = talloc_strdup(ctx, MANGLE_PREFIX "arr_"); m = talloc_asprintf_append_buffer(m, "%d_", at->dimension); mangle_append_sub(&m, def_type(ctx, at->item_type)); add_mangle(ctx, at, m); if (!check_redef(ctx, m)) { wf(ctx, "typedef struct %s {", m); indent_in(ctx); wf(ctx, "%s a[%d];", def_type(ctx, at->item_type), at->dimension); indent_out(ctx); wf(ctx, "} %s;", m); } return m; }
static void write_struct(CTX *ctx, struct ir_struct_type *st, char *name) { assert(ctx->writing_types); wf(ctx, "struct %s;", name); wf(ctx, "typedef struct %s %s;", name, name); // Make sure all types are written out first. for (int n = 0; n < st->members_count; n++) { struct ir_struct_member *m = st->members[n]; def_type(ctx, m->type); } set_loc(ctx, st->loc); wf(ctx, "struct %s {", name); indent_in(ctx); for (int n = 0; n < st->members_count; n++) { struct ir_struct_member *m = st->members[n]; struct name_temp t; char *mname = member_name(m, &t); set_loc(ctx, m->loc); wf(ctx, "%s %s;", def_type(ctx, m->type), mname); } indent_out(ctx); wf(ctx, "};"); set_no_loc(ctx); }
static char *def_fn_type(CTX *ctx, struct ir_fn_type *fnt) { char *m = get_mangle(ctx, fnt); if (m) return m; assert(ctx->writing_types); m = talloc_strdup(ctx, MANGLE_PREFIX "fn_"); mangle_append_sub(&m, def_type(ctx, fnt->ret_type)); for (int n = 0; n < fnt->args->members_count; n++) { struct ir_struct_member *sm = fnt->args->members[n]; mangle_append_sub(&m, def_type(ctx, sm->type)); } switch (fnt->vararg) { case IR_VARARG_NONE: break; case IR_VARARG_NATIVE: mangle_append_sub(&m, "vararg"); break; case IR_VARARG_C: mangle_append_sub(&m, "cvararg"); break; default: assert(false); } add_mangle(ctx, fnt, m); fprintf(ctx->f, "typedef "); write_fn_type(ctx, fnt, true, m); fprintf(ctx->f, ";\n"); return m; }
/* return the type of a token */ static int char_type(char *s) { int c = (unsigned char) s[0]; int t; if (isdigit(c)) return T_NUMBER; if (c == '"') return T_STRING; if ((t = def_type(s)) >= 0) return t; if (c == '~' || c == '^') return T_GAP; if (ispunct(c) && (c != '\\' || !s[1])) return T_ORD; return T_LETTER; }
static char *def_ptr(CTX *ctx, struct ir_type *pt) { if (type_is_untyped(*pt)) return VPTR_MANGLE; char *m = get_mangle(ctx, pt); if (m) return m; assert(ctx->writing_types); char *sub = def_type(ctx, *pt); m = talloc_strdup(ctx, MANGLE_PREFIX "p_"); mangle_append_sub(&m, sub); add_mangle(ctx, pt, m); if (!check_redef(ctx, m)) wf(ctx, "typedef %s *%s;", sub, m); return m; }
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, "}"); }
// Define all referenced function types. static void do_fn_types(CTX *ctx, struct ir_fn_type *fnt) { def_type(ctx, fnt->ret_type); for (int n = 0; n < fnt->args->members_count; n++) def_type(ctx, fnt->args->members[n]->type); }
static char *ret_type(CTX *ctx, struct ir_type t) { // for C ABI compatibility return type_is_void(t) ? "void" : def_type(ctx, t); }
static char *type(CTX *ctx, struct ir_type t) { return def_type(ctx, t); }