irgmod: Pass the new inputs to turn_into_tuple() instead of initialising them with...
[libfirm] / ir / lower / lower_builtins.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   Lowering of builtins to compiler-lib calls
23  * @author  Matthias Braun
24  */
25 #include "config.h"
26
27 #include "lower_builtins.h"
28 #include <stdbool.h>
29 #include <stdlib.h>
30 #include "adt/pmap.h"
31 #include "irnode_t.h"
32 #include "ircons_t.h"
33 #include "irgmod.h"
34 #include "irgwalk.h"
35 #include "iroptimize.h"
36 #include "error.h"
37 #include "util.h"
38
39 static pmap *entities;
40 static bool dont_lower[ir_bk_last+1];
41
42 static const char *get_builtin_name(ir_builtin_kind kind)
43 {
44         switch (kind) {
45         case ir_bk_ffs:      return "ffs";
46         case ir_bk_clz:      return "clz";
47         case ir_bk_ctz:      return "ctz";
48         case ir_bk_popcount: return "popcount";
49         case ir_bk_parity:   return "parity";
50         case ir_bk_bswap:    return "bswap";
51         case ir_bk_prefetch:
52         case ir_bk_trap:
53         case ir_bk_debugbreak:
54         case ir_bk_return_address:
55         case ir_bk_frame_address:
56         case ir_bk_inport:
57         case ir_bk_outport:
58         case ir_bk_inner_trampoline:
59                 break;
60         }
61         abort();
62 }
63
64 static const char *get_gcc_machmode(ir_type *type)
65 {
66         assert(is_Primitive_type(type));
67         switch (get_type_size_bytes(type)) {
68         case 4: return "si";
69         case 8: return "di";
70         default:
71                 panic("couldn't determine gcc machmode for type %+F", type);
72         }
73 }
74
75 static void replace_with_call(ir_node *node)
76 {
77         ir_graph       *irg   = get_irn_irg(node);
78         ir_node        *block = get_nodes_block(node);
79         ir_builtin_kind kind  = get_Builtin_kind(node);
80         const char     *name  = get_builtin_name(kind);
81         ir_type        *mtp   = get_Builtin_type(node);
82         ir_type        *arg1  = get_method_param_type(mtp, 0);
83         dbg_info       *dbgi  = get_irn_dbg_info(node);
84         ir_node        *mem   = get_Builtin_mem(node);
85         const char     *gcc_machmode = get_gcc_machmode(arg1);
86         int             n_params     = get_Builtin_n_params(node);
87         ir_node       **params       = get_Builtin_param_arr(node);
88         ir_type        *res_type = get_method_res_type(mtp, 0);
89         ir_mode        *res_mode = get_type_mode(res_type);
90         ir_node        *call_mem;
91         ir_node        *call_ress;
92         ir_node        *call_res;
93         ir_entity      *entity;
94         ir_node        *symconst;
95         ir_node        *call;
96         ident          *id;
97         union symconst_symbol sym;
98
99         char buf[64];
100         snprintf(buf, sizeof(buf), "__%s%s2", name, gcc_machmode);
101         id = new_id_from_str(buf);
102
103         entity = pmap_get(ir_entity, entities, id);
104         if (entity == NULL) {
105                 entity = create_compilerlib_entity(id, mtp);
106                 pmap_insert(entities, id, entity);
107         }
108
109         sym.entity_p = entity;
110         symconst  = new_r_SymConst(irg, mode_P, sym, symconst_addr_ent);
111         call      = new_rd_Call(dbgi, block, mem, symconst, n_params, params, mtp);
112         call_mem  = new_r_Proj(call, mode_M, pn_Call_M);
113         call_ress = new_r_Proj(call, mode_T, pn_Call_T_result);
114         call_res  = new_r_Proj(call_ress, res_mode, 0);
115
116         ir_node *const in[] = {
117                 [pn_Builtin_M]       = call_mem,
118                 [pn_Builtin_max + 1] = call_res,
119         };
120         turn_into_tuple(node, ARRAY_SIZE(in), in);
121 }
122
123 static void lower_builtin(ir_node *node, void *env)
124 {
125         ir_builtin_kind kind;
126         (void) env;
127         if (!is_Builtin(node))
128                 return;
129
130         kind = get_Builtin_kind(node);
131         if (dont_lower[kind])
132                 return;
133
134         switch (kind) {
135         case ir_bk_prefetch: {
136                 /* just remove it */
137                 ir_node *mem = get_Builtin_mem(node);
138                 ir_node *const in[] = { mem };
139                 turn_into_tuple(node, ARRAY_SIZE(in), in);
140                 break;
141         }
142
143         case ir_bk_ffs:
144         case ir_bk_clz:
145         case ir_bk_ctz:
146         case ir_bk_popcount:
147         case ir_bk_parity:
148         case ir_bk_bswap:
149                 /* replace with a call */
150                 replace_with_call(node);
151                 return;
152
153         case ir_bk_trap:
154         case ir_bk_debugbreak:
155         case ir_bk_return_address:
156         case ir_bk_frame_address:
157         case ir_bk_inport:
158         case ir_bk_outport:
159         case ir_bk_inner_trampoline:
160                 /* can't do anything about these, backend will probably fail now */
161                 panic("Can't lower Builtin node of kind %+F", node);
162         }
163 }
164
165 void lower_builtins(size_t n_exceptions, ir_builtin_kind *exceptions)
166 {
167         size_t i;
168         size_t n_irgs;
169         memset(dont_lower, 0, sizeof(dont_lower));
170         for (i = 0; i < n_exceptions; ++i) {
171                 dont_lower[exceptions[i]] = true;
172         }
173
174         entities = pmap_create();
175
176         n_irgs = get_irp_n_irgs();
177         for (i = 0; i < n_irgs; ++i) {
178                 ir_graph *irg = get_irp_irg(i);
179                 irg_walk_graph(irg, NULL, lower_builtin, NULL);
180         }
181
182         pmap_destroy(entities);
183 }