+/*
+ ___ _____ ____ ____ ___ _____ ____ _
+ |_ _| ___/ ___| | _ \ / _ \_ _| | _ \ _ _ _ __ ___ _ __ (_)_ __ __ _
+ | || |_ | | _ | | | | | | || | | | | | | | | '_ ` _ \| '_ \| | '_ \ / _` |
+ | || _|| |_| | | |_| | |_| || | | |_| | |_| | | | | | | |_) | | | | | (_| |
+ |___|_| \____| |____/ \___/ |_| |____/ \__,_|_| |_| |_| .__/|_|_| |_|\__, |
+ |_| |___/
+*/
+
+static const char *get_dot_color_name(int col)
+{
+ static const char *names[] = {
+ "blue",
+ "red",
+ "green",
+ "yellow",
+ "cyan",
+ "magenta",
+ "orange",
+ "chocolate",
+ "beige",
+ "navy",
+ "darkgreen",
+ "darkred",
+ "lightPink",
+ "chartreuse",
+ "lightskyblue",
+ "linen",
+ "pink",
+ "lightslateblue",
+ "mintcream",
+ "red",
+ "darkolivegreen",
+ "mediumblue",
+ "mistyrose",
+ "salmon",
+ "darkseagreen",
+ "mediumslateblue"
+ "moccasin",
+ "tomato",
+ "forestgreen",
+ "darkturquoise",
+ "palevioletred"
+ };
+
+ return col < sizeof(names)/sizeof(names[0]) ? names[col] : "white";
+}
+
+typedef struct _co_ifg_dump_t {
+ const copy_opt_t *co;
+ unsigned flags;
+} co_ifg_dump_t;
+
+static void ifg_dump_graph_attr(FILE *f, void *self)
+{
+ fprintf(f, "overlap=scale");
+}
+
+static int ifg_is_dump_node(void *self, ir_node *irn)
+{
+ co_ifg_dump_t *cod = self;
+ return !arch_irn_is(cod->co->aenv, irn, ignore);
+}
+
+static void ifg_dump_node_attr(FILE *f, void *self, ir_node *irn)
+{
+ co_ifg_dump_t *env = self;
+ const arch_register_t *reg = arch_get_irn_register(env->co->aenv, irn);
+ arch_register_req_t req;
+ int limited;
+
+ arch_get_register_req(env->co->aenv, &req, irn, BE_OUT_POS(0));
+ limited = arch_register_req_is(&req, limited);
+
+ if(env->flags & CO_IFG_DUMP_LABELS) {
+ ir_fprintf(f, "label=\"%+F", irn);
+
+ if((env->flags & CO_IFG_DUMP_CONSTR) && limited) {
+ bitset_t *bs = bitset_alloca(env->co->cls->n_regs);
+ req.limited(req.limited_env, bs);
+ ir_fprintf(f, "\\n%B", bs);
+ }
+ ir_fprintf(f, "\" ");
+ }
+
+ else
+ fprintf(f, "label=\"\" shape=point " );
+
+ if(env->flags & CO_IFG_DUMP_SHAPE)
+ fprintf(f, "shape=%s ", limited ? "diamond" : "ellipse");
+
+ if(env->flags & CO_IFG_DUMP_COLORS)
+ fprintf(f, "style=filled color=%s ", get_dot_color_name(reg->index));
+}
+
+static void ifg_dump_at_end(FILE *file, void *self)
+{
+ co_ifg_dump_t *env = self;
+ affinity_node_t *a;
+
+ co_gs_foreach_aff_node(env->co, a) {
+ const arch_register_t *ar = arch_get_irn_register(env->co->aenv, a->irn);
+ unsigned aidx = get_irn_idx(a->irn);
+ neighb_t *n;
+
+ co_gs_foreach_neighb(a, n) {
+ const arch_register_t *nr = arch_get_irn_register(env->co->aenv, n->irn);
+ unsigned nidx = get_irn_idx(n->irn);
+
+ if(aidx < nidx) {
+ const char *color = nr == ar ? "blue" : "red";
+ fprintf(file, "\tn%d -- n%d [weight=0.01 ", aidx, nidx);
+ if(env->flags & CO_IFG_DUMP_LABELS)
+ fprintf(file, "label=\"%d\" ", n->costs);
+ if(env->flags & CO_IFG_DUMP_COLORS)
+ fprintf(file, "color=%s ", color);
+ else
+ fprintf(file, "style=dashed");
+ fprintf(file, "];\n");
+ }
+ }
+ }
+}
+
+
+static be_ifg_dump_dot_cb_t ifg_dot_cb = {
+ ifg_is_dump_node,
+ ifg_dump_graph_attr,
+ ifg_dump_node_attr,
+ NULL,
+ NULL,
+ ifg_dump_at_end
+};
+
+
+
+void co_dump_ifg_dot(const copy_opt_t *co, FILE *f, unsigned flags)
+{
+ co_ifg_dump_t cod;
+
+ cod.co = co;
+ cod.flags = flags;
+ be_ifg_dump_dot(co->cenv->ifg, co->irg, f, &ifg_dot_cb, &cod);
+}
+