OSDN Git Service

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