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