OSDN Git Service

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