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
);