isas and spillers register themselfes in the module constructors now
[libfirm] / ir / be / TEMPLATE / bearch_TEMPLATE.c
1 /* The main TEMPLATE backend driver file. */
2 /* $Id$ */
3
4 #ifdef HAVE_CONFIG_H
5 #include "config.h"
6 #endif
7
8 #include "pseudo_irg.h"
9 #include "irgwalk.h"
10 #include "irprog.h"
11 #include "irprintf.h"
12 #include "ircons.h"
13 #include "irgmod.h"
14
15 #include "bitset.h"
16 #include "debug.h"
17
18 #include "../bearch.h"                /* the general register allocator interface */
19 #include "../benode_t.h"
20 #include "../belower.h"
21 #include "../besched_t.h"
22 #include "../be.h"
23 #include "../beabi.h"
24 #include "../bemodule.h"
25
26 #include "bearch_TEMPLATE_t.h"
27
28 #include "TEMPLATE_new_nodes.h"           /* TEMPLATE nodes interface */
29 #include "gen_TEMPLATE_regalloc_if.h"     /* the generated interface (register type and class defenitions) */
30 #include "TEMPLATE_gen_decls.h"           /* interface declaration emitter */
31 #include "TEMPLATE_transform.h"
32 #include "TEMPLATE_emitter.h"
33 #include "TEMPLATE_map_regs.h"
34
35 #define DEBUG_MODULE "firm.be.TEMPLATE.isa"
36
37 /* TODO: ugly, but we need it to get access to the registers assigned to Phi nodes */
38 static set *cur_reg_set = NULL;
39
40 /**************************************************
41  *                         _ _              _  __
42  *                        | | |            (_)/ _|
43  *  _ __ ___  __ _    __ _| | | ___   ___   _| |_
44  * | '__/ _ \/ _` |  / _` | | |/ _ \ / __| | |  _|
45  * | | |  __/ (_| | | (_| | | | (_) | (__  | | |
46  * |_|  \___|\__, |  \__,_|_|_|\___/ \___| |_|_|
47  *            __/ |
48  *           |___/
49  **************************************************/
50
51 static ir_node *my_skip_proj(const ir_node *n) {
52         while (is_Proj(n))
53                 n = get_Proj_pred(n);
54         return (ir_node *)n;
55 }
56
57 /**
58  * Return register requirements for a TEMPLATE node.
59  * If the node returns a tuple (mode_T) then the proj's
60  * will be asked for this information.
61  */
62 static const arch_register_req_t *TEMPLATE_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos) {
63         const TEMPLATE_register_req_t *irn_req;
64         long               node_pos = pos == -1 ? 0 : pos;
65         ir_mode           *mode     = get_irn_mode(irn);
66         FIRM_DBG_REGISTER(firm_dbg_module_t *mod, DEBUG_MODULE);
67
68         if (mode == mode_T || mode == mode_M) {
69                 DBG((mod, LEVEL_1, "ignoring mode_T, mode_M node %+F\n", irn));
70                 return NULL;
71         }
72
73         DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, irn));
74
75         if (is_Proj(irn)) {
76                 /* in case of a proj, we need to get the correct OUT slot */
77                 /* of the node corresponding to the proj number */
78                 if (pos == -1) {
79                         node_pos = TEMPLATE_translate_proj_pos(irn);
80                 }
81                 else {
82                         node_pos = pos;
83                 }
84
85                 irn = my_skip_proj(irn);
86
87                 DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", irn, node_pos));
88         }
89
90         /* get requirements for our own nodes */
91         if (is_TEMPLATE_irn(irn)) {
92                 if (pos >= 0) {
93                         irn_req = get_TEMPLATE_in_req(irn, pos);
94                 }
95                 else {
96                         irn_req = get_TEMPLATE_out_req(irn, node_pos);
97                 }
98
99                 DB((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", irn, pos));
100
101                 memcpy(req, &(irn_req->req), sizeof(*req));
102
103                 if (arch_register_req_is(&(irn_req->req), should_be_same)) {
104                         assert(irn_req->same_pos >= 0 && "should be same constraint for in -> out NYI");
105                         req->other_same = get_irn_n(irn, irn_req->same_pos);
106                 }
107
108                 if (arch_register_req_is(&(irn_req->req), should_be_different)) {
109                         assert(irn_req->different_pos >= 0 && "should be different constraint for in -> out NYI");
110                         req->other_different = get_irn_n(irn, irn_req->different_pos);
111                 }
112         }
113         /* get requirements for FIRM nodes */
114         else {
115                 /* treat Phi like Const with default requirements */
116                 if (is_Phi(irn)) {
117                         DB((mod, LEVEL_1, "returning standard reqs for %+F\n", irn));
118
119                         if (mode_is_float(mode)) {
120                                 memcpy(req, &(TEMPLATE_default_req_TEMPLATE_floating_point.req), sizeof(*req));
121                         }
122                         else if (mode_is_int(mode) || mode_is_reference(mode)) {
123                                 memcpy(req, &(TEMPLATE_default_req_TEMPLATE_general_purpose.req), sizeof(*req));
124                         }
125                         else if (mode == mode_T || mode == mode_M) {
126                                 DBG((mod, LEVEL_1, "ignoring Phi node %+F\n", irn));
127                                 return NULL;
128                         }
129                         else {
130                                 assert(0 && "unsupported Phi-Mode");
131                         }
132                 }
133                 else {
134                         DB((mod, LEVEL_1, "returning NULL for %+F (node not supported)\n", irn));
135                         req = NULL;
136                 }
137         }
138
139         return req;
140 }
141
142 static void TEMPLATE_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
143         int pos = 0;
144
145         if (is_Proj(irn)) {
146                 pos = TEMPLATE_translate_proj_pos(irn);
147                 irn = my_skip_proj(irn);
148         }
149
150         if (is_TEMPLATE_irn(irn)) {
151                 const arch_register_t **slots;
152
153                 slots      = get_TEMPLATE_slots(irn);
154                 slots[pos] = reg;
155         }
156         else {
157                 /* here we set the registers for the Phi nodes */
158                 TEMPLATE_set_firm_reg(irn, reg, cur_reg_set);
159         }
160 }
161
162 static const arch_register_t *TEMPLATE_get_irn_reg(const void *self, const ir_node *irn) {
163         int pos = 0;
164         const arch_register_t *reg = NULL;
165
166         if (is_Proj(irn)) {
167                 pos = TEMPLATE_translate_proj_pos(irn);
168                 irn = my_skip_proj(irn);
169         }
170
171         if (is_TEMPLATE_irn(irn)) {
172                 const arch_register_t **slots;
173                 slots = get_TEMPLATE_slots(irn);
174                 reg   = slots[pos];
175         }
176         else {
177                 reg = TEMPLATE_get_firm_reg(irn, cur_reg_set);
178         }
179
180         return reg;
181 }
182
183 static arch_irn_class_t TEMPLATE_classify(const void *self, const ir_node *irn) {
184         irn = my_skip_proj(irn);
185
186         if (is_cfop(irn)) {
187                 return arch_irn_class_branch;
188         }
189         else if (is_TEMPLATE_irn(irn)) {
190                 return arch_irn_class_normal;
191         }
192
193         return 0;
194 }
195
196 static arch_irn_flags_t TEMPLATE_get_flags(const void *self, const ir_node *irn) {
197         irn = my_skip_proj(irn);
198
199         if (is_TEMPLATE_irn(irn)) {
200                 return get_TEMPLATE_flags(irn);
201         }
202         else if (is_Unknown(irn)) {
203                 return arch_irn_flags_ignore;
204         }
205
206         return 0;
207 }
208
209 static entity *TEMPLATE_get_frame_entity(const void *self, const ir_node *irn) {
210         /* TODO: return the entity assigned to the frame */
211         return NULL;
212 }
213
214 static void TEMPLATE_set_frame_entity(const void *self, const ir_node *irn, entity *ent) {
215         /* TODO: set the entity assigned to the frame */
216 }
217
218 /**
219  * This function is called by the generic backend to correct offsets for
220  * nodes accessing the stack.
221  */
222 static void TEMPLATE_set_frame_offset(const void *self, ir_node *irn, int offset) {
223         /* TODO: correct offset if irn accesses the stack */
224 }
225
226 static int TEMPLATE_get_sp_bias(const void *self, const ir_node *irn) {
227         return 0;
228 }
229
230 /* fill register allocator interface */
231
232 static const arch_irn_ops_if_t TEMPLATE_irn_ops_if = {
233         TEMPLATE_get_irn_reg_req,
234         TEMPLATE_set_irn_reg,
235         TEMPLATE_get_irn_reg,
236         TEMPLATE_classify,
237         TEMPLATE_get_flags,
238         TEMPLATE_get_frame_entity,
239         TEMPLATE_set_frame_entity,
240         TEMPLATE_set_frame_offset,
241         TEMPLATE_get_sp_bias,
242         NULL,    /* get_inverse             */
243         NULL,    /* get_op_estimated_cost   */
244         NULL,    /* possible_memory_operand */
245         NULL,    /* perform_memory_operand  */
246 };
247
248 TEMPLATE_irn_ops_t TEMPLATE_irn_ops = {
249         &TEMPLATE_irn_ops_if,
250         NULL
251 };
252
253
254
255 /**************************************************
256  *                _                         _  __
257  *               | |                       (_)/ _|
258  *   ___ ___   __| | ___  __ _  ___ _ __    _| |_
259  *  / __/ _ \ / _` |/ _ \/ _` |/ _ \ '_ \  | |  _|
260  * | (_| (_) | (_| |  __/ (_| |  __/ | | | | | |
261  *  \___\___/ \__,_|\___|\__, |\___|_| |_| |_|_|
262  *                        __/ |
263  *                       |___/
264  **************************************************/
265
266 /**
267  * Transforms the standard firm graph into
268  * a TEMLPATE firm graph
269  */
270 static void TEMPLATE_prepare_graph(void *self) {
271         TEMPLATE_code_gen_t *cg = self;
272
273         irg_walk_blkwise_graph(cg->irg, NULL, TEMPLATE_transform_node, cg);
274 }
275
276
277
278 /**
279  * Called immediatly before emit phase.
280  */
281 static void TEMPLATE_finish_irg(void *self) {
282         TEMPLATE_code_gen_t *cg = self;
283         ir_graph            *irg = cg->irg;
284
285         dump_ir_block_graph_sched(irg, "-TEMPLATE-finished");
286 }
287
288
289 /**
290  * These are some hooks which must be filled but are probably not needed.
291  */
292 static void TEMPLATE_before_sched(void *self) {
293         /* Some stuff you need to do after scheduling but before register allocation */
294 }
295
296 static void TEMPLATE_before_ra(void *self) {
297         /* Some stuff you need to do after scheduling but before register allocation */
298 }
299
300 static void TEMPLATE_after_ra(void *self) {
301         /* Some stuff you need to do immediatly after register allocation */
302 }
303
304
305
306 /**
307  * Emits the code, closes the output file and frees
308  * the code generator interface.
309  */
310 static void TEMPLATE_emit_and_done(void *self) {
311         TEMPLATE_code_gen_t *cg = self;
312         ir_graph           *irg = cg->irg;
313         FILE               *out = cg->isa->out;
314
315         if (cg->emit_decls) {
316                 TEMPLATE_gen_decls(out);
317                 cg->emit_decls = 0;
318         }
319
320         TEMPLATE_gen_routine(out, irg, cg);
321
322         cur_reg_set = NULL;
323
324         /* de-allocate code generator */
325         del_set(cg->reg_set);
326         free(self);
327 }
328
329 static void *TEMPLATE_cg_init(const be_irg_t *birg);
330
331 static const arch_code_generator_if_t TEMPLATE_code_gen_if = {
332         TEMPLATE_cg_init,
333         TEMPLATE_prepare_graph,
334         TEMPLATE_before_sched,   /* before scheduling hook */
335         TEMPLATE_before_ra,      /* before register allocation hook */
336         TEMPLATE_after_ra,       /* after register allocation hook */
337         TEMPLATE_finish_irg,
338         TEMPLATE_emit_and_done
339 };
340
341 /**
342  * Initializes the code generator.
343  */
344 static void *TEMPLATE_cg_init(const be_irg_t *birg) {
345         TEMPLATE_isa_t      *isa = (TEMPLATE_isa_t *)birg->main_env->arch_env->isa;
346         TEMPLATE_code_gen_t *cg  = xmalloc(sizeof(*cg));
347
348         cg->impl     = &TEMPLATE_code_gen_if;
349         cg->irg      = birg->irg;
350         cg->reg_set  = new_set(TEMPLATE_cmp_irn_reg_assoc, 1024);
351         cg->arch_env = birg->main_env->arch_env;
352         cg->isa      = isa;
353         cg->birg     = birg;
354         FIRM_DBG_REGISTER(cg->mod, "firm.be.TEMPLATE.cg");
355
356         isa->num_codegens++;
357
358         if (isa->num_codegens > 1)
359                 cg->emit_decls = 0;
360         else
361                 cg->emit_decls = 1;
362
363         cur_reg_set = cg->reg_set;
364
365         TEMPLATE_irn_ops.cg = cg;
366
367         return (arch_code_generator_t *)cg;
368 }
369
370
371
372 /*****************************************************************
373  *  ____             _                  _   _____  _____
374  * |  _ \           | |                | | |_   _|/ ____|  /\
375  * | |_) | __ _  ___| | _____ _ __   __| |   | | | (___   /  \
376  * |  _ < / _` |/ __| |/ / _ \ '_ \ / _` |   | |  \___ \ / /\ \
377  * | |_) | (_| | (__|   <  __/ | | | (_| |  _| |_ ____) / ____ \
378  * |____/ \__,_|\___|_|\_\___|_| |_|\__,_| |_____|_____/_/    \_\
379  *
380  *****************************************************************/
381
382 static TEMPLATE_isa_t TEMPLATE_isa_template = {
383         &TEMPLATE_isa_if,
384         &TEMPLATE_general_purpose_regs[REG_R6],
385         &TEMPLATE_general_purpose_regs[REG_R7],
386         -1,
387         0
388 };
389
390 /**
391  * Initializes the backend ISA and opens the output file.
392  */
393 static void *TEMPLATE_init(FILE *outfile) {
394         static int inited = 0;
395         TEMPLATE_isa_t *isa;
396
397         if(inited)
398                 return NULL;
399
400         isa = xcalloc(1, sizeof(*isa));
401         memcpy(isa, &TEMPLATE_isa_template, sizeof(*isa));
402
403         isa->out = outfile;
404
405         TEMPLATE_register_init(isa);
406         TEMPLATE_create_opcodes();
407
408         inited = 1;
409
410         return isa;
411 }
412
413
414
415 /**
416  * Closes the output file and frees the ISA structure.
417  */
418 static void TEMPLATE_done(void *self) {
419         free(self);
420 }
421
422
423
424 static int TEMPLATE_get_n_reg_class(const void *self) {
425         return N_CLASSES;
426 }
427
428 static const arch_register_class_t *TEMPLATE_get_reg_class(const void *self, int i) {
429         assert(i >= 0 && i < N_CLASSES && "Invalid TEMPLATE register class requested.");
430         return &TEMPLATE_reg_classes[i];
431 }
432
433
434
435 /**
436  * Get the register class which shall be used to store a value of a given mode.
437  * @param self The this pointer.
438  * @param mode The mode in question.
439  * @return A register class which can hold values of the given mode.
440  */
441 const arch_register_class_t *TEMPLATE_get_reg_class_for_mode(const void *self, const ir_mode *mode) {
442         if (mode_is_float(mode))
443                 return &TEMPLATE_reg_classes[CLASS_TEMPLATE_floating_point];
444         else
445                 return &TEMPLATE_reg_classes[CLASS_TEMPLATE_general_purpose];
446 }
447
448
449
450 /**
451  * Produces the type which sits between the stack args and the locals on the stack.
452  * it will contain the return address and space to store the old base pointer.
453  * @return The Firm type modelling the ABI between type.
454  */
455 static ir_type *get_between_type(void) {
456         static ir_type *between_type = NULL;
457         static entity *old_bp_ent    = NULL;
458
459         if(!between_type) {
460                 entity *ret_addr_ent;
461                 ir_type *ret_addr_type = new_type_primitive(new_id_from_str("return_addr"), mode_P);
462                 ir_type *old_bp_type   = new_type_primitive(new_id_from_str("bp"), mode_P);
463
464                 between_type           = new_type_class(new_id_from_str("TEMPLATE_between_type"));
465                 old_bp_ent             = new_entity(between_type, new_id_from_str("old_bp"), old_bp_type);
466                 ret_addr_ent           = new_entity(between_type, new_id_from_str("old_bp"), ret_addr_type);
467
468                 set_entity_offset_bytes(old_bp_ent, 0);
469                 set_entity_offset_bytes(ret_addr_ent, get_type_size_bytes(old_bp_type));
470                 set_type_size_bytes(between_type, get_type_size_bytes(old_bp_type) + get_type_size_bytes(ret_addr_type));
471         }
472
473         return between_type;
474 }
475
476 /**
477  * Get the ABI restrictions for procedure calls.
478  * @param self        The this pointer.
479  * @param method_type The type of the method (procedure) in question.
480  * @param abi         The abi object to be modified
481  */
482 void TEMPLATE_get_call_abi(const void *self, ir_type *method_type, be_abi_call_t *abi) {
483         ir_type  *between_type;
484         ir_type  *tp;
485         ir_mode  *mode;
486         int       i, n = get_method_n_params(method_type);
487         const arch_register_t *reg;
488         be_abi_call_flags_t call_flags;
489
490         /* set abi flags for calls */
491         call_flags.bits.left_to_right         = 0;
492         call_flags.bits.store_args_sequential = 1;
493         call_flags.bits.try_omit_fp           = 1;
494         call_flags.bits.fp_free               = 0;
495         call_flags.bits.call_has_imm          = 1;
496
497         /* get the between type and the frame pointer save entity */
498         between_type = get_between_type();
499
500         /* set stack parameter passing style */
501         be_abi_call_set_flags(abi, call_flags, between_type);
502
503         for (i = 0; i < n; i++) {
504                 /* TODO: implement register parameter: */
505                 /* reg = get reg for param i;          */
506                 /* be_abi_call_param_reg(abi, i, reg); */
507
508                 /* default: all parameters on stack */
509                 be_abi_call_param_stack(abi, i, 4, 0, 0);
510         }
511
512         /* TODO: set correct return register */
513         /* default: return value is in R0 resp. F0 */
514         if (get_method_n_ress(method_type) > 0) {
515                 tp   = get_method_res_type(method_type, 0);
516                 mode = get_type_mode(tp);
517
518                 be_abi_call_res_reg(abi, 0,
519                         mode_is_float(mode) ? &TEMPLATE_floating_point_regs[REG_F0] : &TEMPLATE_general_purpose_regs[REG_R0]);
520         }
521 }
522
523 static const void *TEMPLATE_get_irn_ops(const arch_irn_handler_t *self, const ir_node *irn) {
524         return &TEMPLATE_irn_ops;
525 }
526
527 const arch_irn_handler_t TEMPLATE_irn_handler = {
528         TEMPLATE_get_irn_ops
529 };
530
531 const arch_irn_handler_t *TEMPLATE_get_irn_handler(const void *self) {
532         return &TEMPLATE_irn_handler;
533 }
534
535 int TEMPLATE_to_appear_in_schedule(void *block_env, const ir_node *irn) {
536         return is_TEMPLATE_irn(irn);
537 }
538
539 /**
540  * Initializes the code generator interface.
541  */
542 static const arch_code_generator_if_t *TEMPLATE_get_code_generator_if(void *self) {
543         return &TEMPLATE_code_gen_if;
544 }
545
546 list_sched_selector_t TEMPLATE_sched_selector;
547
548 /**
549  * Returns the reg_pressure scheduler with to_appear_in_schedule() overloaded
550  */
551 static const list_sched_selector_t *TEMPLATE_get_list_sched_selector(const void *self) {
552         memcpy(&TEMPLATE_sched_selector, trivial_selector, sizeof(list_sched_selector_t));
553         TEMPLATE_sched_selector.to_appear_in_schedule = TEMPLATE_to_appear_in_schedule;
554         return &TEMPLATE_sched_selector;
555 }
556
557 /**
558  * Returns the necessary byte alignment for storing a register of given class.
559  */
560 static int TEMPLATE_get_reg_class_alignment(const void *self, const arch_register_class_t *cls) {
561         ir_mode *mode = arch_register_class_mode(cls);
562         return get_mode_size_bytes(mode);
563 }
564
565 /**
566  * Returns the libFirm configuration parameter for this backend.
567  */
568 static const backend_params *TEMPLATE_get_libfirm_params(void) {
569         static arch_dep_params_t ad = {
570                 1,  /* allow subs */
571                 0,  /* Muls are fast enough on Firm */
572                 31, /* shift would be ok */
573                 0,  /* no Mulhs */
574                 0,  /* no Mulhu */
575                 0,  /* no Mulh */
576         };
577         static backend_params p = {
578                 NULL,  /* no additional opcodes */
579                 NULL,  /* will be set later */
580                 0,     /* no dword lowering */
581                 NULL,  /* no creator function */
582                 NULL,  /* context for create_intrinsic_fkt */
583         };
584
585         p.dep_param = &ad;
586         return &p;
587 }
588
589 const arch_isa_if_t TEMPLATE_isa_if = {
590         TEMPLATE_init,
591         TEMPLATE_done,
592         TEMPLATE_get_n_reg_class,
593         TEMPLATE_get_reg_class,
594         TEMPLATE_get_reg_class_for_mode,
595         TEMPLATE_get_call_abi,
596         TEMPLATE_get_irn_handler,
597         TEMPLATE_get_code_generator_if,
598         TEMPLATE_get_list_sched_selector,
599         TEMPLATE_get_reg_class_alignment,
600     TEMPLATE_get_libfirm_params,
601 };
602
603 void be_init_arch_TEMPLATE(void)
604 {
605         be_register_isa_if("TEMPLATE", &TEMPLATE_isa_if);
606 }
607
608 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_TEMPLATE);