More doxygen comments added
[libfirm] / ir / be / begnuas.c
1 /**
2  * Dumps global variables and constants as gas assembler.
3  * @author Christian Wuerdig, Matthias Braun
4  * @date 04.11.2005
5  * @version $Id$
6  */
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10
11 #include "begnuas.h"
12
13 #include <stdlib.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <assert.h>
17
18 #include "obst.h"
19 #include "tv.h"
20 #include "irnode.h"
21 #include "entity.h"
22 #include "irprog.h"
23 #include "pdeq.h"
24 #include "error.h"
25
26 #include "be_t.h"
27 #include "beemitter.h"
28 #include "be_dbgout.h"
29
30 typedef struct obstack obstack_t;
31
32 /** by default, we generate assembler code for the Linux gas */
33 be_gas_flavour_t be_gas_flavour = GAS_FLAVOUR_NORMAL;
34
35 /**
36  * Return the pseudo-instruction to be issued for a section switch
37  * depending on the current flavour.
38  *
39  * @param section  the section to switch to
40  *
41  * @return  the pseudo-instruction
42  */
43 static const char *get_section_name(be_gas_section_t section) {
44         static const char *text[GAS_FLAVOUR_MAX][GAS_SECTION_MAX] = {
45                 {
46                         ".section\t.text",
47                         ".section\t.data",
48                         ".section\t.rodata",
49                         ".section\t.bss",
50                         ".section\t.tbss,\"awT\",@nobits",
51                         ".section\t.ctors,\"aw\",@progbits"
52                 },
53                 {
54                         ".section\t.text",
55                         ".section\t.data",
56                         ".section .rdata,\"dr\"",
57                         ".section\t.bss",
58                         ".section\t.tbss,\"awT\",@nobits",
59                         ".section\t.ctors,\"aw\",@progbits"
60                 }
61         };
62
63         assert(be_gas_flavour >= 0 && be_gas_flavour < GAS_FLAVOUR_MAX);
64         assert(section >= 0 && section < GAS_SECTION_MAX);
65         return text[be_gas_flavour][section];
66 }
67
68 /**
69  * Emit necessary code to switch to a section.
70  *
71  * @param env      the emitter environment
72  * @param section  the section to switch to
73  */
74 void be_gas_emit_switch_section(be_emit_env_t *env, be_gas_section_t section) {
75         be_emit_char(env, '\t');
76         be_emit_string(env, get_section_name(section));
77         be_emit_char(env, '\n');
78         be_emit_write_line(env);
79 }
80
81 typedef struct _ia32_decl_env {
82         obstack_t *rodata_obst;
83         obstack_t *data_obst;
84         obstack_t *bss_obst;
85         obstack_t *ctor_obst;
86         const be_main_env_t *main_env;
87         waitq     *worklist;
88 } ia32_decl_env_t;
89
90 /************************************************************************/
91
92 /**
93  * output a tarval
94  */
95 static void dump_arith_tarval(obstack_t *obst, tarval *tv, int bytes)
96 {
97         switch (bytes) {
98
99         case 1:
100                 obstack_printf(obst, "0x%02x", get_tarval_sub_bits(tv, 0));
101                 break;
102
103         case 2:
104                 obstack_printf(obst, "0x%02x%02x", get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
105                 break;
106
107         case 4:
108                 obstack_printf(obst, "0x%02x%02x%02x%02x",
109                         get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
110                 break;
111
112         case 8:
113                 obstack_printf(obst, "0x%02x%02x%02x%02x%02x%02x%02x%02x",
114                         get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6), get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4),
115                         get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
116                 break;
117
118         case 10:
119         case 12:
120                 break;
121
122         case 16:
123                 obstack_printf(obst, "0x%02x%02x%02x%02x%02x%02x%02x%02x"
124                                                "%02x%02x%02x%02x%02x%02x%02x%02x",
125                         get_tarval_sub_bits(tv, 15), get_tarval_sub_bits(tv, 16),
126                         get_tarval_sub_bits(tv, 13), get_tarval_sub_bits(tv, 12),
127                         get_tarval_sub_bits(tv, 11), get_tarval_sub_bits(tv, 10),
128                         get_tarval_sub_bits(tv, 9), get_tarval_sub_bits(tv, 8),
129                         get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6),
130                         get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4),
131                         get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2),
132                         get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
133                 break;
134
135
136         default:
137                 fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
138                 assert(0);
139         }
140 }
141
142 /**
143  * Return the tarval of an atomic initializer.
144  */
145 static tarval *get_atomic_init_tv(ir_node *init)
146 {
147         for (;;) {
148                 ir_mode *mode = get_irn_mode(init);
149
150                 switch (get_irn_opcode(init)) {
151
152                 case iro_Cast:
153                         init = get_Cast_op(init);
154                         continue;
155
156                 case iro_Conv:
157                         init = get_Conv_op(init);
158                         continue;
159
160                 case iro_Const:
161                         return get_Const_tarval(init);
162
163                 case iro_SymConst:
164                         switch (get_SymConst_kind(init)) {
165                         case symconst_ofs_ent:
166                                 return new_tarval_from_long(get_entity_offset(get_SymConst_entity(init)), mode);
167
168                         case symconst_type_size:
169                                 return new_tarval_from_long(get_type_size_bytes(get_SymConst_type(init)), mode);
170
171                         case symconst_type_align:
172                                 return new_tarval_from_long(get_type_alignment_bytes(get_SymConst_type(init)), mode);
173
174                         case symconst_enum_const:
175                                 return get_enumeration_value(get_SymConst_enum(init));
176
177                         default:
178                                 return NULL;
179                         }
180
181                 default:
182                         return NULL;
183                 }
184         }
185 }
186
187 /**
188  * dump an atomic value
189  */
190 static void do_dump_atomic_init(ia32_decl_env_t *env, obstack_t *obst,
191                                 ir_node *init)
192 {
193         ir_mode *mode = get_irn_mode(init);
194         int bytes     = get_mode_size_bytes(mode);
195         tarval *tv;
196         ir_entity *ent;
197
198         switch (get_irn_opcode(init)) {
199
200         case iro_Cast:
201                 do_dump_atomic_init(env, obst, get_Cast_op(init));
202                 return;
203
204         case iro_Conv:
205                 do_dump_atomic_init(env, obst, get_Conv_op(init));
206                 return;
207
208         case iro_Const:
209                 tv = get_Const_tarval(init);
210
211                 /* it's a arithmetic value */
212                 dump_arith_tarval(obst, tv, bytes);
213                 return;
214
215         case iro_SymConst:
216                 switch (get_SymConst_kind(init)) {
217                 case symconst_addr_name:
218                         obstack_printf(obst, "%s", get_id_str(get_SymConst_name(init)));
219                         break;
220
221                 case symconst_addr_ent:
222                         ent = get_SymConst_entity(init);
223                         if(!entity_visited(ent)) {
224                                 waitq_put(env->worklist, ent);
225                                 mark_entity_visited(ent);
226                         }
227                         obstack_printf(obst, "%s", get_entity_ld_name(ent));
228                         break;
229
230                 case symconst_ofs_ent:
231                         ent = get_SymConst_entity(init);
232 #if 0       /* not needed, is it? */
233                         if(!entity_visited(ent)) {
234                                 waitq_put(env->worklist, ent);
235                                 mark_entity_visited(ent);
236                         }
237 #endif
238                         obstack_printf(obst, "%d", get_entity_offset(ent));
239                         break;
240
241                 case symconst_type_size:
242                         obstack_printf(obst, "%d", get_type_size_bytes(get_SymConst_type(init)));
243                         break;
244
245                 case symconst_type_align:
246                         obstack_printf(obst, "%d", get_type_alignment_bytes(get_SymConst_type(init)));
247                         break;
248
249                 case symconst_enum_const:
250                         tv = get_enumeration_value(get_SymConst_enum(init));
251                         dump_arith_tarval(obst, tv, bytes);
252                         break;
253
254                 default:
255                         assert(!"dump_atomic_init(): don't know how to init from this SymConst");
256                 }
257                 return;
258
259                 case iro_Add:
260                         do_dump_atomic_init(env, obst, get_Add_left(init));
261                         obstack_printf(obst, " + ");
262                         do_dump_atomic_init(env, obst, get_Add_right(init));
263                         return;
264
265                 case iro_Sub:
266                         do_dump_atomic_init(env, obst, get_Sub_left(init));
267                         obstack_printf(obst, " - ");
268                         do_dump_atomic_init(env, obst, get_Sub_right(init));
269                         return;
270
271                 case iro_Mul:
272                         do_dump_atomic_init(env, obst, get_Mul_left(init));
273                         obstack_printf(obst, " * ");
274                         do_dump_atomic_init(env, obst, get_Mul_right(init));
275                         return;
276
277                 default:
278                         assert(0 && "dump_atomic_init(): unknown IR-node");
279         }
280 }
281
282 /**
283  * dumps the type for given size (.byte, .long, ...)
284  */
285 static void dump_size_type(obstack_t *obst, int size) {
286         switch (size) {
287
288         case 1:
289                 obstack_printf(obst, "\t.byte\t");
290                 break;
291
292         case 2:
293                 obstack_printf(obst, "\t.value\t");
294                 break;
295
296         case 4:
297                 obstack_printf(obst, "\t.long\t");
298                 break;
299
300         case 8:
301                 obstack_printf(obst, "\t.quad\t");
302                 break;
303
304         case 10:
305         case 12:
306                 /* handled in arith */
307                 break;
308
309         case 16:
310                 obstack_printf(obst, "\t.octa\t");
311                 break;
312
313         default:
314                 fprintf(stderr, "Try to dump a type with %d bytes\n", size);
315                 assert(0);
316         }
317 }
318
319 /**
320  * dump an atomic value to an obstack
321  */
322 static void dump_atomic_init(ia32_decl_env_t *env, obstack_t *obst,
323                              ir_node *init)
324 {
325         ir_mode *mode = get_irn_mode(init);
326         int bytes     = get_mode_size_bytes(mode);
327
328         dump_size_type(obst, bytes);
329         do_dump_atomic_init(env, obst, init);
330         obstack_printf(obst, "\n");
331 }
332
333 /************************************************************************/
334 /* Routines to dump global variables                                    */
335 /************************************************************************/
336
337 /**
338  * Determine if an entity is a string constant
339  * @param ent The entity
340  * @return 1 if it is a string constant, 0 otherwise
341  */
342 static int ent_is_string_const(ir_entity *ent)
343 {
344         ir_type *type, *element_type;
345         ir_mode *mode;
346         int i, c, n;
347
348         type = get_entity_type(ent);
349
350         /* if it's an array */
351         if (!is_Array_type(type))
352                 return 0;
353
354         element_type = get_array_element_type(type);
355
356         /* and the array's element type is primitive */
357         if (!is_Primitive_type(element_type))
358                 return 0;
359
360         /* and the mode of the element type is an int of
361          * the same size as the byte mode */
362         mode = get_type_mode(element_type);
363         if (!mode_is_int(mode)
364                 || get_mode_size_bits(mode) != get_mode_size_bits(mode_Bs))
365                 return 0;
366
367         /* if it contains only printable chars and a 0 at the end */
368         n = get_compound_ent_n_values(ent);
369         for (i = 0; i < n; ++i) {
370                 ir_node *irn = get_compound_ent_value(ent, i);
371                 if(get_irn_opcode(irn) != iro_Const)
372                         return 0;
373
374                 c = (int) get_tarval_long(get_Const_tarval(irn));
375
376                 if((i < n - 1 && !(isgraph(c) || isspace(c)))
377                                 || (i == n - 1 && c != '\0'))
378                         return 0;
379         }
380
381         /* then we can emit it as a string constant */
382         return 1;
383 }
384
385 /**
386  * Dump a string constant.
387  * No checks are made!!
388  * @param obst The obst to dump on.
389  * @param ent The entity to dump.
390  */
391 static void dump_string_cst(obstack_t *obst, ir_entity *ent)
392 {
393         int i, n;
394
395         obstack_printf(obst, "\t.string \"");
396         n = get_compound_ent_n_values(ent);
397
398         for (i = 0; i < n-1; ++i) {
399                 ir_node *irn;
400                 int c;
401
402                 irn = get_compound_ent_value(ent, i);
403                 c = (int) get_tarval_long(get_Const_tarval(irn));
404
405                 switch (c) {
406                 case '"' : obstack_printf(obst, "\\\""); break;
407                 case '\n': obstack_printf(obst, "\\n"); break;
408                 case '\r': obstack_printf(obst, "\\r"); break;
409                 case '\t': obstack_printf(obst, "\\t"); break;
410                 case '\\': obstack_printf(obst, "\\\\"); break;
411                 default  :
412                         if (isprint(c))
413                                 obstack_printf(obst, "%c", c);
414                         else
415                                 obstack_printf(obst, "\\%o", c);
416                         break;
417                 }
418         }
419         obstack_printf(obst, "\"\n");
420 }
421
422 static void dump_array_init(ia32_decl_env_t *env, obstack_t *obst,
423                             ir_entity *ent)
424 {
425         const ir_type *ty = get_entity_type(ent);
426         int i;
427         int filler;
428         int size = 0;
429
430         /* potential spare values should be already included! */
431         for (i = 0; i < get_compound_ent_n_values(ent); ++i) {
432                 ir_entity *step = get_compound_ent_value_member(ent, i);
433                 ir_type *stype = get_entity_type(step);
434
435                 if (get_type_mode(stype)) {
436                         int align = (get_type_alignment_bits(stype) + 7) >> 3;
437                         int n     = size % align;
438
439                         if (n > 0) {
440                                 obstack_printf(obst, "\t.zero\t%d\n", align - n);
441                                 size += align - n;
442                         }
443                 }
444                 dump_atomic_init(env, obst, get_compound_ent_value(ent, i));
445                 size += get_type_size_bytes(stype);
446         }
447         filler = get_type_size_bytes(ty) - size;
448
449         if (filler > 0)
450                 obstack_printf(obst, "\t.skip\t%d\n", filler);
451 }
452
453 enum normal_or_bitfield_kind {
454         NORMAL = 0,
455         BITFIELD
456 };
457
458 typedef struct {
459         enum normal_or_bitfield_kind kind;
460         union {
461                 ir_node *value;
462                 unsigned char bf_val;
463         } v;
464 } normal_or_bitfield;
465
466 /**
467  * Dump an initializer for a compound entity.
468  */
469 static void dump_compound_init(ia32_decl_env_t *env, obstack_t *obst,
470                                ir_entity *ent)
471 {
472         normal_or_bitfield *vals;
473         int i, j, n = get_compound_ent_n_values(ent);
474         int last_ofs;
475
476         /* Find the initializer size. Sorrily gcc support a nasty feature:
477            The last field of a compound may be a flexible array. This allows
478            initializers bigger than the type size. */
479         last_ofs = get_type_size_bytes(get_entity_type(ent));
480         for (i = 0; i < n; ++i) {
481                 int offset = get_compound_ent_value_offset_bytes(ent, i);
482                 int bits_remainder = get_compound_ent_value_offset_bit_remainder(ent, i);
483                 const compound_graph_path *path = get_compound_ent_value_path(ent, i);
484                 int path_len = get_compound_graph_path_length(path);
485                 ir_entity *last_ent = get_compound_graph_path_node(path, path_len - 1);
486                 int value_len = get_type_size_bits(get_entity_type(last_ent));
487
488                 offset += (value_len + bits_remainder + 7) >> 3;
489
490                 if (offset > last_ofs) {
491                         last_ofs = offset;
492                 }
493         }
494
495         /*
496          * In the worst case, every initializer allocates one byte.
497          * Moreover, initializer might be big, do not allocate on stack.
498          */
499         vals = xcalloc(last_ofs, sizeof(vals[0]));
500
501         /* collect the values and store them at the offsets */
502         for (i = 0; i < n; ++i) {
503                 const compound_graph_path *path = get_compound_ent_value_path(ent, i);
504                 int path_len = get_compound_graph_path_length(path);
505                 int offset = get_compound_ent_value_offset_bytes(ent, i);
506                 int offset_bits = get_compound_ent_value_offset_bit_remainder(ent, i);
507                 ir_node *value = get_compound_ent_value(ent, i);
508                 ir_entity *last_ent = get_compound_graph_path_node(path, path_len - 1);
509                 int value_len = get_type_size_bits(get_entity_type(last_ent));
510                 assert(offset >= 0);
511                 assert(offset_bits >= 0);
512
513                 if (offset_bits != 0 ||
514                         (value_len != 8 && value_len != 16 && value_len != 32 && value_len != 64)) {
515                         tarval *shift, *shifted;
516                         tarval *tv = get_atomic_init_tv(value);
517                         if (tv == NULL) {
518                                 panic("Couldn't get numeric value for bitfield initializer '%s'\n",
519                                       get_entity_ld_name(ent));
520                         }
521                         tv = tarval_convert_to(tv, mode_Lu);
522                         shift = new_tarval_from_long(offset_bits, mode_Is);
523                         shifted = tarval_shl(tv, shift);
524                         if (shifted == tarval_bad || shifted == tarval_undefined) {
525                                 panic("Couldn't shift numeric value for bitfield initializer '%s'\n",
526                                       get_entity_ld_name(ent));
527                         }
528
529                         for (j = 0; value_len > 0; ++j) {
530                                 assert(offset + j < last_ofs);
531                                 assert(vals[offset + j].kind == BITFIELD || vals[offset + j].v.value == NULL);
532                                 vals[offset + j].kind = BITFIELD;
533                                 vals[offset + j].v.bf_val |= get_tarval_sub_bits(shifted, j);
534                                 value_len -= 8 - offset_bits;
535                                 offset_bits = 0;
536                         }
537                 } else {
538                         assert(offset < last_ofs);
539                         assert(vals[offset].kind == NORMAL);
540                         assert(vals[offset].v.value == NULL);
541                         vals[offset].v.value = value;
542                 }
543         }
544
545         /* now write them sorted */
546         for (i = 0; i < last_ofs; ) {
547                 int space = 0, skip = 0;
548                 if (vals[i].kind == NORMAL) {
549                         if(vals[i].v.value != NULL) {
550                                 dump_atomic_init(env, obst, vals[i].v.value);
551                                 skip = get_mode_size_bytes(get_irn_mode(vals[i].v.value)) - 1;
552                         } else {
553                                 space = 1;
554                         }
555                 } else {
556                         assert(vals[i].kind == BITFIELD);
557                         obstack_printf(obst, "\t.byte\t%d\n", vals[i].v.bf_val);
558                 }
559
560                 ++i;
561                 space = 0;
562                 while (i < last_ofs && vals[i].kind == NORMAL && vals[i].v.value == NULL) {
563                         ++space;
564                         ++i;
565                 }
566                 space -= skip;
567                 assert(space >= 0);
568
569                 /* a gap */
570                 if (space > 0)
571                         obstack_printf(obst, "\t.skip\t%d\n", space);
572         }
573         xfree(vals);
574 }
575
576 /**
577  * Dump a global entity.
578  */
579 static void dump_global(ia32_decl_env_t *env, ir_entity *ent, int emit_commons)
580 {
581         obstack_t *obst;
582         ir_type *type = get_entity_type(ent);
583         const char *ld_name = get_entity_ld_name(ent);
584         ir_variability variability = get_entity_variability(ent);
585         ir_visibility visibility = get_entity_visibility(ent);
586         int align = get_type_alignment_bytes(type);
587         int emit_as_common = 0;
588
589         obst = env->data_obst;
590         if (is_Method_type(type)) {
591                 if (get_method_img_section(ent) == section_constructors) {
592                         obst = env->ctor_obst;
593                         obstack_printf(obst, ".balign\t%d\n", align);
594                         dump_size_type(obst, align);
595                         obstack_printf(obst, "%s\n", ld_name);
596                 }
597                 return;
598         } else if (variability == variability_constant) {
599                 /* a constant entity, put it on the rdata */
600                 obst = env->rodata_obst;
601         } else if (variability == variability_uninitialized) {
602                 /* uninitialized entity put it in bss segment */
603                 obst = env->bss_obst;
604                 if(emit_commons && visibility != visibility_local)
605                         emit_as_common = 1;
606         }
607
608         be_dbg_variable(env->main_env->db_handle, obst, ent);
609
610         /* global or not global */
611         if (visibility == visibility_external_visible && !emit_as_common) {
612                 obstack_printf(obst, ".global\t%s\n", ld_name);
613         } else if(visibility == visibility_external_allocated) {
614                 obstack_printf(obst, ".global\t%s\n", ld_name);
615                 /* we can return now... */
616                 return;
617         }
618         /* alignment */
619         if (align > 1 && !emit_as_common) {
620                 obstack_printf(obst, ".balign\t%d\n", align);
621         }
622
623         if (!emit_as_common) {
624                 obstack_printf(obst, "%s:\n", ld_name);
625         }
626
627         if (variability == variability_uninitialized) {
628                 if(emit_as_common) {
629                         obstack_printf(obst, "\t.comm %s,%d,%d\n",
630                                         ld_name, get_type_size_bytes(type), align);
631                 } else {
632                         obstack_printf(obst, "\t.zero %d\n", get_type_size_bytes(type));
633                 }
634         } else if (is_atomic_type(type)) {
635                 dump_atomic_init(env, obst, get_atomic_ent_value(ent));
636         } else if (ent_is_string_const(ent)) {
637                 dump_string_cst(obst, ent);
638         } else if (is_Array_type(type)) {
639                 dump_array_init(env, obst, ent);
640         } else if (is_compound_type(type)) {
641                 dump_compound_init(env, obst, ent);
642         } else {
643                 assert(0 && "unsupported type");
644         }
645 }
646
647 /**
648  * Dumps declarations of global variables and the initialization code.
649  */
650 static void ia32_dump_globals(ir_type *gt, ia32_decl_env_t *env,
651                               int emit_commons, int only_emit_marked)
652 {
653         int i, n = get_compound_n_members(gt);
654         waitq *worklist = new_waitq();
655
656         if(only_emit_marked) {
657                 for (i = 0; i < n; i++) {
658                         ir_entity *ent = get_compound_member(gt, i);
659                         if(entity_visited(ent) ||
660                                         get_entity_visibility(ent) != visibility_external_allocated) {
661                                 waitq_put(worklist, ent);
662                                 mark_entity_visited(ent);
663                         }
664                 }
665         } else {
666                 inc_master_type_visited();
667                 for (i = 0; i < n; i++) {
668                         ir_entity *ent = get_compound_member(gt, i);
669                         mark_entity_visited(ent);
670                         waitq_put(worklist, ent);
671                 }
672         }
673
674         env->worklist = worklist;
675
676         while(!waitq_empty(worklist)) {
677                 ir_entity *ent = waitq_get(worklist);
678
679                 dump_global(env, ent, emit_commons);
680         }
681
682         del_waitq(worklist);
683         env->worklist = NULL;
684 }
685
686 /************************************************************************/
687
688 void be_gas_emit_decls(be_emit_env_t *emit, const be_main_env_t *main_env,
689                        int only_emit_marked_entities)
690 {
691         ia32_decl_env_t env;
692         obstack_t rodata, data, bss, ctor;
693         int    size;
694         char   *cp;
695
696         /* dump the global type */
697         obstack_init(&rodata);
698         obstack_init(&data);
699         obstack_init(&bss);
700         obstack_init(&ctor);
701
702         env.rodata_obst = &rodata;
703         env.data_obst   = &data;
704         env.bss_obst    = &bss;
705         env.ctor_obst   = &ctor;
706         env.main_env    = main_env;
707
708         ia32_dump_globals(get_glob_type(), &env, 1, only_emit_marked_entities);
709
710         size = obstack_object_size(&data);
711         cp   = obstack_finish(&data);
712         if (size > 0) {
713                 be_gas_emit_switch_section(emit, GAS_SECTION_DATA);
714                 be_emit_string_len(emit, cp, size);
715                 be_emit_write_line(emit);
716         }
717
718         size = obstack_object_size(&rodata);
719         cp   = obstack_finish(&rodata);
720         if (size > 0) {
721                 be_gas_emit_switch_section(emit, GAS_SECTION_RODATA);
722                 be_emit_string_len(emit, cp, size);
723                 be_emit_write_line(emit);
724         }
725
726         size = obstack_object_size(&bss);
727         cp   = obstack_finish(&bss);
728         if (size > 0) {
729                 be_gas_emit_switch_section(emit, GAS_SECTION_COMMON);
730                 be_emit_string_len(emit, cp, size);
731                 be_emit_write_line(emit);
732         }
733
734         size = obstack_object_size(&ctor);
735         cp   = obstack_finish(&ctor);
736         if (size > 0) {
737                 be_gas_emit_switch_section(emit, GAS_SECTION_CTOR);
738                 be_emit_string_len(emit, cp, size);
739                 be_emit_write_line(emit);
740         }
741
742         obstack_free(&rodata, NULL);
743         obstack_free(&data, NULL);
744         obstack_free(&bss, NULL);
745         obstack_free(&ctor, NULL);
746
747         /* dump the Thread Local Storage */
748         obstack_init(&data);
749
750         env.rodata_obst = &data;
751         env.data_obst   = &data;
752         env.bss_obst    = &data;
753         env.ctor_obst   = NULL;
754
755         ia32_dump_globals(get_tls_type(), &env, 0, only_emit_marked_entities);
756
757         size = obstack_object_size(&data);
758         cp   = obstack_finish(&data);
759         if (size > 0) {
760                 be_gas_emit_switch_section(emit, GAS_SECTION_TLS);
761                 be_emit_cstring(emit, ".balign\t32\n");
762                 be_emit_write_line(emit);
763                 be_emit_string_len(emit, cp, size);
764                 be_emit_write_line(emit);
765         }
766
767         obstack_free(&data, NULL);
768 }