OSDN Git Service

2001-04-10 Andrew MacLeod <amacleod@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2asm.c
1 /* Dwarf2 assembler output helper routines.
2    Copyright (C) 2001 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21
22 #include "config.h"
23 #include "system.h"
24 #include "flags.h"
25 #include "rtl.h"
26 #include "output.h"
27 #include "dwarf2asm.h"
28 #include "tm_p.h"
29
30
31 /* How to start an assembler comment.  */
32 #ifndef ASM_COMMENT_START
33 #define ASM_COMMENT_START ";#"
34 #endif
35
36 /* Definitions of defaults for assembler-dependent names of various
37    pseudo-ops and section names.  These may be overridden in the tm.h
38    file (if necessary) for a particular assembler.  */
39
40 #ifdef OBJECT_FORMAT_ELF
41 #ifndef UNALIGNED_SHORT_ASM_OP
42 #define UNALIGNED_SHORT_ASM_OP          "\t.2byte\t"
43 #endif
44 #ifndef UNALIGNED_INT_ASM_OP
45 #define UNALIGNED_INT_ASM_OP            "\t.4byte\t"
46 #endif
47 #ifndef UNALIGNED_DOUBLE_INT_ASM_OP
48 #define UNALIGNED_DOUBLE_INT_ASM_OP     "\t.8byte\t"
49 #endif
50 #endif /* OBJECT_FORMAT_ELF */
51
52 #ifndef ASM_BYTE_OP
53 #define ASM_BYTE_OP                     "\t.byte\t"
54 #endif
55
56 /* We don't have unaligned support, let's hope the normal output works for
57    .debug_frame.  But we know it won't work for .debug_info.  */
58 #if !defined(UNALIGNED_INT_ASM_OP) && defined(DWARF2_DEBUGGING_INFO)
59  #error DWARF2_DEBUGGING_INFO requires UNALIGNED_INT_ASM_OP.
60 #endif
61
62 \f
63 #ifdef UNALIGNED_INT_ASM_OP
64 static const char * unaligned_integer_asm_op  PARAMS ((int));
65
66 static inline const char *
67 unaligned_integer_asm_op (size)
68      int size;
69 {
70   const char *op;
71   switch (size)
72     {
73     case 1:
74       op = ASM_BYTE_OP;
75       break;
76     case 2:
77       op = UNALIGNED_SHORT_ASM_OP;
78       break;
79     case 4:
80       op = UNALIGNED_INT_ASM_OP;
81       break;
82     case 8:
83 #ifdef UNALIGNED_DOUBLE_INT_ASM_OP
84       op = UNALIGNED_DOUBLE_INT_ASM_OP;
85       break;
86 #endif
87     default:
88       abort ();
89     }
90   return op;
91 }
92 #endif /* UNALIGNED_INT_ASM_OP */
93
94 /* Output an immediate constant in a given size.  */
95
96 void
97 dw2_asm_output_data VPARAMS ((int size, unsigned HOST_WIDE_INT value,
98                               const char *comment, ...))
99 {
100 #ifndef ANSI_PROTOTYPES
101   int size;
102   unsigned HOST_WIDE_INT value;
103   const char *comment;
104 #endif
105   va_list ap;
106
107   VA_START (ap, comment);
108
109 #ifndef ANSI_PROTOTYPES
110   size = va_arg (ap, int);
111   value = va_arg (ap, unsigned HOST_WIDE_INT);
112   comment = va_arg (ap, const char *);
113 #endif
114
115   if (size * 8 < HOST_BITS_PER_WIDE_INT)
116     value &= ~(~(unsigned HOST_WIDE_INT)0 << (size * 8));
117
118 #ifdef UNALIGNED_INT_ASM_OP
119   fputs (unaligned_integer_asm_op (size), asm_out_file);
120   fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
121 #else
122   assemble_integer (GEN_INT (value), size, 1);
123 #endif
124
125   if (flag_debug_asm && comment)
126     {
127       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
128       vfprintf (asm_out_file, comment, ap);
129     }
130   fputc ('\n', asm_out_file);
131
132   va_end (ap);
133 }
134
135 /* Output the difference between two symbols in a given size.  */
136 /* ??? There appear to be assemblers that do not like such
137    subtraction, but do support ASM_SET_OP.  It's unfortunately
138    impossible to do here, since the ASM_SET_OP for the difference
139    symbol must appear after both symbols are defined.  */
140
141 void
142 dw2_asm_output_delta VPARAMS ((int size, const char *lab1, const char *lab2,
143                                const char *comment, ...))
144 {
145 #ifndef ANSI_PROTOTYPES
146   int size;
147   const char *lab1, *lab2;
148   const char *comment;
149 #endif
150   va_list ap;
151
152   VA_START (ap, comment);
153
154 #ifndef ANSI_PROTOTYPES
155   size = va_arg (ap, int);
156   lab1 = va_arg (ap, const char *);
157   lab2 = va_arg (ap, const char *);
158   comment = va_arg (ap, const char *);
159 #endif
160
161 #ifdef UNALIGNED_INT_ASM_OP
162   fputs (unaligned_integer_asm_op (size), asm_out_file);
163   assemble_name (asm_out_file, lab1);
164   fputc ('-', asm_out_file);
165   assemble_name (asm_out_file, lab2);
166 #else
167   assemble_integer (gen_rtx_MINUS (smallest_mode_for_size (size, MODE_INT),
168                                    gen_rtx_SYMBOL_REF (Pmode, lab1),
169                                    gen_rtx_SYMBOL_REF (Pmode, lab2)),
170                     size, 1);
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 a section-relative reference to a label.  In general this
184    can only be done for debugging symbols.  E.g. on most targets with
185    the GNU linker, this is accomplished with a direct reference and
186    the knowledge that the debugging section will be placed at VMA 0.
187    Some targets have special relocations for this that we must use.  */
188
189 void
190 dw2_asm_output_offset VPARAMS ((int size, const char *label,
191                                const char *comment, ...))
192 {
193 #ifndef ANSI_PROTOTYPES
194   int size;
195   const char *label;
196   const char *comment;
197 #endif
198   va_list ap;
199
200   VA_START (ap, comment);
201
202 #ifndef ANSI_PROTOTYPES
203   size = va_arg (ap, int);
204   label = va_arg (ap, const char *);
205   comment = va_arg (ap, const char *);
206 #endif
207
208 #ifdef ASM_OUTPUT_DWARF_OFFSET
209   ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label);
210 #else
211 #ifdef UNALIGNED_INT_ASM_OP
212   fputs (unaligned_integer_asm_op (size), asm_out_file);
213   assemble_name (asm_out_file, label);
214 #else
215   assemble_integer (gen_rtx_SYMBOL_REF (Pmode, label), size, 1);
216 #endif
217 #endif
218
219   if (flag_debug_asm && comment)
220     {
221       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
222       vfprintf (asm_out_file, comment, ap);
223     }
224   fputc ('\n', asm_out_file);
225
226   va_end (ap);
227 }
228
229 /* Output a self-relative reference to a label, possibly in a
230    different section or object file.  */
231
232 void
233 dw2_asm_output_pcrel VPARAMS ((int size, const char *label,
234                                const char *comment, ...))
235 {
236 #ifndef ANSI_PROTOTYPES
237   int size;
238   const char *label;
239   const char *comment;
240 #endif
241   va_list ap;
242
243   VA_START (ap, comment);
244
245 #ifndef ANSI_PROTOTYPES
246   size = va_arg (ap, int);
247   label = va_arg (ap, const char *);
248   comment = va_arg (ap, const char *);
249 #endif
250
251 #ifdef ASM_OUTPUT_DWARF_PCREL
252   ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label);
253 #else
254 #ifdef UNALIGNED_INT_ASM_OP
255   fputs (unaligned_integer_asm_op (size), asm_out_file);
256   assemble_name (asm_out_file, label);
257   fputc ('-', asm_out_file);
258   fputc ('.', asm_out_file);
259 #else
260   abort ();
261 #endif
262 #endif
263
264   if (flag_debug_asm && comment)
265     {
266       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
267       vfprintf (asm_out_file, comment, ap);
268     }
269   fputc ('\n', asm_out_file);
270
271   va_end (ap);
272 }
273
274 /* Output an absolute reference to a label.  */
275
276 void
277 dw2_asm_output_addr VPARAMS ((int size, const char *label,
278                               const char *comment, ...))
279 {
280 #ifndef ANSI_PROTOTYPES
281   int size;
282   const char *label;
283   const char *comment;
284 #endif
285   va_list ap;
286
287   VA_START (ap, comment);
288
289 #ifndef ANSI_PROTOTYPES
290   size = va_arg (ap, int);
291   label = va_arg (ap, const char *);
292   comment = va_arg (ap, const char *);
293 #endif
294
295 #ifdef UNALIGNED_INT_ASM_OP
296   fputs (unaligned_integer_asm_op (size), asm_out_file);
297   assemble_name (asm_out_file, label);
298 #else
299   assemble_integer (gen_rtx_SYMBOL_REF (Pmode, label), size, 1);
300 #endif
301
302   if (flag_debug_asm && comment)
303     {
304       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
305       vfprintf (asm_out_file, comment, ap);
306     }
307   fputc ('\n', asm_out_file);
308
309   va_end (ap);
310 }
311
312 /* Similar, but use an RTX expression instead of a text label.  */
313
314 void
315 dw2_asm_output_addr_rtx VPARAMS ((int size, rtx addr,
316                                   const char *comment, ...))
317 {
318 #ifndef ANSI_PROTOTYPES
319   int size;
320   rtx addr;
321   const char *comment;
322 #endif
323   va_list ap;
324
325   VA_START (ap, comment);
326
327 #ifndef ANSI_PROTOTYPES
328   size = va_arg (ap, int);
329   addr = va_arg (ap, rtx);
330   comment = va_arg (ap, const char *);
331 #endif
332
333 #ifdef UNALIGNED_INT_ASM_OP
334   fputs (unaligned_integer_asm_op (size), asm_out_file);
335   output_addr_const (asm_out_file, addr);
336 #else
337   assemble_integer (addr, size, 1);
338 #endif
339
340   if (flag_debug_asm && comment)
341     {
342       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
343       vfprintf (asm_out_file, comment, ap);
344     }
345   fputc ('\n', asm_out_file);
346
347   va_end (ap);
348 }
349
350 void
351 dw2_asm_output_nstring VPARAMS ((const char *str, size_t orig_len,
352                                  const char *comment, ...))
353 {
354 #ifndef ANSI_PROTOTYPES
355   const char *str;
356   size_t orig_len;
357   const char *comment;
358 #endif
359   va_list ap;
360   size_t i, len = orig_len;
361
362   VA_START (ap, comment);
363
364 #ifndef ANSI_PROTOTYPES
365   str = va_arg (ap, const char *);
366   len = va_arg (ap, size_t);
367   comment = va_arg (ap, const char *);
368 #endif
369
370   if (len == (size_t) -1)
371     len = strlen (str);
372
373   if (flag_debug_asm && comment)
374     {
375       fputs ("\t.ascii \"", asm_out_file);
376       for (i = 0; i < len; i++)
377         {
378           int c = str[i];
379           if (c == '\"' || c == '\\')
380             fputc ('\\', asm_out_file);
381           if (ISPRINT(c))
382             fputc (c, asm_out_file);
383           else
384             fprintf (asm_out_file, "\\%o", c);
385         }
386       fprintf (asm_out_file, "\\0\"\t%s ", ASM_COMMENT_START);
387       vfprintf (asm_out_file, comment, ap);
388       fputc ('\n', asm_out_file);
389     }
390   else
391     {
392       /* If an explicit length was given, we can't assume there
393          is a null termination in the string buffer.  */
394       if (orig_len == (size_t) -1)
395         len += 1;
396       ASM_OUTPUT_ASCII (asm_out_file, str, len);
397       if (orig_len != (size_t) -1)
398         fprintf (asm_out_file, "%s0\n", ASM_BYTE_OP);
399     }
400
401   va_end (ap);
402 }
403 \f
404
405 /* Return the size of an unsigned LEB128 quantity.  */
406
407 int
408 size_of_uleb128 (value)
409      unsigned HOST_WIDE_INT value;
410 {
411   int size = 0, byte;
412
413   do
414     {
415       byte = (value & 0x7f);
416       value >>= 7;
417       size += 1;
418     }
419   while (value != 0);
420
421   return size;
422 }
423
424 /* Return the size of a signed LEB128 quantity.  */
425
426 int
427 size_of_sleb128 (value)
428      HOST_WIDE_INT value;
429 {
430   int size = 0, byte;
431
432   do
433     {
434       byte = (value & 0x7f);
435       value >>= 7;
436       size += 1;
437     }
438   while (!((value == 0 && (byte & 0x40) == 0)
439            || (value == -1 && (byte & 0x40) != 0)));
440
441   return size;
442 }
443
444 /* Output an unsigned LEB128 quantity.  */
445
446 void
447 dw2_asm_output_data_uleb128 VPARAMS ((unsigned HOST_WIDE_INT value,
448                                       const char *comment, ...))
449 {
450 #ifndef ANSI_PROTOTYPES
451   unsigned HOST_WIDE_INT value;
452   const char *comment;
453 #endif
454   va_list ap;
455
456   VA_START (ap, comment);
457
458 #ifndef ANSI_PROTOTYPES
459   value = va_arg (ap, unsigned HOST_WIDE_INT);
460   comment = va_arg (ap, const char *);
461 #endif
462
463 #ifdef HAVE_AS_LEB128
464   fputs ("\t.uleb128 ", asm_out_file);
465   fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
466
467   if (flag_debug_asm && comment)
468     {
469       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
470       vfprintf (asm_out_file, comment, ap);
471     }
472 #else
473   {
474     unsigned HOST_WIDE_INT work = value;
475
476     fputs (ASM_BYTE_OP, asm_out_file);
477     do
478       {
479         int byte = (work & 0x7f);
480         work >>= 7;
481         if (work != 0)
482           /* More bytes to follow.  */
483           byte |= 0x80;
484
485         fprintf (asm_out_file, "0x%x", byte);
486         if (work != 0)
487           fputc (',', asm_out_file);
488       }
489     while (work != 0);
490
491   if (flag_debug_asm)
492     {
493       fprintf (asm_out_file, "\t%s uleb128 ", ASM_COMMENT_START);
494       fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
495       if (comment)
496         {
497           fputs ("; ", asm_out_file);
498           vfprintf (asm_out_file, comment, ap);
499         }
500     }
501   }
502 #endif
503   fputc ('\n', asm_out_file);
504
505   va_end (ap);
506 }
507
508 /* Output an signed LEB128 quantity.  */
509
510 void
511 dw2_asm_output_data_sleb128 VPARAMS ((HOST_WIDE_INT value,
512                                       const char *comment, ...))
513 {
514 #ifndef ANSI_PROTOTYPES
515   HOST_WIDE_INT value;
516   const char *comment;
517 #endif
518   va_list ap;
519
520   VA_START (ap, comment);
521
522 #ifndef ANSI_PROTOTYPES
523   value = va_arg (ap, HOST_WIDE_INT);
524   comment = va_arg (ap, const char *);
525 #endif
526
527 #ifdef HAVE_AS_LEB128
528   fputs ("\t.sleb128 ", asm_out_file);
529   fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, value);
530
531   if (flag_debug_asm && comment)
532     {
533       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
534       vfprintf (asm_out_file, comment, ap);
535     }
536 #else
537   {
538     HOST_WIDE_INT work = value;
539     int more, byte;
540
541     fputs (ASM_BYTE_OP, asm_out_file);
542     do
543       {
544         byte = (work & 0x7f);
545         /* arithmetic shift */
546         work >>= 7;
547         more = !((work == 0 && (byte & 0x40) == 0)
548                  || (work == -1 && (byte & 0x40) != 0));
549         if (more)
550           byte |= 0x80;
551
552         fprintf (asm_out_file, "0x%x", byte);
553         if (more)
554           fputc (',', asm_out_file);
555       }
556     while (more);
557
558   if (flag_debug_asm)
559     {
560       fprintf (asm_out_file, "\t%s sleb128 ", ASM_COMMENT_START);
561       fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, value);
562       if (comment)
563         {
564           fputs ("; ", asm_out_file);
565           vfprintf (asm_out_file, comment, ap);
566         }
567     }
568   }
569 #endif
570   fputc ('\n', asm_out_file);
571
572   va_end (ap);
573 }
574
575 void
576 dw2_asm_output_delta_uleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
577                                        const char *lab2 ATTRIBUTE_UNUSED,
578                                        const char *comment, ...))
579 {
580 #ifndef ANSI_PROTOTYPES
581   const char *lab1, *lab2;
582   const char *comment;
583 #endif
584   va_list ap;
585
586   VA_START (ap, comment);
587
588 #ifndef ANSI_PROTOTYPES
589   lab1 = va_arg (ap, const char *);
590   lab2 = va_arg (ap, const char *);
591   comment = va_arg (ap, const char *);
592 #endif
593
594 #ifdef HAVE_AS_LEB128
595   fputs ("\t.uleb128 ", asm_out_file);
596   assemble_name (asm_out_file, lab1);
597   fputc ('-', asm_out_file);
598   assemble_name (asm_out_file, lab2);
599 #else
600   abort ();
601 #endif
602
603   if (flag_debug_asm && comment)
604     {
605       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
606       vfprintf (asm_out_file, comment, ap);
607     }
608   fputc ('\n', asm_out_file);
609
610   va_end (ap);
611 }
612
613 void
614 dw2_asm_output_delta_sleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
615                                        const char *lab2 ATTRIBUTE_UNUSED,
616                                        const char *comment, ...))
617 {
618 #ifndef ANSI_PROTOTYPES
619   const char *lab1, *lab2;
620   const char *comment;
621 #endif
622   va_list ap;
623
624   VA_START (ap, comment);
625
626 #ifndef ANSI_PROTOTYPES
627   lab1 = va_arg (ap, const char *);
628   lab2 = va_arg (ap, const char *);
629   comment = va_arg (ap, const char *);
630 #endif
631
632 #ifdef HAVE_AS_LEB128
633   fputs ("\t.sleb128 ", asm_out_file);
634   assemble_name (asm_out_file, lab1);
635   fputc ('-', asm_out_file);
636   assemble_name (asm_out_file, lab2);
637 #else
638   abort ();
639 #endif
640
641   if (flag_debug_asm && comment)
642     {
643       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
644       vfprintf (asm_out_file, comment, ap);
645     }
646   fputc ('\n', asm_out_file);
647
648   va_end (ap);
649 }