OSDN Git Service

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