* c-aux-info.c: NULL_PTR->NULL in calls to `concat'.
[official-gcc.git] / gcc / dwarf2asm.c
blob98667350efbbd296da4236893767469dc72833bc
1 /* Dwarf2 assembler output helper routines.
2 Copyright (C) 2001 Free Software Foundation, Inc.
4 This file is part of GNU CC.
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.
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.
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. */
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"
31 /* How to start an assembler comment. */
32 #ifndef ASM_COMMENT_START
33 #define ASM_COMMENT_START ";#"
34 #endif
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. */
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 */
52 #ifndef ASM_BYTE_OP
53 #define ASM_BYTE_OP "\t.byte\t"
54 #endif
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
63 #ifdef UNALIGNED_INT_ASM_OP
64 static const char * unaligned_integer_asm_op PARAMS ((int));
66 static inline const char *
67 unaligned_integer_asm_op (size)
68 int size;
70 const char *op;
71 switch (size)
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 ();
90 return op;
92 #endif /* UNALIGNED_INT_ASM_OP */
94 /* Output an immediate constant in a given size. */
96 void
97 dw2_asm_output_data VPARAMS ((int size, unsigned HOST_WIDE_INT value,
98 const char *comment, ...))
100 #ifndef ANSI_PROTOTYPES
101 int size;
102 unsigned HOST_WIDE_INT value;
103 const char *comment;
104 #endif
105 va_list ap;
107 VA_START (ap, comment);
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
115 if (size * 8 < HOST_BITS_PER_WIDE_INT)
116 value &= ~(~(unsigned HOST_WIDE_INT)0 << (size * 8));
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
125 if (flag_debug_asm && comment)
127 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
128 vfprintf (asm_out_file, comment, ap);
130 fputc ('\n', asm_out_file);
132 va_end (ap);
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. */
141 void
142 dw2_asm_output_delta VPARAMS ((int size, const char *lab1, const char *lab2,
143 const char *comment, ...))
145 #ifndef ANSI_PROTOTYPES
146 int size;
147 const char *lab1, *lab2;
148 const char *comment;
149 #endif
150 va_list ap;
152 VA_START (ap, comment);
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
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
173 if (flag_debug_asm && comment)
175 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
176 vfprintf (asm_out_file, comment, ap);
178 fputc ('\n', asm_out_file);
180 va_end (ap);
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. */
189 void
190 dw2_asm_output_offset VPARAMS ((int size, const char *label,
191 const char *comment, ...))
193 #ifndef ANSI_PROTOTYPES
194 int size;
195 const char *label;
196 const char *comment;
197 #endif
198 va_list ap;
200 VA_START (ap, comment);
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
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
219 if (flag_debug_asm && comment)
221 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
222 vfprintf (asm_out_file, comment, ap);
224 fputc ('\n', asm_out_file);
226 va_end (ap);
229 /* Output a self-relative reference to a label, possibly in a
230 different section or object file. */
232 void
233 dw2_asm_output_pcrel VPARAMS ((int size, const char *label,
234 const char *comment, ...))
236 #ifndef ANSI_PROTOTYPES
237 int size;
238 const char *label;
239 const char *comment;
240 #endif
241 va_list ap;
243 VA_START (ap, comment);
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
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
264 if (flag_debug_asm && comment)
266 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
267 vfprintf (asm_out_file, comment, ap);
269 fputc ('\n', asm_out_file);
271 va_end (ap);
274 /* Output an absolute reference to a label. */
276 void
277 dw2_asm_output_addr VPARAMS ((int size, const char *label,
278 const char *comment, ...))
280 #ifndef ANSI_PROTOTYPES
281 int size;
282 const char *label;
283 const char *comment;
284 #endif
285 va_list ap;
287 VA_START (ap, comment);
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
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
302 if (flag_debug_asm && comment)
304 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
305 vfprintf (asm_out_file, comment, ap);
307 fputc ('\n', asm_out_file);
309 va_end (ap);
312 /* Similar, but use an RTX expression instead of a text label. */
314 void
315 dw2_asm_output_addr_rtx VPARAMS ((int size, rtx addr,
316 const char *comment, ...))
318 #ifndef ANSI_PROTOTYPES
319 int size;
320 rtx addr;
321 const char *comment;
322 #endif
323 va_list ap;
325 VA_START (ap, comment);
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
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
340 if (flag_debug_asm && comment)
342 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
343 vfprintf (asm_out_file, comment, ap);
345 fputc ('\n', asm_out_file);
347 va_end (ap);
350 void
351 dw2_asm_output_nstring VPARAMS ((const char *str, size_t orig_len,
352 const char *comment, ...))
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;
362 VA_START (ap, comment);
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
370 if (len == (size_t) -1)
371 len = strlen (str);
373 if (flag_debug_asm && comment)
375 fputs ("\t.ascii \"", asm_out_file);
376 for (i = 0; i < len; i++)
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);
386 fprintf (asm_out_file, "\\0\"\t%s ", ASM_COMMENT_START);
387 vfprintf (asm_out_file, comment, ap);
388 fputc ('\n', asm_out_file);
390 else
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);
401 va_end (ap);
405 /* Return the size of an unsigned LEB128 quantity. */
408 size_of_uleb128 (value)
409 unsigned HOST_WIDE_INT value;
411 int size = 0, byte;
415 byte = (value & 0x7f);
416 value >>= 7;
417 size += 1;
419 while (value != 0);
421 return size;
424 /* Return the size of a signed LEB128 quantity. */
427 size_of_sleb128 (value)
428 HOST_WIDE_INT value;
430 int size = 0, byte;
434 byte = (value & 0x7f);
435 value >>= 7;
436 size += 1;
438 while (!((value == 0 && (byte & 0x40) == 0)
439 || (value == -1 && (byte & 0x40) != 0)));
441 return size;
444 /* Output an unsigned LEB128 quantity. */
446 void
447 dw2_asm_output_data_uleb128 VPARAMS ((unsigned HOST_WIDE_INT value,
448 const char *comment, ...))
450 #ifndef ANSI_PROTOTYPES
451 unsigned HOST_WIDE_INT value;
452 const char *comment;
453 #endif
454 va_list ap;
456 VA_START (ap, comment);
458 #ifndef ANSI_PROTOTYPES
459 value = va_arg (ap, unsigned HOST_WIDE_INT);
460 comment = va_arg (ap, const char *);
461 #endif
463 #ifdef HAVE_AS_LEB128
464 fputs ("\t.uleb128 ", asm_out_file);
465 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
467 if (flag_debug_asm && comment)
469 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
470 vfprintf (asm_out_file, comment, ap);
472 #else
474 unsigned HOST_WIDE_INT work = value;
476 fputs (ASM_BYTE_OP, asm_out_file);
479 int byte = (work & 0x7f);
480 work >>= 7;
481 if (work != 0)
482 /* More bytes to follow. */
483 byte |= 0x80;
485 fprintf (asm_out_file, "0x%x", byte);
486 if (work != 0)
487 fputc (',', asm_out_file);
489 while (work != 0);
491 if (flag_debug_asm)
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)
497 fputs ("; ", asm_out_file);
498 vfprintf (asm_out_file, comment, ap);
502 #endif
503 fputc ('\n', asm_out_file);
505 va_end (ap);
508 /* Output an signed LEB128 quantity. */
510 void
511 dw2_asm_output_data_sleb128 VPARAMS ((HOST_WIDE_INT value,
512 const char *comment, ...))
514 #ifndef ANSI_PROTOTYPES
515 HOST_WIDE_INT value;
516 const char *comment;
517 #endif
518 va_list ap;
520 VA_START (ap, comment);
522 #ifndef ANSI_PROTOTYPES
523 value = va_arg (ap, HOST_WIDE_INT);
524 comment = va_arg (ap, const char *);
525 #endif
527 #ifdef HAVE_AS_LEB128
528 fputs ("\t.sleb128 ", asm_out_file);
529 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, value);
531 if (flag_debug_asm && comment)
533 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
534 vfprintf (asm_out_file, comment, ap);
536 #else
538 HOST_WIDE_INT work = value;
539 int more, byte;
541 fputs (ASM_BYTE_OP, asm_out_file);
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;
552 fprintf (asm_out_file, "0x%x", byte);
553 if (more)
554 fputc (',', asm_out_file);
556 while (more);
558 if (flag_debug_asm)
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)
564 fputs ("; ", asm_out_file);
565 vfprintf (asm_out_file, comment, ap);
569 #endif
570 fputc ('\n', asm_out_file);
572 va_end (ap);
575 void
576 dw2_asm_output_delta_uleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
577 const char *lab2 ATTRIBUTE_UNUSED,
578 const char *comment, ...))
580 #ifndef ANSI_PROTOTYPES
581 const char *lab1, *lab2;
582 const char *comment;
583 #endif
584 va_list ap;
586 VA_START (ap, comment);
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
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
603 if (flag_debug_asm && comment)
605 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
606 vfprintf (asm_out_file, comment, ap);
608 fputc ('\n', asm_out_file);
610 va_end (ap);
613 void
614 dw2_asm_output_delta_sleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
615 const char *lab2 ATTRIBUTE_UNUSED,
616 const char *comment, ...))
618 #ifndef ANSI_PROTOTYPES
619 const char *lab1, *lab2;
620 const char *comment;
621 #endif
622 va_list ap;
624 VA_START (ap, comment);
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
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
641 if (flag_debug_asm && comment)
643 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
644 vfprintf (asm_out_file, comment, ap);
646 fputc ('\n', asm_out_file);
648 va_end (ap);