1 /* Dwarf2 assembler output helper routines.
2 Copyright (C) 2001-2024 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"
29 #include "stringpool.h"
32 #include "dwarf2asm.h"
36 #include "fold-const.h"
38 #ifndef XCOFF_DEBUGGING_INFO
39 #define XCOFF_DEBUGGING_INFO 0
43 /* Output an unaligned integer with the given value and size. Prefer not
44 to print a newline, since the caller may want to add a comment. */
47 dw2_assemble_integer (int size
, rtx x
)
49 if (size
== 2 * (int) DWARF2_ADDR_SIZE
&& !CONST_SCALAR_INT_P (x
))
51 /* On 32-bit targets with -gdwarf64, DImode values with
52 relocations usually result in assembler errors. Assume
53 all such values are positive and emit the relocation only
54 in the least significant half. */
55 const char *op
= integer_asm_op (DWARF2_ADDR_SIZE
, false);
60 fputs (op
, asm_out_file
);
61 fprint_whex (asm_out_file
, 0);
62 fputs (", ", asm_out_file
);
63 output_addr_const (asm_out_file
, x
);
67 assemble_integer (const0_rtx
, DWARF2_ADDR_SIZE
,
69 putc ('\n', asm_out_file
);
70 assemble_integer (x
, DWARF2_ADDR_SIZE
,
78 fputs (op
, asm_out_file
);
79 output_addr_const (asm_out_file
, x
);
80 fputs (", ", asm_out_file
);
81 fprint_whex (asm_out_file
, 0);
85 assemble_integer (x
, DWARF2_ADDR_SIZE
,
87 putc ('\n', asm_out_file
);
88 assemble_integer (const0_rtx
, DWARF2_ADDR_SIZE
,
95 const char *op
= integer_asm_op (size
, false);
99 fputs (op
, asm_out_file
);
101 fprint_whex (asm_out_file
, (unsigned HOST_WIDE_INT
) INTVAL (x
));
103 output_addr_const (asm_out_file
, x
);
106 assemble_integer (x
, size
, BITS_PER_UNIT
, 1);
110 /* Output a value of a given size in target byte order. */
113 dw2_asm_output_data_raw (int size
, unsigned HOST_WIDE_INT value
)
115 unsigned char bytes
[8];
118 for (i
= 0; i
< 8; ++i
)
120 bytes
[i
] = value
& 0xff;
124 if (BYTES_BIG_ENDIAN
)
126 for (i
= size
- 1; i
> 0; --i
)
127 fprintf (asm_out_file
, "%#x,", bytes
[i
]);
128 fprintf (asm_out_file
, "%#x", bytes
[0]);
132 for (i
= 0; i
< size
- 1; ++i
)
133 fprintf (asm_out_file
, "%#x,", bytes
[i
]);
134 fprintf (asm_out_file
, "%#x", bytes
[i
]);
138 /* Output an immediate constant in a given SIZE in bytes. */
141 dw2_asm_output_data (int size
, unsigned HOST_WIDE_INT value
,
142 const char *comment
, ...)
145 const char *op
= integer_asm_op (size
, false);
147 va_start (ap
, comment
);
149 if (size
* 8 < HOST_BITS_PER_WIDE_INT
)
150 value
&= ~(HOST_WIDE_INT_M1U
<< (size
* 8));
154 fputs (op
, asm_out_file
);
155 fprint_whex (asm_out_file
, value
);
158 assemble_integer (GEN_INT (value
), size
, BITS_PER_UNIT
, 1);
160 if (flag_debug_asm
&& comment
)
162 fputs ("\t" ASM_COMMENT_START
" ", asm_out_file
);
163 vfprintf (asm_out_file
, comment
, ap
);
165 putc ('\n', asm_out_file
);
170 /* Output the difference between two symbols in a given size. */
171 /* ??? There appear to be assemblers that do not like such
172 subtraction, but do support ASM_SET_OP. It's unfortunately
173 impossible to do here, since the ASM_SET_OP for the difference
174 symbol must appear after both symbols are defined. */
177 dw2_asm_output_delta (int size
, const char *lab1
, const char *lab2
,
178 const char *comment
, ...)
182 va_start (ap
, comment
);
184 #ifdef ASM_OUTPUT_DWARF_DELTA
185 ASM_OUTPUT_DWARF_DELTA (asm_out_file
, size
, lab1
, lab2
);
187 dw2_assemble_integer (size
,
188 gen_rtx_MINUS (Pmode
,
189 gen_rtx_SYMBOL_REF (Pmode
, lab1
),
190 gen_rtx_SYMBOL_REF (Pmode
, lab2
)));
192 if (flag_debug_asm
&& comment
)
194 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
195 vfprintf (asm_out_file
, comment
, ap
);
197 fputc ('\n', asm_out_file
);
202 #ifdef ASM_OUTPUT_DWARF_VMS_DELTA
203 /* Output the difference between two symbols in instruction units
207 dw2_asm_output_vms_delta (int size ATTRIBUTE_UNUSED
,
208 const char *lab1
, const char *lab2
,
209 const char *comment
, ...)
213 va_start (ap
, comment
);
215 ASM_OUTPUT_DWARF_VMS_DELTA (asm_out_file
, size
, lab1
, lab2
);
216 if (flag_debug_asm
&& comment
)
218 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
219 vfprintf (asm_out_file
, comment
, ap
);
221 fputc ('\n', asm_out_file
);
227 /* Output a section-relative reference to a LABEL, which was placed in
228 BASE. In general this can only be done for debugging symbols.
229 E.g. on most targets with the GNU linker, this is accomplished with
230 a direct reference and the knowledge that the debugging section
231 will be placed at VMA 0. Some targets have special relocations for
232 this that we must use. */
235 dw2_asm_output_offset (int size
, const char *label
,
236 section
*base ATTRIBUTE_UNUSED
,
237 const char *comment
, ...)
241 va_start (ap
, comment
);
243 #ifdef ASM_OUTPUT_DWARF_OFFSET
244 ASM_OUTPUT_DWARF_OFFSET (asm_out_file
, size
, label
, 0, base
);
246 dw2_assemble_integer (size
, gen_rtx_SYMBOL_REF (Pmode
, label
));
249 if (flag_debug_asm
&& comment
)
251 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
252 vfprintf (asm_out_file
, comment
, ap
);
254 fputc ('\n', asm_out_file
);
260 dw2_asm_output_offset (int size
, const char *label
, HOST_WIDE_INT offset
,
261 section
*base ATTRIBUTE_UNUSED
,
262 const char *comment
, ...)
266 va_start (ap
, comment
);
268 #ifdef ASM_OUTPUT_DWARF_OFFSET
269 ASM_OUTPUT_DWARF_OFFSET (asm_out_file
, size
, label
, offset
, base
);
271 dw2_assemble_integer (size
, gen_rtx_PLUS (Pmode
,
272 gen_rtx_SYMBOL_REF (Pmode
, label
),
273 gen_int_mode (offset
, Pmode
)));
276 if (flag_debug_asm
&& comment
)
278 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
279 vfprintf (asm_out_file
, comment
, ap
);
281 fputc ('\n', asm_out_file
);
288 /* Output a self-relative reference to a label, possibly in a
289 different section or object file. */
292 dw2_asm_output_pcrel (int size ATTRIBUTE_UNUSED
,
293 const char *label ATTRIBUTE_UNUSED
,
294 const char *comment
, ...)
298 va_start (ap
, comment
);
300 #ifdef ASM_OUTPUT_DWARF_PCREL
301 ASM_OUTPUT_DWARF_PCREL (asm_out_file
, size
, label
);
303 dw2_assemble_integer (size
,
304 gen_rtx_MINUS (Pmode
,
305 gen_rtx_SYMBOL_REF (Pmode
, label
),
309 if (flag_debug_asm
&& comment
)
311 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
312 vfprintf (asm_out_file
, comment
, ap
);
314 fputc ('\n', asm_out_file
);
320 /* Output an absolute reference to a label. */
323 dw2_asm_output_addr (int size
, const char *label
,
324 const char *comment
, ...)
328 va_start (ap
, comment
);
330 dw2_assemble_integer (size
, gen_rtx_SYMBOL_REF (Pmode
, label
));
332 if (flag_debug_asm
&& comment
)
334 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
335 vfprintf (asm_out_file
, comment
, ap
);
337 fputc ('\n', asm_out_file
);
342 /* Similar, but use an RTX expression instead of a text label. */
345 dw2_asm_output_addr_rtx (int size
, rtx addr
,
346 const char *comment
, ...)
350 va_start (ap
, comment
);
352 dw2_assemble_integer (size
, addr
);
354 if (flag_debug_asm
&& comment
)
356 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
357 vfprintf (asm_out_file
, comment
, ap
);
359 fputc ('\n', asm_out_file
);
364 /* Output the first ORIG_LEN characters of STR as a string.
365 If ORIG_LEN is equal to -1, ignore this parameter and output
366 the entire STR instead.
367 If COMMENT is not NULL and comments in the debug information
368 have been requested by the user, append the given COMMENT
369 to the generated output. */
372 dw2_asm_output_nstring (const char *str
, size_t orig_len
,
373 const char *comment
, ...)
378 va_start (ap
, comment
);
382 if (len
== (size_t) -1)
385 if (flag_debug_asm
&& comment
)
387 if (XCOFF_DEBUGGING_INFO
)
388 fputs ("\t.byte \"", asm_out_file
);
390 fputs ("\t.ascii \"", asm_out_file
);
392 for (i
= 0; i
< len
; i
++)
396 fputc (XCOFF_DEBUGGING_INFO
? '\"' : '\\', asm_out_file
);
398 fputc ('\\', asm_out_file
);
400 fputc (c
, asm_out_file
);
402 fprintf (asm_out_file
, "\\%o", c
);
404 fprintf (asm_out_file
, "\\0\"\t%s ", ASM_COMMENT_START
);
405 vfprintf (asm_out_file
, comment
, ap
);
406 fputc ('\n', asm_out_file
);
410 /* If an explicit length was given, we can't assume there
411 is a null termination in the string buffer. */
412 if (orig_len
== (size_t) -1)
414 ASM_OUTPUT_ASCII (asm_out_file
, str
, len
);
415 if (orig_len
!= (size_t) -1)
416 assemble_integer (const0_rtx
, 1, BITS_PER_UNIT
, 1);
423 /* Return the size of an unsigned LEB128 quantity. */
426 size_of_uleb128 (unsigned HOST_WIDE_INT value
)
440 /* Return the size of a signed LEB128 quantity. */
443 size_of_sleb128 (HOST_WIDE_INT value
)
449 byte
= (value
& 0x7f);
453 while (!((value
== 0 && (byte
& 0x40) == 0)
454 || (value
== -1 && (byte
& 0x40) != 0)));
459 /* Given an encoding, return the number of bytes the format occupies.
460 This is only defined for fixed-size encodings, and so does not
464 size_of_encoded_value (int encoding
)
466 if (encoding
== DW_EH_PE_omit
)
469 switch (encoding
& 0x07)
471 case DW_EH_PE_absptr
:
472 return POINTER_SIZE_UNITS
;
473 case DW_EH_PE_udata2
:
475 case DW_EH_PE_udata4
:
477 case DW_EH_PE_udata8
:
484 /* Yield a name for a given pointer encoding. */
487 eh_data_format_name (int format
)
489 #if HAVE_DESIGNATED_INITIALIZERS
490 #define S(p, v) [p] = v,
492 #define S(p, v) case p: return v;
495 #if HAVE_DESIGNATED_INITIALIZERS
496 __extension__
static const char * const format_names
[256] = {
501 S(DW_EH_PE_absptr
, "absolute")
502 S(DW_EH_PE_omit
, "omit")
503 S(DW_EH_PE_aligned
, "aligned absolute")
505 S(DW_EH_PE_uleb128
, "uleb128")
506 S(DW_EH_PE_udata2
, "udata2")
507 S(DW_EH_PE_udata4
, "udata4")
508 S(DW_EH_PE_udata8
, "udata8")
509 S(DW_EH_PE_sleb128
, "sleb128")
510 S(DW_EH_PE_sdata2
, "sdata2")
511 S(DW_EH_PE_sdata4
, "sdata4")
512 S(DW_EH_PE_sdata8
, "sdata8")
514 S(DW_EH_PE_absptr
| DW_EH_PE_pcrel
, "pcrel")
515 S(DW_EH_PE_uleb128
| DW_EH_PE_pcrel
, "pcrel uleb128")
516 S(DW_EH_PE_udata2
| DW_EH_PE_pcrel
, "pcrel udata2")
517 S(DW_EH_PE_udata4
| DW_EH_PE_pcrel
, "pcrel udata4")
518 S(DW_EH_PE_udata8
| DW_EH_PE_pcrel
, "pcrel udata8")
519 S(DW_EH_PE_sleb128
| DW_EH_PE_pcrel
, "pcrel sleb128")
520 S(DW_EH_PE_sdata2
| DW_EH_PE_pcrel
, "pcrel sdata2")
521 S(DW_EH_PE_sdata4
| DW_EH_PE_pcrel
, "pcrel sdata4")
522 S(DW_EH_PE_sdata8
| DW_EH_PE_pcrel
, "pcrel sdata8")
524 S(DW_EH_PE_absptr
| DW_EH_PE_textrel
, "textrel")
525 S(DW_EH_PE_uleb128
| DW_EH_PE_textrel
, "textrel uleb128")
526 S(DW_EH_PE_udata2
| DW_EH_PE_textrel
, "textrel udata2")
527 S(DW_EH_PE_udata4
| DW_EH_PE_textrel
, "textrel udata4")
528 S(DW_EH_PE_udata8
| DW_EH_PE_textrel
, "textrel udata8")
529 S(DW_EH_PE_sleb128
| DW_EH_PE_textrel
, "textrel sleb128")
530 S(DW_EH_PE_sdata2
| DW_EH_PE_textrel
, "textrel sdata2")
531 S(DW_EH_PE_sdata4
| DW_EH_PE_textrel
, "textrel sdata4")
532 S(DW_EH_PE_sdata8
| DW_EH_PE_textrel
, "textrel sdata8")
534 S(DW_EH_PE_absptr
| DW_EH_PE_datarel
, "datarel")
535 S(DW_EH_PE_uleb128
| DW_EH_PE_datarel
, "datarel uleb128")
536 S(DW_EH_PE_udata2
| DW_EH_PE_datarel
, "datarel udata2")
537 S(DW_EH_PE_udata4
| DW_EH_PE_datarel
, "datarel udata4")
538 S(DW_EH_PE_udata8
| DW_EH_PE_datarel
, "datarel udata8")
539 S(DW_EH_PE_sleb128
| DW_EH_PE_datarel
, "datarel sleb128")
540 S(DW_EH_PE_sdata2
| DW_EH_PE_datarel
, "datarel sdata2")
541 S(DW_EH_PE_sdata4
| DW_EH_PE_datarel
, "datarel sdata4")
542 S(DW_EH_PE_sdata8
| DW_EH_PE_datarel
, "datarel sdata8")
544 S(DW_EH_PE_absptr
| DW_EH_PE_funcrel
, "funcrel")
545 S(DW_EH_PE_uleb128
| DW_EH_PE_funcrel
, "funcrel uleb128")
546 S(DW_EH_PE_udata2
| DW_EH_PE_funcrel
, "funcrel udata2")
547 S(DW_EH_PE_udata4
| DW_EH_PE_funcrel
, "funcrel udata4")
548 S(DW_EH_PE_udata8
| DW_EH_PE_funcrel
, "funcrel udata8")
549 S(DW_EH_PE_sleb128
| DW_EH_PE_funcrel
, "funcrel sleb128")
550 S(DW_EH_PE_sdata2
| DW_EH_PE_funcrel
, "funcrel sdata2")
551 S(DW_EH_PE_sdata4
| DW_EH_PE_funcrel
, "funcrel sdata4")
552 S(DW_EH_PE_sdata8
| DW_EH_PE_funcrel
, "funcrel sdata8")
554 S(DW_EH_PE_indirect
| DW_EH_PE_absptr
, "indirect absolute")
556 S(DW_EH_PE_indirect
| DW_EH_PE_absptr
| DW_EH_PE_pcrel
,
558 S(DW_EH_PE_indirect
| DW_EH_PE_uleb128
| DW_EH_PE_pcrel
,
559 "indirect pcrel uleb128")
560 S(DW_EH_PE_indirect
| DW_EH_PE_udata2
| DW_EH_PE_pcrel
,
561 "indirect pcrel udata2")
562 S(DW_EH_PE_indirect
| DW_EH_PE_udata4
| DW_EH_PE_pcrel
,
563 "indirect pcrel udata4")
564 S(DW_EH_PE_indirect
| DW_EH_PE_udata8
| DW_EH_PE_pcrel
,
565 "indirect pcrel udata8")
566 S(DW_EH_PE_indirect
| DW_EH_PE_sleb128
| DW_EH_PE_pcrel
,
567 "indirect pcrel sleb128")
568 S(DW_EH_PE_indirect
| DW_EH_PE_sdata2
| DW_EH_PE_pcrel
,
569 "indirect pcrel sdata2")
570 S(DW_EH_PE_indirect
| DW_EH_PE_sdata4
| DW_EH_PE_pcrel
,
571 "indirect pcrel sdata4")
572 S(DW_EH_PE_indirect
| DW_EH_PE_sdata8
| DW_EH_PE_pcrel
,
573 "indirect pcrel sdata8")
575 S(DW_EH_PE_indirect
| DW_EH_PE_absptr
| DW_EH_PE_textrel
,
577 S(DW_EH_PE_indirect
| DW_EH_PE_uleb128
| DW_EH_PE_textrel
,
578 "indirect textrel uleb128")
579 S(DW_EH_PE_indirect
| DW_EH_PE_udata2
| DW_EH_PE_textrel
,
580 "indirect textrel udata2")
581 S(DW_EH_PE_indirect
| DW_EH_PE_udata4
| DW_EH_PE_textrel
,
582 "indirect textrel udata4")
583 S(DW_EH_PE_indirect
| DW_EH_PE_udata8
| DW_EH_PE_textrel
,
584 "indirect textrel udata8")
585 S(DW_EH_PE_indirect
| DW_EH_PE_sleb128
| DW_EH_PE_textrel
,
586 "indirect textrel sleb128")
587 S(DW_EH_PE_indirect
| DW_EH_PE_sdata2
| DW_EH_PE_textrel
,
588 "indirect textrel sdata2")
589 S(DW_EH_PE_indirect
| DW_EH_PE_sdata4
| DW_EH_PE_textrel
,
590 "indirect textrel sdata4")
591 S(DW_EH_PE_indirect
| DW_EH_PE_sdata8
| DW_EH_PE_textrel
,
592 "indirect textrel sdata8")
594 S(DW_EH_PE_indirect
| DW_EH_PE_absptr
| DW_EH_PE_datarel
,
596 S(DW_EH_PE_indirect
| DW_EH_PE_uleb128
| DW_EH_PE_datarel
,
597 "indirect datarel uleb128")
598 S(DW_EH_PE_indirect
| DW_EH_PE_udata2
| DW_EH_PE_datarel
,
599 "indirect datarel udata2")
600 S(DW_EH_PE_indirect
| DW_EH_PE_udata4
| DW_EH_PE_datarel
,
601 "indirect datarel udata4")
602 S(DW_EH_PE_indirect
| DW_EH_PE_udata8
| DW_EH_PE_datarel
,
603 "indirect datarel udata8")
604 S(DW_EH_PE_indirect
| DW_EH_PE_sleb128
| DW_EH_PE_datarel
,
605 "indirect datarel sleb128")
606 S(DW_EH_PE_indirect
| DW_EH_PE_sdata2
| DW_EH_PE_datarel
,
607 "indirect datarel sdata2")
608 S(DW_EH_PE_indirect
| DW_EH_PE_sdata4
| DW_EH_PE_datarel
,
609 "indirect datarel sdata4")
610 S(DW_EH_PE_indirect
| DW_EH_PE_sdata8
| DW_EH_PE_datarel
,
611 "indirect datarel sdata8")
613 S(DW_EH_PE_indirect
| DW_EH_PE_absptr
| DW_EH_PE_funcrel
,
615 S(DW_EH_PE_indirect
| DW_EH_PE_uleb128
| DW_EH_PE_funcrel
,
616 "indirect funcrel uleb128")
617 S(DW_EH_PE_indirect
| DW_EH_PE_udata2
| DW_EH_PE_funcrel
,
618 "indirect funcrel udata2")
619 S(DW_EH_PE_indirect
| DW_EH_PE_udata4
| DW_EH_PE_funcrel
,
620 "indirect funcrel udata4")
621 S(DW_EH_PE_indirect
| DW_EH_PE_udata8
| DW_EH_PE_funcrel
,
622 "indirect funcrel udata8")
623 S(DW_EH_PE_indirect
| DW_EH_PE_sleb128
| DW_EH_PE_funcrel
,
624 "indirect funcrel sleb128")
625 S(DW_EH_PE_indirect
| DW_EH_PE_sdata2
| DW_EH_PE_funcrel
,
626 "indirect funcrel sdata2")
627 S(DW_EH_PE_indirect
| DW_EH_PE_sdata4
| DW_EH_PE_funcrel
,
628 "indirect funcrel sdata4")
629 S(DW_EH_PE_indirect
| DW_EH_PE_sdata8
| DW_EH_PE_funcrel
,
630 "indirect funcrel sdata8")
632 #if HAVE_DESIGNATED_INITIALIZERS
635 gcc_assert (format
>= 0 && format
< 0x100 && format_names
[format
]);
637 return format_names
[format
];
644 /* Output an unsigned LEB128 quantity, but only the byte values. */
647 dw2_asm_output_data_uleb128_raw (unsigned HOST_WIDE_INT value
)
651 int byte
= (value
& 0x7f);
654 /* More bytes to follow. */
657 fprintf (asm_out_file
, "%#x", byte
);
660 fputc (',', asm_out_file
);
664 /* Output an unsigned LEB128 quantity. */
667 dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value
,
668 const char *comment
, ...)
672 va_start (ap
, comment
);
676 fputs ("\t.uleb128 ", asm_out_file
);
677 fprint_whex (asm_out_file
, value
);
679 if (flag_debug_asm
&& comment
)
681 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
682 vfprintf (asm_out_file
, comment
, ap
);
687 unsigned HOST_WIDE_INT work
= value
;
688 const char *byte_op
= targetm
.asm_out
.byte_op
;
691 fputs (byte_op
, asm_out_file
);
694 int byte
= (work
& 0x7f);
697 /* More bytes to follow. */
702 fprintf (asm_out_file
, "%#x", byte
);
704 fputc (',', asm_out_file
);
707 assemble_integer (GEN_INT (byte
), 1, BITS_PER_UNIT
, 1);
713 fprintf (asm_out_file
, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX
,
714 ASM_COMMENT_START
, value
);
717 fputs ("; ", asm_out_file
);
718 vfprintf (asm_out_file
, comment
, ap
);
723 putc ('\n', asm_out_file
);
728 /* Output an signed LEB128 quantity, but only the byte values. */
731 dw2_asm_output_data_sleb128_raw (HOST_WIDE_INT value
)
737 byte
= (value
& 0x7f);
739 more
= !((value
== 0 && (byte
& 0x40) == 0)
740 || (value
== -1 && (byte
& 0x40) != 0));
744 fprintf (asm_out_file
, "%#x", byte
);
747 fputc (',', asm_out_file
);
751 /* Output a signed LEB128 quantity. */
754 dw2_asm_output_data_sleb128 (HOST_WIDE_INT value
,
755 const char *comment
, ...)
759 va_start (ap
, comment
);
763 fprintf (asm_out_file
, "\t.sleb128 " HOST_WIDE_INT_PRINT_DEC
, value
);
765 if (flag_debug_asm
&& comment
)
767 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
768 vfprintf (asm_out_file
, comment
, ap
);
773 HOST_WIDE_INT work
= value
;
775 const char *byte_op
= targetm
.asm_out
.byte_op
;
778 fputs (byte_op
, asm_out_file
);
781 byte
= (work
& 0x7f);
782 /* arithmetic shift */
784 more
= !((work
== 0 && (byte
& 0x40) == 0)
785 || (work
== -1 && (byte
& 0x40) != 0));
791 fprintf (asm_out_file
, "%#x", byte
);
793 fputc (',', asm_out_file
);
796 assemble_integer (GEN_INT (byte
), 1, BITS_PER_UNIT
, 1);
802 fprintf (asm_out_file
, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC
,
803 ASM_COMMENT_START
, value
);
806 fputs ("; ", asm_out_file
);
807 vfprintf (asm_out_file
, comment
, ap
);
812 fputc ('\n', asm_out_file
);
817 /* Output symbol LAB1 as an unsigned LEB128 quantity. LAB1 should be
818 an assembler-computed constant, e.g. a view number, because we
819 can't have relocations in LEB128 quantities. */
822 dw2_asm_output_symname_uleb128 (const char *lab1 ATTRIBUTE_UNUSED
,
823 const char *comment
, ...)
827 va_start (ap
, comment
);
829 #ifdef HAVE_AS_LEB128
830 fputs ("\t.uleb128 ", asm_out_file
);
831 assemble_name (asm_out_file
, lab1
);
836 if (flag_debug_asm
&& comment
)
838 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
839 vfprintf (asm_out_file
, comment
, ap
);
841 fputc ('\n', asm_out_file
);
847 dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED
,
848 const char *lab2 ATTRIBUTE_UNUSED
,
849 const char *comment
, ...)
853 va_start (ap
, comment
);
855 gcc_assert (HAVE_AS_LEB128
);
857 fputs ("\t.uleb128 ", asm_out_file
);
858 assemble_name (asm_out_file
, lab1
);
859 putc ('-', asm_out_file
);
860 /* dwarf2out.cc might give us a label expression (e.g. .LVL548-1)
861 as second argument. If so, make it a subexpression, to make
862 sure the substraction is done in the right order. */
863 if (strchr (lab2
, '-') != NULL
)
865 putc ('(', asm_out_file
);
866 assemble_name (asm_out_file
, lab2
);
867 putc (')', asm_out_file
);
870 assemble_name (asm_out_file
, lab2
);
872 if (flag_debug_asm
&& comment
)
874 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
875 vfprintf (asm_out_file
, comment
, ap
);
877 fputc ('\n', asm_out_file
);
885 dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED
,
886 const char *lab2 ATTRIBUTE_UNUSED
,
887 const char *comment
, ...)
891 va_start (ap
, comment
);
893 gcc_assert (HAVE_AS_LEB128
);
895 fputs ("\t.sleb128 ", asm_out_file
);
896 assemble_name (asm_out_file
, lab1
);
897 putc ('-', asm_out_file
);
898 assemble_name (asm_out_file
, lab2
);
900 if (flag_debug_asm
&& comment
)
902 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
903 vfprintf (asm_out_file
, comment
, ap
);
905 fputc ('\n', asm_out_file
);
911 static GTY(()) hash_map
<const char *, tree
> *indirect_pool
;
913 static GTY(()) int dw2_const_labelno
;
915 #if defined(HAVE_GAS_HIDDEN)
916 # define USE_LINKONCE_INDIRECT (SUPPORTS_ONE_ONLY && !XCOFF_DEBUGGING_INFO)
918 # define USE_LINKONCE_INDIRECT 0
921 /* Compare two std::pair<const char *, tree> by their first element.
923 >0 to indicate whether K1 is less than, equal to, or greater than
927 compare_strings (const void *a
, const void *b
)
929 const char *s1
= ((const std::pair
<const char *, tree
> *) a
)->first
;
930 const char *s2
= ((const std::pair
<const char *, tree
> *) b
)->first
;
936 ret
= strcmp (s1
, s2
);
938 /* The strings are always those from IDENTIFIER_NODEs, and,
939 therefore, we should never have two copies of the same
946 /* Put X, a SYMBOL_REF, in memory. Return a SYMBOL_REF to the allocated
947 memory. Differs from force_const_mem in that a single pool is used for
948 the entire unit of translation, and the memory is not guaranteed to be
949 "near" the function in any interesting sense. IS_PUBLIC controls whether
950 the symbol can be shared across the entire application (or DSO). */
953 dw2_force_const_mem (rtx x
, bool is_public
)
959 indirect_pool
= hash_map
<const char *, tree
>::create_ggc (64);
961 gcc_assert (GET_CODE (x
) == SYMBOL_REF
);
964 tree
*slot
= indirect_pool
->get (key
);
970 const char *str
= targetm
.strip_name_encoding (key
);
972 if (is_public
&& USE_LINKONCE_INDIRECT
)
974 char *ref_name
= XALLOCAVEC (char, strlen (str
) + sizeof "DW.ref.");
976 sprintf (ref_name
, "DW.ref.%s", str
);
977 gcc_assert (!maybe_get_identifier (ref_name
));
978 decl_id
= get_identifier (ref_name
);
979 TREE_PUBLIC (decl_id
) = 1;
985 ASM_GENERATE_INTERNAL_LABEL (label
, "LDFCM", dw2_const_labelno
);
987 gcc_assert (!maybe_get_identifier (label
));
988 decl_id
= get_identifier (label
);
991 id
= maybe_get_identifier (str
);
993 TREE_SYMBOL_REFERENCED (id
) = 1;
995 indirect_pool
->put (key
, decl_id
);
998 return gen_rtx_SYMBOL_REF (Pmode
, IDENTIFIER_POINTER (decl_id
));
1001 /* A helper function for dw2_output_indirect_constants. Emit one queued
1002 constant to memory. */
1005 dw2_output_indirect_constant_1 (const char *sym
, tree id
)
1010 decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, id
, ptr_type_node
);
1011 SET_DECL_ASSEMBLER_NAME (decl
, id
);
1012 DECL_ARTIFICIAL (decl
) = 1;
1013 DECL_IGNORED_P (decl
) = 1;
1014 DECL_INITIAL (decl
) = build_fold_addr_expr (decl
);
1015 TREE_READONLY (decl
) = 1;
1016 TREE_STATIC (decl
) = 1;
1018 if (TREE_PUBLIC (id
))
1020 TREE_PUBLIC (decl
) = 1;
1021 make_decl_one_only (decl
, DECL_ASSEMBLER_NAME (decl
));
1022 if (USE_LINKONCE_INDIRECT
)
1023 DECL_VISIBILITY (decl
) = VISIBILITY_HIDDEN
;
1026 sym_ref
= gen_rtx_SYMBOL_REF (Pmode
, sym
);
1027 /* Disable ASan for decl because redzones cause ABI breakage between GCC and
1028 libstdc++ for `.LDFCM*' variables. See PR 78651 for details. */
1029 unsigned int save_flag_sanitize
= flag_sanitize
;
1030 flag_sanitize
&= ~(SANITIZE_ADDRESS
| SANITIZE_USER_ADDRESS
1031 | SANITIZE_KERNEL_ADDRESS
);
1032 /* And also temporarily disable -fsection-anchors. These indirect constants
1033 are never referenced from code, so it doesn't make any sense to aggregate
1035 int save_flag_section_anchors
= flag_section_anchors
;
1036 flag_section_anchors
= 0;
1037 assemble_variable (decl
, 1, 1, 1);
1038 flag_section_anchors
= save_flag_section_anchors
;
1039 flag_sanitize
= save_flag_sanitize
;
1040 assemble_integer (sym_ref
, POINTER_SIZE_UNITS
, POINTER_SIZE
, 1);
1041 /* The following is a hack recognized by use_blocks_for_decl_p to disable
1042 section anchor handling of the decl. */
1043 DECL_INITIAL (decl
) = decl
;
1048 /* Emit the constants queued through dw2_force_const_mem. */
1051 dw2_output_indirect_constants (void)
1056 auto_vec
<std::pair
<const char *, tree
> > temp (indirect_pool
->elements ());
1057 for (hash_map
<const char *, tree
>::iterator iter
= indirect_pool
->begin ();
1058 iter
!= indirect_pool
->end (); ++iter
)
1059 temp
.quick_push (*iter
);
1061 temp
.qsort (compare_strings
);
1063 for (unsigned int i
= 0; i
< temp
.length (); i
++)
1064 dw2_output_indirect_constant_1 (temp
[i
].first
, temp
[i
].second
);
1067 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.
1068 If PUBLIC is set and the encoding is DW_EH_PE_indirect, the indirect
1069 reference is shared across the entire application (or DSO). */
1072 dw2_asm_output_encoded_addr_rtx (int encoding
, rtx addr
, bool is_public
,
1073 const char *comment
, ...)
1078 va_start (ap
, comment
);
1080 size
= size_of_encoded_value (encoding
);
1082 if (encoding
== DW_EH_PE_aligned
)
1084 assemble_align (POINTER_SIZE
);
1085 assemble_integer (addr
, size
, POINTER_SIZE
, 1);
1090 /* NULL is _always_ represented as a plain zero, as is 1 for Ada's
1092 if (addr
== const0_rtx
|| addr
== const1_rtx
)
1093 assemble_integer (addr
, size
, BITS_PER_UNIT
, 1);
1097 /* Allow the target first crack at emitting this. Some of the
1098 special relocations require special directives instead of
1099 just ".4byte" or whatever. */
1100 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
1101 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file
, encoding
, size
,
1105 /* Indirection is used to get dynamic relocations out of a
1106 read-only section. */
1107 if (encoding
& DW_EH_PE_indirect
)
1109 /* It is very tempting to use force_const_mem so that we share data
1110 with the normal constant pool. However, we've already emitted
1111 the constant pool for this function. Moreover, we'd like to
1112 share these constants across the entire unit of translation and
1113 even, if possible, across the entire application (or DSO). */
1114 addr
= dw2_force_const_mem (addr
, is_public
);
1115 encoding
&= ~DW_EH_PE_indirect
;
1119 switch (encoding
& 0xF0)
1121 case DW_EH_PE_absptr
:
1122 dw2_assemble_integer (size
, addr
);
1125 #ifdef ASM_OUTPUT_DWARF_DATAREL
1126 case DW_EH_PE_datarel
:
1127 gcc_assert (GET_CODE (addr
) == SYMBOL_REF
);
1128 ASM_OUTPUT_DWARF_DATAREL (asm_out_file
, size
, XSTR (addr
, 0));
1132 case DW_EH_PE_pcrel
:
1133 gcc_assert (GET_CODE (addr
) == SYMBOL_REF
);
1134 #ifdef ASM_OUTPUT_DWARF_PCREL
1135 ASM_OUTPUT_DWARF_PCREL (asm_out_file
, size
, XSTR (addr
, 0));
1137 dw2_assemble_integer (size
, gen_rtx_MINUS (Pmode
, addr
, pc_rtx
));
1142 /* Other encodings should have been handled by
1143 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
1147 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
1152 if (flag_debug_asm
&& comment
)
1154 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
1155 vfprintf (asm_out_file
, comment
, ap
);
1157 fputc ('\n', asm_out_file
);
1162 #include "gt-dwarf2asm.h"