Added register requirements transfer function
[libfirm] / ir / be / beraextern.c
1 /**
2  * Author:      Daniel Grund
3  * Date:                17.01.2006
4  * Copyright:   (c) Universitaet Karlsruhe
5  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
6  *
7  * Implementation of the RA-Interface for an external, (non-SSA) register allocator.
8  *
9  * The external register allocator is a program taking 2 arguments:
10  *   1) An input file in which the cfg is defined
11  *   2) An output file containing the essential actions performed during allocation
12  *
13
14
15 The input file format
16 ----------------------
17
18 inputfile       ::= regs nodes interf affinities .
19
20 regs            ::= 'regs' regcount .                                           // Anzahl der register (0..regcount-1), die zur Verfuegung stehen
21
22 nodes           ::= 'nodes' '{' node* '}' .                                     // All nodes in the graph
23
24 interf          ::= 'interferences' '{' edge* '}' .                     // Interference edges of the graph
25
26 affinities      ::= 'affinities' '{' edge* '}' .                        // Affinity edges of the graph
27
28 node            ::= node-nr
29                           | node-nr '<' reg-nr '>' .                            // Reg-nr is present in case of constraints
30
31 edge            ::= '(' node-nr node-nr ')' .
32
33
34 regcount, node-nr ::= integer .
35
36
37 The output file format
38 -----------------------
39
40 outputfile      ::= spills | allocs .
41
42 spills          ::= 'spills' node-nr+ .
43
44 allocs          ::= 'allocs' alloc* .
45
46 alloc           ::= node-nr reg-nr .
47
48
49 ******** End of file format docu ********/
50
51 #ifdef HAVE_CONFIG_H
52 #include "config.h"
53 #endif
54
55 #ifdef WIN32
56 #include <malloc.h>
57 #else
58 #include <alloca.h>
59 #endif
60
61 #include <stdio.h>
62 #include <stdlib.h>
63 #ifdef WITH_LIBCORE
64 #include <libcore/lc_opts.h>
65 #include <libcore/lc_opts_enum.h>
66 #endif
67
68 #include "set.h"
69 #include "pset.h"
70 #include "pmap.h"
71 #include "bitset.h"
72
73 #include "irprintf_t.h"
74 #include "irnode_t.h"
75 #include "irgraph_t.h"
76 #include "irgwalk.h"
77 #include "iredges_t.h"
78 #include "irdom_t.h"
79 #include "phiclass.h"
80
81 #include "beraextern.h"
82 #include "bearch.h"
83 #include "benode_t.h"
84 #include "beirgmod.h"
85 #include "besched.h"
86 #include "beutil.h"
87
88 typedef struct _var_info_t var_info_t;
89
90 /**
91  * Environment with all the needed stuff
92  */
93 typedef struct _be_raext_env_t {
94         arch_env_t *aenv;
95         const arch_register_class_t *cls;
96         ir_graph *irg;
97         dom_front_info_t *dom_info;
98
99         FILE *f;                                /**< file handle used for out- and input file */
100         set *vars;                              /**< contains all var_info_t */
101         int n_cls_vars;                 /**< length of the array cls_vars */
102         var_info_t **cls_vars;  /**< only the var_infos for current cls. needed for double iterating */
103 } be_raext_env_t;
104
105
106
107 /******************************************************************************
108     _    _      _
109    | |  | |    | |
110    | |__| | ___| |_ __   ___ _ __ ___
111    |  __  |/ _ \ | '_ \ / _ \ '__/ __|
112    | |  | |  __/ | |_) |  __/ |  \__ \
113    |_|  |_|\___|_| .__/ \___|_|  |___/
114                  | |
115                  |_|
116  *****************************************************************************/
117
118
119 #define pset_foreach(pset, irn)  for(irn=pset_first(pset); irn; irn=pset_next(pset))
120 #define set_foreach(set, e)  for(e=set_first(set); e; e=set_next(set))
121
122 /**
123  * Checks if _the_ result of the irn belongs to the
124  * current register class (raenv->cls)
125  * NOTE: Only the first result is checked.
126  */
127 #define is_res_in_reg_class(irn) arch_irn_has_reg_class(raenv->aenv, irn, -1, raenv->cls)
128
129 static INLINE ir_node *get_first_non_phi(pset *s) {
130         ir_node *irn;
131
132         pset_foreach(s, irn)
133                 if (!is_Phi(irn)) {
134                         pset_break(s);
135                         return irn;
136                 }
137
138         assert(0 && "There must be a non-phi-irn in this");
139         return NULL;
140 }
141
142 static INLINE ir_node *get_first_phi(pset *s) {
143         ir_node *irn;
144
145         pset_foreach(s, irn)
146                 if (is_Phi(irn)) {
147                         pset_break(s);
148                         return irn;
149                 }
150
151         assert(0 && "There must be a phi in this");
152         return NULL;
153 }
154
155
156 /******************************************************************************
157      _____ _____              _____            _
158     / ____/ ____|  /\        |  __ \          | |
159    | (___| (___   /  \ ______| |  | | ___  ___| |_ _ __
160     \___ \\___ \ / /\ \______| |  | |/ _ \/ __| __| '__|
161     ____) |___) / ____ \     | |__| |  __/\__ \ |_| |
162    |_____/_____/_/    \_\    |_____/ \___||___/\__|_|
163
164  *****************************************************************************/
165
166 #define mark_as_done(irn, pos)                  set_irn_link(irn, INT_TO_PTR(pos+1))
167 #define has_been_done(irn, pos)                 (PTR_TO_INT(get_irn_link(irn)) > pos)
168
169 /**
170  * Insert a copy for the argument of @p start_phi found at position @p pos.
171  * Also searches a phi-loop of arbitrary length to detect and resolve
172  *   the class of phi-swap-problems. To search for a loop recursion is used.
173  *
174  * 1) Simplest case (phi with a non-phi arg):
175  *     A single copy is inserted.
176  *
177  * 2) Phi chain (phi (with phi-arg)* with non=phi arg):
178  *     Several copies are placed, each after returning from recursion.
179  *
180  * 3) Phi-loop:
181  *     On detection a loop breaker is inserted, which is a copy of the start_phi.
182  *     This copy then pretends beeing the argumnent of the last phi.
183  *     Now case 2) can be used.
184  *
185  * The values of @p start_phi and @p pos never change during recursion.
186  *
187  * @p raenv      Environment with all the stuff needed
188  * @p start_phi  Phi node to process
189  * @p pos        Argument position to insert copy/copies for
190  * @p curr_phi   Phi node currently processed during recursion. Equals start_phi on initial call
191  *
192  * @return NULL  If no copy is necessary
193  *         NULL  If the phi has already been processed at this pos
194  *               Link field is used to keep track of processed positions
195  *         In all other cases the ir_node *copy which was placed is returned.
196  */
197 static ir_node *insert_copies(be_raext_env_t *raenv, ir_node *start_phi, int pos, ir_node *curr_phi) {
198         ir_node *arg = get_irn_n(curr_phi, pos);
199         ir_node *arg_blk = get_nodes_block(arg);
200         ir_node *pred_blk = get_Block_cfgpred_block(get_nodes_block(curr_phi), pos);
201         ir_node *curr_cpy, *last_cpy;
202
203         assert(is_Phi(start_phi) && is_Phi(curr_phi));
204
205         if (has_been_done(start_phi, pos))
206                 return NULL;
207
208         /* In case this is a 'normal' phi we insert into
209          * the schedule before the pred_blk irn */
210         last_cpy = pred_blk;
211
212         /* If we detect a loop stop recursion. */
213         if (arg == start_phi) {
214                 ir_node *loop_breaker;
215                 if (start_phi == curr_phi) {
216                         /* Phi directly uses itself. No copy necessary */
217                         return NULL;
218                 }
219
220                 /* At least 2 phis are involved */
221                 /* Insert a loop breaking copy (an additional variable T) */
222                 loop_breaker = be_new_Copy(raenv->cls, raenv->irg, pred_blk, start_phi);
223                 sched_add_before(pred_blk, loop_breaker);
224
225                 arg = loop_breaker;
226         }
227
228         /* If arg is a phi in the same block we have to continue search */
229         if (is_Phi(arg) && arg_blk == get_nodes_block(start_phi))
230                 last_cpy = insert_copies(raenv, start_phi, pos, arg);
231
232         /* Insert copy of argument (may be the loop-breaker) */
233         curr_cpy = be_new_Copy(raenv->cls, raenv->irg, pred_blk, arg);
234         set_irn_n(curr_phi, pos, curr_cpy);
235         mark_as_done(curr_phi, pos);
236         sched_add_before(last_cpy, curr_cpy);
237         return curr_cpy;
238 }
239
240
241 /**
242  * Perform simple SSA-destruction with copies.
243  * The order of processing _must_ be
244  *  for all positions {
245  *    for all phis {
246  *      doit
247  *    }
248  *  }
249  * else the magic to keep track of processed phi-positions will fail in
250  * function 'insert_copies'
251  */
252 static void ssa_destr_simple_walker(ir_node *blk, void *env) {
253         be_raext_env_t *raenv = env;
254         int pos, max;
255         ir_node *phi;
256
257         /* for all argument positions of the phis */
258         for (pos=0, max=get_irn_arity(blk); pos<max; ++pos) {
259
260                 /* for all phi nodes (which are scheduled first) */
261                 sched_foreach(blk, phi) {
262                         if (!is_Phi(phi))
263                                 break;
264
265                         raenv->cls = arch_get_irn_reg_class(raenv->aenv, phi, -1);
266                         insert_copies(raenv, phi, pos, phi);
267                 }
268         }
269 }
270
271
272 static void ssa_destr_simple(be_raext_env_t *raenv) {
273         be_clear_links(raenv->irg);
274         irg_block_walk_graph(raenv->irg, ssa_destr_simple_walker, NULL, raenv);
275 }
276
277
278 static void ssa_destr_rastello(be_raext_env_t *raenv) {
279         assert(0 && "NYI");
280         /* TODO
281         phi_class_compute(raenv->irg);
282         irg_block_walk_graph(irg, ssa_destr_rastello, NULL, &raenv);
283         */
284 }
285
286 /******************************************************************************
287    __      __   _       ___   __      __
288    \ \    / /  | |     |__ \  \ \    / /
289     \ \  / /_ _| |___     ) |  \ \  / /_ _ _ __ ___
290      \ \/ / _` | / __|   / /    \ \/ / _` | '__/ __|
291       \  / (_| | \__ \  / /_     \  / (_| | |  \__ \
292        \/ \__,_|_|___/ |____|     \/ \__,_|_|  |___/
293  *****************************************************************************/
294
295 /**
296  * This struct maps a variable (nr) to the values belonging to this variable
297  */
298 struct _var_info_t {
299         int var_nr;             /* the key */
300         pset *values;   /* the ssa-values belonging to this variable */
301 };
302
303 #define SET_REMOVED -1
304
305 /**
306  * The link field of an irn points to the var_info struct
307  * representing the corresponding variable.
308  */
309 #define set_var_info(irn, vi)                           set_irn_link(irn, vi)
310 #define get_var_info(irn)                                       ((var_info_t *)get_irn_link(irn))
311
312 #define HASH_VAR_NR(var_nr) var_nr
313
314 static int compare_var_infos(const void *e1, const void *e2, size_t size) {
315         const var_info_t *v1 = e1;
316         const var_info_t *v2 = e2;
317
318         if (v1->var_nr == SET_REMOVED || v2->var_nr == SET_REMOVED)
319                 return 1;
320
321         return v1->var_nr != v2->var_nr;
322 }
323
324 static INLINE var_info_t *var_find(set *vars, int var_nr) {
325         var_info_t vi;
326         vi.var_nr = var_nr;
327
328         return set_find(vars, &vi, sizeof(vi), HASH_VAR_NR(var_nr));
329 }
330
331 static INLINE var_info_t *var_find_or_insert(set *vars, int var_nr) {
332         var_info_t vi, *found;
333         memset(&vi, 0, sizeof(vi));
334         vi.var_nr = var_nr;
335
336         found = set_insert(vars, &vi, sizeof(vi), HASH_VAR_NR(var_nr));
337
338         if (!found->values)
339                 found->values  = pset_new_ptr(1);
340
341         return found;
342 }
343
344 /**
345  * Adds a value to a variable. Sets all pointers accordingly.
346  */
347 static INLINE var_info_t *var_add_value(be_raext_env_t *raenv, int var_nr, ir_node *irn) {
348         var_info_t *vi = var_find_or_insert(raenv->vars, var_nr);
349
350         /* var 2 value mapping */
351         pset_insert_ptr(vi->values, irn);
352
353         /* value 2 var mapping */
354         set_var_info(irn, vi);
355
356         return vi;
357 }
358
359 static INLINE pset *get_var_values(be_raext_env_t *raenv, int var_nr) {
360         var_info_t *vi = var_find(raenv->vars, var_nr);
361         assert(vi && "Variable does not exist");
362         return vi->values;
363 }
364
365 /**
366  * Define variables (numbers) for all SSA-values.
367  * All values in a phi class get assigned the same variable name.
368  * The link field maps values to the var-name
369  */
370 static void values_to_vars(ir_node *irn, void *env) {
371         be_raext_env_t *raenv = env;
372         int nr;
373         pset *vals;
374
375         vals = get_phi_class(irn);
376
377         if (vals) {
378                 nr = get_irn_node_nr(get_first_phi(vals));
379         } else {
380                 /* not a phi class member, value == var */
381                 nr = get_irn_node_nr(irn);
382                 vals = pset_new_ptr(1);
383                 pset_insert_ptr(vals, irn);
384         }
385
386         /* values <--> var mapping */
387         pset_foreach(vals, irn)
388                 var_add_value(raenv, nr, irn);
389 }
390
391
392 /******************************************************************************
393     _____
394    |  __ \
395    | |  | |_   _ _ __ ___  _ __   ___ _ __
396    | |  | | | | | '_ ` _ \| '_ \ / _ \ '__|
397    | |__| | |_| | | | | | | |_) |  __/ |
398    |_____/ \__,_|_| |_| |_| .__/ \___|_|
399                           | |
400                           |_|
401  *****************************************************************************/
402
403
404 static void extract_vars_of_cls(be_raext_env_t *raenv) {
405         int count = 0;
406         var_info_t *vi;
407
408         raenv->cls_vars = malloc(set_count(raenv->vars) * sizeof(*raenv->cls_vars));
409         assert(raenv->cls_vars);
410
411         set_foreach(raenv->vars, vi)
412                 if (is_res_in_reg_class(get_first_non_phi(vi->values)))
413                         raenv->cls_vars[count++] = vi;
414
415         raenv->cls_vars = realloc(raenv->cls_vars, count * sizeof(*raenv->cls_vars));
416         assert(raenv->cls_vars);
417
418         raenv->n_cls_vars = count;
419 }
420
421
422 /**
423  * Check if node irn has a limited-constraint at position pos.
424  * If yes, dump it to FILE raenv->f
425  */
426 static INLINE void dump_constraint(be_raext_env_t *raenv, ir_node *irn, int pos) {
427         bitset_t *bs = bitset_alloca(raenv->cls->n_regs);
428         arch_register_req_t req;
429
430         arch_get_register_req(raenv->aenv, &req, irn, pos);
431         if (arch_register_req_is(&req, limited)) {
432                 int reg_nr;
433                 req.limited(req.limited_env, bs);
434                 reg_nr = bitset_next_set(bs, 0);
435                 fprintf(raenv->f, "<%d>", reg_nr);
436                 assert(-1 == bitset_next_set(bs, reg_nr+1) && "Constraints with more than 1 possible register are not supported");
437         }
438 }
439
440
441 static void dump_nodes(be_raext_env_t *raenv) {
442         FILE *f = raenv->f;
443         int i;
444
445         fprintf(f, "\nnodes {\n");
446
447         for (i=0; i<raenv->n_cls_vars; ++i) {
448                 var_info_t *vi = raenv->cls_vars[i];
449
450                 if (vi->var_nr == SET_REMOVED)
451                         continue;
452
453                 fprintf(f, "%d", vi->var_nr);
454                 dump_constraint(raenv, get_first_non_phi(vi->values), -1);
455                 fprintf(f, "\n");
456         }
457
458         fprintf(f, "}\n");
459 }
460
461
462 static void dump_interferences(be_raext_env_t *raenv) {
463         int i,o;
464         var_info_t *vi1, *vi2;
465         ir_node *irn1, *irn2;
466         FILE *f = raenv->f;
467
468         fprintf(f, "\ninterferences {\n");
469
470         for (i=0; i<raenv->n_cls_vars; ++i) {
471                 vi1 = raenv->cls_vars[i];
472
473                 if (vi1->var_nr == SET_REMOVED)
474                         continue;
475
476                 for (o=i+1; o<raenv->n_cls_vars; ++o) {
477                         vi2 = raenv->cls_vars[o];
478
479                         if (vi2->var_nr == SET_REMOVED)
480                                 continue;
481
482                         pset_foreach(vi1->values, irn1)
483                                 pset_foreach(vi2->values, irn2)
484                                         if (values_interfere(irn1, irn2)) {
485                                                 pset_break(vi1->values);
486                                                 pset_break(vi2->values);
487                                                 fprintf(f, "(%d %d)\n", vi1->var_nr, vi2->var_nr);
488                                         }
489                 }
490         }
491         fprintf(f, "}\n");
492 }
493
494
495 static void dump_affinities_walker(ir_node *irn, void *env) {
496         be_raext_env_t *raenv = env;
497
498         if (arch_irn_classify(raenv->aenv, irn) == arch_irn_class_copy) {
499                 ir_node *src = get_irn_n(irn, 0);
500                 var_info_t *vi1 = get_irn_link(irn);
501                 var_info_t *vi2 = get_irn_link(src);
502
503                 fprintf(raenv->f, "(%d %d)\n",  vi1->var_nr, vi2->var_nr);
504         }
505 }
506
507
508 static void dump_affinities(be_raext_env_t *raenv) {
509         fprintf(raenv->f, "\ninterferences {\n");
510         irg_walk_graph(raenv->irg, NULL, dump_affinities_walker, raenv);
511         fprintf(raenv->f, "}\n");
512 }
513
514 /**
515  * Dump all information needed by the external
516  * register allocator to a single file.
517  */
518 static void dump_to_file(be_raext_env_t *raenv, char *filename) {
519         FILE *f;
520
521         if (!(f = fopen(filename, "wt"))) {
522                 fprintf(stderr, "Could not open file %s for writing\n", filename);
523                 exit(0xdeadbeef);
524         }
525         raenv->f = f;
526
527         /* dump register info */
528         fprintf(f, "regs %d\n", arch_register_class_n_regs(raenv->cls));
529
530         /* dump the interference graph */
531         dump_nodes(raenv);
532         dump_interferences(raenv);
533         dump_affinities(raenv);
534
535         fclose(f);
536 }
537
538 /******************************************************************************
539     ______                     _
540    |  ____|                   | |
541    | |__  __  _____  ___ _   _| |_ ___
542    |  __| \ \/ / _ \/ __| | | | __/ _ \
543    | |____ >  <  __/ (__| |_| | ||  __/
544    |______/_/\_\___|\___|\__,_|\__\___|
545  *****************************************************************************/
546
547 /**
548  * Execute the external register allocator specified in the
549  * firm-option firm.be.ra.ext.callee
550  */
551 static void execute(char *prog_to_call, char *out_file, char *result_file) {
552         char cmd_line[1024];
553         int ret_status;
554
555         snprintf(cmd_line, sizeof(cmd_line), "%s %s %s", prog_to_call, out_file, result_file);
556
557         ret_status = system(cmd_line);
558         assert(ret_status != -1 && "Invokation of external register allocator failed");
559 }
560
561 /******************************************************************************
562                          _         _____                 _ _
563        /\               | |       |  __ \               | | |
564       /  \   _ __  _ __ | |_   _  | |__) |___  ___ _   _| | |_
565      / /\ \ | '_ \| '_ \| | | | | |  _  // _ \/ __| | | | | __|
566     / ____ \| |_) | |_) | | |_| | | | \ \  __/\__ \ |_| | | |_
567    /_/    \_\ .__/| .__/|_|\__, | |_|  \_\___||___/\__,_|_|\__|
568             | |   | |       __/ |
569             |_|   |_|      |___/
570  *****************************************************************************/
571
572 /**
573  * Spill a variable and add reloads before all uses.
574  */
575 static INLINE void var_add_spills_and_reloads(be_raext_env_t *raenv, int var_nr) {
576         var_info_t *vi = var_find(raenv->vars, var_nr);
577         ir_node *spill=NULL, *ctx, *irn;
578         const ir_edge_t *edge;
579         pset *spills  = pset_new_ptr(4);        /* the spills of this variable */
580         pset *reloads = pset_new_ptr(4);        /* the reloads of this variable */
581         int new_size, n_spills, n_reloads;
582
583         assert(vi && "Variable nr does not exist!");
584         assert(pset_count(vi->values) && "There are no values associated to this variable");
585
586         /* the spill context is set to an arbitrary node of the phi-class */
587         ctx = get_first_phi(vi->values);
588
589         /* for each value of this variable insert the spills */
590         pset_foreach(vi->values, irn) {
591                 if (is_Phi(irn))
592                         continue;
593
594                 /* all ordinary nodes must be spilled */
595                 spill = be_new_Spill(raenv->cls, raenv->irg, get_nodes_block(irn), irn, ctx);
596                 sched_add_after(irn, spill);
597
598                 /* remember the spill */
599                 pset_insert_ptr(spills, spill);
600         }
601
602         assert(spill && "There must be at least one non-phi-node");
603
604         /* insert reloads and wire them arbitrary*/
605         pset_foreach(vi->values, irn)
606                 foreach_out_edge(irn, edge) {
607                         ir_node *reload, *src = edge->src;
608                         if (is_Phi(src))
609                                 continue;
610
611                         /* all real uses must be reloaded */
612                         reload = be_new_Reload(raenv->cls, raenv->irg, get_nodes_block(src), get_irn_mode(get_irn_n(spill, 0)), spill);
613                         sched_add_before(src, reload);
614
615                         /* remember the reload */
616                         pset_insert_ptr(reloads, reload);
617                 }
618
619         /* correct the reload->spill pointers... */
620         be_introduce_copies_for_set(raenv->dom_info, spills, reloads); /* TODO */
621
622
623         /****** correct the variable <--> values mapping: ******
624          *
625          *  - if we had a phi class it gets split into several new variables
626          *  - all reloads are new variables
627          */
628         n_spills = pset_count(spills);
629         n_reloads = pset_count(reloads);
630
631         /* first make room for new pointers in the cls_var array */
632         new_size = raenv->n_cls_vars + n_reloads + ((n_spills>1) ? n_spills : 0);
633         raenv->cls_vars = realloc(raenv->cls_vars, (new_size) * sizeof(*raenv->cls_vars));
634         assert(raenv->cls_vars && "Out of mem!?");
635
636         /* if we had a real phi-class, we must... */
637         if (pset_count(spills) > 1) {
638                 /* ...remove the old variable corresponding to the phi class */
639                 vi->var_nr = SET_REMOVED;
640
641                 /* ...add new vars for each non-phi-member */
642                 pset_foreach(spills, irn) {
643                         ir_node *spilled = get_irn_n(irn, 0);
644                         raenv->cls_vars[raenv->n_cls_vars++] = var_add_value(raenv, get_irn_node_nr(spilled), spilled);
645                 }
646         }
647
648         /* add new variables for all reloads */
649         pset_foreach(reloads, irn)
650                 raenv->cls_vars[raenv->n_cls_vars++] = var_add_value(raenv, get_irn_node_nr(irn), irn);
651
652
653
654         del_pset(spills);
655         del_pset(reloads);
656 }
657
658 #define INVALID_FILE_FORMAT assert(0 && "Invalid file format.")
659 #define BUFLEN 32
660 #define BUFCONV " %32s "
661
662 /**
663  * Read in the actions performed by the external allocator.
664  * Apply these transformations to the irg.
665  * @return 1 if an allocation was read in. 0 otherwise.
666  */
667 static int read_and_apply_results(be_raext_env_t *raenv, char *filename) {
668         FILE *f;
669         char buf[BUFLEN];
670         int is_allocation = 0;
671
672         if (!(f = fopen(filename, "rt"))) {
673                 fprintf(stderr, "Could not open file %s for reading\n", filename);
674                 exit(0xdeadbeef);
675         }
676         raenv->f = f;
677
678         /* read the action */
679         if (fscanf(f, BUFCONV, buf) != 1)
680                 INVALID_FILE_FORMAT;
681
682         /* do we spill */
683         if (!strcmp(buf, "spills")) {
684                 int var_nr;
685                 while (fscanf(f, " %d ", &var_nr) == 1)
686                         var_add_spills_and_reloads(raenv, var_nr);
687         } else
688
689         /* or do we allocate */
690         if (!strcmp(buf, "allocs")) {
691                 int var_nr, reg_nr;
692
693                 is_allocation = 1;
694                 while (fscanf(f, " %d %d ", &var_nr, &reg_nr) == 2) {
695                         ir_node *irn;
696                         pset *vals = get_var_values(raenv, var_nr);
697
698                         assert(vals && "Variable nr does not exist!");
699                         pset_foreach(vals, irn)
700                                 arch_set_irn_register(raenv->aenv, irn, arch_register_for_index(raenv->cls, reg_nr));
701                 }
702         } else
703                 INVALID_FILE_FORMAT;
704
705         if (!feof(f))
706                 INVALID_FILE_FORMAT;
707
708         fclose(f);
709
710         return is_allocation;
711 }
712
713 /******************************************************************************
714     __  __       _
715    |  \/  |     (_)
716    | \  / | __ _ _ _ __
717    | |\/| |/ _` | | '_ \
718    | |  | | (_| | | | | |
719    |_|  |_|\__,_|_|_| |_|
720  *****************************************************************************/
721
722 /**
723  * Default values for options
724  */
725 static void (*ssa_destr)(be_raext_env_t*) = ssa_destr_simple;
726 static char callee[128] = "echo";
727
728
729 /**
730  * Allocate registers with an external program using a text-file interface.
731  *
732  * Do some computations (SSA-destruction and mapping of values--vars)
733  * Write file
734  * Execute external program
735  * Read in results and apply them
736  *
737  */
738 static void be_ra_extern_main(const be_main_env_t *env, ir_graph *irg) {
739         be_raext_env_t raenv;
740         int clsnr, clss;
741         var_info_t *vi;
742
743         compute_doms(irg);
744
745         raenv.irg      = irg;
746         raenv.aenv     = env->arch_env;
747         raenv.dom_info = be_compute_dominance_frontiers(irg);
748         raenv.vars     = new_set(compare_var_infos, 64);
749
750
751         //TODO /* Insert copies */
752         //TODO /* Change In to Out constraints */
753
754         /* SSA destruction */
755         ssa_destr(&raenv);
756
757         /* Mapping of SSA-Values <--> Variables */
758         phi_class_compute(irg);
759         be_clear_links(irg);
760         irg_walk_graph(irg, values_to_vars, NULL, &raenv);
761
762         dump_ir_block_graph_sched(irg, "-extern-ssadestr");
763
764         /* For all register classes */
765         for(clsnr = 0, clss = arch_isa_get_n_reg_class(raenv.aenv->isa); clsnr < clss; ++clsnr) {
766                 int done = 0;
767                 char out[256], in[256];
768
769                 raenv.cls = arch_isa_get_reg_class(raenv.aenv->isa, clsnr);
770                 ir_snprintf(out, sizeof(out), "%F-%s.ra", irg, raenv.cls->name);
771                 ir_snprintf(in, sizeof(in), "%F-%s.ra.res", irg, raenv.cls->name);
772
773                 extract_vars_of_cls(&raenv);
774
775                 while (!done) {
776                         dump_to_file(&raenv, out);
777                         execute(callee, out, in);
778                         done = read_and_apply_results(&raenv, in);
779                 }
780
781                 free(raenv.cls_vars);
782         }
783
784         /* Clean up */
785         set_foreach(raenv.vars, vi)
786                 del_pset(vi->values);
787         del_set(raenv.vars);
788         be_free_dominance_frontiers(raenv.dom_info);
789 }
790
791 /******************************************************************************
792      ____        _   _
793     / __ \      | | (_)
794    | |  | |_ __ | |_ _  ___  _ __  ___
795    | |  | | '_ \| __| |/ _ \| '_ \/ __|
796    | |__| | |_) | |_| | (_) | | | \__ \
797     \____/| .__/ \__|_|\___/|_| |_|___/
798           | |
799           |_|
800  *****************************************************************************/
801
802 #ifdef WITH_LIBCORE
803
804 static const lc_opt_enum_const_ptr_items_t ssa_destr_items[] = {
805         { "simple",    ssa_destr_simple },
806         { "rastello",  ssa_destr_rastello },
807         { NULL,      NULL }
808 };
809
810 static lc_opt_enum_const_ptr_var_t ssa_destr_var = {
811         (const void **) &ssa_destr, ssa_destr_items
812 };
813
814 static const lc_opt_table_entry_t be_ra_extern_options[] = {
815         LC_OPT_ENT_ENUM_FUNC_PTR("ssa_destr", "SSA destruction flavor", &ssa_destr_var),
816         LC_OPT_ENT_STR("callee", "The external program to call", callee, sizeof(callee)),
817         { NULL }
818 };
819
820 static void be_ra_extern_register_options(lc_opt_entry_t *root) {
821         lc_opt_entry_t *grp = lc_opt_get_grp(root, "ext");
822
823         lc_opt_add_table(grp, be_ra_extern_options);
824 }
825
826 #endif /* WITH_LIBCORE */
827
828 const be_ra_t be_ra_external_allocator = {
829 #ifdef WITH_LIBCORE
830         be_ra_extern_register_options,
831 #endif
832         be_ra_extern_main
833 };