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