OSDN Git Service

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