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