1 /* Dwarf2 assembler output helper routines.
2 Copyright (C) 2001-2014 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"
27 #include "stringpool.h"
32 #include "dwarf2asm.h"
34 #include "splay-tree.h"
39 /* Output an unaligned integer with the given value and size. Prefer not
40 to print a newline, since the caller may want to add a comment. */
43 dw2_assemble_integer (int size
, rtx x
)
45 const char *op
= integer_asm_op (size
, FALSE
);
49 fputs (op
, asm_out_file
);
51 fprint_whex (asm_out_file
, (unsigned HOST_WIDE_INT
) INTVAL (x
));
53 output_addr_const (asm_out_file
, x
);
56 assemble_integer (x
, size
, BITS_PER_UNIT
, 1);
60 /* Output a value of a given size in target byte order. */
63 dw2_asm_output_data_raw (int size
, unsigned HOST_WIDE_INT value
)
65 unsigned char bytes
[8];
68 for (i
= 0; i
< 8; ++i
)
70 bytes
[i
] = value
& 0xff;
76 for (i
= size
- 1; i
> 0; --i
)
77 fprintf (asm_out_file
, "%#x,", bytes
[i
]);
78 fprintf (asm_out_file
, "%#x", bytes
[0]);
82 for (i
= 0; i
< size
- 1; ++i
)
83 fprintf (asm_out_file
, "%#x,", bytes
[i
]);
84 fprintf (asm_out_file
, "%#x", bytes
[i
]);
88 /* Output an immediate constant in a given SIZE in bytes. */
91 dw2_asm_output_data (int size
, unsigned HOST_WIDE_INT value
,
92 const char *comment
, ...)
95 const char *op
= integer_asm_op (size
, FALSE
);
97 va_start (ap
, comment
);
99 if (size
* 8 < HOST_BITS_PER_WIDE_INT
)
100 value
&= ~(~(unsigned HOST_WIDE_INT
) 0 << (size
* 8));
104 fputs (op
, asm_out_file
);
105 fprint_whex (asm_out_file
, value
);
108 assemble_integer (GEN_INT (value
), size
, BITS_PER_UNIT
, 1);
110 if (flag_debug_asm
&& comment
)
112 fputs ("\t" ASM_COMMENT_START
" ", asm_out_file
);
113 vfprintf (asm_out_file
, comment
, ap
);
115 putc ('\n', asm_out_file
);
120 /* Output the difference between two symbols in a given size. */
121 /* ??? There appear to be assemblers that do not like such
122 subtraction, but do support ASM_SET_OP. It's unfortunately
123 impossible to do here, since the ASM_SET_OP for the difference
124 symbol must appear after both symbols are defined. */
127 dw2_asm_output_delta (int size
, const char *lab1
, const char *lab2
,
128 const char *comment
, ...)
132 va_start (ap
, comment
);
134 #ifdef ASM_OUTPUT_DWARF_DELTA
135 ASM_OUTPUT_DWARF_DELTA (asm_out_file
, size
, lab1
, lab2
);
137 dw2_assemble_integer (size
,
138 gen_rtx_MINUS (Pmode
,
139 gen_rtx_SYMBOL_REF (Pmode
, lab1
),
140 gen_rtx_SYMBOL_REF (Pmode
, lab2
)));
142 if (flag_debug_asm
&& comment
)
144 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
145 vfprintf (asm_out_file
, comment
, ap
);
147 fputc ('\n', asm_out_file
);
152 /* Output the difference between two symbols in instruction units
156 dw2_asm_output_vms_delta (int size ATTRIBUTE_UNUSED
,
157 const char *lab1
, const char *lab2
,
158 const char *comment
, ...)
162 va_start (ap
, comment
);
164 #ifndef ASM_OUTPUT_DWARF_VMS_DELTA
165 /* VMS Delta is only special on ia64-vms, but this function also gets
166 called on alpha-vms so it has to do something sane. */
167 dw2_asm_output_delta (size
, lab1
, lab2
, comment
);
169 ASM_OUTPUT_DWARF_VMS_DELTA (asm_out_file
, size
, lab1
, lab2
);
170 if (flag_debug_asm
&& comment
)
172 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
173 vfprintf (asm_out_file
, comment
, ap
);
175 fputc ('\n', asm_out_file
);
181 /* Output a section-relative reference to a LABEL, which was placed in
182 BASE. In general this can only be done for debugging symbols.
183 E.g. on most targets with the GNU linker, this is accomplished with
184 a direct reference and the knowledge that the debugging section
185 will be placed at VMA 0. Some targets have special relocations for
186 this that we must use. */
189 dw2_asm_output_offset (int size
, const char *label
,
190 section
*base ATTRIBUTE_UNUSED
,
191 const char *comment
, ...)
195 va_start (ap
, comment
);
197 #ifdef ASM_OUTPUT_DWARF_OFFSET
198 ASM_OUTPUT_DWARF_OFFSET (asm_out_file
, size
, label
, base
);
200 dw2_assemble_integer (size
, gen_rtx_SYMBOL_REF (Pmode
, label
));
203 if (flag_debug_asm
&& comment
)
205 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
206 vfprintf (asm_out_file
, comment
, ap
);
208 fputc ('\n', asm_out_file
);
215 /* Output a self-relative reference to a label, possibly in a
216 different section or object file. */
219 dw2_asm_output_pcrel (int size ATTRIBUTE_UNUSED
,
220 const char *label ATTRIBUTE_UNUSED
,
221 const char *comment
, ...)
225 va_start (ap
, comment
);
227 #ifdef ASM_OUTPUT_DWARF_PCREL
228 ASM_OUTPUT_DWARF_PCREL (asm_out_file
, size
, label
);
230 dw2_assemble_integer (size
,
231 gen_rtx_MINUS (Pmode
,
232 gen_rtx_SYMBOL_REF (Pmode
, label
),
236 if (flag_debug_asm
&& comment
)
238 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
239 vfprintf (asm_out_file
, comment
, ap
);
241 fputc ('\n', asm_out_file
);
247 /* Output an absolute reference to a label. */
250 dw2_asm_output_addr (int size
, const char *label
,
251 const char *comment
, ...)
255 va_start (ap
, comment
);
257 dw2_assemble_integer (size
, gen_rtx_SYMBOL_REF (Pmode
, label
));
259 if (flag_debug_asm
&& comment
)
261 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
262 vfprintf (asm_out_file
, comment
, ap
);
264 fputc ('\n', asm_out_file
);
269 /* Similar, but use an RTX expression instead of a text label. */
272 dw2_asm_output_addr_rtx (int size
, rtx addr
,
273 const char *comment
, ...)
277 va_start (ap
, comment
);
279 dw2_assemble_integer (size
, addr
);
281 if (flag_debug_asm
&& comment
)
283 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
284 vfprintf (asm_out_file
, comment
, ap
);
286 fputc ('\n', asm_out_file
);
291 /* Output the first ORIG_LEN characters of STR as a string.
292 If ORIG_LEN is equal to -1, ignore this parameter and output
293 the entire STR instead.
294 If COMMENT is not NULL and comments in the debug information
295 have been requested by the user, append the given COMMENT
296 to the generated output. */
299 dw2_asm_output_nstring (const char *str
, size_t orig_len
,
300 const char *comment
, ...)
305 va_start (ap
, comment
);
309 if (len
== (size_t) -1)
312 if (flag_debug_asm
&& comment
)
314 fputs ("\t.ascii \"", asm_out_file
);
315 for (i
= 0; i
< len
; i
++)
318 if (c
== '\"' || c
== '\\')
319 fputc ('\\', asm_out_file
);
321 fputc (c
, asm_out_file
);
323 fprintf (asm_out_file
, "\\%o", c
);
325 fprintf (asm_out_file
, "\\0\"\t%s ", ASM_COMMENT_START
);
326 vfprintf (asm_out_file
, comment
, ap
);
327 fputc ('\n', asm_out_file
);
331 /* If an explicit length was given, we can't assume there
332 is a null termination in the string buffer. */
333 if (orig_len
== (size_t) -1)
335 ASM_OUTPUT_ASCII (asm_out_file
, str
, len
);
336 if (orig_len
!= (size_t) -1)
337 assemble_integer (const0_rtx
, 1, BITS_PER_UNIT
, 1);
344 /* Return the size of an unsigned LEB128 quantity. */
347 size_of_uleb128 (unsigned HOST_WIDE_INT value
)
361 /* Return the size of a signed LEB128 quantity. */
364 size_of_sleb128 (HOST_WIDE_INT value
)
370 byte
= (value
& 0x7f);
374 while (!((value
== 0 && (byte
& 0x40) == 0)
375 || (value
== -1 && (byte
& 0x40) != 0)));
380 /* Given an encoding, return the number of bytes the format occupies.
381 This is only defined for fixed-size encodings, and so does not
385 size_of_encoded_value (int encoding
)
387 if (encoding
== DW_EH_PE_omit
)
390 switch (encoding
& 0x07)
392 case DW_EH_PE_absptr
:
393 return POINTER_SIZE
/ BITS_PER_UNIT
;
394 case DW_EH_PE_udata2
:
396 case DW_EH_PE_udata4
:
398 case DW_EH_PE_udata8
:
405 /* Yield a name for a given pointer encoding. */
408 eh_data_format_name (int format
)
410 #if HAVE_DESIGNATED_INITIALIZERS
411 #define S(p, v) [p] = v,
413 #define S(p, v) case p: return v;
416 #if HAVE_DESIGNATED_INITIALIZERS
417 __extension__
static const char * const format_names
[256] = {
422 S(DW_EH_PE_absptr
, "absolute")
423 S(DW_EH_PE_omit
, "omit")
424 S(DW_EH_PE_aligned
, "aligned absolute")
426 S(DW_EH_PE_uleb128
, "uleb128")
427 S(DW_EH_PE_udata2
, "udata2")
428 S(DW_EH_PE_udata4
, "udata4")
429 S(DW_EH_PE_udata8
, "udata8")
430 S(DW_EH_PE_sleb128
, "sleb128")
431 S(DW_EH_PE_sdata2
, "sdata2")
432 S(DW_EH_PE_sdata4
, "sdata4")
433 S(DW_EH_PE_sdata8
, "sdata8")
435 S(DW_EH_PE_absptr
| DW_EH_PE_pcrel
, "pcrel")
436 S(DW_EH_PE_uleb128
| DW_EH_PE_pcrel
, "pcrel uleb128")
437 S(DW_EH_PE_udata2
| DW_EH_PE_pcrel
, "pcrel udata2")
438 S(DW_EH_PE_udata4
| DW_EH_PE_pcrel
, "pcrel udata4")
439 S(DW_EH_PE_udata8
| DW_EH_PE_pcrel
, "pcrel udata8")
440 S(DW_EH_PE_sleb128
| DW_EH_PE_pcrel
, "pcrel sleb128")
441 S(DW_EH_PE_sdata2
| DW_EH_PE_pcrel
, "pcrel sdata2")
442 S(DW_EH_PE_sdata4
| DW_EH_PE_pcrel
, "pcrel sdata4")
443 S(DW_EH_PE_sdata8
| DW_EH_PE_pcrel
, "pcrel sdata8")
445 S(DW_EH_PE_absptr
| DW_EH_PE_textrel
, "textrel")
446 S(DW_EH_PE_uleb128
| DW_EH_PE_textrel
, "textrel uleb128")
447 S(DW_EH_PE_udata2
| DW_EH_PE_textrel
, "textrel udata2")
448 S(DW_EH_PE_udata4
| DW_EH_PE_textrel
, "textrel udata4")
449 S(DW_EH_PE_udata8
| DW_EH_PE_textrel
, "textrel udata8")
450 S(DW_EH_PE_sleb128
| DW_EH_PE_textrel
, "textrel sleb128")
451 S(DW_EH_PE_sdata2
| DW_EH_PE_textrel
, "textrel sdata2")
452 S(DW_EH_PE_sdata4
| DW_EH_PE_textrel
, "textrel sdata4")
453 S(DW_EH_PE_sdata8
| DW_EH_PE_textrel
, "textrel sdata8")
455 S(DW_EH_PE_absptr
| DW_EH_PE_datarel
, "datarel")
456 S(DW_EH_PE_uleb128
| DW_EH_PE_datarel
, "datarel uleb128")
457 S(DW_EH_PE_udata2
| DW_EH_PE_datarel
, "datarel udata2")
458 S(DW_EH_PE_udata4
| DW_EH_PE_datarel
, "datarel udata4")
459 S(DW_EH_PE_udata8
| DW_EH_PE_datarel
, "datarel udata8")
460 S(DW_EH_PE_sleb128
| DW_EH_PE_datarel
, "datarel sleb128")
461 S(DW_EH_PE_sdata2
| DW_EH_PE_datarel
, "datarel sdata2")
462 S(DW_EH_PE_sdata4
| DW_EH_PE_datarel
, "datarel sdata4")
463 S(DW_EH_PE_sdata8
| DW_EH_PE_datarel
, "datarel sdata8")
465 S(DW_EH_PE_absptr
| DW_EH_PE_funcrel
, "funcrel")
466 S(DW_EH_PE_uleb128
| DW_EH_PE_funcrel
, "funcrel uleb128")
467 S(DW_EH_PE_udata2
| DW_EH_PE_funcrel
, "funcrel udata2")
468 S(DW_EH_PE_udata4
| DW_EH_PE_funcrel
, "funcrel udata4")
469 S(DW_EH_PE_udata8
| DW_EH_PE_funcrel
, "funcrel udata8")
470 S(DW_EH_PE_sleb128
| DW_EH_PE_funcrel
, "funcrel sleb128")
471 S(DW_EH_PE_sdata2
| DW_EH_PE_funcrel
, "funcrel sdata2")
472 S(DW_EH_PE_sdata4
| DW_EH_PE_funcrel
, "funcrel sdata4")
473 S(DW_EH_PE_sdata8
| DW_EH_PE_funcrel
, "funcrel sdata8")
475 S(DW_EH_PE_indirect
| DW_EH_PE_absptr
, "indirect absolute")
477 S(DW_EH_PE_indirect
| DW_EH_PE_absptr
| DW_EH_PE_pcrel
,
479 S(DW_EH_PE_indirect
| DW_EH_PE_uleb128
| DW_EH_PE_pcrel
,
480 "indirect pcrel uleb128")
481 S(DW_EH_PE_indirect
| DW_EH_PE_udata2
| DW_EH_PE_pcrel
,
482 "indirect pcrel udata2")
483 S(DW_EH_PE_indirect
| DW_EH_PE_udata4
| DW_EH_PE_pcrel
,
484 "indirect pcrel udata4")
485 S(DW_EH_PE_indirect
| DW_EH_PE_udata8
| DW_EH_PE_pcrel
,
486 "indirect pcrel udata8")
487 S(DW_EH_PE_indirect
| DW_EH_PE_sleb128
| DW_EH_PE_pcrel
,
488 "indirect pcrel sleb128")
489 S(DW_EH_PE_indirect
| DW_EH_PE_sdata2
| DW_EH_PE_pcrel
,
490 "indirect pcrel sdata2")
491 S(DW_EH_PE_indirect
| DW_EH_PE_sdata4
| DW_EH_PE_pcrel
,
492 "indirect pcrel sdata4")
493 S(DW_EH_PE_indirect
| DW_EH_PE_sdata8
| DW_EH_PE_pcrel
,
494 "indirect pcrel sdata8")
496 S(DW_EH_PE_indirect
| DW_EH_PE_absptr
| DW_EH_PE_textrel
,
498 S(DW_EH_PE_indirect
| DW_EH_PE_uleb128
| DW_EH_PE_textrel
,
499 "indirect textrel uleb128")
500 S(DW_EH_PE_indirect
| DW_EH_PE_udata2
| DW_EH_PE_textrel
,
501 "indirect textrel udata2")
502 S(DW_EH_PE_indirect
| DW_EH_PE_udata4
| DW_EH_PE_textrel
,
503 "indirect textrel udata4")
504 S(DW_EH_PE_indirect
| DW_EH_PE_udata8
| DW_EH_PE_textrel
,
505 "indirect textrel udata8")
506 S(DW_EH_PE_indirect
| DW_EH_PE_sleb128
| DW_EH_PE_textrel
,
507 "indirect textrel sleb128")
508 S(DW_EH_PE_indirect
| DW_EH_PE_sdata2
| DW_EH_PE_textrel
,
509 "indirect textrel sdata2")
510 S(DW_EH_PE_indirect
| DW_EH_PE_sdata4
| DW_EH_PE_textrel
,
511 "indirect textrel sdata4")
512 S(DW_EH_PE_indirect
| DW_EH_PE_sdata8
| DW_EH_PE_textrel
,
513 "indirect textrel sdata8")
515 S(DW_EH_PE_indirect
| DW_EH_PE_absptr
| DW_EH_PE_datarel
,
517 S(DW_EH_PE_indirect
| DW_EH_PE_uleb128
| DW_EH_PE_datarel
,
518 "indirect datarel uleb128")
519 S(DW_EH_PE_indirect
| DW_EH_PE_udata2
| DW_EH_PE_datarel
,
520 "indirect datarel udata2")
521 S(DW_EH_PE_indirect
| DW_EH_PE_udata4
| DW_EH_PE_datarel
,
522 "indirect datarel udata4")
523 S(DW_EH_PE_indirect
| DW_EH_PE_udata8
| DW_EH_PE_datarel
,
524 "indirect datarel udata8")
525 S(DW_EH_PE_indirect
| DW_EH_PE_sleb128
| DW_EH_PE_datarel
,
526 "indirect datarel sleb128")
527 S(DW_EH_PE_indirect
| DW_EH_PE_sdata2
| DW_EH_PE_datarel
,
528 "indirect datarel sdata2")
529 S(DW_EH_PE_indirect
| DW_EH_PE_sdata4
| DW_EH_PE_datarel
,
530 "indirect datarel sdata4")
531 S(DW_EH_PE_indirect
| DW_EH_PE_sdata8
| DW_EH_PE_datarel
,
532 "indirect datarel sdata8")
534 S(DW_EH_PE_indirect
| DW_EH_PE_absptr
| DW_EH_PE_funcrel
,
536 S(DW_EH_PE_indirect
| DW_EH_PE_uleb128
| DW_EH_PE_funcrel
,
537 "indirect funcrel uleb128")
538 S(DW_EH_PE_indirect
| DW_EH_PE_udata2
| DW_EH_PE_funcrel
,
539 "indirect funcrel udata2")
540 S(DW_EH_PE_indirect
| DW_EH_PE_udata4
| DW_EH_PE_funcrel
,
541 "indirect funcrel udata4")
542 S(DW_EH_PE_indirect
| DW_EH_PE_udata8
| DW_EH_PE_funcrel
,
543 "indirect funcrel udata8")
544 S(DW_EH_PE_indirect
| DW_EH_PE_sleb128
| DW_EH_PE_funcrel
,
545 "indirect funcrel sleb128")
546 S(DW_EH_PE_indirect
| DW_EH_PE_sdata2
| DW_EH_PE_funcrel
,
547 "indirect funcrel sdata2")
548 S(DW_EH_PE_indirect
| DW_EH_PE_sdata4
| DW_EH_PE_funcrel
,
549 "indirect funcrel sdata4")
550 S(DW_EH_PE_indirect
| DW_EH_PE_sdata8
| DW_EH_PE_funcrel
,
551 "indirect funcrel sdata8")
553 #if HAVE_DESIGNATED_INITIALIZERS
556 gcc_assert (format
>= 0 && format
< 0x100 && format_names
[format
]);
558 return format_names
[format
];
565 /* Output an unsigned LEB128 quantity, but only the byte values. */
568 dw2_asm_output_data_uleb128_raw (unsigned HOST_WIDE_INT value
)
572 int byte
= (value
& 0x7f);
575 /* More bytes to follow. */
578 fprintf (asm_out_file
, "%#x", byte
);
581 fputc (',', asm_out_file
);
585 /* Output an unsigned LEB128 quantity. */
588 dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value
,
589 const char *comment
, ...)
593 va_start (ap
, comment
);
595 #ifdef HAVE_AS_LEB128
596 fputs ("\t.uleb128 ", asm_out_file
);
597 fprint_whex (asm_out_file
, value
);
599 if (flag_debug_asm
&& comment
)
601 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
602 vfprintf (asm_out_file
, comment
, ap
);
606 unsigned HOST_WIDE_INT work
= value
;
607 const char *byte_op
= targetm
.asm_out
.byte_op
;
610 fputs (byte_op
, asm_out_file
);
613 int byte
= (work
& 0x7f);
616 /* More bytes to follow. */
621 fprintf (asm_out_file
, "%#x", byte
);
623 fputc (',', asm_out_file
);
626 assemble_integer (GEN_INT (byte
), 1, BITS_PER_UNIT
, 1);
632 fprintf (asm_out_file
, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX
,
633 ASM_COMMENT_START
, value
);
636 fputs ("; ", asm_out_file
);
637 vfprintf (asm_out_file
, comment
, ap
);
642 putc ('\n', asm_out_file
);
647 /* Output an signed LEB128 quantity, but only the byte values. */
650 dw2_asm_output_data_sleb128_raw (HOST_WIDE_INT value
)
656 byte
= (value
& 0x7f);
658 more
= !((value
== 0 && (byte
& 0x40) == 0)
659 || (value
== -1 && (byte
& 0x40) != 0));
663 fprintf (asm_out_file
, "%#x", byte
);
666 fputc (',', asm_out_file
);
670 /* Output a signed LEB128 quantity. */
673 dw2_asm_output_data_sleb128 (HOST_WIDE_INT value
,
674 const char *comment
, ...)
678 va_start (ap
, comment
);
680 #ifdef HAVE_AS_LEB128
681 fprintf (asm_out_file
, "\t.sleb128 " HOST_WIDE_INT_PRINT_DEC
, value
);
683 if (flag_debug_asm
&& comment
)
685 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
686 vfprintf (asm_out_file
, comment
, ap
);
690 HOST_WIDE_INT work
= value
;
692 const char *byte_op
= targetm
.asm_out
.byte_op
;
695 fputs (byte_op
, asm_out_file
);
698 byte
= (work
& 0x7f);
699 /* arithmetic shift */
701 more
= !((work
== 0 && (byte
& 0x40) == 0)
702 || (work
== -1 && (byte
& 0x40) != 0));
708 fprintf (asm_out_file
, "%#x", byte
);
710 fputc (',', asm_out_file
);
713 assemble_integer (GEN_INT (byte
), 1, BITS_PER_UNIT
, 1);
719 fprintf (asm_out_file
, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC
,
720 ASM_COMMENT_START
, value
);
723 fputs ("; ", asm_out_file
);
724 vfprintf (asm_out_file
, comment
, ap
);
729 fputc ('\n', asm_out_file
);
735 dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED
,
736 const char *lab2 ATTRIBUTE_UNUSED
,
737 const char *comment
, ...)
741 va_start (ap
, comment
);
743 #ifdef HAVE_AS_LEB128
744 fputs ("\t.uleb128 ", asm_out_file
);
745 assemble_name (asm_out_file
, lab1
);
746 putc ('-', asm_out_file
);
747 assemble_name (asm_out_file
, lab2
);
752 if (flag_debug_asm
&& comment
)
754 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
755 vfprintf (asm_out_file
, comment
, ap
);
757 fputc ('\n', asm_out_file
);
765 dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED
,
766 const char *lab2 ATTRIBUTE_UNUSED
,
767 const char *comment
, ...)
771 va_start (ap
, comment
);
773 #ifdef HAVE_AS_LEB128
774 fputs ("\t.sleb128 ", asm_out_file
);
775 assemble_name (asm_out_file
, lab1
);
776 putc ('-', asm_out_file
);
777 assemble_name (asm_out_file
, lab2
);
782 if (flag_debug_asm
&& comment
)
784 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
785 vfprintf (asm_out_file
, comment
, ap
);
787 fputc ('\n', asm_out_file
);
793 static int dw2_output_indirect_constant_1 (splay_tree_node
, void *);
795 static GTY((param1_is (char *), param2_is (tree
))) splay_tree indirect_pool
;
797 static GTY(()) int dw2_const_labelno
;
799 #if defined(HAVE_GAS_HIDDEN)
800 # define USE_LINKONCE_INDIRECT (SUPPORTS_ONE_ONLY)
802 # define USE_LINKONCE_INDIRECT 0
805 /* Comparison function for a splay tree in which the keys are strings.
806 K1 and K2 have the dynamic type "const char *". Returns <0, 0, or
807 >0 to indicate whether K1 is less than, equal to, or greater than
811 splay_tree_compare_strings (splay_tree_key k1
, splay_tree_key k2
)
813 const char *s1
= (const char *)k1
;
814 const char *s2
= (const char *)k2
;
820 ret
= strcmp (s1
, s2
);
822 /* The strings are always those from IDENTIFIER_NODEs, and,
823 therefore, we should never have two copies of the same
830 /* Put X, a SYMBOL_REF, in memory. Return a SYMBOL_REF to the allocated
831 memory. Differs from force_const_mem in that a single pool is used for
832 the entire unit of translation, and the memory is not guaranteed to be
833 "near" the function in any interesting sense. IS_PUBLIC controls whether
834 the symbol can be shared across the entire application (or DSO). */
837 dw2_force_const_mem (rtx x
, bool is_public
)
839 splay_tree_node node
;
844 /* We use strcmp, rather than just comparing pointers, so that the
845 sort order will not depend on the host system. */
846 indirect_pool
= splay_tree_new_ggc (splay_tree_compare_strings
,
847 ggc_alloc_splay_tree_str_tree_node_splay_tree_s
,
848 ggc_alloc_splay_tree_str_tree_node_splay_tree_node_s
);
850 gcc_assert (GET_CODE (x
) == SYMBOL_REF
);
853 node
= splay_tree_lookup (indirect_pool
, (splay_tree_key
) key
);
855 decl_id
= (tree
) node
->value
;
859 const char *str
= targetm
.strip_name_encoding (key
);
861 if (is_public
&& USE_LINKONCE_INDIRECT
)
863 char *ref_name
= XALLOCAVEC (char, strlen (str
) + sizeof "DW.ref.");
865 sprintf (ref_name
, "DW.ref.%s", str
);
866 gcc_assert (!maybe_get_identifier (ref_name
));
867 decl_id
= get_identifier (ref_name
);
868 TREE_PUBLIC (decl_id
) = 1;
874 ASM_GENERATE_INTERNAL_LABEL (label
, "LDFCM", dw2_const_labelno
);
876 gcc_assert (!maybe_get_identifier (label
));
877 decl_id
= get_identifier (label
);
880 id
= maybe_get_identifier (str
);
882 TREE_SYMBOL_REFERENCED (id
) = 1;
884 splay_tree_insert (indirect_pool
, (splay_tree_key
) key
,
885 (splay_tree_value
) decl_id
);
888 return gen_rtx_SYMBOL_REF (Pmode
, IDENTIFIER_POINTER (decl_id
));
891 /* A helper function for dw2_output_indirect_constants called through
892 splay_tree_foreach. Emit one queued constant to memory. */
895 dw2_output_indirect_constant_1 (splay_tree_node node
,
896 void *data ATTRIBUTE_UNUSED
)
902 sym
= (const char *) node
->key
;
903 id
= (tree
) node
->value
;
905 decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, id
, ptr_type_node
);
906 SET_DECL_ASSEMBLER_NAME (decl
, id
);
907 DECL_ARTIFICIAL (decl
) = 1;
908 DECL_IGNORED_P (decl
) = 1;
909 DECL_INITIAL (decl
) = decl
;
910 TREE_READONLY (decl
) = 1;
911 TREE_STATIC (decl
) = 1;
913 if (TREE_PUBLIC (id
))
915 TREE_PUBLIC (decl
) = 1;
916 make_decl_one_only (decl
, DECL_ASSEMBLER_NAME (decl
));
917 if (USE_LINKONCE_INDIRECT
)
918 DECL_VISIBILITY (decl
) = VISIBILITY_HIDDEN
;
921 sym_ref
= gen_rtx_SYMBOL_REF (Pmode
, sym
);
922 assemble_variable (decl
, 1, 1, 1);
923 assemble_integer (sym_ref
, POINTER_SIZE
/ BITS_PER_UNIT
, POINTER_SIZE
, 1);
928 /* Emit the constants queued through dw2_force_const_mem. */
931 dw2_output_indirect_constants (void)
934 splay_tree_foreach (indirect_pool
, dw2_output_indirect_constant_1
, NULL
);
937 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.
938 If PUBLIC is set and the encoding is DW_EH_PE_indirect, the indirect
939 reference is shared across the entire application (or DSO). */
942 dw2_asm_output_encoded_addr_rtx (int encoding
, rtx addr
, bool is_public
,
943 const char *comment
, ...)
948 va_start (ap
, comment
);
950 size
= size_of_encoded_value (encoding
);
952 if (encoding
== DW_EH_PE_aligned
)
954 assemble_align (POINTER_SIZE
);
955 assemble_integer (addr
, size
, POINTER_SIZE
, 1);
960 /* NULL is _always_ represented as a plain zero, as is 1 for Ada's
962 if (addr
== const0_rtx
|| addr
== const1_rtx
)
963 assemble_integer (addr
, size
, BITS_PER_UNIT
, 1);
967 /* Allow the target first crack at emitting this. Some of the
968 special relocations require special directives instead of
969 just ".4byte" or whatever. */
970 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
971 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file
, encoding
, size
,
975 /* Indirection is used to get dynamic relocations out of a
976 read-only section. */
977 if (encoding
& DW_EH_PE_indirect
)
979 /* It is very tempting to use force_const_mem so that we share data
980 with the normal constant pool. However, we've already emitted
981 the constant pool for this function. Moreover, we'd like to
982 share these constants across the entire unit of translation and
983 even, if possible, across the entire application (or DSO). */
984 addr
= dw2_force_const_mem (addr
, is_public
);
985 encoding
&= ~DW_EH_PE_indirect
;
989 switch (encoding
& 0xF0)
991 case DW_EH_PE_absptr
:
992 dw2_assemble_integer (size
, addr
);
996 gcc_assert (GET_CODE (addr
) == SYMBOL_REF
);
997 #ifdef ASM_OUTPUT_DWARF_PCREL
998 ASM_OUTPUT_DWARF_PCREL (asm_out_file
, size
, XSTR (addr
, 0));
1000 dw2_assemble_integer (size
, gen_rtx_MINUS (Pmode
, addr
, pc_rtx
));
1005 /* Other encodings should have been handled by
1006 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
1010 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
1015 if (flag_debug_asm
&& comment
)
1017 fprintf (asm_out_file
, "\t%s ", ASM_COMMENT_START
);
1018 vfprintf (asm_out_file
, comment
, ap
);
1020 fputc ('\n', asm_out_file
);
1025 #include "gt-dwarf2asm.h"