OSDN Git Service

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