34d200a21198265298885f6ff323f28f978eae11
[libfirm] / ir / be / TEMPLATE / bearch_TEMPLATE.c
1 /*
2  * Copyright (C) 1995-2008 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    The main TEMPLATE backend driver file.
23  * @version  $Id$
24  */
25 #include "config.h"
26
27 #include "irgwalk.h"
28 #include "irprog.h"
29 #include "irprintf.h"
30 #include "ircons.h"
31 #include "irgmod.h"
32
33 #include "bitset.h"
34 #include "debug.h"
35
36 #include "be.h"
37 #include "../bearch.h"
38 #include "../benode.h"
39 #include "../belower.h"
40 #include "../besched.h"
41 #include "../beabi.h"
42 #include "../bemodule.h"
43 #include "../begnuas.h"
44 #include "../belistsched.h"
45
46 #include "bearch_TEMPLATE_t.h"
47
48 #include "TEMPLATE_new_nodes.h"
49 #include "gen_TEMPLATE_regalloc_if.h"
50 #include "TEMPLATE_transform.h"
51 #include "TEMPLATE_emitter.h"
52
53 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
54
55 static arch_irn_class_t TEMPLATE_classify(const ir_node *irn)
56 {
57         (void) irn;
58         return 0;
59 }
60
61 static ir_entity *TEMPLATE_get_frame_entity(const ir_node *node)
62 {
63         (void) node;
64         /* TODO: return the ir_entity assigned to the frame */
65         return NULL;
66 }
67
68 /**
69  * This function is called by the generic backend to correct offsets for
70  * nodes accessing the stack.
71  */
72 static void TEMPLATE_set_frame_offset(ir_node *irn, int offset)
73 {
74         (void) irn;
75         (void) offset;
76         /* TODO: correct offset if irn accesses the stack */
77 }
78
79 static int TEMPLATE_get_sp_bias(const ir_node *irn)
80 {
81         (void) irn;
82         return 0;
83 }
84
85 /* fill register allocator interface */
86
87 static const arch_irn_ops_t TEMPLATE_irn_ops = {
88         get_TEMPLATE_in_req,
89         TEMPLATE_classify,
90         TEMPLATE_get_frame_entity,
91         TEMPLATE_set_frame_offset,
92         TEMPLATE_get_sp_bias,
93         NULL,    /* get_inverse             */
94         NULL,    /* get_op_estimated_cost   */
95         NULL,    /* possible_memory_operand */
96         NULL,    /* perform_memory_operand  */
97 };
98
99
100
101 /**
102  * Transforms the standard firm graph into
103  * a TEMLPATE firm graph
104  */
105 static void TEMPLATE_prepare_graph(void *self)
106 {
107         TEMPLATE_code_gen_t *cg = self;
108
109         /* transform nodes into assembler instructions */
110         TEMPLATE_transform_graph(cg);
111 }
112
113
114
115 /**
116  * Called immediatly before emit phase.
117  */
118 static void TEMPLATE_finish_irg(void *self)
119 {
120         (void) self;
121 }
122
123
124 static void TEMPLATE_before_ra(void *self)
125 {
126         (void) self;
127         /* Some stuff you need to do after scheduling but before register allocation */
128 }
129
130 static void TEMPLATE_after_ra(void *self)
131 {
132         (void) self;
133         /* Some stuff you need to do immediatly after register allocation */
134 }
135
136
137
138 /**
139  * Emits the code, closes the output file and frees
140  * the code generator interface.
141  */
142 static void TEMPLATE_emit_and_done(void *self)
143 {
144         TEMPLATE_code_gen_t *cg = self;
145         ir_graph           *irg = cg->irg;
146
147         TEMPLATE_emit_routine(irg);
148
149         /* de-allocate code generator */
150         free(cg);
151 }
152
153 static void *TEMPLATE_cg_init(ir_graph *irg);
154
155 static const arch_code_generator_if_t TEMPLATE_code_gen_if = {
156         TEMPLATE_cg_init,
157         NULL,                    /* get_pic_base hook */
158         NULL,                    /* before abi introduce hook */
159         TEMPLATE_prepare_graph,
160         NULL,                    /* spill hook */
161         TEMPLATE_before_ra,      /* before register allocation hook */
162         TEMPLATE_after_ra,       /* after register allocation hook */
163         TEMPLATE_finish_irg,
164         TEMPLATE_emit_and_done
165 };
166
167 /**
168  * Initializes the code generator.
169  */
170 static void *TEMPLATE_cg_init(ir_graph *irg)
171 {
172         const arch_env_t    *arch_env = be_get_irg_arch_env(irg);
173         TEMPLATE_isa_t      *isa      = (TEMPLATE_isa_t *) arch_env;
174         TEMPLATE_code_gen_t *cg       = XMALLOC(TEMPLATE_code_gen_t);
175
176         cg->impl = &TEMPLATE_code_gen_if;
177         cg->irg  = irg;
178         cg->isa  = isa;
179
180         return (arch_code_generator_t *)cg;
181 }
182
183
184
185 const arch_isa_if_t TEMPLATE_isa_if;
186 static TEMPLATE_isa_t TEMPLATE_isa_template = {
187         {
188                 &TEMPLATE_isa_if,             /* isa interface implementation */
189                 &TEMPLATE_gp_regs[REG_SP],  /* stack pointer register */
190                 &TEMPLATE_gp_regs[REG_BP],  /* base pointer register */
191                 &TEMPLATE_reg_classes[CLASS_TEMPLATE_gp],  /* link pointer register class */
192                 -1,                          /* stack direction */
193                 2,                           /* power of two stack alignment for calls, 2^2 == 4 */
194                 NULL,                        /* main environment */
195                 7,                           /* costs for a spill instruction */
196                 5,                           /* costs for a reload instruction */
197                 false,                       /* no custom abi handling */
198         },
199 };
200
201 /**
202  * Initializes the backend ISA
203  */
204 static arch_env_t *TEMPLATE_init(FILE *outfile)
205 {
206         static int run_once = 0;
207         TEMPLATE_isa_t *isa;
208
209         if (run_once)
210                 return NULL;
211         run_once = 1;
212
213         isa = XMALLOC(TEMPLATE_isa_t);
214         memcpy(isa, &TEMPLATE_isa_template, sizeof(*isa));
215
216         be_emit_init(outfile);
217
218         TEMPLATE_register_init();
219         TEMPLATE_create_opcodes(&TEMPLATE_irn_ops);
220
221         return &isa->arch_env;
222 }
223
224
225
226 /**
227  * Closes the output file and frees the ISA structure.
228  */
229 static void TEMPLATE_done(void *self)
230 {
231         TEMPLATE_isa_t *isa = self;
232
233         /* emit now all global declarations */
234         be_gas_emit_decls(isa->arch_env.main_env);
235
236         be_emit_exit();
237         free(self);
238 }
239
240
241 static unsigned TEMPLATE_get_n_reg_class(void)
242 {
243         return N_CLASSES;
244 }
245
246 static const arch_register_class_t *TEMPLATE_get_reg_class(unsigned i)
247 {
248         assert(i < N_CLASSES);
249         return &TEMPLATE_reg_classes[i];
250 }
251
252
253
254 /**
255  * Get the register class which shall be used to store a value of a given mode.
256  * @param self The this pointer.
257  * @param mode The mode in question.
258  * @return A register class which can hold values of the given mode.
259  */
260 static const arch_register_class_t *TEMPLATE_get_reg_class_for_mode(const ir_mode *mode)
261 {
262         if (mode_is_float(mode))
263                 return &TEMPLATE_reg_classes[CLASS_TEMPLATE_fp];
264         else
265                 return &TEMPLATE_reg_classes[CLASS_TEMPLATE_gp];
266 }
267
268
269
270 typedef struct {
271         be_abi_call_flags_bits_t flags;
272         const arch_env_t *arch_env;
273         ir_graph *irg;
274 } TEMPLATE_abi_env_t;
275
276 static void *TEMPLATE_abi_init(const be_abi_call_t *call, const arch_env_t *arch_env, ir_graph *irg)
277 {
278         TEMPLATE_abi_env_t *env = XMALLOC(TEMPLATE_abi_env_t);
279         be_abi_call_flags_t fl = be_abi_call_get_flags(call);
280         env->flags    = fl.bits;
281         env->irg      = irg;
282         env->arch_env = arch_env;
283         return env;
284 }
285
286 /**
287  * Get the between type for that call.
288  * @param self The callback object.
289  * @return The between type of for that call.
290  */
291 static ir_type *TEMPLATE_get_between_type(void *self)
292 {
293         static ir_type *between_type = NULL;
294         static ir_entity *old_bp_ent = NULL;
295         (void) self;
296
297         if (!between_type) {
298                 ir_entity *ret_addr_ent;
299                 ir_type *ret_addr_type = new_type_primitive(mode_P);
300                 ir_type *old_bp_type   = new_type_primitive(mode_P);
301
302                 between_type           = new_type_class(new_id_from_str("TEMPLATE_between_type"));
303                 old_bp_ent             = new_entity(between_type, new_id_from_str("old_bp"), old_bp_type);
304                 ret_addr_ent           = new_entity(between_type, new_id_from_str("old_bp"), ret_addr_type);
305
306                 set_entity_offset(old_bp_ent, 0);
307                 set_entity_offset(ret_addr_ent, get_type_size_bytes(old_bp_type));
308                 set_type_size_bytes(between_type, get_type_size_bytes(old_bp_type) + get_type_size_bytes(ret_addr_type));
309         }
310
311         return between_type;
312 }
313
314 /**
315  * Build the prolog, return the BASE POINTER register
316  */
317 static const arch_register_t *TEMPLATE_abi_prologue(void *self, ir_node **mem,
318                                                     pmap *reg_map, int *stack_bias)
319 {
320         TEMPLATE_abi_env_t *env = self;
321         (void) reg_map;
322         (void) mem;
323         (void) stack_bias;
324
325         if (env->flags.try_omit_fp)
326                 return env->arch_env->sp;
327         return env->arch_env->bp;
328 }
329
330 /* Build the epilog */
331 static void TEMPLATE_abi_epilogue(void *self, ir_node *bl, ir_node **mem,
332                                   pmap *reg_map)
333 {
334         (void) self;
335         (void) bl;
336         (void) mem;
337         (void) reg_map;
338 }
339
340 static const be_abi_callbacks_t TEMPLATE_abi_callbacks = {
341         TEMPLATE_abi_init,
342         free,
343         TEMPLATE_get_between_type,
344         TEMPLATE_abi_prologue,
345         TEMPLATE_abi_epilogue,
346 };
347
348 /**
349  * Get the ABI restrictions for procedure calls.
350  * @param self        The this pointer.
351  * @param method_type The type of the method (procedure) in question.
352  * @param abi         The abi object to be modified
353  */
354 static void TEMPLATE_get_call_abi(const void *self, ir_type *method_type,
355                                   be_abi_call_t *abi)
356 {
357         ir_type  *tp;
358         ir_mode  *mode;
359         int       i, n = get_method_n_params(method_type);
360         be_abi_call_flags_t call_flags;
361         (void) self;
362
363         /* set abi flags for calls */
364         call_flags.bits.left_to_right         = 0;
365         call_flags.bits.store_args_sequential = 1;
366         call_flags.bits.try_omit_fp           = 1;
367         call_flags.bits.fp_free               = 0;
368         call_flags.bits.call_has_imm          = 1;
369
370         /* set stack parameter passing style */
371         be_abi_call_set_flags(abi, call_flags, &TEMPLATE_abi_callbacks);
372
373         for (i = 0; i < n; i++) {
374                 /* TODO: implement register parameter: */
375                 /* reg = get reg for param i;          */
376                 /* be_abi_call_param_reg(abi, i, reg, ABI_CONTEXT_BOTH); */
377
378                 /* default: all parameters on stack */
379                 tp   = get_method_param_type(method_type, i);
380                 mode = get_type_mode(tp);
381                 be_abi_call_param_stack(abi, i, mode, 4, 0, 0, ABI_CONTEXT_BOTH);
382         }
383
384         /* TODO: set correct return register */
385         /* default: return value is in R0 resp. F0 */
386         if (get_method_n_ress(method_type) > 0) {
387                 tp   = get_method_res_type(method_type, 0);
388                 mode = get_type_mode(tp);
389
390                 be_abi_call_res_reg(abi, 0,
391                         mode_is_float(mode) ? &TEMPLATE_fp_regs[REG_F0] : &TEMPLATE_gp_regs[REG_R0], ABI_CONTEXT_BOTH);
392         }
393 }
394
395 static int TEMPLATE_to_appear_in_schedule(void *block_env, const ir_node *irn)
396 {
397         (void) block_env;
398
399         if (!is_TEMPLATE_irn(irn))
400                 return -1;
401
402         return 1;
403 }
404
405 /**
406  * Initializes the code generator interface.
407  */
408 static const arch_code_generator_if_t *TEMPLATE_get_code_generator_if(
409                 void *self)
410 {
411         (void) self;
412         return &TEMPLATE_code_gen_if;
413 }
414
415 list_sched_selector_t TEMPLATE_sched_selector;
416
417 /**
418  * Returns the reg_pressure scheduler with to_appear_in_schedule() overloaded
419  */
420 static const list_sched_selector_t *TEMPLATE_get_list_sched_selector(
421                 const void *self, list_sched_selector_t *selector)
422 {
423         (void) self;
424         (void) selector;
425
426         TEMPLATE_sched_selector = trivial_selector;
427         TEMPLATE_sched_selector.to_appear_in_schedule = TEMPLATE_to_appear_in_schedule;
428         return &TEMPLATE_sched_selector;
429 }
430
431 static const ilp_sched_selector_t *TEMPLATE_get_ilp_sched_selector(
432                 const void *self)
433 {
434         (void) self;
435         return NULL;
436 }
437
438 /**
439  * Returns the necessary byte alignment for storing a register of given class.
440  */
441 static int TEMPLATE_get_reg_class_alignment(const arch_register_class_t *cls)
442 {
443         ir_mode *mode = arch_register_class_mode(cls);
444         return get_mode_size_bytes(mode);
445 }
446
447 /**
448  * Returns the libFirm configuration parameter for this backend.
449  */
450 static const backend_params *TEMPLATE_get_backend_params(void)
451 {
452         static backend_params p = {
453                 0,     /* no dword lowering */
454                 0,     /* no inline assembly */
455                 NULL,  /* will be set later */
456                 NULL,  /* no creator function */
457                 NULL,  /* context for create_intrinsic_fkt */
458                 NULL,  /* parameter for if conversion */
459                 NULL,  /* float arithmetic mode */
460                 0,     /* no trampoline support: size 0 */
461                 0,     /* no trampoline support: align 0 */
462                 NULL,  /* no trampoline support: no trampoline builder */
463                 4      /* alignment of stack parameter: typically 4 (32bit) or 8 (64bit) */
464         };
465         return &p;
466 }
467
468 static const be_execution_unit_t ***TEMPLATE_get_allowed_execution_units(
469                 const ir_node *irn)
470 {
471         (void) irn;
472         /* TODO */
473         return NULL;
474 }
475
476 static const be_machine_t *TEMPLATE_get_machine(const void *self)
477 {
478         (void) self;
479         /* TODO */
480         return NULL;
481 }
482
483 static ir_graph **TEMPLATE_get_backend_irg_list(const void *self,
484                                                 ir_graph ***irgs)
485 {
486         (void) self;
487         (void) irgs;
488         return NULL;
489 }
490
491 static asm_constraint_flags_t TEMPLATE_parse_asm_constraint(const char **c)
492 {
493         (void) c;
494         return ASM_CONSTRAINT_FLAG_INVALID;
495 }
496
497 static int TEMPLATE_is_valid_clobber(const char *clobber)
498 {
499         (void) clobber;
500         return 0;
501 }
502
503 const arch_isa_if_t TEMPLATE_isa_if = {
504         TEMPLATE_init,
505         TEMPLATE_done,
506         NULL,                /* handle intrinsics */
507         TEMPLATE_get_n_reg_class,
508         TEMPLATE_get_reg_class,
509         TEMPLATE_get_reg_class_for_mode,
510         TEMPLATE_get_call_abi,
511         TEMPLATE_get_code_generator_if,
512         TEMPLATE_get_list_sched_selector,
513         TEMPLATE_get_ilp_sched_selector,
514         TEMPLATE_get_reg_class_alignment,
515     TEMPLATE_get_backend_params,
516         TEMPLATE_get_allowed_execution_units,
517         TEMPLATE_get_machine,
518         TEMPLATE_get_backend_irg_list,
519         NULL,                    /* mark remat */
520         TEMPLATE_parse_asm_constraint,
521         TEMPLATE_is_valid_clobber
522 };
523
524 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_TEMPLATE);
525 void be_init_arch_TEMPLATE(void)
526 {
527         be_register_isa_if("TEMPLATE", &TEMPLATE_isa_if);
528         FIRM_DBG_REGISTER(dbg, "firm.be.TEMPLATE.cg");
529         TEMPLATE_init_transform();
530 }