Rename arch_register_req_type_should_be_different to the more appropriate arch_regist...
[libfirm] / ir / lower / lower_dw.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   Lower Double word operations, ie 64bit -> 32bit, 32bit -> 16bit etc.
23  * @date    8.10.2004
24  * @author  Michael Beck
25  * @version $Id$
26  */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifdef HAVE_STRING_H
32 # include <string.h>
33 #endif
34 #ifdef HAVE_STDLIB_H
35 # include <stdlib.h>
36 #endif
37
38 #include <assert.h>
39
40 #include "lowering.h"
41 #include "irnode_t.h"
42 #include "irgraph_t.h"
43 #include "irmode_t.h"
44 #include "iropt_t.h"
45 #include "irgmod.h"
46 #include "tv_t.h"
47 #include "dbginfo_t.h"
48 #include "iropt_dbg.h"
49 #include "irflag_t.h"
50 #include "firmstat.h"
51 #include "irgwalk.h"
52 #include "ircons.h"
53 #include "irflag.h"
54 #include "irtools.h"
55 #include "debug.h"
56 #include "set.h"
57 #include "pmap.h"
58 #include "pdeq.h"
59 #include "irdump.h"
60 #include "xmalloc.h"
61
62 /** A map from mode to a primitive type. */
63 static pmap *prim_types;
64
65 /** A map from (op, imode, omode) to Intrinsic functions entities. */
66 static set *intrinsic_fkt;
67
68 /** A map from (imode, omode) to conv function types. */
69 static set *conv_types;
70
71 /** A map from a method type to its lowered type. */
72 static pmap *lowered_type;
73
74 /** The types for the binop and unop intrinsics. */
75 static ir_type *binop_tp_u, *binop_tp_s, *unop_tp_u, *unop_tp_s, *shiftop_tp_u, *shiftop_tp_s, *tp_s, *tp_u;
76
77 /** the debug handle */
78 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
79
80 /**
81  * An entry in the (op, imode, omode) -> entity map.
82  */
83 typedef struct _op_mode_entry {
84         const ir_op   *op;    /**< the op */
85         const ir_mode *imode; /**< the input mode */
86         const ir_mode *omode; /**< the output mode */
87         ir_entity     *ent;   /**< the associated entity of this (op, imode, omode) triple */
88 } op_mode_entry_t;
89
90 /**
91  * An entry in the (imode, omode) -> tp map.
92  */
93 typedef struct _conv_tp_entry {
94         const ir_mode *imode; /**< the input mode */
95         const ir_mode *omode; /**< the output mode */
96         ir_type       *mtd;   /**< the associated method type of this (imode, omode) pair */
97 } conv_tp_entry_t;
98
99 /**
100  * Every double word node will be replaced,
101  * we need some store to hold the replacement:
102  */
103 typedef struct _node_entry_t {
104         ir_node *low_word;    /**< the low word */
105         ir_node *high_word;   /**< the high word */
106 } node_entry_t;
107
108 enum lower_flags {
109         MUST_BE_LOWERED = 1,  /**< graph must be lowered */
110         CF_CHANGED      = 2,  /**< control flow was changed */
111 };
112
113 /**
114  * The lower environment.
115  */
116 typedef struct _lower_env_t {
117         node_entry_t **entries;       /**< entries per node */
118         struct obstack obst;          /**< an obstack holding the temporary data */
119         tarval   *tv_mode_bytes;      /**< a tarval containing the number of bytes in the lowered modes */
120         tarval   *tv_mode_bits;       /**< a tarval containing the number of bits in the lowered modes */
121         pdeq     *waitq;              /**< a wait queue of all nodes that must be handled later */
122         pmap     *proj_2_block;       /**< a map from ProjX to its destination blocks */
123         const lwrdw_param_t *params;  /**< transformation parameter */
124         unsigned flags;               /**< some flags */
125         int      n_entries;           /**< number of entries */
126 } lower_env_t;
127
128 /**
129  * Get a primitive mode for a mode.
130  */
131 static ir_type *get_primitive_type(ir_mode *mode) {
132         pmap_entry *entry = pmap_find(prim_types, mode);
133         ir_type *tp;
134         char buf[64];
135
136         if (entry)
137                 return entry->value;
138
139         snprintf(buf, sizeof(buf), "_prim_%s", get_mode_name(mode));
140         tp = new_type_primitive(new_id_from_str(buf), mode);
141
142         pmap_insert(prim_types, mode, tp);
143         return tp;
144 }  /* get_primitive_type */
145
146 /**
147  * Create a method type for a Conv emulation from imode to omode.
148  */
149 static ir_type *get_conv_type(ir_mode *imode, ir_mode *omode, lower_env_t *env) {
150         conv_tp_entry_t key, *entry;
151         ir_type *mtd;
152
153         key.imode = imode;
154         key.omode = omode;
155         key.mtd   = NULL;
156
157         entry = set_insert(conv_types, &key, sizeof(key), HASH_PTR(imode) ^ HASH_PTR(omode));
158         if (! entry->mtd) {
159                 int n_param = 1, n_res = 1;
160                 char buf[64];
161
162                 if (imode == env->params->high_signed || imode == env->params->high_unsigned)
163                         n_param = 2;
164                 if (omode == env->params->high_signed || omode == env->params->high_unsigned)
165                         n_res = 2;
166
167                 /* create a new one */
168                 snprintf(buf, sizeof(buf), "LConv%s%s", get_mode_name(imode), get_mode_name(omode));
169                 mtd = new_type_method(new_id_from_str(buf), n_param, n_res);
170
171                 /* set param types and result types */
172                 n_param = 0;
173                 if (imode == env->params->high_signed) {
174                         set_method_param_type(mtd, n_param++, tp_u);
175                         set_method_param_type(mtd, n_param++, tp_s);
176                 } else if (imode == env->params->high_unsigned) {
177                         set_method_param_type(mtd, n_param++, tp_u);
178                         set_method_param_type(mtd, n_param++, tp_u);
179                 } else {
180                         ir_type *tp = get_primitive_type(imode);
181                         set_method_param_type(mtd, n_param++, tp);
182                 }  /* if */
183
184                 n_res = 0;
185                 if (omode == env->params->high_signed) {
186                         set_method_res_type(mtd, n_res++, tp_u);
187                         set_method_res_type(mtd, n_res++, tp_s);
188                 } else if (omode == env->params->high_unsigned) {
189                         set_method_res_type(mtd, n_res++, tp_u);
190                         set_method_res_type(mtd, n_res++, tp_u);
191                 } else {
192                         ir_type *tp = get_primitive_type(omode);
193                         set_method_res_type(mtd, n_res++, tp);
194                 }  /* if */
195                 entry->mtd = mtd;
196         } else {
197                 mtd = entry->mtd;
198         }  /* if */
199         return mtd;
200 }  /* get_conv_type */
201
202 /**
203  * Add an additional control flow input to a block.
204  * Patch all Phi nodes. The new Phi inputs are copied from
205  * old input number nr.
206  */
207 static void add_block_cf_input_nr(ir_node *block, int nr, ir_node *cf)
208 {
209         int i, arity = get_irn_arity(block);
210         ir_node **in, *phi;
211
212         assert(nr < arity);
213
214         NEW_ARR_A(ir_node *, in, arity + 1);
215         for (i = 0; i < arity; ++i)
216                 in[i] = get_irn_n(block, i);
217         in[i] = cf;
218
219         set_irn_in(block, i + 1, in);
220
221         for (phi = get_irn_link(block); phi; phi = get_irn_link(phi)) {
222                 for (i = 0; i < arity; ++i)
223                         in[i] = get_irn_n(phi, i);
224                 in[i] = in[nr];
225                 set_irn_in(phi, i + 1, in);
226         }  /* for */
227 }  /* add_block_cf_input_nr */
228
229 /**
230  * Add an additional control flow input to a block.
231  * Patch all Phi nodes. The new Phi inputs are copied from
232  * old input from cf tmpl.
233  */
234 static void add_block_cf_input(ir_node *block, ir_node *tmpl, ir_node *cf)
235 {
236         int i, arity = get_irn_arity(block);
237         int nr = 0;
238
239         for (i = 0; i < arity; ++i) {
240                 if (get_irn_n(block, i) == tmpl) {
241                         nr = i;
242                         break;
243                 }  /* if */
244         }  /* for */
245         assert(i < arity);
246         add_block_cf_input_nr(block, nr, cf);
247 }  /* add_block_cf_input */
248
249 /**
250  * Return the "operational" mode of a Firm node.
251  */
252 static ir_mode *get_irn_op_mode(ir_node *node)
253 {
254         switch (get_irn_opcode(node)) {
255         case iro_Load:
256                 return get_Load_mode(node);
257         case iro_Store:
258                 return get_irn_mode(get_Store_value(node));
259         case iro_DivMod:
260                 return get_irn_mode(get_DivMod_left(node));
261         case iro_Div:
262                 return get_irn_mode(get_Div_left(node));
263         case iro_Mod:
264                 return get_irn_mode(get_Mod_left(node));
265         case iro_Cmp:
266                 return get_irn_mode(get_Cmp_left(node));
267         default:
268                 return get_irn_mode(node);
269         }  /* switch */
270 }  /* get_irn_op_mode */
271
272 /**
273  * Walker, prepare the node links.
274  */
275 static void prepare_links(ir_node *node, void *env)
276 {
277         lower_env_t  *lenv = env;
278         ir_mode      *mode = get_irn_op_mode(node);
279         node_entry_t *link;
280         int          i, idx;
281
282         if (mode == lenv->params->high_signed ||
283                 mode == lenv->params->high_unsigned) {
284                 /* ok, found a node that will be lowered */
285                 link = obstack_alloc(&lenv->obst, sizeof(*link));
286
287                 memset(link, 0, sizeof(*link));
288
289                 idx = get_irn_idx(node);
290                 if (idx >= lenv->n_entries) {
291                         /* enlarge: this happens only for Rotl nodes which is RARELY */
292                         int old = lenv->n_entries;
293                         int n_idx = idx + (idx >> 3);
294
295                         ARR_RESIZE(node_entry_t *, lenv->entries, n_idx);
296                         memset(&lenv->entries[old], 0, (n_idx - old) * sizeof(lenv->entries[0]));
297                         lenv->n_entries = n_idx;
298                 }
299                 lenv->entries[idx] = link;
300                 lenv->flags |= MUST_BE_LOWERED;
301         } else if (is_Conv(node)) {
302                 /* Conv nodes have two modes */
303                 ir_node *pred = get_Conv_op(node);
304                 mode = get_irn_mode(pred);
305
306                 if (mode == lenv->params->high_signed ||
307                         mode == lenv->params->high_unsigned) {
308                         /* must lower this node either but don't need a link */
309                         lenv->flags |= MUST_BE_LOWERED;
310                 }  /* if */
311                 return;
312         }  /* if */
313
314         if (is_Proj(node)) {
315                 /* link all Proj nodes to its predecessor:
316                    Note that Tuple Proj's and its Projs are linked either. */
317                 ir_node *pred = get_Proj_pred(node);
318
319                 set_irn_link(node, get_irn_link(pred));
320                 set_irn_link(pred, node);
321         } else if (is_Phi(node)) {
322                 /* link all Phi nodes to its block */
323                 ir_node *block = get_nodes_block(node);
324
325                 set_irn_link(node, get_irn_link(block));
326                 set_irn_link(block, node);
327         } else if (is_Block(node)) {
328                 /* fill the Proj -> Block map */
329                 for (i = get_Block_n_cfgpreds(node) - 1; i >= 0; --i) {
330                         ir_node *pred = get_Block_cfgpred(node, i);
331
332                         if (is_Proj(pred))
333                                 pmap_insert(lenv->proj_2_block, pred, node);
334                 }  /* for */
335         }  /* if */
336 }  /* prepare_links */
337
338 /**
339  * Translate a Constant: create two.
340  */
341 static void lower_Const(ir_node *node, ir_mode *mode, lower_env_t *env) {
342         tarval   *tv, *tv_l, *tv_h;
343         ir_node  *low, *high;
344         dbg_info *dbg = get_irn_dbg_info(node);
345         ir_node  *block = get_nodes_block(node);
346         int      idx;
347         ir_graph *irg = current_ir_graph;
348         ir_mode  *low_mode = env->params->low_unsigned;
349
350         tv   = get_Const_tarval(node);
351
352         tv_l = tarval_convert_to(tv, low_mode);
353         low  = new_rd_Const(dbg, irg, block, low_mode, tv_l);
354
355         tv_h = tarval_convert_to(tarval_shrs(tv, env->tv_mode_bits), mode);
356         high = new_rd_Const(dbg, irg, block, mode, tv_h);
357
358         idx = get_irn_idx(node);
359         assert(idx < env->n_entries);
360         env->entries[idx]->low_word  = low;
361         env->entries[idx]->high_word = high;
362 }  /* lower_Const */
363
364 /**
365  * Translate a Load: create two.
366  */
367 static void lower_Load(ir_node *node, ir_mode *mode, lower_env_t *env) {
368         ir_mode  *low_mode = env->params->low_unsigned;
369         ir_graph *irg = current_ir_graph;
370         ir_node  *adr = get_Load_ptr(node);
371         ir_node  *mem = get_Load_mem(node);
372         ir_node  *low, *high, *proj;
373         dbg_info *dbg;
374         ir_node  *block = get_nodes_block(node);
375         int      idx;
376
377         if (env->params->little_endian) {
378                 low  = adr;
379                 high = new_r_Add(irg, block, adr,
380                         new_r_Const(irg, block, get_tarval_mode(env->tv_mode_bytes), env->tv_mode_bytes),
381                         get_irn_mode(adr));
382         } else {
383                 low  = new_r_Add(irg, block, adr,
384                         new_r_Const(irg, block, get_tarval_mode(env->tv_mode_bytes), env->tv_mode_bytes),
385                         get_irn_mode(adr));
386                 high = adr;
387         }  /* if */
388
389         /* create two loads */
390         dbg  = get_irn_dbg_info(node);
391         low  = new_rd_Load(dbg, irg, block, mem,  low,  low_mode);
392         proj = new_r_Proj(irg, block, low, mode_M, pn_Load_M);
393         high = new_rd_Load(dbg, irg, block, proj, high, mode);
394
395         set_Load_volatility(low,  get_Load_volatility(node));
396         set_Load_volatility(high, get_Load_volatility(node));
397
398         idx = get_irn_idx(node);
399         assert(idx < env->n_entries);
400         env->entries[idx]->low_word  = low;
401         env->entries[idx]->high_word = high;
402
403         for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
404                 idx = get_irn_idx(proj);
405
406                 switch (get_Proj_proj(proj)) {
407                 case pn_Load_M:         /* Memory result. */
408                         /* put it to the second one */
409                         set_Proj_pred(proj, high);
410                         break;
411                 case pn_Load_X_except:  /* Execution result if exception occurred. */
412                         /* put it to the first one */
413                         set_Proj_pred(proj, low);
414                         break;
415                 case pn_Load_res:       /* Result of load operation. */
416                         assert(idx < env->n_entries);
417                         env->entries[idx]->low_word  = new_r_Proj(irg, block, low,  low_mode, pn_Load_res);
418                         env->entries[idx]->high_word = new_r_Proj(irg, block, high, mode,     pn_Load_res);
419                         break;
420                 default:
421                         assert(0 && "unexpected Proj number");
422                 }  /* switch */
423                 /* mark this proj: we have handled it already, otherwise we might fall into
424                  * out new nodes. */
425                 mark_irn_visited(proj);
426         }  /* for */
427 }  /* lower_Load */
428
429 /**
430  * Translate a Store: create two.
431  */
432 static void lower_Store(ir_node *node, ir_mode *mode, lower_env_t *env) {
433         ir_graph *irg;
434         ir_node  *block, *adr, *mem;
435         ir_node  *low, *high, *irn, *proj;
436         dbg_info *dbg;
437         int      idx;
438         node_entry_t *entry;
439         (void) node;
440         (void) mode;
441
442         irn = get_Store_value(node);
443         entry = env->entries[get_irn_idx(irn)];
444         assert(entry);
445
446         if (! entry->low_word) {
447                 /* not ready yet, wait */
448                 pdeq_putr(env->waitq, node);
449                 return;
450         }  /* if */
451
452         irg = current_ir_graph;
453         adr = get_Store_ptr(node);
454         mem = get_Store_mem(node);
455         block = get_nodes_block(node);
456
457         if (env->params->little_endian) {
458                 low  = adr;
459                 high = new_r_Add(irg, block, adr,
460                         new_r_Const(irg, block, get_tarval_mode(env->tv_mode_bytes), env->tv_mode_bytes),
461                         get_irn_mode(adr));
462         } else {
463                 low  = new_r_Add(irg, block, adr,
464                         new_r_Const(irg, block, get_tarval_mode(env->tv_mode_bytes), env->tv_mode_bytes),
465                         get_irn_mode(adr));
466                 high = adr;
467         }  /* if */
468
469         /* create two Stores */
470         dbg = get_irn_dbg_info(node);
471         low  = new_rd_Store(dbg, irg, block, mem, low,  entry->low_word);
472         proj = new_r_Proj(irg, block, low, mode_M, pn_Store_M);
473         high = new_rd_Store(dbg, irg, block, proj, high, entry->high_word);
474
475         set_Store_volatility(low,  get_Store_volatility(node));
476         set_Store_volatility(high, get_Store_volatility(node));
477
478         idx = get_irn_idx(node);
479         assert(idx < env->n_entries);
480         env->entries[idx]->low_word  = low;
481         env->entries[idx]->high_word = high;
482
483         for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
484                 idx = get_irn_idx(proj);
485
486                 switch (get_Proj_proj(proj)) {
487                 case pn_Store_M:         /* Memory result. */
488                         /* put it to the second one */
489                         set_Proj_pred(proj, high);
490                         break;
491                 case pn_Store_X_except:  /* Execution result if exception occurred. */
492                         /* put it to the first one */
493                         set_Proj_pred(proj, low);
494                         break;
495                 default:
496                         assert(0 && "unexpected Proj number");
497                 }  /* switch */
498                 /* mark this proj: we have handled it already, otherwise we might fall into
499                  * out new nodes. */
500                 mark_irn_visited(proj);
501         }  /* for */
502 }  /* lower_Store */
503
504 /**
505  * Return a node containing the address of the intrinsic emulation function.
506  *
507  * @param method  the method type of the emulation function
508  * @param op      the emulated ir_op
509  * @param imode   the input mode of the emulated opcode
510  * @param omode   the output mode of the emulated opcode
511  * @param block   where the new mode is created
512  * @param env     the lower environment
513  */
514 static ir_node *get_intrinsic_address(ir_type *method, ir_op *op,
515                                       ir_mode *imode, ir_mode *omode,
516                                       ir_node *block, lower_env_t *env) {
517         symconst_symbol sym;
518         ir_entity *ent;
519         op_mode_entry_t key, *entry;
520
521         key.op    = op;
522         key.imode = imode;
523         key.omode = omode;
524         key.ent   = NULL;
525
526         entry = set_insert(intrinsic_fkt, &key, sizeof(key),
527                                 HASH_PTR(op) ^ HASH_PTR(imode) ^ (HASH_PTR(omode) << 8));
528         if (! entry->ent) {
529                 /* create a new one */
530                 ent = env->params->create_intrinsic(method, op, imode, omode, env->params->ctx);
531
532                 assert(ent && "Intrinsic creator must return an entity");
533                 entry->ent = ent;
534         } else {
535                 ent = entry->ent;
536         }  /* if */
537         sym.entity_p = ent;
538         return new_r_SymConst(current_ir_graph, block, mode_P_code, sym, symconst_addr_ent);
539 }  /* get_intrinsic_address */
540
541 /**
542  * Translate a Div.
543  *
544  * Create an intrinsic Call.
545  */
546 static void lower_Div(ir_node *node, ir_mode *mode, lower_env_t *env) {
547         ir_node  *block, *irn, *call, *proj;
548         ir_node  *in[4];
549         ir_mode  *opmode;
550         dbg_info *dbg;
551         ir_type  *mtp;
552         int      idx;
553         ir_graph *irg;
554         node_entry_t *entry;
555
556         irn   = get_Div_left(node);
557         entry = env->entries[get_irn_idx(irn)];
558         assert(entry);
559
560         if (! entry->low_word) {
561                 /* not ready yet, wait */
562                 pdeq_putr(env->waitq, node);
563                 return;
564         }  /* if */
565
566         in[0] = entry->low_word;
567         in[1] = entry->high_word;
568
569         irn   = get_Div_right(node);
570         entry = env->entries[get_irn_idx(irn)];
571         assert(entry);
572
573         if (! entry->low_word) {
574                 /* not ready yet, wait */
575                 pdeq_putr(env->waitq, node);
576                 return;
577         }  /* if */
578
579         in[2] = entry->low_word;
580         in[3] = entry->high_word;
581
582         dbg   = get_irn_dbg_info(node);
583         block = get_nodes_block(node);
584         irg   = current_ir_graph;
585
586         mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
587         opmode = get_irn_op_mode(node);
588         irn = get_intrinsic_address(mtp, get_irn_op(node), opmode, opmode, block, env);
589         call = new_rd_Call(dbg, irg, block, get_Div_mem(node),
590                 irn, 4, in, mtp);
591         set_irn_pinned(call, get_irn_pinned(node));
592         irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
593
594         for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
595                 switch (get_Proj_proj(proj)) {
596                 case pn_Div_M:         /* Memory result. */
597                         /* reroute to the call */
598                         set_Proj_pred(proj, call);
599                         set_Proj_proj(proj, pn_Call_M_except);
600                         break;
601                 case pn_Div_X_except:  /* Execution result if exception occurred. */
602                         /* reroute to the call */
603                         set_Proj_pred(proj, call);
604                         set_Proj_proj(proj, pn_Call_X_except);
605                         break;
606                 case pn_Div_res:       /* Result of computation. */
607                         idx = get_irn_idx(proj);
608                         assert(idx < env->n_entries);
609                         env->entries[idx]->low_word  = new_r_Proj(current_ir_graph, block, irn, env->params->low_unsigned, 0);
610                         env->entries[idx]->high_word = new_r_Proj(current_ir_graph, block, irn, mode,                      1);
611                         break;
612                 default:
613                         assert(0 && "unexpected Proj number");
614                 }  /* switch */
615                 /* mark this proj: we have handled it already, otherwise we might fall into
616                  * out new nodes. */
617                 mark_irn_visited(proj);
618         }  /* for */
619 }  /* lower_Div */
620
621 /**
622  * Translate a Mod.
623  *
624  * Create an intrinsic Call.
625  */
626 static void lower_Mod(ir_node *node, ir_mode *mode, lower_env_t *env) {
627         ir_node  *block, *proj, *irn, *call;
628         ir_node  *in[4];
629         ir_mode  *opmode;
630         dbg_info *dbg;
631         ir_type  *mtp;
632         int      idx;
633         ir_graph *irg;
634         node_entry_t *entry;
635
636         irn   = get_Mod_left(node);
637         entry = env->entries[get_irn_idx(irn)];
638         assert(entry);
639
640         if (! entry->low_word) {
641                 /* not ready yet, wait */
642                 pdeq_putr(env->waitq, node);
643                 return;
644         }  /* if */
645
646         in[0] = entry->low_word;
647         in[1] = entry->high_word;
648
649         irn   = get_Mod_right(node);
650         entry = env->entries[get_irn_idx(irn)];
651         assert(entry);
652
653         if (! entry->low_word) {
654                 /* not ready yet, wait */
655                 pdeq_putr(env->waitq, node);
656                 return;
657         }  /* if */
658
659         in[2] = entry->low_word;
660         in[3] = entry->high_word;
661
662         dbg   = get_irn_dbg_info(node);
663         block = get_nodes_block(node);
664         irg   = current_ir_graph;
665
666         mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
667         opmode = get_irn_op_mode(node);
668         irn = get_intrinsic_address(mtp, get_irn_op(node), opmode, opmode, block, env);
669         call = new_rd_Call(dbg, irg, block, get_Mod_mem(node),
670                 irn, 4, in, mtp);
671         set_irn_pinned(call, get_irn_pinned(node));
672         irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
673
674         for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
675                 switch (get_Proj_proj(proj)) {
676                 case pn_Mod_M:         /* Memory result. */
677                         /* reroute to the call */
678                         set_Proj_pred(proj, call);
679                         set_Proj_proj(proj, pn_Call_M_except);
680                         break;
681                 case pn_Mod_X_except:  /* Execution result if exception occurred. */
682                         /* reroute to the call */
683                         set_Proj_pred(proj, call);
684                         set_Proj_proj(proj, pn_Call_X_except);
685                         break;
686                 case pn_Mod_res:       /* Result of computation. */
687                         idx = get_irn_idx(proj);
688                         assert(idx < env->n_entries);
689                         env->entries[idx]->low_word  = new_r_Proj(irg, block, irn, env->params->low_unsigned, 0);
690                         env->entries[idx]->high_word = new_r_Proj(irg, block, irn, mode,                      1);
691                         break;
692                 default:
693                         assert(0 && "unexpected Proj number");
694                 }  /* switch */
695                 /* mark this proj: we have handled it already, otherwise we might fall into
696                  * out new nodes. */
697                 mark_irn_visited(proj);
698         }  /* for */
699 }  /* lower_Mod */
700
701 /**
702  * Translate a DivMod.
703  *
704  * Create two intrinsic Calls.
705  */
706 static void lower_DivMod(ir_node *node, ir_mode *mode, lower_env_t *env) {
707         ir_node  *block, *proj, *irn, *mem, *callDiv, *callMod;
708         ir_node  *resDiv = NULL;
709         ir_node  *resMod = NULL;
710         ir_node  *in[4];
711         ir_mode  *opmode;
712         dbg_info *dbg;
713         ir_type  *mtp;
714         int      idx;
715         node_entry_t *entry;
716         unsigned flags = 0;
717         ir_graph *irg;
718
719         /* check if both results are needed */
720         for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
721                 switch (get_Proj_proj(proj)) {
722                 case pn_DivMod_res_div: flags |= 1; break;
723                 case pn_DivMod_res_mod: flags |= 2; break;
724                 default: break;
725                 }  /* switch */
726         }  /* for */
727
728         irn   = get_DivMod_left(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         }  /* if */
737
738         in[0] = entry->low_word;
739         in[1] = entry->high_word;
740
741         irn   = get_DivMod_right(node);
742         entry = env->entries[get_irn_idx(irn)];
743         assert(entry);
744
745         if (! entry->low_word) {
746                 /* not ready yet, wait */
747                 pdeq_putr(env->waitq, node);
748                 return;
749         }  /* if */
750
751         in[2] = entry->low_word;
752         in[3] = entry->high_word;
753
754         dbg   = get_irn_dbg_info(node);
755         block = get_nodes_block(node);
756         irg   = current_ir_graph;
757
758         mem = get_DivMod_mem(node);
759
760         callDiv = callMod = NULL;
761         mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
762         if (flags & 1) {
763                 opmode = get_irn_op_mode(node);
764                 irn = get_intrinsic_address(mtp, op_Div, opmode, opmode, block, env);
765                 callDiv = new_rd_Call(dbg, irg, block, mem,
766                         irn, 4, in, mtp);
767                 set_irn_pinned(callDiv, get_irn_pinned(node));
768                 resDiv = new_r_Proj(irg, block, callDiv, mode_T, pn_Call_T_result);
769         }  /* if */
770         if (flags & 2) {
771                 if (flags & 1)
772                         mem = new_r_Proj(irg, block, callDiv, mode_M, pn_Call_M);
773                 opmode = get_irn_op_mode(node);
774                 irn = get_intrinsic_address(mtp, op_Mod, opmode, opmode, block, env);
775                 callMod = new_rd_Call(dbg, irg, block, mem,
776                         irn, 4, in, mtp);
777                 set_irn_pinned(callMod, get_irn_pinned(node));
778                 resMod = new_r_Proj(irg, block, callMod, mode_T, pn_Call_T_result);
779         }  /* if */
780
781         for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
782                 switch (get_Proj_proj(proj)) {
783                 case pn_DivMod_M:         /* Memory result. */
784                         /* reroute to the first call */
785                         set_Proj_pred(proj, callDiv ? callDiv : (callMod ? callMod : mem));
786                         set_Proj_proj(proj, pn_Call_M_except);
787                         break;
788                 case pn_DivMod_X_except:  /* Execution result if exception occurred. */
789                         /* reroute to the first call */
790                         set_Proj_pred(proj, callDiv ? callDiv : (callMod ? callMod : mem));
791                         set_Proj_proj(proj, pn_Call_X_except);
792                         break;
793                 case pn_DivMod_res_div:   /* Result of Div. */
794                         idx = get_irn_idx(proj);
795                         assert(idx < env->n_entries);
796                         env->entries[idx]->low_word  = new_r_Proj(irg, block, resDiv, env->params->low_unsigned, 0);
797                         env->entries[idx]->high_word = new_r_Proj(irg, block, resDiv, mode,                      1);
798                         break;
799                 case pn_DivMod_res_mod:   /* Result of Mod. */
800                         idx = get_irn_idx(proj);
801                         env->entries[idx]->low_word  = new_r_Proj(irg, block, resMod, env->params->low_unsigned, 0);
802                         env->entries[idx]->high_word = new_r_Proj(irg, block, resMod, mode,                      1);
803                         break;
804                 default:
805                         assert(0 && "unexpected Proj number");
806                 }  /* switch */
807                 /* mark this proj: we have handled it already, otherwise we might fall into
808                  * out new nodes. */
809                 mark_irn_visited(proj);
810         }  /* for */
811 }  /* lower_DivMod */
812
813 /**
814  * Translate a Binop.
815  *
816  * Create an intrinsic Call.
817  */
818 static void lower_Binop(ir_node *node, ir_mode *mode, lower_env_t *env) {
819         ir_node  *block, *irn;
820         ir_node  *in[4];
821         dbg_info *dbg;
822         ir_type  *mtp;
823         int      idx;
824         ir_graph *irg;
825         node_entry_t *entry;
826
827         irn   = get_binop_left(node);
828         entry = env->entries[get_irn_idx(irn)];
829         assert(entry);
830
831         if (! entry->low_word) {
832                 /* not ready yet, wait */
833                 pdeq_putr(env->waitq, node);
834                 return;
835         }  /* if */
836
837         in[0] = entry->low_word;
838         in[1] = entry->high_word;
839
840         irn   = get_binop_right(node);
841         entry = env->entries[get_irn_idx(irn)];
842         assert(entry);
843
844         if (! entry->low_word) {
845                 /* not ready yet, wait */
846                 pdeq_putr(env->waitq, node);
847                 return;
848         }  /* if */
849
850         in[2] = entry->low_word;
851         in[3] = entry->high_word;
852
853         dbg   = get_irn_dbg_info(node);
854         block = get_nodes_block(node);
855         irg   = current_ir_graph;
856
857         mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
858         irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, block, env);
859         irn = new_rd_Call(dbg, irg, block, get_irg_no_mem(current_ir_graph),
860                 irn, 4, in, mtp);
861         set_irn_pinned(irn, get_irn_pinned(node));
862         irn = new_r_Proj(irg, block, irn, mode_T, pn_Call_T_result);
863
864         idx = get_irn_idx(node);
865         assert(idx < env->n_entries);
866         env->entries[idx]->low_word  = new_r_Proj(irg, block, irn, env->params->low_unsigned, 0);
867         env->entries[idx]->high_word = new_r_Proj(irg, block, irn, mode,                      1);
868 }  /* lower_Binop */
869
870 /**
871  * Translate a Shiftop.
872  *
873  * Create an intrinsic Call.
874  */
875 static void lower_Shiftop(ir_node *node, ir_mode *mode, lower_env_t *env) {
876         ir_node  *block, *irn;
877         ir_node  *in[3];
878         dbg_info *dbg;
879         ir_type  *mtp;
880         int      idx;
881         ir_graph *irg;
882         node_entry_t *entry;
883
884         irn   = get_binop_left(node);
885         entry = env->entries[get_irn_idx(irn)];
886         assert(entry);
887
888         if (! entry->low_word) {
889                 /* not ready yet, wait */
890                 pdeq_putr(env->waitq, node);
891                 return;
892         }  /* if */
893
894         in[0] = entry->low_word;
895         in[1] = entry->high_word;
896
897         /* The shift count is always mode_Iu in firm, so there is no need for lowering */
898         in[2] = get_binop_right(node);
899
900         dbg   = get_irn_dbg_info(node);
901         block = get_nodes_block(node);
902         irg  = current_ir_graph;
903
904         mtp = mode_is_signed(mode) ? shiftop_tp_s : shiftop_tp_u;
905         irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, block, env);
906         irn = new_rd_Call(dbg, irg, block, get_irg_no_mem(current_ir_graph),
907                 irn, 3, in, mtp);
908         set_irn_pinned(irn, get_irn_pinned(node));
909         irn = new_r_Proj(irg, block, irn, mode_T, pn_Call_T_result);
910
911         idx = get_irn_idx(node);
912         assert(idx < env->n_entries);
913         env->entries[idx]->low_word  = new_r_Proj(irg, block, irn, env->params->low_unsigned, 0);
914         env->entries[idx]->high_word = new_r_Proj(irg, block, irn, mode,                      1);
915 }  /* lower_Shiftop */
916
917 /**
918  * Translate a Shr and handle special cases.
919  */
920 static void lower_Shr(ir_node *node, ir_mode *mode, lower_env_t *env) {
921         ir_node  *right = get_Shr_right(node);
922         ir_graph *irg = current_ir_graph;
923
924         if (get_mode_arithmetic(mode) == irma_twos_complement && is_Const(right)) {
925                 tarval *tv = get_Const_tarval(right);
926
927                 if (tarval_is_long(tv) &&
928                     get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
929                         ir_node *block = get_nodes_block(node);
930                         ir_node *left = get_Shr_left(node);
931                         ir_node *c;
932                         long shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode);
933                         int idx = get_irn_idx(left);
934
935                         left = env->entries[idx]->high_word;
936                         idx = get_irn_idx(node);
937
938                         if (shf_cnt > 0) {
939                                 c = new_r_Const_long(irg, block, mode_Iu, shf_cnt);
940                                 env->entries[idx]->low_word = new_r_Shr(irg, block, left, c, mode);
941                         } else {
942                                 env->entries[idx]->low_word = left;
943                         }  /* if */
944                         env->entries[idx]->high_word = new_r_Const(irg, block, mode, get_mode_null(mode));
945
946                         return;
947                 }  /* if */
948         }  /* if */
949         lower_Shiftop(node, mode, env);
950 }  /* lower_Shr */
951
952 /**
953  * Translate a Shl and handle special cases.
954  */
955 static void lower_Shl(ir_node *node, ir_mode *mode, lower_env_t *env) {
956         ir_node  *right = get_Shl_right(node);
957         ir_graph *irg = current_ir_graph;
958
959         if (get_mode_arithmetic(mode) == irma_twos_complement && is_Const(right)) {
960                 tarval *tv = get_Const_tarval(right);
961
962                 if (tarval_is_long(tv) &&
963                     get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
964                         ir_mode *mode_l;
965                         ir_node *block = get_nodes_block(node);
966                         ir_node *left = get_Shl_left(node);
967                         ir_node *c;
968                         long shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode);
969                         int idx = get_irn_idx(left);
970
971                         left = new_r_Conv(irg, block, env->entries[idx]->low_word, mode);
972                         idx = get_irn_idx(node);
973
974                         if (shf_cnt > 0) {
975                                 c = new_r_Const_long(irg, block, mode_Iu, shf_cnt);
976                                 env->entries[idx]->high_word = new_r_Shl(irg, block, left, c, mode);
977                         } else {
978                                 env->entries[idx]->high_word = left;
979                         }  /* if */
980                         mode_l = env->params->low_unsigned;
981                         env->entries[idx]->low_word  = new_r_Const(irg, block, mode_l, get_mode_null(mode_l));
982
983                         return;
984                 }  /* if */
985         }  /* if */
986         lower_Shiftop(node, mode, env);
987 }  /* lower_Shl */
988
989 /**
990  * Translate a Shrs and handle special cases.
991  */
992 static void lower_Shrs(ir_node *node, ir_mode *mode, lower_env_t *env) {
993         ir_node  *right = get_Shrs_right(node);
994         ir_graph *irg = current_ir_graph;
995
996         if (get_mode_arithmetic(mode) == irma_twos_complement && is_Const(right)) {
997                 tarval *tv = get_Const_tarval(right);
998
999                 if (tarval_is_long(tv) &&
1000                     get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
1001                         ir_node *block = get_nodes_block(node);
1002                         ir_node *left = get_Shrs_left(node);
1003                         long shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode);
1004                         ir_node *c;
1005                         int idx = get_irn_idx(left);
1006
1007                         left = env->entries[idx]->high_word;
1008                         idx = get_irn_idx(node);
1009
1010                         if (shf_cnt > 0) {
1011                                 ir_node *tmp;
1012                                 c = new_r_Const_long(irg, block, mode_Iu, shf_cnt);
1013                                 tmp = new_r_Shrs(irg, block, left, c, mode);
1014                                 /* low word is expected to have mode_Iu */
1015                                 env->entries[idx]->low_word = new_r_Conv(irg, block, tmp, mode_Iu);
1016                         } else {
1017                                 env->entries[idx]->low_word = left;
1018                         }  /* if */
1019                         c = new_r_Const_long(irg, block, mode_Iu, get_mode_size_bits(mode) - 1);
1020                         env->entries[idx]->high_word = new_r_Shrs(irg, block, left, c, mode);
1021
1022                         return;
1023                 }  /* if */
1024         }  /* if */
1025         lower_Shiftop(node, mode, env);
1026 }  /* lower_Shrs */
1027
1028 /**
1029  * Rebuild Rotl nodes into Or(Shl, Shr) and prepare all nodes.
1030  */
1031 static void prepare_links_and_handle_rotl(ir_node *node, void *env) {
1032         lower_env_t *lenv = env;
1033
1034         if (is_Rotl(node)) {
1035                 ir_mode *mode = get_irn_op_mode(node);
1036                         if (mode == lenv->params->high_signed ||
1037                             mode == lenv->params->high_unsigned) {
1038                                 ir_node  *right = get_Rotl_right(node);
1039                                 ir_node  *left, *shl, *shr, *or, *block, *sub, *c;
1040                                 ir_mode  *omode, *rmode;
1041                                 ir_graph *irg;
1042                                 dbg_info *dbg;
1043                                 optimization_state_t state;
1044
1045                                 if (get_mode_arithmetic(mode) == irma_twos_complement && is_Const(right)) {
1046                                         tarval *tv = get_Const_tarval(right);
1047
1048                                         if (tarval_is_long(tv) &&
1049                                             get_tarval_long(tv) == (long)get_mode_size_bits(mode)) {
1050                                                 /* will be optimized in lower_Rotl() */
1051                                                 return;
1052                                         }
1053                                 }
1054
1055                                 /* replace the Rotl(x,y) by an Or(Shl(x,y), Shr(x,64-y)) and lower those */
1056                                 dbg   = get_irn_dbg_info(node);
1057                                 omode = get_irn_mode(node);
1058                                 left  = get_Rotl_left(node);
1059                                 irg   = current_ir_graph;
1060                                 block = get_nodes_block(node);
1061                                 shl   = new_rd_Shl(dbg, irg, block, left, right, omode);
1062                                 rmode = get_irn_mode(right);
1063                                 c     = new_Const_long(rmode, get_mode_size_bits(omode));
1064                                 sub   = new_rd_Sub(dbg, irg, block, c, right, rmode);
1065                                 shr   = new_rd_Shr(dbg, irg, block, left, sub, omode);
1066
1067                                 /* optimization must be switched off here, or we will get the Rotl back */
1068                                 save_optimization_state(&state);
1069                                 set_opt_algebraic_simplification(0);
1070                                 or = new_rd_Or(dbg, irg, block, shl, shr, omode);
1071                                 restore_optimization_state(&state);
1072
1073                                 exchange(node, or);
1074
1075                                 /* do lowering on the new nodes */
1076                                 prepare_links(shl, env);
1077                                 prepare_links(c, env);
1078                                 prepare_links(sub, env);
1079                                 prepare_links(shr, env);
1080                                 prepare_links(or, env);
1081                         }
1082         } else {
1083                 prepare_links(node, env);
1084         }
1085 }
1086
1087 /**
1088  * Translate a special case Rotl(x, sizeof(w)).
1089  */
1090 static void lower_Rotl(ir_node *node, ir_mode *mode, lower_env_t *env) {
1091         ir_node *right = get_Rotl_right(node);
1092         ir_node *left = get_Rotl_left(node);
1093         ir_node *h, *l;
1094         int idx = get_irn_idx(left);
1095
1096         assert(get_mode_arithmetic(mode) == irma_twos_complement &&
1097                is_Const(right) && tarval_is_long(get_Const_tarval(right)) &&
1098                get_tarval_long(get_Const_tarval(right)) == (long)get_mode_size_bits(mode));
1099
1100         l = env->entries[idx]->low_word;
1101         h = env->entries[idx]->high_word;
1102         idx = get_irn_idx(node);
1103
1104         env->entries[idx]->low_word  = h;
1105         env->entries[idx]->high_word = l;
1106 }  /* lower_Rotl */
1107
1108 /**
1109  * Translate an Unop.
1110  *
1111  * Create an intrinsic Call.
1112  */
1113 static void lower_Unop(ir_node *node, ir_mode *mode, lower_env_t *env) {
1114         ir_node  *block, *irn;
1115         ir_node  *in[2];
1116         dbg_info *dbg;
1117         ir_type  *mtp;
1118         int      idx;
1119         ir_graph *irg;
1120         node_entry_t *entry;
1121
1122         irn   = get_unop_op(node);
1123         entry = env->entries[get_irn_idx(irn)];
1124         assert(entry);
1125
1126         if (! entry->low_word) {
1127                 /* not ready yet, wait */
1128                 pdeq_putr(env->waitq, node);
1129                 return;
1130         }  /* if */
1131
1132         in[0] = entry->low_word;
1133         in[1] = entry->high_word;
1134
1135         dbg   = get_irn_dbg_info(node);
1136         block = get_nodes_block(node);
1137         irg   = current_ir_graph;
1138
1139         mtp = mode_is_signed(mode) ? unop_tp_s : unop_tp_u;
1140         irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, block, env);
1141         irn = new_rd_Call(dbg, irg, block, get_irg_no_mem(current_ir_graph),
1142                 irn, 2, in, mtp);
1143         set_irn_pinned(irn, get_irn_pinned(node));
1144         irn = new_r_Proj(irg, block, irn, mode_T, pn_Call_T_result);
1145
1146         idx = get_irn_idx(node);
1147         assert(idx < env->n_entries);
1148         env->entries[idx]->low_word  = new_r_Proj(irg, block, irn, env->params->low_unsigned, 0);
1149         env->entries[idx]->high_word = new_r_Proj(irg, block, irn, mode,                      1);
1150 }  /* lower_Unop */
1151
1152 /**
1153  * Translate a logical Binop.
1154  *
1155  * Create two logical Binops.
1156  */
1157 static void lower_Binop_logical(ir_node *node, ir_mode *mode, lower_env_t *env,
1158                                                                 ir_node *(*constr_rd)(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) ) {
1159         ir_node  *block, *irn;
1160         ir_node  *lop_l, *lop_h, *rop_l, *rop_h;
1161         dbg_info *dbg;
1162         int      idx;
1163         ir_graph *irg;
1164         node_entry_t *entry;
1165
1166         irn   = get_binop_left(node);
1167         entry = env->entries[get_irn_idx(irn)];
1168         assert(entry);
1169
1170         if (! entry->low_word) {
1171                 /* not ready yet, wait */
1172                 pdeq_putr(env->waitq, node);
1173                 return;
1174         }  /* if */
1175
1176         lop_l = entry->low_word;
1177         lop_h = entry->high_word;
1178
1179         irn   = get_binop_right(node);
1180         entry = env->entries[get_irn_idx(irn)];
1181         assert(entry);
1182
1183         if (! entry->low_word) {
1184                 /* not ready yet, wait */
1185                 pdeq_putr(env->waitq, node);
1186                 return;
1187         }  /* if */
1188
1189         rop_l = entry->low_word;
1190         rop_h = entry->high_word;
1191
1192         dbg = get_irn_dbg_info(node);
1193         block = get_nodes_block(node);
1194
1195         idx = get_irn_idx(node);
1196         assert(idx < env->n_entries);
1197         irg = current_ir_graph;
1198         env->entries[idx]->low_word  = constr_rd(dbg, irg, block, lop_l, rop_l, env->params->low_unsigned);
1199         env->entries[idx]->high_word = constr_rd(dbg, irg, block, lop_h, rop_h, mode);
1200 }  /* lower_Binop_logical */
1201
1202 /** create a logical operation transformation */
1203 #define lower_logical(op)                                                \
1204 static void lower_##op(ir_node *node, ir_mode *mode, lower_env_t *env) { \
1205         lower_Binop_logical(node, mode, env, new_rd_##op);                   \
1206 }
1207
1208 lower_logical(And)
1209 lower_logical(Or)
1210 lower_logical(Eor)
1211
1212 /**
1213  * Translate a Not.
1214  *
1215  * Create two logical Nots.
1216  */
1217 static void lower_Not(ir_node *node, ir_mode *mode, lower_env_t *env) {
1218         ir_node  *block, *irn;
1219         ir_node  *op_l, *op_h;
1220         dbg_info *dbg;
1221         int      idx;
1222         ir_graph *irg;
1223         node_entry_t *entry;
1224
1225         irn   = get_Not_op(node);
1226         entry = env->entries[get_irn_idx(irn)];
1227         assert(entry);
1228
1229         if (! entry->low_word) {
1230                 /* not ready yet, wait */
1231                 pdeq_putr(env->waitq, node);
1232                 return;
1233         }  /* if */
1234
1235         op_l = entry->low_word;
1236         op_h = entry->high_word;
1237
1238         dbg   = get_irn_dbg_info(node);
1239         block = get_nodes_block(node);
1240         irg   = current_ir_graph;
1241
1242         idx = get_irn_idx(node);
1243         assert(idx < env->n_entries);
1244         env->entries[idx]->low_word  = new_rd_Not(dbg, current_ir_graph, block, op_l, env->params->low_unsigned);
1245         env->entries[idx]->high_word = new_rd_Not(dbg, current_ir_graph, block, op_h, mode);
1246 }  /* lower_Not */
1247
1248 /**
1249  * Translate a Cond.
1250  */
1251 static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env) {
1252         ir_node *cmp, *left, *right, *block;
1253         ir_node *sel = get_Cond_selector(node);
1254         ir_mode *m = get_irn_mode(sel);
1255         int     idx;
1256         (void) mode;
1257
1258         if (m == mode_b) {
1259                 node_entry_t *lentry, *rentry;
1260                 ir_node  *proj, *projT = NULL, *projF = NULL;
1261                 ir_node  *new_bl, *cmpH, *cmpL, *irn;
1262                 ir_node  *projHF, *projHT;
1263                 ir_node  *dst_blk;
1264                 ir_graph *irg;
1265                 pn_Cmp   pnc;
1266                 dbg_info *dbg;
1267
1268                 if(!is_Proj(sel))
1269                         return;
1270
1271                 cmp   = get_Proj_pred(sel);
1272                 if(!is_Cmp(cmp))
1273                         return;
1274
1275                 left  = get_Cmp_left(cmp);
1276                 idx   = get_irn_idx(left);
1277                 lentry = env->entries[idx];
1278
1279                 if (! lentry) {
1280                         /* a normal Cmp */
1281                         return;
1282                 }  /* if */
1283
1284                 right = get_Cmp_right(cmp);
1285                 idx   = get_irn_idx(right);
1286                 rentry = env->entries[idx];
1287                 assert(rentry);
1288
1289                 if (! lentry->low_word || !rentry->low_word) {
1290                         /* not yet ready */
1291                         pdeq_putr(env->waitq, node);
1292                         return;
1293                 }  /* if */
1294
1295                 /* all right, build the code */
1296                 for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
1297                         long proj_nr = get_Proj_proj(proj);
1298
1299                         if (proj_nr == pn_Cond_true) {
1300                                 assert(projT == NULL && "more than one Proj(true)");
1301                                 projT = proj;
1302                         } else {
1303                                 assert(proj_nr == pn_Cond_false);
1304                                 assert(projF == NULL && "more than one Proj(false)");
1305                                 projF = proj;
1306                         }  /* if */
1307                         mark_irn_visited(proj);
1308                 }  /* for */
1309                 assert(projT && projF);
1310
1311                 /* create a new high compare */
1312                 block = get_nodes_block(node);
1313                 dbg   = get_irn_dbg_info(cmp);
1314                 irg   = current_ir_graph;
1315                 pnc   = get_Proj_proj(sel);
1316
1317                 if (is_Const(right) && is_Const_null(right)) {
1318                         if (pnc == pn_Cmp_Eq || pnc == pn_Cmp_Lg) {
1319                                 /* x ==/!= 0 ==> or(low,high) ==/!= 0 */
1320                                 ir_mode *mode = env->params->low_unsigned;
1321                                 ir_node *low  = new_r_Conv(irg, block, lentry->low_word, mode);
1322                                 ir_node *high = new_r_Conv(irg, block, lentry->high_word, mode);
1323                                 ir_node *or   = new_rd_Or(dbg, irg, block, low, high, mode);
1324                                 ir_node *cmp  = new_rd_Cmp(dbg, irg, block, or, new_Const_long(mode, 0));
1325
1326                                 ir_node *proj = new_r_Proj(irg, block, cmp, mode_b, pnc);
1327                                 set_Cond_selector(node, proj);
1328                                 return;
1329                         }
1330                 }
1331
1332                 cmpH = new_rd_Cmp(dbg, irg, block, lentry->high_word, rentry->high_word);
1333
1334                 if (pnc == pn_Cmp_Eq) {
1335                         /* simple case:a == b <==> a_h == b_h && a_l == b_l */
1336                         pmap_entry *entry = pmap_find(env->proj_2_block, projF);
1337
1338                         assert(entry);
1339                         dst_blk = entry->value;
1340
1341                         irn = new_r_Proj(irg, block, cmpH, mode_b, pn_Cmp_Eq);
1342                         dbg = get_irn_dbg_info(node);
1343                         irn = new_rd_Cond(dbg, irg, block, irn);
1344
1345                         projHF = new_r_Proj(irg, block, irn, mode_X, pn_Cond_false);
1346                         mark_irn_visited(projHF);
1347                         exchange(projF, projHF);
1348
1349                         projHT = new_r_Proj(irg, block, irn, mode_X, pn_Cond_true);
1350                         mark_irn_visited(projHT);
1351
1352                         new_bl = new_r_Block(irg, 1, &projHT);
1353
1354                         dbg   = get_irn_dbg_info(cmp);
1355                         cmpL = new_rd_Cmp(dbg, irg, new_bl, lentry->low_word, rentry->low_word);
1356                         irn = new_r_Proj(irg, new_bl, cmpL, mode_b, pn_Cmp_Eq);
1357                         dbg = get_irn_dbg_info(node);
1358                         irn = new_rd_Cond(dbg, irg, new_bl, irn);
1359
1360                         proj = new_r_Proj(irg, new_bl, irn, mode_X, pn_Cond_false);
1361                         mark_irn_visited(proj);
1362                         add_block_cf_input(dst_blk, projHF, proj);
1363
1364                         proj = new_r_Proj(irg, new_bl, irn, mode_X, pn_Cond_true);
1365                         mark_irn_visited(proj);
1366                         exchange(projT, proj);
1367                 } else if (pnc == pn_Cmp_Lg) {
1368                         /* simple case:a != b <==> a_h != b_h || a_l != b_l */
1369                         pmap_entry *entry = pmap_find(env->proj_2_block, projT);
1370
1371                         assert(entry);
1372                         dst_blk = entry->value;
1373
1374                         irn = new_r_Proj(irg, block, cmpH, mode_b, pn_Cmp_Lg);
1375                         dbg = get_irn_dbg_info(node);
1376                         irn = new_rd_Cond(dbg, irg, block, irn);
1377
1378                         projHT = new_r_Proj(irg, block, irn, mode_X, pn_Cond_true);
1379                         mark_irn_visited(projHT);
1380                         exchange(projT, projHT);
1381
1382                         projHF = new_r_Proj(irg, block, irn, mode_X, pn_Cond_false);
1383                         mark_irn_visited(projHF);
1384
1385                         new_bl = new_r_Block(irg, 1, &projHF);
1386
1387                         dbg   = get_irn_dbg_info(cmp);
1388                         cmpL = new_rd_Cmp(dbg, irg, new_bl, lentry->low_word, rentry->low_word);
1389                         irn = new_r_Proj(irg, new_bl, cmpL, mode_b, pn_Cmp_Lg);
1390                         dbg = get_irn_dbg_info(node);
1391                         irn = new_rd_Cond(dbg, irg, new_bl, irn);
1392
1393                         proj = new_r_Proj(irg, new_bl, irn, mode_X, pn_Cond_true);
1394                         mark_irn_visited(proj);
1395                         add_block_cf_input(dst_blk, projHT, proj);
1396
1397                         proj = new_r_Proj(irg, new_bl, irn, mode_X, pn_Cond_false);
1398                         mark_irn_visited(proj);
1399                         exchange(projF, proj);
1400                 } else {
1401                         /* a rel b <==> a_h REL b_h || (a_h == b_h && a_l rel b_l) */
1402                         ir_node *dstT, *dstF, *newbl_eq, *newbl_l;
1403                         pmap_entry *entry;
1404
1405                         entry = pmap_find(env->proj_2_block, projT);
1406                         assert(entry);
1407                         dstT = entry->value;
1408
1409                         entry = pmap_find(env->proj_2_block, projF);
1410                         assert(entry);
1411                         dstF = entry->value;
1412
1413                         irn = new_r_Proj(irg, block, cmpH, mode_b, pnc & ~pn_Cmp_Eq);
1414                         dbg = get_irn_dbg_info(node);
1415                         irn = new_rd_Cond(dbg, irg, block, irn);
1416
1417                         projHT = new_r_Proj(irg, block, irn, mode_X, pn_Cond_true);
1418                         mark_irn_visited(projHT);
1419                         exchange(projT, projHT);
1420                         projT = projHT;
1421
1422                         projHF = new_r_Proj(irg, block, irn, mode_X, pn_Cond_false);
1423                         mark_irn_visited(projHF);
1424
1425                         newbl_eq = new_r_Block(irg, 1, &projHF);
1426
1427                         irn = new_r_Proj(irg, newbl_eq, cmpH, mode_b, pn_Cmp_Eq);
1428                         irn = new_rd_Cond(dbg, irg, newbl_eq, irn);
1429
1430                         proj = new_r_Proj(irg, newbl_eq, irn, mode_X, pn_Cond_false);
1431                         mark_irn_visited(proj);
1432                         exchange(projF, proj);
1433                         projF = proj;
1434
1435                         proj = new_r_Proj(irg, newbl_eq, irn, mode_X, pn_Cond_true);
1436                         mark_irn_visited(proj);
1437
1438                         newbl_l = new_r_Block(irg, 1, &proj);
1439
1440                         dbg   = get_irn_dbg_info(cmp);
1441                         cmpL = new_rd_Cmp(dbg, irg, newbl_l, lentry->low_word, rentry->low_word);
1442                         irn = new_r_Proj(irg, newbl_l, cmpL, mode_b, pnc);
1443                         dbg = get_irn_dbg_info(node);
1444                         irn = new_rd_Cond(dbg, irg, newbl_l, irn);
1445
1446                         proj = new_r_Proj(irg, newbl_l, irn, mode_X, pn_Cond_true);
1447                         mark_irn_visited(proj);
1448                         add_block_cf_input(dstT, projT, proj);
1449
1450                         proj = new_r_Proj(irg, newbl_l, irn, mode_X, pn_Cond_false);
1451                         mark_irn_visited(proj);
1452                         add_block_cf_input(dstF, projF, proj);
1453                 }  /* if */
1454
1455                 /* we have changed the control flow */
1456                 env->flags |= CF_CHANGED;
1457         } else {
1458                 idx = get_irn_idx(sel);
1459
1460                 if (env->entries[idx]) {
1461                         /*
1462                            Bad, a jump-table with double-word index.
1463                            This should not happen, but if it does we handle
1464                            it like a Conv were between (in other words, ignore
1465                            the high part.
1466                          */
1467
1468                         if (! env->entries[idx]->low_word) {
1469                                 /* not ready yet, wait */
1470                                 pdeq_putr(env->waitq, node);
1471                                 return;
1472                         }  /* if */
1473                         set_Cond_selector(node, env->entries[idx]->low_word);
1474                 }  /* if */
1475         }  /* if */
1476 }  /* lower_Cond */
1477
1478 /**
1479  * Translate a Conv to higher_signed
1480  */
1481 static void lower_Conv_to_Ls(ir_node *node, lower_env_t *env) {
1482         ir_node  *op    = get_Conv_op(node);
1483         ir_mode  *imode = get_irn_mode(op);
1484         ir_mode  *dst_mode_l = env->params->low_unsigned;
1485         ir_mode  *dst_mode_h = env->params->low_signed;
1486         int      idx = get_irn_idx(node);
1487         ir_graph *irg = current_ir_graph;
1488         ir_node  *block = get_nodes_block(node);
1489         dbg_info *dbg = get_irn_dbg_info(node);
1490
1491         assert(idx < env->n_entries);
1492
1493         if (mode_is_int(imode) || mode_is_reference(imode)) {
1494                 if (imode == env->params->high_unsigned) {
1495                         /* a Conv from Lu to Ls */
1496                         int op_idx = get_irn_idx(op);
1497
1498                         if (! env->entries[op_idx]->low_word) {
1499                                 /* not ready yet, wait */
1500                                 pdeq_putr(env->waitq, node);
1501                                 return;
1502                         }  /* if */
1503                         env->entries[idx]->low_word  = new_rd_Conv(dbg, irg, block, env->entries[op_idx]->low_word,  dst_mode_l);
1504                         env->entries[idx]->high_word = new_rd_Conv(dbg, irg, block, env->entries[op_idx]->high_word, dst_mode_h);
1505                 } else {
1506                         /* simple case: create a high word */
1507                         if (imode != dst_mode_l)
1508                                 op = new_rd_Conv(dbg, irg, block, op, dst_mode_l);
1509
1510                         env->entries[idx]->low_word  = op;
1511
1512                         if (mode_is_signed(imode)) {
1513                                 ir_node *op_conv = new_rd_Conv(dbg, irg, block, op, dst_mode_h);
1514                                 env->entries[idx]->high_word = new_rd_Shrs(dbg, irg, block, op_conv,
1515                                         new_Const_long(mode_Iu, get_mode_size_bits(dst_mode_h) - 1), dst_mode_h);
1516                         } else {
1517                                 env->entries[idx]->high_word = new_Const(dst_mode_h, get_mode_null(dst_mode_h));
1518                         }  /* if */
1519                 }  /* if */
1520         } else {
1521                 ir_node *irn, *call;
1522                 ir_mode *omode = env->params->high_signed;
1523                 ir_type *mtp = get_conv_type(imode, omode, env);
1524
1525                 irn = get_intrinsic_address(mtp, get_irn_op(node), imode, omode, block, env);
1526                 call = new_rd_Call(dbg, irg, block, get_irg_no_mem(irg), irn, 1, &op, mtp);
1527                 set_irn_pinned(call, get_irn_pinned(node));
1528                 irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
1529
1530                 env->entries[idx]->low_word  = new_r_Proj(irg, block, irn, dst_mode_l, 0);
1531                 env->entries[idx]->high_word = new_r_Proj(irg, block, irn, dst_mode_h, 1);
1532         }  /* if */
1533 }  /* lower_Conv_to_Ls */
1534
1535 /**
1536  * Translate a Conv to higher_unsigned
1537  */
1538 static void lower_Conv_to_Lu(ir_node *node, lower_env_t *env) {
1539         ir_node  *op    = get_Conv_op(node);
1540         ir_mode  *imode = get_irn_mode(op);
1541         ir_mode  *dst_mode = env->params->low_unsigned;
1542         int      idx = get_irn_idx(node);
1543         ir_graph *irg = current_ir_graph;
1544         ir_node  *block = get_nodes_block(node);
1545         dbg_info *dbg = get_irn_dbg_info(node);
1546
1547         assert(idx < env->n_entries);
1548
1549         if (mode_is_int(imode) || mode_is_reference(imode)) {
1550                 if (imode == env->params->high_signed) {
1551                         /* a Conv from Ls to Lu */
1552                         int op_idx = get_irn_idx(op);
1553
1554                         if (! env->entries[op_idx]->low_word) {
1555                                 /* not ready yet, wait */
1556                                 pdeq_putr(env->waitq, node);
1557                                 return;
1558                         }  /* if */
1559                         env->entries[idx]->low_word  = new_rd_Conv(dbg, irg, block, env->entries[op_idx]->low_word, dst_mode);
1560                         env->entries[idx]->high_word = new_rd_Conv(dbg, irg, block, env->entries[op_idx]->high_word, dst_mode);
1561                 } else {
1562                         /* simple case: create a high word */
1563                         if (imode != dst_mode)
1564                                 op = new_rd_Conv(dbg, irg, block, op, dst_mode);
1565
1566                         env->entries[idx]->low_word  = op;
1567
1568                         if (mode_is_signed(imode)) {
1569                                 env->entries[idx]->high_word = new_rd_Shrs(dbg, irg, block, op,
1570                                         new_Const_long(mode_Iu, get_mode_size_bits(dst_mode) - 1), dst_mode);
1571                         } else {
1572                                 env->entries[idx]->high_word = new_Const(dst_mode, get_mode_null(dst_mode));
1573                         }  /* if */
1574                 }  /* if */
1575         } else {
1576                 ir_node *irn, *call;
1577                 ir_mode *omode = env->params->high_unsigned;
1578                 ir_type *mtp = get_conv_type(imode, omode, env);
1579
1580                 /* do an intrinsic call */
1581                 irn = get_intrinsic_address(mtp, get_irn_op(node), imode, omode, block, env);
1582                 call = new_rd_Call(dbg, irg, block, get_irg_no_mem(irg), irn, 1, &op, mtp);
1583                 set_irn_pinned(call, get_irn_pinned(node));
1584                 irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
1585
1586                 env->entries[idx]->low_word  = new_r_Proj(irg, block, irn, dst_mode, 0);
1587                 env->entries[idx]->high_word = new_r_Proj(irg, block, irn, dst_mode, 1);
1588         }  /* if */
1589 }  /* lower_Conv_to_Lu */
1590
1591 /**
1592  * Translate a Conv from higher_signed
1593  */
1594 static void lower_Conv_from_Ls(ir_node *node, lower_env_t *env) {
1595         ir_node  *op    = get_Conv_op(node);
1596         ir_mode  *omode = get_irn_mode(node);
1597         ir_node  *block = get_nodes_block(node);
1598         dbg_info *dbg = get_irn_dbg_info(node);
1599         int      idx = get_irn_idx(op);
1600         ir_graph *irg = current_ir_graph;
1601
1602         assert(idx < env->n_entries);
1603
1604         if (! env->entries[idx]->low_word) {
1605                 /* not ready yet, wait */
1606                 pdeq_putr(env->waitq, node);
1607                 return;
1608         }  /* if */
1609
1610         if (mode_is_int(omode) || mode_is_reference(omode)) {
1611                 op = env->entries[idx]->low_word;
1612
1613                 /* simple case: create a high word */
1614                 if (omode != env->params->low_signed)
1615                         op = new_rd_Conv(dbg, irg, block, op, omode);
1616
1617                 set_Conv_op(node, op);
1618         } else {
1619                 ir_node *irn, *call, *in[2];
1620                 ir_mode *imode = env->params->high_signed;
1621                 ir_type *mtp = get_conv_type(imode, omode, env);
1622
1623                 irn = get_intrinsic_address(mtp, get_irn_op(node), imode, omode, block, env);
1624                 in[0] = env->entries[idx]->low_word;
1625                 in[1] = env->entries[idx]->high_word;
1626
1627                 call = new_rd_Call(dbg, irg, block, get_irg_no_mem(irg), irn, 2, in, mtp);
1628                 set_irn_pinned(call, get_irn_pinned(node));
1629                 irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
1630
1631                 exchange(node, new_r_Proj(irg, block, irn, omode, 0));
1632         }  /* if */
1633 }  /* lower_Conv_from_Ls */
1634
1635 /**
1636  * Translate a Conv from higher_unsigned
1637  */
1638 static void lower_Conv_from_Lu(ir_node *node, lower_env_t *env) {
1639         ir_node  *op    = get_Conv_op(node);
1640         ir_mode  *omode = get_irn_mode(node);
1641         ir_node  *block = get_nodes_block(node);
1642         dbg_info *dbg = get_irn_dbg_info(node);
1643         int      idx = get_irn_idx(op);
1644         ir_graph *irg = current_ir_graph;
1645
1646         assert(idx < env->n_entries);
1647
1648         if (! env->entries[idx]->low_word) {
1649                 /* not ready yet, wait */
1650                 pdeq_putr(env->waitq, node);
1651                 return;
1652         }  /* if */
1653
1654         if (mode_is_int(omode) || mode_is_reference(omode)) {
1655                 op = env->entries[idx]->low_word;
1656
1657                 /* simple case: create a high word */
1658                 if (omode != env->params->low_unsigned)
1659                         op = new_rd_Conv(dbg, irg, block, op, omode);
1660
1661                 set_Conv_op(node, op);
1662         } else {
1663                 ir_node *irn, *call, *in[2];
1664                 ir_mode *imode = env->params->high_unsigned;
1665                 ir_type *mtp = get_conv_type(imode, omode, env);
1666
1667                 irn = get_intrinsic_address(mtp, get_irn_op(node), imode, omode, block, env);
1668                 in[0] = env->entries[idx]->low_word;
1669                 in[1] = env->entries[idx]->high_word;
1670
1671                 call = new_rd_Call(dbg, irg, block, get_irg_no_mem(irg), irn, 2, in, mtp);
1672                 set_irn_pinned(call, get_irn_pinned(node));
1673                 irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
1674
1675                 exchange(node, new_r_Proj(irg, block, irn, omode, 0));
1676         }  /* if */
1677 }  /* lower_Conv_from_Lu */
1678
1679 /**
1680  * Translate a Conv.
1681  */
1682 static void lower_Conv(ir_node *node, ir_mode *mode, lower_env_t *env) {
1683         mode = get_irn_mode(node);
1684
1685         if (mode == env->params->high_signed) {
1686                 lower_Conv_to_Ls(node, env);
1687         } else if (mode == env->params->high_unsigned) {
1688                 lower_Conv_to_Lu(node, env);
1689         } else {
1690                 ir_mode *mode = get_irn_mode(get_Conv_op(node));
1691
1692                 if (mode == env->params->high_signed) {
1693                         lower_Conv_from_Ls(node, env);
1694                 } else if (mode == env->params->high_unsigned) {
1695                         lower_Conv_from_Lu(node, env);
1696                 }  /* if */
1697         }  /* if */
1698 }  /* lower_Conv */
1699
1700 /**
1701  * Lower the method type.
1702  */
1703 static ir_type *lower_mtp(ir_type *mtp, lower_env_t *env) {
1704         pmap_entry *entry;
1705         ident      *id;
1706         ir_type    *res;
1707
1708         if (is_lowered_type(mtp))
1709                 return mtp;
1710
1711         entry = pmap_find(lowered_type, mtp);
1712         if (! entry) {
1713                 int i, n, r, n_param, n_res;
1714
1715                 /* count new number of params */
1716                 n_param = n = get_method_n_params(mtp);
1717                 for (i = n_param - 1; i >= 0; --i) {
1718                         ir_type *tp = get_method_param_type(mtp, i);
1719
1720                         if (is_Primitive_type(tp)) {
1721                                 ir_mode *mode = get_type_mode(tp);
1722
1723                                 if (mode == env->params->high_signed ||
1724                                         mode == env->params->high_unsigned)
1725                                         ++n_param;
1726                         }  /* if */
1727                 }  /* for */
1728
1729                 /* count new number of results */
1730                 n_res = r = get_method_n_ress(mtp);
1731                 for (i = n_res - 1; i >= 0; --i) {
1732                         ir_type *tp = get_method_res_type(mtp, i);
1733
1734                         if (is_Primitive_type(tp)) {
1735                                 ir_mode *mode = get_type_mode(tp);
1736
1737                                 if (mode == env->params->high_signed ||
1738                                         mode == env->params->high_unsigned)
1739                                         ++n_res;
1740                         }  /* if */
1741                 }  /* for */
1742
1743                 id = mangle_u(new_id_from_chars("L", 1), get_type_ident(mtp));
1744                 res = new_type_method(id, n_param, n_res);
1745
1746                 /* set param types and result types */
1747                 for (i = n_param = 0; i < n; ++i) {
1748                         ir_type *tp = get_method_param_type(mtp, i);
1749
1750                         if (is_Primitive_type(tp)) {
1751                                 ir_mode *mode = get_type_mode(tp);
1752
1753                                 if (mode == env->params->high_signed) {
1754                                         set_method_param_type(res, n_param++, tp_u);
1755                                         set_method_param_type(res, n_param++, tp_s);
1756                                 } else if (mode == env->params->high_unsigned) {
1757                                         set_method_param_type(res, n_param++, tp_u);
1758                                         set_method_param_type(res, n_param++, tp_u);
1759                                 } else {
1760                                         set_method_param_type(res, n_param++, tp);
1761                                 }  /* if */
1762                         } else {
1763                                 set_method_param_type(res, n_param++, tp);
1764                         }  /* if */
1765                 }  /* for */
1766                 for (i = n_res = 0; i < r; ++i) {
1767                         ir_type *tp = get_method_res_type(mtp, i);
1768
1769                         if (is_Primitive_type(tp)) {
1770                                 ir_mode *mode = get_type_mode(tp);
1771
1772                                 if (mode == env->params->high_signed) {
1773                                         set_method_res_type(res, n_res++, tp_u);
1774                                         set_method_res_type(res, n_res++, tp_s);
1775                                 } else if (mode == env->params->high_unsigned) {
1776                                         set_method_res_type(res, n_res++, tp_u);
1777                                         set_method_res_type(res, n_res++, tp_u);
1778                                 } else {
1779                                         set_method_res_type(res, n_res++, tp);
1780                                 }  /* if */
1781                         } else {
1782                                 set_method_res_type(res, n_res++, tp);
1783                         }  /* if */
1784                 }  /* for */
1785                 set_lowered_type(mtp, res);
1786                 pmap_insert(lowered_type, mtp, res);
1787         } else {
1788                 res = entry->value;
1789         }  /* if */
1790         return res;
1791 }  /* lower_mtp */
1792
1793 /**
1794  * Translate a Return.
1795  */
1796 static void lower_Return(ir_node *node, ir_mode *mode, lower_env_t *env) {
1797         ir_graph  *irg = current_ir_graph;
1798         ir_entity *ent = get_irg_entity(irg);
1799         ir_type   *mtp = get_entity_type(ent);
1800         ir_node   **in;
1801         int       i, j, n, idx;
1802         int       need_conv = 0;
1803         (void) mode;
1804
1805         /* check if this return must be lowered */
1806         for (i = 0, n = get_Return_n_ress(node); i < n; ++i) {
1807                 ir_node *pred = get_Return_res(node, i);
1808                 ir_mode *mode = get_irn_op_mode(pred);
1809
1810                 if (mode == env->params->high_signed ||
1811                         mode == env->params->high_unsigned) {
1812                         idx = get_irn_idx(pred);
1813                         if (! env->entries[idx]->low_word) {
1814                                 /* not ready yet, wait */
1815                                 pdeq_putr(env->waitq, node);
1816                                 return;
1817                         }  /* if */
1818                         need_conv = 1;
1819                 }  /* if */
1820         }  /* for */
1821         if (! need_conv)
1822                 return;
1823
1824         ent = get_irg_entity(irg);
1825         mtp = get_entity_type(ent);
1826
1827         mtp = lower_mtp(mtp, env);
1828         set_entity_type(ent, mtp);
1829
1830         /* create a new in array */
1831         NEW_ARR_A(ir_node *, in, get_method_n_ress(mtp) + 1);
1832         in[0] = get_Return_mem(node);
1833
1834         for (j = i = 0, n = get_Return_n_ress(node); i < n; ++i) {
1835                 ir_node *pred = get_Return_res(node, i);
1836
1837                 idx = get_irn_idx(pred);
1838                 assert(idx < env->n_entries);
1839
1840                 if (env->entries[idx]) {
1841                         in[++j] = env->entries[idx]->low_word;
1842                         in[++j] = env->entries[idx]->high_word;
1843                 } else {
1844                         in[++j] = pred;
1845                 }  /* if */
1846         }  /* for */
1847
1848         set_irn_in(node, j+1, in);
1849 }  /* lower_Return */
1850
1851 /**
1852  * Translate the parameters.
1853  */
1854 static void lower_Start(ir_node *node, ir_mode *mode, lower_env_t *env) {
1855         ir_graph  *irg = current_ir_graph;
1856         ir_entity *ent = get_irg_entity(irg);
1857         ir_type   *tp  = get_entity_type(ent);
1858         ir_type   *mtp;
1859         long      *new_projs;
1860         int       i, j, n_params, rem;
1861         ir_node   *proj, *args;
1862         (void) mode;
1863
1864         if (is_lowered_type(tp)) {
1865                 mtp = get_associated_type(tp);
1866         } else {
1867                 mtp = tp;
1868         }  /* if */
1869         assert(! is_lowered_type(mtp));
1870
1871         n_params = get_method_n_params(mtp);
1872         if (n_params <= 0)
1873                 return;
1874
1875         NEW_ARR_A(long, new_projs, n_params);
1876
1877         /* first check if we have parameters that must be fixed */
1878         for (i = j = 0; i < n_params; ++i, ++j) {
1879                 ir_type *tp = get_method_param_type(mtp, i);
1880
1881                 new_projs[i] = j;
1882                 if (is_Primitive_type(tp)) {
1883                         ir_mode *mode = get_type_mode(tp);
1884
1885                         if (mode == env->params->high_signed ||
1886                                 mode == env->params->high_unsigned)
1887                                 ++j;
1888                 }  /* if */
1889         }  /* for */
1890         if (i == j)
1891                 return;
1892
1893         mtp = lower_mtp(mtp, env);
1894         set_entity_type(ent, mtp);
1895
1896         /* switch off optimization for new Proj nodes or they might be CSE'ed
1897            with not patched one's */
1898         rem = get_optimize();
1899         set_optimize(0);
1900
1901         /* ok, fix all Proj's and create new ones */
1902         args = get_irg_args(irg);
1903         for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
1904                 ir_node *pred = get_Proj_pred(proj);
1905                 long proj_nr;
1906                 int idx;
1907                 ir_mode *mode;
1908                 dbg_info *dbg;
1909
1910                 /* do not visit this node again */
1911                 mark_irn_visited(proj);
1912
1913                 if (pred != args)
1914                         continue;
1915
1916                 proj_nr = get_Proj_proj(proj);
1917                 set_Proj_proj(proj, new_projs[proj_nr]);
1918
1919                 idx = get_irn_idx(proj);
1920                 if (env->entries[idx]) {
1921                         ir_mode *low_mode = env->params->low_unsigned;
1922
1923                         mode = get_irn_mode(proj);
1924
1925                         if (mode == env->params->high_signed) {
1926                                 mode = env->params->low_signed;
1927                         } else {
1928                                 mode = env->params->low_unsigned;
1929                         }  /* if */
1930
1931                         dbg = get_irn_dbg_info(proj);
1932                         env->entries[idx]->low_word  =
1933                                 new_rd_Proj(dbg, irg, get_nodes_block(proj), args, low_mode, new_projs[proj_nr]);
1934                         env->entries[idx]->high_word =
1935                                 new_rd_Proj(dbg, irg, get_nodes_block(proj), args, mode, new_projs[proj_nr] + 1);
1936                 }  /* if */
1937         }  /* for */
1938         set_optimize(rem);
1939 }  /* lower_Start */
1940
1941 /**
1942  * Translate a Call.
1943  */
1944 static void lower_Call(ir_node *node, ir_mode *mode, lower_env_t *env) {
1945         ir_graph *irg = current_ir_graph;
1946         ir_type  *tp = get_Call_type(node);
1947         ir_type  *call_tp;
1948         ir_node  **in, *proj, *results;
1949         int      n_params, n_res, need_lower = 0;
1950         int      i, j;
1951         long     *res_numbers = NULL;
1952         (void) mode;
1953
1954         if (is_lowered_type(tp)) {
1955                 call_tp = get_associated_type(tp);
1956         } else {
1957                 call_tp = tp;
1958         }  /* if */
1959
1960         assert(! is_lowered_type(call_tp));
1961
1962         n_params = get_method_n_params(call_tp);
1963         for (i = 0; i < n_params; ++i) {
1964                 ir_type *tp = get_method_param_type(call_tp, i);
1965
1966                 if (is_Primitive_type(tp)) {
1967                         ir_mode *mode = get_type_mode(tp);
1968
1969                         if (mode == env->params->high_signed ||
1970                                 mode == env->params->high_unsigned) {
1971                                 need_lower = 1;
1972                                 break;
1973                         }  /* if */
1974                 }  /* if */
1975         }  /* for */
1976         n_res = get_method_n_ress(call_tp);
1977         if (n_res > 0) {
1978                 NEW_ARR_A(long, res_numbers, n_res);
1979
1980                 for (i = j = 0; i < n_res; ++i, ++j) {
1981                         ir_type *tp = get_method_res_type(call_tp, i);
1982
1983                         res_numbers[i] = j;
1984                         if (is_Primitive_type(tp)) {
1985                                 ir_mode *mode = get_type_mode(tp);
1986
1987                                 if (mode == env->params->high_signed ||
1988                                         mode == env->params->high_unsigned) {
1989                                         need_lower = 1;
1990                                         ++j;
1991                                 }  /* if */
1992                         }  /* if */
1993                 }  /* for */
1994         }  /* if */
1995
1996         if (! need_lower)
1997                 return;
1998
1999         /* let's lower it */
2000         call_tp = lower_mtp(call_tp, env);
2001         set_Call_type(node, call_tp);
2002
2003         NEW_ARR_A(ir_node *, in, get_method_n_params(call_tp) + 2);
2004
2005         in[0] = get_Call_mem(node);
2006         in[1] = get_Call_ptr(node);
2007
2008         for (j = 2, i = 0; i < n_params; ++i) {
2009                 ir_node *pred = get_Call_param(node, i);
2010                 int     idx = get_irn_idx(pred);
2011
2012                 if (env->entries[idx]) {
2013                         if (! env->entries[idx]->low_word) {
2014                                 /* not ready yet, wait */
2015                                 pdeq_putr(env->waitq, node);
2016                                 return;
2017                         }
2018                         in[j++] = env->entries[idx]->low_word;
2019                         in[j++] = env->entries[idx]->high_word;
2020                 } else {
2021                         in[j++] = pred;
2022                 }  /* if */
2023         }  /* for */
2024
2025         set_irn_in(node, j, in);
2026
2027         /* fix the results */
2028         results = NULL;
2029         for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
2030                 long proj_nr = get_Proj_proj(proj);
2031
2032                 if (proj_nr == pn_Call_T_result && get_Proj_pred(proj) == node) {
2033                         /* found the result proj */
2034                         results = proj;
2035                         break;
2036                 }  /* if */
2037         }  /* for */
2038
2039         if (results) {          /* there are results */
2040                 int rem = get_optimize();
2041
2042                 /* switch off optimization for new Proj nodes or they might be CSE'ed
2043                    with not patched one's */
2044                 set_optimize(0);
2045                 for (i = j = 0, proj = get_irn_link(results); proj; proj = get_irn_link(proj), ++i, ++j) {
2046                         if (get_Proj_pred(proj) == results) {
2047                                 long proj_nr = get_Proj_proj(proj);
2048                                 int idx;
2049
2050                                 /* found a result */
2051                                 set_Proj_proj(proj, res_numbers[proj_nr]);
2052                                 idx = get_irn_idx(proj);
2053                                 if (env->entries[idx]) {
2054                                         ir_mode *mode = get_irn_mode(proj);
2055                                         ir_mode *low_mode = env->params->low_unsigned;
2056                                         dbg_info *dbg;
2057
2058                                         if (mode == env->params->high_signed) {
2059                                                 mode = env->params->low_signed;
2060                                         } else {
2061                                                 mode = env->params->low_unsigned;
2062                                         }  /* if */
2063
2064                                         dbg = get_irn_dbg_info(proj);
2065                                         env->entries[idx]->low_word  =
2066                                                 new_rd_Proj(dbg, irg, get_nodes_block(proj), results, low_mode, res_numbers[proj_nr]);
2067                                         env->entries[idx]->high_word =
2068                                                 new_rd_Proj(dbg, irg, get_nodes_block(proj), results, mode, res_numbers[proj_nr] + 1);
2069                                 }  /* if */
2070                                 mark_irn_visited(proj);
2071                         }  /* if */
2072                 }  /* for */
2073                 set_optimize(rem);
2074         }
2075 }  /* lower_Call */
2076
2077 /**
2078  * Translate an Unknown into two.
2079  */
2080 static void lower_Unknown(ir_node *node, ir_mode *mode, lower_env_t *env) {
2081         int      idx = get_irn_idx(node);
2082         ir_graph *irg = current_ir_graph;
2083         ir_mode  *low_mode = env->params->low_unsigned;
2084
2085         env->entries[idx]->low_word  = new_r_Unknown(irg, low_mode);
2086         env->entries[idx]->high_word = new_r_Unknown(irg, mode);
2087 }  /* lower_Unknown */
2088
2089 /**
2090  * Translate a Phi.
2091  *
2092  * First step: just create two templates
2093  */
2094 static void lower_Phi(ir_node *phi, ir_mode *mode, lower_env_t *env) {
2095         ir_mode  *mode_l = env->params->low_unsigned;
2096         ir_graph *irg = current_ir_graph;
2097         ir_node  *block, *unk_l, *unk_h, *phi_l, *phi_h;
2098         ir_node  **inl, **inh;
2099         dbg_info *dbg;
2100         int      idx, i, arity = get_Phi_n_preds(phi);
2101         int      enq = 0;
2102
2103         idx = get_irn_idx(phi);
2104         if (env->entries[idx]->low_word) {
2105                 /* Phi nodes already build, check for inputs */
2106                 ir_node *phil = env->entries[idx]->low_word;
2107                 ir_node *phih = env->entries[idx]->high_word;
2108
2109                 for (i = 0; i < arity; ++i) {
2110                         ir_node *pred = get_Phi_pred(phi, i);
2111                         int     idx = get_irn_idx(pred);
2112
2113                         if (env->entries[idx]->low_word) {
2114                                 set_Phi_pred(phil, i, env->entries[idx]->low_word);
2115                                 set_Phi_pred(phih, i, env->entries[idx]->high_word);
2116                         } else {
2117                                 /* still not ready */
2118                                 pdeq_putr(env->waitq, phi);
2119                                 return;
2120                         }  /* if */
2121                 }  /* for */
2122         }  /* if */
2123
2124         /* first create a new in array */
2125         NEW_ARR_A(ir_node *, inl, arity);
2126         NEW_ARR_A(ir_node *, inh, arity);
2127         unk_l = new_r_Unknown(irg, mode_l);
2128         unk_h = new_r_Unknown(irg, mode);
2129
2130         for (i = 0; i < arity; ++i) {
2131                 ir_node *pred = get_Phi_pred(phi, i);
2132                 int     idx = get_irn_idx(pred);
2133
2134                 if (env->entries[idx]->low_word) {
2135                         inl[i] = env->entries[idx]->low_word;
2136                         inh[i] = env->entries[idx]->high_word;
2137                 } else {
2138                         inl[i] = unk_l;
2139                         inh[i] = unk_h;
2140                         enq = 1;
2141                 }  /* if */
2142         }  /* for */
2143
2144         dbg   = get_irn_dbg_info(phi);
2145         block = get_nodes_block(phi);
2146
2147         idx = get_irn_idx(phi);
2148         assert(idx < env->n_entries);
2149         env->entries[idx]->low_word  = phi_l = new_rd_Phi(dbg, irg, block, arity, inl, mode_l);
2150         env->entries[idx]->high_word = phi_h = new_rd_Phi(dbg, irg, block, arity, inh, mode);
2151
2152         /* Don't forget to link the new Phi nodes into the block! */
2153         set_irn_link(phi_l, get_irn_link(block));
2154         set_irn_link(phi_h, phi_l);
2155         set_irn_link(block, phi_h);
2156
2157         if (enq) {
2158                 /* not yet finished */
2159                 pdeq_putr(env->waitq, phi);
2160         }  /* if */
2161 }  /* lower_Phi */
2162
2163 /**
2164  * Translate a Mux.
2165  */
2166 static void lower_Mux(ir_node *mux, ir_mode *mode, lower_env_t *env) {
2167         ir_graph *irg = current_ir_graph;
2168         ir_node  *block, *val;
2169         ir_node  *true_l, *true_h, *false_l, *false_h, *sel;
2170         dbg_info *dbg;
2171         int      idx;
2172
2173         val = get_Mux_true(mux);
2174         idx = get_irn_idx(val);
2175         if (env->entries[idx]->low_word) {
2176                 /* Values already build */
2177                 true_l = env->entries[idx]->low_word;
2178                 true_h = env->entries[idx]->high_word;
2179         } else {
2180                 /* still not ready */
2181                 pdeq_putr(env->waitq, mux);
2182                 return;
2183         }  /* if */
2184
2185         val = get_Mux_false(mux);
2186         idx = get_irn_idx(val);
2187         if (env->entries[idx]->low_word) {
2188                 /* Values already build */
2189                 false_l = env->entries[idx]->low_word;
2190                 false_h = env->entries[idx]->high_word;
2191         } else {
2192                 /* still not ready */
2193                 pdeq_putr(env->waitq, mux);
2194                 return;
2195         }  /* if */
2196
2197
2198         sel = get_Mux_sel(mux);
2199
2200         dbg   = get_irn_dbg_info(mux);
2201         block = get_nodes_block(mux);
2202
2203         idx = get_irn_idx(mux);
2204         assert(idx < env->n_entries);
2205         env->entries[idx]->low_word  = new_rd_Mux(dbg, irg, block, sel, false_l, true_l, mode);
2206         env->entries[idx]->high_word = new_rd_Mux(dbg, irg, block, sel, false_h, true_h, mode);
2207 }  /* lower_Mux */
2208
2209 /**
2210  * check for opcodes that must always be lowered.
2211  */
2212 static int always_lower(ir_opcode code) {
2213         switch (code) {
2214         case iro_Proj:
2215         case iro_Start:
2216         case iro_Call:
2217         case iro_Return:
2218         case iro_Cond:
2219         case iro_Conv:
2220                 return 1;
2221         default:
2222                 return 0;
2223         }  /* switch */
2224 }  /* always_lower */
2225
2226 /**
2227  * lower boolean Proj(Cmp)
2228  */
2229 static ir_node *lower_boolean_Proj_Cmp(ir_node *proj, ir_node *cmp, lower_env_t *env) {
2230         int      lidx, ridx;
2231         ir_node  *l, *r, *low, *high, *t, *res;
2232         pn_Cmp   pnc;
2233         ir_node  *blk;
2234         ir_graph *irg = current_ir_graph;
2235         dbg_info *db;
2236
2237         l    = get_Cmp_left(cmp);
2238         lidx = get_irn_idx(l);
2239         if (! env->entries[lidx]->low_word) {
2240                 /* still not ready */
2241                 return NULL;
2242         }  /* if */
2243
2244         r    = get_Cmp_right(cmp);
2245         ridx = get_irn_idx(r);
2246         if (! env->entries[ridx]->low_word) {
2247                 /* still not ready */
2248                 return NULL;
2249         }  /* if */
2250
2251         pnc  = get_Proj_proj(proj);
2252         blk  = get_nodes_block(cmp);
2253         db   = get_irn_dbg_info(cmp);
2254         low  = new_rd_Cmp(db, irg, blk, env->entries[lidx]->low_word, env->entries[ridx]->low_word);
2255         high = new_rd_Cmp(db, irg, blk, env->entries[lidx]->high_word, env->entries[ridx]->high_word);
2256
2257         if (pnc == pn_Cmp_Eq) {
2258                 /* simple case:a == b <==> a_h == b_h && a_l == b_l */
2259                 res = new_rd_And(db, irg, blk,
2260                         new_r_Proj(irg, blk, low, mode_b, pnc),
2261                         new_r_Proj(irg, blk, high, mode_b, pnc),
2262                         mode_b);
2263         } else if (pnc == pn_Cmp_Lg) {
2264                 /* simple case:a != b <==> a_h != b_h || a_l != b_l */
2265                 res = new_rd_Or(db, irg, blk,
2266                         new_r_Proj(irg, blk, low, mode_b, pnc),
2267                         new_r_Proj(irg, blk, high, mode_b, pnc),
2268                         mode_b);
2269         } else {
2270                 /* a rel b <==> a_h REL b_h || (a_h == b_h && a_l rel b_l) */
2271                 t = new_rd_And(db, irg, blk,
2272                         new_r_Proj(irg, blk, low, mode_b, pnc),
2273                         new_r_Proj(irg, blk, high, mode_b, pn_Cmp_Eq),
2274                         mode_b);
2275                 res = new_rd_Or(db, irg, blk,
2276                         new_r_Proj(irg, blk, high, mode_b, pnc & ~pn_Cmp_Eq),
2277                         t,
2278                         mode_b);
2279         }  /* if */
2280         return res;
2281 }  /* lower_boolean_Proj_Cmp */
2282
2283 /**
2284  * The type of a lower function.
2285  *
2286  * @param node   the node to be lowered
2287  * @param mode   the low mode for the destination node
2288  * @param env    the lower environment
2289  */
2290 typedef void (*lower_func)(ir_node *node, ir_mode *mode, lower_env_t *env);
2291
2292 /**
2293  * Lower a node.
2294  */
2295 static void lower_ops(ir_node *node, void *env)
2296 {
2297         lower_env_t  *lenv = env;
2298         node_entry_t *entry;
2299         int          idx = get_irn_idx(node);
2300         ir_mode      *mode = get_irn_mode(node);
2301
2302         if (mode == mode_b || is_Mux(node) || is_Conv(node)) {
2303                 int i;
2304
2305                 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
2306                         ir_node *proj = get_irn_n(node, i);
2307
2308                         if (is_Proj(proj)) {
2309                                 ir_node *cmp = get_Proj_pred(proj);
2310
2311                                 if (is_Cmp(cmp)) {
2312                                         ir_node *arg = get_Cmp_left(cmp);
2313
2314                                         mode = get_irn_mode(arg);
2315                                         if (mode == lenv->params->high_signed ||
2316                                                 mode == lenv->params->high_unsigned) {
2317                                                 ir_node *res = lower_boolean_Proj_Cmp(proj, cmp, lenv);
2318
2319                                                 if (res == NULL) {
2320                                                         /* could not lower because predecessors not ready */
2321                                                         waitq_put(lenv->waitq, node);
2322                                                         return;
2323                                                 }  /* if */
2324                                                 set_irn_n(node, i, res);
2325                                         }  /* if */
2326                                 }  /* if */
2327                         }  /* if */
2328                 }  /* for */
2329         }  /* if */
2330
2331         entry = idx < lenv->n_entries ? lenv->entries[idx] : NULL;
2332         if (entry || always_lower(get_irn_opcode(node))) {
2333                 ir_op      *op = get_irn_op(node);
2334                 lower_func func = (lower_func)op->ops.generic;
2335
2336                 if (func) {
2337                         mode = get_irn_op_mode(node);
2338
2339                         if (mode == lenv->params->high_signed)
2340                                 mode = lenv->params->low_signed;
2341                         else
2342                                 mode = lenv->params->low_unsigned;
2343
2344                         DB((dbg, LEVEL_1, "  %+F\n", node));
2345                         func(node, mode, lenv);
2346                 }  /* if */
2347         }  /* if */
2348 }  /* lower_ops */
2349
2350 #define IDENT(s)  new_id_from_chars(s, sizeof(s)-1)
2351
2352 /**
2353  * Compare two op_mode_entry_t's.
2354  */
2355 static int cmp_op_mode(const void *elt, const void *key, size_t size) {
2356         const op_mode_entry_t *e1 = elt;
2357         const op_mode_entry_t *e2 = key;
2358         (void) size;
2359
2360         return (e1->op - e2->op) | (e1->imode - e2->imode) | (e1->omode - e2->omode);
2361 }  /* cmp_op_mode */
2362
2363 /**
2364  * Compare two conv_tp_entry_t's.
2365  */
2366 static int cmp_conv_tp(const void *elt, const void *key, size_t size) {
2367         const conv_tp_entry_t *e1 = elt;
2368         const conv_tp_entry_t *e2 = key;
2369         (void) size;
2370
2371         return (e1->imode - e2->imode) | (e1->omode - e2->omode);
2372 }  /* static int cmp_conv_tp */
2373
2374 /**
2375  * Enter a lowering function into an ir_op.
2376  */
2377 static void enter_lower_func(ir_op *op, lower_func func) {
2378         op->ops.generic = (op_func)func;
2379 }
2380
2381 /*
2382  * Do the lowering.
2383  */
2384 void lower_dw_ops(const lwrdw_param_t *param)
2385 {
2386         lower_env_t lenv;
2387         int i;
2388         ir_graph *rem;
2389
2390         if (! param)
2391                 return;
2392
2393         if (! param->enable)
2394                 return;
2395
2396         FIRM_DBG_REGISTER(dbg, "firm.lower.dw");
2397
2398         assert(2 * get_mode_size_bits(param->low_signed)   == get_mode_size_bits(param->high_signed));
2399         assert(2 * get_mode_size_bits(param->low_unsigned) == get_mode_size_bits(param->high_unsigned));
2400         assert(get_mode_size_bits(param->low_signed) == get_mode_size_bits(param->low_unsigned));
2401
2402         /* create the necessary maps */
2403         if (! prim_types)
2404                 prim_types = pmap_create();
2405         if (! intrinsic_fkt)
2406                 intrinsic_fkt = new_set(cmp_op_mode, iro_Last + 1);
2407         if (! conv_types)
2408                 conv_types = new_set(cmp_conv_tp, 16);
2409         if (! lowered_type)
2410                 lowered_type = pmap_create();
2411
2412         /* create a primitive unsigned and signed type */
2413         if (! tp_u)
2414                 tp_u = get_primitive_type(param->low_unsigned);
2415         if (! tp_s)
2416                 tp_s = get_primitive_type(param->low_signed);
2417
2418         /* create method types for the created binop calls */
2419         if (! binop_tp_u) {
2420                 binop_tp_u = new_type_method(IDENT("binop_u_intrinsic"), 4, 2);
2421                 set_method_param_type(binop_tp_u, 0, tp_u);
2422                 set_method_param_type(binop_tp_u, 1, tp_u);
2423                 set_method_param_type(binop_tp_u, 2, tp_u);
2424                 set_method_param_type(binop_tp_u, 3, tp_u);
2425                 set_method_res_type(binop_tp_u, 0, tp_u);
2426                 set_method_res_type(binop_tp_u, 1, tp_u);
2427         }  /* if */
2428         if (! binop_tp_s) {
2429                 binop_tp_s = new_type_method(IDENT("binop_s_intrinsic"), 4, 2);
2430                 set_method_param_type(binop_tp_s, 0, tp_u);
2431                 set_method_param_type(binop_tp_s, 1, tp_s);
2432                 set_method_param_type(binop_tp_s, 2, tp_u);
2433                 set_method_param_type(binop_tp_s, 3, tp_s);
2434                 set_method_res_type(binop_tp_s, 0, tp_u);
2435                 set_method_res_type(binop_tp_s, 1, tp_s);
2436         }  /* if */
2437         if (! shiftop_tp_u) {
2438                 shiftop_tp_u = new_type_method(IDENT("shiftop_u_intrinsic"), 3, 2);
2439                 set_method_param_type(shiftop_tp_u, 0, tp_u);
2440                 set_method_param_type(shiftop_tp_u, 1, tp_u);
2441                 set_method_param_type(shiftop_tp_u, 2, tp_u);
2442                 set_method_res_type(shiftop_tp_u, 0, tp_u);
2443                 set_method_res_type(shiftop_tp_u, 1, tp_u);
2444         }  /* if */
2445         if (! shiftop_tp_s) {
2446                 shiftop_tp_s = new_type_method(IDENT("shiftop_s_intrinsic"), 3, 2);
2447                 set_method_param_type(shiftop_tp_s, 0, tp_u);
2448                 set_method_param_type(shiftop_tp_s, 1, tp_s);
2449                 /* beware: shift count is always mode_Iu */
2450                 set_method_param_type(shiftop_tp_s, 2, tp_u);
2451                 set_method_res_type(shiftop_tp_s, 0, tp_u);
2452                 set_method_res_type(shiftop_tp_s, 1, tp_s);
2453         }  /* if */
2454         if (! unop_tp_u) {
2455                 unop_tp_u = new_type_method(IDENT("unop_u_intrinsic"), 2, 2);
2456                 set_method_param_type(unop_tp_u, 0, tp_u);
2457                 set_method_param_type(unop_tp_u, 1, tp_u);
2458                 set_method_res_type(unop_tp_u, 0, tp_u);
2459                 set_method_res_type(unop_tp_u, 1, tp_u);
2460         }  /* if */
2461         if (! unop_tp_s) {
2462                 unop_tp_s = new_type_method(IDENT("unop_s_intrinsic"), 2, 2);
2463                 set_method_param_type(unop_tp_s, 0, tp_u);
2464                 set_method_param_type(unop_tp_s, 1, tp_s);
2465                 set_method_res_type(unop_tp_s, 0, tp_u);
2466                 set_method_res_type(unop_tp_s, 1, tp_s);
2467         }  /* if */
2468
2469         lenv.tv_mode_bytes = new_tarval_from_long(get_mode_size_bytes(param->low_unsigned), mode_Iu);
2470         lenv.tv_mode_bits  = new_tarval_from_long(get_mode_size_bits(param->low_unsigned), mode_Iu);
2471         lenv.waitq         = new_pdeq();
2472         lenv.params        = param;
2473
2474         /* first clear the generic function pointer for all ops */
2475         clear_irp_opcodes_generic_func();
2476
2477 #define LOWER2(op, fkt)   enter_lower_func(op_##op, fkt)
2478 #define LOWER(op)         LOWER2(op, lower_##op)
2479 #define LOWER_BIN(op)     LOWER2(op, lower_Binop)
2480 #define LOWER_UN(op)      LOWER2(op, lower_Unop)
2481
2482         /* the table of all operations that must be lowered follows */
2483         LOWER(Load);
2484         LOWER(Store);
2485         LOWER(Const);
2486         LOWER(And);
2487         LOWER(Or);
2488         LOWER(Eor);
2489         LOWER(Not);
2490         LOWER(Cond);
2491         LOWER(Return);
2492         LOWER(Call);
2493         LOWER(Unknown);
2494         LOWER(Phi);
2495         LOWER(Mux);
2496         LOWER(Start);
2497
2498         LOWER_BIN(Add);
2499         LOWER_BIN(Sub);
2500         LOWER_BIN(Mul);
2501         LOWER(Shl);
2502         LOWER(Shr);
2503         LOWER(Shrs);
2504         LOWER(Rotl);
2505         LOWER(DivMod);
2506         LOWER(Div);
2507         LOWER(Mod);
2508         LOWER_UN(Abs);
2509         LOWER_UN(Minus);
2510
2511         LOWER(Conv);
2512
2513 #undef LOWER_UN
2514 #undef LOWER_BIN
2515 #undef LOWER
2516 #undef LOWER2
2517
2518         /* transform all graphs */
2519         rem = current_ir_graph;
2520         for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2521                 ir_graph *irg = get_irp_irg(i);
2522                 int n_idx;
2523
2524                 obstack_init(&lenv.obst);
2525
2526                 n_idx = get_irg_last_idx(irg);
2527                 n_idx = n_idx + (n_idx >> 2);  /* add 25% */
2528                 lenv.n_entries = n_idx;
2529                 lenv.entries   = NEW_ARR_F(node_entry_t *, n_idx);
2530                 memset(lenv.entries, 0, n_idx * sizeof(lenv.entries[0]));
2531
2532                 /* first step: link all nodes and allocate data */
2533                 lenv.flags = 0;
2534                 lenv.proj_2_block = pmap_create();
2535                 irg_walk_graph(irg, firm_clear_link, prepare_links_and_handle_rotl, &lenv);
2536
2537                 if (lenv.flags & MUST_BE_LOWERED) {
2538                         DB((dbg, LEVEL_1, "Lowering graph %+F\n", irg));
2539
2540                         /* must do some work */
2541                         irg_walk_graph(irg, NULL, lower_ops, &lenv);
2542
2543                         /* last step: all waiting nodes */
2544                         DB((dbg, LEVEL_1, "finishing waiting nodes:\n"));
2545                         current_ir_graph = irg;
2546                         while (! pdeq_empty(lenv.waitq)) {
2547                                 ir_node *node = pdeq_getl(lenv.waitq);
2548
2549                                 lower_ops(node, &lenv);
2550                         }  /* while */
2551
2552                         /* outs are invalid, we changed the graph */
2553                         set_irg_outs_inconsistent(irg);
2554
2555                         if (lenv.flags & CF_CHANGED) {
2556                                 /* control flow changed, dominance info is invalid */
2557                                 set_irg_doms_inconsistent(irg);
2558                                 set_irg_extblk_inconsistent(irg);
2559                                 set_irg_loopinfo_inconsistent(irg);
2560                         }  /* if */
2561                 }  /* if */
2562                 pmap_destroy(lenv.proj_2_block);
2563                 DEL_ARR_F(lenv.entries);
2564                 obstack_free(&lenv.obst, NULL);
2565         }  /* for */
2566         del_pdeq(lenv.waitq);
2567         current_ir_graph = rem;
2568 }  /* lower_dw_ops */
2569
2570 /* Default implementation. */
2571 ir_entity *def_create_intrinsic_fkt(ir_type *method, const ir_op *op,
2572                                     const ir_mode *imode, const ir_mode *omode,
2573                                     void *context)
2574 {
2575         char buf[64];
2576         ident *id;
2577         ir_entity *ent;
2578         (void) context;
2579
2580         if (imode == omode) {
2581                 snprintf(buf, sizeof(buf), "__l%s%s", get_op_name(op), get_mode_name(imode));
2582         } else {
2583                 snprintf(buf, sizeof(buf), "__l%s%s%s", get_op_name(op),
2584                         get_mode_name(imode), get_mode_name(omode));
2585         }  /* if */
2586         id = new_id_from_str(buf);
2587
2588         ent = new_entity(get_glob_type(), id, method);
2589         set_entity_ld_ident(ent, get_entity_ident(ent));
2590         set_entity_visibility(ent, visibility_external_allocated);
2591         return ent;
2592 }  /* def_create_intrinsic_fkt */