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