2003-06-19 Aldy Hernandez <aldyh@redhat.com>
[official-gcc.git] / gcc / dwarf2asm.c
blobc2ca9166f460ca699359d31044fda5ab49b8ec7b
1 /* Dwarf2 assembler output helper routines.
2 Copyright (C) 2001, 2002 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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. */
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"
38 /* How to start an assembler comment. */
39 #ifndef ASM_COMMENT_START
40 #define ASM_COMMENT_START ";#"
41 #endif
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. */
47 void
48 dw2_assemble_integer (size, x)
49 int size;
50 rtx x;
52 const char *op = integer_asm_op (size, FALSE);
54 if (op)
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);
62 else
63 assemble_integer (x, size, BITS_PER_UNIT, 1);
67 /* Output an immediate constant in a given size. */
69 void
70 dw2_asm_output_data (int size, unsigned HOST_WIDE_INT value,
71 const char *comment, ...)
73 va_list ap;
75 va_start (ap, comment);
77 if (size * 8 < HOST_BITS_PER_WIDE_INT)
78 value &= ~(~(unsigned HOST_WIDE_INT) 0 << (size * 8));
80 dw2_assemble_integer (size, GEN_INT (value));
82 if (flag_debug_asm && comment)
84 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
85 vfprintf (asm_out_file, comment, ap);
87 fputc ('\n', asm_out_file);
89 va_end (ap);
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. */
98 void
99 dw2_asm_output_delta (int size, const char *lab1, const char *lab2,
100 const char *comment, ...)
102 va_list ap;
104 va_start (ap, comment);
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)
116 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
117 vfprintf (asm_out_file, comment, ap);
119 fputc ('\n', asm_out_file);
121 va_end (ap);
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. */
130 void
131 dw2_asm_output_offset (int size, const char *label,
132 const char *comment, ...)
134 va_list ap;
136 va_start (ap, comment);
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
144 if (flag_debug_asm && comment)
146 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
147 vfprintf (asm_out_file, comment, ap);
149 fputc ('\n', asm_out_file);
151 va_end (ap);
154 /* Output a self-relative reference to a label, possibly in a
155 different section or object file. */
157 void
158 dw2_asm_output_pcrel (int size ATTRIBUTE_UNUSED,
159 const char *label ATTRIBUTE_UNUSED,
160 const char *comment, ...)
162 va_list ap;
164 va_start (ap, comment);
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
175 if (flag_debug_asm && comment)
177 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
178 vfprintf (asm_out_file, comment, ap);
180 fputc ('\n', asm_out_file);
182 va_end (ap);
185 /* Output an absolute reference to a label. */
187 void
188 dw2_asm_output_addr (int size, const char *label,
189 const char *comment, ...)
191 va_list ap;
193 va_start (ap, comment);
195 dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
197 if (flag_debug_asm && comment)
199 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
200 vfprintf (asm_out_file, comment, ap);
202 fputc ('\n', asm_out_file);
204 va_end (ap);
207 /* Similar, but use an RTX expression instead of a text label. */
209 void
210 dw2_asm_output_addr_rtx (int size, rtx addr,
211 const char *comment, ...)
213 va_list ap;
215 va_start (ap, comment);
217 dw2_assemble_integer (size, addr);
219 if (flag_debug_asm && comment)
221 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
222 vfprintf (asm_out_file, comment, ap);
224 fputc ('\n', asm_out_file);
226 va_end (ap);
229 void
230 dw2_asm_output_nstring (const char *str, size_t orig_len,
231 const char *comment, ...)
233 size_t i, len;
234 va_list ap;
236 va_start (ap, comment);
238 len = orig_len;
240 if (len == (size_t) -1)
241 len = strlen (str);
243 if (flag_debug_asm && comment)
245 fputs ("\t.ascii \"", asm_out_file);
246 for (i = 0; i < len; i++)
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);
256 fprintf (asm_out_file, "\\0\"\t%s ", ASM_COMMENT_START);
257 vfprintf (asm_out_file, comment, ap);
258 fputc ('\n', asm_out_file);
260 else
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);
271 va_end (ap);
275 /* Return the size of an unsigned LEB128 quantity. */
278 size_of_uleb128 (value)
279 unsigned HOST_WIDE_INT value;
281 int size = 0;
285 value >>= 7;
286 size += 1;
288 while (value != 0);
290 return size;
293 /* Return the size of a signed LEB128 quantity. */
296 size_of_sleb128 (value)
297 HOST_WIDE_INT value;
299 int size = 0, byte;
303 byte = (value & 0x7f);
304 value >>= 7;
305 size += 1;
307 while (!((value == 0 && (byte & 0x40) == 0)
308 || (value == -1 && (byte & 0x40) != 0)));
310 return size;
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. */
318 size_of_encoded_value (encoding)
319 int encoding;
321 if (encoding == DW_EH_PE_omit)
322 return 0;
324 switch (encoding & 0x07)
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;
335 abort ();
338 /* Yield a name for a given pointer encoding. */
340 const char *
341 eh_data_format_name (format)
342 int format;
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
350 #if HAVE_DESIGNATED_INITIALIZERS
351 __extension__ static const char * const format_names[256] = {
352 #else
353 switch (format) {
354 #endif
356 S(DW_EH_PE_absptr, "absolute")
357 S(DW_EH_PE_omit, "omit")
358 S(DW_EH_PE_aligned, "aligned absolute")
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")
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")
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")
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")
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")
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")
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")
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")
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")
485 #if HAVE_DESIGNATED_INITIALIZERS
488 if (format < 0 || format > 0xff || format_names[format] == NULL)
489 abort ();
490 return format_names[format];
491 #else
493 abort ();
494 #endif
497 /* Output an unsigned LEB128 quantity. */
499 void
500 dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value,
501 const char *comment, ...)
503 va_list ap;
505 va_start (ap, comment);
507 #ifdef HAVE_AS_LEB128
508 fprintf (asm_out_file, "\t.uleb128 " HOST_WIDE_INT_PRINT_HEX , value);
510 if (flag_debug_asm && comment)
512 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
513 vfprintf (asm_out_file, comment, ap);
515 #else
517 unsigned HOST_WIDE_INT work = value;
518 const char *byte_op = targetm.asm_out.byte_op;
520 if (byte_op)
521 fputs (byte_op, asm_out_file);
524 int byte = (work & 0x7f);
525 work >>= 7;
526 if (work != 0)
527 /* More bytes to follow. */
528 byte |= 0x80;
530 if (byte_op)
532 fprintf (asm_out_file, "0x%x", byte);
533 if (work != 0)
534 fputc (',', asm_out_file);
536 else
537 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
539 while (work != 0);
541 if (flag_debug_asm)
543 fprintf (asm_out_file, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX,
544 ASM_COMMENT_START, value);
545 if (comment)
547 fputs ("; ", asm_out_file);
548 vfprintf (asm_out_file, comment, ap);
552 #endif
553 fputc ('\n', asm_out_file);
555 va_end (ap);
558 /* Output a signed LEB128 quantity. */
560 void
561 dw2_asm_output_data_sleb128 (HOST_WIDE_INT value,
562 const char *comment, ...)
564 va_list ap;
566 va_start (ap, comment);
568 #ifdef HAVE_AS_LEB128
569 fprintf (asm_out_file, "\t.sleb128 " HOST_WIDE_INT_PRINT_DEC, value);
571 if (flag_debug_asm && comment)
573 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
574 vfprintf (asm_out_file, comment, ap);
576 #else
578 HOST_WIDE_INT work = value;
579 int more, byte;
580 const char *byte_op = targetm.asm_out.byte_op;
582 if (byte_op)
583 fputs (byte_op, asm_out_file);
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;
594 if (byte_op)
596 fprintf (asm_out_file, "0x%x", byte);
597 if (more)
598 fputc (',', asm_out_file);
600 else
601 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
603 while (more);
605 if (flag_debug_asm)
607 fprintf (asm_out_file, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC,
608 ASM_COMMENT_START, value);
609 if (comment)
611 fputs ("; ", asm_out_file);
612 vfprintf (asm_out_file, comment, ap);
616 #endif
617 fputc ('\n', asm_out_file);
619 va_end (ap);
622 void
623 dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
624 const char *lab2 ATTRIBUTE_UNUSED,
625 const char *comment, ...)
627 va_list ap;
629 va_start (ap, comment);
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
640 if (flag_debug_asm && comment)
642 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
643 vfprintf (asm_out_file, comment, ap);
645 fputc ('\n', asm_out_file);
647 va_end (ap);
650 void
651 dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED,
652 const char *lab2 ATTRIBUTE_UNUSED,
653 const char *comment, ...)
655 va_list ap;
657 va_start (ap, comment);
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
668 if (flag_debug_asm && comment)
670 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
671 vfprintf (asm_out_file, comment, ap);
673 fputc ('\n', asm_out_file);
675 va_end (ap);
678 static rtx dw2_force_const_mem PARAMS ((rtx));
679 static int dw2_output_indirect_constant_1 PARAMS ((splay_tree_node, void *));
681 static GTY((param1_is (char *), param2_is (tree))) splay_tree indirect_pool;
683 static GTY(()) int dw2_const_labelno;
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
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. */
696 static rtx
697 dw2_force_const_mem (x)
698 rtx x;
700 splay_tree_node node;
701 const char *str;
702 tree decl;
704 if (! indirect_pool)
705 indirect_pool = splay_tree_new_ggc (splay_tree_compare_pointers);
707 if (GET_CODE (x) != SYMBOL_REF)
708 abort ();
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
716 tree id;
718 if (USE_LINKONCE_INDIRECT)
720 char *ref_name = alloca (strlen (str) + sizeof "DW.ref.");
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);
730 else
732 char label[32];
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;
743 id = maybe_get_identifier (str);
744 if (id)
745 TREE_SYMBOL_REFERENCED (id) = 1;
747 splay_tree_insert (indirect_pool, (splay_tree_key) str,
748 (splay_tree_value) decl);
751 return XEXP (DECL_RTL (decl), 0);
754 /* A helper function for dw2_output_indirect_constants called through
755 splay_tree_foreach. Emit one queued constant to memory. */
757 static int
758 dw2_output_indirect_constant_1 (node, data)
759 splay_tree_node node;
760 void* data ATTRIBUTE_UNUSED;
762 const char *sym;
763 rtx sym_ref;
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);
772 return 0;
775 /* Emit the constants queued through dw2_force_const_mem. */
777 void
778 dw2_output_indirect_constants ()
780 if (indirect_pool)
781 splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL);
784 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed. */
786 void
787 dw2_asm_output_encoded_addr_rtx (int encoding, rtx addr,
788 const char *comment, ...)
790 int size;
791 va_list ap;
793 va_start (ap, comment);
795 size = size_of_encoded_value (encoding);
797 if (encoding == DW_EH_PE_aligned)
799 assemble_align (POINTER_SIZE);
800 assemble_integer (addr, size, POINTER_SIZE, 1);
801 return;
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
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
819 /* Indirection is used to get dynamic relocations out of a
820 read-only section. */
821 if (encoding & DW_EH_PE_indirect)
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;
833 switch (encoding & 0xF0)
835 case DW_EH_PE_absptr:
836 dw2_assemble_integer (size, addr);
837 break;
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;
849 default:
850 /* Other encodings should have been handled by
851 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
852 abort ();
855 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
856 done:;
857 #endif
860 if (flag_debug_asm && comment)
862 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
863 vfprintf (asm_out_file, comment, ap);
865 fputc ('\n', asm_out_file);
867 va_end (ap);
870 #include "gt-dwarf2asm.h"