simplify/rework lower_calls interface and code
[libfirm] / include / libfirm / lowering.h
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 high level constructs.
23  * @author  Michael Beck
24  * @version $Id$
25  */
26 #ifndef FIRM_LOWERING_H
27 #define FIRM_LOWERING_H
28
29 #include <stddef.h>
30
31 #include "firm_types.h"
32
33 #include "begin.h"
34
35 /**
36  * Lower CopyB nodes of size smaller that max_size into Loads/Stores
37  */
38 FIRM_API void lower_CopyB(ir_graph *irg, unsigned max_size,
39                           unsigned native_mode_bytes);
40
41 /**
42  * Lowers all Switches (Cond nodes with non-boolean mode) depending on spare_size.
43  * They will either remain the same or be converted into if-cascades.
44  *
45  * @param irg        The ir graph to be lowered.
46  * @param small_switch  If switch has <= cases then change it to an if-cascade.
47  * @param spare_size Allowed spare size for table switches in machine words.
48  *                   (Default in edgfe: 128)
49  * @param allow_out_of_bounds   backend can handle out-of-bounds values
50  *                              (values bigger than minimum and maximum proj
51  *                               number)
52  */
53 FIRM_API void lower_switch(ir_graph *irg, unsigned small_switch,
54                            unsigned spare_size, int allow_out_of_bounds);
55
56 /**
57  * Replaces SymConsts by a real constant if possible.
58  * Replace Sel nodes by address computation.  Also resolves array access.
59  * Handle bit fields by added And/Or calculations.
60  *
61  * @param irg               the graph to lower
62  * @param lower_bitfields   the graph contains old-style bitfield
63  *                          constructs
64  *
65  * @note: There is NO lowering ob objects oriented types. This is highly compiler
66  *        and ABI specific and should be placed directly in the compiler.
67  */
68 FIRM_API void lower_highlevel_graph(ir_graph *irg, int lower_bitfields);
69
70 /**
71  * Creates an ir_graph pass for lower_highlevel_graph().
72  *
73  * @param name              the name of this pass or NULL
74  * @param lower_bitfields   the graph contains old-style bitfield
75  *                          constructs
76  *
77  * @return  the newly created ir_graph pass
78  */
79 FIRM_API ir_graph_pass_t *lower_highlevel_graph_pass(const char *name,
80                                                      int lower_bitfields);
81
82 /**
83  * Replaces SymConsts by a real constant if possible.
84  * Replace Sel nodes by address computation.  Also resolves array access.
85  * Handle bit fields by added And/Or calculations.
86  * Lowers all graphs.
87  *
88  * @note There is NO lowering of objects oriented types. This is highly compiler
89  *       and ABI specific and should be placed directly in the compiler.
90  */
91 FIRM_API void lower_highlevel(int lower_bitfields);
92
93 /**
94  * does the same as lower_highlevel for all nodes on the const code irg
95  */
96 FIRM_API void lower_const_code(void);
97
98 /**
99  * Creates an ir_prog pass for lower_const_code().
100  *
101  * @param name     the name of this pass or NULL
102  *
103  * @return  the newly created ir_prog pass
104  */
105 FIRM_API ir_prog_pass_t *lower_const_code_pass(const char *name);
106
107 /**
108  * Function which creates a "set" instraction. A "set" instruction takes a
109  * condition value (a value with mode_b) as input and produces a value in a
110  * general purpose integer mode.
111  * Most architectures have special intrinsics for this. But if all else fails
112  * you can just produces the an if-like construct.
113  */
114 typedef ir_node* (*create_set_func)(ir_node *cond);
115
116 /**
117  * implementation of create_set_func which produces a Mux node with 0/1 input
118  */
119 FIRM_API ir_node *ir_create_mux_set(ir_node *cond, ir_mode *dest_mode);
120
121 /**
122  * implementation of create_set_func which produces a cond with control
123  * flow
124  */
125 FIRM_API ir_node *ir_create_cond_set(ir_node *cond, ir_mode *dest_mode);
126
127 typedef struct lower_mode_b_config_t {
128         /* mode that is used to transport 0/1 values */
129         ir_mode *lowered_mode;
130         /* callback for creating set-like instructions */
131         create_set_func create_set;
132         /* whether direct Cond(Cmp) should also be lowered */
133         int lower_direct_cmp;
134 } lower_mode_b_config_t;
135
136 /**
137  * Lowers mode_b operations to integer arithmetic. After the lowering the only
138  * operations with mode_b are the Projs of Cmps; the only nodes with mode_b
139  * inputs are Cond and Psi nodes.
140  *
141  * Example: Psi(a < 0, 1, 0) => a >> 31
142  *
143  * @param irg      the firm graph to lower
144  * @param config   configuration for mode_b lowerer
145  */
146 FIRM_API void ir_lower_mode_b(ir_graph *irg,
147                               const lower_mode_b_config_t *config);
148
149 /**
150  * Used as callback, whenever a lowerable mux is found. The return value
151  * indicates, whether the mux should be lowered. This may be used, to lower
152  * floating point muxes, while keeping mux nodes for integers, for example.
153  *
154  * @param mux  The mux node that may be lowered.
155  * @return     A non-zero value indicates that the mux should be lowered.
156  */
157 typedef int lower_mux_callback(ir_node* mux);
158
159 /**
160  * Lowers all mux nodes in the given graph. A callback function may be
161  * given, to select the mux nodes to lower.
162  *
163  * @param irg      The graph to lower mux nodes in.
164  * @param cb_func  The callback function for mux selection. Can be NULL,
165  *                 to lower all mux nodes.
166  */
167 FIRM_API void lower_mux(ir_graph *irg, lower_mux_callback *cb_func);
168
169 /**
170  * Creates an ir_graph pass for lower_mux().
171  *
172  * @param name     the name of this pass or NULL
173  * @param cb_func  The callback function for mux selection. Can be NULL,
174  *                 to lower all mux nodes.
175  *
176  * @return  the newly created ir_graph pass
177  */
178 FIRM_API ir_graph_pass_t *lower_mux_pass(const char *name,
179                                          lower_mux_callback *cb_func);
180
181 /**
182  * An intrinsic mapper function.
183  *
184  * @param node   the IR-node that will be mapped
185  * @param ctx    a context
186  *
187  * @return  non-zero if the call was mapped
188  */
189 typedef int (*i_mapper_func)(ir_node *node, void *ctx);
190
191 enum ikind {
192         INTRINSIC_CALL  = 0,  /**< the record represents an intrinsic call */
193         INTRINSIC_INSTR       /**< the record represents an intrinsic instruction */
194 };
195
196 /**
197  * An intrinsic call record.
198  */
199 typedef struct i_call_record {
200         enum ikind    kind;       /**< must be INTRINSIC_CALL */
201         ir_entity     *i_ent;     /**< the entity representing an intrinsic call */
202         i_mapper_func i_mapper;   /**< the mapper function to call */
203         void          *ctx;       /**< mapper context */
204         void          *link;      /**< used in the construction algorithm, must be NULL */
205 } i_call_record;
206
207 /**
208  * An intrinsic instruction record.
209  */
210 typedef struct i_instr_record {
211         enum ikind    kind;       /**< must be INTRINSIC_INSTR */
212         ir_op         *op;        /**< the opcode that must be mapped. */
213         i_mapper_func i_mapper;   /**< the mapper function to call */
214         void          *ctx;       /**< mapper context */
215         void          *link;      /**< used in the construction algorithm, must be NULL */
216 } i_instr_record;
217
218 /**
219  * An intrinsic record.
220  */
221 typedef union i_record {
222         i_call_record  i_call;
223         i_instr_record i_instr;
224 } i_record;
225
226 /**
227  * Go through all graphs and map calls to intrinsic functions and instructions.
228  *
229  * Every call or instruction is reported to its mapper function,
230  * which is responsible for rebuilding the graph.
231  *
232  * current_ir_graph is always set.
233  *
234  * @param list             an array of intrinsic map records
235  * @param length           the length of the array
236  * @param part_block_used  set to true if part_block() must be using during lowering
237  *
238  * @return number of found intrinsics.
239  */
240 FIRM_API size_t lower_intrinsics(i_record *list, size_t length,
241                                    int part_block_used);
242
243 /**
244  * Creates an irprog pass for lower_intrinsics.
245  *
246  * @param name             the name of this pass or NULL
247  * @param list             an array of intrinsic map records
248  * @param length           the length of the array
249  * @param part_block_used  set to true if part_block() must be using during lowering
250  */
251 FIRM_API ir_prog_pass_t *lower_intrinsics_pass(const char *name, i_record *list,
252                                                size_t length, int part_block_used);
253
254 /**
255  * A mapper for the integer/float absolute value: type abs(type v).
256  * Replaces the call by a Abs node.
257  *
258  * @return always 1
259  */
260 FIRM_API int i_mapper_abs(ir_node *call, void *ctx);
261
262 /**
263  * A mapper for the integer byte swap value: type bswap(type v).
264  * Replaces the call by a builtin[ir_bk_bswap] node.
265  *
266  * @return always 1
267  */
268 FIRM_API int i_mapper_bswap(ir_node *call, void *ctx);
269
270 /**
271  * A mapper for the floating point sqrt(v): floattype sqrt(floattype v);
272  *
273  * @return 1 if the sqrt call was removed, 0 else.
274  */
275 FIRM_API int i_mapper_sqrt(ir_node *call, void *ctx);
276
277 /**
278  * A mapper for the floating point cbrt(v): floattype sqrt(floattype v);
279  *
280  * @return 1 if the cbrt call was removed, 0 else.
281  */
282 FIRM_API int i_mapper_cbrt(ir_node *call, void *ctx);
283
284 /**
285  * A mapper for the floating point pow(a, b): floattype pow(floattype a, floattype b);
286  *
287  * @return 1 if the pow call was removed, 0 else.
288  */
289 FIRM_API int i_mapper_pow(ir_node *call, void *ctx);
290
291 /**
292  * A mapper for the floating point exp(a): floattype exp(floattype a);
293  *
294  * @return 1 if the exp call was removed, 0 else.
295  */
296 FIRM_API int i_mapper_exp(ir_node *call, void *ctx);
297
298 #define i_mapper_exp2   i_mapper_exp
299 #define i_mapper_exp10  i_mapper_exp
300
301 /**
302  * A mapper for the floating point log(a): floattype log(floattype a);
303  *
304  * @return 1 if the log call was removed, 0 else.
305  */
306 FIRM_API int i_mapper_log(ir_node *call, void *ctx);
307
308 #define i_mapper_log2   i_mapper_log
309 #define i_mapper_log10  i_mapper_log
310
311 /**
312  * A mapper for the floating point sin(a): floattype sin(floattype a);
313  *
314  * @return 1 if the sin call was removed, 0 else.
315  */
316 FIRM_API int i_mapper_sin(ir_node *call, void *ctx);
317
318 /**
319  * A mapper for the floating point sin(a): floattype cos(floattype a);
320  *
321  * @return 1 if the cos call was removed, 0 else.
322  */
323 FIRM_API int i_mapper_cos(ir_node *call, void *ctx);
324
325 /**
326  * A mapper for the floating point tan(a): floattype tan(floattype a);
327  *
328  * @return 1 if the tan call was removed, 0 else.
329  */
330 FIRM_API int i_mapper_tan(ir_node *call, void *ctx);
331
332 /**
333  * A mapper for the floating point asin(a): floattype asin(floattype a);
334  *
335  * @return 1 if the asin call was removed, 0 else.
336  */
337 FIRM_API int i_mapper_asin(ir_node *call, void *ctx);
338
339 /**
340  * A mapper for the floating point acos(a): floattype acos(floattype a);
341  *
342  * @return 1 if the tan call was removed, 0 else.
343  */
344 FIRM_API int i_mapper_acos(ir_node *call, void *ctx);
345
346 /**
347  * A mapper for the floating point atan(a): floattype atan(floattype a);
348  *
349  * @return 1 if the atan call was removed, 0 else.
350  */
351 FIRM_API int i_mapper_atan(ir_node *call, void *ctx);
352
353 /**
354  * A mapper for the floating point sinh(a): floattype sinh(floattype a);
355  *
356  * @return 1 if the sinh call was removed, 0 else.
357  */
358 FIRM_API int i_mapper_sinh(ir_node *call, void *ctx);
359
360 /**
361  * A mapper for the floating point cosh(a): floattype cosh(floattype a);
362  *
363  * @return 1 if the cosh call was removed, 0 else.
364  */
365 FIRM_API int i_mapper_cosh(ir_node *call, void *ctx);
366
367 /**
368  * A mapper for the floating point tanh(a): floattype tanh(floattype a);
369  *
370  * @return 1 if the tanh call was removed, 0 else.
371  */
372 FIRM_API int i_mapper_tanh(ir_node *call, void *ctx);
373
374 /**
375  * A mapper for the strcmp-Function: inttype strcmp(char pointer a, char pointer b);
376  *
377  * @return 1 if the strcmp call was removed, 0 else.
378  */
379 FIRM_API int i_mapper_strcmp(ir_node *call, void *ctx);
380
381 /**
382  * A mapper for the strncmp-Function: inttype strncmp(char pointer a, char pointer b, inttype len);
383  *
384  * @return 1 if the strncmp call was removed, 0 else.
385  */
386 FIRM_API int i_mapper_strncmp(ir_node *call, void *ctx);
387
388 /**
389  * A mapper for the strcpy-Function: char pointer strcpy(char pointer a, char pointer b);
390  *
391  * @return 1 if the strcpy call was removed, 0 else.
392  */
393 FIRM_API int i_mapper_strcpy(ir_node *call, void *ctx);
394
395 /**
396  * A mapper for the strlen-Function: inttype strlen(char pointer a);
397  *
398  * @return 1 if the strlen call was removed, 0 else.
399  */
400 FIRM_API int i_mapper_strlen(ir_node *call, void *ctx);
401
402 /**
403  * A mapper for the memcpy-Function: void pointer memcpy(void pointer d, void pointer s, inttype c);
404  *
405  * @return 1 if the memcpy call was removed, 0 else.
406  */
407 FIRM_API int i_mapper_memcpy(ir_node *call, void *ctx);
408
409 /**
410  * A mapper for the mempcpy-Function: void pointer mempcpy(void pointer d, void pointer s, inttype c);
411  *
412  * @return 1 if the mempcpy call was removed, 0 else.
413  */
414 FIRM_API int i_mapper_mempcpy(ir_node *call, void *ctx);
415
416 /**
417  * A mapper for the memmove-Function: void pointer memmove(void pointer d, void pointer s, inttype c);
418  *
419  * @return 1 if the memmove call was removed, 0 else.
420  */
421 FIRM_API int i_mapper_memmove(ir_node *call, void *ctx);
422
423 /**
424  * A mapper for the memset-Function: void pointer memset(void pointer d, inttype C, inttype len);
425  *
426  * @return 1 if the memset call was removed, 0 else.
427  */
428 FIRM_API int i_mapper_memset(ir_node *call, void *ctx);
429
430 /**
431  * A mapper for the strncmp-Function: inttype memcmp(void pointer a, void pointer b, inttype len);
432  *
433  * @return 1 if the strncmp call was removed, 0 else.
434  */
435 FIRM_API int i_mapper_memcmp(ir_node *call, void *ctx);
436
437 /**
438  * A mapper for the alloca() function: pointer alloca(inttype size)
439  * Replaces the call by a Alloca(stack_alloc) node.
440  *
441  * @return always 1
442  */
443 FIRM_API int i_mapper_alloca(ir_node *call, void *ctx);
444
445 /**
446  * A runtime routine description.
447  */
448 typedef struct runtime_rt {
449         ir_entity *ent;            /**< The entity representing the runtime routine. */
450         ir_mode   *mode;           /**< The operation mode of the mapped instruction. */
451         ir_mode   *res_mode;       /**< The result mode of the mapped instruction or NULL. */
452         long      mem_proj_nr;     /**< if >= 0, create a memory ProjM() */
453         long      regular_proj_nr; /**< if >= 0, create a regular ProjX() */
454         long      exc_proj_nr;     /**< if >= 0, create a exception ProjX() */
455         long      res_proj_nr;     /**< if >= 0, first result projection number */
456 } runtime_rt;
457
458 /**
459  * A mapper for mapping unsupported instructions to runtime calls.
460  * Maps a op(arg_0, ..., arg_n) into a call to a runtime function
461  * rt(arg_0, ..., arg_n).
462  *
463  * The mapping is only done, if the modes of all arguments matches the
464  * modes of rt's argument.
465  * Further, if op has a memory input, the generated Call uses it, else
466  * it gets a NoMem.
467  * The pinned state of the Call will be set to the pinned state of op.
468  *
469  * Note that i_mapper_RuntimeCall() must be used with a i_instr_record.
470  *
471  * @return 1 if an op was mapped, 0 else
472  *
473  * Some examples:
474  *
475  * - Maps signed Div nodes to calls to rt_Div():
476    @code
477   runtime_rt rt_Div = {
478     ent("int rt_Div(int, int)"),
479     mode_T,
480     mode_Is,
481     pn_Div_M,
482     pn_Div_X_regular,
483     pn_Div_X_except,
484     pn_Div_M,
485     pn_Div_res
486   };
487   i_instr_record map_Div = {
488     INTRINSIC_INSTR,
489     op_Div,
490     i_mapper_RuntimeCall,
491     &rt_Div,
492     NULL
493   };
494   @endcode
495  *
496  * - Maps ConvD(F) to calls to rt_Float2Div():
497   @code
498   runtime_rt rt_Float2Double = {
499     ent("double rt_Float2Div(float)"),
500     get_type_mode("double"),
501     NULL,
502     -1,
503     -1,
504     -1,
505     -1,
506     -1
507   };
508   i_instr_record map_Float2Double = {
509     INTRINSIC_INSTR,
510     op_Conv,
511     i_mapper_RuntimeCall,
512     &rt_Float2Double,
513     NULL
514   };
515   @endcode
516  */
517 FIRM_API int i_mapper_RuntimeCall(ir_node *node, runtime_rt *rt);
518
519 #include "end.h"
520
521 #endif