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