OSDN Git Service

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