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)
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. */
27 #include "dwarf2asm.h"
31 /* How to start an assembler comment. */
32 #ifndef ASM_COMMENT_START
33 #define ASM_COMMENT_START ";#"
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"
44 #ifndef UNALIGNED_INT_ASM_OP
45 #define UNALIGNED_INT_ASM_OP "\t.4byte\t"
47 #ifndef UNALIGNED_DOUBLE_INT_ASM_OP
48 #define UNALIGNED_DOUBLE_INT_ASM_OP "\t.8byte\t"
50 #endif /* OBJECT_FORMAT_ELF */
53 #define ASM_BYTE_OP "\t.byte\t"
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.
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)
77 op = UNALIGNED_SHORT_ASM_OP;
80 op = UNALIGNED_INT_ASM_OP;
83 #ifdef UNALIGNED_DOUBLE_INT_ASM_OP
84 op = UNALIGNED_DOUBLE_INT_ASM_OP;
92 #endif /* UNALIGNED_INT_ASM_OP */
94 /* Output an immediate constant in a given size. */
97 dw2_asm_output_data VPARAMS ((int size, unsigned HOST_WIDE_INT value,
98 const char *comment, ...))
100 #ifndef ANSI_PROTOTYPES
102 unsigned HOST_WIDE_INT value;
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 *);
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);
122 assemble_integer (GEN_INT (value), size, 1);
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);
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. */
142 dw2_asm_output_delta VPARAMS ((int size, const char *lab1, const char *lab2,
143 const char *comment, ...))
145 #ifndef ANSI_PROTOTYPES
147 const char *lab1, *lab2;
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 *);
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);
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)),
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);
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. */
190 dw2_asm_output_offset VPARAMS ((int size, const char *label,
191 const char *comment, ...))
193 #ifndef ANSI_PROTOTYPES
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 *);
208 #ifdef ASM_OUTPUT_DWARF_OFFSET
209 ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label);
211 #ifdef UNALIGNED_INT_ASM_OP
212 fputs (unaligned_integer_asm_op (size), asm_out_file);
213 assemble_name (asm_out_file, label);
215 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, label), size, 1);
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);
229 /* Output a self-relative reference to a label, possibly in a
230 different section or object file. */
233 dw2_asm_output_pcrel VPARAMS ((int size, const char *label,
234 const char *comment, ...))
236 #ifndef ANSI_PROTOTYPES
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 *);
251 #ifdef ASM_OUTPUT_DWARF_PCREL
252 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label);
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);
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);
274 /* Output an absolute reference to a label. */
277 dw2_asm_output_addr VPARAMS ((int size, const char *label,
278 const char *comment, ...))
280 #ifndef ANSI_PROTOTYPES
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 *);
295 #ifdef UNALIGNED_INT_ASM_OP
296 fputs (unaligned_integer_asm_op (size), asm_out_file);
297 assemble_name (asm_out_file, label);
299 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, label), size, 1);
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);
312 /* Similar, but use an RTX expression instead of a text label. */
315 dw2_asm_output_addr_rtx VPARAMS ((int size, rtx addr,
316 const char *comment, ...))
318 #ifndef ANSI_PROTOTYPES
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 *);
333 #ifdef UNALIGNED_INT_ASM_OP
334 fputs (unaligned_integer_asm_op (size), asm_out_file);
335 output_addr_const (asm_out_file, addr);
337 assemble_integer (addr, size, 1);
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);
351 dw2_asm_output_nstring VPARAMS ((const char *str, size_t orig_len,
352 const char *comment, ...))
354 #ifndef ANSI_PROTOTYPES
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 *);
370 if (len == (size_t) -1)
373 if (flag_debug_asm && comment)
375 fputs ("\t.ascii \"", asm_out_file);
376 for (i = 0; i < len; i++)
379 if (c == '\"' || c == '\\')
380 fputc ('\\', asm_out_file);
382 fputc (c, asm_out_file);
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);
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)
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);
405 /* Return the size of an unsigned LEB128 quantity. */
408 size_of_uleb128 (value)
409 unsigned HOST_WIDE_INT value;
415 byte = (value & 0x7f);
424 /* Return the size of a signed LEB128 quantity. */
427 size_of_sleb128 (value)
434 byte = (value & 0x7f);
438 while (!((value == 0 && (byte & 0x40) == 0)
439 || (value == -1 && (byte & 0x40) != 0)));
444 /* Output an unsigned LEB128 quantity. */
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;
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 *);
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);
474 unsigned HOST_WIDE_INT work = value;
476 fputs (ASM_BYTE_OP, asm_out_file);
479 int byte = (work & 0x7f);
482 /* More bytes to follow. */
485 fprintf (asm_out_file, "0x%x", byte);
487 fputc (',', asm_out_file);
493 fprintf (asm_out_file, "\t%s uleb128 ", ASM_COMMENT_START);
494 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
497 fputs ("; ", asm_out_file);
498 vfprintf (asm_out_file, comment, ap);
503 fputc ('\n', asm_out_file);
508 /* Output an signed LEB128 quantity. */
511 dw2_asm_output_data_sleb128 VPARAMS ((HOST_WIDE_INT value,
512 const char *comment, ...))
514 #ifndef ANSI_PROTOTYPES
520 VA_START (ap, comment);
522 #ifndef ANSI_PROTOTYPES
523 value = va_arg (ap, HOST_WIDE_INT);
524 comment = va_arg (ap, const char *);
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);
538 HOST_WIDE_INT work = value;
541 fputs (ASM_BYTE_OP, asm_out_file);
544 byte = (work & 0x7f);
545 /* arithmetic shift */
547 more = !((work == 0 && (byte & 0x40) == 0)
548 || (work == -1 && (byte & 0x40) != 0));
552 fprintf (asm_out_file, "0x%x", byte);
554 fputc (',', asm_out_file);
560 fprintf (asm_out_file, "\t%s sleb128 ", ASM_COMMENT_START);
561 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, value);
564 fputs ("; ", asm_out_file);
565 vfprintf (asm_out_file, comment, ap);
570 fputc ('\n', asm_out_file);
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;
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 *);
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);
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);
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;
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 *);
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);
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);