added isa-callback so backend can provide it's own sorted list of irgs to generate...
[libfirm] / ir / be / ppc32 / ppc32_gen_decls.c
1 /**
2  * Dumps global variables and constants as ppc assembler.
3  * @date 14.02.2006
4  * @version $Id$
5  */
6 #ifdef HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include <assert.h>
14
15 #include "xmalloc.h"
16 #include "obst.h"
17
18 #include "tv.h"
19 #include "irnode.h"
20 #include "entity.h"
21 #include "irprog.h"
22 #include "pset.h"
23
24 #include "ppc32_gen_decls.h"
25
26 extern pset *symbol_pset;
27
28 /************************************************************************/
29
30 /*
31  * returns the highest bit value
32  */
33 static unsigned highest_bit(unsigned v)
34 {
35   int res = -1;
36
37   if (v >= (1U << 16U)) {
38     res += 16;
39     v >>= 16;
40   }
41   if (v >= (1U << 8U)) {
42     res += 8;
43     v >>= 8;
44   }
45   if (v >= (1U << 4U)) {
46     res += 4;
47     v >>= 4;
48   }
49   if (v >= (1U << 2U)) {
50     res += 2;
51     v >>= 2;
52   }
53   if (v >= (1U << 1U)) {
54     res += 1;
55     v >>= 1;
56   }
57   if (v >= 1)
58     res += 1;
59
60   return res;
61 }
62
63 /*
64  * output the alignment
65  */
66 static void ppc32_dump_align(struct obstack *obst, int align)
67 {
68   int h = highest_bit(align);
69
70   if ((1 << h) < align)
71     ++h;
72   align = (1 << h);
73
74   if (align > 1)
75     obstack_printf(obst, "\t.align %d\n", align);
76 }
77
78 static void dump_arith_tarval(struct obstack *obst, tarval *tv, int bytes)
79 {
80   switch (bytes) {
81
82   case 1:
83     obstack_printf(obst, "0x%02x", get_tarval_sub_bits(tv, 0));
84     break;
85
86   case 2:
87     obstack_printf(obst, "0x%02x%02x", get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
88     break;
89
90   case 4:
91     obstack_printf(obst, "0x%02x%02x%02x%02x",
92     get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
93     break;
94
95   case 8:
96     obstack_printf(obst, "0x%02x%02x%02x%02x%02x%02x%02x%02x",
97     get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6), get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4),
98     get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
99     break;
100
101   case 10:
102   case 12:
103     break;
104
105   default:
106     fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
107     assert(0);
108   }
109 }
110
111 #if 0
112 /*
113  * dump an arithmetic tarval
114  */
115 static void ppc32_dump_arith_tarval(struct obstack *obst, tarval *tv, int bytes)
116 {
117   switch (bytes) {
118
119   case 1:
120     obstack_printf(obst, "\t.byte\t");
121     break;
122
123   case 2:
124     obstack_printf(obst, "\t.value\t");
125     break;
126
127   case 4:
128     obstack_printf(obst, "\t.long\t");
129     break;
130
131   case 8:
132     obstack_printf(obst, "\t.quad\t");
133     break;
134
135   case 10:
136   case 12:
137     break;
138
139   default:
140     fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
141     assert(0);
142   }
143   dump_arith_tarval(obst, tv, bytes);
144 }
145 #endif
146
147 /*
148  * dump an atomic value
149  */
150 static void do_dump_atomic_init(struct obstack *obst, ir_node *init)
151 {
152   ir_mode *mode = get_irn_mode(init);
153   int bytes     = get_mode_size_bytes(mode);
154   tarval *tv;
155
156   switch (get_irn_opcode(init)) {
157
158   case iro_Cast:
159     do_dump_atomic_init(obst, get_Cast_op(init));
160     return;
161
162   case iro_Conv:
163     do_dump_atomic_init(obst, get_Conv_op(init));
164     return;
165
166   case iro_Const:
167     tv = get_Const_tarval(init);
168
169     /* beware of old stuff */
170     assert(! mode_is_reference(mode));
171
172     /* it's a arithmetic value */
173     dump_arith_tarval(obst, tv, bytes);
174     return;
175
176   case iro_SymConst:
177     switch (get_SymConst_kind(init)) {
178     case symconst_addr_name:
179       obstack_printf(obst, "%s", get_id_str(get_SymConst_name(init)));
180       break;
181
182     case symconst_addr_ent:
183       obstack_printf(obst, "%s", get_entity_ld_name(get_SymConst_entity(init)));
184       break;
185
186     case symconst_ofs_ent:
187       obstack_printf(obst, "%d", get_entity_offset(get_SymConst_entity(init)));
188       break;
189
190     case symconst_type_size:
191       obstack_printf(obst, "%d", get_type_size_bytes(get_SymConst_type(init)));
192       break;
193
194     case symconst_type_align:
195       obstack_printf(obst, "%d", get_type_alignment_bytes(get_SymConst_type(init)));
196       break;
197
198     case symconst_enum_const:
199       tv = get_enumeration_value(get_SymConst_enum(init));
200       dump_arith_tarval(obst, tv, bytes);
201       break;
202
203     default:
204       assert(!"dump_atomic_init(): don't know how to init from this SymConst");
205     }
206     return;
207
208   case iro_Add:
209     do_dump_atomic_init(obst, get_Add_left(init));
210     obstack_printf(obst, " + ");
211     do_dump_atomic_init(obst, get_Add_right(init));
212     return;
213
214   case iro_Sub:
215     do_dump_atomic_init(obst, get_Sub_left(init));
216     obstack_printf(obst, " - ");
217     do_dump_atomic_init(obst, get_Sub_right(init));
218     return;
219
220   case iro_Mul:
221     do_dump_atomic_init(obst, get_Mul_left(init));
222     obstack_printf(obst, " * ");
223     do_dump_atomic_init(obst, get_Mul_right(init));
224     return;
225
226   default:
227     assert(0 && "dump_atomic_init(): unknown IR-node");
228   }
229 }
230
231 /*
232  * dump an atomic value
233  */
234 static void dump_atomic_init(struct obstack *obst, ir_node *init)
235 {
236   ir_mode *mode = get_irn_mode(init);
237   int bytes     = get_mode_size_bytes(mode);
238
239   switch (bytes) {
240
241   case 1:
242     obstack_printf(obst, "\t.byte\t");
243     break;
244
245   case 2:
246     obstack_printf(obst, "\t.value\t");
247     break;
248
249   case 4:
250     obstack_printf(obst, "\t.long\t");
251     break;
252
253   case 8:
254     obstack_printf(obst, "\t.quad\t");
255     break;
256
257   case 10:
258   case 12:
259     /* handled in arith */
260     break;
261
262   default:
263     fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
264     assert(0);
265   }
266
267   do_dump_atomic_init(obst, init);
268   obstack_printf(obst, "\n");
269 }
270
271 /************************************************************************/
272 /* Routines to dump global variables                                    */
273 /************************************************************************/
274
275 /**
276  * Determine if an entity is a string constant
277  * @param ent The entity
278  * @return 1 if it is a string constant, 0 otherwise
279  */
280 static int ent_is_string_const(ir_entity *ent)
281 {
282   int res = 0;
283   ir_type *ty;
284
285   ty = get_entity_type(ent);
286
287   /* if it's an array */
288   if (is_Array_type(ty)) {
289     ir_type *elm_ty = get_array_element_type(ty);
290
291     /* and the array's element type is primitive */
292     if (is_Primitive_type(elm_ty)) {
293       ir_mode *mode = get_type_mode(elm_ty);
294
295       /*
296        * and the mode of the element type is an int of
297        * the same size as the byte mode
298        */
299       if (mode_is_int(mode)
300          && get_mode_size_bits(mode) == get_mode_size_bits(mode_Bs))
301       {
302         int i, c, n;
303
304         n = get_compound_ent_n_values(ent);
305         for (i = 0; i < n; ++i) {
306           ir_node *irn = get_compound_ent_value(ent, i);
307           if(get_irn_opcode(irn) != iro_Const)
308             return 0;
309
310           c = (int) get_tarval_long(get_Const_tarval(irn));
311
312           if((i < n - 1 && !(isgraph(c) || isspace(c)))
313              || (i == n - 1 && c != '\0'))
314             return 0;
315         }
316
317         res = 1;
318       }
319     }
320   }
321
322   return res;
323 }
324
325 /**
326  * Dump a atring constant.
327  * No checks are made!!
328  * @param obst The obst to dump on.
329  * @param ent The entity to dump.
330  */
331 static void dump_string_cst(struct obstack *obst, ir_entity *ent)
332 {
333   int i, n;
334
335   obstack_printf(obst, "\t.asciz \"");
336   n = get_compound_ent_n_values(ent);
337
338   for (i = 0; i < n-1; ++i) {
339     ir_node *irn;
340     int c;
341
342     irn = get_compound_ent_value(ent, i);
343     c = (int) get_tarval_long(get_Const_tarval(irn));
344
345     switch (c) {
346     case '"' : obstack_printf(obst, "\\\""); break;
347     case '\n': obstack_printf(obst, "\\n"); break;
348     case '\r': obstack_printf(obst, "\\r"); break;
349     case '\t': obstack_printf(obst, "\\t"); break;
350     default  :
351       if (isprint(c))
352         obstack_printf(obst, "%c", c);
353       else
354         obstack_printf(obst, "\\%o", c);
355       break;
356     }
357   }
358   obstack_printf(obst, "\"\n");
359 }
360
361 struct arr_info {
362   int n_elems;
363   int visit_cnt;
364   int size;
365 };
366
367 /*
368  * Dumps the initialization of global variables that are not
369  * "uninitialized".
370  */
371 static void dump_global(struct obstack *rdata_obstack, struct obstack *data_obstack, struct obstack *comm_obstack, ir_entity *ent)
372 {
373   ir_type *ty         = get_entity_type(ent);
374   const char *ld_name = get_entity_ld_name(ent);
375   int align; //, h;
376   struct obstack *obst = data_obstack;
377
378   /*
379    * FIXME: did NOT work for partly constant values
380    */
381   if (! is_Method_type(ty)) {
382     ir_variability variability = get_entity_variability(ent);
383     ir_visibility visibility = get_entity_visibility(ent);
384
385     if (variability == variability_constant) {
386       /* a constant entity, put it on the rdata */
387       obst = rdata_obstack;
388     }
389
390     /* check, whether it is initialized, if yes create data */
391     if (variability != variability_uninitialized) {
392       if (visibility == visibility_external_visible) {
393         obstack_printf(obst, ".globl\t%s\n", ld_name);
394       }
395 //      obstack_printf(obst, "\t.type\t%s,@object\n", ld_name);
396 //      obstack_printf(obst, "\t.size\t%s,%d\n", ld_name, (get_type_size_bits(ty) + 7) >> 3);
397
398       align = get_type_alignment_bytes(ty);
399       ppc32_dump_align(obst, align);
400
401       obstack_printf(obst, "%s:\n", ld_name);
402
403       if (is_atomic_type(ty)) {
404         if (get_entity_visibility(ent) != visibility_external_allocated)
405           dump_atomic_init(obst, get_atomic_ent_value(ent));
406       }
407       else {
408         int i, size = 0;
409
410         if (ent_is_string_const(ent)) {
411           dump_string_cst(obst, ent);
412         }
413         else if (is_Array_type(ty)) {
414           int filler;
415
416           /* potential spare values should be already included! */
417           for (i = 0; i < get_compound_ent_n_values(ent); ++i) {
418             ir_entity *step = get_compound_ent_value_member(ent, i);
419             ir_type *stype = get_entity_type(step);
420
421             if (get_type_mode(stype)) {
422               int align = (get_type_alignment_bits(stype) + 7) >> 3;
423               int n     = size % align;
424
425               if (n > 0) {
426                 obstack_printf(obst, "\t.zero\t%d\n", align - n);
427                 size += align - n;
428               }
429             }
430             dump_atomic_init(obst, get_compound_ent_value(ent, i));
431             size += get_type_size_bytes(stype);
432           }
433           filler = get_type_size_bytes(ty) - size;
434
435           if (filler > 0)
436             obstack_printf(obst, "\t.zero\t%d\n", filler);
437         }
438         else if (is_compound_type(ty)) {
439           ir_node **vals;
440           int type_size, j;
441
442           /* Compound entities are NOT sorted.
443            * The sorting strategy used doesn't work for `value' compound fields nor
444            * for partially_constant entities.
445            */
446
447           /*
448            * in the worst case, every entity allocates one byte, so the type
449            * size should be equal or bigger the number of fields
450            */
451           type_size = get_type_size_bytes(ty);
452           vals      = xcalloc(type_size, sizeof(*vals));
453
454           /* collect the values and store them at the offsets */
455           for(i = 0; i < get_compound_ent_n_values(ent); ++i) {
456             int                 graph_length, aipos, offset;
457             struct arr_info     *ai;
458             int                 all_n = 1;
459             compound_graph_path *path = get_compound_ent_value_path(ent, i);
460
461             /* get the access path to the costant value */
462             graph_length = get_compound_graph_path_length(path);
463             ai = xcalloc(graph_length, sizeof(struct arr_info));
464
465             /* We wanna know how many arrays are on the path to the entity. We also have to know how
466              * many elements each array holds to calculate the offset for the entity. */
467             for (j = 0; j < graph_length; j++) {
468               ir_entity *step      = get_compound_graph_path_node(path, j);
469               ir_type   *step_type = get_entity_type(step);
470               int       ty_size    = (get_type_size_bits(step_type) + 7) >> 3;
471               int       k, n       = 0;
472
473               if (is_Array_type(step_type))
474                 for (k = 0; k < get_array_n_dimensions(step_type); k++)
475                   n += get_tarval_long(get_Const_tarval(get_array_upper_bound(step_type, k)));
476               if (n) all_n *= n;
477               ai[j].n_elems = n ? all_n + 1 : 0;
478               ai[j].visit_cnt = 0;
479               ai[j].size = ty_size;
480             }
481
482             aipos = graph_length - 1;
483             if (aipos) aipos--;
484
485             for (offset = j = 0; j < graph_length; j++) {
486               ir_entity *step    = get_compound_graph_path_node(path, j);
487               ir_type *step_type = get_entity_type(step);
488               int ent_ofs        = get_entity_offset(step);
489               int stepsize       = 0;
490
491               /* add all positive offsets (= offsets in structs) */
492               if (ent_ofs >= 0) offset += ent_ofs;
493
494               if (j == graph_length - 1) {
495                 stepsize = (get_type_size_bits(step_type) + 7) >> 3;
496
497                 /* Search the next free position in vals depending on the information from above (ai). */
498                 while (vals[offset]) {
499                   if (ai[aipos].visit_cnt < ai[aipos].n_elems) {
500                     offset += stepsize;
501                     ai[aipos].visit_cnt++;
502                   }
503                   else
504                     while (aipos >= 0 && ai[aipos].visit_cnt == ai[aipos].n_elems) {
505                       stepsize = ai[aipos--].size;
506                       offset  += stepsize;
507                   }
508                 }
509
510                 assert(aipos >= 0 && "couldn't store entity");
511                 vals[offset] = get_compound_ent_value(ent, i);
512               }
513             }
514
515             free(ai);
516           }
517
518           /* now write them sorted */
519           for(i = 0; i < type_size; ) {
520             if (vals[i]) {
521               dump_atomic_init(obst, vals[i]);
522               i += (get_mode_size_bytes(get_irn_mode(vals[i])));
523             }
524             else {
525               /* a gap */
526               obstack_printf(obst, "\t.byte\t0\n");
527               ++i;
528             }
529           }
530           free(vals);
531         }
532         else {
533           assert(0 && "unsupported type");
534         }
535       }
536       obstack_printf(obst, "\n");
537     }
538     else if (visibility != visibility_external_allocated) {
539       if (visibility == visibility_local) {
540         obstack_printf(comm_obstack, "\t.local\t%s\n", ld_name);
541       }
542
543       /* calculate the alignment */
544 /*      align = get_type_alignment_bytes(ty);
545       h = highest_bit(align);
546
547       if ((1 << h) < align)
548         ++h;
549       align = (1 << h);
550
551       if (align < 1)
552         align = 1;
553
554       obstack_printf(comm_obstack, "\t.comm\t%s,%d,%d\n", ld_name, (get_type_size_bits(ty) + 7) >> 3, align);*/
555       obstack_printf(comm_obstack, "\t.comm\t%s,%d\n", ld_name, (get_type_size_bits(ty) + 7) >> 3);
556     }
557   }
558 }
559
560 /*
561  * Dumps declarations of global variables and the initialization code.
562  */
563 void ppc32_dump_globals(struct obstack *rdata_obstack, struct obstack *data_obstack, struct obstack *comm_obstack)
564 {
565   ir_type *gt = get_glob_type();
566   int i, n = get_class_n_members(gt);
567
568   for (i = 0; i < n; i++)
569     dump_global(rdata_obstack, data_obstack, comm_obstack, get_class_member(gt, i));
570 }
571
572 void ppc32_dump_indirect_symbols(struct obstack *isyms)
573 {
574   ir_entity *ent;
575
576   foreach_pset(symbol_pset, ent) {
577     const char *ld_name = get_entity_ld_name(ent);
578     obstack_printf(isyms, ".non_lazy_symbol_pointer\n%s:\n\t.indirect_symbol _%s\n\t.long 0\n\n",ld_name,ld_name);
579   }
580 }
581
582 /************************************************************************/
583
584 void ppc32_gen_decls(FILE *out) {
585   struct obstack rodata, data, comm, isyms;
586   int    size;
587   char   *cp;
588
589   obstack_init(&rodata);
590   obstack_init(&data);
591   obstack_init(&comm);
592
593   ppc32_dump_globals(&rodata, &data, &comm);
594
595   size = obstack_object_size(&data);
596   cp   = obstack_finish(&data);
597   if (size > 0) {
598     fprintf(out, "\t.data\n");
599     fwrite(cp, 1, size, out);
600   }
601
602   size = obstack_object_size(&rodata);
603   cp   = obstack_finish(&rodata);
604   if (size > 0) {
605     fprintf(out, "\t.const_data\n");
606     fwrite(cp, 1, size, out);
607   }
608
609   size = obstack_object_size(&comm);
610   cp   = obstack_finish(&comm);
611   if (size > 0) {
612 //    fprintf(out, "\t.common\n");
613     fwrite(cp, 1, size, out);
614     fprintf(out, "\n");
615   }
616
617   obstack_free(&rodata, NULL);
618   obstack_free(&data, NULL);
619   obstack_free(&comm, NULL);
620
621   obstack_init(&isyms);
622
623   ppc32_dump_indirect_symbols(&isyms);
624
625   size = obstack_object_size(&isyms);
626   cp   = obstack_finish(&isyms);
627   if (size > 0) {
628           fprintf(out, "\t.data\n");
629           fwrite(cp, 1, size, out);
630   }
631
632   obstack_free(&isyms,NULL);
633 }