PR libstdc++/3584
[official-gcc.git] / gcc / dwarf2asm.c
blobb80e7c3398f7fcd1e3008cdcb631e529550c8c09
1 /* Dwarf2 assembler output helper routines.
2 Copyright (C) 2001, 2002 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 2, 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 COPYING. If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
22 #include "config.h"
23 #include "system.h"
24 #include "flags.h"
25 #include "tree.h"
26 #include "rtl.h"
27 #include "output.h"
28 #include "target.h"
29 #include "dwarf2asm.h"
30 #include "dwarf2.h"
31 #include "splay-tree.h"
32 #include "ggc.h"
33 #include "tm_p.h"
36 /* How to start an assembler comment. */
37 #ifndef ASM_COMMENT_START
38 #define ASM_COMMENT_START ";#"
39 #endif
42 /* Output an unaligned integer with the given value and size. Prefer not
43 to print a newline, since the caller may want to add a comment. */
45 void
46 dw2_assemble_integer (size, x)
47 int size;
48 rtx x;
50 const char *op = integer_asm_op (size, FALSE);
52 if (op)
54 fputs (op, asm_out_file);
55 if (GET_CODE (x) == CONST_INT)
56 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
57 else
58 output_addr_const (asm_out_file, x);
60 else
61 assemble_integer (x, size, BITS_PER_UNIT, 1);
65 /* Output an immediate constant in a given size. */
67 void
68 dw2_asm_output_data VPARAMS ((int size, unsigned HOST_WIDE_INT value,
69 const char *comment, ...))
71 VA_OPEN (ap, comment);
72 VA_FIXEDARG (ap, int, size);
73 VA_FIXEDARG (ap, unsigned HOST_WIDE_INT, value);
74 VA_FIXEDARG (ap, const char *, comment);
76 if (size * 8 < HOST_BITS_PER_WIDE_INT)
77 value &= ~(~(unsigned HOST_WIDE_INT) 0 << (size * 8));
79 dw2_assemble_integer (size, GEN_INT (value));
81 if (flag_debug_asm && comment)
83 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
84 vfprintf (asm_out_file, comment, ap);
86 fputc ('\n', asm_out_file);
88 VA_CLOSE (ap);
91 /* Output the difference between two symbols in a given size. */
92 /* ??? There appear to be assemblers that do not like such
93 subtraction, but do support ASM_SET_OP. It's unfortunately
94 impossible to do here, since the ASM_SET_OP for the difference
95 symbol must appear after both symbols are defined. */
97 void
98 dw2_asm_output_delta VPARAMS ((int size, const char *lab1, const char *lab2,
99 const char *comment, ...))
101 VA_OPEN (ap, comment);
102 VA_FIXEDARG (ap, int, size);
103 VA_FIXEDARG (ap, const char *, lab1);
104 VA_FIXEDARG (ap, const char *, lab2);
105 VA_FIXEDARG (ap, const char *, comment);
107 #ifdef ASM_OUTPUT_DWARF_DELTA
108 ASM_OUTPUT_DWARF_DELTA (asm_out_file, size, lab1, lab2);
109 #else
110 dw2_assemble_integer (size,
111 gen_rtx_MINUS (Pmode,
112 gen_rtx_SYMBOL_REF (Pmode, lab1),
113 gen_rtx_SYMBOL_REF (Pmode, lab2)));
114 #endif
115 if (flag_debug_asm && comment)
117 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
118 vfprintf (asm_out_file, comment, ap);
120 fputc ('\n', asm_out_file);
122 VA_CLOSE (ap);
125 /* Output a section-relative reference to a label. In general this
126 can only be done for debugging symbols. E.g. on most targets with
127 the GNU linker, this is accomplished with a direct reference and
128 the knowledge that the debugging section will be placed at VMA 0.
129 Some targets have special relocations for this that we must use. */
131 void
132 dw2_asm_output_offset VPARAMS ((int size, const char *label,
133 const char *comment, ...))
135 VA_OPEN (ap, comment);
136 VA_FIXEDARG (ap, int, size);
137 VA_FIXEDARG (ap, const char *, label);
138 VA_FIXEDARG (ap, const char *, comment);
140 #ifdef ASM_OUTPUT_DWARF_OFFSET
141 ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label);
142 #else
143 dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
144 #endif
146 if (flag_debug_asm && comment)
148 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
149 vfprintf (asm_out_file, comment, ap);
151 fputc ('\n', asm_out_file);
153 VA_CLOSE (ap);
156 /* Output a self-relative reference to a label, possibly in a
157 different section or object file. */
159 void
160 dw2_asm_output_pcrel VPARAMS ((int size ATTRIBUTE_UNUSED,
161 const char *label ATTRIBUTE_UNUSED,
162 const char *comment, ...))
164 VA_OPEN (ap, comment);
165 VA_FIXEDARG (ap, int, size);
166 VA_FIXEDARG (ap, const char *, label);
167 VA_FIXEDARG (ap, const char *, comment);
169 #ifdef ASM_OUTPUT_DWARF_PCREL
170 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label);
171 #else
172 dw2_assemble_integer (size,
173 gen_rtx_MINUS (Pmode,
174 gen_rtx_SYMBOL_REF (Pmode, label),
175 pc_rtx));
176 #endif
178 if (flag_debug_asm && comment)
180 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
181 vfprintf (asm_out_file, comment, ap);
183 fputc ('\n', asm_out_file);
185 VA_CLOSE (ap);
188 /* Output an absolute reference to a label. */
190 void
191 dw2_asm_output_addr VPARAMS ((int size, const char *label,
192 const char *comment, ...))
194 VA_OPEN (ap, comment);
195 VA_FIXEDARG (ap, int, size);
196 VA_FIXEDARG (ap, const char *, label);
197 VA_FIXEDARG (ap, const char *, comment);
199 dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
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_CLOSE (ap);
211 /* Similar, but use an RTX expression instead of a text label. */
213 void
214 dw2_asm_output_addr_rtx VPARAMS ((int size, rtx addr,
215 const char *comment, ...))
217 VA_OPEN (ap, comment);
218 VA_FIXEDARG (ap, int, size);
219 VA_FIXEDARG (ap, rtx, addr);
220 VA_FIXEDARG (ap, const char *, comment);
222 dw2_assemble_integer (size, addr);
224 if (flag_debug_asm && comment)
226 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
227 vfprintf (asm_out_file, comment, ap);
229 fputc ('\n', asm_out_file);
231 VA_CLOSE (ap);
234 void
235 dw2_asm_output_nstring VPARAMS ((const char *str, size_t orig_len,
236 const char *comment, ...))
238 size_t i, len;
240 VA_OPEN (ap, comment);
241 VA_FIXEDARG (ap, const char *, str);
242 VA_FIXEDARG (ap, size_t, orig_len);
243 VA_FIXEDARG (ap, const char *, comment);
245 len = orig_len;
247 if (len == (size_t) -1)
248 len = strlen (str);
250 if (flag_debug_asm && comment)
252 fputs ("\t.ascii \"", asm_out_file);
253 for (i = 0; i < len; i++)
255 int c = str[i];
256 if (c == '\"' || c == '\\')
257 fputc ('\\', asm_out_file);
258 if (ISPRINT(c))
259 fputc (c, asm_out_file);
260 else
261 fprintf (asm_out_file, "\\%o", c);
263 fprintf (asm_out_file, "\\0\"\t%s ", ASM_COMMENT_START);
264 vfprintf (asm_out_file, comment, ap);
265 fputc ('\n', asm_out_file);
267 else
269 /* If an explicit length was given, we can't assume there
270 is a null termination in the string buffer. */
271 if (orig_len == (size_t) -1)
272 len += 1;
273 ASM_OUTPUT_ASCII (asm_out_file, str, len);
274 if (orig_len != (size_t) -1)
275 assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1);
278 VA_CLOSE (ap);
282 /* Return the size of an unsigned LEB128 quantity. */
285 size_of_uleb128 (value)
286 unsigned HOST_WIDE_INT value;
288 int size = 0, byte;
292 byte = (value & 0x7f);
293 value >>= 7;
294 size += 1;
296 while (value != 0);
298 return size;
301 /* Return the size of a signed LEB128 quantity. */
304 size_of_sleb128 (value)
305 HOST_WIDE_INT value;
307 int size = 0, byte;
311 byte = (value & 0x7f);
312 value >>= 7;
313 size += 1;
315 while (!((value == 0 && (byte & 0x40) == 0)
316 || (value == -1 && (byte & 0x40) != 0)));
318 return size;
321 /* Given an encoding, return the number of bytes the format occupies.
322 This is only defined for fixed-size encodings, and so does not
323 include leb128. */
326 size_of_encoded_value (encoding)
327 int encoding;
329 if (encoding == DW_EH_PE_omit)
330 return 0;
332 switch (encoding & 0x07)
334 case DW_EH_PE_absptr:
335 return POINTER_SIZE / BITS_PER_UNIT;
336 case DW_EH_PE_udata2:
337 return 2;
338 case DW_EH_PE_udata4:
339 return 4;
340 case DW_EH_PE_udata8:
341 return 8;
343 abort ();
346 /* Yield a name for a given pointer encoding. */
348 const char *
349 eh_data_format_name (format)
350 int format;
352 #if HAVE_DESIGNATED_INITIALIZERS
353 #define S(p, v) [p] = v,
354 #else
355 #define S(p, v) case p: return v;
356 #endif
358 #if HAVE_DESIGNATED_INITIALIZERS
359 __extension__ static const char * const format_names[256] = {
360 #else
361 switch (format) {
362 #endif
364 S(DW_EH_PE_absptr, "absolute")
365 S(DW_EH_PE_omit, "omit")
366 S(DW_EH_PE_aligned, "aligned absolute")
368 S(DW_EH_PE_uleb128, "uleb128")
369 S(DW_EH_PE_udata2, "udata2")
370 S(DW_EH_PE_udata4, "udata4")
371 S(DW_EH_PE_udata8, "udata8")
372 S(DW_EH_PE_sleb128, "sleb128")
373 S(DW_EH_PE_sdata2, "sdata2")
374 S(DW_EH_PE_sdata4, "sdata4")
375 S(DW_EH_PE_sdata8, "sdata8")
377 S(DW_EH_PE_absptr | DW_EH_PE_pcrel, "pcrel")
378 S(DW_EH_PE_uleb128 | DW_EH_PE_pcrel, "pcrel uleb128")
379 S(DW_EH_PE_udata2 | DW_EH_PE_pcrel, "pcrel udata2")
380 S(DW_EH_PE_udata4 | DW_EH_PE_pcrel, "pcrel udata4")
381 S(DW_EH_PE_udata8 | DW_EH_PE_pcrel, "pcrel udata8")
382 S(DW_EH_PE_sleb128 | DW_EH_PE_pcrel, "pcrel sleb128")
383 S(DW_EH_PE_sdata2 | DW_EH_PE_pcrel, "pcrel sdata2")
384 S(DW_EH_PE_sdata4 | DW_EH_PE_pcrel, "pcrel sdata4")
385 S(DW_EH_PE_sdata8 | DW_EH_PE_pcrel, "pcrel sdata8")
387 S(DW_EH_PE_absptr | DW_EH_PE_textrel, "textrel")
388 S(DW_EH_PE_uleb128 | DW_EH_PE_textrel, "textrel uleb128")
389 S(DW_EH_PE_udata2 | DW_EH_PE_textrel, "textrel udata2")
390 S(DW_EH_PE_udata4 | DW_EH_PE_textrel, "textrel udata4")
391 S(DW_EH_PE_udata8 | DW_EH_PE_textrel, "textrel udata8")
392 S(DW_EH_PE_sleb128 | DW_EH_PE_textrel, "textrel sleb128")
393 S(DW_EH_PE_sdata2 | DW_EH_PE_textrel, "textrel sdata2")
394 S(DW_EH_PE_sdata4 | DW_EH_PE_textrel, "textrel sdata4")
395 S(DW_EH_PE_sdata8 | DW_EH_PE_textrel, "textrel sdata8")
397 S(DW_EH_PE_absptr | DW_EH_PE_datarel, "datarel")
398 S(DW_EH_PE_uleb128 | DW_EH_PE_datarel, "datarel uleb128")
399 S(DW_EH_PE_udata2 | DW_EH_PE_datarel, "datarel udata2")
400 S(DW_EH_PE_udata4 | DW_EH_PE_datarel, "datarel udata4")
401 S(DW_EH_PE_udata8 | DW_EH_PE_datarel, "datarel udata8")
402 S(DW_EH_PE_sleb128 | DW_EH_PE_datarel, "datarel sleb128")
403 S(DW_EH_PE_sdata2 | DW_EH_PE_datarel, "datarel sdata2")
404 S(DW_EH_PE_sdata4 | DW_EH_PE_datarel, "datarel sdata4")
405 S(DW_EH_PE_sdata8 | DW_EH_PE_datarel, "datarel sdata8")
407 S(DW_EH_PE_absptr | DW_EH_PE_funcrel, "funcrel")
408 S(DW_EH_PE_uleb128 | DW_EH_PE_funcrel, "funcrel uleb128")
409 S(DW_EH_PE_udata2 | DW_EH_PE_funcrel, "funcrel udata2")
410 S(DW_EH_PE_udata4 | DW_EH_PE_funcrel, "funcrel udata4")
411 S(DW_EH_PE_udata8 | DW_EH_PE_funcrel, "funcrel udata8")
412 S(DW_EH_PE_sleb128 | DW_EH_PE_funcrel, "funcrel sleb128")
413 S(DW_EH_PE_sdata2 | DW_EH_PE_funcrel, "funcrel sdata2")
414 S(DW_EH_PE_sdata4 | DW_EH_PE_funcrel, "funcrel sdata4")
415 S(DW_EH_PE_sdata8 | DW_EH_PE_funcrel, "funcrel sdata8")
417 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel,
418 "indirect pcrel")
419 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel,
420 "indirect pcrel uleb128")
421 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_pcrel,
422 "indirect pcrel udata2")
423 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_pcrel,
424 "indirect pcrel udata4")
425 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_pcrel,
426 "indirect pcrel udata8")
427 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_pcrel,
428 "indirect pcrel sleb128")
429 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_pcrel,
430 "indirect pcrel sdata2")
431 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_pcrel,
432 "indirect pcrel sdata4")
433 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_pcrel,
434 "indirect pcrel sdata8")
436 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_textrel,
437 "indirect textrel")
438 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_textrel,
439 "indirect textrel uleb128")
440 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_textrel,
441 "indirect textrel udata2")
442 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_textrel,
443 "indirect textrel udata4")
444 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_textrel,
445 "indirect textrel udata8")
446 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_textrel,
447 "indirect textrel sleb128")
448 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_textrel,
449 "indirect textrel sdata2")
450 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_textrel,
451 "indirect textrel sdata4")
452 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_textrel,
453 "indirect textrel sdata8")
455 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_datarel,
456 "indirect datarel")
457 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_datarel,
458 "indirect datarel uleb128")
459 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_datarel,
460 "indirect datarel udata2")
461 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_datarel,
462 "indirect datarel udata4")
463 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_datarel,
464 "indirect datarel udata8")
465 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_datarel,
466 "indirect datarel sleb128")
467 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_datarel,
468 "indirect datarel sdata2")
469 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_datarel,
470 "indirect datarel sdata4")
471 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_datarel,
472 "indirect datarel sdata8")
474 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_funcrel,
475 "indirect funcrel")
476 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_funcrel,
477 "indirect funcrel uleb128")
478 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_funcrel,
479 "indirect funcrel udata2")
480 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_funcrel,
481 "indirect funcrel udata4")
482 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_funcrel,
483 "indirect funcrel udata8")
484 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_funcrel,
485 "indirect funcrel sleb128")
486 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_funcrel,
487 "indirect funcrel sdata2")
488 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_funcrel,
489 "indirect funcrel sdata4")
490 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_funcrel,
491 "indirect funcrel sdata8")
493 #if HAVE_DESIGNATED_INITIALIZERS
496 if (format < 0 || format > 0xff || format_names[format] == NULL)
497 abort ();
498 return format_names[format];
499 #else
501 abort ();
502 #endif
505 /* Output an unsigned LEB128 quantity. */
507 void
508 dw2_asm_output_data_uleb128 VPARAMS ((unsigned HOST_WIDE_INT value,
509 const char *comment, ...))
511 VA_OPEN (ap, comment);
512 VA_FIXEDARG (ap, unsigned HOST_WIDE_INT, value);
513 VA_FIXEDARG (ap, const char *, comment);
515 #ifdef HAVE_AS_LEB128
516 fputs ("\t.uleb128 ", asm_out_file);
517 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
519 if (flag_debug_asm && comment)
521 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
522 vfprintf (asm_out_file, comment, ap);
524 #else
526 unsigned HOST_WIDE_INT work = value;
527 const char *byte_op = targetm.asm_out.byte_op;
529 if (byte_op)
530 fputs (byte_op, asm_out_file);
533 int byte = (work & 0x7f);
534 work >>= 7;
535 if (work != 0)
536 /* More bytes to follow. */
537 byte |= 0x80;
539 if (byte_op)
541 fprintf (asm_out_file, "0x%x", byte);
542 if (work != 0)
543 fputc (',', asm_out_file);
545 else
546 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
548 while (work != 0);
550 if (flag_debug_asm)
552 fprintf (asm_out_file, "\t%s uleb128 ", ASM_COMMENT_START);
553 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
554 if (comment)
556 fputs ("; ", asm_out_file);
557 vfprintf (asm_out_file, comment, ap);
561 #endif
562 fputc ('\n', asm_out_file);
564 VA_CLOSE (ap);
567 /* Output an signed LEB128 quantity. */
569 void
570 dw2_asm_output_data_sleb128 VPARAMS ((HOST_WIDE_INT value,
571 const char *comment, ...))
573 VA_OPEN (ap, comment);
574 VA_FIXEDARG (ap, HOST_WIDE_INT, value);
575 VA_FIXEDARG (ap, const char *, comment);
577 #ifdef HAVE_AS_LEB128
578 fputs ("\t.sleb128 ", asm_out_file);
579 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, value);
581 if (flag_debug_asm && comment)
583 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
584 vfprintf (asm_out_file, comment, ap);
586 #else
588 HOST_WIDE_INT work = value;
589 int more, byte;
590 const char *byte_op = targetm.asm_out.byte_op;
592 if (byte_op)
593 fputs (byte_op, asm_out_file);
596 byte = (work & 0x7f);
597 /* arithmetic shift */
598 work >>= 7;
599 more = !((work == 0 && (byte & 0x40) == 0)
600 || (work == -1 && (byte & 0x40) != 0));
601 if (more)
602 byte |= 0x80;
604 if (byte_op)
606 fprintf (asm_out_file, "0x%x", byte);
607 if (more)
608 fputc (',', asm_out_file);
610 else
611 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
613 while (more);
615 if (flag_debug_asm)
617 fprintf (asm_out_file, "\t%s sleb128 ", ASM_COMMENT_START);
618 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, value);
619 if (comment)
621 fputs ("; ", asm_out_file);
622 vfprintf (asm_out_file, comment, ap);
626 #endif
627 fputc ('\n', asm_out_file);
629 VA_CLOSE (ap);
632 void
633 dw2_asm_output_delta_uleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
634 const char *lab2 ATTRIBUTE_UNUSED,
635 const char *comment, ...))
637 VA_OPEN (ap, comment);
638 VA_FIXEDARG (ap, const char *, lab1);
639 VA_FIXEDARG (ap, const char *, lab2);
640 VA_FIXEDARG (ap, const char *, comment);
642 #ifdef HAVE_AS_LEB128
643 fputs ("\t.uleb128 ", asm_out_file);
644 assemble_name (asm_out_file, lab1);
645 fputc ('-', asm_out_file);
646 assemble_name (asm_out_file, lab2);
647 #else
648 abort ();
649 #endif
651 if (flag_debug_asm && comment)
653 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
654 vfprintf (asm_out_file, comment, ap);
656 fputc ('\n', asm_out_file);
658 VA_CLOSE (ap);
661 void
662 dw2_asm_output_delta_sleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
663 const char *lab2 ATTRIBUTE_UNUSED,
664 const char *comment, ...))
666 VA_OPEN (ap, comment);
667 VA_FIXEDARG (ap, const char *, lab1);
668 VA_FIXEDARG (ap, const char *, lab2);
669 VA_FIXEDARG (ap, const char *, comment);
671 #ifdef HAVE_AS_LEB128
672 fputs ("\t.sleb128 ", asm_out_file);
673 assemble_name (asm_out_file, lab1);
674 fputc ('-', asm_out_file);
675 assemble_name (asm_out_file, lab2);
676 #else
677 abort ();
678 #endif
680 if (flag_debug_asm && comment)
682 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
683 vfprintf (asm_out_file, comment, ap);
685 fputc ('\n', asm_out_file);
687 VA_CLOSE (ap);
690 static int mark_indirect_pool_entry PARAMS ((splay_tree_node, void *));
691 static void mark_indirect_pool PARAMS ((PTR arg));
692 static rtx dw2_force_const_mem PARAMS ((rtx));
693 static int dw2_output_indirect_constant_1 PARAMS ((splay_tree_node, void *));
695 static splay_tree indirect_pool;
697 #if defined(HAVE_GAS_HIDDEN) && defined(SUPPORTS_ONE_ONLY)
698 # define USE_LINKONCE_INDIRECT 1
699 #else
700 # define USE_LINKONCE_INDIRECT 0
701 #endif
703 /* Mark all indirect constants for GC. */
705 static int
706 mark_indirect_pool_entry (node, data)
707 splay_tree_node node;
708 void* data ATTRIBUTE_UNUSED;
710 ggc_mark_tree ((tree) node->value);
711 return 0;
714 /* Mark all indirect constants for GC. */
716 static void
717 mark_indirect_pool (arg)
718 PTR arg ATTRIBUTE_UNUSED;
720 splay_tree_foreach (indirect_pool, mark_indirect_pool_entry, NULL);
723 /* Put X, a SYMBOL_REF, in memory. Return a SYMBOL_REF to the allocated
724 memory. Differs from force_const_mem in that a single pool is used for
725 the entire unit of translation, and the memory is not guaranteed to be
726 "near" the function in any interesting sense. */
728 static rtx
729 dw2_force_const_mem (x)
730 rtx x;
732 splay_tree_node node;
733 const char *str;
734 tree decl;
736 if (! indirect_pool)
738 indirect_pool = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
739 ggc_add_root (&indirect_pool, 1, sizeof indirect_pool, mark_indirect_pool);
742 if (GET_CODE (x) != SYMBOL_REF)
743 abort ();
745 str = (* targetm.strip_name_encoding) (XSTR (x, 0));
746 node = splay_tree_lookup (indirect_pool, (splay_tree_key) str);
747 if (node)
748 decl = (tree) node->value;
749 else
751 tree id;
753 if (USE_LINKONCE_INDIRECT)
755 char *ref_name = alloca (strlen (str) + sizeof "DW.ref.");
757 sprintf (ref_name, "DW.ref.%s", str);
758 id = get_identifier (ref_name);
759 decl = build_decl (VAR_DECL, id, ptr_type_node);
760 DECL_ARTIFICIAL (decl) = 1;
761 TREE_PUBLIC (decl) = 1;
762 DECL_INITIAL (decl) = decl;
763 make_decl_one_only (decl);
765 else
767 extern int const_labelno;
768 char label[32];
770 ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
771 ++const_labelno;
772 id = get_identifier (label);
773 decl = build_decl (VAR_DECL, id, ptr_type_node);
774 DECL_ARTIFICIAL (decl) = 1;
775 TREE_STATIC (decl) = 1;
776 DECL_INITIAL (decl) = decl;
779 id = maybe_get_identifier (str);
780 if (id)
781 TREE_SYMBOL_REFERENCED (id) = 1;
783 splay_tree_insert (indirect_pool, (splay_tree_key) str,
784 (splay_tree_value) decl);
787 return XEXP (DECL_RTL (decl), 0);
790 /* A helper function for dw2_output_indirect_constants called through
791 splay_tree_foreach. Emit one queued constant to memory. */
793 static int
794 dw2_output_indirect_constant_1 (node, data)
795 splay_tree_node node;
796 void* data ATTRIBUTE_UNUSED;
798 const char *sym;
799 rtx sym_ref;
801 sym = (const char *) node->key;
802 sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
803 if (USE_LINKONCE_INDIRECT)
804 fprintf (asm_out_file, "\t.hidden DW.ref.%s\n", sym);
805 assemble_variable ((tree) node->value, 1, 1, 1);
806 assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
808 return 0;
811 /* Emit the constants queued through dw2_force_const_mem. */
813 void
814 dw2_output_indirect_constants ()
816 if (indirect_pool)
817 splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL);
820 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed. */
822 void
823 dw2_asm_output_encoded_addr_rtx VPARAMS ((int encoding,
824 rtx addr,
825 const char *comment, ...))
827 int size;
829 VA_OPEN (ap, comment);
830 VA_FIXEDARG (ap, int, encoding);
831 VA_FIXEDARG (ap, rtx, addr);
832 VA_FIXEDARG (ap, const char *, comment);
834 size = size_of_encoded_value (encoding);
836 if (encoding == DW_EH_PE_aligned)
838 assemble_align (POINTER_SIZE);
839 assemble_integer (addr, size, POINTER_SIZE, 1);
840 return;
843 /* NULL is _always_ represented as a plain zero, as is 1 for Ada's
844 "all others". */
845 if (addr == const0_rtx || addr == const1_rtx)
846 assemble_integer (addr, size, BITS_PER_UNIT, 1);
847 else
849 restart:
850 /* Allow the target first crack at emitting this. Some of the
851 special relocations require special directives instead of
852 just ".4byte" or whatever. */
853 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
854 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
855 addr, done);
856 #endif
858 /* Indirection is used to get dynamic relocations out of a
859 read-only section. */
860 if (encoding & DW_EH_PE_indirect)
862 /* It is very tempting to use force_const_mem so that we share data
863 with the normal constant pool. However, we've already emitted
864 the constant pool for this function. Moreover, we'd like to
865 share these constants across the entire unit of translation,
866 or better, across the entire application (or DSO). */
867 addr = dw2_force_const_mem (addr);
868 encoding &= ~DW_EH_PE_indirect;
869 goto restart;
872 switch (encoding & 0xF0)
874 case DW_EH_PE_absptr:
875 dw2_assemble_integer (size, addr);
876 break;
878 case DW_EH_PE_pcrel:
879 if (GET_CODE (addr) != SYMBOL_REF)
880 abort ();
881 #ifdef ASM_OUTPUT_DWARF_PCREL
882 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
883 #else
884 dw2_assemble_integer (size, gen_rtx_MINUS (Pmode, addr, pc_rtx));
885 #endif
886 break;
888 default:
889 /* Other encodings should have been handled by
890 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
891 abort ();
894 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
895 done:;
896 #endif
899 if (flag_debug_asm && comment)
901 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
902 vfprintf (asm_out_file, comment, ap);
904 fputc ('\n', asm_out_file);
906 VA_CLOSE (ap);