ia32_gen_decls.c 16.6 KB
Newer Older
1
2
3
4
5
6
7
/**
 * Dumps global variables and constants as ia32 assembler.
 * @author Christian Wuerdig
 * @date 04.11.2005
 * @version $Id$
 */

8
9
10
11
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

12
13
14
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
Christian Würdig's avatar
Christian Würdig committed
15
#include <assert.h>
16

17
#include "obst.h"
18
19
20
21
#include "tv.h"
#include "irnode.h"
#include "entity.h"
#include "irprog.h"
22
#include "error.h"
23

Christian Würdig's avatar
Christian Würdig committed
24
#include "../be.h"
Christian Würdig's avatar
Christian Würdig committed
25

Michael Beck's avatar
Michael Beck committed
26
#include "ia32_emitter.h"
27
28
#include "ia32_gen_decls.h"

Christian Würdig's avatar
Christian Würdig committed
29
30
31
typedef struct obstack obstack_t;

typedef struct _ia32_decl_env {
Christian Würdig's avatar
Christian Würdig committed
32
33
	obstack_t *rodata_obst;
	obstack_t *data_obst;
34
	obstack_t *bss_obst;
Christian Würdig's avatar
Christian Würdig committed
35
36
	obstack_t *ctor_obst;
	const be_main_env_t *main_env;
Christian Würdig's avatar
Christian Würdig committed
37
38
} ia32_decl_env_t;

39
40
/************************************************************************/

Michael Beck's avatar
Michael Beck committed
41
42
43
/**
 * output a tarval
 */
Christian Würdig's avatar
Christian Würdig committed
44
static void dump_arith_tarval(obstack_t *obst, tarval *tv, int bytes)
45
{
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
	switch (bytes) {

	case 1:
		obstack_printf(obst, "0x%02x", get_tarval_sub_bits(tv, 0));
		break;

	case 2:
		obstack_printf(obst, "0x%02x%02x", get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
		break;

	case 4:
		obstack_printf(obst, "0x%02x%02x%02x%02x",
			get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
		break;

	case 8:
		obstack_printf(obst, "0x%02x%02x%02x%02x%02x%02x%02x%02x",
			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));
		break;

	case 10:
	case 12:
		break;

71
72
73
74
75
76
77
78
79
80
81
82
83
84
	case 16:
		obstack_printf(obst, "0x%02x%02x%02x%02x%02x%02x%02x%02x"
				               "%02x%02x%02x%02x%02x%02x%02x%02x",
			get_tarval_sub_bits(tv, 15), get_tarval_sub_bits(tv, 16),
			get_tarval_sub_bits(tv, 13), get_tarval_sub_bits(tv, 12),
			get_tarval_sub_bits(tv, 11), get_tarval_sub_bits(tv, 10),
			get_tarval_sub_bits(tv, 9), get_tarval_sub_bits(tv, 8),
			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));
		break;


85
86
87
88
	default:
		fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
		assert(0);
	}
89
90
}

91
92
93
/**
 * Return the tarval of an atomic initializer.
 */
94
95
static tarval *get_atomic_init_tv(ir_node *init)
{
96
97
	for (;;) {
		ir_mode *mode = get_irn_mode(init);
98

99
		switch (get_irn_opcode(init)) {
100

101
102
103
		case iro_Cast:
			init = get_Cast_op(init);
			continue;
104

105
106
107
		case iro_Conv:
			init = get_Conv_op(init);
			continue;
108

109
110
		case iro_Const:
			return get_Const_tarval(init);
111

112
113
114
115
		case iro_SymConst:
			switch (get_SymConst_kind(init)) {
			case symconst_ofs_ent:
				return new_tarval_from_long(get_entity_offset(get_SymConst_entity(init)), mode);
116

117
118
			case symconst_type_size:
				return new_tarval_from_long(get_type_size_bytes(get_SymConst_type(init)), mode);
119

120
121
			case symconst_type_align:
				return new_tarval_from_long(get_type_alignment_bytes(get_SymConst_type(init)), mode);
122

123
124
			case symconst_enum_const:
				return get_enumeration_value(get_SymConst_enum(init));
125

126
127
128
			default:
				return NULL;
			}
129
130
131

		default:
			return NULL;
132
		}
133
134
135
	}
}

136
/**
137
138
 * dump an atomic value
 */
Christian Würdig's avatar
Christian Würdig committed
139
static void do_dump_atomic_init(obstack_t *obst, ir_node *init)
140
{
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
	ir_mode *mode = get_irn_mode(init);
	int bytes     = get_mode_size_bytes(mode);
	tarval *tv;

	switch (get_irn_opcode(init)) {

	case iro_Cast:
		do_dump_atomic_init(obst, get_Cast_op(init));
		return;

	case iro_Conv:
		do_dump_atomic_init(obst, get_Conv_op(init));
		return;

	case iro_Const:
		tv = get_Const_tarval(init);

		/* it's a arithmetic value */
		dump_arith_tarval(obst, tv, bytes);
		return;

	case iro_SymConst:
		switch (get_SymConst_kind(init)) {
		case symconst_addr_name:
			obstack_printf(obst, "%s", get_id_str(get_SymConst_name(init)));
			break;

		case symconst_addr_ent:
			obstack_printf(obst, "%s", get_entity_ld_name(get_SymConst_entity(init)));
			break;

172
		case symconst_ofs_ent:
173
			obstack_printf(obst, "%d", get_entity_offset(get_SymConst_entity(init)));
174
175
			break;

176
		case symconst_type_size:
177
178
179
			obstack_printf(obst, "%d", get_type_size_bytes(get_SymConst_type(init)));
			break;

180
181
182
183
		case symconst_type_align:
			obstack_printf(obst, "%d", get_type_alignment_bytes(get_SymConst_type(init)));
			break;

Michael Beck's avatar
Michael Beck committed
184
		case symconst_enum_const:
185
186
			tv = get_enumeration_value(get_SymConst_enum(init));
			dump_arith_tarval(obst, tv, bytes);
Michael Beck's avatar
Michael Beck committed
187
188
			break;

189
		default:
190
			assert(!"dump_atomic_init(): don't know how to init from this SymConst");
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
		}
		return;

		case iro_Add:
			do_dump_atomic_init(obst, get_Add_left(init));
			obstack_printf(obst, " + ");
			do_dump_atomic_init(obst, get_Add_right(init));
			return;

		case iro_Sub:
			do_dump_atomic_init(obst, get_Sub_left(init));
			obstack_printf(obst, " - ");
			do_dump_atomic_init(obst, get_Sub_right(init));
			return;

		case iro_Mul:
			do_dump_atomic_init(obst, get_Mul_left(init));
			obstack_printf(obst, " * ");
			do_dump_atomic_init(obst, get_Mul_right(init));
			return;

		default:
			assert(0 && "dump_atomic_init(): unknown IR-node");
	}
215
216
}

217
/**
Christian Würdig's avatar
Christian Würdig committed
218
 * dumps the type for given size (.byte, .long, ...)
219
 */
Christian Würdig's avatar
Christian Würdig committed
220
221
static void dump_size_type(obstack_t *obst, int size) {
	switch (size) {
222

223
224
225
	case 1:
		obstack_printf(obst, "\t.byte\t");
		break;
226

227
228
229
	case 2:
		obstack_printf(obst, "\t.value\t");
		break;
230

231
232
233
	case 4:
		obstack_printf(obst, "\t.long\t");
		break;
234

235
236
237
	case 8:
		obstack_printf(obst, "\t.quad\t");
		break;
238

239
240
241
242
	case 10:
	case 12:
		/* handled in arith */
		break;
243

244
245
246
247
	case 16:
		obstack_printf(obst, "\t.octa\t");
		break;

248
	default:
Christian Würdig's avatar
Christian Würdig committed
249
		fprintf(stderr, "Try to dump a type with %d bytes\n", size);
250
251
		assert(0);
	}
Christian Würdig's avatar
Christian Würdig committed
252
253
}

254
255
/**
 * dump an atomic value to an obstack
Christian Würdig's avatar
Christian Würdig committed
256
257
258
259
260
 */
static void dump_atomic_init(obstack_t *obst, ir_node *init)
{
	ir_mode *mode = get_irn_mode(init);
	int bytes     = get_mode_size_bytes(mode);
261

Christian Würdig's avatar
Christian Würdig committed
262
	dump_size_type(obst, bytes);
263
264
	do_dump_atomic_init(obst, init);
	obstack_printf(obst, "\n");
265
266
267
268
269
270
271
272
273
274
275
}

/************************************************************************/
/* Routines to dump global variables                                    */
/************************************************************************/

/**
 * Determine if an entity is a string constant
 * @param ent The entity
 * @return 1 if it is a string constant, 0 otherwise
 */
276
static int ent_is_string_const(ir_entity *ent)
277
{
278
279
280
	ir_type *type, *element_type;
	ir_mode *mode;
	int i, c, n;
281

282
	type = get_entity_type(ent);
283
284

	/* if it's an array */
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
	if (!is_Array_type(type))
		return 0;

	element_type = get_array_element_type(type);

	/* and the array's element type is primitive */
	if (!is_Primitive_type(element_type))
		return 0;

	/* and the mode of the element type is an int of
	 * the same size as the byte mode */
	mode = get_type_mode(element_type);
	if (!mode_is_int(mode)
		|| get_mode_size_bits(mode) != get_mode_size_bits(mode_Bs))
		return 0;

	/* if it contains only printable chars and a 0 at the end */
	n = get_compound_ent_n_values(ent);
	for (i = 0; i < n; ++i) {
		ir_node *irn = get_compound_ent_value(ent, i);
		if(get_irn_opcode(irn) != iro_Const)
			return 0;

		c = (int) get_tarval_long(get_Const_tarval(irn));

		if((i < n - 1 && !(isgraph(c) || isspace(c)))
				|| (i == n - 1 && c != '\0'))
			return 0;
313
314
	}

315
316
	/* then we can emit it as a string constant */
	return 1;
317
318
319
}

/**
Michael Beck's avatar
Michael Beck committed
320
 * Dump a string constant.
321
322
323
324
 * No checks are made!!
 * @param obst The obst to dump on.
 * @param ent The entity to dump.
 */
325
static void dump_string_cst(obstack_t *obst, ir_entity *ent)
326
{
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
	int i, n;

	obstack_printf(obst, "\t.string \"");
	n = get_compound_ent_n_values(ent);

	for (i = 0; i < n-1; ++i) {
		ir_node *irn;
		int c;

		irn = get_compound_ent_value(ent, i);
		c = (int) get_tarval_long(get_Const_tarval(irn));

		switch (c) {
		case '"' : obstack_printf(obst, "\\\""); break;
		case '\n': obstack_printf(obst, "\\n"); break;
		case '\r': obstack_printf(obst, "\\r"); break;
		case '\t': obstack_printf(obst, "\\t"); break;
344
		case '\\': obstack_printf(obst, "\\\\"); break;
345
346
347
348
		default  :
			if (isprint(c))
				obstack_printf(obst, "%c", c);
			else
349
				obstack_printf(obst, "\\%o", c);
350
351
352
353
			break;
		}
	}
	obstack_printf(obst, "\"\n");
354
355
}

356
static void dump_array_init(obstack_t *obst, ir_entity *ent)
357
358
359
360
361
362
363
364
{
	const ir_type *ty = get_entity_type(ent);
	int i;
	int filler;
	int size = 0;

	/* potential spare values should be already included! */
	for (i = 0; i < get_compound_ent_n_values(ent); ++i) {
365
		ir_entity *step = get_compound_ent_value_member(ent, i);
366
367
368
369
370
371
372
373
374
375
376
377
378
		ir_type *stype = get_entity_type(step);

		if (get_type_mode(stype)) {
			int align = (get_type_alignment_bits(stype) + 7) >> 3;
			int n     = size % align;

			if (n > 0) {
				obstack_printf(obst, "\t.zero\t%d\n", align - n);
				size += align - n;
			}
		}
		dump_atomic_init(obst, get_compound_ent_value(ent, i));
		size += get_type_size_bytes(stype);
Michael Beck's avatar
Michael Beck committed
379
	}
380
381
382
383
	filler = get_type_size_bytes(ty) - size;

	if (filler > 0)
		obstack_printf(obst, "\t.skip\t%d\n", filler);
384
385
}

386
387
388
389
390
391
392
393
394
395
396
397
398
enum normal_or_bitfield_kind {
	NORMAL = 0,
	BITFIELD
};

typedef struct {
	enum normal_or_bitfield_kind kind;
	union {
		ir_node *value;
		unsigned char bf_val;
	} v;
} normal_or_bitfield;

399
400
401
/**
 * Dump an initializer for a compound entity.
 */
402
static void dump_compound_init(obstack_t *obst, ir_entity *ent)
403
{
404
	normal_or_bitfield *vals;
405
406
407
408
	int i, j, n = get_compound_ent_n_values(ent);
	int last_ofs;

	/* Find the initializer size. Sorrily gcc support a nasty feature:
409
	   The last field of a compound may be a flexible array. This allows
410
411
412
413
	   initializers bigger than the type size. */
	last_ofs = 0;
	for (i = 0; i < n; ++i) {
		int offset = get_compound_ent_value_offset_bytes(ent, i);
414
		int bits_remainder = get_compound_ent_value_offset_bit_remainder(ent, i);
Michael Beck's avatar
Michael Beck committed
415
416
417
418
		const compound_graph_path *path = get_compound_ent_value_path(ent, i);
		int path_len = get_compound_graph_path_length(path);
		ir_entity *last_ent = get_compound_graph_path_node(path, path_len - 1);
		int value_len = get_type_size_bits(get_entity_type(last_ent));
419

420
		offset += (value_len + bits_remainder + 7) >> 3;
Michael Beck's avatar
Michael Beck committed
421
422

		if (offset > last_ofs) {
423
			last_ofs = offset;
Michael Beck's avatar
Michael Beck committed
424
		}
425
	}
426
427

	/*
428
429
	 * In the worst case, every initializer allocates one byte.
	 * Moreover, initializer might be big, do not allocate an stack.
Michael Beck's avatar
Michael Beck committed
430
	 */
431
	vals = xcalloc(last_ofs, sizeof(vals[0]));
432
433

	/* collect the values and store them at the offsets */
434
	for (i = 0; i < n; ++i) {
435
436
437
		const compound_graph_path *path = get_compound_ent_value_path(ent, i);
		int path_len = get_compound_graph_path_length(path);
		int offset = get_compound_ent_value_offset_bytes(ent, i);
438
		int offset_bits = get_compound_ent_value_offset_bit_remainder(ent, i);
439
		ir_node *value = get_compound_ent_value(ent, i);
440
		ir_entity *last_ent = get_compound_graph_path_node(path, path_len - 1);
441
		int value_len = get_type_size_bits(get_entity_type(last_ent));
442
443
		assert(offset >= 0);
		assert(offset_bits >= 0);
444

445
446
		if (offset_bits != 0 ||
			(value_len != 8 && value_len != 16 && value_len != 32 && value_len != 64)) {
447
448
			tarval *shift, *shifted;
			tarval *tv = get_atomic_init_tv(value);
449
			if (tv == NULL) {
450
451
452
				panic("Couldn't get numeric value for bitfield initializer '%s'\n",
				      get_entity_ld_name(ent));
			}
453
			tv = tarval_convert_to(tv, mode_Lu);
454
455
			shift = new_tarval_from_long(offset_bits, mode_Is);
			shifted = tarval_shl(tv, shift);
456
			if (shifted == tarval_bad || shifted == tarval_undefined) {
457
458
459
				panic("Couldn't shift numeric value for bitfield initializer '%s'\n",
				      get_entity_ld_name(ent));
			}
460

461
			for (j = 0; value_len > 0; ++j) {
462
				assert(offset + j < last_ofs);
Michael Beck's avatar
Michael Beck committed
463
464
465
				assert(vals[offset + j].kind == BITFIELD || vals[offset + j].v.value == NULL);
				vals[offset + j].kind = BITFIELD;
				vals[offset + j].v.bf_val |= get_tarval_sub_bits(shifted, j);
Matthias Braun's avatar
Matthias Braun committed
466
467
				value_len -= 8 - offset_bits;
				offset_bits = 0;
468
469
			}
		} else {
470
			assert(offset < last_ofs);
471
472
473
			assert(vals[offset].kind == NORMAL);
			assert(vals[offset].v.value == NULL);
			vals[offset].v.value = value;
474
		}
475
	}
476

477
	/* now write them sorted */
478
	for (i = 0; i < last_ofs; ) {
479
480
		int space = 0, skip = 0;
		if (vals[i].kind == NORMAL) {
481
482
483
484
485
486
			if(vals[i].v.value != NULL) {
				dump_atomic_init(obst, vals[i].v.value);
				skip = get_mode_size_bytes(get_irn_mode(vals[i].v.value)) - 1;
	 		} else {
	 			space = 1;
	 		}
487
		} else {
488
			assert(vals[i].kind == BITFIELD);
489
490
			obstack_printf(obst, "\t.byte\t%d\n", vals[i].v.bf_val);
		}
491

492
493
		++i;
		space = 0;
494
		while (i < last_ofs && vals[i].kind == NORMAL && vals[i].v.value == NULL) {
495
496
497
498
499
			++space;
			++i;
		}
		space -= skip;
		assert(space >= 0);
500

501
		/* a gap */
502
		if (space > 0)
503
504
			obstack_printf(obst, "\t.skip\t%d\n", space);
	}
505
	xfree(vals);
506
}
507

508
509
510
/**
 * Dump a global entity.
 */
511
static void dump_global(ia32_decl_env_t *env, ir_entity *ent, int emit_commons)
512
513
514
515
516
517
518
{
	obstack_t *obst;
	ir_type *type = get_entity_type(ent);
	const char *ld_name = get_entity_ld_name(ent);
	ir_variability variability = get_entity_variability(ent);
	ir_visibility visibility = get_entity_visibility(ent);
	int align = get_type_alignment_bytes(type);
519
	int emit_as_common = 0;
520
521

	obst = env->data_obst;
522
523
	if (is_Method_type(type)) {
		if (get_method_img_section(ent) == section_constructors) {
524
525
526
527
528
529
			obst = env->ctor_obst;
			obstack_printf(obst, ".balign\t%d\n", align);
			dump_size_type(obst, align);
			obstack_printf(obst, "%s\n", ld_name);
		}
		return;
530
	} else if (variability == variability_constant) {
531
532
		/* a constant entity, put it on the rdata */
		obst = env->rodata_obst;
533
	} else if (variability == variability_uninitialized) {
534
535
		/* uninitialized entity put it in bss segment */
		obst = env->bss_obst;
536
537
		if(emit_commons)
			emit_as_common = 1;
538
	}
539

540
	be_dbg_variable(env->main_env->db_handle, obst, ent);
541

542
	/* global or not global */
543
	if (visibility == visibility_external_visible && !emit_as_common) {
544
545
546
547
548
		obstack_printf(obst, ".global\t%s\n", ld_name);
	} else if(visibility == visibility_external_allocated) {
		obstack_printf(obst, ".global\t%s\n", ld_name);
		/* we can return now... */
		return;
549
	}
550
	/* alignment */
551
	if (align > 1 && !emit_as_common) {
552
553
554
		obstack_printf(obst, ".balign\t%d\n", align);
	}

555
	if (!emit_as_common) {
556
557
		obstack_printf(obst, "%s:\n", ld_name);
	}
558

559
	if (variability == variability_uninitialized) {
560
561
562
563
564
565
		if(emit_as_common) {
			obstack_printf(obst, "\t.comm %s,%d,%d\n",
					ld_name, get_type_size_bytes(type), align);
		} else {
			obstack_printf(obst, "\t.zero %d\n", get_type_size_bytes(type));
		}
566
	} else if (is_atomic_type(type)) {
567
		dump_atomic_init(obst, get_atomic_ent_value(ent));
568
	} else if (ent_is_string_const(ent)) {
569
		dump_string_cst(obst, ent);
570
	} else if (is_Array_type(type)) {
571
		dump_array_init(obst, ent);
572
	} else if (is_compound_type(type)) {
573
		dump_compound_init(obst, ent);
574
	} else {
575
		assert(0 && "unsupported type");
576
	}
577
578
}

Michael Beck's avatar
Michael Beck committed
579
/**
580
581
 * Dumps declarations of global variables and the initialization code.
 */
582
static void ia32_dump_globals(ir_type *gt, ia32_decl_env_t *env, int emit_commons)
583
{
Michael Beck's avatar
Michael Beck committed
584
	int i, n = get_compound_n_members(gt);
585

586
	for (i = 0; i < n; i++) {
587
		ir_entity *ent = get_compound_member(gt, i);
588
		dump_global(env, ent, emit_commons);
589
	}
590
591
592
593
}

/************************************************************************/

Christian Würdig's avatar
Christian Würdig committed
594
void ia32_gen_decls(FILE *out, const be_main_env_t *main_env) {
Christian Würdig's avatar
Christian Würdig committed
595
	ia32_decl_env_t env;
596
	obstack_t rodata, data, bss, ctor;
597
598
599
	int    size;
	char   *cp;

Michael Beck's avatar
Michael Beck committed
600
	/* dump the global type */
601
602
	obstack_init(&rodata);
	obstack_init(&data);
603
	obstack_init(&bss);
604

Christian Würdig's avatar
Christian Würdig committed
605
	if (main_env->options->opt_profile)
Christian Würdig's avatar
Christian Würdig committed
606
607
608
609
		obstack_init(&ctor);

	env.rodata_obst = &rodata;
	env.data_obst   = &data;
610
	env.bss_obst    = &bss;
Christian Würdig's avatar
Christian Würdig committed
611
612
	env.ctor_obst   = main_env->options->opt_profile ? &ctor : NULL;
	env.main_env    = main_env;
Christian Würdig's avatar
Christian Würdig committed
613

614
	ia32_dump_globals(get_glob_type(), &env, 1);
615
616
617
618

	size = obstack_object_size(&data);
	cp   = obstack_finish(&data);
	if (size > 0) {
Michael Beck's avatar
Michael Beck committed
619
		ia32_switch_section(out, SECTION_DATA);
620
621
622
623
624
625
		fwrite(cp, 1, size, out);
	}

	size = obstack_object_size(&rodata);
	cp   = obstack_finish(&rodata);
	if (size > 0) {
Michael Beck's avatar
Michael Beck committed
626
		ia32_switch_section(out, SECTION_RODATA);
627
628
629
		fwrite(cp, 1, size, out);
	}

630
631
	size = obstack_object_size(&bss);
	cp   = obstack_finish(&bss);
632
	if (size > 0) {
Michael Beck's avatar
Michael Beck committed
633
		ia32_switch_section(out, SECTION_COMMON);
634
635
636
		fwrite(cp, 1, size, out);
	}

Christian Würdig's avatar
Christian Würdig committed
637
	if (main_env->options->opt_profile) {
Christian Würdig's avatar
Christian Würdig committed
638
639
640
641
642
643
644
645
646
		size = obstack_object_size(&ctor);
		cp   = obstack_finish(&ctor);
		if (size > 0) {
			ia32_switch_section(out, SECTION_CTOR);
			fwrite(cp, 1, size, out);
		}
		obstack_free(&ctor, NULL);
	}

647
648
	obstack_free(&rodata, NULL);
	obstack_free(&data, NULL);
649
	obstack_free(&bss, NULL);
Michael Beck's avatar
Michael Beck committed
650
651
652

	/* dump the Thread Local Storage */
	obstack_init(&data);
Christian Würdig's avatar
Christian Würdig committed
653
654
655

	env.rodata_obst = &data;
	env.data_obst   = &data;
656
	env.bss_obst   = &data;
Christian Würdig's avatar
Christian Würdig committed
657
658
	env.ctor_obst   = NULL;

659
	ia32_dump_globals(get_tls_type(), &env, 0);
Michael Beck's avatar
Michael Beck committed
660
661
662
663
664

	size = obstack_object_size(&data);
	cp   = obstack_finish(&data);
	if (size > 0) {
		ia32_switch_section(out, SECTION_TLS);
665
		fprintf(out, ".balign\t%d\n", 32);
Michael Beck's avatar
Michael Beck committed
666
667
668
		fwrite(cp, 1, size, out);
	}

Christian Würdig's avatar
Christian Würdig committed
669
	obstack_free(&data, NULL);
670
}