create register slots in attributes on irg obstack
[libfirm] / ir / be / beasm_asm_gnu.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <assert.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <ctype.h>
10
11 #include "obst.h"
12 #include "beasm_asm_gnu.h"
13 #include "tv.h"
14
15 static struct obstack *get_obstack_for_segment ( gnuasm_privdata_t *privdata, asm_segment_t segment ) {
16
17         switch (segment) {
18                 case ASM_SEGMENT_CONST:
19                         return &privdata->rdata_obst;
20                         break;
21                 case ASM_SEGMENT_DATA_INIT:
22                         return &privdata->data_obst;
23                         break;
24                 case ASM_SEGMENT_CODE:
25                         return &privdata->code_obst;
26                         break;
27                 case ASM_SEGMENT_DATA_UNINIT:
28                         return &privdata->common_obst;
29                         break;
30                 default:
31                         assert(0 && "unknown segment type");
32                         break;
33         }
34   return NULL;
35 }
36
37
38 /**
39  * the dumper callbacks
40  */
41 /*
42 static void gnuasm_dump_align(void *data, asm_segment_t segment, int align) {
43   gnuasm_privdata_t *privdata = data;
44         struct obstack* obst = get_obstack_for_segment( privdata, segment );
45         obstack_printf(obst, "\t.align %d\n", align);
46 }
47 */
48
49 static void gnuasm_dump_arith_tarval(void *data, asm_segment_t segment, tarval *tv, int bytes)
50 {
51   gnuasm_privdata_t *privdata = data;
52         struct obstack* obst = get_obstack_for_segment ( privdata, segment );
53
54         switch (bytes) {
55
56         case 1:
57                 obstack_printf(obst, "0x%02x", get_tarval_sub_bits(tv, 0));
58                 break;
59         case 2:
60                 obstack_printf(obst, "0x%02x%02x", get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
61                 break;
62
63         case 4:
64                 obstack_printf(obst, "0x%02x%02x%02x%02x",
65                 get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
66                 break;
67
68         case 8:
69                 obstack_printf(obst, "0x%02x%02x%02x%02x%02x%02x%02x%02x",
70 get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6), get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4), get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
71                 break;
72
73         default:
74                 fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
75                 assert(0);
76         }
77 }
78
79
80 static void gnuasm_dump_atomic_decl(void *data, asm_segment_t segment, int bytes)
81 {
82   gnuasm_privdata_t *privdata = data;
83         struct obstack* obst = get_obstack_for_segment( privdata, segment );
84
85         switch (bytes) {
86
87         case 1:
88                 obstack_printf(obst, "\t.byte\t");
89                 break;
90
91         case 2:
92                 obstack_printf(obst, "\t.value\t");
93                 break;
94
95         case 4:
96                 obstack_printf(obst, "\t.long\t");
97                 break;
98
99         case 8:
100                 obstack_printf(obst, "\t.quad\t");
101                 break;
102
103         default:
104                 fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
105                 assert(0);
106         }
107
108 //      obstack_printf(obst, "\n");
109 }
110
111 static void gnuasm_dump_string(void *data, asm_segment_t segment, entity *ent)
112 {
113   gnuasm_privdata_t *privdata = data;
114   int i, n;
115
116   struct obstack* obst = get_obstack_for_segment ( privdata, segment );
117
118   obstack_printf(obst, "\t.string \"");
119   n = get_compound_ent_n_values(ent);
120
121   for (i = 0; i < n-1; ++i) {
122     ir_node *irn;
123     int c;
124
125     irn = get_compound_ent_value(ent, i);
126     c = (int) get_tarval_long(get_Const_tarval(irn));
127
128     switch (c) {
129     case '"' : obstack_printf(obst, "\\\""); break;
130     case '\n': obstack_printf(obst, "\\n");  break;
131     case '\r': obstack_printf(obst, "\\r");  break;
132     case '\t': obstack_printf(obst, "\\t");  break;
133     default:
134       if (isprint(c))
135               obstack_printf(obst, "%c", c);
136       else
137               obstack_printf(obst, "%O", c);
138       break;
139     }
140   }
141   obstack_printf(obst, "\"\n");
142 }
143
144
145 static void gnuasm_dump_declare_initialized_symbol(void *data, asm_segment_t segment, const char* ld_name, int bytes, int align, visibility visibility)
146 {
147   gnuasm_privdata_t* priv_data = data;
148
149   /* get the obstack for the given segment (const, data) */
150   struct obstack* obst = get_obstack_for_segment ( priv_data, segment );
151
152   /* if the symbol is externally visible, declare it so. */
153   if (visibility == visibility_external_visible)
154     obstack_printf(obst, ".globl\t%s\n", ld_name);
155
156   obstack_printf(obst, "\t.type\t%s,@object\n", ld_name);
157   obstack_printf(obst, "\t.size\t%s,%d\n", ld_name, bytes);
158   obstack_printf(obst, "\t.align\t%d\n", align);
159   obstack_printf(obst, "\t%s:\n", ld_name);
160 }
161
162 static void gnuasm_dump_declare_uninitialized_symbol(void *data, asm_segment_t segment, const char* ld_name, int bytes, int align, visibility visibility)
163 {
164   gnuasm_privdata_t *priv_data = data;
165
166   /* external symbols are not required to be declared in gnuasm. */
167   if(visibility == visibility_external_allocated) return;
168
169   /* declare local, uninitialized symbol to the uninit-obst */
170   obstack_printf(&priv_data->common_obst, "\t.comm\t%s,%d,%d\n", ld_name, bytes, align);
171 }
172
173 static void gnuasm_dump_zero_padding(void *data, asm_segment_t segment, int size)
174 {
175   gnuasm_privdata_t *privdata = data;
176         struct obstack* obst = get_obstack_for_segment ( privdata, segment );
177         obstack_printf(obst, "\t.zero\t%d\n", size);
178 }
179
180 ////////////////////////////////////////////////////////////////////////////
181
182 static void gnuasm_dump_arith_op(void *data, asm_segment_t segment, asm_arith_operation_t op)
183 {
184   gnuasm_privdata_t *privdata = data;
185         struct obstack* obst = get_obstack_for_segment ( privdata, segment );
186         switch (op) {
187                 case ASM_ARITH_OPERATION_ADD:
188                         obstack_printf(obst, "+");
189                         break;
190                 case ASM_ARITH_OPERATION_SUB:
191                         obstack_printf(obst, "-");
192                         break;
193                 case ASM_ARITH_OPERATION_MUL:
194                         obstack_printf(obst, "*");
195                         break;
196         }
197         //obstack_printf(obst, "+");
198 }
199
200 static void gnuasm_dump_symconst(void *data, asm_segment_t segment, ir_node *init)
201 {
202   gnuasm_privdata_t *privdata = data;
203   struct obstack* obst = get_obstack_for_segment ( privdata, segment );
204   switch (get_SymConst_kind(init)) {
205     case symconst_addr_name:
206         obstack_printf(obst, "%s", get_id_str(get_SymConst_name(init)));
207       break;
208
209     case symconst_addr_ent:
210         obstack_printf(obst, "%s", get_entity_ld_name(get_SymConst_entity(init)));
211       break;
212
213     case symconst_size:
214         obstack_printf(obst, "%d", get_type_size_bytes(get_SymConst_type(init)));
215       break;
216
217     default:
218       assert(0 && "dump_atomic_init(): don't know how to init from this SymConst");
219     }
220 }
221
222 static void gnuasm_dump_newline(void *data, asm_segment_t segment)
223 {
224   gnuasm_privdata_t *privdata = data;
225         struct obstack* obst = get_obstack_for_segment ( privdata, segment );
226         obstack_printf(obst, "\n");
227 }
228
229 //////////////////////////////////////////////////////////////////////////////
230
231 static void gnuasm_dump_header(void *data) {
232   /*gnuasm_privdata_t *privdata = data;*/
233 }
234
235 static void gnuasm_dump_footer(void *data) {
236   /*gnuasm_privdata_t *privdata = data;*/
237 }
238
239 static void gnuasm_dump_segment_header(void *data) {
240   /*gnuasm_privdata_t *privdata = data;*/
241 }
242
243 //////////////////////////////////////////////////////////////////////////////
244
245 assembler_t *gnuasm_create_assembler ( void ) {
246
247         gnuasm_privdata_t *priv_data = xmalloc ( sizeof(gnuasm_privdata_t ));
248         assembler_t *assembler = xmalloc ( sizeof( assembler_t ));
249         memset(assembler, 0, sizeof( assembler_t ));
250         assembler->private_data = priv_data;
251
252         obstack_init (&priv_data->common_obst);
253         obstack_init (&priv_data->data_obst);
254         obstack_init (&priv_data->rdata_obst);
255         obstack_init (&priv_data->code_obst);
256
257
258   assembler->dump_declare_uninitialized_symbol = gnuasm_dump_declare_uninitialized_symbol;
259   assembler->dump_declare_initialized_symbol   = gnuasm_dump_declare_initialized_symbol;
260
261 //  assembler->dump_align = (dump_align_proc) &gnuasm_dump_align;
262         assembler->dump_arith_tarval = gnuasm_dump_arith_tarval;
263         assembler->dump_atomic_decl  = gnuasm_dump_atomic_decl;
264         assembler->dump_string       = gnuasm_dump_string;
265         assembler->dump_zero_padding = gnuasm_dump_zero_padding;
266         assembler->dump_arith_op     = gnuasm_dump_arith_op;
267         assembler->dump_symconst     = gnuasm_dump_symconst;
268         assembler->dump_newline      = gnuasm_dump_newline;
269
270         assembler->dump_header         = gnuasm_dump_header;
271         assembler->dump_footer         = gnuasm_dump_footer;
272         assembler->dump_segment_header = gnuasm_dump_segment_header;
273
274
275         return assembler;
276
277 }
278
279 static void gnuasm_dump_obst(struct obstack *obst, FILE *out) {
280         obstack_grow0 (obst, NULL, 0);
281         fprintf(out, "%s", (char *)obstack_finish(obst));
282 }
283
284 void gnuasm_dump( assembler_t *assembler, FILE *out ) {
285
286         gnuasm_privdata_t *privdata = assembler->private_data;
287
288 //      fprintf(out, "<COMMON>\n");
289         gnuasm_dump_obst ( &privdata->common_obst, out);
290         fprintf(out, ".data\n");
291         gnuasm_dump_obst ( &privdata->data_obst, out);
292         fprintf(out, ".section .rodata\n");
293         gnuasm_dump_obst ( &privdata->rdata_obst, out);
294         fprintf(out, ".text\n");
295         gnuasm_dump_obst ( &privdata->code_obst, out);
296         //////
297 }
298
299 void gnuasm_delete_assembler( assembler_t *assembler ) {
300         free( assembler->private_data );
301         free( assembler );
302 }