]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/dwarf2asm.c
c2ca9166f460ca699359d31044fda5ab49b8ec7b
[thirdparty/gcc.git] / gcc / dwarf2asm.c
1 /* Dwarf2 assembler output helper routines.
2 Copyright (C) 2001, 2002 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "flags.h"
27 #include "tree.h"
28 #include "rtl.h"
29 #include "output.h"
30 #include "target.h"
31 #include "dwarf2asm.h"
32 #include "dwarf2.h"
33 #include "splay-tree.h"
34 #include "ggc.h"
35 #include "tm_p.h"
36
37
38 /* How to start an assembler comment. */
39 #ifndef ASM_COMMENT_START
40 #define ASM_COMMENT_START ";#"
41 #endif
42
43 \f
44 /* Output an unaligned integer with the given value and size. Prefer not
45 to print a newline, since the caller may want to add a comment. */
46
47 void
48 dw2_assemble_integer (size, x)
49 int size;
50 rtx x;
51 {
52 const char *op = integer_asm_op (size, FALSE);
53
54 if (op)
55 {
56 fputs (op, asm_out_file);
57 if (GET_CODE (x) == CONST_INT)
58 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
59 else
60 output_addr_const (asm_out_file, x);
61 }
62 else
63 assemble_integer (x, size, BITS_PER_UNIT, 1);
64 }
65
66
67 /* Output an immediate constant in a given size. */
68
69 void
70 dw2_asm_output_data (int size, unsigned HOST_WIDE_INT value,
71 const char *comment, ...)
72 {
73 va_list ap;
74
75 va_start (ap, comment);
76
77 if (size * 8 < HOST_BITS_PER_WIDE_INT)
78 value &= ~(~(unsigned HOST_WIDE_INT) 0 << (size * 8));
79
80 dw2_assemble_integer (size, GEN_INT (value));
81
82 if (flag_debug_asm && comment)
83 {
84 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
85 vfprintf (asm_out_file, comment, ap);
86 }
87 fputc ('\n', asm_out_file);
88
89 va_end (ap);
90 }
91
92 /* Output the difference between two symbols in a given size. */
93 /* ??? There appear to be assemblers that do not like such
94 subtraction, but do support ASM_SET_OP. It's unfortunately
95 impossible to do here, since the ASM_SET_OP for the difference
96 symbol must appear after both symbols are defined. */
97
98 void
99 dw2_asm_output_delta (int size, const char *lab1, const char *lab2,
100 const char *comment, ...)
101 {
102 va_list ap;
103
104 va_start (ap, comment);
105
106 #ifdef ASM_OUTPUT_DWARF_DELTA
107 ASM_OUTPUT_DWARF_DELTA (asm_out_file, size, lab1, lab2);
108 #else
109 dw2_assemble_integer (size,
110 gen_rtx_MINUS (Pmode,
111 gen_rtx_SYMBOL_REF (Pmode, lab1),
112 gen_rtx_SYMBOL_REF (Pmode, lab2)));
113 #endif
114 if (flag_debug_asm && comment)
115 {
116 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
117 vfprintf (asm_out_file, comment, ap);
118 }
119 fputc ('\n', asm_out_file);
120
121 va_end (ap);
122 }
123
124 /* Output a section-relative reference to a label. In general this
125 can only be done for debugging symbols. E.g. on most targets with
126 the GNU linker, this is accomplished with a direct reference and
127 the knowledge that the debugging section will be placed at VMA 0.
128 Some targets have special relocations for this that we must use. */
129
130 void
131 dw2_asm_output_offset (int size, const char *label,
132 const char *comment, ...)
133 {
134 va_list ap;
135
136 va_start (ap, comment);
137
138 #ifdef ASM_OUTPUT_DWARF_OFFSET
139 ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label);
140 #else
141 dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
142 #endif
143
144 if (flag_debug_asm && comment)
145 {
146 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
147 vfprintf (asm_out_file, comment, ap);
148 }
149 fputc ('\n', asm_out_file);
150
151 va_end (ap);
152 }
153
154 /* Output a self-relative reference to a label, possibly in a
155 different section or object file. */
156
157 void
158 dw2_asm_output_pcrel (int size ATTRIBUTE_UNUSED,
159 const char *label ATTRIBUTE_UNUSED,
160 const char *comment, ...)
161 {
162 va_list ap;
163
164 va_start (ap, comment);
165
166 #ifdef ASM_OUTPUT_DWARF_PCREL
167 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label);
168 #else
169 dw2_assemble_integer (size,
170 gen_rtx_MINUS (Pmode,
171 gen_rtx_SYMBOL_REF (Pmode, label),
172 pc_rtx));
173 #endif
174
175 if (flag_debug_asm && comment)
176 {
177 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
178 vfprintf (asm_out_file, comment, ap);
179 }
180 fputc ('\n', asm_out_file);
181
182 va_end (ap);
183 }
184
185 /* Output an absolute reference to a label. */
186
187 void
188 dw2_asm_output_addr (int size, const char *label,
189 const char *comment, ...)
190 {
191 va_list ap;
192
193 va_start (ap, comment);
194
195 dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
196
197 if (flag_debug_asm && comment)
198 {
199 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
200 vfprintf (asm_out_file, comment, ap);
201 }
202 fputc ('\n', asm_out_file);
203
204 va_end (ap);
205 }
206
207 /* Similar, but use an RTX expression instead of a text label. */
208
209 void
210 dw2_asm_output_addr_rtx (int size, rtx addr,
211 const char *comment, ...)
212 {
213 va_list ap;
214
215 va_start (ap, comment);
216
217 dw2_assemble_integer (size, addr);
218
219 if (flag_debug_asm && comment)
220 {
221 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
222 vfprintf (asm_out_file, comment, ap);
223 }
224 fputc ('\n', asm_out_file);
225
226 va_end (ap);
227 }
228
229 void
230 dw2_asm_output_nstring (const char *str, size_t orig_len,
231 const char *comment, ...)
232 {
233 size_t i, len;
234 va_list ap;
235
236 va_start (ap, comment);
237
238 len = orig_len;
239
240 if (len == (size_t) -1)
241 len = strlen (str);
242
243 if (flag_debug_asm && comment)
244 {
245 fputs ("\t.ascii \"", asm_out_file);
246 for (i = 0; i < len; i++)
247 {
248 int c = str[i];
249 if (c == '\"' || c == '\\')
250 fputc ('\\', asm_out_file);
251 if (ISPRINT(c))
252 fputc (c, asm_out_file);
253 else
254 fprintf (asm_out_file, "\\%o", c);
255 }
256 fprintf (asm_out_file, "\\0\"\t%s ", ASM_COMMENT_START);
257 vfprintf (asm_out_file, comment, ap);
258 fputc ('\n', asm_out_file);
259 }
260 else
261 {
262 /* If an explicit length was given, we can't assume there
263 is a null termination in the string buffer. */
264 if (orig_len == (size_t) -1)
265 len += 1;
266 ASM_OUTPUT_ASCII (asm_out_file, str, len);
267 if (orig_len != (size_t) -1)
268 assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1);
269 }
270
271 va_end (ap);
272 }
273 \f
274
275 /* Return the size of an unsigned LEB128 quantity. */
276
277 int
278 size_of_uleb128 (value)
279 unsigned HOST_WIDE_INT value;
280 {
281 int size = 0;
282
283 do
284 {
285 value >>= 7;
286 size += 1;
287 }
288 while (value != 0);
289
290 return size;
291 }
292
293 /* Return the size of a signed LEB128 quantity. */
294
295 int
296 size_of_sleb128 (value)
297 HOST_WIDE_INT value;
298 {
299 int size = 0, byte;
300
301 do
302 {
303 byte = (value & 0x7f);
304 value >>= 7;
305 size += 1;
306 }
307 while (!((value == 0 && (byte & 0x40) == 0)
308 || (value == -1 && (byte & 0x40) != 0)));
309
310 return size;
311 }
312
313 /* Given an encoding, return the number of bytes the format occupies.
314 This is only defined for fixed-size encodings, and so does not
315 include leb128. */
316
317 int
318 size_of_encoded_value (encoding)
319 int encoding;
320 {
321 if (encoding == DW_EH_PE_omit)
322 return 0;
323
324 switch (encoding & 0x07)
325 {
326 case DW_EH_PE_absptr:
327 return POINTER_SIZE / BITS_PER_UNIT;
328 case DW_EH_PE_udata2:
329 return 2;
330 case DW_EH_PE_udata4:
331 return 4;
332 case DW_EH_PE_udata8:
333 return 8;
334 }
335 abort ();
336 }
337
338 /* Yield a name for a given pointer encoding. */
339
340 const char *
341 eh_data_format_name (format)
342 int format;
343 {
344 #if HAVE_DESIGNATED_INITIALIZERS
345 #define S(p, v) [p] = v,
346 #else
347 #define S(p, v) case p: return v;
348 #endif
349
350 #if HAVE_DESIGNATED_INITIALIZERS
351 __extension__ static const char * const format_names[256] = {
352 #else
353 switch (format) {
354 #endif
355
356 S(DW_EH_PE_absptr, "absolute")
357 S(DW_EH_PE_omit, "omit")
358 S(DW_EH_PE_aligned, "aligned absolute")
359
360 S(DW_EH_PE_uleb128, "uleb128")
361 S(DW_EH_PE_udata2, "udata2")
362 S(DW_EH_PE_udata4, "udata4")
363 S(DW_EH_PE_udata8, "udata8")
364 S(DW_EH_PE_sleb128, "sleb128")
365 S(DW_EH_PE_sdata2, "sdata2")
366 S(DW_EH_PE_sdata4, "sdata4")
367 S(DW_EH_PE_sdata8, "sdata8")
368
369 S(DW_EH_PE_absptr | DW_EH_PE_pcrel, "pcrel")
370 S(DW_EH_PE_uleb128 | DW_EH_PE_pcrel, "pcrel uleb128")
371 S(DW_EH_PE_udata2 | DW_EH_PE_pcrel, "pcrel udata2")
372 S(DW_EH_PE_udata4 | DW_EH_PE_pcrel, "pcrel udata4")
373 S(DW_EH_PE_udata8 | DW_EH_PE_pcrel, "pcrel udata8")
374 S(DW_EH_PE_sleb128 | DW_EH_PE_pcrel, "pcrel sleb128")
375 S(DW_EH_PE_sdata2 | DW_EH_PE_pcrel, "pcrel sdata2")
376 S(DW_EH_PE_sdata4 | DW_EH_PE_pcrel, "pcrel sdata4")
377 S(DW_EH_PE_sdata8 | DW_EH_PE_pcrel, "pcrel sdata8")
378
379 S(DW_EH_PE_absptr | DW_EH_PE_textrel, "textrel")
380 S(DW_EH_PE_uleb128 | DW_EH_PE_textrel, "textrel uleb128")
381 S(DW_EH_PE_udata2 | DW_EH_PE_textrel, "textrel udata2")
382 S(DW_EH_PE_udata4 | DW_EH_PE_textrel, "textrel udata4")
383 S(DW_EH_PE_udata8 | DW_EH_PE_textrel, "textrel udata8")
384 S(DW_EH_PE_sleb128 | DW_EH_PE_textrel, "textrel sleb128")
385 S(DW_EH_PE_sdata2 | DW_EH_PE_textrel, "textrel sdata2")
386 S(DW_EH_PE_sdata4 | DW_EH_PE_textrel, "textrel sdata4")
387 S(DW_EH_PE_sdata8 | DW_EH_PE_textrel, "textrel sdata8")
388
389 S(DW_EH_PE_absptr | DW_EH_PE_datarel, "datarel")
390 S(DW_EH_PE_uleb128 | DW_EH_PE_datarel, "datarel uleb128")
391 S(DW_EH_PE_udata2 | DW_EH_PE_datarel, "datarel udata2")
392 S(DW_EH_PE_udata4 | DW_EH_PE_datarel, "datarel udata4")
393 S(DW_EH_PE_udata8 | DW_EH_PE_datarel, "datarel udata8")
394 S(DW_EH_PE_sleb128 | DW_EH_PE_datarel, "datarel sleb128")
395 S(DW_EH_PE_sdata2 | DW_EH_PE_datarel, "datarel sdata2")
396 S(DW_EH_PE_sdata4 | DW_EH_PE_datarel, "datarel sdata4")
397 S(DW_EH_PE_sdata8 | DW_EH_PE_datarel, "datarel sdata8")
398
399 S(DW_EH_PE_absptr | DW_EH_PE_funcrel, "funcrel")
400 S(DW_EH_PE_uleb128 | DW_EH_PE_funcrel, "funcrel uleb128")
401 S(DW_EH_PE_udata2 | DW_EH_PE_funcrel, "funcrel udata2")
402 S(DW_EH_PE_udata4 | DW_EH_PE_funcrel, "funcrel udata4")
403 S(DW_EH_PE_udata8 | DW_EH_PE_funcrel, "funcrel udata8")
404 S(DW_EH_PE_sleb128 | DW_EH_PE_funcrel, "funcrel sleb128")
405 S(DW_EH_PE_sdata2 | DW_EH_PE_funcrel, "funcrel sdata2")
406 S(DW_EH_PE_sdata4 | DW_EH_PE_funcrel, "funcrel sdata4")
407 S(DW_EH_PE_sdata8 | DW_EH_PE_funcrel, "funcrel sdata8")
408
409 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel,
410 "indirect pcrel")
411 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel,
412 "indirect pcrel uleb128")
413 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_pcrel,
414 "indirect pcrel udata2")
415 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_pcrel,
416 "indirect pcrel udata4")
417 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_pcrel,
418 "indirect pcrel udata8")
419 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_pcrel,
420 "indirect pcrel sleb128")
421 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_pcrel,
422 "indirect pcrel sdata2")
423 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_pcrel,
424 "indirect pcrel sdata4")
425 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_pcrel,
426 "indirect pcrel sdata8")
427
428 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_textrel,
429 "indirect textrel")
430 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_textrel,
431 "indirect textrel uleb128")
432 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_textrel,
433 "indirect textrel udata2")
434 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_textrel,
435 "indirect textrel udata4")
436 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_textrel,
437 "indirect textrel udata8")
438 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_textrel,
439 "indirect textrel sleb128")
440 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_textrel,
441 "indirect textrel sdata2")
442 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_textrel,
443 "indirect textrel sdata4")
444 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_textrel,
445 "indirect textrel sdata8")
446
447 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_datarel,
448 "indirect datarel")
449 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_datarel,
450 "indirect datarel uleb128")
451 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_datarel,
452 "indirect datarel udata2")
453 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_datarel,
454 "indirect datarel udata4")
455 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_datarel,
456 "indirect datarel udata8")
457 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_datarel,
458 "indirect datarel sleb128")
459 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_datarel,
460 "indirect datarel sdata2")
461 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_datarel,
462 "indirect datarel sdata4")
463 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_datarel,
464 "indirect datarel sdata8")
465
466 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_funcrel,
467 "indirect funcrel")
468 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_funcrel,
469 "indirect funcrel uleb128")
470 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_funcrel,
471 "indirect funcrel udata2")
472 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_funcrel,
473 "indirect funcrel udata4")
474 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_funcrel,
475 "indirect funcrel udata8")
476 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_funcrel,
477 "indirect funcrel sleb128")
478 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_funcrel,
479 "indirect funcrel sdata2")
480 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_funcrel,
481 "indirect funcrel sdata4")
482 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_funcrel,
483 "indirect funcrel sdata8")
484
485 #if HAVE_DESIGNATED_INITIALIZERS
486 };
487
488 if (format < 0 || format > 0xff || format_names[format] == NULL)
489 abort ();
490 return format_names[format];
491 #else
492 }
493 abort ();
494 #endif
495 }
496
497 /* Output an unsigned LEB128 quantity. */
498
499 void
500 dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value,
501 const char *comment, ...)
502 {
503 va_list ap;
504
505 va_start (ap, comment);
506
507 #ifdef HAVE_AS_LEB128
508 fprintf (asm_out_file, "\t.uleb128 " HOST_WIDE_INT_PRINT_HEX , value);
509
510 if (flag_debug_asm && comment)
511 {
512 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
513 vfprintf (asm_out_file, comment, ap);
514 }
515 #else
516 {
517 unsigned HOST_WIDE_INT work = value;
518 const char *byte_op = targetm.asm_out.byte_op;
519
520 if (byte_op)
521 fputs (byte_op, asm_out_file);
522 do
523 {
524 int byte = (work & 0x7f);
525 work >>= 7;
526 if (work != 0)
527 /* More bytes to follow. */
528 byte |= 0x80;
529
530 if (byte_op)
531 {
532 fprintf (asm_out_file, "0x%x", byte);
533 if (work != 0)
534 fputc (',', asm_out_file);
535 }
536 else
537 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
538 }
539 while (work != 0);
540
541 if (flag_debug_asm)
542 {
543 fprintf (asm_out_file, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX,
544 ASM_COMMENT_START, value);
545 if (comment)
546 {
547 fputs ("; ", asm_out_file);
548 vfprintf (asm_out_file, comment, ap);
549 }
550 }
551 }
552 #endif
553 fputc ('\n', asm_out_file);
554
555 va_end (ap);
556 }
557
558 /* Output a signed LEB128 quantity. */
559
560 void
561 dw2_asm_output_data_sleb128 (HOST_WIDE_INT value,
562 const char *comment, ...)
563 {
564 va_list ap;
565
566 va_start (ap, comment);
567
568 #ifdef HAVE_AS_LEB128
569 fprintf (asm_out_file, "\t.sleb128 " HOST_WIDE_INT_PRINT_DEC, value);
570
571 if (flag_debug_asm && comment)
572 {
573 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
574 vfprintf (asm_out_file, comment, ap);
575 }
576 #else
577 {
578 HOST_WIDE_INT work = value;
579 int more, byte;
580 const char *byte_op = targetm.asm_out.byte_op;
581
582 if (byte_op)
583 fputs (byte_op, asm_out_file);
584 do
585 {
586 byte = (work & 0x7f);
587 /* arithmetic shift */
588 work >>= 7;
589 more = !((work == 0 && (byte & 0x40) == 0)
590 || (work == -1 && (byte & 0x40) != 0));
591 if (more)
592 byte |= 0x80;
593
594 if (byte_op)
595 {
596 fprintf (asm_out_file, "0x%x", byte);
597 if (more)
598 fputc (',', asm_out_file);
599 }
600 else
601 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
602 }
603 while (more);
604
605 if (flag_debug_asm)
606 {
607 fprintf (asm_out_file, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC,
608 ASM_COMMENT_START, value);
609 if (comment)
610 {
611 fputs ("; ", asm_out_file);
612 vfprintf (asm_out_file, comment, ap);
613 }
614 }
615 }
616 #endif
617 fputc ('\n', asm_out_file);
618
619 va_end (ap);
620 }
621
622 void
623 dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
624 const char *lab2 ATTRIBUTE_UNUSED,
625 const char *comment, ...)
626 {
627 va_list ap;
628
629 va_start (ap, comment);
630
631 #ifdef HAVE_AS_LEB128
632 fputs ("\t.uleb128 ", asm_out_file);
633 assemble_name (asm_out_file, lab1);
634 fputc ('-', asm_out_file);
635 assemble_name (asm_out_file, lab2);
636 #else
637 abort ();
638 #endif
639
640 if (flag_debug_asm && comment)
641 {
642 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
643 vfprintf (asm_out_file, comment, ap);
644 }
645 fputc ('\n', asm_out_file);
646
647 va_end (ap);
648 }
649
650 void
651 dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED,
652 const char *lab2 ATTRIBUTE_UNUSED,
653 const char *comment, ...)
654 {
655 va_list ap;
656
657 va_start (ap, comment);
658
659 #ifdef HAVE_AS_LEB128
660 fputs ("\t.sleb128 ", asm_out_file);
661 assemble_name (asm_out_file, lab1);
662 fputc ('-', asm_out_file);
663 assemble_name (asm_out_file, lab2);
664 #else
665 abort ();
666 #endif
667
668 if (flag_debug_asm && comment)
669 {
670 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
671 vfprintf (asm_out_file, comment, ap);
672 }
673 fputc ('\n', asm_out_file);
674
675 va_end (ap);
676 }
677 \f
678 static rtx dw2_force_const_mem PARAMS ((rtx));
679 static int dw2_output_indirect_constant_1 PARAMS ((splay_tree_node, void *));
680
681 static GTY((param1_is (char *), param2_is (tree))) splay_tree indirect_pool;
682
683 static GTY(()) int dw2_const_labelno;
684
685 #if defined(HAVE_GAS_HIDDEN) && defined(SUPPORTS_ONE_ONLY)
686 # define USE_LINKONCE_INDIRECT 1
687 #else
688 # define USE_LINKONCE_INDIRECT 0
689 #endif
690
691 /* Put X, a SYMBOL_REF, in memory. Return a SYMBOL_REF to the allocated
692 memory. Differs from force_const_mem in that a single pool is used for
693 the entire unit of translation, and the memory is not guaranteed to be
694 "near" the function in any interesting sense. */
695
696 static rtx
697 dw2_force_const_mem (x)
698 rtx x;
699 {
700 splay_tree_node node;
701 const char *str;
702 tree decl;
703
704 if (! indirect_pool)
705 indirect_pool = splay_tree_new_ggc (splay_tree_compare_pointers);
706
707 if (GET_CODE (x) != SYMBOL_REF)
708 abort ();
709
710 str = (* targetm.strip_name_encoding) (XSTR (x, 0));
711 node = splay_tree_lookup (indirect_pool, (splay_tree_key) str);
712 if (node)
713 decl = (tree) node->value;
714 else
715 {
716 tree id;
717
718 if (USE_LINKONCE_INDIRECT)
719 {
720 char *ref_name = alloca (strlen (str) + sizeof "DW.ref.");
721
722 sprintf (ref_name, "DW.ref.%s", str);
723 id = get_identifier (ref_name);
724 decl = build_decl (VAR_DECL, id, ptr_type_node);
725 DECL_ARTIFICIAL (decl) = 1;
726 TREE_PUBLIC (decl) = 1;
727 DECL_INITIAL (decl) = decl;
728 make_decl_one_only (decl);
729 }
730 else
731 {
732 char label[32];
733
734 ASM_GENERATE_INTERNAL_LABEL (label, "LDFCM", dw2_const_labelno);
735 ++dw2_const_labelno;
736 id = get_identifier (label);
737 decl = build_decl (VAR_DECL, id, ptr_type_node);
738 DECL_ARTIFICIAL (decl) = 1;
739 TREE_STATIC (decl) = 1;
740 DECL_INITIAL (decl) = decl;
741 }
742
743 id = maybe_get_identifier (str);
744 if (id)
745 TREE_SYMBOL_REFERENCED (id) = 1;
746
747 splay_tree_insert (indirect_pool, (splay_tree_key) str,
748 (splay_tree_value) decl);
749 }
750
751 return XEXP (DECL_RTL (decl), 0);
752 }
753
754 /* A helper function for dw2_output_indirect_constants called through
755 splay_tree_foreach. Emit one queued constant to memory. */
756
757 static int
758 dw2_output_indirect_constant_1 (node, data)
759 splay_tree_node node;
760 void* data ATTRIBUTE_UNUSED;
761 {
762 const char *sym;
763 rtx sym_ref;
764
765 sym = (const char *) node->key;
766 sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
767 if (USE_LINKONCE_INDIRECT)
768 fprintf (asm_out_file, "\t.hidden DW.ref.%s\n", sym);
769 assemble_variable ((tree) node->value, 1, 1, 1);
770 assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
771
772 return 0;
773 }
774
775 /* Emit the constants queued through dw2_force_const_mem. */
776
777 void
778 dw2_output_indirect_constants ()
779 {
780 if (indirect_pool)
781 splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL);
782 }
783
784 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed. */
785
786 void
787 dw2_asm_output_encoded_addr_rtx (int encoding, rtx addr,
788 const char *comment, ...)
789 {
790 int size;
791 va_list ap;
792
793 va_start (ap, comment);
794
795 size = size_of_encoded_value (encoding);
796
797 if (encoding == DW_EH_PE_aligned)
798 {
799 assemble_align (POINTER_SIZE);
800 assemble_integer (addr, size, POINTER_SIZE, 1);
801 return;
802 }
803
804 /* NULL is _always_ represented as a plain zero, as is 1 for Ada's
805 "all others". */
806 if (addr == const0_rtx || addr == const1_rtx)
807 assemble_integer (addr, size, BITS_PER_UNIT, 1);
808 else
809 {
810 restart:
811 /* Allow the target first crack at emitting this. Some of the
812 special relocations require special directives instead of
813 just ".4byte" or whatever. */
814 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
815 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
816 addr, done);
817 #endif
818
819 /* Indirection is used to get dynamic relocations out of a
820 read-only section. */
821 if (encoding & DW_EH_PE_indirect)
822 {
823 /* It is very tempting to use force_const_mem so that we share data
824 with the normal constant pool. However, we've already emitted
825 the constant pool for this function. Moreover, we'd like to
826 share these constants across the entire unit of translation,
827 or better, across the entire application (or DSO). */
828 addr = dw2_force_const_mem (addr);
829 encoding &= ~DW_EH_PE_indirect;
830 goto restart;
831 }
832
833 switch (encoding & 0xF0)
834 {
835 case DW_EH_PE_absptr:
836 dw2_assemble_integer (size, addr);
837 break;
838
839 case DW_EH_PE_pcrel:
840 if (GET_CODE (addr) != SYMBOL_REF)
841 abort ();
842 #ifdef ASM_OUTPUT_DWARF_PCREL
843 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
844 #else
845 dw2_assemble_integer (size, gen_rtx_MINUS (Pmode, addr, pc_rtx));
846 #endif
847 break;
848
849 default:
850 /* Other encodings should have been handled by
851 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
852 abort ();
853 }
854
855 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
856 done:;
857 #endif
858 }
859
860 if (flag_debug_asm && comment)
861 {
862 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
863 vfprintf (asm_out_file, comment, ap);
864 }
865 fputc ('\n', asm_out_file);
866
867 va_end (ap);
868 }
869
870 #include "gt-dwarf2asm.h"