1 /* Dwarf2 assembler output helper routines.
2 Copyright (C) 2001-2016 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 3, or (at your option) any later
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
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
28 #include "stringpool.h"
31 #include "dwarf2asm.h"
36 #ifndef XCOFF_DEBUGGING_INFO
37 #define XCOFF_DEBUGGING_INFO 0
41 /* Output an unaligned integer with the given value and size. Prefer not
42 to print a newline, since the caller may want to add a comment. */
45 dw2_assemble_integer (int size
, rtx x
)
47 const char *op
= integer_asm_op (size
, FALSE
);
51 fputs (op
, asm_out_file
);
53 fprint_whex (asm_out_file
, (unsigned HOST_WIDE_INT
) INTVAL (x
));
55 output_addr_const (asm_out_file
, x
);
58 assemble_integer (x
, size
, BITS_PER_UNIT
, 1);
62 /* Output a value of a given size in target byte order. */
65 dw2_asm_output_data_raw (int size
, unsigned HOST_WIDE_INT value
)
67 unsigned char bytes
[8];
70 for (i
= 0; i
< 8; ++i
)
72 bytes
[i
] = value
& 0xff;
78 for (i
= size
- 1; i
> 0; --i
)
79 fprintf (asm_out_file
, "%#x,", bytes
[i
]);
80 fprintf (asm_out_file
, "%#x", bytes
[0]);
84 for (i
= 0; i
< size
- 1; ++i
)
85 fprintf (asm_out_file
, "%#x,", bytes
[i
]);
86 fprintf (asm_out_file
, "%#x", bytes
[i
]);
90 /* Output an immediate constant in a given SIZE in bytes. */
93 dw2_asm_output_data (int size
, unsigned HOST_WIDE_INT value
,
94 const char *comment
, ...)
97 const char *op
= integer_asm_op (size
, FALSE
);
99 va_start (ap
, comment
);
101 if (size
* 8 < HOST_BITS_PER_WIDE_INT
)
102 value
&= ~(HOST_WIDE_INT_M1U
<< (size
* 8));
106 fputs (op
, asm_out_file
);
107 fprint_whex (asm_out_file
, value
);
110 assemble_integer (GEN_INT (value
), size
, BITS_PER_UNIT
, 1);
112 if (flag_debug_asm
&& comment
)
114 fputs ("\t" ASM_COMMENT_START
" ", asm_out_file
);
115 vfprintf (asm_out_file
, comment
, ap
);
117 putc ('\n', asm_out_file
);
122 /* Output the difference between two symbols in a given size. */
123 /* ??? There appear to be assemblers that do not like such
124 subtraction, but do support ASM_SET_OP. It's unfortunately
125 impossible to do here, since the ASM_SET_OP for the difference
126 symbol must appear after both symbols are defined. */
129 dw2_asm_output_delta (int size
, const char *lab1
, const char *lab2
,
130 const char *comment
, ...)
134 va_start (ap
, comment
);
136 #ifdef ASM_OUTPUT_DWARF_DELTA
137 ASM_OUTPUT_DWARF_DELTA (asm_out_file
, size
, lab1
, lab2
);
139 dw2_assemble_integer (size
,
140 gen_rtx_MINUS (Pmode
,
141 gen_rtx_SYMBOL_REF (Pmode
, lab1
),
142 gen_rtx_SYMBOL_REF (Pmode
, lab2
)));
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
);
154 #ifdef ASM_OUTPUT_DWARF_VMS_DELTA
155 /* Output the difference between two symbols in instruction units
159 dw2_asm_output_vms_delta (int size ATTRIBUTE_UNUSED
,
160 const char *lab1
, const char *lab2
,
161 const char *comment
, ...)
165 va_start (ap
, comment
);
167 ASM_OUTPUT_DWARF_VMS_DELTA (asm_out_file
, size
, lab1
, lab2
);
168 if (flag_debug_asm
&& comment
)
170 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
171 vfprintf (asm_out_file
, comment
, ap
);
173 fputc ('\n', asm_out_file
);
179 /* Output a section-relative reference to a LABEL, which was placed in
180 BASE. In general this can only be done for debugging symbols.
181 E.g. on most targets with the GNU linker, this is accomplished with
182 a direct reference and the knowledge that the debugging section
183 will be placed at VMA 0. Some targets have special relocations for
184 this that we must use. */
187 dw2_asm_output_offset (int size
, const char *label
,
188 section
*base ATTRIBUTE_UNUSED
,
189 const char *comment
, ...)
193 va_start (ap
, comment
);
195 #ifdef ASM_OUTPUT_DWARF_OFFSET
196 ASM_OUTPUT_DWARF_OFFSET (asm_out_file
, size
, label
, 0, base
);
198 dw2_assemble_integer (size
, gen_rtx_SYMBOL_REF (Pmode
, label
));
201 if (flag_debug_asm
&& comment
)
203 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
204 vfprintf (asm_out_file
, comment
, ap
);
206 fputc ('\n', asm_out_file
);
212 dw2_asm_output_offset (int size
, const char *label
, HOST_WIDE_INT offset
,
213 section
*base ATTRIBUTE_UNUSED
,
214 const char *comment
, ...)
218 va_start (ap
, comment
);
220 #ifdef ASM_OUTPUT_DWARF_OFFSET
221 ASM_OUTPUT_DWARF_OFFSET (asm_out_file
, size
, label
, offset
, base
);
223 dw2_assemble_integer (size
, gen_rtx_PLUS (Pmode
,
224 gen_rtx_SYMBOL_REF (Pmode
, label
),
225 gen_int_mode (offset
, Pmode
)));
228 if (flag_debug_asm
&& comment
)
230 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
231 vfprintf (asm_out_file
, comment
, ap
);
233 fputc ('\n', asm_out_file
);
240 /* Output a self-relative reference to a label, possibly in a
241 different section or object file. */
244 dw2_asm_output_pcrel (int size ATTRIBUTE_UNUSED
,
245 const char *label ATTRIBUTE_UNUSED
,
246 const char *comment
, ...)
250 va_start (ap
, comment
);
252 #ifdef ASM_OUTPUT_DWARF_PCREL
253 ASM_OUTPUT_DWARF_PCREL (asm_out_file
, size
, label
);
255 dw2_assemble_integer (size
,
256 gen_rtx_MINUS (Pmode
,
257 gen_rtx_SYMBOL_REF (Pmode
, label
),
261 if (flag_debug_asm
&& comment
)
263 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
264 vfprintf (asm_out_file
, comment
, ap
);
266 fputc ('\n', asm_out_file
);
272 /* Output an absolute reference to a label. */
275 dw2_asm_output_addr (int size
, const char *label
,
276 const char *comment
, ...)
280 va_start (ap
, comment
);
282 dw2_assemble_integer (size
, gen_rtx_SYMBOL_REF (Pmode
, label
));
284 if (flag_debug_asm
&& comment
)
286 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
287 vfprintf (asm_out_file
, comment
, ap
);
289 fputc ('\n', asm_out_file
);
294 /* Similar, but use an RTX expression instead of a text label. */
297 dw2_asm_output_addr_rtx (int size
, rtx addr
,
298 const char *comment
, ...)
302 va_start (ap
, comment
);
304 dw2_assemble_integer (size
, addr
);
306 if (flag_debug_asm
&& comment
)
308 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
309 vfprintf (asm_out_file
, comment
, ap
);
311 fputc ('\n', asm_out_file
);
316 /* Output the first ORIG_LEN characters of STR as a string.
317 If ORIG_LEN is equal to -1, ignore this parameter and output
318 the entire STR instead.
319 If COMMENT is not NULL and comments in the debug information
320 have been requested by the user, append the given COMMENT
321 to the generated output. */
324 dw2_asm_output_nstring (const char *str
, size_t orig_len
,
325 const char *comment
, ...)
330 va_start (ap
, comment
);
334 if (len
== (size_t) -1)
337 if (flag_debug_asm
&& comment
)
339 if (XCOFF_DEBUGGING_INFO
)
340 fputs ("\t.byte \"", asm_out_file
);
342 fputs ("\t.ascii \"", asm_out_file
);
344 for (i
= 0; i
< len
; i
++)
347 if (c
== '\"' || c
== '\\')
348 fputc ('\\', asm_out_file
);
350 fputc (c
, asm_out_file
);
352 fprintf (asm_out_file
, "\\%o", c
);
354 fprintf (asm_out_file
, "\\0\"\t%s ", ASM_COMMENT_START
);
355 vfprintf (asm_out_file
, comment
, ap
);
356 fputc ('\n', asm_out_file
);
360 /* If an explicit length was given, we can't assume there
361 is a null termination in the string buffer. */
362 if (orig_len
== (size_t) -1)
364 ASM_OUTPUT_ASCII (asm_out_file
, str
, len
);
365 if (orig_len
!= (size_t) -1)
366 assemble_integer (const0_rtx
, 1, BITS_PER_UNIT
, 1);
373 /* Return the size of an unsigned LEB128 quantity. */
376 size_of_uleb128 (unsigned HOST_WIDE_INT value
)
390 /* Return the size of a signed LEB128 quantity. */
393 size_of_sleb128 (HOST_WIDE_INT value
)
399 byte
= (value
& 0x7f);
403 while (!((value
== 0 && (byte
& 0x40) == 0)
404 || (value
== -1 && (byte
& 0x40) != 0)));
409 /* Given an encoding, return the number of bytes the format occupies.
410 This is only defined for fixed-size encodings, and so does not
414 size_of_encoded_value (int encoding
)
416 if (encoding
== DW_EH_PE_omit
)
419 switch (encoding
& 0x07)
421 case DW_EH_PE_absptr
:
422 return POINTER_SIZE_UNITS
;
423 case DW_EH_PE_udata2
:
425 case DW_EH_PE_udata4
:
427 case DW_EH_PE_udata8
:
434 /* Yield a name for a given pointer encoding. */
437 eh_data_format_name (int format
)
439 #if HAVE_DESIGNATED_INITIALIZERS
440 #define S(p, v) [p] = v,
442 #define S(p, v) case p: return v;
445 #if HAVE_DESIGNATED_INITIALIZERS
446 __extension__
static const char * const format_names
[256] = {
451 S(DW_EH_PE_absptr
, "absolute")
452 S(DW_EH_PE_omit
, "omit")
453 S(DW_EH_PE_aligned
, "aligned absolute")
455 S(DW_EH_PE_uleb128
, "uleb128")
456 S(DW_EH_PE_udata2
, "udata2")
457 S(DW_EH_PE_udata4
, "udata4")
458 S(DW_EH_PE_udata8
, "udata8")
459 S(DW_EH_PE_sleb128
, "sleb128")
460 S(DW_EH_PE_sdata2
, "sdata2")
461 S(DW_EH_PE_sdata4
, "sdata4")
462 S(DW_EH_PE_sdata8
, "sdata8")
464 S(DW_EH_PE_absptr
| DW_EH_PE_pcrel
, "pcrel")
465 S(DW_EH_PE_uleb128
| DW_EH_PE_pcrel
, "pcrel uleb128")
466 S(DW_EH_PE_udata2
| DW_EH_PE_pcrel
, "pcrel udata2")
467 S(DW_EH_PE_udata4
| DW_EH_PE_pcrel
, "pcrel udata4")
468 S(DW_EH_PE_udata8
| DW_EH_PE_pcrel
, "pcrel udata8")
469 S(DW_EH_PE_sleb128
| DW_EH_PE_pcrel
, "pcrel sleb128")
470 S(DW_EH_PE_sdata2
| DW_EH_PE_pcrel
, "pcrel sdata2")
471 S(DW_EH_PE_sdata4
| DW_EH_PE_pcrel
, "pcrel sdata4")
472 S(DW_EH_PE_sdata8
| DW_EH_PE_pcrel
, "pcrel sdata8")
474 S(DW_EH_PE_absptr
| DW_EH_PE_textrel
, "textrel")
475 S(DW_EH_PE_uleb128
| DW_EH_PE_textrel
, "textrel uleb128")
476 S(DW_EH_PE_udata2
| DW_EH_PE_textrel
, "textrel udata2")
477 S(DW_EH_PE_udata4
| DW_EH_PE_textrel
, "textrel udata4")
478 S(DW_EH_PE_udata8
| DW_EH_PE_textrel
, "textrel udata8")
479 S(DW_EH_PE_sleb128
| DW_EH_PE_textrel
, "textrel sleb128")
480 S(DW_EH_PE_sdata2
| DW_EH_PE_textrel
, "textrel sdata2")
481 S(DW_EH_PE_sdata4
| DW_EH_PE_textrel
, "textrel sdata4")
482 S(DW_EH_PE_sdata8
| DW_EH_PE_textrel
, "textrel sdata8")
484 S(DW_EH_PE_absptr
| DW_EH_PE_datarel
, "datarel")
485 S(DW_EH_PE_uleb128
| DW_EH_PE_datarel
, "datarel uleb128")
486 S(DW_EH_PE_udata2
| DW_EH_PE_datarel
, "datarel udata2")
487 S(DW_EH_PE_udata4
| DW_EH_PE_datarel
, "datarel udata4")
488 S(DW_EH_PE_udata8
| DW_EH_PE_datarel
, "datarel udata8")
489 S(DW_EH_PE_sleb128
| DW_EH_PE_datarel
, "datarel sleb128")
490 S(DW_EH_PE_sdata2
| DW_EH_PE_datarel
, "datarel sdata2")
491 S(DW_EH_PE_sdata4
| DW_EH_PE_datarel
, "datarel sdata4")
492 S(DW_EH_PE_sdata8
| DW_EH_PE_datarel
, "datarel sdata8")
494 S(DW_EH_PE_absptr
| DW_EH_PE_funcrel
, "funcrel")
495 S(DW_EH_PE_uleb128
| DW_EH_PE_funcrel
, "funcrel uleb128")
496 S(DW_EH_PE_udata2
| DW_EH_PE_funcrel
, "funcrel udata2")
497 S(DW_EH_PE_udata4
| DW_EH_PE_funcrel
, "funcrel udata4")
498 S(DW_EH_PE_udata8
| DW_EH_PE_funcrel
, "funcrel udata8")
499 S(DW_EH_PE_sleb128
| DW_EH_PE_funcrel
, "funcrel sleb128")
500 S(DW_EH_PE_sdata2
| DW_EH_PE_funcrel
, "funcrel sdata2")
501 S(DW_EH_PE_sdata4
| DW_EH_PE_funcrel
, "funcrel sdata4")
502 S(DW_EH_PE_sdata8
| DW_EH_PE_funcrel
, "funcrel sdata8")
504 S(DW_EH_PE_indirect
| DW_EH_PE_absptr
, "indirect absolute")
506 S(DW_EH_PE_indirect
| DW_EH_PE_absptr
| DW_EH_PE_pcrel
,
508 S(DW_EH_PE_indirect
| DW_EH_PE_uleb128
| DW_EH_PE_pcrel
,
509 "indirect pcrel uleb128")
510 S(DW_EH_PE_indirect
| DW_EH_PE_udata2
| DW_EH_PE_pcrel
,
511 "indirect pcrel udata2")
512 S(DW_EH_PE_indirect
| DW_EH_PE_udata4
| DW_EH_PE_pcrel
,
513 "indirect pcrel udata4")
514 S(DW_EH_PE_indirect
| DW_EH_PE_udata8
| DW_EH_PE_pcrel
,
515 "indirect pcrel udata8")
516 S(DW_EH_PE_indirect
| DW_EH_PE_sleb128
| DW_EH_PE_pcrel
,
517 "indirect pcrel sleb128")
518 S(DW_EH_PE_indirect
| DW_EH_PE_sdata2
| DW_EH_PE_pcrel
,
519 "indirect pcrel sdata2")
520 S(DW_EH_PE_indirect
| DW_EH_PE_sdata4
| DW_EH_PE_pcrel
,
521 "indirect pcrel sdata4")
522 S(DW_EH_PE_indirect
| DW_EH_PE_sdata8
| DW_EH_PE_pcrel
,
523 "indirect pcrel sdata8")
525 S(DW_EH_PE_indirect
| DW_EH_PE_absptr
| DW_EH_PE_textrel
,
527 S(DW_EH_PE_indirect
| DW_EH_PE_uleb128
| DW_EH_PE_textrel
,
528 "indirect textrel uleb128")
529 S(DW_EH_PE_indirect
| DW_EH_PE_udata2
| DW_EH_PE_textrel
,
530 "indirect textrel udata2")
531 S(DW_EH_PE_indirect
| DW_EH_PE_udata4
| DW_EH_PE_textrel
,
532 "indirect textrel udata4")
533 S(DW_EH_PE_indirect
| DW_EH_PE_udata8
| DW_EH_PE_textrel
,
534 "indirect textrel udata8")
535 S(DW_EH_PE_indirect
| DW_EH_PE_sleb128
| DW_EH_PE_textrel
,
536 "indirect textrel sleb128")
537 S(DW_EH_PE_indirect
| DW_EH_PE_sdata2
| DW_EH_PE_textrel
,
538 "indirect textrel sdata2")
539 S(DW_EH_PE_indirect
| DW_EH_PE_sdata4
| DW_EH_PE_textrel
,
540 "indirect textrel sdata4")
541 S(DW_EH_PE_indirect
| DW_EH_PE_sdata8
| DW_EH_PE_textrel
,
542 "indirect textrel sdata8")
544 S(DW_EH_PE_indirect
| DW_EH_PE_absptr
| DW_EH_PE_datarel
,
546 S(DW_EH_PE_indirect
| DW_EH_PE_uleb128
| DW_EH_PE_datarel
,
547 "indirect datarel uleb128")
548 S(DW_EH_PE_indirect
| DW_EH_PE_udata2
| DW_EH_PE_datarel
,
549 "indirect datarel udata2")
550 S(DW_EH_PE_indirect
| DW_EH_PE_udata4
| DW_EH_PE_datarel
,
551 "indirect datarel udata4")
552 S(DW_EH_PE_indirect
| DW_EH_PE_udata8
| DW_EH_PE_datarel
,
553 "indirect datarel udata8")
554 S(DW_EH_PE_indirect
| DW_EH_PE_sleb128
| DW_EH_PE_datarel
,
555 "indirect datarel sleb128")
556 S(DW_EH_PE_indirect
| DW_EH_PE_sdata2
| DW_EH_PE_datarel
,
557 "indirect datarel sdata2")
558 S(DW_EH_PE_indirect
| DW_EH_PE_sdata4
| DW_EH_PE_datarel
,
559 "indirect datarel sdata4")
560 S(DW_EH_PE_indirect
| DW_EH_PE_sdata8
| DW_EH_PE_datarel
,
561 "indirect datarel sdata8")
563 S(DW_EH_PE_indirect
| DW_EH_PE_absptr
| DW_EH_PE_funcrel
,
565 S(DW_EH_PE_indirect
| DW_EH_PE_uleb128
| DW_EH_PE_funcrel
,
566 "indirect funcrel uleb128")
567 S(DW_EH_PE_indirect
| DW_EH_PE_udata2
| DW_EH_PE_funcrel
,
568 "indirect funcrel udata2")
569 S(DW_EH_PE_indirect
| DW_EH_PE_udata4
| DW_EH_PE_funcrel
,
570 "indirect funcrel udata4")
571 S(DW_EH_PE_indirect
| DW_EH_PE_udata8
| DW_EH_PE_funcrel
,
572 "indirect funcrel udata8")
573 S(DW_EH_PE_indirect
| DW_EH_PE_sleb128
| DW_EH_PE_funcrel
,
574 "indirect funcrel sleb128")
575 S(DW_EH_PE_indirect
| DW_EH_PE_sdata2
| DW_EH_PE_funcrel
,
576 "indirect funcrel sdata2")
577 S(DW_EH_PE_indirect
| DW_EH_PE_sdata4
| DW_EH_PE_funcrel
,
578 "indirect funcrel sdata4")
579 S(DW_EH_PE_indirect
| DW_EH_PE_sdata8
| DW_EH_PE_funcrel
,
580 "indirect funcrel sdata8")
582 #if HAVE_DESIGNATED_INITIALIZERS
585 gcc_assert (format
>= 0 && format
< 0x100 && format_names
[format
]);
587 return format_names
[format
];
594 /* Output an unsigned LEB128 quantity, but only the byte values. */
597 dw2_asm_output_data_uleb128_raw (unsigned HOST_WIDE_INT value
)
601 int byte
= (value
& 0x7f);
604 /* More bytes to follow. */
607 fprintf (asm_out_file
, "%#x", byte
);
610 fputc (',', asm_out_file
);
614 /* Output an unsigned LEB128 quantity. */
617 dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value
,
618 const char *comment
, ...)
622 va_start (ap
, comment
);
624 #ifdef HAVE_AS_LEB128
625 fputs ("\t.uleb128 ", asm_out_file
);
626 fprint_whex (asm_out_file
, value
);
628 if (flag_debug_asm
&& comment
)
630 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
631 vfprintf (asm_out_file
, comment
, ap
);
635 unsigned HOST_WIDE_INT work
= value
;
636 const char *byte_op
= targetm
.asm_out
.byte_op
;
639 fputs (byte_op
, asm_out_file
);
642 int byte
= (work
& 0x7f);
645 /* More bytes to follow. */
650 fprintf (asm_out_file
, "%#x", byte
);
652 fputc (',', asm_out_file
);
655 assemble_integer (GEN_INT (byte
), 1, BITS_PER_UNIT
, 1);
661 fprintf (asm_out_file
, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX
,
662 ASM_COMMENT_START
, value
);
665 fputs ("; ", asm_out_file
);
666 vfprintf (asm_out_file
, comment
, ap
);
671 putc ('\n', asm_out_file
);
676 /* Output an signed LEB128 quantity, but only the byte values. */
679 dw2_asm_output_data_sleb128_raw (HOST_WIDE_INT value
)
685 byte
= (value
& 0x7f);
687 more
= !((value
== 0 && (byte
& 0x40) == 0)
688 || (value
== -1 && (byte
& 0x40) != 0));
692 fprintf (asm_out_file
, "%#x", byte
);
695 fputc (',', asm_out_file
);
699 /* Output a signed LEB128 quantity. */
702 dw2_asm_output_data_sleb128 (HOST_WIDE_INT value
,
703 const char *comment
, ...)
707 va_start (ap
, comment
);
709 #ifdef HAVE_AS_LEB128
710 fprintf (asm_out_file
, "\t.sleb128 " HOST_WIDE_INT_PRINT_DEC
, value
);
712 if (flag_debug_asm
&& comment
)
714 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
715 vfprintf (asm_out_file
, comment
, ap
);
719 HOST_WIDE_INT work
= value
;
721 const char *byte_op
= targetm
.asm_out
.byte_op
;
724 fputs (byte_op
, asm_out_file
);
727 byte
= (work
& 0x7f);
728 /* arithmetic shift */
730 more
= !((work
== 0 && (byte
& 0x40) == 0)
731 || (work
== -1 && (byte
& 0x40) != 0));
737 fprintf (asm_out_file
, "%#x", byte
);
739 fputc (',', asm_out_file
);
742 assemble_integer (GEN_INT (byte
), 1, BITS_PER_UNIT
, 1);
748 fprintf (asm_out_file
, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC
,
749 ASM_COMMENT_START
, value
);
752 fputs ("; ", asm_out_file
);
753 vfprintf (asm_out_file
, comment
, ap
);
758 fputc ('\n', asm_out_file
);
764 dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED
,
765 const char *lab2 ATTRIBUTE_UNUSED
,
766 const char *comment
, ...)
770 va_start (ap
, comment
);
772 #ifdef HAVE_AS_LEB128
773 fputs ("\t.uleb128 ", asm_out_file
);
774 assemble_name (asm_out_file
, lab1
);
775 putc ('-', asm_out_file
);
776 assemble_name (asm_out_file
, lab2
);
781 if (flag_debug_asm
&& comment
)
783 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
784 vfprintf (asm_out_file
, comment
, ap
);
786 fputc ('\n', asm_out_file
);
794 dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED
,
795 const char *lab2 ATTRIBUTE_UNUSED
,
796 const char *comment
, ...)
800 va_start (ap
, comment
);
802 #ifdef HAVE_AS_LEB128
803 fputs ("\t.sleb128 ", asm_out_file
);
804 assemble_name (asm_out_file
, lab1
);
805 putc ('-', asm_out_file
);
806 assemble_name (asm_out_file
, lab2
);
811 if (flag_debug_asm
&& comment
)
813 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
814 vfprintf (asm_out_file
, comment
, ap
);
816 fputc ('\n', asm_out_file
);
822 static GTY(()) hash_map
<const char *, tree
> *indirect_pool
;
824 static GTY(()) int dw2_const_labelno
;
826 #if defined(HAVE_GAS_HIDDEN)
827 # define USE_LINKONCE_INDIRECT (SUPPORTS_ONE_ONLY)
829 # define USE_LINKONCE_INDIRECT 0
832 /* Compare two std::pair<const char *, tree> by their first element.
834 >0 to indicate whether K1 is less than, equal to, or greater than
838 compare_strings (const void *a
, const void *b
)
840 const char *s1
= ((const std::pair
<const char *, tree
> *) a
)->first
;
841 const char *s2
= ((const std::pair
<const char *, tree
> *) b
)->first
;
847 ret
= strcmp (s1
, s2
);
849 /* The strings are always those from IDENTIFIER_NODEs, and,
850 therefore, we should never have two copies of the same
857 /* Put X, a SYMBOL_REF, in memory. Return a SYMBOL_REF to the allocated
858 memory. Differs from force_const_mem in that a single pool is used for
859 the entire unit of translation, and the memory is not guaranteed to be
860 "near" the function in any interesting sense. IS_PUBLIC controls whether
861 the symbol can be shared across the entire application (or DSO). */
864 dw2_force_const_mem (rtx x
, bool is_public
)
870 indirect_pool
= hash_map
<const char *, tree
>::create_ggc (64);
872 gcc_assert (GET_CODE (x
) == SYMBOL_REF
);
875 tree
*slot
= indirect_pool
->get (key
);
881 const char *str
= targetm
.strip_name_encoding (key
);
883 if (is_public
&& USE_LINKONCE_INDIRECT
)
885 char *ref_name
= XALLOCAVEC (char, strlen (str
) + sizeof "DW.ref.");
887 sprintf (ref_name
, "DW.ref.%s", str
);
888 gcc_assert (!maybe_get_identifier (ref_name
));
889 decl_id
= get_identifier (ref_name
);
890 TREE_PUBLIC (decl_id
) = 1;
896 ASM_GENERATE_INTERNAL_LABEL (label
, "LDFCM", dw2_const_labelno
);
898 gcc_assert (!maybe_get_identifier (label
));
899 decl_id
= get_identifier (label
);
902 id
= maybe_get_identifier (str
);
904 TREE_SYMBOL_REFERENCED (id
) = 1;
906 indirect_pool
->put (key
, decl_id
);
909 return gen_rtx_SYMBOL_REF (Pmode
, IDENTIFIER_POINTER (decl_id
));
912 /* A helper function for dw2_output_indirect_constants. Emit one queued
913 constant to memory. */
916 dw2_output_indirect_constant_1 (const char *sym
, tree id
)
921 decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, id
, ptr_type_node
);
922 SET_DECL_ASSEMBLER_NAME (decl
, id
);
923 DECL_ARTIFICIAL (decl
) = 1;
924 DECL_IGNORED_P (decl
) = 1;
925 DECL_INITIAL (decl
) = decl
;
926 TREE_READONLY (decl
) = 1;
927 TREE_STATIC (decl
) = 1;
929 if (TREE_PUBLIC (id
))
931 TREE_PUBLIC (decl
) = 1;
932 make_decl_one_only (decl
, DECL_ASSEMBLER_NAME (decl
));
933 if (USE_LINKONCE_INDIRECT
)
934 DECL_VISIBILITY (decl
) = VISIBILITY_HIDDEN
;
937 sym_ref
= gen_rtx_SYMBOL_REF (Pmode
, sym
);
938 assemble_variable (decl
, 1, 1, 1);
939 assemble_integer (sym_ref
, POINTER_SIZE_UNITS
, POINTER_SIZE
, 1);
944 /* Emit the constants queued through dw2_force_const_mem. */
947 dw2_output_indirect_constants (void)
952 auto_vec
<std::pair
<const char *, tree
> > temp (indirect_pool
->elements ());
953 for (hash_map
<const char *, tree
>::iterator iter
= indirect_pool
->begin ();
954 iter
!= indirect_pool
->end (); ++iter
)
955 temp
.quick_push (*iter
);
957 temp
.qsort (compare_strings
);
959 for (unsigned int i
= 0; i
< temp
.length (); i
++)
960 dw2_output_indirect_constant_1 (temp
[i
].first
, temp
[i
].second
);
963 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.
964 If PUBLIC is set and the encoding is DW_EH_PE_indirect, the indirect
965 reference is shared across the entire application (or DSO). */
968 dw2_asm_output_encoded_addr_rtx (int encoding
, rtx addr
, bool is_public
,
969 const char *comment
, ...)
974 va_start (ap
, comment
);
976 size
= size_of_encoded_value (encoding
);
978 if (encoding
== DW_EH_PE_aligned
)
980 assemble_align (POINTER_SIZE
);
981 assemble_integer (addr
, size
, POINTER_SIZE
, 1);
986 /* NULL is _always_ represented as a plain zero, as is 1 for Ada's
988 if (addr
== const0_rtx
|| addr
== const1_rtx
)
989 assemble_integer (addr
, size
, BITS_PER_UNIT
, 1);
993 /* Allow the target first crack at emitting this. Some of the
994 special relocations require special directives instead of
995 just ".4byte" or whatever. */
996 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
997 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file
, encoding
, size
,
1001 /* Indirection is used to get dynamic relocations out of a
1002 read-only section. */
1003 if (encoding
& DW_EH_PE_indirect
)
1005 /* It is very tempting to use force_const_mem so that we share data
1006 with the normal constant pool. However, we've already emitted
1007 the constant pool for this function. Moreover, we'd like to
1008 share these constants across the entire unit of translation and
1009 even, if possible, across the entire application (or DSO). */
1010 addr
= dw2_force_const_mem (addr
, is_public
);
1011 encoding
&= ~DW_EH_PE_indirect
;
1015 switch (encoding
& 0xF0)
1017 case DW_EH_PE_absptr
:
1018 dw2_assemble_integer (size
, addr
);
1021 #ifdef ASM_OUTPUT_DWARF_DATAREL
1022 case DW_EH_PE_datarel
:
1023 gcc_assert (GET_CODE (addr
) == SYMBOL_REF
);
1024 ASM_OUTPUT_DWARF_DATAREL (asm_out_file
, size
, XSTR (addr
, 0));
1028 case DW_EH_PE_pcrel
:
1029 gcc_assert (GET_CODE (addr
) == SYMBOL_REF
);
1030 #ifdef ASM_OUTPUT_DWARF_PCREL
1031 ASM_OUTPUT_DWARF_PCREL (asm_out_file
, size
, XSTR (addr
, 0));
1033 dw2_assemble_integer (size
, gen_rtx_MINUS (Pmode
, addr
, pc_rtx
));
1038 /* Other encodings should have been handled by
1039 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
1043 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
1048 if (flag_debug_asm
&& comment
)
1050 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
1051 vfprintf (asm_out_file
, comment
, ap
);
1053 fputc ('\n', asm_out_file
);
1058 #include "gt-dwarf2asm.h"