OSDN Git Service

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