179fdc0e163db2c0061b26c5c124f99141f45d06
[libfirm] / ir / lower / lower_dw.c
1 /**
2  * @file irlwrdw.c
3  * @date 8.10.2004
4  * @author Michael Beck
5  * @brief Lower Double word operations, ie Mode L -> I.
6  *
7  * $Id$
8  */
9 #ifdef HAVE_CONFIG_H
10 # include "config.h"
11 #endif
12
13 #ifdef HAVE_MALLOC_H
14 # include <malloc.h>
15 #endif
16 #ifdef HAVE_ALLOCA_H
17 # include <alloca.h>
18 #endif
19 #ifdef HAVE_STRING_H
20 # include <string.h>
21 #endif
22 #ifdef HAVE_STDLIB_H
23 # include <stdlib.h>
24 #endif
25
26 #include <assert.h>
27
28 #include "irnode_t.h"
29 #include "irgraph_t.h"
30 #include "irmode_t.h"
31 #include "iropt_t.h"
32 #include "irgmod.h"
33 #include "tv_t.h"
34 #include "dbginfo_t.h"
35 #include "iropt_dbg.h"
36 #include "irflag_t.h"
37 #include "firmstat.h"
38 #include "irgwalk.h"
39 #include "ircons.h"
40 #include "lower_dw.h"
41 #include "irflag.h"
42 #include "irtools.h"
43 #include "debug.h"
44 #include "set.h"
45 #include "pmap.h"
46 #include "pdeq.h"
47 #include "irdump.h"
48
49 /** A map from mode to a primitive type. */
50 static pmap *prim_types;
51
52 /** A map from (op, imode, omode) to Intrinsic functions entities. */
53 static set *intrinsic_fkt;
54
55 /** A map from (imode, omode) to conv function types. */
56 static set *conv_types;
57
58 /** A map from a method type to its lowered type. */
59 static pmap *lowered_type;
60
61 /** The types for the binop and unop intrinsics. */
62 static ir_type *binop_tp_u, *binop_tp_s, *unop_tp_u, *unop_tp_s, *tp_s, *tp_u;
63
64 /** the debug handle */
65 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
66
67 /**
68  * An entry in the (op, imode, omode) -> entity map.
69  */
70 typedef struct _op_mode_entry {
71         const ir_op   *op;    /**< the op */
72         const ir_mode *imode; /**< the input mode */
73         const ir_mode *omode; /**< the output mode */
74         entity        *ent;   /**< the associated entity of this (op, imode, omode) triple */
75 } op_mode_entry_t;
76
77 /**
78  * An entry in the (imode, omode) -> tp map.
79  */
80 typedef struct _conv_tp_entry {
81         const ir_mode *imode; /**< the input mode */
82         const ir_mode *omode; /**< the output mode */
83         ir_type       *mtd;   /**< the associated method type of this (imode, omode) pair */
84 } conv_tp_entry_t;
85
86 /**
87  * Every double word node will be replaced,
88  * we need some store to hold the replacement:
89  */
90 typedef struct _node_entry_t {
91         ir_node *low_word;        /**< the low word */
92         ir_node *high_word;       /**< the high word */
93 } node_entry_t;
94
95 enum lower_flags {
96         MUST_BE_LOWERED = 1,   /**< graph must be lowered */
97         CF_CHANGED      = 2,   /**< control flow was changed */
98 };
99
100 /**
101  * The lower environment.
102  */
103 typedef struct _lower_env_t {
104         node_entry_t **entries;       /**< entries per node */
105         struct obstack obst;          /**< an obstack holding the temporary data */
106         tarval   *tv_mode_bytes;      /**< a tarval containing the number of bytes in the lowered modes */
107         tarval   *tv_mode_bits;       /**< a tarval containing the number of bits in the lowered modes */
108         pdeq     *waitq;              /**< a wait queue of all nodes that must be handled later */
109         pmap     *proj_2_block;       /**< a map from ProjX to its destination blocks */
110         const lwrdw_param_t *params;  /**< transformation parameter */
111         unsigned flags;               /**< some flags */
112         int      n_entries;           /**< number of entries */
113 } lower_env_t;
114
115 /**
116  * Get a primitive mode for a mode.
117  */
118 static ir_type *get_primitive_type(ir_mode *mode) {
119         pmap_entry *entry = pmap_find(prim_types, mode);
120         ir_type *tp;
121         char buf[64];
122
123         if (entry)
124                 return entry->value;
125
126         snprintf(buf, sizeof(buf), "_prim_%s", get_mode_name(mode));
127         tp = new_type_primitive(new_id_from_str(buf), mode);
128
129         pmap_insert(prim_types, mode, tp);
130         return tp;
131 }
132
133 /**
134  * Create a method type for a Conv emulation from imode to omode.
135  */
136 static ir_type *get_conv_type(ir_mode *imode, ir_mode *omode, lower_env_t *env) {
137         conv_tp_entry_t key, *entry;
138         ir_type *mtd;
139
140         key.imode = imode;
141         key.omode = omode;
142         key.mtd   = NULL;
143
144         entry = set_insert(conv_types, &key, sizeof(key), HASH_PTR(imode) ^ HASH_PTR(omode));
145         if (! entry->mtd) {
146                 int n_param = 1, n_res = 1;
147                 char buf[64];
148
149                 if (imode == env->params->high_signed || imode == env->params->high_unsigned)
150                         n_param = 2;
151                 if (omode == env->params->high_signed || omode == env->params->high_unsigned)
152                         n_res = 2;
153
154                 /* create a new one */
155                 snprintf(buf, sizeof(buf), "LConv%s%s", get_mode_name(imode), get_mode_name(omode));
156                 mtd = new_type_method(new_id_from_str(buf), n_param, n_res);
157
158                 /* set param types and result types */
159                 n_param = 0;
160                 if (imode == env->params->high_signed) {
161                         set_method_param_type(mtd, n_param++, tp_s);
162                         set_method_param_type(mtd, n_param++, tp_s);
163                 }
164                 else if (imode == env->params->high_unsigned) {
165                         set_method_param_type(mtd, n_param++, tp_u);
166                         set_method_param_type(mtd, n_param++, tp_u);
167                 }
168                 else {
169                         ir_type *tp = get_primitive_type(imode);
170                         set_method_param_type(mtd, n_param++, tp);
171                 }
172
173                 n_res = 0;
174                 if (omode == env->params->high_signed) {
175                         set_method_res_type(mtd, n_res++, tp_s);
176                         set_method_res_type(mtd, n_res++, tp_s);
177                 }
178                 else if (omode == env->params->high_unsigned) {
179                         set_method_res_type(mtd, n_res++, tp_u);
180                         set_method_res_type(mtd, n_res++, tp_u);
181                 }
182                 else {
183                         ir_type *tp = get_primitive_type(omode);
184                         set_method_res_type(mtd, n_res++, tp);
185                 }
186
187                 entry->mtd = mtd;
188         }
189         else
190                 mtd = entry->mtd;
191         return mtd;
192 }
193
194 /**
195  * Add an additional control flow input to a block.
196  * Patch all Phi nodes. The new Phi inputs are copied from
197  * old input number nr.
198  */
199 static void add_block_cf_input_nr(ir_node *block, int nr, ir_node *cf)
200 {
201         int i, arity = get_irn_arity(block);
202         ir_node **in, *phi;
203
204         assert(nr < arity);
205
206         NEW_ARR_A(ir_node *, in, arity + 1);
207         for (i = 0; i < arity; ++i)
208                 in[i] = get_irn_n(block, i);
209         in[i] = cf;
210
211         set_irn_in(block, i + 1, in);
212
213         for (phi = get_irn_link(block); phi; phi = get_irn_link(phi)) {
214                 for (i = 0; i < arity; ++i)
215                         in[i] = get_irn_n(phi, i);
216                 in[i] = in[nr];
217                 set_irn_in(phi, i + 1, in);
218         }
219 }
220
221 /**
222  * Add an additional control flow input to a block.
223  * Patch all Phi nodes. The new Phi inputs are copied from
224  * old input from cf tmpl.
225  */
226 static void add_block_cf_input(ir_node *block, ir_node *tmpl, ir_node *cf)
227 {
228         int i, arity = get_irn_arity(block);
229         int nr = 0;
230
231         for (i = 0; i < arity; ++i) {
232                 if (get_irn_n(block, i) == tmpl) {
233                         nr = i;
234                         break;
235                 }
236         }
237         assert(i < arity);
238         add_block_cf_input_nr(block, nr, cf);
239 }
240
241 /**
242  * Return the "operational" mode of a Firm node.
243  */
244 static ir_mode *get_irn_op_mode(ir_node *node)
245 {
246         switch (get_irn_opcode(node)) {
247         case iro_Load:
248                 return get_Load_mode(node);
249
250         case iro_Store:
251                 return get_irn_mode(get_Store_value(node));
252
253         case iro_DivMod:
254                 return get_irn_mode(get_DivMod_left(node));
255
256         case iro_Div:
257                 return get_irn_mode(get_Div_left(node));
258
259         case iro_Mod:
260                 return get_irn_mode(get_Mod_left(node));
261
262         case iro_Cmp:
263                 return get_irn_mode(get_Cmp_left(node));
264
265         default:
266                 return get_irn_mode(node);
267         }
268 }
269
270 /**
271  * walker, prepare the node links
272  */
273 static void prepare_links(ir_node *node, void *env)
274 {
275         lower_env_t  *lenv = env;
276         ir_mode      *mode = get_irn_op_mode(node);
277         node_entry_t *link;
278         int          i;
279
280         if (mode == lenv->params->high_signed ||
281                 mode == lenv->params->high_unsigned) {
282                 /* ok, found a node that will be lowered */
283                 link = obstack_alloc(&lenv->obst, sizeof(*link));
284
285                 memset(link, 0, sizeof(*link));
286
287                 lenv->entries[get_irn_idx(node)] = link;
288                 lenv->flags |= MUST_BE_LOWERED;
289         }
290         else if (get_irn_op(node) == op_Conv) {
291                 /* Conv nodes have two modes */
292                 ir_node *pred = get_Conv_op(node);
293                 mode = get_irn_mode(pred);
294
295                 if (mode == lenv->params->high_signed ||
296                         mode == lenv->params->high_unsigned) {
297                         /* must lower this node either */
298                         link = obstack_alloc(&lenv->obst, sizeof(*link));
299
300                         memset(link, 0, sizeof(*link));
301
302                         lenv->entries[get_irn_idx(node)] = link;
303                         lenv->flags |= MUST_BE_LOWERED;
304                 }
305                 return;
306         }
307
308         if (is_Proj(node)) {
309                 /* link all Proj nodes to its predecessor:
310                    Note that Tuple Proj's and its Projs are linked either. */
311                 ir_node *pred = get_Proj_pred(node);
312
313                 set_irn_link(node, get_irn_link(pred));
314                 set_irn_link(pred, node);
315         }
316         else if (is_Phi(node)) {
317                 /* link all Phi nodes to its block */
318                 ir_node *block = get_nodes_block(node);
319
320                 set_irn_link(node, get_irn_link(block));
321                 set_irn_link(block, node);
322         }
323         else if (is_Block(node)) {
324                 /* fill the Proj -> Block map */
325                 for (i = get_Block_n_cfgpreds(node) - 1; i >= 0; --i) {
326                         ir_node *pred = get_Block_cfgpred(node, i);
327
328                         if (is_Proj(pred))
329                                 pmap_insert(lenv->proj_2_block, pred, node);
330                 }
331         }
332 }
333
334 /**
335  * Translate a Constant: create two.
336  */
337 static void lower_Const(ir_node *node, ir_mode *mode, lower_env_t *env) {
338         tarval   *tv, *tv_l, *tv_h;
339         ir_node  *low, *high;
340         dbg_info *dbg = get_irn_dbg_info(node);
341         ir_node  *block = get_nodes_block(node);
342         int      idx;
343
344         tv   = get_Const_tarval(node);
345
346         tv_l = tarval_convert_to(tv, mode);
347         low  = new_rd_Const(dbg, current_ir_graph, block, mode, tv_l);
348
349         tv_h = tarval_convert_to(tarval_shrs(tv, env->tv_mode_bits), mode);
350         high = new_rd_Const(dbg, current_ir_graph, block, mode, tv_h);
351
352         idx = get_irn_idx(node);
353         assert(idx < env->n_entries);
354         env->entries[idx]->low_word  = low;
355         env->entries[idx]->high_word = high;
356 }
357
358 /**
359  * Translate a Load: create two.
360  */
361 static void lower_Load(ir_node *node, ir_mode *mode, lower_env_t *env) {
362         ir_graph *irg = current_ir_graph;
363         ir_node  *adr = get_Load_ptr(node);
364         ir_node  *mem = get_Load_mem(node);
365         ir_node  *low, *high, *proj;
366         dbg_info *dbg;
367         ir_node  *block = get_nodes_block(node);
368         int      idx;
369
370         if (env->params->little_endian) {
371                 low  = adr;
372                 high = new_r_Add(irg, block, adr,
373                         new_r_Const(irg, block, get_tarval_mode(env->tv_mode_bytes), env->tv_mode_bytes),
374                         get_irn_mode(adr));
375         }
376         else {
377                 low  = new_r_Add(irg, block, adr,
378                         new_r_Const(irg, block, get_tarval_mode(env->tv_mode_bytes), env->tv_mode_bytes),
379                         get_irn_mode(adr));
380                 high = adr;
381         }
382
383         /* create two loads */
384         dbg  = get_irn_dbg_info(node);
385         low  = new_rd_Load(dbg, irg, block, mem, low,  mode);
386         proj = new_r_Proj(irg, block, low, mode_M, pn_Load_M);
387         high = new_rd_Load(dbg, irg, block, proj, high, mode);
388
389         set_Load_volatility(low,  get_Load_volatility(node));
390         set_Load_volatility(high, get_Load_volatility(node));
391
392         idx = get_irn_idx(node);
393         assert(idx < env->n_entries);
394         env->entries[idx]->low_word  = low;
395         env->entries[idx]->high_word = high;
396
397         for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
398                 idx = get_irn_idx(proj);
399
400                 switch (get_Proj_proj(proj)) {
401                 case pn_Load_M:         /* Memory result. */
402                         /* put it to the second one */
403                         set_Proj_pred(proj, high);
404                         break;
405                 case pn_Load_X_except:  /* Execution result if exception occurred. */
406                         /* put it to the first one */
407                         set_Proj_pred(proj, low);
408                         break;
409                 case pn_Load_res:       /* Result of load operation. */
410                         assert(idx < env->n_entries);
411                         env->entries[idx]->low_word  = new_r_Proj(irg, block, low, mode, pn_Load_res);
412                         env->entries[idx]->high_word = new_r_Proj(irg, block, high, mode, pn_Load_res);
413                         break;
414                 default:
415                         assert(0 && "unexpected Proj number");
416                 }
417                 /* mark this proj: we have handled it already, otherwise we might fall into
418                  * out new nodes. */
419                 mark_irn_visited(proj);
420         }
421 }
422
423 /**
424  * Translate a Store: create two.
425  */
426 static void lower_Store(ir_node *node, ir_mode *mode, lower_env_t *env) {
427         ir_graph *irg;
428         ir_node  *block, *adr, *mem;
429         ir_node  *low, *high, *irn, *proj;
430         dbg_info *dbg;
431         int      idx;
432         node_entry_t *entry;
433
434         irn = get_Store_value(node);
435         entry = env->entries[get_irn_idx(irn)];
436         assert(entry);
437
438         if (! entry->low_word) {
439                 /* not ready yet, wait */
440                 pdeq_putr(env->waitq, node);
441                 return;
442         }
443
444         irg = current_ir_graph;
445         adr = get_Store_ptr(node);
446         mem = get_Store_mem(node);
447         block = get_nodes_block(node);
448
449         if (env->params->little_endian) {
450                 low  = adr;
451                 high = new_r_Add(irg, block, adr,
452                         new_r_Const(irg, block, get_tarval_mode(env->tv_mode_bytes), env->tv_mode_bytes),
453                         get_irn_mode(adr));
454         }
455         else {
456                 low  = new_r_Add(irg, block, adr,
457                         new_r_Const(irg, block, get_tarval_mode(env->tv_mode_bytes), env->tv_mode_bytes),
458                         get_irn_mode(adr));
459                 high = adr;
460         }
461
462         /* create two Stores */
463         dbg = get_irn_dbg_info(node);
464         low  = new_rd_Store(dbg, irg, block, mem, low,  entry->low_word);
465         proj = new_r_Proj(irg, block, low, mode_M, pn_Store_M);
466         high = new_rd_Store(dbg, irg, block, proj, high, entry->high_word);
467
468         set_Store_volatility(low,  get_Store_volatility(node));
469         set_Store_volatility(high, get_Store_volatility(node));
470
471         idx = get_irn_idx(node);
472         assert(idx < env->n_entries);
473         env->entries[idx]->low_word  = low;
474         env->entries[idx]->high_word = high;
475
476         for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
477                 idx = get_irn_idx(proj);
478
479                 switch (get_Proj_proj(proj)) {
480                 case pn_Store_M:         /* Memory result. */
481                         /* put it to the second one */
482                         set_Proj_pred(proj, high);
483                         break;
484                 case pn_Store_X_except:  /* Execution result if exception occurred. */
485                         /* put it to the first one */
486                         set_Proj_pred(proj, low);
487                         break;
488                 default:
489                         assert(0 && "unexpected Proj number");
490                 }
491                 /* mark this proj: we have handled it already, otherwise we might fall into
492                  * out new nodes. */
493                 mark_irn_visited(proj);
494         }
495 }
496
497 /**
498  * Return a node containing the address of the intrinsic emulation function.
499  *
500  * @param method  the method type of the emulation function
501  * @param op      the emulated ir_op
502  * @param imode   the input mode of the emulated opcode
503  * @param omode   the output mode of the emulated opcode
504  * @param block   where the new mode is created
505  * @param env     the lower environment
506  */
507 static ir_node *get_intrinsic_address(ir_type *method, ir_op *op,
508                                       ir_mode *imode, ir_mode *omode,
509                                       ir_node *block, lower_env_t *env) {
510         symconst_symbol sym;
511         entity *ent;
512         op_mode_entry_t key, *entry;
513
514         key.op    = op;
515         key.imode = imode;
516         key.omode = omode;
517         key.ent   = NULL;
518
519         entry = set_insert(intrinsic_fkt, &key, sizeof(key),
520                                 HASH_PTR(op) ^ HASH_PTR(imode) ^ (HASH_PTR(omode) << 8));
521         if (! entry->ent) {
522                 /* create a new one */
523                 ent = env->params->create_intrinsic(method, op, imode, omode, env->params->ctx);
524
525                 assert(ent && "Intrinsic creator must return an entity");
526                 entry->ent = ent;
527         }
528         else
529                 ent = entry->ent;
530
531         sym.entity_p = ent;
532         return new_r_SymConst(current_ir_graph, block, sym, symconst_addr_ent);
533 }
534
535 /**
536  * Translate a Div.
537  *
538  * Create an intrinsic Call.
539  */
540 static void lower_Div(ir_node *node, ir_mode *mode, lower_env_t *env) {
541         ir_node  *block, *irn, *call, *proj;
542         ir_node  *in[4];
543         ir_mode  *opmode;
544         dbg_info *dbg;
545         ir_type  *mtp;
546         int      idx;
547         node_entry_t *entry;
548
549         irn   = get_Div_left(node);
550         entry = env->entries[get_irn_idx(irn)];
551         assert(entry);
552
553         if (! entry->low_word) {
554                 /* not ready yet, wait */
555                 pdeq_putr(env->waitq, node);
556                 return;
557         }
558
559         in[0] = entry->low_word;
560         in[1] = entry->high_word;
561
562         irn   = get_Div_right(node);
563         entry = env->entries[get_irn_idx(irn)];
564         assert(entry);
565
566         if (! entry->low_word) {
567                 /* not ready yet, wait */
568                 pdeq_putr(env->waitq, node);
569                 return;
570         }
571
572         in[2] = entry->low_word;
573         in[3] = entry->high_word;
574
575         dbg = get_irn_dbg_info(node);
576         block = get_nodes_block(node);
577
578         mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
579         opmode = get_irn_op_mode(node);
580         irn = get_intrinsic_address(mtp, get_irn_op(node), opmode, opmode, block, env);
581         call = new_rd_Call(dbg, current_ir_graph, block, get_Div_mem(node),
582                 irn, 4, in, mtp);
583         set_irn_pinned(call, get_irn_pinned(node));
584         irn = new_r_Proj(current_ir_graph, block, call, mode_T, pn_Call_T_result);
585
586         for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
587                 switch (get_Proj_proj(proj)) {
588                 case pn_Div_M:         /* Memory result. */
589                         /* reroute to the call */
590                         set_Proj_pred(proj, call);
591                         set_Proj_proj(proj, pn_Call_M_except);
592                         break;
593                 case pn_Div_X_except:  /* Execution result if exception occurred. */
594                         /* reroute to the call */
595                         set_Proj_pred(proj, call);
596                         set_Proj_proj(proj, pn_Call_X_except);
597                         break;
598                 case pn_Div_res:       /* Result of computation. */
599                         idx = get_irn_idx(proj);
600                         assert(idx < env->n_entries);
601                         env->entries[idx]->low_word  = new_r_Proj(current_ir_graph, block, irn, mode, 0);
602                         env->entries[idx]->high_word = new_r_Proj(current_ir_graph, block, irn, mode, 1);
603                         break;
604                 default:
605                         assert(0 && "unexpected Proj number");
606                 }
607                 /* mark this proj: we have handled it already, otherwise we might fall into
608                  * out new nodes. */
609                 mark_irn_visited(proj);
610         }
611 }
612
613 /**
614  * Translate a Mod.
615  *
616  * Create an intrinsic Call.
617  */
618 static void lower_Mod(ir_node *node, ir_mode *mode, lower_env_t *env) {
619         ir_node  *block, *proj, *irn, *call;
620         ir_node  *in[4];
621         ir_mode  *opmode;
622         dbg_info *dbg;
623         ir_type  *mtp;
624         int      idx;
625         node_entry_t *entry;
626
627         irn   = get_Mod_left(node);
628         entry = env->entries[get_irn_idx(irn)];
629         assert(entry);
630
631         if (! entry->low_word) {
632                 /* not ready yet, wait */
633                 pdeq_putr(env->waitq, node);
634                 return;
635         }
636
637         in[0] = entry->low_word;
638         in[1] = entry->high_word;
639
640         irn   = get_Mod_right(node);
641         entry = env->entries[get_irn_idx(irn)];
642         assert(entry);
643
644         if (! entry->low_word) {
645                 /* not ready yet, wait */
646                 pdeq_putr(env->waitq, node);
647                 return;
648         }
649
650         in[2] = entry->low_word;
651         in[3] = entry->high_word;
652
653         dbg = get_irn_dbg_info(node);
654         block = get_nodes_block(node);
655
656         mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
657         opmode = get_irn_op_mode(node);
658         irn = get_intrinsic_address(mtp, get_irn_op(node), opmode, opmode, block, env);
659         call = new_rd_Call(dbg, current_ir_graph, block, get_Mod_mem(node),
660                 irn, 4, in, mtp);
661         set_irn_pinned(call, get_irn_pinned(node));
662         irn = new_r_Proj(current_ir_graph, block, call, mode_T, pn_Call_T_result);
663
664         for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
665                 switch (get_Proj_proj(proj)) {
666                 case pn_Mod_M:         /* Memory result. */
667                         /* reroute to the call */
668                         set_Proj_pred(proj, call);
669                         set_Proj_proj(proj, pn_Call_M_except);
670                         break;
671                 case pn_Mod_X_except:  /* Execution result if exception occurred. */
672                         /* reroute to the call */
673                         set_Proj_pred(proj, call);
674                         set_Proj_proj(proj, pn_Call_X_except);
675                         break;
676                 case pn_Mod_res:       /* Result of computation. */
677                         idx = get_irn_idx(proj);
678                         assert(idx < env->n_entries);
679                         env->entries[idx]->low_word  = new_r_Proj(current_ir_graph, block, irn, mode, 0);
680                         env->entries[idx]->high_word = new_r_Proj(current_ir_graph, block, irn, mode, 1);
681                         break;
682                 default:
683                         assert(0 && "unexpected Proj number");
684                 }
685                 /* mark this proj: we have handled it already, otherwise we might fall into
686                  * out new nodes. */
687                 mark_irn_visited(proj);
688         }
689 }
690
691 /**
692  * Translate a DivMod.
693  *
694  * Create two intrinsic Calls.
695  */
696 static void lower_DivMod(ir_node *node, ir_mode *mode, lower_env_t *env) {
697         ir_node  *block, *proj, *irn, *mem, *callDiv, *callMod, *resDiv, *resMod;
698         ir_node  *in[4];
699         ir_mode  *opmode;
700         dbg_info *dbg;
701         ir_type  *mtp;
702         int      idx;
703         node_entry_t *entry;
704         unsigned flags = 0;
705
706         /* check if both results are needed */
707         for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
708                 switch (get_Proj_proj(proj)) {
709                 case pn_DivMod_res_div: flags |= 1; break;
710                 case pn_DivMod_res_mod: flags |= 2; break;
711                 default: break;
712                 }
713         }
714
715         irn   = get_DivMod_left(node);
716         entry = env->entries[get_irn_idx(irn)];
717         assert(entry);
718
719         if (! entry->low_word) {
720                 /* not ready yet, wait */
721                 pdeq_putr(env->waitq, node);
722                 return;
723         }
724
725         in[0] = entry->low_word;
726         in[1] = entry->high_word;
727
728         irn   = get_DivMod_right(node);
729         entry = env->entries[get_irn_idx(irn)];
730         assert(entry);
731
732         if (! entry->low_word) {
733                 /* not ready yet, wait */
734                 pdeq_putr(env->waitq, node);
735                 return;
736         }
737
738         in[2] = entry->low_word;
739         in[3] = entry->high_word;
740
741         dbg = get_irn_dbg_info(node);
742         block = get_nodes_block(node);
743
744         mem = get_DivMod_mem(node);
745
746         callDiv = callMod = NULL;
747         mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
748         if (flags & 1) {
749                 opmode = get_irn_op_mode(node);
750                 irn = get_intrinsic_address(mtp, op_Div, opmode, opmode, block, env);
751                 callDiv = new_rd_Call(dbg, current_ir_graph, block, mem,
752                         irn, 4, in, mtp);
753                 set_irn_pinned(callDiv, get_irn_pinned(node));
754                 resDiv = new_r_Proj(current_ir_graph, block, callDiv, mode_T, pn_Call_T_result);
755         }
756         if (flags & 2) {
757                 if (flags & 1)
758                         mem = new_r_Proj(current_ir_graph, block, callDiv, mode_M, pn_Call_M);
759                 opmode = get_irn_op_mode(node);
760                 irn = get_intrinsic_address(mtp, op_Mod, opmode, opmode, block, env);
761                 callMod = new_rd_Call(dbg, current_ir_graph, block, mem,
762                         irn, 4, in, mtp);
763                 set_irn_pinned(callMod, get_irn_pinned(node));
764                 resMod = new_r_Proj(current_ir_graph, block, callMod, mode_T, pn_Call_T_result);
765         }
766
767         for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
768                 switch (get_Proj_proj(proj)) {
769                 case pn_DivMod_M:         /* Memory result. */
770                         /* reroute to the first call */
771                         set_Proj_pred(proj, callDiv ? callDiv : (callMod ? callMod : mem));
772                         set_Proj_proj(proj, pn_Call_M_except);
773                         break;
774                 case pn_DivMod_X_except:  /* Execution result if exception occurred. */
775                         /* reroute to the first call */
776                         set_Proj_pred(proj, callDiv ? callDiv : (callMod ? callMod : mem));
777                         set_Proj_proj(proj, pn_Call_X_except);
778                         break;
779                 case pn_DivMod_res_div:   /* Result of Div. */
780                         idx = get_irn_idx(proj);
781                         assert(idx < env->n_entries);
782                         env->entries[idx]->low_word  = new_r_Proj(current_ir_graph, block, resDiv, mode, 0);
783                         env->entries[idx]->high_word = new_r_Proj(current_ir_graph, block, resDiv, mode, 1);
784                         break;
785                 case pn_DivMod_res_mod:   /* Result of Mod. */
786                         idx = get_irn_idx(proj);
787                         env->entries[idx]->low_word  = new_r_Proj(current_ir_graph, block, resMod, mode, 0);
788                         env->entries[idx]->high_word = new_r_Proj(current_ir_graph, block, resMod, mode, 1);
789                         break;
790                 default:
791                         assert(0 && "unexpected Proj number");
792                 }
793                 /* mark this proj: we have handled it already, otherwise we might fall into
794                  * out new nodes. */
795                 mark_irn_visited(proj);
796         }
797 }
798
799 /**
800  * Translate a Binop.
801  *
802  * Create an intrinsic Call.
803  */
804 static void lower_Binop(ir_node *node, ir_mode *mode, lower_env_t *env) {
805         ir_node  *block, *irn;
806         ir_node  *in[4];
807         dbg_info *dbg;
808         ir_type  *mtp;
809         int      idx;
810         node_entry_t *entry;
811
812         irn   = get_binop_left(node);
813         entry = env->entries[get_irn_idx(irn)];
814         assert(entry);
815
816         if (! entry->low_word) {
817                 /* not ready yet, wait */
818                 pdeq_putr(env->waitq, node);
819                 return;
820         }
821
822         in[0] = entry->low_word;
823         in[1] = entry->high_word;
824
825         irn   = get_binop_right(node);
826         entry = env->entries[get_irn_idx(irn)];
827         assert(entry);
828
829         if (! entry->low_word) {
830                 /* not ready yet, wait */
831                 pdeq_putr(env->waitq, node);
832                 return;
833         }
834
835         in[2] = entry->low_word;
836         in[3] = entry->high_word;
837
838         dbg = get_irn_dbg_info(node);
839         block = get_nodes_block(node);
840
841         mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
842         irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, block, env);
843         irn = new_rd_Call(dbg, current_ir_graph, block, get_irg_no_mem(current_ir_graph),
844                 irn, 4, in, mtp);
845         set_irn_pinned(irn, get_irn_pinned(node));
846         irn = new_r_Proj(current_ir_graph, block, irn, mode_T, pn_Call_T_result);
847
848         idx = get_irn_idx(node);
849         assert(idx < env->n_entries);
850         env->entries[idx]->low_word  = new_r_Proj(current_ir_graph, block, irn, mode, 0);
851         env->entries[idx]->high_word = new_r_Proj(current_ir_graph, block, irn, mode, 1);
852 }
853
854 /**
855  * Translate an Unop.
856  *
857  * Create an intrinsic Call.
858  */
859 static void lower_Unop(ir_node *node, ir_mode *mode, lower_env_t *env) {
860         ir_node  *block, *irn;
861         ir_node  *in[2];
862         dbg_info *dbg;
863         ir_type  *mtp;
864         int      idx;
865         node_entry_t *entry;
866
867         irn   = get_unop_op(node);
868         entry = env->entries[get_irn_idx(irn)];
869         assert(entry);
870
871         if (! entry->low_word) {
872                 /* not ready yet, wait */
873                 pdeq_putr(env->waitq, node);
874                 return;
875         }
876
877         in[0] = entry->low_word;
878         in[1] = entry->high_word;
879
880         dbg = get_irn_dbg_info(node);
881         block = get_nodes_block(node);
882
883         mtp = mode_is_signed(mode) ? unop_tp_s : unop_tp_u;
884         irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, block, env);
885         irn = new_rd_Call(dbg, current_ir_graph, block, get_irg_no_mem(current_ir_graph),
886                 irn, 2, in, mtp);
887         set_irn_pinned(irn, get_irn_pinned(node));
888         irn = new_r_Proj(current_ir_graph, block, irn, mode_T, pn_Call_T_result);
889
890         idx = get_irn_idx(node);
891         assert(idx < env->n_entries);
892         env->entries[idx]->low_word  = new_r_Proj(current_ir_graph, block, irn, mode, 0);
893         env->entries[idx]->high_word = new_r_Proj(current_ir_graph, block, irn, mode, 1);
894 }
895
896 /**
897  * Translate a logical Binop.
898  *
899  * Create two logical Binops.
900  */
901 static void lower_Binop_logical(ir_node *node, ir_mode *mode, lower_env_t *env,
902                                                                 ir_node *(*constr_rd)(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) ) {
903         ir_node  *block, *irn;
904         ir_node  *lop_l, *lop_h, *rop_l, *rop_h;
905         dbg_info *dbg;
906         int      idx;
907         node_entry_t *entry;
908
909         irn   = get_binop_left(node);
910         entry = env->entries[get_irn_idx(irn)];
911         assert(entry);
912
913         if (! entry->low_word) {
914                 /* not ready yet, wait */
915                 pdeq_putr(env->waitq, node);
916                 return;
917         }
918
919         lop_l = entry->low_word;
920         lop_h = entry->high_word;
921
922         irn   = get_binop_right(node);
923         entry = env->entries[get_irn_idx(irn)];
924         assert(entry);
925
926         if (! entry->low_word) {
927                 /* not ready yet, wait */
928                 pdeq_putr(env->waitq, node);
929                 return;
930         }
931
932         rop_l = entry->low_word;
933         rop_h = entry->high_word;
934
935         dbg = get_irn_dbg_info(node);
936         block = get_nodes_block(node);
937
938         idx = get_irn_idx(node);
939         assert(idx < env->n_entries);
940         env->entries[idx]->low_word  = constr_rd(dbg, current_ir_graph, block, lop_l, rop_l, mode);
941         env->entries[idx]->high_word = constr_rd(dbg, current_ir_graph, block, lop_h, rop_h, mode);
942 }
943
944 /** create a logical operation tranformation */
945 #define lower_logical(op)                                                \
946 static void lower_##op(ir_node *node, ir_mode *mode, lower_env_t *env) { \
947         lower_Binop_logical(node, mode, env, new_rd_##op);                   \
948 }
949
950 lower_logical(And)
951 lower_logical(Or)
952 lower_logical(Eor)
953
954 /**
955  * Translate a Not.
956  *
957  * Create two logical Nots.
958  */
959 static void lower_Not(ir_node *node, ir_mode *mode, lower_env_t *env) {
960         ir_node  *block, *irn;
961         ir_node  *op_l, *op_h;
962         dbg_info *dbg;
963         int      idx;
964         node_entry_t *entry;
965
966         irn   = get_Not_op(node);
967         entry = env->entries[get_irn_idx(irn)];
968         assert(entry);
969
970         if (! entry->low_word) {
971                 /* not ready yet, wait */
972                 pdeq_putr(env->waitq, node);
973                 return;
974         }
975
976         op_l = entry->low_word;
977         op_h = entry->high_word;
978
979         dbg = get_irn_dbg_info(node);
980         block = get_nodes_block(node);
981
982         idx = get_irn_idx(node);
983         assert(idx < env->n_entries);
984         env->entries[idx]->low_word  = new_rd_Not(dbg, current_ir_graph, block, op_l, mode);
985         env->entries[idx]->high_word = new_rd_Not(dbg, current_ir_graph, block, op_h, mode);
986 }
987
988 /**
989  * Translate a Cond.
990  */
991 static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env) {
992         ir_node *cmp, *left, *right, *block;
993         ir_node *sel = get_Cond_selector(node);
994         ir_mode *m = get_irn_mode(sel);
995         int     idx;
996
997         if (m == mode_b) {
998                 node_entry_t *lentry, *rentry;
999                 ir_node  *proj, *projT = NULL, *projF = NULL;
1000                 ir_node  *new_bl, *cmpH, *cmpL, *irn;
1001                 ir_node  *projHF, *projHT;
1002                 ir_node  *dst_blk;
1003                 ir_graph *irg;
1004                 pn_Cmp   pnc;
1005                 dbg_info *dbg;
1006
1007                 cmp   = get_Proj_pred(sel);
1008                 left  = get_Cmp_left(cmp);
1009                 idx   = get_irn_idx(left);
1010                 lentry = env->entries[idx];
1011
1012                 if (! lentry)
1013                         /* a normal Cmp */
1014                         return;
1015
1016                 right = get_Cmp_right(cmp);
1017                 idx   = get_irn_idx(right);
1018                 rentry = env->entries[idx];
1019                 assert(rentry);
1020
1021                 if (! lentry->low_word || !rentry->low_word) {
1022                         /* not yet ready */
1023                         pdeq_putr(env->waitq, node);
1024                         return;
1025                 }
1026
1027                 /* all right, build the code */
1028                 for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
1029                         long proj_nr = get_Proj_proj(proj);
1030
1031                         if (proj_nr == pn_Cond_true) {
1032                                 assert(projT == NULL && "more than one Proj(true)");
1033                                 projT = proj;
1034                         }
1035                         else {
1036                                 assert(proj_nr == pn_Cond_false);
1037                                 assert(projF == NULL && "more than one Proj(false)");
1038                                 projF = proj;
1039                         }
1040                         mark_irn_visited(proj);
1041                 }
1042                 assert(projT && projF);
1043
1044                 /* create a new high compare */
1045                 block = get_nodes_block(cmp);
1046                 dbg   = get_irn_dbg_info(cmp);
1047                 irg   = current_ir_graph;
1048
1049                 cmpH = new_rd_Cmp(dbg, irg, block, lentry->high_word, rentry->high_word);
1050
1051                 pnc = get_Proj_proj(sel);
1052                 if (pnc == pn_Cmp_Eq) {
1053                         /* simple case:a == b <==> a_h == b_h && a_l == b_l */
1054                         pmap_entry *entry = pmap_find(env->proj_2_block, projF);
1055
1056                         assert(entry);
1057                         dst_blk = entry->value;
1058
1059                         irn = new_r_Proj(irg, block, cmpH, mode_b, pn_Cmp_Eq);
1060                         dbg = get_irn_dbg_info(node);
1061                         irn = new_rd_Cond(dbg, irg, block, irn);
1062
1063                         projHF = new_r_Proj(irg, block, irn, mode_X, pn_Cond_false);
1064                         mark_irn_visited(projHF);
1065                         exchange(projF, projHF);
1066
1067                         projHT = new_r_Proj(irg, block, irn, mode_X, pn_Cond_true);
1068                         mark_irn_visited(projHT);
1069
1070                         new_bl = new_r_Block(irg, 1, &projHT);
1071
1072                         dbg   = get_irn_dbg_info(cmp);
1073                         cmpL = new_rd_Cmp(dbg, irg, new_bl, lentry->low_word, rentry->low_word);
1074                         irn = new_r_Proj(irg, new_bl, cmpL, mode_b, pn_Cmp_Eq);
1075                         dbg = get_irn_dbg_info(node);
1076                         irn = new_rd_Cond(dbg, irg, new_bl, irn);
1077
1078                         proj = new_r_Proj(irg, new_bl, irn, mode_X, pn_Cond_false);
1079                         mark_irn_visited(proj);
1080                         add_block_cf_input(dst_blk, projHF, proj);
1081
1082                         proj = new_r_Proj(irg, new_bl, irn, mode_X, pn_Cond_true);
1083                         mark_irn_visited(proj);
1084                         exchange(projT, proj);
1085                 }
1086                 else if (pnc == pn_Cmp_Lg) {
1087                         /* simple case:a != b <==> a_h != b_h || a_l != b_l */
1088                         pmap_entry *entry = pmap_find(env->proj_2_block, projT);
1089
1090                         assert(entry);
1091                         dst_blk = entry->value;
1092
1093                         irn = new_r_Proj(irg, block, cmpH, mode_b, pn_Cmp_Lg);
1094                         dbg = get_irn_dbg_info(node);
1095                         irn = new_rd_Cond(dbg, irg, block, irn);
1096
1097                         projHT = new_r_Proj(irg, block, irn, mode_X, pn_Cond_true);
1098                         mark_irn_visited(projHT);
1099                         exchange(projT, projHT);
1100
1101                         projHF = new_r_Proj(irg, block, irn, mode_X, pn_Cond_false);
1102                         mark_irn_visited(projHF);
1103
1104                         new_bl = new_r_Block(irg, 1, &projHF);
1105
1106                         dbg   = get_irn_dbg_info(cmp);
1107                         cmpL = new_rd_Cmp(dbg, irg, new_bl, lentry->low_word, rentry->low_word);
1108                         irn = new_r_Proj(irg, new_bl, cmpL, mode_b, pn_Cmp_Lg);
1109                         dbg = get_irn_dbg_info(node);
1110                         irn = new_rd_Cond(dbg, irg, new_bl, irn);
1111
1112                         proj = new_r_Proj(irg, new_bl, irn, mode_X, pn_Cond_true);
1113                         mark_irn_visited(proj);
1114                         add_block_cf_input(dst_blk, projHT, proj);
1115
1116                         proj = new_r_Proj(irg, new_bl, irn, mode_X, pn_Cond_false);
1117                         mark_irn_visited(proj);
1118                         exchange(projF, proj);
1119                 }
1120                 else {
1121                         /* a rel b <==> a_h rel b_h || (a_h == b_h && a_l rel b_l) */
1122                         ir_node *dstT, *dstF, *newbl_eq, *newbl_l;
1123                         pmap_entry *entry;
1124
1125                         entry = pmap_find(env->proj_2_block, projT);
1126                         assert(entry);
1127                         dstT = entry->value;
1128
1129                         entry = pmap_find(env->proj_2_block, projF);
1130                         assert(entry);
1131                         dstF = entry->value;
1132
1133                         irn = new_r_Proj(irg, block, cmpH, mode_b, pnc);
1134                         dbg = get_irn_dbg_info(node);
1135                         irn = new_rd_Cond(dbg, irg, block, irn);
1136
1137                         projHT = new_r_Proj(irg, block, irn, mode_X, pn_Cond_true);
1138                         mark_irn_visited(projHT);
1139                         exchange(projT, projHT);
1140                         projT = projHT;
1141
1142                         projHF = new_r_Proj(irg, block, irn, mode_X, pn_Cond_false);
1143                         mark_irn_visited(projHF);
1144
1145                         newbl_eq = new_r_Block(irg, 1, &projHF);
1146
1147                         irn = new_r_Proj(irg, newbl_eq, cmpH, mode_b, pn_Cmp_Eq);
1148                         irn = new_rd_Cond(dbg, irg, newbl_eq, irn);
1149
1150                         proj = new_r_Proj(irg, newbl_eq, irn, mode_X, pn_Cond_false);
1151                         mark_irn_visited(proj);
1152                         exchange(projF, proj);
1153                         projF = proj;
1154
1155                         proj = new_r_Proj(irg, newbl_eq, irn, mode_X, pn_Cond_true);
1156                         mark_irn_visited(proj);
1157
1158                         newbl_l = new_r_Block(irg, 1, &proj);
1159
1160                         dbg   = get_irn_dbg_info(cmp);
1161                         cmpL = new_rd_Cmp(dbg, irg, newbl_l, lentry->low_word, rentry->low_word);
1162                         irn = new_r_Proj(irg, newbl_l, cmpL, mode_b, pnc);
1163                         dbg = get_irn_dbg_info(node);
1164                         irn = new_rd_Cond(dbg, irg, newbl_l, irn);
1165
1166                         proj = new_r_Proj(irg, newbl_l, irn, mode_X, pn_Cond_true);
1167                         mark_irn_visited(proj);
1168                         add_block_cf_input(dstT, projT, proj);
1169
1170                         proj = new_r_Proj(irg, newbl_l, irn, mode_X, pn_Cond_false);
1171                         mark_irn_visited(proj);
1172                         add_block_cf_input(dstF, projF, proj);
1173                 }
1174
1175                 /* we have changed the control flow */
1176                 env->flags |= CF_CHANGED;
1177         }
1178         else {
1179                 idx = get_irn_idx(sel);
1180
1181                 if (env->entries[idx]) {
1182                         /*
1183                            Bad, a jump-table with double-word index.
1184                            This should not happen, but if it does we handle
1185                            it like a Conv were between (in other words, ignore
1186                            the high part.
1187                          */
1188
1189                         if (! env->entries[idx]->low_word) {
1190                                 /* not ready yet, wait */
1191                                 pdeq_putr(env->waitq, node);
1192                                 return;
1193                         }
1194                         set_Cond_selector(node, env->entries[idx]->low_word);
1195                 }
1196         }
1197 }
1198
1199 /**
1200  * Translate a Conv to higher_signed
1201  */
1202 static void lower_Conv_to_Ls(ir_node *node, lower_env_t *env) {
1203         ir_node  *op    = get_Conv_op(node);
1204         ir_mode  *imode = get_irn_mode(op);
1205         ir_mode  *dst_mode = env->params->low_signed;
1206         int      idx = get_irn_idx(node);
1207         ir_graph *irg = current_ir_graph;
1208         ir_node  *block = get_nodes_block(node);
1209         dbg_info *dbg = get_irn_dbg_info(node);
1210
1211         assert(idx < env->n_entries);
1212
1213         if (mode_is_int(imode) || mode_is_reference(imode)) {
1214                 /* simple case: create a high word */
1215                 if (imode != dst_mode)
1216                         op = new_rd_Conv(dbg, irg, block, op, dst_mode);
1217
1218                 env->entries[idx]->low_word  = op;
1219                 env->entries[idx]->high_word = new_rd_Shrs(dbg, irg, block, op,
1220                         new_Const_long(mode_Iu, get_mode_size_bits(dst_mode) - 1), dst_mode);
1221         }
1222         else {
1223                 ir_node *irn, *call;
1224                 ir_mode *omode = env->params->high_signed;
1225                 ir_type *mtp = get_conv_type(imode, omode, env);
1226
1227                 irn = get_intrinsic_address(mtp, get_irn_op(node), imode, omode, block, env);
1228                 call = new_rd_Call(dbg, irg, block, get_irg_no_mem(irg), irn, 1, &op, mtp);
1229                 set_irn_pinned(call, get_irn_pinned(node));
1230                 irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
1231
1232                 env->entries[idx]->low_word  = new_r_Proj(irg, block, irn, dst_mode, 0);
1233                 env->entries[idx]->high_word = new_r_Proj(irg, block, irn, dst_mode, 1);
1234         }
1235 }
1236
1237 /**
1238  * Translate a Conv to higher_unsigned
1239  */
1240 static void lower_Conv_to_Lu(ir_node *node, lower_env_t *env) {
1241         ir_node  *op    = get_Conv_op(node);
1242         ir_mode  *imode  = get_irn_mode(op);
1243         ir_mode  *dst_mode = env->params->low_unsigned;
1244         int      idx = get_irn_idx(node);
1245         ir_graph *irg = current_ir_graph;
1246         ir_node  *block = get_nodes_block(node);
1247         dbg_info *dbg = get_irn_dbg_info(node);
1248
1249         assert(idx < env->n_entries);
1250
1251         if (mode_is_int(imode) || mode_is_reference(imode)) {
1252                 /* simple case: create a high word */
1253                 if (imode != dst_mode)
1254                         op = new_rd_Conv(dbg, irg, block, op, dst_mode);
1255
1256                 env->entries[idx]->low_word  = op;
1257                 env->entries[idx]->high_word = new_Const(dst_mode, get_mode_null(dst_mode));
1258         }
1259         else {
1260                 ir_node *irn, *call;
1261                 ir_mode *omode = env->params->high_unsigned;
1262                 ir_type *mtp = get_conv_type(imode, omode, env);
1263
1264                 irn = get_intrinsic_address(mtp, get_irn_op(node), imode, omode, block, env);
1265                 call = new_rd_Call(dbg, irg, block, get_irg_no_mem(irg), irn, 1, &op, mtp);
1266                 set_irn_pinned(call, get_irn_pinned(node));
1267                 irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
1268
1269                 env->entries[idx]->low_word  = new_r_Proj(irg, block, irn, dst_mode, 0);
1270                 env->entries[idx]->high_word = new_r_Proj(irg, block, irn, dst_mode, 1);
1271         }
1272 }
1273
1274 /**
1275  * Translate a Conv from higher_signed
1276  */
1277 static void lower_Conv_from_Ls(ir_node *node, lower_env_t *env) {
1278         ir_node  *op    = get_Conv_op(node);
1279         ir_mode  *omode = get_irn_mode(node);
1280         ir_node  *block = get_nodes_block(node);
1281         dbg_info *dbg = get_irn_dbg_info(node);
1282         int      idx = get_irn_idx(op);
1283         ir_graph *irg = current_ir_graph;
1284
1285         assert(idx < env->n_entries);
1286
1287         if (mode_is_int(omode) || mode_is_reference(omode)) {
1288                 op = env->entries[idx]->low_word;
1289
1290                 /* simple case: create a high word */
1291                 if (omode != env->params->low_signed)
1292                         op = new_rd_Conv(dbg, irg, block, op, omode);
1293
1294                 set_Conv_op(node, op);
1295         }
1296         else {
1297                 ir_node *irn, *call, *in[2];
1298                 ir_mode *imode = env->params->high_signed;
1299                 ir_type *mtp = get_conv_type(imode, omode, env);
1300
1301                 irn = get_intrinsic_address(mtp, get_irn_op(node), imode, omode, block, env);
1302                 in[0] = env->entries[idx]->low_word;
1303                 in[1] = env->entries[idx]->high_word;
1304
1305                 call = new_rd_Call(dbg, irg, block, get_irg_no_mem(irg), irn, 2, in, mtp);
1306                 set_irn_pinned(call, get_irn_pinned(node));
1307                 irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
1308
1309                 exchange(node, new_r_Proj(irg, block, irn, omode, 0));
1310         }
1311 }
1312
1313 /**
1314  * Translate a Conv from higher_unsigned
1315  */
1316 static void lower_Conv_from_Lu(ir_node *node, lower_env_t *env) {
1317         ir_node  *op    = get_Conv_op(node);
1318         ir_mode  *omode = get_irn_mode(node);
1319         ir_node  *block = get_nodes_block(node);
1320         dbg_info *dbg = get_irn_dbg_info(node);
1321         int      idx = get_irn_idx(op);
1322         ir_graph *irg = current_ir_graph;
1323
1324         assert(idx < env->n_entries);
1325
1326         if (mode_is_int(omode) || mode_is_reference(omode)) {
1327                 op = env->entries[idx]->low_word;
1328
1329                 /* simple case: create a high word */
1330                 if (omode != env->params->low_unsigned)
1331                         op = new_rd_Conv(dbg, irg, block, op, omode);
1332
1333                 set_Conv_op(node, op);
1334         }
1335         else {
1336                 ir_node *irn, *call, *in[2];
1337                 ir_mode *imode = env->params->high_unsigned;
1338                 ir_type *mtp = get_conv_type(imode, omode, env);
1339
1340                 irn = get_intrinsic_address(mtp, get_irn_op(node), imode, omode, block, env);
1341                 in[0] = env->entries[idx]->low_word;
1342                 in[1] = env->entries[idx]->high_word;
1343
1344                 call = new_rd_Call(dbg, irg, block, get_irg_no_mem(irg), irn, 2, in, mtp);
1345                 set_irn_pinned(call, get_irn_pinned(node));
1346                 irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
1347
1348                 exchange(node, new_r_Proj(irg, block, irn, omode, 0));
1349         }
1350 }
1351
1352 /**
1353  * Translate a Conv.
1354  */
1355 static void lower_Conv(ir_node *node, ir_mode *mode, lower_env_t *env) {
1356         mode = get_irn_mode(node);
1357
1358         if (mode == env->params->high_signed)
1359                 lower_Conv_to_Ls(node, env);
1360         else if (mode == env->params->high_unsigned)
1361                 lower_Conv_to_Lu(node, env);
1362         else {
1363                 ir_mode *mode = get_irn_mode(get_Conv_op(node));
1364
1365                 if (mode == env->params->high_signed)
1366                         lower_Conv_from_Ls(node, env);
1367                 else {
1368                         assert(mode == env->params->high_unsigned);
1369                         lower_Conv_from_Lu(node, env);
1370                 }
1371         }
1372 }
1373
1374 /**
1375  * Lower the method type.
1376  */
1377 static ir_type *lower_mtp(ir_type *mtp, lower_env_t *env) {
1378         pmap_entry *entry;
1379         ident      *id;
1380         ir_type    *res;
1381
1382         if (is_lowered_type(mtp))
1383                 return mtp;
1384
1385         entry = pmap_find(lowered_type, mtp);
1386         if (! entry) {
1387                 int i, n, r, n_param, n_res;
1388
1389                 /* count new number of params */
1390                 n_param = n = get_method_n_params(mtp);
1391                 for (i = n_param - 1; i >= 0; --i) {
1392                         ir_type *tp = get_method_param_type(mtp, i);
1393
1394                         if (is_Primitive_type(tp)) {
1395                                 ir_mode *mode = get_type_mode(tp);
1396
1397                                 if (mode == env->params->high_signed ||
1398                                         mode == env->params->high_unsigned)
1399                                         ++n_param;
1400                         }
1401                 }
1402
1403                 /* count new number of results */
1404                 n_res = r = get_method_n_ress(mtp);
1405                 for (i = n_res - 1; i >= 0; --i) {
1406                         ir_type *tp = get_method_res_type(mtp, i);
1407
1408                         if (is_Primitive_type(tp)) {
1409                                 ir_mode *mode = get_type_mode(tp);
1410
1411                                 if (mode == env->params->high_signed ||
1412                                         mode == env->params->high_unsigned)
1413                                         ++n_res;
1414                         }
1415                 }
1416
1417                 id = mangle_u(new_id_from_chars("L", 1), get_type_ident(mtp));
1418                 res = new_type_method(id, n_param, n_res);
1419
1420                 /* set param types and result types */
1421                 for (i = n_param = 0; i < n; ++i) {
1422                         ir_type *tp = get_method_param_type(mtp, i);
1423
1424                         if (is_Primitive_type(tp)) {
1425                                 ir_mode *mode = get_type_mode(tp);
1426
1427                                 if (mode == env->params->high_signed) {
1428                                         set_method_param_type(res, n_param++, tp_s);
1429                                         set_method_param_type(res, n_param++, tp_s);
1430                                 }
1431                                 else if (mode == env->params->high_unsigned) {
1432                                         set_method_param_type(res, n_param++, tp_u);
1433                                         set_method_param_type(res, n_param++, tp_u);
1434                                 }
1435                                 else
1436                                         set_method_param_type(res, n_param++, tp);
1437                         }
1438                         else
1439                                 set_method_param_type(res, n_param++, tp);
1440                 }
1441                 for (i = n_res = 0; i < r; ++i) {
1442                         ir_type *tp = get_method_res_type(mtp, i);
1443
1444                         if (is_Primitive_type(tp)) {
1445                                 ir_mode *mode = get_type_mode(tp);
1446
1447                                 if (mode == env->params->high_signed) {
1448                                         set_method_res_type(res, n_res++, tp_s);
1449                                         set_method_res_type(res, n_res++, tp_s);
1450                                 }
1451                                 else if (mode == env->params->high_unsigned) {
1452                                         set_method_res_type(res, n_res++, tp_u);
1453                                         set_method_res_type(res, n_res++, tp_u);
1454                                 }
1455                                 else
1456                                         set_method_res_type(res, n_res++, tp);
1457                         }
1458                         else
1459                                 set_method_res_type(res, n_res++, tp);
1460                 }
1461                 set_lowered_type(mtp, res);
1462                 pmap_insert(lowered_type, mtp, res);
1463         }
1464         else
1465                 res = entry->value;
1466         return res;
1467 }
1468
1469 /**
1470  * Translate a Return.
1471  */
1472 static void lower_Return(ir_node *node, ir_mode *mode, lower_env_t *env) {
1473         ir_graph *irg = current_ir_graph;
1474         entity   *ent = get_irg_entity(irg);
1475         ir_type  *mtp = get_entity_type(ent);
1476         ir_node  **in;
1477         int      i, j, n, idx;
1478         int      need_conv = 0;
1479
1480         /* check if this return must be lowered */
1481         for (i = 0, n = get_Return_n_ress(node); i < n; ++i) {
1482                 ir_node *pred = get_Return_res(node, i);
1483                 ir_mode *mode = get_irn_op_mode(pred);
1484
1485                 if (mode == env->params->high_signed ||
1486                         mode == env->params->high_unsigned) {
1487                         idx = get_irn_idx(pred);
1488                         if (! env->entries[idx]->low_word) {
1489                                 /* not ready yet, wait */
1490                                 pdeq_putr(env->waitq, node);
1491                                 return;
1492                         }
1493                         need_conv = 1;
1494                 }
1495         }
1496         if (! need_conv)
1497                 return;
1498
1499         ent = get_irg_entity(irg);
1500         mtp = get_entity_type(ent);
1501
1502         mtp = lower_mtp(mtp, env);
1503         set_entity_type(ent, mtp);
1504
1505         /* create a new in array */
1506         NEW_ARR_A(ir_node *, in, get_method_n_ress(mtp) + 1);
1507         in[0] = get_Return_mem(node);
1508
1509         for (j = i = 0, n = get_Return_n_ress(node); i < n; ++i) {
1510                 ir_node *pred = get_Return_res(node, i);
1511
1512                 idx = get_irn_idx(pred);
1513                 assert(idx < env->n_entries);
1514
1515                 if (env->entries[idx]) {
1516                         in[++j] = env->entries[idx]->low_word;
1517                         in[++j] = env->entries[idx]->high_word;
1518                 }
1519                 else
1520                         in[++j] = pred;
1521         }
1522
1523         set_irn_in(node, j+1, in);
1524 }
1525
1526 /**
1527  * Translate the parameters.
1528  */
1529 static void lower_Start(ir_node *node, ir_mode *mode, lower_env_t *env) {
1530         ir_graph *irg = current_ir_graph;
1531         entity   *ent = get_irg_entity(irg);
1532         ir_type  *tp  = get_entity_type(ent);
1533         ir_type  *mtp;
1534         long     *new_projs;
1535         int      i, j, n_params, rem;
1536         ir_node  *proj, *args;
1537
1538         if (is_lowered_type(tp))
1539                 mtp = get_associated_type(tp);
1540         else
1541                 mtp = tp;
1542
1543         assert(! is_lowered_type(mtp));
1544
1545         n_params = get_method_n_params(mtp);
1546         if (n_params <= 0)
1547                 return;
1548
1549         NEW_ARR_A(long, new_projs, n_params);
1550
1551         /* first check if we have parameters that must be fixed */
1552         for (i = j = 0; i < n_params; ++i, ++j) {
1553                 ir_type *tp = get_method_param_type(mtp, i);
1554
1555                 new_projs[i] = j;
1556                 if (is_Primitive_type(tp)) {
1557                         ir_mode *mode = get_type_mode(tp);
1558
1559                         if (mode == env->params->high_signed ||
1560                                 mode == env->params->high_unsigned)
1561                                 ++j;
1562                 }
1563         }
1564         if (i == j)
1565                 return;
1566
1567         mtp = lower_mtp(mtp, env);
1568         set_entity_type(ent, mtp);
1569
1570         /* switch off optimization for new Proj nodes or they might be CSE'ed
1571            with not patched one's */
1572         rem = get_optimize();
1573         set_optimize(0);
1574
1575         /* ok, fix all Proj's and create new ones */
1576         args = get_irg_args(irg);
1577         for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
1578                 ir_node *pred = get_Proj_pred(proj);
1579                 long proj_nr;
1580                 int idx;
1581                 ir_mode *mode;
1582                 dbg_info *dbg;
1583
1584                 /* do not visit this node again */
1585                 mark_irn_visited(proj);
1586
1587                 if (pred != args)
1588                         continue;
1589
1590                 proj_nr = get_Proj_proj(proj);
1591                 set_Proj_proj(proj, new_projs[proj_nr]);
1592
1593                 idx = get_irn_idx(proj);
1594                 if (env->entries[idx]) {
1595                         mode = get_irn_mode(proj);
1596
1597                         if (mode == env->params->high_signed)
1598                                 mode = env->params->low_signed;
1599                         else
1600                                 mode = env->params->high_signed;
1601
1602                         dbg = get_irn_dbg_info(proj);
1603                         env->entries[idx]->low_word  =
1604                                 new_rd_Proj(dbg, irg, get_nodes_block(proj), args, mode, new_projs[proj_nr]);
1605                         env->entries[idx]->high_word =
1606                                 new_rd_Proj(dbg, irg, get_nodes_block(proj), args, mode, new_projs[proj_nr] + 1);
1607                 }
1608         }
1609         set_optimize(rem);
1610 }
1611
1612 /**
1613  * Translate a Call.
1614  */
1615 static void lower_Call(ir_node *node, ir_mode *mode, lower_env_t *env) {
1616         ir_graph *irg = current_ir_graph;
1617         ir_type  *tp = get_Call_type(node);
1618         ir_type  *call_tp;
1619         ir_node  **in, *proj, *results;
1620         int      n_params, n_res, need_lower = 0;
1621         int      i, j;
1622         long     *res_numbers = NULL;
1623
1624         if (is_lowered_type(tp))
1625                 call_tp = get_associated_type(tp);
1626         else
1627                 call_tp = tp;
1628
1629         assert(! is_lowered_type(call_tp));
1630
1631         n_params = get_method_n_params(call_tp);
1632         for (i = 0; i < n_params; ++i) {
1633                 ir_type *tp = get_method_param_type(call_tp, i);
1634
1635                 if (is_Primitive_type(tp)) {
1636                         ir_mode *mode = get_type_mode(tp);
1637
1638                         if (mode == env->params->high_signed ||
1639                                 mode == env->params->high_unsigned) {
1640                                 need_lower = 1;
1641                                 break;
1642                         }
1643                 }
1644         }
1645         n_res = get_method_n_ress(call_tp);
1646         if (n_res > 0) {
1647                 NEW_ARR_A(long, res_numbers, n_res);
1648
1649                 for (i = j = 0; i < n_res; ++i, ++j) {
1650                         ir_type *tp = get_method_res_type(call_tp, i);
1651
1652                         res_numbers[i] = j;
1653                         if (is_Primitive_type(tp)) {
1654                                 ir_mode *mode = get_type_mode(tp);
1655
1656                                 if (mode == env->params->high_signed ||
1657                                         mode == env->params->high_unsigned) {
1658                                         need_lower = 1;
1659                                         ++j;
1660                                 }
1661                         }
1662                 }
1663         }
1664
1665         if (! need_lower)
1666                 return;
1667
1668         /* let's lower it */
1669         call_tp = lower_mtp(call_tp, env);
1670         set_Call_type(node, call_tp);
1671
1672         NEW_ARR_A(ir_node *, in, get_method_n_params(call_tp) + 2);
1673
1674         in[0] = get_Call_mem(node);
1675         in[1] = get_Call_ptr(node);
1676
1677         for (j = 2, i = 0; i < n_params; ++i) {
1678                 ir_node *pred = get_Call_param(node, i);
1679                 int     idx = get_irn_idx(pred);
1680
1681                 if (env->entries[idx]) {
1682                         if (! env->entries[idx]->low_word) {
1683                                 /* not ready yet, wait */
1684                                 pdeq_putr(env->waitq, node);
1685                                 return;
1686                         }
1687                         in[j++] = env->entries[idx]->low_word;
1688                         in[j++] = env->entries[idx]->high_word;
1689                 }
1690                 else
1691                         in[j++] = pred;
1692         }
1693
1694         set_irn_in(node, j, in);
1695
1696         /* fix the results */
1697         results = NULL;
1698         for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
1699                 long proj_nr = get_Proj_proj(proj);
1700
1701                 if (proj_nr == pn_Call_T_result && get_Proj_pred(proj) == node) {
1702                         /* found the result proj */
1703                         results = proj;
1704                         break;
1705                 }
1706         }
1707
1708         if (results) {          /* there are results */
1709                 int rem = get_optimize();
1710
1711                 /* switch off optimization for new Proj nodes or they might be CSE'ed
1712                    with not patched one's */
1713                 set_optimize(0);
1714                 for (i = j = 0, proj = get_irn_link(results); proj; proj = get_irn_link(proj), ++i, ++j) {
1715                         if (get_Proj_pred(proj) == results) {
1716                                 long proj_nr = get_Proj_proj(proj);
1717                                 int idx;
1718
1719                                 /* found a result */
1720                                 set_Proj_proj(proj, res_numbers[proj_nr]);
1721                                 idx = get_irn_idx(proj);
1722                                 if (env->entries[idx]) {
1723                                         ir_mode *mode = get_irn_mode(proj);
1724                                         dbg_info *dbg;
1725
1726                                         if (mode == env->params->high_signed)
1727                                                 mode = env->params->low_signed;
1728                                         else
1729                                                 mode = env->params->low_unsigned;
1730
1731                                         dbg = get_irn_dbg_info(proj);
1732                                         env->entries[idx]->low_word  =
1733                                                 new_rd_Proj(dbg, irg, get_nodes_block(proj), results, mode, res_numbers[proj_nr]);
1734                                         env->entries[idx]->high_word =
1735                                                 new_rd_Proj(dbg, irg, get_nodes_block(proj), results, mode, res_numbers[proj_nr] + 1);
1736                                 }
1737                                 mark_irn_visited(proj);
1738                         }
1739                 }
1740                 set_optimize(rem);
1741         }
1742 }
1743
1744 /**
1745  * Translate an Unknown into two.
1746  */
1747 static void lower_Unknown(ir_node *node, ir_mode *mode, lower_env_t *env) {
1748         int idx = get_irn_idx(node);
1749
1750         env->entries[idx]->low_word  =
1751         env->entries[idx]->high_word = new_r_Unknown(current_ir_graph, mode);
1752 }
1753
1754 /**
1755  * Translate a Phi.
1756  *
1757  * First step: just create two templates
1758  */
1759 static void lower_Phi(ir_node *phi, ir_mode *mode, lower_env_t *env) {
1760         ir_node  *block, *unk;
1761         ir_node  **inl, **inh;
1762         dbg_info *dbg;
1763         int      idx, i, arity = get_Phi_n_preds(phi);
1764         int      enq = 0;
1765
1766         idx = get_irn_idx(phi);
1767         if (env->entries[idx]->low_word) {
1768                 /* Phi nodes already build, check for inputs */
1769                 ir_node *phil = env->entries[idx]->low_word;
1770                 ir_node *phih = env->entries[idx]->high_word;
1771
1772                 for (i = 0; i < arity; ++i) {
1773                         ir_node *pred = get_Phi_pred(phi, i);
1774                         int     idx = get_irn_idx(pred);
1775
1776                         if (env->entries[idx]->low_word) {
1777                                 set_Phi_pred(phil, i, env->entries[idx]->low_word);
1778                                 set_Phi_pred(phil, i, env->entries[idx]->high_word);
1779                         }
1780                         else {
1781                                 /* still not ready */
1782                                 pdeq_putr(env->waitq, phi);
1783                                 return;
1784                         }
1785                 }
1786         }
1787
1788         /* first create a new in array */
1789         NEW_ARR_A(ir_node *, inl, arity);
1790         NEW_ARR_A(ir_node *, inh, arity);
1791         unk = new_r_Unknown(current_ir_graph, mode);
1792
1793         for (i = 0; i < arity; ++i) {
1794                 ir_node *pred = get_Phi_pred(phi, i);
1795                 int     idx = get_irn_idx(pred);
1796
1797                 if (env->entries[idx]->low_word) {
1798                         inl[i] = env->entries[idx]->low_word;
1799                         inh[i] = env->entries[idx]->high_word;
1800                 }
1801                 else {
1802                         inl[i] = unk;
1803                         inh[i] = unk;
1804                         enq = 1;
1805                 }
1806         }
1807
1808         dbg = get_irn_dbg_info(phi);
1809         block = get_nodes_block(phi);
1810
1811         idx = get_irn_idx(phi);
1812         assert(idx < env->n_entries);
1813         env->entries[idx]->low_word  = new_rd_Phi(dbg, current_ir_graph, block, arity, inl, mode);
1814         env->entries[idx]->high_word = new_rd_Phi(dbg, current_ir_graph, block, arity, inh, mode);
1815
1816         if (enq) {
1817                 /* not yet finished */
1818                 pdeq_putr(env->waitq, phi);
1819         }
1820 }
1821
1822 /**
1823  * check for opcodes that must always be lowered.
1824  */
1825 static int always_lower(opcode code) {
1826         switch (code) {
1827         case iro_Start:
1828         case iro_Call:
1829         case iro_Return:
1830         case iro_Cond:
1831                 return 1;
1832         default:
1833                 return 0;
1834         }
1835 }
1836
1837 /** The type of a lower function. */
1838 typedef void (*lower_func)(ir_node *node, ir_mode *mode, lower_env_t *env);
1839
1840 /**
1841  * lower a node.
1842  */
1843 static void lower_ops(ir_node *node, void *env)
1844 {
1845         lower_env_t  *lenv = env;
1846         node_entry_t *entry;
1847         int          idx = get_irn_idx(node);
1848
1849         entry = lenv->entries[idx];
1850         if (entry || always_lower(get_irn_opcode(node))) {
1851                 ir_op      *op = get_irn_op(node);
1852                 lower_func func = (lower_func)op->ops.generic;
1853
1854                 if (func) {
1855                         ir_mode *mode = get_irn_op_mode(node);
1856
1857                         if (mode == lenv->params->high_signed)
1858                                 mode = lenv->params->low_signed;
1859                         else
1860                                 mode = lenv->params->low_unsigned;
1861
1862                         DB((dbg, LEVEL_1, "  %+F\n", node));
1863                         func(node, mode, lenv);
1864                 }
1865         }
1866 }
1867
1868 #define IDENT(s)  new_id_from_chars(s, sizeof(s)-1)
1869
1870 /**
1871  * Compare two op_mode_entry_t's.
1872  */
1873 static int cmp_op_mode(const void *elt, const void *key, size_t size) {
1874         const op_mode_entry_t *e1 = elt;
1875         const op_mode_entry_t *e2 = key;
1876
1877         return (e1->op - e2->op) | (e1->imode - e2->imode) | (e1->omode - e2->omode);
1878 }
1879
1880 /**
1881  * Compare two conv_tp_entry_t's.
1882  */
1883 static int cmp_conv_tp(const void *elt, const void *key, size_t size) {
1884         const conv_tp_entry_t *e1 = elt;
1885         const conv_tp_entry_t *e2 = key;
1886
1887         return (e1->imode - e2->imode) | (e1->omode - e2->omode);
1888 }
1889
1890 /*
1891  * Do the lowering.
1892  */
1893 void lower_dw_ops(const lwrdw_param_t *param)
1894 {
1895         lower_env_t lenv;
1896         int i;
1897
1898         if (! param)
1899                 return;
1900
1901         if (! param->enable)
1902                 return;
1903
1904         FIRM_DBG_REGISTER(dbg, "firm.lower.dw");
1905
1906         assert(2 * get_mode_size_bits(param->low_signed)   == get_mode_size_bits(param->high_signed));
1907         assert(2 * get_mode_size_bits(param->low_unsigned) == get_mode_size_bits(param->high_unsigned));
1908         assert(get_mode_size_bits(param->low_signed) == get_mode_size_bits(param->low_unsigned));
1909
1910         if (! prim_types)
1911                 prim_types = pmap_create();
1912         if (! intrinsic_fkt)
1913                 intrinsic_fkt = new_set(cmp_op_mode, iro_MaxOpcode);
1914         if (! conv_types)
1915                 conv_types = new_set(cmp_conv_tp, 16);
1916         if (! lowered_type)
1917                 lowered_type = pmap_create();
1918
1919         if (! tp_u)
1920                 tp_u = get_primitive_type(param->low_unsigned);
1921         if (! tp_s)
1922                 tp_s = get_primitive_type(param->low_signed);
1923
1924
1925         if (! binop_tp_u) {
1926                 binop_tp_u = new_type_method(IDENT("binop_u_intrinsic"), 4, 2);
1927
1928                 set_method_param_type(binop_tp_u, 0, tp_u);
1929                 set_method_param_type(binop_tp_u, 1, tp_u);
1930                 set_method_param_type(binop_tp_u, 2, tp_u);
1931                 set_method_param_type(binop_tp_u, 3, tp_u);
1932                 set_method_res_type(binop_tp_u, 0, tp_u);
1933                 set_method_res_type(binop_tp_u, 1, tp_u);
1934         }
1935         if (! binop_tp_s) {
1936                 binop_tp_s = new_type_method(IDENT("binop_s_intrinsic"), 4, 2);
1937                 set_method_param_type(binop_tp_s, 0, tp_s);
1938                 set_method_param_type(binop_tp_s, 1, tp_s);
1939                 set_method_param_type(binop_tp_s, 2, tp_s);
1940                 set_method_param_type(binop_tp_s, 3, tp_s);
1941                 set_method_res_type(binop_tp_s, 0, tp_s);
1942                 set_method_res_type(binop_tp_s, 1, tp_s);
1943         }
1944         if (! unop_tp_u) {
1945                 unop_tp_u = new_type_method(IDENT("unop_u_intrinsic"), 2, 2);
1946                 set_method_param_type(unop_tp_u, 0, tp_u);
1947                 set_method_param_type(unop_tp_u, 1, tp_u);
1948                 set_method_res_type(unop_tp_u, 0, tp_u);
1949                 set_method_res_type(unop_tp_u, 1, tp_u);
1950         }
1951         if (! unop_tp_s) {
1952                 unop_tp_s = new_type_method(IDENT("unop_s_intrinsic"), 2, 2);
1953                 set_method_param_type(unop_tp_s, 0, tp_s);
1954                 set_method_param_type(unop_tp_s, 1, tp_s);
1955                 set_method_res_type(unop_tp_s, 0, tp_s);
1956                 set_method_res_type(unop_tp_s, 1, tp_s);
1957         }
1958
1959         lenv.tv_mode_bytes = new_tarval_from_long(get_mode_size_bytes(param->low_unsigned), mode_Iu);
1960         lenv.tv_mode_bits  = new_tarval_from_long(get_mode_size_bits(param->low_unsigned), mode_Iu);
1961         lenv.waitq         = new_pdeq();
1962         lenv.params        = param;
1963
1964         /* first clear the generic function pointer for all ops */
1965         clear_irp_opcodes_generic_func();
1966
1967 #define LOWER2(op, fkt)   op_##op->ops.generic = (op_func)fkt
1968 #define LOWER(op)         LOWER2(op, lower_##op)
1969 #define LOWER_BIN(op)     LOWER2(op, lower_Binop)
1970 #define LOWER_UN(op)      LOWER2(op, lower_Unop)
1971
1972         LOWER(Load);
1973         LOWER(Store);
1974         LOWER(Const);
1975         LOWER(And);
1976         LOWER(Or);
1977         LOWER(Eor);
1978         LOWER(Not);
1979         LOWER(Cond);
1980         LOWER(Return);
1981         LOWER(Call);
1982         LOWER(Unknown);
1983         LOWER(Phi);
1984         LOWER(Start);
1985
1986         LOWER_BIN(Add);
1987         LOWER_BIN(Sub);
1988         LOWER_BIN(Mul);
1989         LOWER_BIN(Shl);
1990         LOWER_BIN(Shr);
1991         LOWER_BIN(Shrs);
1992         LOWER_BIN(Rot);
1993         LOWER_UN(Minus);
1994         LOWER(DivMod);
1995         LOWER(Div);
1996         LOWER(Mod);
1997         LOWER_UN(Abs);
1998
1999         LOWER(Conv);
2000
2001 #undef LOWER_UN
2002 #undef LOWER_BIN
2003 #undef LOWER
2004 #undef LOWER2
2005
2006         /* transform all graphs */
2007         for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2008                 ir_graph *irg = get_irp_irg(i);
2009                 int n_idx;
2010
2011                 obstack_init(&lenv.obst);
2012
2013                 n_idx = get_irg_last_idx(irg);
2014                 lenv.n_entries = n_idx;
2015                 lenv.entries   = xmalloc(n_idx * sizeof(lenv.entries[0]));
2016                 memset(lenv.entries, 0, n_idx * sizeof(lenv.entries[0]));
2017
2018                 /* first step: link all nodes and allocate data */
2019                 lenv.flags = 0;
2020                 lenv.proj_2_block = pmap_create();
2021                 irg_walk_graph(irg, firm_clear_link, prepare_links, &lenv);
2022
2023                 if (lenv.flags & MUST_BE_LOWERED) {
2024                         DB((dbg, LEVEL_1, "Lowering graph %+F\n", irg));
2025
2026                         /* must do some work */
2027                         irg_walk_graph(irg, NULL, lower_ops, &lenv);
2028
2029                         /* last step: all waiting nodes */
2030                         DB((dbg, LEVEL_1, "finishing waiting nodes:\n"));
2031                         while (! pdeq_empty(lenv.waitq)) {
2032                                 ir_node *node = pdeq_getl(lenv.waitq);
2033
2034                                 lower_ops(node, &lenv);
2035                         }
2036
2037                         /* outs are invalid, we changed the graph */
2038                         set_irg_outs_inconsistent(irg);
2039
2040                         if (lenv.flags & CF_CHANGED) {
2041                                 /* control flow changed, dominance info is invalid */
2042                                 set_irg_doms_inconsistent(irg);
2043                                 set_irg_extblk_inconsistent(irg);
2044                                 set_irg_loopinfo_inconsistent(irg);
2045                         }
2046
2047                         dump_ir_block_graph(irg, "-dw");
2048                 }
2049                 pmap_destroy(lenv.proj_2_block);
2050                 free(lenv.entries);
2051                 obstack_free(&lenv.obst, NULL);
2052         }
2053         del_pdeq(lenv.waitq);
2054 }
2055
2056 /* Default implementation. */
2057 entity *def_create_intrinsic_fkt(ir_type *method, const ir_op *op,
2058                                  const ir_mode *imode, const ir_mode *omode,
2059                                  void *context)
2060 {
2061         char buf[64];
2062         ident *id;
2063         entity *ent;
2064
2065         if (imode == omode)
2066                 snprintf(buf, sizeof(buf), "__l%s%s", get_op_name(op), get_mode_name(imode));
2067         else
2068                 snprintf(buf, sizeof(buf), "__l%s%s%s", get_op_name(op),
2069                         get_mode_name(imode), get_mode_name(omode));
2070         id = new_id_from_str(buf);
2071
2072         ent = new_entity(get_glob_type(), id, method);
2073         set_entity_ld_ident(ent, get_entity_ident(ent));
2074         set_entity_visibility(ent, visibility_external_allocated);
2075         return ent;
2076 }