OSDN Git Service

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