hppa: Export main in pr104869.C on hpux
[official-gcc.git] / gcc / dwarf2asm.cc
blobea3f3982347d606e1c620d5005c12bdefac2afbc
1 /* Dwarf2 assembler output helper routines.
2 Copyright (C) 2001-2023 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
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 COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "target.h"
25 #include "rtl.h"
26 #include "tree.h"
27 #include "memmodel.h"
28 #include "tm_p.h"
29 #include "stringpool.h"
30 #include "varasm.h"
31 #include "output.h"
32 #include "dwarf2asm.h"
33 #include "dwarf2.h"
34 #include "function.h"
35 #include "emit-rtl.h"
36 #include "fold-const.h"
38 #ifndef XCOFF_DEBUGGING_INFO
39 #define XCOFF_DEBUGGING_INFO 0
40 #endif
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. */
46 void
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);
56 if (BYTES_BIG_ENDIAN)
58 if (op)
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);
65 else
67 assemble_integer (const0_rtx, DWARF2_ADDR_SIZE,
68 BITS_PER_UNIT, 1);
69 putc ('\n', asm_out_file);
70 assemble_integer (x, DWARF2_ADDR_SIZE,
71 BITS_PER_UNIT, 1);
74 else
76 if (op)
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);
83 else
85 assemble_integer (x, DWARF2_ADDR_SIZE,
86 BITS_PER_UNIT, 1);
87 putc ('\n', asm_out_file);
88 assemble_integer (const0_rtx, DWARF2_ADDR_SIZE,
89 BITS_PER_UNIT, 1);
92 return;
95 const char *op = integer_asm_op (size, false);
97 if (op)
99 fputs (op, asm_out_file);
100 if (CONST_INT_P (x))
101 fprint_whex (asm_out_file, (unsigned HOST_WIDE_INT) INTVAL (x));
102 else
103 output_addr_const (asm_out_file, x);
105 else
106 assemble_integer (x, size, BITS_PER_UNIT, 1);
110 /* Output a value of a given size in target byte order. */
112 void
113 dw2_asm_output_data_raw (int size, unsigned HOST_WIDE_INT value)
115 unsigned char bytes[8];
116 int i;
118 for (i = 0; i < 8; ++i)
120 bytes[i] = value & 0xff;
121 value >>= 8;
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]);
130 else
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. */
140 void
141 dw2_asm_output_data (int size, unsigned HOST_WIDE_INT value,
142 const char *comment, ...)
144 va_list ap;
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));
152 if (op)
154 fputs (op, asm_out_file);
155 fprint_whex (asm_out_file, value);
157 else
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);
167 va_end (ap);
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. */
176 void
177 dw2_asm_output_delta (int size, const char *lab1, const char *lab2,
178 const char *comment, ...)
180 va_list ap;
182 va_start (ap, comment);
184 #ifdef ASM_OUTPUT_DWARF_DELTA
185 ASM_OUTPUT_DWARF_DELTA (asm_out_file, size, lab1, lab2);
186 #else
187 dw2_assemble_integer (size,
188 gen_rtx_MINUS (Pmode,
189 gen_rtx_SYMBOL_REF (Pmode, lab1),
190 gen_rtx_SYMBOL_REF (Pmode, lab2)));
191 #endif
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);
199 va_end (ap);
202 #ifdef ASM_OUTPUT_DWARF_VMS_DELTA
203 /* Output the difference between two symbols in instruction units
204 in a given size. */
206 void
207 dw2_asm_output_vms_delta (int size ATTRIBUTE_UNUSED,
208 const char *lab1, const char *lab2,
209 const char *comment, ...)
211 va_list ap;
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);
223 va_end (ap);
225 #endif
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. */
234 void
235 dw2_asm_output_offset (int size, const char *label,
236 section *base ATTRIBUTE_UNUSED,
237 const char *comment, ...)
239 va_list ap;
241 va_start (ap, comment);
243 #ifdef ASM_OUTPUT_DWARF_OFFSET
244 ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label, 0, base);
245 #else
246 dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
247 #endif
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);
256 va_end (ap);
259 void
260 dw2_asm_output_offset (int size, const char *label, HOST_WIDE_INT offset,
261 section *base ATTRIBUTE_UNUSED,
262 const char *comment, ...)
264 va_list ap;
266 va_start (ap, comment);
268 #ifdef ASM_OUTPUT_DWARF_OFFSET
269 ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label, offset, base);
270 #else
271 dw2_assemble_integer (size, gen_rtx_PLUS (Pmode,
272 gen_rtx_SYMBOL_REF (Pmode, label),
273 gen_int_mode (offset, Pmode)));
274 #endif
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);
283 va_end (ap);
286 #if 0
288 /* Output a self-relative reference to a label, possibly in a
289 different section or object file. */
291 void
292 dw2_asm_output_pcrel (int size ATTRIBUTE_UNUSED,
293 const char *label ATTRIBUTE_UNUSED,
294 const char *comment, ...)
296 va_list ap;
298 va_start (ap, comment);
300 #ifdef ASM_OUTPUT_DWARF_PCREL
301 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label);
302 #else
303 dw2_assemble_integer (size,
304 gen_rtx_MINUS (Pmode,
305 gen_rtx_SYMBOL_REF (Pmode, label),
306 pc_rtx));
307 #endif
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);
316 va_end (ap);
318 #endif /* 0 */
320 /* Output an absolute reference to a label. */
322 void
323 dw2_asm_output_addr (int size, const char *label,
324 const char *comment, ...)
326 va_list ap;
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);
339 va_end (ap);
342 /* Similar, but use an RTX expression instead of a text label. */
344 void
345 dw2_asm_output_addr_rtx (int size, rtx addr,
346 const char *comment, ...)
348 va_list ap;
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);
361 va_end (ap);
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. */
371 void
372 dw2_asm_output_nstring (const char *str, size_t orig_len,
373 const char *comment, ...)
375 size_t i, len;
376 va_list ap;
378 va_start (ap, comment);
380 len = orig_len;
382 if (len == (size_t) -1)
383 len = strlen (str);
385 if (flag_debug_asm && comment)
387 if (XCOFF_DEBUGGING_INFO)
388 fputs ("\t.byte \"", asm_out_file);
389 else
390 fputs ("\t.ascii \"", asm_out_file);
392 for (i = 0; i < len; i++)
394 int c = str[i];
395 if (c == '\"')
396 fputc (XCOFF_DEBUGGING_INFO ? '\"' : '\\', asm_out_file);
397 else if (c == '\\')
398 fputc ('\\', asm_out_file);
399 if (ISPRINT (c))
400 fputc (c, asm_out_file);
401 else
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);
408 else
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)
413 len += 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);
419 va_end (ap);
423 /* Return the size of an unsigned LEB128 quantity. */
426 size_of_uleb128 (unsigned HOST_WIDE_INT value)
428 int size = 0;
432 value >>= 7;
433 size += 1;
435 while (value != 0);
437 return size;
440 /* Return the size of a signed LEB128 quantity. */
443 size_of_sleb128 (HOST_WIDE_INT value)
445 int size = 0, byte;
449 byte = (value & 0x7f);
450 value >>= 7;
451 size += 1;
453 while (!((value == 0 && (byte & 0x40) == 0)
454 || (value == -1 && (byte & 0x40) != 0)));
456 return size;
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
461 include leb128. */
464 size_of_encoded_value (int encoding)
466 if (encoding == DW_EH_PE_omit)
467 return 0;
469 switch (encoding & 0x07)
471 case DW_EH_PE_absptr:
472 return POINTER_SIZE_UNITS;
473 case DW_EH_PE_udata2:
474 return 2;
475 case DW_EH_PE_udata4:
476 return 4;
477 case DW_EH_PE_udata8:
478 return 8;
479 default:
480 gcc_unreachable ();
484 /* Yield a name for a given pointer encoding. */
486 const char *
487 eh_data_format_name (int format)
489 #if HAVE_DESIGNATED_INITIALIZERS
490 #define S(p, v) [p] = v,
491 #else
492 #define S(p, v) case p: return v;
493 #endif
495 #if HAVE_DESIGNATED_INITIALIZERS
496 __extension__ static const char * const format_names[256] = {
497 #else
498 switch (format) {
499 #endif
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,
557 "indirect 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,
576 "indirect 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,
595 "indirect 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,
614 "indirect 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];
638 #else
640 gcc_unreachable ();
641 #endif
644 /* Output an unsigned LEB128 quantity, but only the byte values. */
646 void
647 dw2_asm_output_data_uleb128_raw (unsigned HOST_WIDE_INT value)
649 while (1)
651 int byte = (value & 0x7f);
652 value >>= 7;
653 if (value != 0)
654 /* More bytes to follow. */
655 byte |= 0x80;
657 fprintf (asm_out_file, "%#x", byte);
658 if (value == 0)
659 break;
660 fputc (',', asm_out_file);
664 /* Output an unsigned LEB128 quantity. */
666 void
667 dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value,
668 const char *comment, ...)
670 va_list ap;
672 va_start (ap, comment);
674 if (HAVE_AS_LEB128)
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);
685 else
687 unsigned HOST_WIDE_INT work = value;
688 const char *byte_op = targetm.asm_out.byte_op;
690 if (byte_op)
691 fputs (byte_op, asm_out_file);
694 int byte = (work & 0x7f);
695 work >>= 7;
696 if (work != 0)
697 /* More bytes to follow. */
698 byte |= 0x80;
700 if (byte_op)
702 fprintf (asm_out_file, "%#x", byte);
703 if (work != 0)
704 fputc (',', asm_out_file);
706 else
707 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
709 while (work != 0);
711 if (flag_debug_asm)
713 fprintf (asm_out_file, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX,
714 ASM_COMMENT_START, value);
715 if (comment)
717 fputs ("; ", asm_out_file);
718 vfprintf (asm_out_file, comment, ap);
723 putc ('\n', asm_out_file);
725 va_end (ap);
728 /* Output an signed LEB128 quantity, but only the byte values. */
730 void
731 dw2_asm_output_data_sleb128_raw (HOST_WIDE_INT value)
733 int byte, more;
735 while (1)
737 byte = (value & 0x7f);
738 value >>= 7;
739 more = !((value == 0 && (byte & 0x40) == 0)
740 || (value == -1 && (byte & 0x40) != 0));
741 if (more)
742 byte |= 0x80;
744 fprintf (asm_out_file, "%#x", byte);
745 if (!more)
746 break;
747 fputc (',', asm_out_file);
751 /* Output a signed LEB128 quantity. */
753 void
754 dw2_asm_output_data_sleb128 (HOST_WIDE_INT value,
755 const char *comment, ...)
757 va_list ap;
759 va_start (ap, comment);
761 if (HAVE_AS_LEB128)
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);
771 else
773 HOST_WIDE_INT work = value;
774 int more, byte;
775 const char *byte_op = targetm.asm_out.byte_op;
777 if (byte_op)
778 fputs (byte_op, asm_out_file);
781 byte = (work & 0x7f);
782 /* arithmetic shift */
783 work >>= 7;
784 more = !((work == 0 && (byte & 0x40) == 0)
785 || (work == -1 && (byte & 0x40) != 0));
786 if (more)
787 byte |= 0x80;
789 if (byte_op)
791 fprintf (asm_out_file, "%#x", byte);
792 if (more)
793 fputc (',', asm_out_file);
795 else
796 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
798 while (more);
800 if (flag_debug_asm)
802 fprintf (asm_out_file, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC,
803 ASM_COMMENT_START, value);
804 if (comment)
806 fputs ("; ", asm_out_file);
807 vfprintf (asm_out_file, comment, ap);
812 fputc ('\n', asm_out_file);
814 va_end (ap);
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. */
821 void
822 dw2_asm_output_symname_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
823 const char *comment, ...)
825 va_list ap;
827 va_start (ap, comment);
829 #ifdef HAVE_AS_LEB128
830 fputs ("\t.uleb128 ", asm_out_file);
831 assemble_name (asm_out_file, lab1);
832 #else
833 gcc_unreachable ();
834 #endif
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);
843 va_end (ap);
846 void
847 dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
848 const char *lab2 ATTRIBUTE_UNUSED,
849 const char *comment, ...)
851 va_list ap;
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);
869 else
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);
879 va_end (ap);
882 #if 0
884 void
885 dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED,
886 const char *lab2 ATTRIBUTE_UNUSED,
887 const char *comment, ...)
889 va_list ap;
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);
907 va_end (ap);
909 #endif /* 0 */
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)
917 #else
918 # define USE_LINKONCE_INDIRECT 0
919 #endif
921 /* Compare two std::pair<const char *, tree> by their first element.
922 Returns <0, 0, or
923 >0 to indicate whether K1 is less than, equal to, or greater than
924 K2, respectively. */
926 static int
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;
931 int ret;
933 if (s1 == s2)
934 return 0;
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
940 string. */
941 gcc_assert (ret);
943 return ret;
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)
955 const char *key;
956 tree decl_id;
958 if (! indirect_pool)
959 indirect_pool = hash_map<const char *, tree>::create_ggc (64);
961 gcc_assert (GET_CODE (x) == SYMBOL_REF);
963 key = XSTR (x, 0);
964 tree *slot = indirect_pool->get (key);
965 if (slot)
966 decl_id = *slot;
967 else
969 tree id;
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;
981 else
983 char label[32];
985 ASM_GENERATE_INTERNAL_LABEL (label, "LDFCM", dw2_const_labelno);
986 ++dw2_const_labelno;
987 gcc_assert (!maybe_get_identifier (label));
988 decl_id = get_identifier (label);
991 id = maybe_get_identifier (str);
992 if (id)
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. */
1004 static int
1005 dw2_output_indirect_constant_1 (const char *sym, tree id)
1007 rtx sym_ref;
1008 tree decl;
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
1034 them in blocks. */
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;
1045 return 0;
1048 /* Emit the constants queued through dw2_force_const_mem. */
1050 void
1051 dw2_output_indirect_constants (void)
1053 if (!indirect_pool)
1054 return;
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). */
1071 void
1072 dw2_asm_output_encoded_addr_rtx (int encoding, rtx addr, bool is_public,
1073 const char *comment, ...)
1075 int size;
1076 va_list ap;
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);
1086 va_end (ap);
1087 return;
1090 /* NULL is _always_ represented as a plain zero, as is 1 for Ada's
1091 "all others". */
1092 if (addr == const0_rtx || addr == const1_rtx)
1093 assemble_integer (addr, size, BITS_PER_UNIT, 1);
1094 else
1096 restart:
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,
1102 addr, done);
1103 #endif
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;
1116 goto restart;
1119 switch (encoding & 0xF0)
1121 case DW_EH_PE_absptr:
1122 dw2_assemble_integer (size, addr);
1123 break;
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));
1129 break;
1130 #endif
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));
1136 #else
1137 dw2_assemble_integer (size, gen_rtx_MINUS (Pmode, addr, pc_rtx));
1138 #endif
1139 break;
1141 default:
1142 /* Other encodings should have been handled by
1143 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
1144 gcc_unreachable ();
1147 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
1148 done:;
1149 #endif
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);
1159 va_end (ap);
1162 #include "gt-dwarf2asm.h"