2016-09-26 François Dumont <fdumont@gcc.gnu.org>
[official-gcc.git] / gcc / dwarf2asm.c
blobcad550916d4c6c230ee3bae32e22b0c54953727e
1 /* Dwarf2 assembler output helper routines.
2 Copyright (C) 2001-2016 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
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 "tm_p.h"
28 #include "stringpool.h"
29 #include "varasm.h"
30 #include "output.h"
31 #include "dwarf2asm.h"
32 #include "dwarf2.h"
33 #include "function.h"
34 #include "emit-rtl.h"
36 #ifndef XCOFF_DEBUGGING_INFO
37 #define XCOFF_DEBUGGING_INFO 0
38 #endif
41 /* Output an unaligned integer with the given value and size. Prefer not
42 to print a newline, since the caller may want to add a comment. */
44 void
45 dw2_assemble_integer (int size, rtx x)
47 const char *op = integer_asm_op (size, FALSE);
49 if (op)
51 fputs (op, asm_out_file);
52 if (CONST_INT_P (x))
53 fprint_whex (asm_out_file, (unsigned HOST_WIDE_INT) INTVAL (x));
54 else
55 output_addr_const (asm_out_file, x);
57 else
58 assemble_integer (x, size, BITS_PER_UNIT, 1);
62 /* Output a value of a given size in target byte order. */
64 void
65 dw2_asm_output_data_raw (int size, unsigned HOST_WIDE_INT value)
67 unsigned char bytes[8];
68 int i;
70 for (i = 0; i < 8; ++i)
72 bytes[i] = value & 0xff;
73 value >>= 8;
76 if (BYTES_BIG_ENDIAN)
78 for (i = size - 1; i > 0; --i)
79 fprintf (asm_out_file, "%#x,", bytes[i]);
80 fprintf (asm_out_file, "%#x", bytes[0]);
82 else
84 for (i = 0; i < size - 1; ++i)
85 fprintf (asm_out_file, "%#x,", bytes[i]);
86 fprintf (asm_out_file, "%#x", bytes[i]);
90 /* Output an immediate constant in a given SIZE in bytes. */
92 void
93 dw2_asm_output_data (int size, unsigned HOST_WIDE_INT value,
94 const char *comment, ...)
96 va_list ap;
97 const char *op = integer_asm_op (size, FALSE);
99 va_start (ap, comment);
101 if (size * 8 < HOST_BITS_PER_WIDE_INT)
102 value &= ~(HOST_WIDE_INT_M1U << (size * 8));
104 if (op)
106 fputs (op, asm_out_file);
107 fprint_whex (asm_out_file, value);
109 else
110 assemble_integer (GEN_INT (value), size, BITS_PER_UNIT, 1);
112 if (flag_debug_asm && comment)
114 fputs ("\t" ASM_COMMENT_START " ", asm_out_file);
115 vfprintf (asm_out_file, comment, ap);
117 putc ('\n', asm_out_file);
119 va_end (ap);
122 /* Output the difference between two symbols in a given size. */
123 /* ??? There appear to be assemblers that do not like such
124 subtraction, but do support ASM_SET_OP. It's unfortunately
125 impossible to do here, since the ASM_SET_OP for the difference
126 symbol must appear after both symbols are defined. */
128 void
129 dw2_asm_output_delta (int size, const char *lab1, const char *lab2,
130 const char *comment, ...)
132 va_list ap;
134 va_start (ap, comment);
136 #ifdef ASM_OUTPUT_DWARF_DELTA
137 ASM_OUTPUT_DWARF_DELTA (asm_out_file, size, lab1, lab2);
138 #else
139 dw2_assemble_integer (size,
140 gen_rtx_MINUS (Pmode,
141 gen_rtx_SYMBOL_REF (Pmode, lab1),
142 gen_rtx_SYMBOL_REF (Pmode, lab2)));
143 #endif
144 if (flag_debug_asm && comment)
146 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
147 vfprintf (asm_out_file, comment, ap);
149 fputc ('\n', asm_out_file);
151 va_end (ap);
154 #ifdef ASM_OUTPUT_DWARF_VMS_DELTA
155 /* Output the difference between two symbols in instruction units
156 in a given size. */
158 void
159 dw2_asm_output_vms_delta (int size ATTRIBUTE_UNUSED,
160 const char *lab1, const char *lab2,
161 const char *comment, ...)
163 va_list ap;
165 va_start (ap, comment);
167 ASM_OUTPUT_DWARF_VMS_DELTA (asm_out_file, size, lab1, lab2);
168 if (flag_debug_asm && comment)
170 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
171 vfprintf (asm_out_file, comment, ap);
173 fputc ('\n', asm_out_file);
175 va_end (ap);
177 #endif
179 /* Output a section-relative reference to a LABEL, which was placed in
180 BASE. In general this can only be done for debugging symbols.
181 E.g. on most targets with the GNU linker, this is accomplished with
182 a direct reference and the knowledge that the debugging section
183 will be placed at VMA 0. Some targets have special relocations for
184 this that we must use. */
186 void
187 dw2_asm_output_offset (int size, const char *label,
188 section *base ATTRIBUTE_UNUSED,
189 const char *comment, ...)
191 va_list ap;
193 va_start (ap, comment);
195 #ifdef ASM_OUTPUT_DWARF_OFFSET
196 ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label, 0, base);
197 #else
198 dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
199 #endif
201 if (flag_debug_asm && comment)
203 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
204 vfprintf (asm_out_file, comment, ap);
206 fputc ('\n', asm_out_file);
208 va_end (ap);
211 void
212 dw2_asm_output_offset (int size, const char *label, HOST_WIDE_INT offset,
213 section *base ATTRIBUTE_UNUSED,
214 const char *comment, ...)
216 va_list ap;
218 va_start (ap, comment);
220 #ifdef ASM_OUTPUT_DWARF_OFFSET
221 ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label, offset, base);
222 #else
223 dw2_assemble_integer (size, gen_rtx_PLUS (Pmode,
224 gen_rtx_SYMBOL_REF (Pmode, label),
225 gen_int_mode (offset, Pmode)));
226 #endif
228 if (flag_debug_asm && comment)
230 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
231 vfprintf (asm_out_file, comment, ap);
233 fputc ('\n', asm_out_file);
235 va_end (ap);
238 #if 0
240 /* Output a self-relative reference to a label, possibly in a
241 different section or object file. */
243 void
244 dw2_asm_output_pcrel (int size ATTRIBUTE_UNUSED,
245 const char *label ATTRIBUTE_UNUSED,
246 const char *comment, ...)
248 va_list ap;
250 va_start (ap, comment);
252 #ifdef ASM_OUTPUT_DWARF_PCREL
253 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label);
254 #else
255 dw2_assemble_integer (size,
256 gen_rtx_MINUS (Pmode,
257 gen_rtx_SYMBOL_REF (Pmode, label),
258 pc_rtx));
259 #endif
261 if (flag_debug_asm && comment)
263 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
264 vfprintf (asm_out_file, comment, ap);
266 fputc ('\n', asm_out_file);
268 va_end (ap);
270 #endif /* 0 */
272 /* Output an absolute reference to a label. */
274 void
275 dw2_asm_output_addr (int size, const char *label,
276 const char *comment, ...)
278 va_list ap;
280 va_start (ap, comment);
282 dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
284 if (flag_debug_asm && comment)
286 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
287 vfprintf (asm_out_file, comment, ap);
289 fputc ('\n', asm_out_file);
291 va_end (ap);
294 /* Similar, but use an RTX expression instead of a text label. */
296 void
297 dw2_asm_output_addr_rtx (int size, rtx addr,
298 const char *comment, ...)
300 va_list ap;
302 va_start (ap, comment);
304 dw2_assemble_integer (size, addr);
306 if (flag_debug_asm && comment)
308 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
309 vfprintf (asm_out_file, comment, ap);
311 fputc ('\n', asm_out_file);
313 va_end (ap);
316 /* Output the first ORIG_LEN characters of STR as a string.
317 If ORIG_LEN is equal to -1, ignore this parameter and output
318 the entire STR instead.
319 If COMMENT is not NULL and comments in the debug information
320 have been requested by the user, append the given COMMENT
321 to the generated output. */
323 void
324 dw2_asm_output_nstring (const char *str, size_t orig_len,
325 const char *comment, ...)
327 size_t i, len;
328 va_list ap;
330 va_start (ap, comment);
332 len = orig_len;
334 if (len == (size_t) -1)
335 len = strlen (str);
337 if (flag_debug_asm && comment)
339 if (XCOFF_DEBUGGING_INFO)
340 fputs ("\t.byte \"", asm_out_file);
341 else
342 fputs ("\t.ascii \"", asm_out_file);
344 for (i = 0; i < len; i++)
346 int c = str[i];
347 if (c == '\"' || c == '\\')
348 fputc ('\\', asm_out_file);
349 if (ISPRINT (c))
350 fputc (c, asm_out_file);
351 else
352 fprintf (asm_out_file, "\\%o", c);
354 fprintf (asm_out_file, "\\0\"\t%s ", ASM_COMMENT_START);
355 vfprintf (asm_out_file, comment, ap);
356 fputc ('\n', asm_out_file);
358 else
360 /* If an explicit length was given, we can't assume there
361 is a null termination in the string buffer. */
362 if (orig_len == (size_t) -1)
363 len += 1;
364 ASM_OUTPUT_ASCII (asm_out_file, str, len);
365 if (orig_len != (size_t) -1)
366 assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1);
369 va_end (ap);
373 /* Return the size of an unsigned LEB128 quantity. */
376 size_of_uleb128 (unsigned HOST_WIDE_INT value)
378 int size = 0;
382 value >>= 7;
383 size += 1;
385 while (value != 0);
387 return size;
390 /* Return the size of a signed LEB128 quantity. */
393 size_of_sleb128 (HOST_WIDE_INT value)
395 int size = 0, byte;
399 byte = (value & 0x7f);
400 value >>= 7;
401 size += 1;
403 while (!((value == 0 && (byte & 0x40) == 0)
404 || (value == -1 && (byte & 0x40) != 0)));
406 return size;
409 /* Given an encoding, return the number of bytes the format occupies.
410 This is only defined for fixed-size encodings, and so does not
411 include leb128. */
414 size_of_encoded_value (int encoding)
416 if (encoding == DW_EH_PE_omit)
417 return 0;
419 switch (encoding & 0x07)
421 case DW_EH_PE_absptr:
422 return POINTER_SIZE_UNITS;
423 case DW_EH_PE_udata2:
424 return 2;
425 case DW_EH_PE_udata4:
426 return 4;
427 case DW_EH_PE_udata8:
428 return 8;
429 default:
430 gcc_unreachable ();
434 /* Yield a name for a given pointer encoding. */
436 const char *
437 eh_data_format_name (int format)
439 #if HAVE_DESIGNATED_INITIALIZERS
440 #define S(p, v) [p] = v,
441 #else
442 #define S(p, v) case p: return v;
443 #endif
445 #if HAVE_DESIGNATED_INITIALIZERS
446 __extension__ static const char * const format_names[256] = {
447 #else
448 switch (format) {
449 #endif
451 S(DW_EH_PE_absptr, "absolute")
452 S(DW_EH_PE_omit, "omit")
453 S(DW_EH_PE_aligned, "aligned absolute")
455 S(DW_EH_PE_uleb128, "uleb128")
456 S(DW_EH_PE_udata2, "udata2")
457 S(DW_EH_PE_udata4, "udata4")
458 S(DW_EH_PE_udata8, "udata8")
459 S(DW_EH_PE_sleb128, "sleb128")
460 S(DW_EH_PE_sdata2, "sdata2")
461 S(DW_EH_PE_sdata4, "sdata4")
462 S(DW_EH_PE_sdata8, "sdata8")
464 S(DW_EH_PE_absptr | DW_EH_PE_pcrel, "pcrel")
465 S(DW_EH_PE_uleb128 | DW_EH_PE_pcrel, "pcrel uleb128")
466 S(DW_EH_PE_udata2 | DW_EH_PE_pcrel, "pcrel udata2")
467 S(DW_EH_PE_udata4 | DW_EH_PE_pcrel, "pcrel udata4")
468 S(DW_EH_PE_udata8 | DW_EH_PE_pcrel, "pcrel udata8")
469 S(DW_EH_PE_sleb128 | DW_EH_PE_pcrel, "pcrel sleb128")
470 S(DW_EH_PE_sdata2 | DW_EH_PE_pcrel, "pcrel sdata2")
471 S(DW_EH_PE_sdata4 | DW_EH_PE_pcrel, "pcrel sdata4")
472 S(DW_EH_PE_sdata8 | DW_EH_PE_pcrel, "pcrel sdata8")
474 S(DW_EH_PE_absptr | DW_EH_PE_textrel, "textrel")
475 S(DW_EH_PE_uleb128 | DW_EH_PE_textrel, "textrel uleb128")
476 S(DW_EH_PE_udata2 | DW_EH_PE_textrel, "textrel udata2")
477 S(DW_EH_PE_udata4 | DW_EH_PE_textrel, "textrel udata4")
478 S(DW_EH_PE_udata8 | DW_EH_PE_textrel, "textrel udata8")
479 S(DW_EH_PE_sleb128 | DW_EH_PE_textrel, "textrel sleb128")
480 S(DW_EH_PE_sdata2 | DW_EH_PE_textrel, "textrel sdata2")
481 S(DW_EH_PE_sdata4 | DW_EH_PE_textrel, "textrel sdata4")
482 S(DW_EH_PE_sdata8 | DW_EH_PE_textrel, "textrel sdata8")
484 S(DW_EH_PE_absptr | DW_EH_PE_datarel, "datarel")
485 S(DW_EH_PE_uleb128 | DW_EH_PE_datarel, "datarel uleb128")
486 S(DW_EH_PE_udata2 | DW_EH_PE_datarel, "datarel udata2")
487 S(DW_EH_PE_udata4 | DW_EH_PE_datarel, "datarel udata4")
488 S(DW_EH_PE_udata8 | DW_EH_PE_datarel, "datarel udata8")
489 S(DW_EH_PE_sleb128 | DW_EH_PE_datarel, "datarel sleb128")
490 S(DW_EH_PE_sdata2 | DW_EH_PE_datarel, "datarel sdata2")
491 S(DW_EH_PE_sdata4 | DW_EH_PE_datarel, "datarel sdata4")
492 S(DW_EH_PE_sdata8 | DW_EH_PE_datarel, "datarel sdata8")
494 S(DW_EH_PE_absptr | DW_EH_PE_funcrel, "funcrel")
495 S(DW_EH_PE_uleb128 | DW_EH_PE_funcrel, "funcrel uleb128")
496 S(DW_EH_PE_udata2 | DW_EH_PE_funcrel, "funcrel udata2")
497 S(DW_EH_PE_udata4 | DW_EH_PE_funcrel, "funcrel udata4")
498 S(DW_EH_PE_udata8 | DW_EH_PE_funcrel, "funcrel udata8")
499 S(DW_EH_PE_sleb128 | DW_EH_PE_funcrel, "funcrel sleb128")
500 S(DW_EH_PE_sdata2 | DW_EH_PE_funcrel, "funcrel sdata2")
501 S(DW_EH_PE_sdata4 | DW_EH_PE_funcrel, "funcrel sdata4")
502 S(DW_EH_PE_sdata8 | DW_EH_PE_funcrel, "funcrel sdata8")
504 S(DW_EH_PE_indirect | DW_EH_PE_absptr, "indirect absolute")
506 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel,
507 "indirect pcrel")
508 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel,
509 "indirect pcrel uleb128")
510 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_pcrel,
511 "indirect pcrel udata2")
512 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_pcrel,
513 "indirect pcrel udata4")
514 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_pcrel,
515 "indirect pcrel udata8")
516 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_pcrel,
517 "indirect pcrel sleb128")
518 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_pcrel,
519 "indirect pcrel sdata2")
520 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_pcrel,
521 "indirect pcrel sdata4")
522 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_pcrel,
523 "indirect pcrel sdata8")
525 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_textrel,
526 "indirect textrel")
527 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_textrel,
528 "indirect textrel uleb128")
529 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_textrel,
530 "indirect textrel udata2")
531 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_textrel,
532 "indirect textrel udata4")
533 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_textrel,
534 "indirect textrel udata8")
535 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_textrel,
536 "indirect textrel sleb128")
537 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_textrel,
538 "indirect textrel sdata2")
539 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_textrel,
540 "indirect textrel sdata4")
541 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_textrel,
542 "indirect textrel sdata8")
544 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_datarel,
545 "indirect datarel")
546 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_datarel,
547 "indirect datarel uleb128")
548 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_datarel,
549 "indirect datarel udata2")
550 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_datarel,
551 "indirect datarel udata4")
552 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_datarel,
553 "indirect datarel udata8")
554 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_datarel,
555 "indirect datarel sleb128")
556 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_datarel,
557 "indirect datarel sdata2")
558 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_datarel,
559 "indirect datarel sdata4")
560 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_datarel,
561 "indirect datarel sdata8")
563 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_funcrel,
564 "indirect funcrel")
565 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_funcrel,
566 "indirect funcrel uleb128")
567 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_funcrel,
568 "indirect funcrel udata2")
569 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_funcrel,
570 "indirect funcrel udata4")
571 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_funcrel,
572 "indirect funcrel udata8")
573 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_funcrel,
574 "indirect funcrel sleb128")
575 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_funcrel,
576 "indirect funcrel sdata2")
577 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_funcrel,
578 "indirect funcrel sdata4")
579 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_funcrel,
580 "indirect funcrel sdata8")
582 #if HAVE_DESIGNATED_INITIALIZERS
585 gcc_assert (format >= 0 && format < 0x100 && format_names[format]);
587 return format_names[format];
588 #else
590 gcc_unreachable ();
591 #endif
594 /* Output an unsigned LEB128 quantity, but only the byte values. */
596 void
597 dw2_asm_output_data_uleb128_raw (unsigned HOST_WIDE_INT value)
599 while (1)
601 int byte = (value & 0x7f);
602 value >>= 7;
603 if (value != 0)
604 /* More bytes to follow. */
605 byte |= 0x80;
607 fprintf (asm_out_file, "%#x", byte);
608 if (value == 0)
609 break;
610 fputc (',', asm_out_file);
614 /* Output an unsigned LEB128 quantity. */
616 void
617 dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value,
618 const char *comment, ...)
620 va_list ap;
622 va_start (ap, comment);
624 #ifdef HAVE_AS_LEB128
625 fputs ("\t.uleb128 ", asm_out_file);
626 fprint_whex (asm_out_file, value);
628 if (flag_debug_asm && comment)
630 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
631 vfprintf (asm_out_file, comment, ap);
633 #else
635 unsigned HOST_WIDE_INT work = value;
636 const char *byte_op = targetm.asm_out.byte_op;
638 if (byte_op)
639 fputs (byte_op, asm_out_file);
642 int byte = (work & 0x7f);
643 work >>= 7;
644 if (work != 0)
645 /* More bytes to follow. */
646 byte |= 0x80;
648 if (byte_op)
650 fprintf (asm_out_file, "%#x", byte);
651 if (work != 0)
652 fputc (',', asm_out_file);
654 else
655 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
657 while (work != 0);
659 if (flag_debug_asm)
661 fprintf (asm_out_file, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX,
662 ASM_COMMENT_START, value);
663 if (comment)
665 fputs ("; ", asm_out_file);
666 vfprintf (asm_out_file, comment, ap);
670 #endif
671 putc ('\n', asm_out_file);
673 va_end (ap);
676 /* Output an signed LEB128 quantity, but only the byte values. */
678 void
679 dw2_asm_output_data_sleb128_raw (HOST_WIDE_INT value)
681 int byte, more;
683 while (1)
685 byte = (value & 0x7f);
686 value >>= 7;
687 more = !((value == 0 && (byte & 0x40) == 0)
688 || (value == -1 && (byte & 0x40) != 0));
689 if (more)
690 byte |= 0x80;
692 fprintf (asm_out_file, "%#x", byte);
693 if (!more)
694 break;
695 fputc (',', asm_out_file);
699 /* Output a signed LEB128 quantity. */
701 void
702 dw2_asm_output_data_sleb128 (HOST_WIDE_INT value,
703 const char *comment, ...)
705 va_list ap;
707 va_start (ap, comment);
709 #ifdef HAVE_AS_LEB128
710 fprintf (asm_out_file, "\t.sleb128 " HOST_WIDE_INT_PRINT_DEC, value);
712 if (flag_debug_asm && comment)
714 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
715 vfprintf (asm_out_file, comment, ap);
717 #else
719 HOST_WIDE_INT work = value;
720 int more, byte;
721 const char *byte_op = targetm.asm_out.byte_op;
723 if (byte_op)
724 fputs (byte_op, asm_out_file);
727 byte = (work & 0x7f);
728 /* arithmetic shift */
729 work >>= 7;
730 more = !((work == 0 && (byte & 0x40) == 0)
731 || (work == -1 && (byte & 0x40) != 0));
732 if (more)
733 byte |= 0x80;
735 if (byte_op)
737 fprintf (asm_out_file, "%#x", byte);
738 if (more)
739 fputc (',', asm_out_file);
741 else
742 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
744 while (more);
746 if (flag_debug_asm)
748 fprintf (asm_out_file, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC,
749 ASM_COMMENT_START, value);
750 if (comment)
752 fputs ("; ", asm_out_file);
753 vfprintf (asm_out_file, comment, ap);
757 #endif
758 fputc ('\n', asm_out_file);
760 va_end (ap);
763 void
764 dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
765 const char *lab2 ATTRIBUTE_UNUSED,
766 const char *comment, ...)
768 va_list ap;
770 va_start (ap, comment);
772 #ifdef HAVE_AS_LEB128
773 fputs ("\t.uleb128 ", asm_out_file);
774 assemble_name (asm_out_file, lab1);
775 putc ('-', asm_out_file);
776 assemble_name (asm_out_file, lab2);
777 #else
778 gcc_unreachable ();
779 #endif
781 if (flag_debug_asm && comment)
783 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
784 vfprintf (asm_out_file, comment, ap);
786 fputc ('\n', asm_out_file);
788 va_end (ap);
791 #if 0
793 void
794 dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED,
795 const char *lab2 ATTRIBUTE_UNUSED,
796 const char *comment, ...)
798 va_list ap;
800 va_start (ap, comment);
802 #ifdef HAVE_AS_LEB128
803 fputs ("\t.sleb128 ", asm_out_file);
804 assemble_name (asm_out_file, lab1);
805 putc ('-', asm_out_file);
806 assemble_name (asm_out_file, lab2);
807 #else
808 gcc_unreachable ();
809 #endif
811 if (flag_debug_asm && comment)
813 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
814 vfprintf (asm_out_file, comment, ap);
816 fputc ('\n', asm_out_file);
818 va_end (ap);
820 #endif /* 0 */
822 static GTY(()) hash_map<const char *, tree> *indirect_pool;
824 static GTY(()) int dw2_const_labelno;
826 #if defined(HAVE_GAS_HIDDEN)
827 # define USE_LINKONCE_INDIRECT (SUPPORTS_ONE_ONLY)
828 #else
829 # define USE_LINKONCE_INDIRECT 0
830 #endif
832 /* Compare two std::pair<const char *, tree> by their first element.
833 Returns <0, 0, or
834 >0 to indicate whether K1 is less than, equal to, or greater than
835 K2, respectively. */
837 static int
838 compare_strings (const void *a, const void *b)
840 const char *s1 = ((const std::pair<const char *, tree> *) a)->first;
841 const char *s2 = ((const std::pair<const char *, tree> *) b)->first;
842 int ret;
844 if (s1 == s2)
845 return 0;
847 ret = strcmp (s1, s2);
849 /* The strings are always those from IDENTIFIER_NODEs, and,
850 therefore, we should never have two copies of the same
851 string. */
852 gcc_assert (ret);
854 return ret;
857 /* Put X, a SYMBOL_REF, in memory. Return a SYMBOL_REF to the allocated
858 memory. Differs from force_const_mem in that a single pool is used for
859 the entire unit of translation, and the memory is not guaranteed to be
860 "near" the function in any interesting sense. IS_PUBLIC controls whether
861 the symbol can be shared across the entire application (or DSO). */
864 dw2_force_const_mem (rtx x, bool is_public)
866 const char *key;
867 tree decl_id;
869 if (! indirect_pool)
870 indirect_pool = hash_map<const char *, tree>::create_ggc (64);
872 gcc_assert (GET_CODE (x) == SYMBOL_REF);
874 key = XSTR (x, 0);
875 tree *slot = indirect_pool->get (key);
876 if (slot)
877 decl_id = *slot;
878 else
880 tree id;
881 const char *str = targetm.strip_name_encoding (key);
883 if (is_public && USE_LINKONCE_INDIRECT)
885 char *ref_name = XALLOCAVEC (char, strlen (str) + sizeof "DW.ref.");
887 sprintf (ref_name, "DW.ref.%s", str);
888 gcc_assert (!maybe_get_identifier (ref_name));
889 decl_id = get_identifier (ref_name);
890 TREE_PUBLIC (decl_id) = 1;
892 else
894 char label[32];
896 ASM_GENERATE_INTERNAL_LABEL (label, "LDFCM", dw2_const_labelno);
897 ++dw2_const_labelno;
898 gcc_assert (!maybe_get_identifier (label));
899 decl_id = get_identifier (label);
902 id = maybe_get_identifier (str);
903 if (id)
904 TREE_SYMBOL_REFERENCED (id) = 1;
906 indirect_pool->put (key, decl_id);
909 return gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (decl_id));
912 /* A helper function for dw2_output_indirect_constants. Emit one queued
913 constant to memory. */
915 static int
916 dw2_output_indirect_constant_1 (const char *sym, tree id)
918 rtx sym_ref;
919 tree decl;
921 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, id, ptr_type_node);
922 SET_DECL_ASSEMBLER_NAME (decl, id);
923 DECL_ARTIFICIAL (decl) = 1;
924 DECL_IGNORED_P (decl) = 1;
925 DECL_INITIAL (decl) = decl;
926 TREE_READONLY (decl) = 1;
927 TREE_STATIC (decl) = 1;
929 if (TREE_PUBLIC (id))
931 TREE_PUBLIC (decl) = 1;
932 make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
933 if (USE_LINKONCE_INDIRECT)
934 DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
937 sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
938 assemble_variable (decl, 1, 1, 1);
939 assemble_integer (sym_ref, POINTER_SIZE_UNITS, POINTER_SIZE, 1);
941 return 0;
944 /* Emit the constants queued through dw2_force_const_mem. */
946 void
947 dw2_output_indirect_constants (void)
949 if (!indirect_pool)
950 return;
952 auto_vec<std::pair<const char *, tree> > temp (indirect_pool->elements ());
953 for (hash_map<const char *, tree>::iterator iter = indirect_pool->begin ();
954 iter != indirect_pool->end (); ++iter)
955 temp.quick_push (*iter);
957 temp.qsort (compare_strings);
959 for (unsigned int i = 0; i < temp.length (); i++)
960 dw2_output_indirect_constant_1 (temp[i].first, temp[i].second);
963 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.
964 If PUBLIC is set and the encoding is DW_EH_PE_indirect, the indirect
965 reference is shared across the entire application (or DSO). */
967 void
968 dw2_asm_output_encoded_addr_rtx (int encoding, rtx addr, bool is_public,
969 const char *comment, ...)
971 int size;
972 va_list ap;
974 va_start (ap, comment);
976 size = size_of_encoded_value (encoding);
978 if (encoding == DW_EH_PE_aligned)
980 assemble_align (POINTER_SIZE);
981 assemble_integer (addr, size, POINTER_SIZE, 1);
982 va_end (ap);
983 return;
986 /* NULL is _always_ represented as a plain zero, as is 1 for Ada's
987 "all others". */
988 if (addr == const0_rtx || addr == const1_rtx)
989 assemble_integer (addr, size, BITS_PER_UNIT, 1);
990 else
992 restart:
993 /* Allow the target first crack at emitting this. Some of the
994 special relocations require special directives instead of
995 just ".4byte" or whatever. */
996 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
997 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
998 addr, done);
999 #endif
1001 /* Indirection is used to get dynamic relocations out of a
1002 read-only section. */
1003 if (encoding & DW_EH_PE_indirect)
1005 /* It is very tempting to use force_const_mem so that we share data
1006 with the normal constant pool. However, we've already emitted
1007 the constant pool for this function. Moreover, we'd like to
1008 share these constants across the entire unit of translation and
1009 even, if possible, across the entire application (or DSO). */
1010 addr = dw2_force_const_mem (addr, is_public);
1011 encoding &= ~DW_EH_PE_indirect;
1012 goto restart;
1015 switch (encoding & 0xF0)
1017 case DW_EH_PE_absptr:
1018 dw2_assemble_integer (size, addr);
1019 break;
1021 #ifdef ASM_OUTPUT_DWARF_DATAREL
1022 case DW_EH_PE_datarel:
1023 gcc_assert (GET_CODE (addr) == SYMBOL_REF);
1024 ASM_OUTPUT_DWARF_DATAREL (asm_out_file, size, XSTR (addr, 0));
1025 break;
1026 #endif
1028 case DW_EH_PE_pcrel:
1029 gcc_assert (GET_CODE (addr) == SYMBOL_REF);
1030 #ifdef ASM_OUTPUT_DWARF_PCREL
1031 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
1032 #else
1033 dw2_assemble_integer (size, gen_rtx_MINUS (Pmode, addr, pc_rtx));
1034 #endif
1035 break;
1037 default:
1038 /* Other encodings should have been handled by
1039 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
1040 gcc_unreachable ();
1043 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
1044 done:;
1045 #endif
1048 if (flag_debug_asm && comment)
1050 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
1051 vfprintf (asm_out_file, comment, ap);
1053 fputc ('\n', asm_out_file);
1055 va_end (ap);
1058 #include "gt-dwarf2asm.h"