OSDN Git Service

PR c++/27292
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2asm.c
1 /* Dwarf2 assembler output helper routines.
2    Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
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.
10
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.
15
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, 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301, USA.  */
20
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "flags.h"
27 #include "tree.h"
28 #include "rtl.h"
29 #include "output.h"
30 #include "target.h"
31 #include "dwarf2asm.h"
32 #include "dwarf2.h"
33 #include "splay-tree.h"
34 #include "ggc.h"
35 #include "tm_p.h"
36
37
38 /* How to start an assembler comment.  */
39 #ifndef ASM_COMMENT_START
40 #define ASM_COMMENT_START ";#"
41 #endif
42
43 \f
44 /* Output an unaligned integer with the given value and size.  Prefer not
45    to print a newline, since the caller may want to add a comment.  */
46
47 void
48 dw2_assemble_integer (int size, rtx x)
49 {
50   const char *op = integer_asm_op (size, FALSE);
51
52   if (op)
53     {
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);
59     }
60   else
61     assemble_integer (x, size, BITS_PER_UNIT, 1);
62 }
63
64
65 /* Output an immediate constant in a given size.  */
66
67 void
68 dw2_asm_output_data (int size, unsigned HOST_WIDE_INT value,
69                      const char *comment, ...)
70 {
71   va_list ap;
72
73   va_start (ap, comment);
74
75   if (size * 8 < HOST_BITS_PER_WIDE_INT)
76     value &= ~(~(unsigned HOST_WIDE_INT) 0 << (size * 8));
77
78   dw2_assemble_integer (size, GEN_INT (value));
79
80   if (flag_debug_asm && comment)
81     {
82       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
83       vfprintf (asm_out_file, comment, ap);
84     }
85   fputc ('\n', asm_out_file);
86
87   va_end (ap);
88 }
89
90 /* Output the difference between two symbols in a given size.  */
91 /* ??? There appear to be assemblers that do not like such
92    subtraction, but do support ASM_SET_OP.  It's unfortunately
93    impossible to do here, since the ASM_SET_OP for the difference
94    symbol must appear after both symbols are defined.  */
95
96 void
97 dw2_asm_output_delta (int size, const char *lab1, const char *lab2,
98                       const char *comment, ...)
99 {
100   va_list ap;
101
102   va_start (ap, comment);
103
104 #ifdef ASM_OUTPUT_DWARF_DELTA
105   ASM_OUTPUT_DWARF_DELTA (asm_out_file, size, lab1, lab2);
106 #else
107   dw2_assemble_integer (size,
108                         gen_rtx_MINUS (Pmode,
109                                        gen_rtx_SYMBOL_REF (Pmode, lab1),
110                                        gen_rtx_SYMBOL_REF (Pmode, lab2)));
111 #endif
112   if (flag_debug_asm && comment)
113     {
114       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
115       vfprintf (asm_out_file, comment, ap);
116     }
117   fputc ('\n', asm_out_file);
118
119   va_end (ap);
120 }
121
122 /* Output a section-relative reference to a LABEL, which was placed in
123    BASE.  In general this can only be done for debugging symbols.
124    E.g. on most targets with the GNU linker, this is accomplished with
125    a direct reference and the knowledge that the debugging section
126    will be placed at VMA 0.  Some targets have special relocations for
127    this that we must use.  */
128
129 void
130 dw2_asm_output_offset (int size, const char *label,
131                        section *base ATTRIBUTE_UNUSED,
132                        const char *comment, ...)
133 {
134   va_list ap;
135
136   va_start (ap, comment);
137
138 #ifdef ASM_OUTPUT_DWARF_OFFSET
139   ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label, base);
140 #else
141   dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
142 #endif
143
144   if (flag_debug_asm && comment)
145     {
146       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
147       vfprintf (asm_out_file, comment, ap);
148     }
149   fputc ('\n', asm_out_file);
150
151   va_end (ap);
152 }
153
154 #if 0
155
156 /* Output a self-relative reference to a label, possibly in a
157    different section or object file.  */
158
159 void
160 dw2_asm_output_pcrel (int size ATTRIBUTE_UNUSED,
161                       const char *label ATTRIBUTE_UNUSED,
162                       const char *comment, ...)
163 {
164   va_list ap;
165
166   va_start (ap, comment);
167
168 #ifdef ASM_OUTPUT_DWARF_PCREL
169   ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label);
170 #else
171   dw2_assemble_integer (size,
172                         gen_rtx_MINUS (Pmode,
173                                        gen_rtx_SYMBOL_REF (Pmode, label),
174                                        pc_rtx));
175 #endif
176
177   if (flag_debug_asm && comment)
178     {
179       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
180       vfprintf (asm_out_file, comment, ap);
181     }
182   fputc ('\n', asm_out_file);
183
184   va_end (ap);
185 }
186 #endif /* 0 */
187
188 /* Output an absolute reference to a label.  */
189
190 void
191 dw2_asm_output_addr (int size, const char *label,
192                      const char *comment, ...)
193 {
194   va_list ap;
195
196   va_start (ap, comment);
197
198   dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
199
200   if (flag_debug_asm && comment)
201     {
202       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
203       vfprintf (asm_out_file, comment, ap);
204     }
205   fputc ('\n', asm_out_file);
206
207   va_end (ap);
208 }
209
210 /* Similar, but use an RTX expression instead of a text label.  */
211
212 void
213 dw2_asm_output_addr_rtx (int size, rtx addr,
214                          const char *comment, ...)
215 {
216   va_list ap;
217
218   va_start (ap, comment);
219
220   dw2_assemble_integer (size, addr);
221
222   if (flag_debug_asm && comment)
223     {
224       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
225       vfprintf (asm_out_file, comment, ap);
226     }
227   fputc ('\n', asm_out_file);
228
229   va_end (ap);
230 }
231
232 /* Output the first ORIG_LEN characters of STR as a string.
233    If ORIG_LEN is equal to -1, ignore this parameter and output
234    the entire STR instead.
235    If COMMENT is not NULL and comments in the debug information
236    have been requested by the user, append the given COMMENT
237    to the generated output.  */
238    
239 void
240 dw2_asm_output_nstring (const char *str, size_t orig_len,
241                         const char *comment, ...)
242 {
243   size_t i, len;
244   va_list ap;
245
246   va_start (ap, comment);
247
248   len = orig_len;
249
250   if (len == (size_t) -1)
251     len = strlen (str);
252
253   if (flag_debug_asm && comment)
254     {
255       fputs ("\t.ascii \"", asm_out_file);
256       for (i = 0; i < len; i++)
257         {
258           int c = str[i];
259           if (c == '\"' || c == '\\')
260             fputc ('\\', asm_out_file);
261           if (ISPRINT(c))
262             fputc (c, asm_out_file);
263           else
264             fprintf (asm_out_file, "\\%o", c);
265         }
266       fprintf (asm_out_file, "\\0\"\t%s ", ASM_COMMENT_START);
267       vfprintf (asm_out_file, comment, ap);
268       fputc ('\n', asm_out_file);
269     }
270   else
271     {
272       /* If an explicit length was given, we can't assume there
273          is a null termination in the string buffer.  */
274       if (orig_len == (size_t) -1)
275         len += 1;
276       ASM_OUTPUT_ASCII (asm_out_file, str, len);
277       if (orig_len != (size_t) -1)
278         assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1);
279     }
280
281   va_end (ap);
282 }
283 \f
284
285 /* Return the size of an unsigned LEB128 quantity.  */
286
287 int
288 size_of_uleb128 (unsigned HOST_WIDE_INT value)
289 {
290   int size = 0;
291
292   do
293     {
294       value >>= 7;
295       size += 1;
296     }
297   while (value != 0);
298
299   return size;
300 }
301
302 /* Return the size of a signed LEB128 quantity.  */
303
304 int
305 size_of_sleb128 (HOST_WIDE_INT value)
306 {
307   int size = 0, byte;
308
309   do
310     {
311       byte = (value & 0x7f);
312       value >>= 7;
313       size += 1;
314     }
315   while (!((value == 0 && (byte & 0x40) == 0)
316            || (value == -1 && (byte & 0x40) != 0)));
317
318   return size;
319 }
320
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.  */
324
325 int
326 size_of_encoded_value (int encoding)
327 {
328   if (encoding == DW_EH_PE_omit)
329     return 0;
330
331   switch (encoding & 0x07)
332     {
333     case DW_EH_PE_absptr:
334       return POINTER_SIZE / BITS_PER_UNIT;
335     case DW_EH_PE_udata2:
336       return 2;
337     case DW_EH_PE_udata4:
338       return 4;
339     case DW_EH_PE_udata8:
340       return 8;
341     default:
342       gcc_unreachable ();
343     }
344 }
345
346 /* Yield a name for a given pointer encoding.  */
347
348 const char *
349 eh_data_format_name (int format)
350 {
351 #if HAVE_DESIGNATED_INITIALIZERS
352 #define S(p, v)         [p] = v,
353 #else
354 #define S(p, v)         case p: return v;
355 #endif
356
357 #if HAVE_DESIGNATED_INITIALIZERS
358   __extension__ static const char * const format_names[256] = {
359 #else
360   switch (format) {
361 #endif
362
363   S(DW_EH_PE_absptr, "absolute")
364   S(DW_EH_PE_omit, "omit")
365   S(DW_EH_PE_aligned, "aligned absolute")
366
367   S(DW_EH_PE_uleb128, "uleb128")
368   S(DW_EH_PE_udata2, "udata2")
369   S(DW_EH_PE_udata4, "udata4")
370   S(DW_EH_PE_udata8, "udata8")
371   S(DW_EH_PE_sleb128, "sleb128")
372   S(DW_EH_PE_sdata2, "sdata2")
373   S(DW_EH_PE_sdata4, "sdata4")
374   S(DW_EH_PE_sdata8, "sdata8")
375
376   S(DW_EH_PE_absptr | DW_EH_PE_pcrel, "pcrel")
377   S(DW_EH_PE_uleb128 | DW_EH_PE_pcrel, "pcrel uleb128")
378   S(DW_EH_PE_udata2 | DW_EH_PE_pcrel, "pcrel udata2")
379   S(DW_EH_PE_udata4 | DW_EH_PE_pcrel, "pcrel udata4")
380   S(DW_EH_PE_udata8 | DW_EH_PE_pcrel, "pcrel udata8")
381   S(DW_EH_PE_sleb128 | DW_EH_PE_pcrel, "pcrel sleb128")
382   S(DW_EH_PE_sdata2 | DW_EH_PE_pcrel, "pcrel sdata2")
383   S(DW_EH_PE_sdata4 | DW_EH_PE_pcrel, "pcrel sdata4")
384   S(DW_EH_PE_sdata8 | DW_EH_PE_pcrel, "pcrel sdata8")
385
386   S(DW_EH_PE_absptr | DW_EH_PE_textrel, "textrel")
387   S(DW_EH_PE_uleb128 | DW_EH_PE_textrel, "textrel uleb128")
388   S(DW_EH_PE_udata2 | DW_EH_PE_textrel, "textrel udata2")
389   S(DW_EH_PE_udata4 | DW_EH_PE_textrel, "textrel udata4")
390   S(DW_EH_PE_udata8 | DW_EH_PE_textrel, "textrel udata8")
391   S(DW_EH_PE_sleb128 | DW_EH_PE_textrel, "textrel sleb128")
392   S(DW_EH_PE_sdata2 | DW_EH_PE_textrel, "textrel sdata2")
393   S(DW_EH_PE_sdata4 | DW_EH_PE_textrel, "textrel sdata4")
394   S(DW_EH_PE_sdata8 | DW_EH_PE_textrel, "textrel sdata8")
395
396   S(DW_EH_PE_absptr | DW_EH_PE_datarel, "datarel")
397   S(DW_EH_PE_uleb128 | DW_EH_PE_datarel, "datarel uleb128")
398   S(DW_EH_PE_udata2 | DW_EH_PE_datarel, "datarel udata2")
399   S(DW_EH_PE_udata4 | DW_EH_PE_datarel, "datarel udata4")
400   S(DW_EH_PE_udata8 | DW_EH_PE_datarel, "datarel udata8")
401   S(DW_EH_PE_sleb128 | DW_EH_PE_datarel, "datarel sleb128")
402   S(DW_EH_PE_sdata2 | DW_EH_PE_datarel, "datarel sdata2")
403   S(DW_EH_PE_sdata4 | DW_EH_PE_datarel, "datarel sdata4")
404   S(DW_EH_PE_sdata8 | DW_EH_PE_datarel, "datarel sdata8")
405
406   S(DW_EH_PE_absptr | DW_EH_PE_funcrel, "funcrel")
407   S(DW_EH_PE_uleb128 | DW_EH_PE_funcrel, "funcrel uleb128")
408   S(DW_EH_PE_udata2 | DW_EH_PE_funcrel, "funcrel udata2")
409   S(DW_EH_PE_udata4 | DW_EH_PE_funcrel, "funcrel udata4")
410   S(DW_EH_PE_udata8 | DW_EH_PE_funcrel, "funcrel udata8")
411   S(DW_EH_PE_sleb128 | DW_EH_PE_funcrel, "funcrel sleb128")
412   S(DW_EH_PE_sdata2 | DW_EH_PE_funcrel, "funcrel sdata2")
413   S(DW_EH_PE_sdata4 | DW_EH_PE_funcrel, "funcrel sdata4")
414   S(DW_EH_PE_sdata8 | DW_EH_PE_funcrel, "funcrel sdata8")
415
416   S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel,
417     "indirect pcrel")
418   S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel,
419     "indirect pcrel uleb128")
420   S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_pcrel,
421     "indirect pcrel udata2")
422   S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_pcrel,
423     "indirect pcrel udata4")
424   S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_pcrel,
425     "indirect pcrel udata8")
426   S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_pcrel,
427     "indirect pcrel sleb128")
428   S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_pcrel,
429     "indirect pcrel sdata2")
430   S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_pcrel,
431     "indirect pcrel sdata4")
432   S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_pcrel,
433     "indirect pcrel sdata8")
434
435   S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_textrel,
436     "indirect textrel")
437   S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_textrel,
438     "indirect textrel uleb128")
439   S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_textrel,
440     "indirect textrel udata2")
441   S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_textrel,
442     "indirect textrel udata4")
443   S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_textrel,
444     "indirect textrel udata8")
445   S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_textrel,
446     "indirect textrel sleb128")
447   S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_textrel,
448     "indirect textrel sdata2")
449   S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_textrel,
450     "indirect textrel sdata4")
451   S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_textrel,
452     "indirect textrel sdata8")
453
454   S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_datarel,
455     "indirect datarel")
456   S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_datarel,
457     "indirect datarel uleb128")
458   S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_datarel,
459     "indirect datarel udata2")
460   S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_datarel,
461     "indirect datarel udata4")
462   S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_datarel,
463     "indirect datarel udata8")
464   S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_datarel,
465     "indirect datarel sleb128")
466   S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_datarel,
467     "indirect datarel sdata2")
468   S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_datarel,
469     "indirect datarel sdata4")
470   S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_datarel,
471     "indirect datarel sdata8")
472
473   S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_funcrel,
474     "indirect funcrel")
475   S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_funcrel,
476     "indirect funcrel uleb128")
477   S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_funcrel,
478     "indirect funcrel udata2")
479   S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_funcrel,
480     "indirect funcrel udata4")
481   S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_funcrel,
482     "indirect funcrel udata8")
483   S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_funcrel,
484     "indirect funcrel sleb128")
485   S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_funcrel,
486     "indirect funcrel sdata2")
487   S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_funcrel,
488     "indirect funcrel sdata4")
489   S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_funcrel,
490     "indirect funcrel sdata8")
491
492 #if HAVE_DESIGNATED_INITIALIZERS
493   };
494
495   gcc_assert (format >= 0 && format < 0x100 && format_names[format]);
496   
497   return format_names[format];
498 #else
499   }
500   gcc_unreachable ();
501 #endif
502 }
503
504 /* Output an unsigned LEB128 quantity.  */
505
506 void
507 dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value,
508                              const char *comment, ...)
509 {
510   va_list ap;
511
512   va_start (ap, comment);
513
514 #ifdef HAVE_AS_LEB128
515   fprintf (asm_out_file, "\t.uleb128 " HOST_WIDE_INT_PRINT_HEX , value);
516
517   if (flag_debug_asm && comment)
518     {
519       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
520       vfprintf (asm_out_file, comment, ap);
521     }
522 #else
523   {
524     unsigned HOST_WIDE_INT work = value;
525     const char *byte_op = targetm.asm_out.byte_op;
526
527     if (byte_op)
528       fputs (byte_op, asm_out_file);
529     do
530       {
531         int byte = (work & 0x7f);
532         work >>= 7;
533         if (work != 0)
534           /* More bytes to follow.  */
535           byte |= 0x80;
536
537         if (byte_op)
538           {
539             fprintf (asm_out_file, "0x%x", byte);
540             if (work != 0)
541               fputc (',', asm_out_file);
542           }
543         else
544           assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
545       }
546     while (work != 0);
547
548   if (flag_debug_asm)
549     {
550       fprintf (asm_out_file, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX,
551                ASM_COMMENT_START, value);
552       if (comment)
553         {
554           fputs ("; ", asm_out_file);
555           vfprintf (asm_out_file, comment, ap);
556         }
557     }
558   }
559 #endif
560   fputc ('\n', asm_out_file);
561
562   va_end (ap);
563 }
564
565 /* Output a signed LEB128 quantity.  */
566
567 void
568 dw2_asm_output_data_sleb128 (HOST_WIDE_INT value,
569                              const char *comment, ...)
570 {
571   va_list ap;
572
573   va_start (ap, comment);
574
575 #ifdef HAVE_AS_LEB128
576   fprintf (asm_out_file, "\t.sleb128 " HOST_WIDE_INT_PRINT_DEC, value);
577
578   if (flag_debug_asm && comment)
579     {
580       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
581       vfprintf (asm_out_file, comment, ap);
582     }
583 #else
584   {
585     HOST_WIDE_INT work = value;
586     int more, byte;
587     const char *byte_op = targetm.asm_out.byte_op;
588
589     if (byte_op)
590       fputs (byte_op, asm_out_file);
591     do
592       {
593         byte = (work & 0x7f);
594         /* arithmetic shift */
595         work >>= 7;
596         more = !((work == 0 && (byte & 0x40) == 0)
597                  || (work == -1 && (byte & 0x40) != 0));
598         if (more)
599           byte |= 0x80;
600
601         if (byte_op)
602           {
603             fprintf (asm_out_file, "0x%x", byte);
604             if (more)
605               fputc (',', asm_out_file);
606           }
607         else
608           assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
609       }
610     while (more);
611
612   if (flag_debug_asm)
613     {
614       fprintf (asm_out_file, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC,
615                ASM_COMMENT_START, value);
616       if (comment)
617         {
618           fputs ("; ", asm_out_file);
619           vfprintf (asm_out_file, comment, ap);
620         }
621     }
622   }
623 #endif
624   fputc ('\n', asm_out_file);
625
626   va_end (ap);
627 }
628
629 void
630 dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
631                               const char *lab2 ATTRIBUTE_UNUSED,
632                               const char *comment, ...)
633 {
634   va_list ap;
635
636   va_start (ap, comment);
637
638 #ifdef HAVE_AS_LEB128
639   fputs ("\t.uleb128 ", asm_out_file);
640   assemble_name (asm_out_file, lab1);
641   fputc ('-', asm_out_file);
642   assemble_name (asm_out_file, lab2);
643 #else
644   gcc_unreachable ();
645 #endif
646
647   if (flag_debug_asm && comment)
648     {
649       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
650       vfprintf (asm_out_file, comment, ap);
651     }
652   fputc ('\n', asm_out_file);
653
654   va_end (ap);
655 }
656
657 #if 0
658
659 void
660 dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED,
661                               const char *lab2 ATTRIBUTE_UNUSED,
662                               const char *comment, ...)
663 {
664   va_list ap;
665
666   va_start (ap, comment);
667
668 #ifdef HAVE_AS_LEB128
669   fputs ("\t.sleb128 ", asm_out_file);
670   assemble_name (asm_out_file, lab1);
671   fputc ('-', asm_out_file);
672   assemble_name (asm_out_file, lab2);
673 #else
674   gcc_unreachable ();
675 #endif
676
677   if (flag_debug_asm && comment)
678     {
679       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
680       vfprintf (asm_out_file, comment, ap);
681     }
682   fputc ('\n', asm_out_file);
683
684   va_end (ap);
685 }
686 #endif /* 0 */
687 \f
688 static rtx dw2_force_const_mem (rtx, bool);
689 static int dw2_output_indirect_constant_1 (splay_tree_node, void *);
690
691 static GTY((param1_is (char *), param2_is (tree))) splay_tree indirect_pool;
692
693 static GTY(()) int dw2_const_labelno;
694
695 #if defined(HAVE_GAS_HIDDEN) && defined(SUPPORTS_ONE_ONLY)
696 # define USE_LINKONCE_INDIRECT 1
697 #else
698 # define USE_LINKONCE_INDIRECT 0
699 #endif
700
701 /* Put X, a SYMBOL_REF, in memory.  Return a SYMBOL_REF to the allocated
702    memory.  Differs from force_const_mem in that a single pool is used for
703    the entire unit of translation, and the memory is not guaranteed to be
704    "near" the function in any interesting sense.  PUBLIC controls whether
705    the symbol can be shared across the entire application (or DSO).  */
706
707 static rtx
708 dw2_force_const_mem (rtx x, bool public)
709 {
710   splay_tree_node node;
711   const char *str;
712   tree decl;
713
714   if (! indirect_pool)
715     indirect_pool = splay_tree_new_ggc (splay_tree_compare_pointers);
716
717   gcc_assert (GET_CODE (x) == SYMBOL_REF);
718
719   str = targetm.strip_name_encoding (XSTR (x, 0));
720   node = splay_tree_lookup (indirect_pool, (splay_tree_key) str);
721   if (node)
722     decl = (tree) node->value;
723   else
724     {
725       tree id;
726
727       if (public && USE_LINKONCE_INDIRECT)
728         {
729           char *ref_name = alloca (strlen (str) + sizeof "DW.ref.");
730
731           sprintf (ref_name, "DW.ref.%s", str);
732           id = get_identifier (ref_name);
733           decl = build_decl (VAR_DECL, id, ptr_type_node);
734           DECL_ARTIFICIAL (decl) = 1;
735           DECL_IGNORED_P (decl) = 1;
736           TREE_PUBLIC (decl) = 1;
737           DECL_INITIAL (decl) = decl;
738           make_decl_one_only (decl);
739         }
740       else
741         {
742           char label[32];
743
744           ASM_GENERATE_INTERNAL_LABEL (label, "LDFCM", dw2_const_labelno);
745           ++dw2_const_labelno;
746           id = get_identifier (label);
747           decl = build_decl (VAR_DECL, id, ptr_type_node);
748           DECL_ARTIFICIAL (decl) = 1;
749           DECL_IGNORED_P (decl) = 1;
750           TREE_STATIC (decl) = 1;
751           DECL_INITIAL (decl) = decl;
752         }
753
754       id = maybe_get_identifier (str);
755       if (id)
756         TREE_SYMBOL_REFERENCED (id) = 1;
757
758       splay_tree_insert (indirect_pool, (splay_tree_key) str,
759                          (splay_tree_value) decl);
760     }
761
762   return XEXP (DECL_RTL (decl), 0);
763 }
764
765 /* A helper function for dw2_output_indirect_constants called through
766    splay_tree_foreach.  Emit one queued constant to memory.  */
767
768 static int
769 dw2_output_indirect_constant_1 (splay_tree_node node,
770                                 void *data ATTRIBUTE_UNUSED)
771 {
772   const char *sym;
773   rtx sym_ref;
774   tree decl;
775
776   sym = (const char *) node->key;
777   decl = (tree) node->value;
778   sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
779   if (TREE_PUBLIC (decl) && USE_LINKONCE_INDIRECT)
780     fprintf (asm_out_file, "\t.hidden %sDW.ref.%s\n", user_label_prefix, sym);
781   assemble_variable (decl, 1, 1, 1);
782   assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
783
784   return 0;
785 }
786
787 /* Emit the constants queued through dw2_force_const_mem.  */
788
789 void
790 dw2_output_indirect_constants (void)
791 {
792   if (indirect_pool)
793     splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL);
794 }
795
796 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.
797    If PUBLIC is set and the encoding is DW_EH_PE_indirect, the indirect
798    reference is shared across the entire application (or DSO).  */
799
800 void
801 dw2_asm_output_encoded_addr_rtx (int encoding, rtx addr, bool public,
802                                  const char *comment, ...)
803 {
804   int size;
805   va_list ap;
806
807   va_start (ap, comment);
808
809   size = size_of_encoded_value (encoding);
810
811   if (encoding == DW_EH_PE_aligned)
812     {
813       assemble_align (POINTER_SIZE);
814       assemble_integer (addr, size, POINTER_SIZE, 1);
815       return;
816     }
817
818   /* NULL is _always_ represented as a plain zero, as is 1 for Ada's
819      "all others".  */
820   if (addr == const0_rtx || addr == const1_rtx)
821     assemble_integer (addr, size, BITS_PER_UNIT, 1);
822   else
823     {
824     restart:
825       /* Allow the target first crack at emitting this.  Some of the
826          special relocations require special directives instead of
827          just ".4byte" or whatever.  */
828 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
829       ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
830                                          addr, done);
831 #endif
832
833       /* Indirection is used to get dynamic relocations out of a
834          read-only section.  */
835       if (encoding & DW_EH_PE_indirect)
836         {
837           /* It is very tempting to use force_const_mem so that we share data
838              with the normal constant pool.  However, we've already emitted
839              the constant pool for this function.  Moreover, we'd like to
840              share these constants across the entire unit of translation and
841              even, if possible, across the entire application (or DSO).  */
842           addr = dw2_force_const_mem (addr, public);
843           encoding &= ~DW_EH_PE_indirect;
844           goto restart;
845         }
846
847       switch (encoding & 0xF0)
848         {
849         case DW_EH_PE_absptr:
850           dw2_assemble_integer (size, addr);
851           break;
852
853         case DW_EH_PE_pcrel:
854           gcc_assert (GET_CODE (addr) == SYMBOL_REF);
855 #ifdef ASM_OUTPUT_DWARF_PCREL
856           ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
857 #else
858           dw2_assemble_integer (size, gen_rtx_MINUS (Pmode, addr, pc_rtx));
859 #endif
860           break;
861
862         default:
863           /* Other encodings should have been handled by
864              ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX.  */
865           gcc_unreachable ();
866         }
867
868 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
869     done:;
870 #endif
871     }
872
873   if (flag_debug_asm && comment)
874     {
875       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
876       vfprintf (asm_out_file, comment, ap);
877     }
878   fputc ('\n', asm_out_file);
879
880   va_end (ap);
881 }
882
883 #include "gt-dwarf2asm.h"