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