OSDN Git Service

* alpha.c (current_file_function_operand): Don't fail for profiling.
[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, const char *label,
194                                const char *comment, ...))
195 {
196   VA_OPEN (ap, comment);
197   VA_FIXEDARG (ap, int, size);
198   VA_FIXEDARG (ap, const char *, label);
199   VA_FIXEDARG (ap, const char *, comment);
200
201 #ifdef ASM_OUTPUT_DWARF_PCREL
202   ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label);
203 #else
204 #ifdef UNALIGNED_INT_ASM_OP
205   fputs (unaligned_integer_asm_op (size), asm_out_file);
206   assemble_name (asm_out_file, label);
207   fputc ('-', asm_out_file);
208   fputc ('.', asm_out_file);
209 #else
210   abort ();
211 #endif
212 #endif
213
214   if (flag_debug_asm && comment)
215     {
216       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
217       vfprintf (asm_out_file, comment, ap);
218     }
219   fputc ('\n', asm_out_file);
220
221   VA_CLOSE (ap);
222 }
223
224 /* Output an absolute reference to a label.  */
225
226 void
227 dw2_asm_output_addr VPARAMS ((int size, const char *label,
228                               const char *comment, ...))
229 {
230   VA_OPEN (ap, comment);
231   VA_FIXEDARG (ap, int, size);
232   VA_FIXEDARG (ap, const char *, label);
233   VA_FIXEDARG (ap, const char *, comment);
234
235 #ifdef UNALIGNED_INT_ASM_OP
236   fputs (unaligned_integer_asm_op (size), asm_out_file);
237   assemble_name (asm_out_file, label);
238 #else
239   assemble_integer (gen_rtx_SYMBOL_REF (Pmode, label), size, BITS_PER_UNIT, 1);
240 #endif
241
242   if (flag_debug_asm && comment)
243     {
244       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
245       vfprintf (asm_out_file, comment, ap);
246     }
247   fputc ('\n', asm_out_file);
248
249   VA_CLOSE (ap);
250 }
251
252 /* Similar, but use an RTX expression instead of a text label.  */
253
254 void
255 dw2_asm_output_addr_rtx VPARAMS ((int size, rtx addr,
256                                   const char *comment, ...))
257 {
258   VA_OPEN (ap, comment);
259   VA_FIXEDARG (ap, int, size);
260   VA_FIXEDARG (ap, rtx, addr);
261   VA_FIXEDARG (ap, const char *, comment);
262
263 #ifdef UNALIGNED_INT_ASM_OP
264   fputs (unaligned_integer_asm_op (size), asm_out_file);
265   output_addr_const (asm_out_file, addr);
266 #else
267   assemble_integer (addr, size, BITS_PER_UNIT, 1);
268 #endif
269
270   if (flag_debug_asm && comment)
271     {
272       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
273       vfprintf (asm_out_file, comment, ap);
274     }
275   fputc ('\n', asm_out_file);
276
277   VA_CLOSE (ap);
278 }
279
280 void
281 dw2_asm_output_nstring VPARAMS ((const char *str, size_t orig_len,
282                                  const char *comment, ...))
283 {
284   size_t i, len;
285
286   VA_OPEN (ap, comment);
287   VA_FIXEDARG (ap, const char *, str);
288   VA_FIXEDARG (ap, size_t, orig_len);
289   VA_FIXEDARG (ap, const char *, comment);
290
291   len = orig_len;
292
293   if (len == (size_t) -1)
294     len = strlen (str);
295
296   if (flag_debug_asm && comment)
297     {
298       fputs ("\t.ascii \"", asm_out_file);
299       for (i = 0; i < len; i++)
300         {
301           int c = str[i];
302           if (c == '\"' || c == '\\')
303             fputc ('\\', asm_out_file);
304           if (ISPRINT(c))
305             fputc (c, asm_out_file);
306           else
307             fprintf (asm_out_file, "\\%o", c);
308         }
309       fprintf (asm_out_file, "\\0\"\t%s ", ASM_COMMENT_START);
310       vfprintf (asm_out_file, comment, ap);
311       fputc ('\n', asm_out_file);
312     }
313   else
314     {
315       /* If an explicit length was given, we can't assume there
316          is a null termination in the string buffer.  */
317       if (orig_len == (size_t) -1)
318         len += 1;
319       ASM_OUTPUT_ASCII (asm_out_file, str, len);
320       if (orig_len != (size_t) -1)
321         fprintf (asm_out_file, "%s0\n", ASM_BYTE_OP);
322     }
323
324   VA_CLOSE (ap);
325 }
326 \f
327
328 /* Return the size of an unsigned LEB128 quantity.  */
329
330 int
331 size_of_uleb128 (value)
332      unsigned HOST_WIDE_INT value;
333 {
334   int size = 0, byte;
335
336   do
337     {
338       byte = (value & 0x7f);
339       value >>= 7;
340       size += 1;
341     }
342   while (value != 0);
343
344   return size;
345 }
346
347 /* Return the size of a signed LEB128 quantity.  */
348
349 int
350 size_of_sleb128 (value)
351      HOST_WIDE_INT value;
352 {
353   int size = 0, byte;
354
355   do
356     {
357       byte = (value & 0x7f);
358       value >>= 7;
359       size += 1;
360     }
361   while (!((value == 0 && (byte & 0x40) == 0)
362            || (value == -1 && (byte & 0x40) != 0)));
363
364   return size;
365 }
366
367 /* Given an encoding, return the number of bytes the format occupies.
368    This is only defined for fixed-size encodings, and so does not 
369    include leb128.  */
370
371 int
372 size_of_encoded_value (encoding)
373      int encoding;
374 {
375   if (encoding == DW_EH_PE_omit)
376     return 0;
377
378   switch (encoding & 0x07)
379     {
380     case DW_EH_PE_absptr:
381       return POINTER_SIZE / BITS_PER_UNIT;
382     case DW_EH_PE_udata2:
383       return 2;
384     case DW_EH_PE_udata4:
385       return 4;
386     case DW_EH_PE_udata8:
387       return 8;
388     }
389   abort ();
390 }
391
392 /* Yield a name for a given pointer encoding.  */
393
394 const char *
395 eh_data_format_name (format)
396      int format;
397 {
398 #if HAVE_DESIGNATED_INITIALIZERS
399 #define S(p, v)         [p] = v,
400 #else
401 #define S(p, v)         case p: return v;
402 #endif
403
404 #if HAVE_DESIGNATED_INITIALIZERS
405   __extension__ static const char * const format_names[256] = {
406 #else
407   switch (format) {
408 #endif
409
410   S(DW_EH_PE_absptr, "absolute")
411   S(DW_EH_PE_omit, "omit")
412   S(DW_EH_PE_aligned, "aligned absolute")
413
414   S(DW_EH_PE_uleb128, "uleb128")
415   S(DW_EH_PE_udata2, "udata2")
416   S(DW_EH_PE_udata4, "udata4")
417   S(DW_EH_PE_udata8, "udata8")
418   S(DW_EH_PE_sleb128, "sleb128")
419   S(DW_EH_PE_sdata2, "sdata2")
420   S(DW_EH_PE_sdata4, "sdata4")
421   S(DW_EH_PE_sdata8, "sdata8")
422
423   S(DW_EH_PE_absptr | DW_EH_PE_pcrel, "pcrel")
424   S(DW_EH_PE_uleb128 | DW_EH_PE_pcrel, "pcrel uleb128")
425   S(DW_EH_PE_udata2 | DW_EH_PE_pcrel, "pcrel udata2")
426   S(DW_EH_PE_udata4 | DW_EH_PE_pcrel, "pcrel udata4")
427   S(DW_EH_PE_udata8 | DW_EH_PE_pcrel, "pcrel udata8")
428   S(DW_EH_PE_sleb128 | DW_EH_PE_pcrel, "pcrel sleb128")
429   S(DW_EH_PE_sdata2 | DW_EH_PE_pcrel, "pcrel sdata2")
430   S(DW_EH_PE_sdata4 | DW_EH_PE_pcrel, "pcrel sdata4")
431   S(DW_EH_PE_sdata8 | DW_EH_PE_pcrel, "pcrel sdata8")
432
433   S(DW_EH_PE_absptr | DW_EH_PE_textrel, "textrel")
434   S(DW_EH_PE_uleb128 | DW_EH_PE_textrel, "textrel uleb128")
435   S(DW_EH_PE_udata2 | DW_EH_PE_textrel, "textrel udata2")
436   S(DW_EH_PE_udata4 | DW_EH_PE_textrel, "textrel udata4")
437   S(DW_EH_PE_udata8 | DW_EH_PE_textrel, "textrel udata8")
438   S(DW_EH_PE_sleb128 | DW_EH_PE_textrel, "textrel sleb128")
439   S(DW_EH_PE_sdata2 | DW_EH_PE_textrel, "textrel sdata2")
440   S(DW_EH_PE_sdata4 | DW_EH_PE_textrel, "textrel sdata4")
441   S(DW_EH_PE_sdata8 | DW_EH_PE_textrel, "textrel sdata8")
442
443   S(DW_EH_PE_absptr | DW_EH_PE_datarel, "datarel")
444   S(DW_EH_PE_uleb128 | DW_EH_PE_datarel, "datarel uleb128")
445   S(DW_EH_PE_udata2 | DW_EH_PE_datarel, "datarel udata2")
446   S(DW_EH_PE_udata4 | DW_EH_PE_datarel, "datarel udata4")
447   S(DW_EH_PE_udata8 | DW_EH_PE_datarel, "datarel udata8")
448   S(DW_EH_PE_sleb128 | DW_EH_PE_datarel, "datarel sleb128")
449   S(DW_EH_PE_sdata2 | DW_EH_PE_datarel, "datarel sdata2")
450   S(DW_EH_PE_sdata4 | DW_EH_PE_datarel, "datarel sdata4")
451   S(DW_EH_PE_sdata8 | DW_EH_PE_datarel, "datarel sdata8")
452
453   S(DW_EH_PE_absptr | DW_EH_PE_funcrel, "funcrel")
454   S(DW_EH_PE_uleb128 | DW_EH_PE_funcrel, "funcrel uleb128")
455   S(DW_EH_PE_udata2 | DW_EH_PE_funcrel, "funcrel udata2")
456   S(DW_EH_PE_udata4 | DW_EH_PE_funcrel, "funcrel udata4")
457   S(DW_EH_PE_udata8 | DW_EH_PE_funcrel, "funcrel udata8")
458   S(DW_EH_PE_sleb128 | DW_EH_PE_funcrel, "funcrel sleb128")
459   S(DW_EH_PE_sdata2 | DW_EH_PE_funcrel, "funcrel sdata2")
460   S(DW_EH_PE_sdata4 | DW_EH_PE_funcrel, "funcrel sdata4")
461   S(DW_EH_PE_sdata8 | DW_EH_PE_funcrel, "funcrel sdata8")
462
463   S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel,
464     "indirect pcrel")
465   S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel,
466     "indirect pcrel uleb128")
467   S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_pcrel,
468     "indirect pcrel udata2")
469   S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_pcrel,
470     "indirect pcrel udata4")
471   S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_pcrel,
472     "indirect pcrel udata8")
473   S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_pcrel,
474     "indirect pcrel sleb128")
475   S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_pcrel,
476     "indirect pcrel sdata2")
477   S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_pcrel,
478     "indirect pcrel sdata4")
479   S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_pcrel,
480     "indirect pcrel sdata8")
481
482   S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_textrel,
483     "indirect textrel")
484   S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_textrel,
485     "indirect textrel uleb128")
486   S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_textrel,
487     "indirect textrel udata2")
488   S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_textrel,
489     "indirect textrel udata4")
490   S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_textrel,
491     "indirect textrel udata8")
492   S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_textrel,
493     "indirect textrel sleb128")
494   S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_textrel,
495     "indirect textrel sdata2")
496   S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_textrel,
497     "indirect textrel sdata4")
498   S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_textrel,
499     "indirect textrel sdata8")
500
501   S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_datarel,
502     "indirect datarel")
503   S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_datarel,
504     "indirect datarel uleb128")
505   S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_datarel,
506     "indirect datarel udata2")
507   S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_datarel,
508     "indirect datarel udata4")
509   S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_datarel,
510     "indirect datarel udata8")
511   S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_datarel,
512     "indirect datarel sleb128")
513   S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_datarel,
514     "indirect datarel sdata2")
515   S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_datarel,
516     "indirect datarel sdata4")
517   S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_datarel,
518     "indirect datarel sdata8")
519
520   S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_funcrel,
521     "indirect funcrel")
522   S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_funcrel,
523     "indirect funcrel uleb128")
524   S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_funcrel,
525     "indirect funcrel udata2")
526   S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_funcrel,
527     "indirect funcrel udata4")
528   S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_funcrel,
529     "indirect funcrel udata8")
530   S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_funcrel,
531     "indirect funcrel sleb128")
532   S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_funcrel,
533     "indirect funcrel sdata2")
534   S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_funcrel,
535     "indirect funcrel sdata4")
536   S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_funcrel,
537     "indirect funcrel sdata8")
538
539 #if HAVE_DESIGNATED_INITIALIZERS
540   };
541
542   if (format < 0 || format > 0xff || format_names[format] == NULL)
543     abort ();
544   return format_names[format];
545 #else
546   }
547   abort ();
548 #endif
549 }
550
551 /* Output an unsigned LEB128 quantity.  */
552
553 void
554 dw2_asm_output_data_uleb128 VPARAMS ((unsigned HOST_WIDE_INT value,
555                                       const char *comment, ...))
556 {
557   VA_OPEN (ap, comment);
558   VA_FIXEDARG (ap, unsigned HOST_WIDE_INT, value);
559   VA_FIXEDARG (ap, const char *, comment);
560
561 #ifdef HAVE_AS_LEB128
562   fputs ("\t.uleb128 ", asm_out_file);
563   fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
564
565   if (flag_debug_asm && comment)
566     {
567       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
568       vfprintf (asm_out_file, comment, ap);
569     }
570 #else
571   {
572     unsigned HOST_WIDE_INT work = value;
573
574     fputs (ASM_BYTE_OP, asm_out_file);
575     do
576       {
577         int byte = (work & 0x7f);
578         work >>= 7;
579         if (work != 0)
580           /* More bytes to follow.  */
581           byte |= 0x80;
582
583         fprintf (asm_out_file, "0x%x", byte);
584         if (work != 0)
585           fputc (',', asm_out_file);
586       }
587     while (work != 0);
588
589   if (flag_debug_asm)
590     {
591       fprintf (asm_out_file, "\t%s uleb128 ", ASM_COMMENT_START);
592       fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
593       if (comment)
594         {
595           fputs ("; ", asm_out_file);
596           vfprintf (asm_out_file, comment, ap);
597         }
598     }
599   }
600 #endif
601   fputc ('\n', asm_out_file);
602
603   VA_CLOSE (ap);
604 }
605
606 /* Output an signed LEB128 quantity.  */
607
608 void
609 dw2_asm_output_data_sleb128 VPARAMS ((HOST_WIDE_INT value,
610                                       const char *comment, ...))
611 {
612   VA_OPEN (ap, comment);
613   VA_FIXEDARG (ap, HOST_WIDE_INT, value);
614   VA_FIXEDARG (ap, const char *, comment);
615
616 #ifdef HAVE_AS_LEB128
617   fputs ("\t.sleb128 ", asm_out_file);
618   fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, value);
619
620   if (flag_debug_asm && comment)
621     {
622       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
623       vfprintf (asm_out_file, comment, ap);
624     }
625 #else
626   {
627     HOST_WIDE_INT work = value;
628     int more, byte;
629
630     fputs (ASM_BYTE_OP, asm_out_file);
631     do
632       {
633         byte = (work & 0x7f);
634         /* arithmetic shift */
635         work >>= 7;
636         more = !((work == 0 && (byte & 0x40) == 0)
637                  || (work == -1 && (byte & 0x40) != 0));
638         if (more)
639           byte |= 0x80;
640
641         fprintf (asm_out_file, "0x%x", byte);
642         if (more)
643           fputc (',', asm_out_file);
644       }
645     while (more);
646
647   if (flag_debug_asm)
648     {
649       fprintf (asm_out_file, "\t%s sleb128 ", ASM_COMMENT_START);
650       fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, value);
651       if (comment)
652         {
653           fputs ("; ", asm_out_file);
654           vfprintf (asm_out_file, comment, ap);
655         }
656     }
657   }
658 #endif
659   fputc ('\n', asm_out_file);
660
661   VA_CLOSE (ap);
662 }
663
664 void
665 dw2_asm_output_delta_uleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
666                                        const char *lab2 ATTRIBUTE_UNUSED,
667                                        const char *comment, ...))
668 {
669   VA_OPEN (ap, comment);
670   VA_FIXEDARG (ap, const char *, lab1);
671   VA_FIXEDARG (ap, const char *, lab2);
672   VA_FIXEDARG (ap, const char *, comment);
673
674 #ifdef HAVE_AS_LEB128
675   fputs ("\t.uleb128 ", asm_out_file);
676   assemble_name (asm_out_file, lab1);
677   fputc ('-', asm_out_file);
678   assemble_name (asm_out_file, lab2);
679 #else
680   abort ();
681 #endif
682
683   if (flag_debug_asm && comment)
684     {
685       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
686       vfprintf (asm_out_file, comment, ap);
687     }
688   fputc ('\n', asm_out_file);
689
690   VA_CLOSE (ap);
691 }
692
693 void
694 dw2_asm_output_delta_sleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
695                                        const char *lab2 ATTRIBUTE_UNUSED,
696                                        const char *comment, ...))
697 {
698   VA_OPEN (ap, comment);
699   VA_FIXEDARG (ap, const char *, lab1);
700   VA_FIXEDARG (ap, const char *, lab2);
701   VA_FIXEDARG (ap, const char *, comment);
702
703 #ifdef HAVE_AS_LEB128
704   fputs ("\t.sleb128 ", asm_out_file);
705   assemble_name (asm_out_file, lab1);
706   fputc ('-', asm_out_file);
707   assemble_name (asm_out_file, lab2);
708 #else
709   abort ();
710 #endif
711
712   if (flag_debug_asm && comment)
713     {
714       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
715       vfprintf (asm_out_file, comment, ap);
716     }
717   fputc ('\n', asm_out_file);
718
719   VA_CLOSE (ap);
720 }
721 \f
722 static rtx dw2_force_const_mem PARAMS ((rtx));
723 static int dw2_output_indirect_constant_1 PARAMS ((splay_tree_node, void *));
724
725 static splay_tree indirect_pool;
726
727 /* Put X, a SYMBOL_REF, in memory.  Return a SYMBOL_REF to the allocated
728    memory.  Differs from force_const_mem in that a single pool is used for
729    the entire unit of translation, and the memory is not guaranteed to be
730    "near" the function in any interesting sense.  */
731
732 static rtx
733 dw2_force_const_mem (x)
734      rtx x;
735 {
736   splay_tree_node node;
737   const char *const_sym;
738
739   if (! indirect_pool)
740     indirect_pool = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
741
742   if (GET_CODE (x) != SYMBOL_REF)
743     abort ();
744   node = splay_tree_lookup (indirect_pool, (splay_tree_key) XSTR (x, 0));
745   if (node)
746     const_sym = (const char *) node->value;
747   else
748     {
749       extern int const_labelno;
750       char label[32];
751       tree id;
752
753       ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
754       ++const_labelno;
755       const_sym = ggc_strdup (label);
756
757       id = maybe_get_identifier (XSTR (x, 0));
758       if (id)
759         TREE_SYMBOL_REFERENCED (id) = 1;
760
761       splay_tree_insert (indirect_pool, (splay_tree_key) XSTR (x, 0),
762                          (splay_tree_value) const_sym);
763     }
764
765   return gen_rtx_SYMBOL_REF (Pmode, const_sym);
766 }
767
768 /* A helper function for dw2_output_indirect_constants called through
769    splay_tree_foreach.  Emit one queued constant to memory.  */
770
771 static int
772 dw2_output_indirect_constant_1 (node, data)
773      splay_tree_node node;
774      void* data ATTRIBUTE_UNUSED;
775 {
776   const char *label, *sym;
777   rtx sym_ref;
778
779   label = (const char *) node->value;
780   sym = (const char *) node->key;
781   sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
782
783   ASM_OUTPUT_LABEL (asm_out_file, label);
784   assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
785
786   return 0;
787 }
788
789 /* Emit the constants queued through dw2_force_const_mem.  */
790
791 void
792 dw2_output_indirect_constants ()
793 {
794   if (! indirect_pool)
795     return;
796
797   /* Assume that the whole reason we're emitting these symbol references
798      indirectly is that they contain dynamic relocations, and are thus
799      read-write.  If there was no possibility of a dynamic relocation, we
800      might as well have used a direct relocation.  */
801   data_section ();
802
803   /* Everything we're emitting is a pointer.  Align appropriately.  */
804   assemble_align (POINTER_SIZE);
805
806   splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL);
807 }
808
809 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.  */
810
811 void
812 dw2_asm_output_encoded_addr_rtx VPARAMS ((int encoding,
813                                           rtx addr,
814                                           const char *comment, ...))
815 {
816   int size;
817
818   VA_OPEN (ap, comment);
819   VA_FIXEDARG (ap, int, encoding);
820   VA_FIXEDARG (ap, rtx, addr);
821   VA_FIXEDARG (ap, const char *, comment);
822
823   size = size_of_encoded_value (encoding);
824
825   if (encoding == DW_EH_PE_aligned)
826     {
827       assemble_align (POINTER_SIZE);
828       assemble_integer (addr, size, POINTER_SIZE, 1);
829       return;
830     }
831
832   /* NULL is _always_ represented as a plain zero.  */
833   if (addr == const0_rtx)
834     assemble_integer (addr, size, BITS_PER_UNIT, 1);
835   else
836     {
837     restart:
838       /* Allow the target first crack at emitting this.  Some of the
839          special relocations require special directives instead of 
840          just ".4byte" or whatever.  */
841 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
842       ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
843                                          addr, done);
844 #endif
845
846       /* Indirection is used to get dynamic relocations out of a
847          read-only section.  */
848       if (encoding & DW_EH_PE_indirect)
849         {
850           /* It is very tempting to use force_const_mem so that we share data
851              with the normal constant pool.  However, we've already emitted
852              the constant pool for this function.  Moreover, we'd like to
853              share these constants across the entire unit of translation,
854              or better, across the entire application (or DSO).  */
855           addr = dw2_force_const_mem (addr);
856           encoding &= ~DW_EH_PE_indirect;
857           goto restart;
858         }
859
860       switch (encoding & 0xF0)
861         {
862         case DW_EH_PE_absptr:
863 #ifdef UNALIGNED_INT_ASM_OP
864           fputs (unaligned_integer_asm_op (size), asm_out_file);
865           output_addr_const (asm_out_file, addr);
866 #else
867           assemble_integer (addr, size, BITS_PER_UNIT, 1);
868 #endif
869           break;
870
871         case DW_EH_PE_pcrel:
872           if (GET_CODE (addr) != SYMBOL_REF)
873             abort ();
874 #ifdef ASM_OUTPUT_DWARF_PCREL
875           ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
876 #else
877 #ifdef UNALIGNED_INT_ASM_OP
878           fputs (unaligned_integer_asm_op (size), asm_out_file);
879           assemble_name (asm_out_file, XSTR (addr, 0));
880           fputc ('-', asm_out_file);
881           fputc ('.', asm_out_file);
882 #else
883           abort ();
884 #endif
885 #endif
886           break;
887
888         default:
889           /* Other encodings should have been handled by 
890              ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX.  */
891           abort ();
892         }
893
894 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
895     done:;
896 #endif
897     }
898
899   if (flag_debug_asm && comment)
900     {
901       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
902       vfprintf (asm_out_file, comment, ap);
903     }
904   fputc ('\n', asm_out_file);
905
906   VA_CLOSE (ap);
907 }