OSDN Git Service

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