Daily bump.
[official-gcc.git] / gcc / dwarf2asm.c
blob7cd997a8948faafad5989dddc9dc7e10d4d18006
1 /* Dwarf2 assembler output helper routines.
2 Copyright (C) 2001-2015 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 "tm.h"
25 #include "flags.h"
26 #include "alias.h"
27 #include "symtab.h"
28 #include "tree.h"
29 #include "stringpool.h"
30 #include "varasm.h"
31 #include "rtl.h"
32 #include "output.h"
33 #include "target.h"
34 #include "dwarf2asm.h"
35 #include "dwarf2.h"
36 #include "tm_p.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. */
42 void
43 dw2_assemble_integer (int size, rtx x)
45 const char *op = integer_asm_op (size, FALSE);
47 if (op)
49 fputs (op, asm_out_file);
50 if (CONST_INT_P (x))
51 fprint_whex (asm_out_file, (unsigned HOST_WIDE_INT) INTVAL (x));
52 else
53 output_addr_const (asm_out_file, x);
55 else
56 assemble_integer (x, size, BITS_PER_UNIT, 1);
60 /* Output a value of a given size in target byte order. */
62 void
63 dw2_asm_output_data_raw (int size, unsigned HOST_WIDE_INT value)
65 unsigned char bytes[8];
66 int i;
68 for (i = 0; i < 8; ++i)
70 bytes[i] = value & 0xff;
71 value >>= 8;
74 if (BYTES_BIG_ENDIAN)
76 for (i = size - 1; i > 0; --i)
77 fprintf (asm_out_file, "%#x,", bytes[i]);
78 fprintf (asm_out_file, "%#x", bytes[0]);
80 else
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. */
90 void
91 dw2_asm_output_data (int size, unsigned HOST_WIDE_INT value,
92 const char *comment, ...)
94 va_list ap;
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));
102 if (op)
104 fputs (op, asm_out_file);
105 fprint_whex (asm_out_file, value);
107 else
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);
117 va_end (ap);
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. */
126 void
127 dw2_asm_output_delta (int size, const char *lab1, const char *lab2,
128 const char *comment, ...)
130 va_list ap;
132 va_start (ap, comment);
134 #ifdef ASM_OUTPUT_DWARF_DELTA
135 ASM_OUTPUT_DWARF_DELTA (asm_out_file, size, lab1, lab2);
136 #else
137 dw2_assemble_integer (size,
138 gen_rtx_MINUS (Pmode,
139 gen_rtx_SYMBOL_REF (Pmode, lab1),
140 gen_rtx_SYMBOL_REF (Pmode, lab2)));
141 #endif
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);
149 va_end (ap);
152 #ifdef ASM_OUTPUT_DWARF_VMS_DELTA
153 /* Output the difference between two symbols in instruction units
154 in a given size. */
156 void
157 dw2_asm_output_vms_delta (int size ATTRIBUTE_UNUSED,
158 const char *lab1, const char *lab2,
159 const char *comment, ...)
161 va_list ap;
163 va_start (ap, comment);
165 ASM_OUTPUT_DWARF_VMS_DELTA (asm_out_file, size, lab1, lab2);
166 if (flag_debug_asm && comment)
168 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
169 vfprintf (asm_out_file, comment, ap);
171 fputc ('\n', asm_out_file);
173 va_end (ap);
175 #endif
177 /* Output a section-relative reference to a LABEL, which was placed in
178 BASE. In general this can only be done for debugging symbols.
179 E.g. on most targets with the GNU linker, this is accomplished with
180 a direct reference and the knowledge that the debugging section
181 will be placed at VMA 0. Some targets have special relocations for
182 this that we must use. */
184 void
185 dw2_asm_output_offset (int size, const char *label,
186 section *base ATTRIBUTE_UNUSED,
187 const char *comment, ...)
189 va_list ap;
191 va_start (ap, comment);
193 #ifdef ASM_OUTPUT_DWARF_OFFSET
194 ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label, base);
195 #else
196 dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
197 #endif
199 if (flag_debug_asm && comment)
201 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
202 vfprintf (asm_out_file, comment, ap);
204 fputc ('\n', asm_out_file);
206 va_end (ap);
209 #if 0
211 /* Output a self-relative reference to a label, possibly in a
212 different section or object file. */
214 void
215 dw2_asm_output_pcrel (int size ATTRIBUTE_UNUSED,
216 const char *label ATTRIBUTE_UNUSED,
217 const char *comment, ...)
219 va_list ap;
221 va_start (ap, comment);
223 #ifdef ASM_OUTPUT_DWARF_PCREL
224 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label);
225 #else
226 dw2_assemble_integer (size,
227 gen_rtx_MINUS (Pmode,
228 gen_rtx_SYMBOL_REF (Pmode, label),
229 pc_rtx));
230 #endif
232 if (flag_debug_asm && comment)
234 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
235 vfprintf (asm_out_file, comment, ap);
237 fputc ('\n', asm_out_file);
239 va_end (ap);
241 #endif /* 0 */
243 /* Output an absolute reference to a label. */
245 void
246 dw2_asm_output_addr (int size, const char *label,
247 const char *comment, ...)
249 va_list ap;
251 va_start (ap, comment);
253 dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
255 if (flag_debug_asm && comment)
257 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
258 vfprintf (asm_out_file, comment, ap);
260 fputc ('\n', asm_out_file);
262 va_end (ap);
265 /* Similar, but use an RTX expression instead of a text label. */
267 void
268 dw2_asm_output_addr_rtx (int size, rtx addr,
269 const char *comment, ...)
271 va_list ap;
273 va_start (ap, comment);
275 dw2_assemble_integer (size, addr);
277 if (flag_debug_asm && comment)
279 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
280 vfprintf (asm_out_file, comment, ap);
282 fputc ('\n', asm_out_file);
284 va_end (ap);
287 /* Output the first ORIG_LEN characters of STR as a string.
288 If ORIG_LEN is equal to -1, ignore this parameter and output
289 the entire STR instead.
290 If COMMENT is not NULL and comments in the debug information
291 have been requested by the user, append the given COMMENT
292 to the generated output. */
294 void
295 dw2_asm_output_nstring (const char *str, size_t orig_len,
296 const char *comment, ...)
298 size_t i, len;
299 va_list ap;
301 va_start (ap, comment);
303 len = orig_len;
305 if (len == (size_t) -1)
306 len = strlen (str);
308 if (flag_debug_asm && comment)
310 fputs ("\t.ascii \"", asm_out_file);
311 for (i = 0; i < len; i++)
313 int c = str[i];
314 if (c == '\"' || c == '\\')
315 fputc ('\\', asm_out_file);
316 if (ISPRINT (c))
317 fputc (c, asm_out_file);
318 else
319 fprintf (asm_out_file, "\\%o", c);
321 fprintf (asm_out_file, "\\0\"\t%s ", ASM_COMMENT_START);
322 vfprintf (asm_out_file, comment, ap);
323 fputc ('\n', asm_out_file);
325 else
327 /* If an explicit length was given, we can't assume there
328 is a null termination in the string buffer. */
329 if (orig_len == (size_t) -1)
330 len += 1;
331 ASM_OUTPUT_ASCII (asm_out_file, str, len);
332 if (orig_len != (size_t) -1)
333 assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1);
336 va_end (ap);
340 /* Return the size of an unsigned LEB128 quantity. */
343 size_of_uleb128 (unsigned HOST_WIDE_INT value)
345 int size = 0;
349 value >>= 7;
350 size += 1;
352 while (value != 0);
354 return size;
357 /* Return the size of a signed LEB128 quantity. */
360 size_of_sleb128 (HOST_WIDE_INT value)
362 int size = 0, byte;
366 byte = (value & 0x7f);
367 value >>= 7;
368 size += 1;
370 while (!((value == 0 && (byte & 0x40) == 0)
371 || (value == -1 && (byte & 0x40) != 0)));
373 return size;
376 /* Given an encoding, return the number of bytes the format occupies.
377 This is only defined for fixed-size encodings, and so does not
378 include leb128. */
381 size_of_encoded_value (int encoding)
383 if (encoding == DW_EH_PE_omit)
384 return 0;
386 switch (encoding & 0x07)
388 case DW_EH_PE_absptr:
389 return POINTER_SIZE_UNITS;
390 case DW_EH_PE_udata2:
391 return 2;
392 case DW_EH_PE_udata4:
393 return 4;
394 case DW_EH_PE_udata8:
395 return 8;
396 default:
397 gcc_unreachable ();
401 /* Yield a name for a given pointer encoding. */
403 const char *
404 eh_data_format_name (int format)
406 #if HAVE_DESIGNATED_INITIALIZERS
407 #define S(p, v) [p] = v,
408 #else
409 #define S(p, v) case p: return v;
410 #endif
412 #if HAVE_DESIGNATED_INITIALIZERS
413 __extension__ static const char * const format_names[256] = {
414 #else
415 switch (format) {
416 #endif
418 S(DW_EH_PE_absptr, "absolute")
419 S(DW_EH_PE_omit, "omit")
420 S(DW_EH_PE_aligned, "aligned absolute")
422 S(DW_EH_PE_uleb128, "uleb128")
423 S(DW_EH_PE_udata2, "udata2")
424 S(DW_EH_PE_udata4, "udata4")
425 S(DW_EH_PE_udata8, "udata8")
426 S(DW_EH_PE_sleb128, "sleb128")
427 S(DW_EH_PE_sdata2, "sdata2")
428 S(DW_EH_PE_sdata4, "sdata4")
429 S(DW_EH_PE_sdata8, "sdata8")
431 S(DW_EH_PE_absptr | DW_EH_PE_pcrel, "pcrel")
432 S(DW_EH_PE_uleb128 | DW_EH_PE_pcrel, "pcrel uleb128")
433 S(DW_EH_PE_udata2 | DW_EH_PE_pcrel, "pcrel udata2")
434 S(DW_EH_PE_udata4 | DW_EH_PE_pcrel, "pcrel udata4")
435 S(DW_EH_PE_udata8 | DW_EH_PE_pcrel, "pcrel udata8")
436 S(DW_EH_PE_sleb128 | DW_EH_PE_pcrel, "pcrel sleb128")
437 S(DW_EH_PE_sdata2 | DW_EH_PE_pcrel, "pcrel sdata2")
438 S(DW_EH_PE_sdata4 | DW_EH_PE_pcrel, "pcrel sdata4")
439 S(DW_EH_PE_sdata8 | DW_EH_PE_pcrel, "pcrel sdata8")
441 S(DW_EH_PE_absptr | DW_EH_PE_textrel, "textrel")
442 S(DW_EH_PE_uleb128 | DW_EH_PE_textrel, "textrel uleb128")
443 S(DW_EH_PE_udata2 | DW_EH_PE_textrel, "textrel udata2")
444 S(DW_EH_PE_udata4 | DW_EH_PE_textrel, "textrel udata4")
445 S(DW_EH_PE_udata8 | DW_EH_PE_textrel, "textrel udata8")
446 S(DW_EH_PE_sleb128 | DW_EH_PE_textrel, "textrel sleb128")
447 S(DW_EH_PE_sdata2 | DW_EH_PE_textrel, "textrel sdata2")
448 S(DW_EH_PE_sdata4 | DW_EH_PE_textrel, "textrel sdata4")
449 S(DW_EH_PE_sdata8 | DW_EH_PE_textrel, "textrel sdata8")
451 S(DW_EH_PE_absptr | DW_EH_PE_datarel, "datarel")
452 S(DW_EH_PE_uleb128 | DW_EH_PE_datarel, "datarel uleb128")
453 S(DW_EH_PE_udata2 | DW_EH_PE_datarel, "datarel udata2")
454 S(DW_EH_PE_udata4 | DW_EH_PE_datarel, "datarel udata4")
455 S(DW_EH_PE_udata8 | DW_EH_PE_datarel, "datarel udata8")
456 S(DW_EH_PE_sleb128 | DW_EH_PE_datarel, "datarel sleb128")
457 S(DW_EH_PE_sdata2 | DW_EH_PE_datarel, "datarel sdata2")
458 S(DW_EH_PE_sdata4 | DW_EH_PE_datarel, "datarel sdata4")
459 S(DW_EH_PE_sdata8 | DW_EH_PE_datarel, "datarel sdata8")
461 S(DW_EH_PE_absptr | DW_EH_PE_funcrel, "funcrel")
462 S(DW_EH_PE_uleb128 | DW_EH_PE_funcrel, "funcrel uleb128")
463 S(DW_EH_PE_udata2 | DW_EH_PE_funcrel, "funcrel udata2")
464 S(DW_EH_PE_udata4 | DW_EH_PE_funcrel, "funcrel udata4")
465 S(DW_EH_PE_udata8 | DW_EH_PE_funcrel, "funcrel udata8")
466 S(DW_EH_PE_sleb128 | DW_EH_PE_funcrel, "funcrel sleb128")
467 S(DW_EH_PE_sdata2 | DW_EH_PE_funcrel, "funcrel sdata2")
468 S(DW_EH_PE_sdata4 | DW_EH_PE_funcrel, "funcrel sdata4")
469 S(DW_EH_PE_sdata8 | DW_EH_PE_funcrel, "funcrel sdata8")
471 S(DW_EH_PE_indirect | DW_EH_PE_absptr, "indirect absolute")
473 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel,
474 "indirect pcrel")
475 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel,
476 "indirect pcrel uleb128")
477 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_pcrel,
478 "indirect pcrel udata2")
479 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_pcrel,
480 "indirect pcrel udata4")
481 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_pcrel,
482 "indirect pcrel udata8")
483 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_pcrel,
484 "indirect pcrel sleb128")
485 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_pcrel,
486 "indirect pcrel sdata2")
487 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_pcrel,
488 "indirect pcrel sdata4")
489 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_pcrel,
490 "indirect pcrel sdata8")
492 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_textrel,
493 "indirect textrel")
494 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_textrel,
495 "indirect textrel uleb128")
496 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_textrel,
497 "indirect textrel udata2")
498 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_textrel,
499 "indirect textrel udata4")
500 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_textrel,
501 "indirect textrel udata8")
502 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_textrel,
503 "indirect textrel sleb128")
504 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_textrel,
505 "indirect textrel sdata2")
506 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_textrel,
507 "indirect textrel sdata4")
508 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_textrel,
509 "indirect textrel sdata8")
511 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_datarel,
512 "indirect datarel")
513 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_datarel,
514 "indirect datarel uleb128")
515 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_datarel,
516 "indirect datarel udata2")
517 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_datarel,
518 "indirect datarel udata4")
519 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_datarel,
520 "indirect datarel udata8")
521 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_datarel,
522 "indirect datarel sleb128")
523 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_datarel,
524 "indirect datarel sdata2")
525 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_datarel,
526 "indirect datarel sdata4")
527 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_datarel,
528 "indirect datarel sdata8")
530 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_funcrel,
531 "indirect funcrel")
532 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_funcrel,
533 "indirect funcrel uleb128")
534 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_funcrel,
535 "indirect funcrel udata2")
536 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_funcrel,
537 "indirect funcrel udata4")
538 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_funcrel,
539 "indirect funcrel udata8")
540 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_funcrel,
541 "indirect funcrel sleb128")
542 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_funcrel,
543 "indirect funcrel sdata2")
544 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_funcrel,
545 "indirect funcrel sdata4")
546 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_funcrel,
547 "indirect funcrel sdata8")
549 #if HAVE_DESIGNATED_INITIALIZERS
552 gcc_assert (format >= 0 && format < 0x100 && format_names[format]);
554 return format_names[format];
555 #else
557 gcc_unreachable ();
558 #endif
561 /* Output an unsigned LEB128 quantity, but only the byte values. */
563 void
564 dw2_asm_output_data_uleb128_raw (unsigned HOST_WIDE_INT value)
566 while (1)
568 int byte = (value & 0x7f);
569 value >>= 7;
570 if (value != 0)
571 /* More bytes to follow. */
572 byte |= 0x80;
574 fprintf (asm_out_file, "%#x", byte);
575 if (value == 0)
576 break;
577 fputc (',', asm_out_file);
581 /* Output an unsigned LEB128 quantity. */
583 void
584 dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value,
585 const char *comment, ...)
587 va_list ap;
589 va_start (ap, comment);
591 #ifdef HAVE_AS_LEB128
592 fputs ("\t.uleb128 ", asm_out_file);
593 fprint_whex (asm_out_file, value);
595 if (flag_debug_asm && comment)
597 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
598 vfprintf (asm_out_file, comment, ap);
600 #else
602 unsigned HOST_WIDE_INT work = value;
603 const char *byte_op = targetm.asm_out.byte_op;
605 if (byte_op)
606 fputs (byte_op, asm_out_file);
609 int byte = (work & 0x7f);
610 work >>= 7;
611 if (work != 0)
612 /* More bytes to follow. */
613 byte |= 0x80;
615 if (byte_op)
617 fprintf (asm_out_file, "%#x", byte);
618 if (work != 0)
619 fputc (',', asm_out_file);
621 else
622 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
624 while (work != 0);
626 if (flag_debug_asm)
628 fprintf (asm_out_file, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX,
629 ASM_COMMENT_START, value);
630 if (comment)
632 fputs ("; ", asm_out_file);
633 vfprintf (asm_out_file, comment, ap);
637 #endif
638 putc ('\n', asm_out_file);
640 va_end (ap);
643 /* Output an signed LEB128 quantity, but only the byte values. */
645 void
646 dw2_asm_output_data_sleb128_raw (HOST_WIDE_INT value)
648 int byte, more;
650 while (1)
652 byte = (value & 0x7f);
653 value >>= 7;
654 more = !((value == 0 && (byte & 0x40) == 0)
655 || (value == -1 && (byte & 0x40) != 0));
656 if (more)
657 byte |= 0x80;
659 fprintf (asm_out_file, "%#x", byte);
660 if (!more)
661 break;
662 fputc (',', asm_out_file);
666 /* Output a signed LEB128 quantity. */
668 void
669 dw2_asm_output_data_sleb128 (HOST_WIDE_INT value,
670 const char *comment, ...)
672 va_list ap;
674 va_start (ap, comment);
676 #ifdef HAVE_AS_LEB128
677 fprintf (asm_out_file, "\t.sleb128 " HOST_WIDE_INT_PRINT_DEC, value);
679 if (flag_debug_asm && comment)
681 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
682 vfprintf (asm_out_file, comment, ap);
684 #else
686 HOST_WIDE_INT work = value;
687 int more, byte;
688 const char *byte_op = targetm.asm_out.byte_op;
690 if (byte_op)
691 fputs (byte_op, asm_out_file);
694 byte = (work & 0x7f);
695 /* arithmetic shift */
696 work >>= 7;
697 more = !((work == 0 && (byte & 0x40) == 0)
698 || (work == -1 && (byte & 0x40) != 0));
699 if (more)
700 byte |= 0x80;
702 if (byte_op)
704 fprintf (asm_out_file, "%#x", byte);
705 if (more)
706 fputc (',', asm_out_file);
708 else
709 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
711 while (more);
713 if (flag_debug_asm)
715 fprintf (asm_out_file, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC,
716 ASM_COMMENT_START, value);
717 if (comment)
719 fputs ("; ", asm_out_file);
720 vfprintf (asm_out_file, comment, ap);
724 #endif
725 fputc ('\n', asm_out_file);
727 va_end (ap);
730 void
731 dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
732 const char *lab2 ATTRIBUTE_UNUSED,
733 const char *comment, ...)
735 va_list ap;
737 va_start (ap, comment);
739 #ifdef HAVE_AS_LEB128
740 fputs ("\t.uleb128 ", asm_out_file);
741 assemble_name (asm_out_file, lab1);
742 putc ('-', asm_out_file);
743 assemble_name (asm_out_file, lab2);
744 #else
745 gcc_unreachable ();
746 #endif
748 if (flag_debug_asm && comment)
750 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
751 vfprintf (asm_out_file, comment, ap);
753 fputc ('\n', asm_out_file);
755 va_end (ap);
758 #if 0
760 void
761 dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED,
762 const char *lab2 ATTRIBUTE_UNUSED,
763 const char *comment, ...)
765 va_list ap;
767 va_start (ap, comment);
769 #ifdef HAVE_AS_LEB128
770 fputs ("\t.sleb128 ", asm_out_file);
771 assemble_name (asm_out_file, lab1);
772 putc ('-', asm_out_file);
773 assemble_name (asm_out_file, lab2);
774 #else
775 gcc_unreachable ();
776 #endif
778 if (flag_debug_asm && comment)
780 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
781 vfprintf (asm_out_file, comment, ap);
783 fputc ('\n', asm_out_file);
785 va_end (ap);
787 #endif /* 0 */
789 static GTY(()) hash_map<const char *, tree> *indirect_pool;
791 static GTY(()) int dw2_const_labelno;
793 #if defined(HAVE_GAS_HIDDEN)
794 # define USE_LINKONCE_INDIRECT (SUPPORTS_ONE_ONLY)
795 #else
796 # define USE_LINKONCE_INDIRECT 0
797 #endif
799 /* Compare two std::pair<const char *, tree> by their first element.
800 Returns <0, 0, or
801 >0 to indicate whether K1 is less than, equal to, or greater than
802 K2, respectively. */
804 static int
805 compare_strings (const void *a, const void *b)
807 const char *s1 = ((const std::pair<const char *, tree> *) a)->first;
808 const char *s2 = ((const std::pair<const char *, tree> *) b)->first;
809 int ret;
811 if (s1 == s2)
812 return 0;
814 ret = strcmp (s1, s2);
816 /* The strings are always those from IDENTIFIER_NODEs, and,
817 therefore, we should never have two copies of the same
818 string. */
819 gcc_assert (ret);
821 return ret;
824 /* Put X, a SYMBOL_REF, in memory. Return a SYMBOL_REF to the allocated
825 memory. Differs from force_const_mem in that a single pool is used for
826 the entire unit of translation, and the memory is not guaranteed to be
827 "near" the function in any interesting sense. IS_PUBLIC controls whether
828 the symbol can be shared across the entire application (or DSO). */
831 dw2_force_const_mem (rtx x, bool is_public)
833 const char *key;
834 tree decl_id;
836 if (! indirect_pool)
837 indirect_pool = hash_map<const char *, tree>::create_ggc (64);
839 gcc_assert (GET_CODE (x) == SYMBOL_REF);
841 key = XSTR (x, 0);
842 tree *slot = indirect_pool->get (key);
843 if (slot)
844 decl_id = *slot;
845 else
847 tree id;
848 const char *str = targetm.strip_name_encoding (key);
850 if (is_public && USE_LINKONCE_INDIRECT)
852 char *ref_name = XALLOCAVEC (char, strlen (str) + sizeof "DW.ref.");
854 sprintf (ref_name, "DW.ref.%s", str);
855 gcc_assert (!maybe_get_identifier (ref_name));
856 decl_id = get_identifier (ref_name);
857 TREE_PUBLIC (decl_id) = 1;
859 else
861 char label[32];
863 ASM_GENERATE_INTERNAL_LABEL (label, "LDFCM", dw2_const_labelno);
864 ++dw2_const_labelno;
865 gcc_assert (!maybe_get_identifier (label));
866 decl_id = get_identifier (label);
869 id = maybe_get_identifier (str);
870 if (id)
871 TREE_SYMBOL_REFERENCED (id) = 1;
873 indirect_pool->put (key, decl_id);
876 return gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (decl_id));
879 /* A helper function for dw2_output_indirect_constants. Emit one queued
880 constant to memory. */
882 static int
883 dw2_output_indirect_constant_1 (const char *sym, tree id)
885 rtx sym_ref;
886 tree decl;
888 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, id, ptr_type_node);
889 SET_DECL_ASSEMBLER_NAME (decl, id);
890 DECL_ARTIFICIAL (decl) = 1;
891 DECL_IGNORED_P (decl) = 1;
892 DECL_INITIAL (decl) = decl;
893 TREE_READONLY (decl) = 1;
894 TREE_STATIC (decl) = 1;
896 if (TREE_PUBLIC (id))
898 TREE_PUBLIC (decl) = 1;
899 make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
900 if (USE_LINKONCE_INDIRECT)
901 DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
904 sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
905 assemble_variable (decl, 1, 1, 1);
906 assemble_integer (sym_ref, POINTER_SIZE_UNITS, POINTER_SIZE, 1);
908 return 0;
911 /* Emit the constants queued through dw2_force_const_mem. */
913 void
914 dw2_output_indirect_constants (void)
916 if (!indirect_pool)
917 return;
919 auto_vec<std::pair<const char *, tree> > temp (indirect_pool->elements ());
920 for (hash_map<const char *, tree>::iterator iter = indirect_pool->begin ();
921 iter != indirect_pool->end (); ++iter)
922 temp.quick_push (*iter);
924 temp.qsort (compare_strings);
926 for (unsigned int i = 0; i < temp.length (); i++)
927 dw2_output_indirect_constant_1 (temp[i].first, temp[i].second);
930 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.
931 If PUBLIC is set and the encoding is DW_EH_PE_indirect, the indirect
932 reference is shared across the entire application (or DSO). */
934 void
935 dw2_asm_output_encoded_addr_rtx (int encoding, rtx addr, bool is_public,
936 const char *comment, ...)
938 int size;
939 va_list ap;
941 va_start (ap, comment);
943 size = size_of_encoded_value (encoding);
945 if (encoding == DW_EH_PE_aligned)
947 assemble_align (POINTER_SIZE);
948 assemble_integer (addr, size, POINTER_SIZE, 1);
949 va_end (ap);
950 return;
953 /* NULL is _always_ represented as a plain zero, as is 1 for Ada's
954 "all others". */
955 if (addr == const0_rtx || addr == const1_rtx)
956 assemble_integer (addr, size, BITS_PER_UNIT, 1);
957 else
959 restart:
960 /* Allow the target first crack at emitting this. Some of the
961 special relocations require special directives instead of
962 just ".4byte" or whatever. */
963 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
964 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
965 addr, done);
966 #endif
968 /* Indirection is used to get dynamic relocations out of a
969 read-only section. */
970 if (encoding & DW_EH_PE_indirect)
972 /* It is very tempting to use force_const_mem so that we share data
973 with the normal constant pool. However, we've already emitted
974 the constant pool for this function. Moreover, we'd like to
975 share these constants across the entire unit of translation and
976 even, if possible, across the entire application (or DSO). */
977 addr = dw2_force_const_mem (addr, is_public);
978 encoding &= ~DW_EH_PE_indirect;
979 goto restart;
982 switch (encoding & 0xF0)
984 case DW_EH_PE_absptr:
985 dw2_assemble_integer (size, addr);
986 break;
988 case DW_EH_PE_pcrel:
989 gcc_assert (GET_CODE (addr) == SYMBOL_REF);
990 #ifdef ASM_OUTPUT_DWARF_PCREL
991 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
992 #else
993 dw2_assemble_integer (size, gen_rtx_MINUS (Pmode, addr, pc_rtx));
994 #endif
995 break;
997 default:
998 /* Other encodings should have been handled by
999 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
1000 gcc_unreachable ();
1003 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
1004 done:;
1005 #endif
1008 if (flag_debug_asm && comment)
1010 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
1011 vfprintf (asm_out_file, comment, ap);
1013 fputc ('\n', asm_out_file);
1015 va_end (ap);
1018 #include "gt-dwarf2asm.h"