OSDN Git Service

* doc/include/gcc-common.texi (version-GCC): Increase to 3.3.
[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 "flags.h"
25 #include "tree.h"
26 #include "rtl.h"
27 #include "output.h"
28 #include "target.h"
29 #include "dwarf2asm.h"
30 #include "dwarf2.h"
31 #include "splay-tree.h"
32 #include "ggc.h"
33 #include "tm_p.h"
34
35
36 /* How to start an assembler comment.  */
37 #ifndef ASM_COMMENT_START
38 #define ASM_COMMENT_START ";#"
39 #endif
40
41 \f
42 /* Output an unaligned integer with the given value and size.  Prefer not
43    to print a newline, since the caller may want to add a comment.  */
44
45 void
46 dw2_assemble_integer (size, x)
47      int size;
48      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 VPARAMS ((int size, unsigned HOST_WIDE_INT value,
69                               const char *comment, ...))
70 {
71   VA_OPEN (ap, comment);
72   VA_FIXEDARG (ap, int, size);
73   VA_FIXEDARG (ap, unsigned HOST_WIDE_INT, value);
74   VA_FIXEDARG (ap, const char *, comment);
75
76   if (size * 8 < HOST_BITS_PER_WIDE_INT)
77     value &= ~(~(unsigned HOST_WIDE_INT) 0 << (size * 8));
78
79   dw2_assemble_integer (size, GEN_INT (value));
80
81   if (flag_debug_asm && comment)
82     {
83       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
84       vfprintf (asm_out_file, comment, ap);
85     }
86   fputc ('\n', asm_out_file);
87
88   VA_CLOSE (ap);
89 }
90
91 /* Output the difference between two symbols in a given size.  */
92 /* ??? There appear to be assemblers that do not like such
93    subtraction, but do support ASM_SET_OP.  It's unfortunately
94    impossible to do here, since the ASM_SET_OP for the difference
95    symbol must appear after both symbols are defined.  */
96
97 void
98 dw2_asm_output_delta VPARAMS ((int size, const char *lab1, const char *lab2,
99                                const char *comment, ...))
100 {
101   VA_OPEN (ap, comment);
102   VA_FIXEDARG (ap, int, size);
103   VA_FIXEDARG (ap, const char *, lab1);
104   VA_FIXEDARG (ap, const char *, lab2);
105   VA_FIXEDARG (ap, const char *, comment);
106
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
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_CLOSE (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 VPARAMS ((int size, const char *label,
130                                const char *comment, ...))
131 {
132   VA_OPEN (ap, comment);
133   VA_FIXEDARG (ap, int, size);
134   VA_FIXEDARG (ap, const char *, label);
135   VA_FIXEDARG (ap, const char *, comment);
136
137 #ifdef ASM_OUTPUT_DWARF_OFFSET
138   ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label);
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_CLOSE (ap);
151 }
152
153 /* Output a self-relative reference to a label, possibly in a
154    different section or object file.  */
155
156 void
157 dw2_asm_output_pcrel VPARAMS ((int size ATTRIBUTE_UNUSED,
158                                const char *label ATTRIBUTE_UNUSED,
159                                const char *comment, ...))
160 {
161   VA_OPEN (ap, comment);
162   VA_FIXEDARG (ap, int, size);
163   VA_FIXEDARG (ap, const char *, label);
164   VA_FIXEDARG (ap, const char *, 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_CLOSE (ap);
183 }
184
185 /* Output an absolute reference to a label.  */
186
187 void
188 dw2_asm_output_addr VPARAMS ((int size, const char *label,
189                               const char *comment, ...))
190 {
191   VA_OPEN (ap, comment);
192   VA_FIXEDARG (ap, int, size);
193   VA_FIXEDARG (ap, const char *, label);
194   VA_FIXEDARG (ap, const char *, comment);
195
196   dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
197
198   if (flag_debug_asm && comment)
199     {
200       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
201       vfprintf (asm_out_file, comment, ap);
202     }
203   fputc ('\n', asm_out_file);
204
205   VA_CLOSE (ap);
206 }
207
208 /* Similar, but use an RTX expression instead of a text label.  */
209
210 void
211 dw2_asm_output_addr_rtx VPARAMS ((int size, rtx addr,
212                                   const char *comment, ...))
213 {
214   VA_OPEN (ap, comment);
215   VA_FIXEDARG (ap, int, size);
216   VA_FIXEDARG (ap, rtx, addr);
217   VA_FIXEDARG (ap, const char *, 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_CLOSE (ap);
229 }
230
231 void
232 dw2_asm_output_nstring VPARAMS ((const char *str, size_t orig_len,
233                                  const char *comment, ...))
234 {
235   size_t i, len;
236
237   VA_OPEN (ap, comment);
238   VA_FIXEDARG (ap, const char *, str);
239   VA_FIXEDARG (ap, size_t, orig_len);
240   VA_FIXEDARG (ap, const char *, comment);
241
242   len = orig_len;
243
244   if (len == (size_t) -1)
245     len = strlen (str);
246
247   if (flag_debug_asm && comment)
248     {
249       fputs ("\t.ascii \"", asm_out_file);
250       for (i = 0; i < len; i++)
251         {
252           int c = str[i];
253           if (c == '\"' || c == '\\')
254             fputc ('\\', asm_out_file);
255           if (ISPRINT(c))
256             fputc (c, asm_out_file);
257           else
258             fprintf (asm_out_file, "\\%o", c);
259         }
260       fprintf (asm_out_file, "\\0\"\t%s ", ASM_COMMENT_START);
261       vfprintf (asm_out_file, comment, ap);
262       fputc ('\n', asm_out_file);
263     }
264   else
265     {
266       /* If an explicit length was given, we can't assume there
267          is a null termination in the string buffer.  */
268       if (orig_len == (size_t) -1)
269         len += 1;
270       ASM_OUTPUT_ASCII (asm_out_file, str, len);
271       if (orig_len != (size_t) -1)
272         assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1);
273     }
274
275   VA_CLOSE (ap);
276 }
277 \f
278
279 /* Return the size of an unsigned LEB128 quantity.  */
280
281 int
282 size_of_uleb128 (value)
283      unsigned HOST_WIDE_INT value;
284 {
285   int size = 0, byte;
286
287   do
288     {
289       byte = (value & 0x7f);
290       value >>= 7;
291       size += 1;
292     }
293   while (value != 0);
294
295   return size;
296 }
297
298 /* Return the size of a signed LEB128 quantity.  */
299
300 int
301 size_of_sleb128 (value)
302      HOST_WIDE_INT value;
303 {
304   int size = 0, byte;
305
306   do
307     {
308       byte = (value & 0x7f);
309       value >>= 7;
310       size += 1;
311     }
312   while (!((value == 0 && (byte & 0x40) == 0)
313            || (value == -1 && (byte & 0x40) != 0)));
314
315   return size;
316 }
317
318 /* Given an encoding, return the number of bytes the format occupies.
319    This is only defined for fixed-size encodings, and so does not
320    include leb128.  */
321
322 int
323 size_of_encoded_value (encoding)
324      int encoding;
325 {
326   if (encoding == DW_EH_PE_omit)
327     return 0;
328
329   switch (encoding & 0x07)
330     {
331     case DW_EH_PE_absptr:
332       return POINTER_SIZE / BITS_PER_UNIT;
333     case DW_EH_PE_udata2:
334       return 2;
335     case DW_EH_PE_udata4:
336       return 4;
337     case DW_EH_PE_udata8:
338       return 8;
339     }
340   abort ();
341 }
342
343 /* Yield a name for a given pointer encoding.  */
344
345 const char *
346 eh_data_format_name (format)
347      int format;
348 {
349 #if HAVE_DESIGNATED_INITIALIZERS
350 #define S(p, v)         [p] = v,
351 #else
352 #define S(p, v)         case p: return v;
353 #endif
354
355 #if HAVE_DESIGNATED_INITIALIZERS
356   __extension__ static const char * const format_names[256] = {
357 #else
358   switch (format) {
359 #endif
360
361   S(DW_EH_PE_absptr, "absolute")
362   S(DW_EH_PE_omit, "omit")
363   S(DW_EH_PE_aligned, "aligned absolute")
364
365   S(DW_EH_PE_uleb128, "uleb128")
366   S(DW_EH_PE_udata2, "udata2")
367   S(DW_EH_PE_udata4, "udata4")
368   S(DW_EH_PE_udata8, "udata8")
369   S(DW_EH_PE_sleb128, "sleb128")
370   S(DW_EH_PE_sdata2, "sdata2")
371   S(DW_EH_PE_sdata4, "sdata4")
372   S(DW_EH_PE_sdata8, "sdata8")
373
374   S(DW_EH_PE_absptr | DW_EH_PE_pcrel, "pcrel")
375   S(DW_EH_PE_uleb128 | DW_EH_PE_pcrel, "pcrel uleb128")
376   S(DW_EH_PE_udata2 | DW_EH_PE_pcrel, "pcrel udata2")
377   S(DW_EH_PE_udata4 | DW_EH_PE_pcrel, "pcrel udata4")
378   S(DW_EH_PE_udata8 | DW_EH_PE_pcrel, "pcrel udata8")
379   S(DW_EH_PE_sleb128 | DW_EH_PE_pcrel, "pcrel sleb128")
380   S(DW_EH_PE_sdata2 | DW_EH_PE_pcrel, "pcrel sdata2")
381   S(DW_EH_PE_sdata4 | DW_EH_PE_pcrel, "pcrel sdata4")
382   S(DW_EH_PE_sdata8 | DW_EH_PE_pcrel, "pcrel sdata8")
383
384   S(DW_EH_PE_absptr | DW_EH_PE_textrel, "textrel")
385   S(DW_EH_PE_uleb128 | DW_EH_PE_textrel, "textrel uleb128")
386   S(DW_EH_PE_udata2 | DW_EH_PE_textrel, "textrel udata2")
387   S(DW_EH_PE_udata4 | DW_EH_PE_textrel, "textrel udata4")
388   S(DW_EH_PE_udata8 | DW_EH_PE_textrel, "textrel udata8")
389   S(DW_EH_PE_sleb128 | DW_EH_PE_textrel, "textrel sleb128")
390   S(DW_EH_PE_sdata2 | DW_EH_PE_textrel, "textrel sdata2")
391   S(DW_EH_PE_sdata4 | DW_EH_PE_textrel, "textrel sdata4")
392   S(DW_EH_PE_sdata8 | DW_EH_PE_textrel, "textrel sdata8")
393
394   S(DW_EH_PE_absptr | DW_EH_PE_datarel, "datarel")
395   S(DW_EH_PE_uleb128 | DW_EH_PE_datarel, "datarel uleb128")
396   S(DW_EH_PE_udata2 | DW_EH_PE_datarel, "datarel udata2")
397   S(DW_EH_PE_udata4 | DW_EH_PE_datarel, "datarel udata4")
398   S(DW_EH_PE_udata8 | DW_EH_PE_datarel, "datarel udata8")
399   S(DW_EH_PE_sleb128 | DW_EH_PE_datarel, "datarel sleb128")
400   S(DW_EH_PE_sdata2 | DW_EH_PE_datarel, "datarel sdata2")
401   S(DW_EH_PE_sdata4 | DW_EH_PE_datarel, "datarel sdata4")
402   S(DW_EH_PE_sdata8 | DW_EH_PE_datarel, "datarel sdata8")
403
404   S(DW_EH_PE_absptr | DW_EH_PE_funcrel, "funcrel")
405   S(DW_EH_PE_uleb128 | DW_EH_PE_funcrel, "funcrel uleb128")
406   S(DW_EH_PE_udata2 | DW_EH_PE_funcrel, "funcrel udata2")
407   S(DW_EH_PE_udata4 | DW_EH_PE_funcrel, "funcrel udata4")
408   S(DW_EH_PE_udata8 | DW_EH_PE_funcrel, "funcrel udata8")
409   S(DW_EH_PE_sleb128 | DW_EH_PE_funcrel, "funcrel sleb128")
410   S(DW_EH_PE_sdata2 | DW_EH_PE_funcrel, "funcrel sdata2")
411   S(DW_EH_PE_sdata4 | DW_EH_PE_funcrel, "funcrel sdata4")
412   S(DW_EH_PE_sdata8 | DW_EH_PE_funcrel, "funcrel sdata8")
413
414   S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel,
415     "indirect pcrel")
416   S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel,
417     "indirect pcrel uleb128")
418   S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_pcrel,
419     "indirect pcrel udata2")
420   S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_pcrel,
421     "indirect pcrel udata4")
422   S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_pcrel,
423     "indirect pcrel udata8")
424   S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_pcrel,
425     "indirect pcrel sleb128")
426   S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_pcrel,
427     "indirect pcrel sdata2")
428   S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_pcrel,
429     "indirect pcrel sdata4")
430   S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_pcrel,
431     "indirect pcrel sdata8")
432
433   S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_textrel,
434     "indirect textrel")
435   S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_textrel,
436     "indirect textrel uleb128")
437   S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_textrel,
438     "indirect textrel udata2")
439   S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_textrel,
440     "indirect textrel udata4")
441   S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_textrel,
442     "indirect textrel udata8")
443   S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_textrel,
444     "indirect textrel sleb128")
445   S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_textrel,
446     "indirect textrel sdata2")
447   S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_textrel,
448     "indirect textrel sdata4")
449   S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_textrel,
450     "indirect textrel sdata8")
451
452   S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_datarel,
453     "indirect datarel")
454   S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_datarel,
455     "indirect datarel uleb128")
456   S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_datarel,
457     "indirect datarel udata2")
458   S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_datarel,
459     "indirect datarel udata4")
460   S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_datarel,
461     "indirect datarel udata8")
462   S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_datarel,
463     "indirect datarel sleb128")
464   S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_datarel,
465     "indirect datarel sdata2")
466   S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_datarel,
467     "indirect datarel sdata4")
468   S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_datarel,
469     "indirect datarel sdata8")
470
471   S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_funcrel,
472     "indirect funcrel")
473   S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_funcrel,
474     "indirect funcrel uleb128")
475   S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_funcrel,
476     "indirect funcrel udata2")
477   S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_funcrel,
478     "indirect funcrel udata4")
479   S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_funcrel,
480     "indirect funcrel udata8")
481   S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_funcrel,
482     "indirect funcrel sleb128")
483   S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_funcrel,
484     "indirect funcrel sdata2")
485   S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_funcrel,
486     "indirect funcrel sdata4")
487   S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_funcrel,
488     "indirect funcrel sdata8")
489
490 #if HAVE_DESIGNATED_INITIALIZERS
491   };
492
493   if (format < 0 || format > 0xff || format_names[format] == NULL)
494     abort ();
495   return format_names[format];
496 #else
497   }
498   abort ();
499 #endif
500 }
501
502 /* Output an unsigned LEB128 quantity.  */
503
504 void
505 dw2_asm_output_data_uleb128 VPARAMS ((unsigned HOST_WIDE_INT value,
506                                       const char *comment, ...))
507 {
508   VA_OPEN (ap, comment);
509   VA_FIXEDARG (ap, unsigned HOST_WIDE_INT, value);
510   VA_FIXEDARG (ap, const char *, comment);
511
512 #ifdef HAVE_AS_LEB128
513   fputs ("\t.uleb128 ", asm_out_file);
514   fprintf (asm_out_file, 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 ", ASM_COMMENT_START);
550       fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, 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_CLOSE (ap);
562 }
563
564 /* Output an signed LEB128 quantity.  */
565
566 void
567 dw2_asm_output_data_sleb128 VPARAMS ((HOST_WIDE_INT value,
568                                       const char *comment, ...))
569 {
570   VA_OPEN (ap, comment);
571   VA_FIXEDARG (ap, HOST_WIDE_INT, value);
572   VA_FIXEDARG (ap, const char *, comment);
573
574 #ifdef HAVE_AS_LEB128
575   fputs ("\t.sleb128 ", asm_out_file);
576   fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, value);
577
578   if (flag_debug_asm && comment)
579     {
580       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
581       vfprintf (asm_out_file, comment, ap);
582     }
583 #else
584   {
585     HOST_WIDE_INT work = value;
586     int more, byte;
587     const char *byte_op = targetm.asm_out.byte_op;
588
589     if (byte_op)
590       fputs (byte_op, asm_out_file);
591     do
592       {
593         byte = (work & 0x7f);
594         /* arithmetic shift */
595         work >>= 7;
596         more = !((work == 0 && (byte & 0x40) == 0)
597                  || (work == -1 && (byte & 0x40) != 0));
598         if (more)
599           byte |= 0x80;
600
601         if (byte_op)
602           {
603             fprintf (asm_out_file, "0x%x", byte);
604             if (more)
605               fputc (',', asm_out_file);
606           }
607         else
608           assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
609       }
610     while (more);
611
612   if (flag_debug_asm)
613     {
614       fprintf (asm_out_file, "\t%s sleb128 ", ASM_COMMENT_START);
615       fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, value);
616       if (comment)
617         {
618           fputs ("; ", asm_out_file);
619           vfprintf (asm_out_file, comment, ap);
620         }
621     }
622   }
623 #endif
624   fputc ('\n', asm_out_file);
625
626   VA_CLOSE (ap);
627 }
628
629 void
630 dw2_asm_output_delta_uleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
631                                        const char *lab2 ATTRIBUTE_UNUSED,
632                                        const char *comment, ...))
633 {
634   VA_OPEN (ap, comment);
635   VA_FIXEDARG (ap, const char *, lab1);
636   VA_FIXEDARG (ap, const char *, lab2);
637   VA_FIXEDARG (ap, const char *, comment);
638
639 #ifdef HAVE_AS_LEB128
640   fputs ("\t.uleb128 ", asm_out_file);
641   assemble_name (asm_out_file, lab1);
642   fputc ('-', asm_out_file);
643   assemble_name (asm_out_file, lab2);
644 #else
645   abort ();
646 #endif
647
648   if (flag_debug_asm && comment)
649     {
650       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
651       vfprintf (asm_out_file, comment, ap);
652     }
653   fputc ('\n', asm_out_file);
654
655   VA_CLOSE (ap);
656 }
657
658 void
659 dw2_asm_output_delta_sleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
660                                        const char *lab2 ATTRIBUTE_UNUSED,
661                                        const char *comment, ...))
662 {
663   VA_OPEN (ap, comment);
664   VA_FIXEDARG (ap, const char *, lab1);
665   VA_FIXEDARG (ap, const char *, lab2);
666   VA_FIXEDARG (ap, const char *, comment);
667
668 #ifdef HAVE_AS_LEB128
669   fputs ("\t.sleb128 ", asm_out_file);
670   assemble_name (asm_out_file, lab1);
671   fputc ('-', asm_out_file);
672   assemble_name (asm_out_file, lab2);
673 #else
674   abort ();
675 #endif
676
677   if (flag_debug_asm && comment)
678     {
679       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
680       vfprintf (asm_out_file, comment, ap);
681     }
682   fputc ('\n', asm_out_file);
683
684   VA_CLOSE (ap);
685 }
686 \f
687 static int mark_indirect_pool_entry PARAMS ((splay_tree_node, void *));
688 static void mark_indirect_pool PARAMS ((PTR arg));
689 static rtx dw2_force_const_mem PARAMS ((rtx));
690 static int dw2_output_indirect_constant_1 PARAMS ((splay_tree_node, void *));
691
692 static splay_tree indirect_pool;
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 /* Mark all indirect constants for GC.  */
701
702 static int
703 mark_indirect_pool_entry (node, data)
704      splay_tree_node node;
705      void* data ATTRIBUTE_UNUSED;
706 {
707   ggc_mark_tree ((tree) node->value);
708   return 0;
709 }
710
711 /* Mark all indirect constants for GC.  */
712
713 static void
714 mark_indirect_pool (arg)
715      PTR arg ATTRIBUTE_UNUSED;
716 {
717   splay_tree_foreach (indirect_pool, mark_indirect_pool_entry, NULL);
718 }
719
720 /* Put X, a SYMBOL_REF, in memory.  Return a SYMBOL_REF to the allocated
721    memory.  Differs from force_const_mem in that a single pool is used for
722    the entire unit of translation, and the memory is not guaranteed to be
723    "near" the function in any interesting sense.  */
724
725 static rtx
726 dw2_force_const_mem (x)
727      rtx x;
728 {
729   splay_tree_node node;
730   const char *str;
731   tree decl;
732
733   if (! indirect_pool)
734     {
735       indirect_pool = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
736       ggc_add_root (&indirect_pool, 1, sizeof indirect_pool, mark_indirect_pool);
737     }
738
739   if (GET_CODE (x) != SYMBOL_REF)
740     abort ();
741
742   str = (* targetm.strip_name_encoding) (XSTR (x, 0));
743   node = splay_tree_lookup (indirect_pool, (splay_tree_key) str);
744   if (node)
745     decl = (tree) node->value;
746   else
747     {
748       tree id;
749
750       if (USE_LINKONCE_INDIRECT)
751         {
752           char *ref_name = alloca (strlen (str) + sizeof "DW.ref.");
753
754           sprintf (ref_name, "DW.ref.%s", str);
755           id = get_identifier (ref_name);
756           decl = build_decl (VAR_DECL, id, ptr_type_node);
757           DECL_ARTIFICIAL (decl) = 1;
758           TREE_PUBLIC (decl) = 1;
759           DECL_INITIAL (decl) = decl;
760           make_decl_one_only (decl);
761         }
762       else
763         {
764           extern int const_labelno;
765           char label[32];
766
767           ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
768           ++const_labelno;
769           id = get_identifier (label);
770           decl = build_decl (VAR_DECL, id, ptr_type_node);
771           DECL_ARTIFICIAL (decl) = 1;
772           TREE_STATIC (decl) = 1;
773           DECL_INITIAL (decl) = decl;
774         }
775
776       id = maybe_get_identifier (str);
777       if (id)
778         TREE_SYMBOL_REFERENCED (id) = 1;
779
780       splay_tree_insert (indirect_pool, (splay_tree_key) str,
781                          (splay_tree_value) decl);
782     }
783
784   return XEXP (DECL_RTL (decl), 0);
785 }
786
787 /* A helper function for dw2_output_indirect_constants called through
788    splay_tree_foreach.  Emit one queued constant to memory.  */
789
790 static int
791 dw2_output_indirect_constant_1 (node, data)
792      splay_tree_node node;
793      void* data ATTRIBUTE_UNUSED;
794 {
795   const char *sym;
796   rtx sym_ref;
797
798   sym = (const char *) node->key;
799   sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
800   if (USE_LINKONCE_INDIRECT)
801     fprintf (asm_out_file, "\t.hidden DW.ref.%s\n", sym);
802   assemble_variable ((tree) node->value, 1, 1, 1);
803   assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
804
805   return 0;
806 }
807
808 /* Emit the constants queued through dw2_force_const_mem.  */
809
810 void
811 dw2_output_indirect_constants ()
812 {
813   if (indirect_pool)
814     splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL);
815 }
816
817 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.  */
818
819 void
820 dw2_asm_output_encoded_addr_rtx VPARAMS ((int encoding,
821                                           rtx addr,
822                                           const char *comment, ...))
823 {
824   int size;
825
826   VA_OPEN (ap, comment);
827   VA_FIXEDARG (ap, int, encoding);
828   VA_FIXEDARG (ap, rtx, addr);
829   VA_FIXEDARG (ap, const char *, comment);
830
831   size = size_of_encoded_value (encoding);
832
833   if (encoding == DW_EH_PE_aligned)
834     {
835       assemble_align (POINTER_SIZE);
836       assemble_integer (addr, size, POINTER_SIZE, 1);
837       return;
838     }
839
840   /* NULL is _always_ represented as a plain zero, as is 1 for Ada's
841      "all others".  */
842   if (addr == const0_rtx || addr == const1_rtx)
843     assemble_integer (addr, size, BITS_PER_UNIT, 1);
844   else
845     {
846     restart:
847       /* Allow the target first crack at emitting this.  Some of the
848          special relocations require special directives instead of
849          just ".4byte" or whatever.  */
850 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
851       ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
852                                          addr, done);
853 #endif
854
855       /* Indirection is used to get dynamic relocations out of a
856          read-only section.  */
857       if (encoding & DW_EH_PE_indirect)
858         {
859           /* It is very tempting to use force_const_mem so that we share data
860              with the normal constant pool.  However, we've already emitted
861              the constant pool for this function.  Moreover, we'd like to
862              share these constants across the entire unit of translation,
863              or better, across the entire application (or DSO).  */
864           addr = dw2_force_const_mem (addr);
865           encoding &= ~DW_EH_PE_indirect;
866           goto restart;
867         }
868
869       switch (encoding & 0xF0)
870         {
871         case DW_EH_PE_absptr:
872           dw2_assemble_integer (size, addr);
873           break;
874
875         case DW_EH_PE_pcrel:
876           if (GET_CODE (addr) != SYMBOL_REF)
877             abort ();
878 #ifdef ASM_OUTPUT_DWARF_PCREL
879           ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
880 #else
881           dw2_assemble_integer (size, gen_rtx_MINUS (Pmode, addr, pc_rtx));
882 #endif
883           break;
884
885         default:
886           /* Other encodings should have been handled by
887              ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX.  */
888           abort ();
889         }
890
891 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
892     done:;
893 #endif
894     }
895
896   if (flag_debug_asm && comment)
897     {
898       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
899       vfprintf (asm_out_file, comment, ap);
900     }
901   fputc ('\n', asm_out_file);
902
903   VA_CLOSE (ap);
904 }