OSDN Git Service

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