Use new_*_Const(irg, get_mode_$VAL(mode)) instead of new_*_Const_long(irg, mode,...
[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 "error.h"
36
37 static pmap *entities;
38 static bool dont_lower[ir_bk_last+1];
39
40 static const char *get_builtin_name(ir_builtin_kind kind)
41 {
42         switch (kind) {
43         case ir_bk_ffs:      return "ffs";
44         case ir_bk_clz:      return "clz";
45         case ir_bk_ctz:      return "ctz";
46         case ir_bk_popcount: return "popcount";
47         case ir_bk_parity:   return "parity";
48         case ir_bk_bswap:    return "bswap";
49         case ir_bk_prefetch:
50         case ir_bk_trap:
51         case ir_bk_debugbreak:
52         case ir_bk_return_address:
53         case ir_bk_frame_address:
54         case ir_bk_inport:
55         case ir_bk_outport:
56         case ir_bk_inner_trampoline:
57                 break;
58         }
59         abort();
60 }
61
62 static const char *get_gcc_machmode(ir_type *type)
63 {
64         assert(is_Primitive_type(type));
65         switch (get_type_size_bytes(type)) {
66         case 4: return "si";
67         case 8: return "di";
68         default:
69                 panic("couldn't determine gcc machmode for type %+F", type);
70         }
71 }
72
73 static void replace_with_call(ir_node *node)
74 {
75         ir_graph       *irg   = get_irn_irg(node);
76         ir_node        *block = get_nodes_block(node);
77         ir_builtin_kind kind  = get_Builtin_kind(node);
78         const char     *name  = get_builtin_name(kind);
79         ir_type        *mtp   = get_Builtin_type(node);
80         ir_type        *arg1  = get_method_param_type(mtp, 0);
81         dbg_info       *dbgi  = get_irn_dbg_info(node);
82         ir_node        *mem   = get_Builtin_mem(node);
83         const char     *gcc_machmode = get_gcc_machmode(arg1);
84         int             n_params     = get_Builtin_n_params(node);
85         ir_node       **params       = get_Builtin_param_arr(node);
86         ir_type        *res_type = get_method_res_type(mtp, 0);
87         ir_mode        *res_mode = get_type_mode(res_type);
88         ir_node        *call_mem;
89         ir_node        *call_ress;
90         ir_node        *call_res;
91         ir_entity      *entity;
92         ir_node        *symconst;
93         ir_node        *call;
94         ident          *id;
95         union symconst_symbol sym;
96
97         char buf[64];
98         snprintf(buf, sizeof(buf), "__%s%s2", name, gcc_machmode);
99         id = new_id_from_str(buf);
100
101         entity = pmap_get(entities, id);
102         if (entity == NULL) {
103                 ir_type   *glob   = get_glob_type();
104                 entity = new_entity(glob, id, mtp);
105                 set_entity_visibility(entity, ir_visibility_external);
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         turn_into_tuple(node, 2);
117         set_irn_n(node, pn_Builtin_M, call_mem);
118         set_irn_n(node, pn_Builtin_1_result, call_res);
119 }
120
121 static void lower_builtin(ir_node *node, void *env)
122 {
123         ir_builtin_kind kind;
124         (void) env;
125         if (!is_Builtin(node))
126                 return;
127
128         kind = get_Builtin_kind(node);
129         if (dont_lower[kind])
130                 return;
131
132         switch (kind) {
133         case ir_bk_prefetch: {
134                 /* just remove it */
135                 ir_node *mem = get_Builtin_mem(node);
136                 turn_into_tuple(node, 1);
137                 set_irn_n(node, pn_Builtin_M, mem);
138                 break;
139         }
140         case ir_bk_ffs:
141         case ir_bk_clz:
142         case ir_bk_ctz:
143         case ir_bk_popcount:
144         case ir_bk_parity:
145         case ir_bk_bswap:
146                 /* replace with a call */
147                 replace_with_call(node);
148                 return;
149
150         case ir_bk_trap:
151         case ir_bk_debugbreak:
152         case ir_bk_return_address:
153         case ir_bk_frame_address:
154         case ir_bk_inport:
155         case ir_bk_outport:
156         case ir_bk_inner_trampoline:
157                 /* can't do anything about these, backend will probably fail now */
158                 panic("Can't lower Builtin node of kind %+F", node);
159         }
160 }
161
162 void lower_builtins(size_t n_exceptions, ir_builtin_kind *exceptions)
163 {
164         size_t i;
165         size_t n_irgs;
166         memset(dont_lower, 0, sizeof(dont_lower));
167         for (i = 0; i < n_exceptions; ++i) {
168                 dont_lower[exceptions[i]] = true;
169         }
170
171         entities = pmap_create();
172
173         n_irgs = get_irp_n_irgs();
174         for (i = 0; i < n_irgs; ++i) {
175                 ir_graph *irg = get_irp_irg(i);
176                 irg_walk_graph(irg, NULL, lower_builtin, NULL);
177         }
178
179         pmap_destroy(entities);
180 }