OSDN Git Service

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