Let foreach_out_edge_kind() and foreach_out_edge_kind_safe() declare their iterator...
[libfirm] / ir / lower / lower_softfloat.c
1 /*
2  * Copyright (C) 1995-2011 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 floating point operations to function calls
23  * @author  Sebastian Buchwald
24  */
25 #include "config.h"
26
27 #include <stdbool.h>
28
29 #include "be.h"
30 #include "dbginfo_t.h"
31 #include "debug.h"
32 #include "error.h"
33 #include "ircons.h"
34 #include "iredges.h"
35 #include "irgmod.h"
36 #include "irnodeset.h"
37 #include "irgwalk.h"
38 #include "irmode.h"
39 #include "iropt_dbg.h"
40 #include "iroptimize.h"
41 #include "irprog_t.h"
42 #include "lower_softfloat.h"
43 #include "lowering.h"
44 #include "pmap.h"
45 #include "type_t.h"
46 #include "tv_t.h"
47
48 /** The debug handle */
49 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
50
51 typedef void (*lower_softfloat_func)(ir_node *node);
52
53 static ir_type *binop_tp_d;
54 static ir_type *binop_tp_f;
55 static ir_type *cmp_tp_d;
56 static ir_type *cmp_tp_f;
57 static ir_type *unop_tp_d;
58 static ir_type *unop_tp_f;
59 static ir_type *unop_tp_d_f;
60 static ir_type *unop_tp_d_is;
61 static ir_type *unop_tp_d_iu;
62 static ir_type *unop_tp_d_ls;
63 static ir_type *unop_tp_d_lu;
64 static ir_type *unop_tp_f_d;
65 static ir_type *unop_tp_f_is;
66 static ir_type *unop_tp_f_iu;
67 static ir_type *unop_tp_f_ls;
68 static ir_type *unop_tp_f_lu;
69 static ir_type *unop_tp_is_d;
70 static ir_type *unop_tp_is_f;
71 static ir_type *unop_tp_iu_d;
72 static ir_type *unop_tp_iu_f;
73 static ir_type *unop_tp_ls_d;
74 static ir_type *unop_tp_ls_f;
75 static ir_type *unop_tp_lu_d;
76 static ir_type *unop_tp_lu_f;
77
78 /** A map from a method type to its lowered type. */
79 static pmap *lowered_type;
80
81 static ir_nodeset_t created_mux_nodes;
82
83 /**
84  * @return The lowered (floating point) mode.
85  */
86 static ir_mode *get_lowered_mode(ir_mode *mode)
87 {
88         if (! mode_is_float(mode))
89                 return mode;
90
91         if (mode == mode_F)
92                 return mode_Iu;
93         else if (mode == mode_D)
94                 return mode_Lu;
95
96         panic("Unsupported floating point type");
97 }
98
99 /**
100  * Adapts the mode of the given node.
101  */
102 static void lower_mode(ir_node *n, void *env)
103 {
104         ir_op                *op         = get_irn_op(n);
105         lower_softfloat_func  lower_func = (lower_softfloat_func) op->ops.generic;
106         ir_mode              *mode       = get_irn_mode(n);
107
108         (void) env;
109
110         if (lower_func != NULL) {
111                 lower_func(n);
112                 return;
113         }
114
115         set_irn_mode(n, get_lowered_mode(mode));
116 }
117
118 /**
119  * Wrapper for specific lower function.
120  */
121 static void lower_node(ir_node *n, void *env)
122 {
123         ir_op                *op         = get_irn_op(n);
124         lower_softfloat_func  lower_func = (lower_softfloat_func) op->ops.generic;
125
126         (void) env;
127
128         if (lower_func != NULL)
129                 lower_func(n);
130 }
131
132 /**
133  * @return The type of the function replacing the given node.
134  */
135 static ir_type *get_softfloat_type(const ir_node *n)
136 {
137         unsigned opcode       = get_irn_opcode(n);
138         ir_mode *mode         = get_irn_mode(n);
139         ir_node *operand      = get_irn_n(n, 0);
140         ir_mode *operand_mode = get_irn_mode(operand);
141
142         switch (opcode) {
143         case iro_Div:
144                 mode         = get_Div_resmode(n);
145                 operand_mode = get_irn_mode(get_Div_left(n));
146                 /* fall through */
147         case iro_Add:
148         case iro_Mul:
149         case iro_Sub:
150                 if (operand_mode == mode_F)
151                         return binop_tp_f;
152                 else if (operand_mode == mode_D)
153                         return binop_tp_d;
154                 break;
155         case iro_Cmp:
156                 if (operand_mode == mode_F)
157                         return cmp_tp_f;
158                 else if (operand_mode == mode_D)
159                         return cmp_tp_d;
160                 break;
161         case iro_Conv:
162                 if (operand_mode == mode_D) {
163                         if (mode == mode_F)
164                                 return unop_tp_d_f;
165                         else if (mode == mode_Is || mode == mode_Hs || mode == mode_Bs)
166                                 return unop_tp_d_is;
167                         else if (mode == mode_Iu || mode == mode_Hu || mode == mode_Bu)
168                                 return unop_tp_d_iu;
169                         else if (mode == mode_Ls)
170                                 return unop_tp_d_ls;
171                         else if (mode == mode_Lu)
172                                 return unop_tp_d_lu;
173                 }
174                 else if (operand_mode == mode_F) {
175                         if (mode == mode_D)
176                                 return unop_tp_f_d;
177                         else if (mode == mode_Is || mode == mode_Hs || mode == mode_Bs)
178                                 return unop_tp_f_is;
179                         else if (mode == mode_Iu || mode == mode_Hu || mode == mode_Bu)
180                                 return unop_tp_f_iu;
181                         else if (mode == mode_Ls)
182                                 return unop_tp_f_ls;
183                         else if (mode == mode_Lu)
184                                 return unop_tp_f_lu;
185                 }
186                 else if (operand_mode == mode_Is || operand_mode == mode_Hs || operand_mode == mode_Bs) {
187                         if (mode == mode_D)
188                                 return unop_tp_is_d;
189                         else if (mode == mode_F)
190                                 return unop_tp_is_f;
191                 }
192                 else if (operand_mode == mode_Iu || operand_mode == mode_Hu || operand_mode == mode_Bu) {
193                         if (mode == mode_D)
194                                 return unop_tp_iu_d;
195                         else if (mode == mode_F)
196                                 return unop_tp_iu_f;
197                 }
198                 else if (operand_mode == mode_Ls) {
199                         if (mode == mode_D)
200                                 return unop_tp_ls_d;
201                         else if (mode == mode_F)
202                                 return unop_tp_ls_f;
203                 }
204                 else if (operand_mode == mode_Lu) {
205                         if (mode == mode_D)
206                                 return unop_tp_lu_d;
207                         else if (mode == mode_F)
208                                 return unop_tp_lu_f;
209                 }
210                 break;
211         case iro_Minus:
212                 if (operand_mode == mode_F)
213                         return unop_tp_f;
214                 else if (operand_mode == mode_D)
215                         return unop_tp_d;
216                 break;
217         default: break;
218         }
219
220         assert(0 && "Could not determine a suitable type");
221
222         return NULL;
223 }
224
225 /**
226  * @return A SymConst representing the function that replaces the given node.
227  */
228 static ir_node *create_softfloat_symconst(const ir_node *n, const char *name)
229 {
230         char             buf[16];
231         const char      *first_param = "";
232         const char      *second_param = "";
233         const char      *result = "";
234         ir_entity       *ent;
235         size_t           n_params;
236         ident           *id;
237         symconst_symbol  sym;
238         unsigned         float_types  = 0;
239         unsigned         double_types  = 0;
240         ir_graph        *irg    = get_irn_irg(n);
241         ir_type         *method = get_softfloat_type(n);
242
243         n_params = get_method_n_params(method);
244
245         /* Parameter types. */
246         switch (n_params) {
247         case 2:
248                 {
249                         ir_type *param_type = get_method_param_type(method, 1);
250                         ir_mode *mode       = get_type_mode(param_type);
251
252                         if (mode == mode_F) {
253                                 second_param = "sf";
254                                 float_types++;
255                         }
256                         else if (mode == mode_D) {
257                                 second_param = "df";
258                                 double_types++;
259                         }
260                         else if (mode == mode_Iu || mode == mode_Is)
261                                 second_param = "si";
262                         else if (mode == mode_Lu || mode == mode_Ls)
263                                 second_param = "di";
264                 }
265                 /* fall through */
266         case 1:
267                 {
268                         ir_type *param_type = get_method_param_type(method, 0);
269                         ir_mode *mode       = get_type_mode(param_type);
270
271                         if (mode == mode_F) {
272                                 first_param = float_types > 0 ? "" : "sf";
273                                 float_types++;
274                         }
275                         else if (mode == mode_D) {
276                                 first_param = double_types > 0 ? "" : "df";
277                                 double_types++;
278                         }
279                         else if (mode == mode_Iu || mode == mode_Is)
280                                 first_param = "si";
281                         else if (mode == mode_Lu || mode == mode_Ls)
282                                 first_param = "di";
283                 }
284                 break;
285         default:
286                 break;
287         }
288
289         /* Result type. */
290         {
291                 ir_mode *mode;
292
293                 if (is_Div(n))
294                         mode = get_Div_resmode(n);
295                 else
296                         mode = get_irn_mode(n);
297
298                 if (mode == mode_F) {
299                         result = float_types > 0 ? "" : "sf";
300                         float_types++;
301                 }
302                 else if (mode == mode_D) {
303                         result = double_types > 0 ? "" : "df";
304                         double_types++;
305                 }
306                 else if (mode == mode_Iu || mode == mode_Hu || mode == mode_Bu
307                                 || mode == mode_Is || mode == mode_Hs || mode == mode_Bs)
308                         result = "si";
309                 else if (mode == mode_Lu || mode == mode_Ls)
310                         result = "di";
311         }
312
313         assert(float_types <= 3);
314         assert(double_types <= 3);
315
316         if (float_types + double_types > 1)
317                 snprintf(buf, sizeof(buf), "__%s%s%s%s%u", name, first_param, second_param, result, float_types + double_types);
318         else
319                 snprintf(buf, sizeof(buf), "__%s%s%s%s", name, first_param, second_param, result);
320
321         id           = new_id_from_str(buf);
322         ent          = create_compilerlib_entity(id, method);
323         sym.entity_p = ent;
324
325         return new_r_SymConst(irg, mode_P_code, sym, symconst_addr_ent);
326 }
327
328 /**
329  * Transforms an Add into the appropriate soft float function.
330  */
331 static void lower_Add(ir_node *n)
332 {
333         ir_node         *symconst;
334         ir_node         *block       = get_nodes_block(n);
335         ir_node         *call_result = NULL;
336         dbg_info        *dbgi        = get_irn_dbg_info(n);
337         ir_graph        *irg         = get_irn_irg(n);
338         ir_node         *left        = get_Add_left(n);
339         ir_node         *right       = get_Add_right(n);
340         ir_mode         *mode        = get_irn_mode(n);
341
342         if (! mode_is_float(mode))
343                 return;
344
345         symconst = create_softfloat_symconst(n, "add");
346
347         ir_node *call;
348         ir_node *call_results;
349         ir_node *in[2]    = {left, right};
350         ir_node *nomem    = get_irg_no_mem(irg);
351         ir_type *type     = get_softfloat_type(n);
352         ir_mode *res_mode = get_type_mode(get_method_res_type(type, 0));
353
354         call         = new_rd_Call(dbgi, block, nomem, symconst, 2, in, type);
355         call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
356         call_result  = new_r_Proj(call_results, res_mode, 0);
357
358         exchange(n, call_result);
359 }
360
361 /**
362  * @return The lowered (floating point) type.
363  */
364 static ir_type *lower_type(ir_type *tp)
365 {
366         ir_mode *mode         = get_type_mode(tp);
367         ir_mode *lowered_mode = get_lowered_mode(mode);
368
369         return get_type_for_mode(lowered_mode);
370 }
371
372 /**
373  * @return The lowered method type.
374  */
375 static ir_type *lower_method_type(ir_type *mtp)
376 {
377         ir_type *res;
378         size_t   i;
379         size_t   n_param;
380         size_t   n_res;
381
382         res = pmap_get(ir_type, lowered_type, mtp);
383         if (res != NULL)
384                 return res;
385
386         n_param = get_method_n_params(mtp);
387         n_res   = get_method_n_ress(mtp);
388
389         res = new_type_method(n_param, n_res);
390
391         /* set param types and result types */
392         for (i = 0; i < n_param; ++i) {
393                 ir_type *ptp   = get_method_param_type(mtp, i);
394                 ir_mode *pmode = get_type_mode(ptp);
395
396                 if (pmode != NULL && mode_is_float(pmode)) {
397                         ptp = lower_type(ptp);
398                 }
399
400                 set_method_param_type(res, i, ptp);
401         }
402         for (i = 0; i < n_res; ++i) {
403                 ir_type *rtp   = get_method_res_type(mtp, i);
404                 ir_mode *rmode = get_type_mode(rtp);
405
406                 if (rmode != NULL && mode_is_float(rmode)) {
407                         rtp = lower_type(rtp);
408                 }
409
410                 set_method_res_type(res, i, rtp);
411         }
412
413         set_method_variadicity(res, get_method_variadicity(mtp));
414         set_method_calling_convention(res, get_method_calling_convention(mtp));
415         set_method_additional_properties(res, get_method_additional_properties(mtp));
416
417         set_higher_type(res, mtp);
418
419         pmap_insert(lowered_type, mtp, res);
420         return res;
421 }
422
423 /**
424  * Adapts the method type of a Call.
425  */
426 static void lower_Call(ir_node *node)
427 {
428         ir_type  *tp = get_Call_type(node);
429         size_t   n_params;
430         size_t   n_res;
431         bool     need_lower = false;
432         size_t   i;
433         size_t   p;
434
435         n_params = get_method_n_params(tp);
436
437         for (p = 0; p < n_params; ++p) {
438                 ir_type *ptp   = get_method_param_type(tp, p);
439                 ir_mode *pmode = get_type_mode(ptp);
440
441                 if (pmode == NULL)
442                         continue;
443
444                 if (mode_is_float(pmode)) {
445                         need_lower = true;
446                         break;
447                 }
448         }
449
450         n_res = get_method_n_ress(tp);
451
452         for (i = 0; i < n_res; ++i) {
453                 ir_type *rtp   = get_method_res_type(tp, i);
454                 ir_mode *rmode = get_type_mode(rtp);
455
456                 if (rmode == NULL)
457                         continue;
458
459                 if (mode_is_float(rmode)) {
460                         need_lower = true;
461                         break;
462                 }
463         }
464
465         if (! need_lower)
466                 return;
467
468         tp = lower_method_type(tp);
469         set_Call_type(node, tp);
470 }
471
472 /**
473  * Transforms a Cmp into the appropriate soft float function.
474  */
475 static void lower_Cmp(ir_node *n)
476 {
477         ir_node         *symconst    = NULL;
478         ir_node         *block       = get_nodes_block(n);
479         ir_node         *call_result = NULL;
480         dbg_info        *dbgi        = get_irn_dbg_info(n);
481         ir_graph        *irg         = get_irn_irg(n);
482         ir_node         *left        = get_Cmp_left(n);
483         ir_relation      relation    = get_Cmp_relation(n);
484         ir_mode         *op_mode     = get_irn_mode(left);
485         ir_node         *right       = get_Cmp_right(n);
486         ir_node         *symconst2   = NULL;
487         ir_node         *zero        = new_rd_Const(dbgi, irg, get_mode_null(mode_Is));
488
489         if (! mode_is_float(op_mode))
490                 return;
491
492         switch (relation) {
493         case ir_relation_false:
494                 call_result = zero;
495                 break;
496         case ir_relation_equal:
497                 symconst = create_softfloat_symconst(n, "eq");
498                 break;
499         case ir_relation_less:
500                 symconst = create_softfloat_symconst(n, "lt");
501                 break;
502         case ir_relation_greater:
503                 symconst = create_softfloat_symconst(n, "gt");
504                 break;
505         case ir_relation_unordered:
506                 symconst = create_softfloat_symconst(n, "unord");
507                 relation = ir_relation_less_greater;
508                 break;
509         case ir_relation_less_equal:
510                 symconst = create_softfloat_symconst(n, "le");
511                 break;
512         case ir_relation_greater_equal:
513                 symconst = create_softfloat_symconst(n, "ge");
514                 break;
515         case ir_relation_less_greater:
516                 symconst  = create_softfloat_symconst(n, "unord");
517                 symconst2 = create_softfloat_symconst(n, "ne");
518                 break;
519         case ir_relation_less_equal_greater:
520                 symconst = create_softfloat_symconst(n, "unord");
521                 relation = ir_relation_equal;
522                 break;
523         case ir_relation_unordered_equal:
524                 symconst  = create_softfloat_symconst(n, "unord");
525                 relation  = ir_relation_less_greater;
526                 symconst2 = create_softfloat_symconst(n, "ne");
527                 break;
528         case ir_relation_unordered_less:
529                 symconst = create_softfloat_symconst(n, "ge");
530                 relation = ir_relation_less;
531                 break;
532         case ir_relation_unordered_less_equal:
533                 symconst = create_softfloat_symconst(n, "gt");
534                 relation = ir_relation_less_equal;
535                 break;
536         case ir_relation_unordered_greater:
537                 symconst = create_softfloat_symconst(n, "le");
538                 relation = ir_relation_greater;
539                 break;
540         case ir_relation_unordered_greater_equal:
541                 symconst = create_softfloat_symconst(n, "lt");
542                 relation = ir_relation_greater_equal;
543                 break;
544         case ir_relation_unordered_less_greater:
545                 symconst = create_softfloat_symconst(n, "eq");
546                 relation = ir_relation_less_greater;
547                 break;
548         case ir_relation_true:
549                 call_result = zero;
550                 break;
551         }
552
553         if (call_result == NULL) {
554                 ir_node *call;
555                 ir_node *call_results;
556                 ir_node *in[2] = {left, right};
557                 ir_node *nomem = get_irg_no_mem(irg);
558                 ir_type *type  = get_softfloat_type(n);
559
560                 call         = new_rd_Call(dbgi, block, nomem, symconst, 2, in, type);
561                 call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
562                 call_result  = new_r_Proj(call_results, mode_Is, 0);
563         }
564
565         ir_node *cmp = new_r_Cmp(block, call_result, zero, relation);
566
567         /* We need two calls into the softfloat library */
568         if (symconst2 != NULL) {
569                 ir_node *call;
570                 ir_node *call_results;
571                 ir_node *mux;
572                 arch_allow_ifconv_func allow_ifconv = be_get_backend_param()->allow_ifconv;
573                 ir_node *in[2]                      = {left, right};
574                 ir_node *nomem                      = get_irg_no_mem(irg);
575                 ir_type *type                       = get_softfloat_type(n);
576
577                 call         = new_rd_Call(dbgi, block, nomem, symconst2, 2, in, type);
578                 call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
579                 call_result  = new_r_Proj(call_results, mode_Is, 0);
580                 relation     = get_Cmp_relation(n);
581
582                 mux = new_rd_Mux(dbgi, block, cmp, call_result, zero, mode_Is);
583
584                 if (! allow_ifconv(cmp, call_result, zero))
585                         ir_nodeset_insert(&created_mux_nodes, mux);
586
587                 cmp = new_r_Cmp(block, mux, zero, relation);
588         }
589
590         exchange(n, cmp);
591 }
592
593 static const tarval_mode_info hex_output = {
594         TVO_HEX,
595         "0x",
596         NULL,
597 };
598
599 /**
600  * Adapts floating point constants.
601  */
602 static void lower_Const(ir_node *n)
603 {
604         ir_mode   *lowered_mode;
605         ir_mode   *mode         = get_irn_mode(n);
606         ir_tarval *tv = get_Const_tarval(n);
607         char       buf[100];
608         size_t     len;
609
610         if (! mode_is_float(mode))
611                 return;
612
613         lowered_mode = get_lowered_mode(mode);
614         set_irn_mode(n, lowered_mode);
615
616         set_tarval_mode_output_option(mode, &hex_output);
617         tarval_snprintf(buf, 100, get_Const_tarval(n));
618
619         len = strlen(buf);
620         tv  = new_tarval_from_str(buf, len, lowered_mode);
621         set_Const_tarval(n, tv);
622 }
623
624 /**
625  * Transforms a Conv into the appropriate soft float function.
626  */
627 static void lower_Conv(ir_node *n)
628 {
629         ir_node         *symconst;
630         ir_node         *block       = get_nodes_block(n);
631         ir_node         *call_result = NULL;
632         dbg_info        *dbgi        = get_irn_dbg_info(n);
633         ir_graph        *irg         = get_irn_irg(n);
634         ir_node         *op          = get_Conv_op(n);
635         ir_mode         *mode        = get_irn_mode(n);
636         ir_mode         *op_mode     = get_irn_mode(op);
637
638         if (! mode_is_float(mode) && ! mode_is_float(op_mode))
639                 return;
640
641         /* Remove unnecessary Convs. */
642         if (op_mode == mode) {
643                 exchange(n, op);
644                 return;
645         }
646         else if (op_mode == mode_Hs || op_mode == mode_Bs) {
647                 op_mode = mode_Is;
648                 op     = new_rd_Conv(dbgi, block, op, op_mode);
649         }
650         else if (op_mode == mode_Hu || op_mode == mode_Bu) {
651                 op_mode = mode_Iu;
652                 op     = new_rd_Conv(dbgi, block, op, op_mode);
653         }
654
655         if (mode_is_float(op_mode) && mode_is_float(mode)) {
656                 if (get_mode_size_bits(op_mode) > get_mode_size_bits(mode))
657                         symconst = create_softfloat_symconst(n, "trunc");
658                 else
659                         symconst = create_softfloat_symconst(n, "extend");
660         }
661         else if (mode_is_float(op_mode)) {
662                 if (mode_is_signed(mode))
663                         symconst = create_softfloat_symconst(n, "fix");
664                 else
665                         symconst = create_softfloat_symconst(n, "fixuns");
666         }
667         else {
668                 if (mode_is_signed(op_mode))
669                         symconst = create_softfloat_symconst(n, "float");
670                 else
671                         symconst = create_softfloat_symconst(n, "floatun");
672         }
673
674         ir_node *call;
675         ir_node *call_results;
676         ir_node *in[1]    = {op};
677         ir_node *nomem    = get_irg_no_mem(irg);
678         ir_type *type     = get_softfloat_type(n);
679         ir_mode *res_mode = get_type_mode(get_method_res_type(type, 0));
680
681         call         = new_rd_Call(dbgi, block, nomem, symconst, 1, in, type);
682         call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
683         call_result  = new_r_Proj(call_results, res_mode, 0);
684
685         /* Check whether we need a Conv for the result. */
686         if (res_mode != mode)
687                 call_result = new_rd_Conv(dbgi, block, call_result, mode);
688
689         exchange(n, call_result);
690 }
691
692 /**
693  * Transforms a Div into the appropriate soft float function.
694  */
695 static void lower_Div(ir_node *n)
696 {
697         ir_node  *symconst;
698         ir_node  *block       = get_nodes_block(n);
699         ir_node  *call_result = NULL;
700         dbg_info *dbgi        = get_irn_dbg_info(n);
701         ir_graph *irg         = get_irn_irg(n);
702         ir_node  *left        = get_Div_left(n);
703         ir_mode  *mode        = get_Div_resmode(n);
704         ir_node  *right       = get_Div_right(n);
705
706         if (! mode_is_float(mode))
707                 return;
708
709         symconst = create_softfloat_symconst(n, "div");
710
711         ir_node *call;
712         ir_node *call_results;
713         ir_node *in[2]    = {left, right};
714         ir_node *nomem    = get_irg_no_mem(irg);
715         ir_type *type     = get_softfloat_type(n);
716         ir_mode *res_mode = get_type_mode(get_method_res_type(type, 0));
717
718         call         = new_rd_Call(dbgi, block, nomem, symconst, 2, in, type);
719         call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
720         call_result  = new_r_Proj(call_results, res_mode, 0);
721
722         set_irn_pinned(call, get_irn_pinned(n));
723
724         foreach_out_edge_safe(n, edge) {
725                 ir_node *proj = get_edge_src_irn(edge);
726                 if (! is_Proj(proj))
727                         continue;
728
729                 switch (get_Proj_proj(proj)) {
730                 case pn_Div_M:
731                         set_Proj_pred(proj, call);
732                         set_Proj_proj(proj, pn_Call_M);
733                         break;
734                 case pn_Div_X_regular:
735                         set_Proj_pred(proj, call);
736                         set_Proj_proj(proj, pn_Call_X_regular);
737                         break;
738                 case pn_Div_X_except:
739                         set_Proj_pred(proj, call);
740                         set_Proj_proj(proj, pn_Call_X_except);
741                         break;
742                 case pn_Div_res:
743                         exchange(proj, call_result);
744                         break;
745                 default:
746                         assert(0 && "unexpected Proj number");
747                 }
748         }
749
750 }
751
752 /**
753  * Adapts the resmode of a Div.
754  */
755 static void lower_Div_mode(ir_node *n)
756 {
757         ir_mode *res_mode         = get_Div_resmode(n);
758         ir_mode *lowered_res_mode = get_lowered_mode(res_mode);
759         ir_mode *mode             = get_irn_mode(n);
760         ir_mode *lowered_mode     = get_lowered_mode(mode);
761
762         set_irn_mode(n, lowered_mode);
763         set_Div_resmode(n, lowered_res_mode);
764 }
765
766 /**
767  * Adapts the ls_mode of a Load.
768  */
769 static void lower_Load(ir_node *n)
770 {
771         ir_mode *ls_mode         = get_Load_mode(n);
772         ir_mode *lowered_ls_mode = get_lowered_mode(ls_mode);
773         ir_mode *mode            = get_irn_mode(n);
774         ir_mode *lowered_mode    = get_lowered_mode(mode);
775
776         set_irn_mode(n, lowered_mode);
777         set_Load_mode(n, lowered_ls_mode);
778 }
779
780 /**
781  * Transforms a Minus into the appropriate soft float function.
782  */
783 static void lower_Minus(ir_node *n)
784 {
785         ir_node         *symconst;
786         ir_node         *block       = get_nodes_block(n);
787         ir_node         *call_result = NULL;
788         dbg_info        *dbgi        = get_irn_dbg_info(n);
789         ir_graph        *irg         = get_irn_irg(n);
790         ir_mode         *mode        = get_irn_mode(n);
791         ir_node         *op          = get_Minus_op(n);
792
793         if (! mode_is_float(mode))
794                 return;
795
796         symconst = create_softfloat_symconst(n, "neg");
797
798         ir_node *call;
799         ir_node *call_results;
800         ir_node *in[1]    = {op};
801         ir_node *nomem    = get_irg_no_mem(irg);
802         ir_type *type     = get_softfloat_type(n);
803         ir_mode *res_mode = get_type_mode(get_method_res_type(type, 0));
804
805         call         = new_rd_Call(dbgi, block, nomem, symconst, 1, in, type);
806         call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
807         call_result  = new_r_Proj(call_results, res_mode, 0);
808
809         exchange(n, call_result);
810 }
811
812 /**
813  * Transforms a Mul into the appropriate soft float function.
814  */
815 static void lower_Mul(ir_node *n)
816 {
817         ir_node         *symconst;
818         ir_node         *block       = get_nodes_block(n);
819         ir_node         *call_result = NULL;
820         dbg_info        *dbgi        = get_irn_dbg_info(n);
821         ir_graph        *irg         = get_irn_irg(n);
822         ir_node         *left        = get_Mul_left(n);
823         ir_mode         *mode        = get_irn_mode(n);
824         ir_node         *right       = get_Mul_right(n);
825
826         if (! mode_is_float(mode))
827                 return;
828
829         symconst = create_softfloat_symconst(n, "mul");
830
831         ir_node *call;
832         ir_node *call_results;
833         ir_node *in[2]    = {left, right};
834         ir_node *nomem    = get_irg_no_mem(irg);
835         ir_type *type     = get_softfloat_type(n);
836         ir_mode *res_mode = get_type_mode(get_method_res_type(type, 0));
837
838         call         = new_rd_Call(dbgi, block, nomem, symconst, 2, in, type);
839         call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
840         call_result  = new_r_Proj(call_results, res_mode, 0);
841
842         exchange(n, call_result);
843 }
844
845 /**
846  * Transforms a Sub into the appropriate soft float function.
847  */
848 static void lower_Sub(ir_node *n)
849 {
850         ir_node         *symconst;
851         ir_node         *block       = get_nodes_block(n);
852         ir_node         *call_result = NULL;
853         dbg_info        *dbgi        = get_irn_dbg_info(n);
854         ir_graph        *irg         = get_irn_irg(n);
855         ir_node         *left        = get_Sub_left(n);
856         ir_mode         *mode        = get_irn_mode(n);
857         ir_node         *right       = get_Sub_right(n);
858
859         if (! mode_is_float(mode))
860                 return;
861
862         symconst = create_softfloat_symconst(n, "sub");
863
864         ir_node *call;
865         ir_node *call_results;
866         ir_node *in[2]    = {left, right};
867         ir_node *nomem    = get_irg_no_mem(irg);
868         ir_type *type     = get_softfloat_type(n);
869         ir_mode *res_mode = get_type_mode(get_method_res_type(type, 0));
870
871         call         = new_rd_Call(dbgi, block, nomem, symconst, 2, in, type);
872         call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
873         call_result  = new_r_Proj(call_results, res_mode, 0);
874
875         exchange(n, call_result);
876 }
877
878 /**
879  * Enter a lowering function into an ir_op.
880  */
881 static void ir_register_softloat_lower_function(ir_op *op, lower_softfloat_func func)
882 {
883         op->ops.generic = (op_func)func;
884 }
885
886 /*
887  * Initializes softfloat lowering.
888  */
889 static void ir_prepare_softfloat_lowering(void)
890 {
891         FIRM_DBG_REGISTER(dbg, "firm.lower.softfloat");
892
893         if (! lowered_type)
894                 lowered_type = pmap_create();
895
896         if (! binop_tp_d) {
897                 binop_tp_d = new_type_method(2, 1);
898                 set_method_param_type(binop_tp_d, 0, get_type_for_mode(mode_D));
899                 set_method_param_type(binop_tp_d, 1, get_type_for_mode(mode_D));
900                 set_method_res_type(binop_tp_d, 0, get_type_for_mode(mode_D));
901         }
902
903         if (! binop_tp_f) {
904                 binop_tp_f = new_type_method(2, 1);
905                 set_method_param_type(binop_tp_f, 0, get_type_for_mode(mode_F));
906                 set_method_param_type(binop_tp_f, 1, get_type_for_mode(mode_F));
907                 set_method_res_type(binop_tp_f, 0, get_type_for_mode(mode_F));
908         }
909
910         if (! cmp_tp_d) {
911                 cmp_tp_d = new_type_method(2, 1);
912                 set_method_param_type(cmp_tp_d, 0, get_type_for_mode(mode_D));
913                 set_method_param_type(cmp_tp_d, 1, get_type_for_mode(mode_D));
914                 set_method_res_type(cmp_tp_d, 0, get_type_for_mode(mode_Is));
915         }
916
917         if (! cmp_tp_f) {
918                 cmp_tp_f = new_type_method(2, 1);
919                 set_method_param_type(cmp_tp_f, 0, get_type_for_mode(mode_F));
920                 set_method_param_type(cmp_tp_f, 1, get_type_for_mode(mode_F));
921                 set_method_res_type(cmp_tp_f, 0, get_type_for_mode(mode_Is));
922         }
923
924         if (! unop_tp_d) {
925                 unop_tp_d = new_type_method(1, 1);
926                 set_method_param_type(unop_tp_d, 0, get_type_for_mode(mode_D));
927                 set_method_res_type(unop_tp_d, 0, get_type_for_mode(mode_D));
928         }
929
930         if (! unop_tp_f) {
931                 unop_tp_f = new_type_method(1, 1);
932                 set_method_param_type(unop_tp_f, 0, get_type_for_mode(mode_F));
933                 set_method_res_type(unop_tp_f, 0, get_type_for_mode(mode_F));
934         }
935
936         if (! unop_tp_d_f) {
937                 unop_tp_d_f = new_type_method(1, 1);
938                 set_method_param_type(unop_tp_d_f, 0, get_type_for_mode(mode_D));
939                 set_method_res_type(unop_tp_d_f, 0, get_type_for_mode(mode_F));
940         }
941
942         if (! unop_tp_d_is) {
943                 unop_tp_d_is = new_type_method(1, 1);
944                 set_method_param_type(unop_tp_d_is, 0, get_type_for_mode(mode_D));
945                 set_method_res_type(unop_tp_d_is, 0, get_type_for_mode(mode_Is));
946         }
947
948         if (! unop_tp_d_iu) {
949                 unop_tp_d_iu = new_type_method(1, 1);
950                 set_method_param_type(unop_tp_d_iu, 0, get_type_for_mode(mode_D));
951                 set_method_res_type(unop_tp_d_iu, 0, get_type_for_mode(mode_Iu));
952         }
953
954         if (! unop_tp_d_ls) {
955                 unop_tp_d_ls = new_type_method(1, 1);
956                 set_method_param_type(unop_tp_d_ls, 0, get_type_for_mode(mode_D));
957                 set_method_res_type(unop_tp_d_ls, 0, get_type_for_mode(mode_Ls));
958         }
959
960         if (! unop_tp_d_lu) {
961                 unop_tp_d_lu = new_type_method(1, 1);
962                 set_method_param_type(unop_tp_d_lu, 0, get_type_for_mode(mode_D));
963                 set_method_res_type(unop_tp_d_lu, 0, get_type_for_mode(mode_Lu));
964         }
965
966         if (! unop_tp_f_d) {
967                 unop_tp_f_d = new_type_method(1, 1);
968                 set_method_param_type(unop_tp_f_d, 0, get_type_for_mode(mode_F));
969                 set_method_res_type(unop_tp_f_d, 0, get_type_for_mode(mode_D));
970         }
971
972         if (! unop_tp_f_is) {
973                 unop_tp_f_is = new_type_method(1, 1);
974                 set_method_param_type(unop_tp_f_is, 0, get_type_for_mode(mode_F));
975                 set_method_res_type(unop_tp_f_is, 0, get_type_for_mode(mode_Is));
976         }
977
978         if (! unop_tp_f_iu) {
979                 unop_tp_f_iu = new_type_method(1, 1);
980                 set_method_param_type(unop_tp_f_iu, 0, get_type_for_mode(mode_F));
981                 set_method_res_type(unop_tp_f_iu, 0, get_type_for_mode(mode_Iu));
982         }
983
984         if (! unop_tp_f_ls) {
985                 unop_tp_f_ls = new_type_method(1, 1);
986                 set_method_param_type(unop_tp_f_ls, 0, get_type_for_mode(mode_F));
987                 set_method_res_type(unop_tp_f_ls, 0, get_type_for_mode(mode_Ls));
988         }
989
990         if (! unop_tp_f_lu) {
991                 unop_tp_f_lu = new_type_method(1, 1);
992                 set_method_param_type(unop_tp_f_lu, 0, get_type_for_mode(mode_F));
993                 set_method_res_type(unop_tp_f_lu, 0, get_type_for_mode(mode_Lu));
994         }
995
996         if (! unop_tp_is_d) {
997                 unop_tp_is_d = new_type_method(1, 1);
998                 set_method_param_type(unop_tp_is_d, 0, get_type_for_mode(mode_Is));
999                 set_method_res_type(unop_tp_is_d, 0, get_type_for_mode(mode_D));
1000         }
1001
1002         if (! unop_tp_is_f) {
1003                 unop_tp_is_f = new_type_method(1, 1);
1004                 set_method_param_type(unop_tp_is_f, 0, get_type_for_mode(mode_Is));
1005                 set_method_res_type(unop_tp_is_f, 0, get_type_for_mode(mode_F));
1006         }
1007
1008         if (! unop_tp_iu_d) {
1009                 unop_tp_iu_d = new_type_method(1, 1);
1010                 set_method_param_type(unop_tp_iu_d, 0, get_type_for_mode(mode_Iu));
1011                 set_method_res_type(unop_tp_iu_d, 0, get_type_for_mode(mode_D));
1012         }
1013
1014         if (! unop_tp_iu_f) {
1015                 unop_tp_iu_f = new_type_method(1, 1);
1016                 set_method_param_type(unop_tp_iu_f, 0, get_type_for_mode(mode_Iu));
1017                 set_method_res_type(unop_tp_iu_f, 0, get_type_for_mode(mode_F));
1018         }
1019
1020         if (! unop_tp_ls_d) {
1021                 unop_tp_ls_d = new_type_method(1, 1);
1022                 set_method_param_type(unop_tp_ls_d, 0, get_type_for_mode(mode_Ls));
1023                 set_method_res_type(unop_tp_ls_d, 0, get_type_for_mode(mode_D));
1024         }
1025
1026         if (! unop_tp_ls_f) {
1027                 unop_tp_ls_f = new_type_method(1, 1);
1028                 set_method_param_type(unop_tp_ls_f, 0, get_type_for_mode(mode_Ls));
1029                 set_method_res_type(unop_tp_ls_f, 0, get_type_for_mode(mode_F));
1030         }
1031
1032         if (! unop_tp_lu_d) {
1033                 unop_tp_lu_d = new_type_method(1, 1);
1034                 set_method_param_type(unop_tp_lu_d, 0, get_type_for_mode(mode_Lu));
1035                 set_method_res_type(unop_tp_lu_d, 0, get_type_for_mode(mode_D));
1036         }
1037
1038         if (! unop_tp_lu_f) {
1039                 unop_tp_lu_f = new_type_method(1, 1);
1040                 set_method_param_type(unop_tp_lu_f, 0, get_type_for_mode(mode_Lu));
1041                 set_method_res_type(unop_tp_lu_f, 0, get_type_for_mode(mode_F));
1042         }
1043 }
1044
1045 /**
1046  * Callback to lower only the Mux nodes we created.
1047  */
1048 static int lower_mux_cb(ir_node *mux)
1049 {
1050         return ir_nodeset_contains(&created_mux_nodes, mux);
1051 }
1052
1053 void lower_floating_point(void)
1054 {
1055         size_t i;
1056         size_t n_irgs = get_irp_n_irgs();
1057
1058         FIRM_DBG_REGISTER(dbg, "firm.lower.softfloat");
1059
1060         ir_prepare_softfloat_lowering();
1061
1062         ir_clear_opcodes_generic_func();
1063         ir_register_softloat_lower_function(op_Add,   lower_Add);
1064         ir_register_softloat_lower_function(op_Cmp,   lower_Cmp);
1065         ir_register_softloat_lower_function(op_Conv,  lower_Conv);
1066         ir_register_softloat_lower_function(op_Div,   lower_Div);
1067         ir_register_softloat_lower_function(op_Minus, lower_Minus);
1068         ir_register_softloat_lower_function(op_Mul,   lower_Mul);
1069         ir_register_softloat_lower_function(op_Sub,   lower_Sub);
1070
1071         for (i = 0; i < n_irgs; ++i) {
1072                 ir_graph *irg = get_irp_irg(i);
1073
1074                 ir_nodeset_init(&created_mux_nodes);
1075
1076                 assure_edges(irg);
1077
1078                 irg_walk_graph(irg, NULL, lower_node, NULL);
1079
1080                 if (ir_nodeset_size(&created_mux_nodes) > 0)
1081                         lower_mux(irg, lower_mux_cb);
1082
1083                 ir_nodeset_destroy(&created_mux_nodes);
1084         }
1085
1086         ir_clear_opcodes_generic_func();
1087         ir_register_softloat_lower_function(op_Call,  lower_Call);
1088         ir_register_softloat_lower_function(op_Const, lower_Const);
1089         ir_register_softloat_lower_function(op_Div,   lower_Div_mode);
1090         ir_register_softloat_lower_function(op_Load,  lower_Load);
1091
1092         for (i = 0; i < n_irgs; ++i) {
1093                 ir_graph *irg          = get_irp_irg(i);
1094                 ir_entity *ent         = get_irg_entity(irg);
1095                 ir_type   *mtp         = get_entity_type(ent);
1096                 ir_type   *lowered_mtp = lower_method_type(mtp);
1097                 ir_type   *frame_tp    = get_irg_frame_type(irg);
1098                 size_t     n_members;
1099                 size_t     i;
1100
1101                 if (lowered_mtp != mtp)
1102                         set_entity_type(ent, lowered_mtp);
1103
1104                 irg_walk_graph(irg, NULL, lower_mode, NULL);
1105
1106                 /* fixup parameter entities */
1107                 n_members = get_compound_n_members(frame_tp);
1108                 for (i = 0; i < n_members; ++i) {
1109                         ir_entity *member = get_compound_member(frame_tp, i);
1110                         ir_type   *type   = get_entity_type(member);
1111                         if (is_Primitive_type(type)) {
1112                                 ir_type *lowered = lower_type(type);
1113                                 set_entity_type(member, lowered);
1114                         }
1115                 }
1116         }
1117 }