make opcode list global
[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 = (ir_type*)pmap_get(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         const ir_edge_t *edge;
706         const ir_edge_t *next;
707
708         if (! mode_is_float(mode))
709                 return;
710
711         symconst = create_softfloat_symconst(n, "div");
712
713         ir_node *call;
714         ir_node *call_results;
715         ir_node *in[2]    = {left, right};
716         ir_node *nomem    = get_irg_no_mem(irg);
717         ir_type *type     = get_softfloat_type(n);
718         ir_mode *res_mode = get_type_mode(get_method_res_type(type, 0));
719
720         call         = new_rd_Call(dbgi, block, nomem, symconst, 2, in, type);
721         call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
722         call_result  = new_r_Proj(call_results, res_mode, 0);
723
724         set_irn_pinned(call, get_irn_pinned(n));
725
726         foreach_out_edge_safe(n, edge, next) {
727                 ir_node *proj = get_edge_src_irn(edge);
728                 if (! is_Proj(proj))
729                         continue;
730
731                 switch (get_Proj_proj(proj)) {
732                 case pn_Div_M:
733                         set_Proj_pred(proj, call);
734                         set_Proj_proj(proj, pn_Call_M);
735                         break;
736                 case pn_Div_X_regular:
737                         set_Proj_pred(proj, call);
738                         set_Proj_proj(proj, pn_Call_X_regular);
739                         break;
740                 case pn_Div_X_except:
741                         set_Proj_pred(proj, call);
742                         set_Proj_proj(proj, pn_Call_X_except);
743                         break;
744                 case pn_Div_res:
745                         exchange(proj, call_result);
746                         break;
747                 default:
748                         assert(0 && "unexpected Proj number");
749                 }
750         }
751
752 }
753
754 /**
755  * Adapts the resmode of a Div.
756  */
757 static void lower_Div_mode(ir_node *n)
758 {
759         ir_mode *res_mode         = get_Div_resmode(n);
760         ir_mode *lowered_res_mode = get_lowered_mode(res_mode);
761         ir_mode *mode             = get_irn_mode(n);
762         ir_mode *lowered_mode     = get_lowered_mode(mode);
763
764         set_irn_mode(n, lowered_mode);
765         set_Div_resmode(n, lowered_res_mode);
766 }
767
768 /**
769  * Adapts the ls_mode of a Load.
770  */
771 static void lower_Load(ir_node *n)
772 {
773         ir_mode *ls_mode         = get_Load_mode(n);
774         ir_mode *lowered_ls_mode = get_lowered_mode(ls_mode);
775         ir_mode *mode            = get_irn_mode(n);
776         ir_mode *lowered_mode    = get_lowered_mode(mode);
777
778         set_irn_mode(n, lowered_mode);
779         set_Load_mode(n, lowered_ls_mode);
780 }
781
782 /**
783  * Transforms a Minus into the appropriate soft float function.
784  */
785 static void lower_Minus(ir_node *n)
786 {
787         ir_node         *symconst;
788         ir_node         *block       = get_nodes_block(n);
789         ir_node         *call_result = NULL;
790         dbg_info        *dbgi        = get_irn_dbg_info(n);
791         ir_graph        *irg         = get_irn_irg(n);
792         ir_mode         *mode        = get_irn_mode(n);
793         ir_node         *op          = get_Minus_op(n);
794
795         if (! mode_is_float(mode))
796                 return;
797
798         symconst = create_softfloat_symconst(n, "neg");
799
800         ir_node *call;
801         ir_node *call_results;
802         ir_node *in[1]    = {op};
803         ir_node *nomem    = get_irg_no_mem(irg);
804         ir_type *type     = get_softfloat_type(n);
805         ir_mode *res_mode = get_type_mode(get_method_res_type(type, 0));
806
807         call         = new_rd_Call(dbgi, block, nomem, symconst, 1, in, type);
808         call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
809         call_result  = new_r_Proj(call_results, res_mode, 0);
810
811         exchange(n, call_result);
812 }
813
814 /**
815  * Transforms a Mul into the appropriate soft float function.
816  */
817 static void lower_Mul(ir_node *n)
818 {
819         ir_node         *symconst;
820         ir_node         *block       = get_nodes_block(n);
821         ir_node         *call_result = NULL;
822         dbg_info        *dbgi        = get_irn_dbg_info(n);
823         ir_graph        *irg         = get_irn_irg(n);
824         ir_node         *left        = get_Mul_left(n);
825         ir_mode         *mode        = get_irn_mode(n);
826         ir_node         *right       = get_Mul_right(n);
827
828         if (! mode_is_float(mode))
829                 return;
830
831         symconst = create_softfloat_symconst(n, "mul");
832
833         ir_node *call;
834         ir_node *call_results;
835         ir_node *in[2]    = {left, right};
836         ir_node *nomem    = get_irg_no_mem(irg);
837         ir_type *type     = get_softfloat_type(n);
838         ir_mode *res_mode = get_type_mode(get_method_res_type(type, 0));
839
840         call         = new_rd_Call(dbgi, block, nomem, symconst, 2, in, type);
841         call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
842         call_result  = new_r_Proj(call_results, res_mode, 0);
843
844         exchange(n, call_result);
845 }
846
847 /**
848  * Transforms a Sub into the appropriate soft float function.
849  */
850 static void lower_Sub(ir_node *n)
851 {
852         ir_node         *symconst;
853         ir_node         *block       = get_nodes_block(n);
854         ir_node         *call_result = NULL;
855         dbg_info        *dbgi        = get_irn_dbg_info(n);
856         ir_graph        *irg         = get_irn_irg(n);
857         ir_node         *left        = get_Sub_left(n);
858         ir_mode         *mode        = get_irn_mode(n);
859         ir_node         *right       = get_Sub_right(n);
860
861         if (! mode_is_float(mode))
862                 return;
863
864         symconst = create_softfloat_symconst(n, "sub");
865
866         ir_node *call;
867         ir_node *call_results;
868         ir_node *in[2]    = {left, right};
869         ir_node *nomem    = get_irg_no_mem(irg);
870         ir_type *type     = get_softfloat_type(n);
871         ir_mode *res_mode = get_type_mode(get_method_res_type(type, 0));
872
873         call         = new_rd_Call(dbgi, block, nomem, symconst, 2, in, type);
874         call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
875         call_result  = new_r_Proj(call_results, res_mode, 0);
876
877         exchange(n, call_result);
878 }
879
880 /**
881  * Enter a lowering function into an ir_op.
882  */
883 static void ir_register_softloat_lower_function(ir_op *op, lower_softfloat_func func)
884 {
885         op->ops.generic = (op_func)func;
886 }
887
888 /*
889  * Initializes softfloat lowering.
890  */
891 static void ir_prepare_softfloat_lowering(void)
892 {
893         FIRM_DBG_REGISTER(dbg, "firm.lower.softfloat");
894
895         if (! lowered_type)
896                 lowered_type = pmap_create();
897
898         if (! binop_tp_d) {
899                 binop_tp_d = new_type_method(2, 1);
900                 set_method_param_type(binop_tp_d, 0, get_type_for_mode(mode_D));
901                 set_method_param_type(binop_tp_d, 1, get_type_for_mode(mode_D));
902                 set_method_res_type(binop_tp_d, 0, get_type_for_mode(mode_D));
903         }
904
905         if (! binop_tp_f) {
906                 binop_tp_f = new_type_method(2, 1);
907                 set_method_param_type(binop_tp_f, 0, get_type_for_mode(mode_F));
908                 set_method_param_type(binop_tp_f, 1, get_type_for_mode(mode_F));
909                 set_method_res_type(binop_tp_f, 0, get_type_for_mode(mode_F));
910         }
911
912         if (! cmp_tp_d) {
913                 cmp_tp_d = new_type_method(2, 1);
914                 set_method_param_type(cmp_tp_d, 0, get_type_for_mode(mode_D));
915                 set_method_param_type(cmp_tp_d, 1, get_type_for_mode(mode_D));
916                 set_method_res_type(cmp_tp_d, 0, get_type_for_mode(mode_Is));
917         }
918
919         if (! cmp_tp_f) {
920                 cmp_tp_f = new_type_method(2, 1);
921                 set_method_param_type(cmp_tp_f, 0, get_type_for_mode(mode_F));
922                 set_method_param_type(cmp_tp_f, 1, get_type_for_mode(mode_F));
923                 set_method_res_type(cmp_tp_f, 0, get_type_for_mode(mode_Is));
924         }
925
926         if (! unop_tp_d) {
927                 unop_tp_d = new_type_method(1, 1);
928                 set_method_param_type(unop_tp_d, 0, get_type_for_mode(mode_D));
929                 set_method_res_type(unop_tp_d, 0, get_type_for_mode(mode_D));
930         }
931
932         if (! unop_tp_f) {
933                 unop_tp_f = new_type_method(1, 1);
934                 set_method_param_type(unop_tp_f, 0, get_type_for_mode(mode_F));
935                 set_method_res_type(unop_tp_f, 0, get_type_for_mode(mode_F));
936         }
937
938         if (! unop_tp_d_f) {
939                 unop_tp_d_f = new_type_method(1, 1);
940                 set_method_param_type(unop_tp_d_f, 0, get_type_for_mode(mode_D));
941                 set_method_res_type(unop_tp_d_f, 0, get_type_for_mode(mode_F));
942         }
943
944         if (! unop_tp_d_is) {
945                 unop_tp_d_is = new_type_method(1, 1);
946                 set_method_param_type(unop_tp_d_is, 0, get_type_for_mode(mode_D));
947                 set_method_res_type(unop_tp_d_is, 0, get_type_for_mode(mode_Is));
948         }
949
950         if (! unop_tp_d_iu) {
951                 unop_tp_d_iu = new_type_method(1, 1);
952                 set_method_param_type(unop_tp_d_iu, 0, get_type_for_mode(mode_D));
953                 set_method_res_type(unop_tp_d_iu, 0, get_type_for_mode(mode_Iu));
954         }
955
956         if (! unop_tp_d_ls) {
957                 unop_tp_d_ls = new_type_method(1, 1);
958                 set_method_param_type(unop_tp_d_ls, 0, get_type_for_mode(mode_D));
959                 set_method_res_type(unop_tp_d_ls, 0, get_type_for_mode(mode_Ls));
960         }
961
962         if (! unop_tp_d_lu) {
963                 unop_tp_d_lu = new_type_method(1, 1);
964                 set_method_param_type(unop_tp_d_lu, 0, get_type_for_mode(mode_D));
965                 set_method_res_type(unop_tp_d_lu, 0, get_type_for_mode(mode_Lu));
966         }
967
968         if (! unop_tp_f_d) {
969                 unop_tp_f_d = new_type_method(1, 1);
970                 set_method_param_type(unop_tp_f_d, 0, get_type_for_mode(mode_F));
971                 set_method_res_type(unop_tp_f_d, 0, get_type_for_mode(mode_D));
972         }
973
974         if (! unop_tp_f_is) {
975                 unop_tp_f_is = new_type_method(1, 1);
976                 set_method_param_type(unop_tp_f_is, 0, get_type_for_mode(mode_F));
977                 set_method_res_type(unop_tp_f_is, 0, get_type_for_mode(mode_Is));
978         }
979
980         if (! unop_tp_f_iu) {
981                 unop_tp_f_iu = new_type_method(1, 1);
982                 set_method_param_type(unop_tp_f_iu, 0, get_type_for_mode(mode_F));
983                 set_method_res_type(unop_tp_f_iu, 0, get_type_for_mode(mode_Iu));
984         }
985
986         if (! unop_tp_f_ls) {
987                 unop_tp_f_ls = new_type_method(1, 1);
988                 set_method_param_type(unop_tp_f_ls, 0, get_type_for_mode(mode_F));
989                 set_method_res_type(unop_tp_f_ls, 0, get_type_for_mode(mode_Ls));
990         }
991
992         if (! unop_tp_f_lu) {
993                 unop_tp_f_lu = new_type_method(1, 1);
994                 set_method_param_type(unop_tp_f_lu, 0, get_type_for_mode(mode_F));
995                 set_method_res_type(unop_tp_f_lu, 0, get_type_for_mode(mode_Lu));
996         }
997
998         if (! unop_tp_is_d) {
999                 unop_tp_is_d = new_type_method(1, 1);
1000                 set_method_param_type(unop_tp_is_d, 0, get_type_for_mode(mode_Is));
1001                 set_method_res_type(unop_tp_is_d, 0, get_type_for_mode(mode_D));
1002         }
1003
1004         if (! unop_tp_is_f) {
1005                 unop_tp_is_f = new_type_method(1, 1);
1006                 set_method_param_type(unop_tp_is_f, 0, get_type_for_mode(mode_Is));
1007                 set_method_res_type(unop_tp_is_f, 0, get_type_for_mode(mode_F));
1008         }
1009
1010         if (! unop_tp_iu_d) {
1011                 unop_tp_iu_d = new_type_method(1, 1);
1012                 set_method_param_type(unop_tp_iu_d, 0, get_type_for_mode(mode_Iu));
1013                 set_method_res_type(unop_tp_iu_d, 0, get_type_for_mode(mode_D));
1014         }
1015
1016         if (! unop_tp_iu_f) {
1017                 unop_tp_iu_f = new_type_method(1, 1);
1018                 set_method_param_type(unop_tp_iu_f, 0, get_type_for_mode(mode_Iu));
1019                 set_method_res_type(unop_tp_iu_f, 0, get_type_for_mode(mode_F));
1020         }
1021
1022         if (! unop_tp_ls_d) {
1023                 unop_tp_ls_d = new_type_method(1, 1);
1024                 set_method_param_type(unop_tp_ls_d, 0, get_type_for_mode(mode_Ls));
1025                 set_method_res_type(unop_tp_ls_d, 0, get_type_for_mode(mode_D));
1026         }
1027
1028         if (! unop_tp_ls_f) {
1029                 unop_tp_ls_f = new_type_method(1, 1);
1030                 set_method_param_type(unop_tp_ls_f, 0, get_type_for_mode(mode_Ls));
1031                 set_method_res_type(unop_tp_ls_f, 0, get_type_for_mode(mode_F));
1032         }
1033
1034         if (! unop_tp_lu_d) {
1035                 unop_tp_lu_d = new_type_method(1, 1);
1036                 set_method_param_type(unop_tp_lu_d, 0, get_type_for_mode(mode_Lu));
1037                 set_method_res_type(unop_tp_lu_d, 0, get_type_for_mode(mode_D));
1038         }
1039
1040         if (! unop_tp_lu_f) {
1041                 unop_tp_lu_f = new_type_method(1, 1);
1042                 set_method_param_type(unop_tp_lu_f, 0, get_type_for_mode(mode_Lu));
1043                 set_method_res_type(unop_tp_lu_f, 0, get_type_for_mode(mode_F));
1044         }
1045 }
1046
1047 /**
1048  * Callback to lower only the Mux nodes we created.
1049  */
1050 static int lower_mux_cb(ir_node *mux)
1051 {
1052         return ir_nodeset_contains(&created_mux_nodes, mux);
1053 }
1054
1055 void lower_floating_point(void)
1056 {
1057         size_t i;
1058         size_t n_irgs = get_irp_n_irgs();
1059
1060         FIRM_DBG_REGISTER(dbg, "firm.lower.softfloat");
1061
1062         ir_prepare_softfloat_lowering();
1063
1064         ir_clear_opcodes_generic_func();
1065         ir_register_softloat_lower_function(op_Add,   lower_Add);
1066         ir_register_softloat_lower_function(op_Cmp,   lower_Cmp);
1067         ir_register_softloat_lower_function(op_Conv,  lower_Conv);
1068         ir_register_softloat_lower_function(op_Div,   lower_Div);
1069         ir_register_softloat_lower_function(op_Minus, lower_Minus);
1070         ir_register_softloat_lower_function(op_Mul,   lower_Mul);
1071         ir_register_softloat_lower_function(op_Sub,   lower_Sub);
1072
1073         for (i = 0; i < n_irgs; ++i) {
1074                 ir_graph *irg = get_irp_irg(i);
1075
1076                 ir_nodeset_init(&created_mux_nodes);
1077
1078                 edges_assure(irg);
1079
1080                 irg_walk_graph(irg, NULL, lower_node, NULL);
1081
1082                 if (ir_nodeset_size(&created_mux_nodes) > 0)
1083                         lower_mux(irg, lower_mux_cb);
1084
1085                 ir_nodeset_destroy(&created_mux_nodes);
1086         }
1087
1088         ir_clear_opcodes_generic_func();
1089         ir_register_softloat_lower_function(op_Call,  lower_Call);
1090         ir_register_softloat_lower_function(op_Const, lower_Const);
1091         ir_register_softloat_lower_function(op_Div,   lower_Div_mode);
1092         ir_register_softloat_lower_function(op_Load,  lower_Load);
1093
1094         for (i = 0; i < n_irgs; ++i) {
1095                 ir_graph *irg          = get_irp_irg(i);
1096                 ir_entity *ent         = get_irg_entity(irg);
1097                 ir_type   *mtp         = get_entity_type(ent);
1098                 ir_type   *lowered_mtp = lower_method_type(mtp);
1099                 ir_type   *frame_tp    = get_irg_frame_type(irg);
1100                 size_t     n_members;
1101                 size_t     i;
1102
1103                 if (lowered_mtp != mtp)
1104                         set_entity_type(ent, lowered_mtp);
1105
1106                 irg_walk_graph(irg, NULL, lower_mode, NULL);
1107
1108                 /* fixup parameter entities */
1109                 n_members = get_compound_n_members(frame_tp);
1110                 for (i = 0; i < n_members; ++i) {
1111                         ir_entity *member = get_compound_member(frame_tp, i);
1112                         ir_type   *type   = get_entity_type(member);
1113                         if (is_Primitive_type(type)) {
1114                                 ir_type *lowered = lower_type(type);
1115                                 set_entity_type(member, lowered);
1116                         }
1117                 }
1118         }
1119 }