]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/dwarf2asm.c
Makefile.in, [...]: replace "GNU CC" with "GCC".
[thirdparty/gcc.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 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 "flags.h"
25 #include "tree.h"
26 #include "rtl.h"
27 #include "output.h"
28 #include "dwarf2asm.h"
29 #include "dwarf2.h"
30 #include "splay-tree.h"
31 #include "ggc.h"
32 #include "tm_p.h"
33
34
35 /* How to start an assembler comment. */
36 #ifndef ASM_COMMENT_START
37 #define ASM_COMMENT_START ";#"
38 #endif
39
40 /* We don't have unaligned support, let's hope the normal output works for
41 .debug_frame. But we know it won't work for .debug_info. */
42 #if !defined(UNALIGNED_INT_ASM_OP) && defined(DWARF2_DEBUGGING_INFO)
43 #error DWARF2_DEBUGGING_INFO requires UNALIGNED_INT_ASM_OP.
44 #endif
45
46 \f
47 /* Despite the fact that assemble_integer handles unaligned data,
48 continue emitting things by hand when possible, since that makes
49 the assembler commentary come out prettier. */
50 #ifdef UNALIGNED_INT_ASM_OP
51 static const char * unaligned_integer_asm_op PARAMS ((int));
52
53 static inline const char *
54 unaligned_integer_asm_op (size)
55 int size;
56 {
57 const char *op;
58 switch (size)
59 {
60 case 1:
61 op = ASM_BYTE_OP;
62 break;
63 case 2:
64 op = UNALIGNED_SHORT_ASM_OP;
65 break;
66 case 4:
67 op = UNALIGNED_INT_ASM_OP;
68 break;
69 case 8:
70 #ifdef UNALIGNED_DOUBLE_INT_ASM_OP
71 op = UNALIGNED_DOUBLE_INT_ASM_OP;
72 break;
73 #endif
74 default:
75 abort ();
76 }
77 return op;
78 }
79 #endif /* UNALIGNED_INT_ASM_OP */
80
81 /* Output an immediate constant in a given size. */
82
83 void
84 dw2_asm_output_data VPARAMS ((int size, unsigned HOST_WIDE_INT value,
85 const char *comment, ...))
86 {
87 #ifndef ANSI_PROTOTYPES
88 int size;
89 unsigned HOST_WIDE_INT value;
90 const char *comment;
91 #endif
92 va_list ap;
93
94 VA_START (ap, comment);
95
96 #ifndef ANSI_PROTOTYPES
97 size = va_arg (ap, int);
98 value = va_arg (ap, unsigned HOST_WIDE_INT);
99 comment = va_arg (ap, const char *);
100 #endif
101
102 if (size * 8 < HOST_BITS_PER_WIDE_INT)
103 value &= ~(~(unsigned HOST_WIDE_INT)0 << (size * 8));
104
105 #ifdef UNALIGNED_INT_ASM_OP
106 fputs (unaligned_integer_asm_op (size), asm_out_file);
107 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
108 #else
109 assemble_integer (GEN_INT (value), size, BITS_PER_UNIT, 1);
110 #endif
111
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 the difference between two symbols in a given size. */
123 /* ??? There appear to be assemblers that do not like such
124 subtraction, but do support ASM_SET_OP. It's unfortunately
125 impossible to do here, since the ASM_SET_OP for the difference
126 symbol must appear after both symbols are defined. */
127
128 void
129 dw2_asm_output_delta VPARAMS ((int size, const char *lab1, const char *lab2,
130 const char *comment, ...))
131 {
132 #ifndef ANSI_PROTOTYPES
133 int size;
134 const char *lab1, *lab2;
135 const char *comment;
136 #endif
137 va_list ap;
138
139 VA_START (ap, comment);
140
141 #ifndef ANSI_PROTOTYPES
142 size = va_arg (ap, int);
143 lab1 = va_arg (ap, const char *);
144 lab2 = va_arg (ap, const char *);
145 comment = va_arg (ap, const char *);
146 #endif
147
148 #ifdef UNALIGNED_INT_ASM_OP
149 fputs (unaligned_integer_asm_op (size), asm_out_file);
150 assemble_name (asm_out_file, lab1);
151 fputc ('-', asm_out_file);
152 assemble_name (asm_out_file, lab2);
153 #else
154 assemble_integer (gen_rtx_MINUS (Pmode, gen_rtx_SYMBOL_REF (Pmode, lab1),
155 gen_rtx_SYMBOL_REF (Pmode, lab2)),
156 size, BITS_PER_UNIT, 1);
157 #endif
158
159 if (flag_debug_asm && comment)
160 {
161 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
162 vfprintf (asm_out_file, comment, ap);
163 }
164 fputc ('\n', asm_out_file);
165
166 va_end (ap);
167 }
168
169 /* Output a section-relative reference to a label. In general this
170 can only be done for debugging symbols. E.g. on most targets with
171 the GNU linker, this is accomplished with a direct reference and
172 the knowledge that the debugging section will be placed at VMA 0.
173 Some targets have special relocations for this that we must use. */
174
175 void
176 dw2_asm_output_offset VPARAMS ((int size, const char *label,
177 const char *comment, ...))
178 {
179 #ifndef ANSI_PROTOTYPES
180 int size;
181 const char *label;
182 const char *comment;
183 #endif
184 va_list ap;
185
186 VA_START (ap, comment);
187
188 #ifndef ANSI_PROTOTYPES
189 size = va_arg (ap, int);
190 label = va_arg (ap, const char *);
191 comment = va_arg (ap, const char *);
192 #endif
193
194 #ifdef ASM_OUTPUT_DWARF_OFFSET
195 ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label);
196 #else
197 #ifdef UNALIGNED_INT_ASM_OP
198 fputs (unaligned_integer_asm_op (size), asm_out_file);
199 assemble_name (asm_out_file, label);
200 #else
201 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, label), size, BITS_PER_UNIT, 1);
202 #endif
203 #endif
204
205 if (flag_debug_asm && comment)
206 {
207 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
208 vfprintf (asm_out_file, comment, ap);
209 }
210 fputc ('\n', asm_out_file);
211
212 va_end (ap);
213 }
214
215 /* Output a self-relative reference to a label, possibly in a
216 different section or object file. */
217
218 void
219 dw2_asm_output_pcrel VPARAMS ((int size, const char *label,
220 const char *comment, ...))
221 {
222 #ifndef ANSI_PROTOTYPES
223 int size;
224 const char *label;
225 const char *comment;
226 #endif
227 va_list ap;
228
229 VA_START (ap, comment);
230
231 #ifndef ANSI_PROTOTYPES
232 size = va_arg (ap, int);
233 label = va_arg (ap, const char *);
234 comment = va_arg (ap, const char *);
235 #endif
236
237 #ifdef ASM_OUTPUT_DWARF_PCREL
238 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label);
239 #else
240 #ifdef UNALIGNED_INT_ASM_OP
241 fputs (unaligned_integer_asm_op (size), asm_out_file);
242 assemble_name (asm_out_file, label);
243 fputc ('-', asm_out_file);
244 fputc ('.', asm_out_file);
245 #else
246 abort ();
247 #endif
248 #endif
249
250 if (flag_debug_asm && comment)
251 {
252 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
253 vfprintf (asm_out_file, comment, ap);
254 }
255 fputc ('\n', asm_out_file);
256
257 va_end (ap);
258 }
259
260 /* Output an absolute reference to a label. */
261
262 void
263 dw2_asm_output_addr VPARAMS ((int size, const char *label,
264 const char *comment, ...))
265 {
266 #ifndef ANSI_PROTOTYPES
267 int size;
268 const char *label;
269 const char *comment;
270 #endif
271 va_list ap;
272
273 VA_START (ap, comment);
274
275 #ifndef ANSI_PROTOTYPES
276 size = va_arg (ap, int);
277 label = va_arg (ap, const char *);
278 comment = va_arg (ap, const char *);
279 #endif
280
281 #ifdef UNALIGNED_INT_ASM_OP
282 fputs (unaligned_integer_asm_op (size), asm_out_file);
283 assemble_name (asm_out_file, label);
284 #else
285 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, label), size, BITS_PER_UNIT, 1);
286 #endif
287
288 if (flag_debug_asm && comment)
289 {
290 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
291 vfprintf (asm_out_file, comment, ap);
292 }
293 fputc ('\n', asm_out_file);
294
295 va_end (ap);
296 }
297
298 /* Similar, but use an RTX expression instead of a text label. */
299
300 void
301 dw2_asm_output_addr_rtx VPARAMS ((int size, rtx addr,
302 const char *comment, ...))
303 {
304 #ifndef ANSI_PROTOTYPES
305 int size;
306 rtx addr;
307 const char *comment;
308 #endif
309 va_list ap;
310
311 VA_START (ap, comment);
312
313 #ifndef ANSI_PROTOTYPES
314 size = va_arg (ap, int);
315 addr = va_arg (ap, rtx);
316 comment = va_arg (ap, const char *);
317 #endif
318
319 #ifdef UNALIGNED_INT_ASM_OP
320 fputs (unaligned_integer_asm_op (size), asm_out_file);
321 output_addr_const (asm_out_file, addr);
322 #else
323 assemble_integer (addr, size, BITS_PER_UNIT, 1);
324 #endif
325
326 if (flag_debug_asm && comment)
327 {
328 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
329 vfprintf (asm_out_file, comment, ap);
330 }
331 fputc ('\n', asm_out_file);
332
333 va_end (ap);
334 }
335
336 void
337 dw2_asm_output_nstring VPARAMS ((const char *str, size_t orig_len,
338 const char *comment, ...))
339 {
340 #ifndef ANSI_PROTOTYPES
341 const char *str;
342 size_t orig_len;
343 const char *comment;
344 #endif
345 va_list ap;
346 size_t i, len = orig_len;
347
348 VA_START (ap, comment);
349
350 #ifndef ANSI_PROTOTYPES
351 str = va_arg (ap, const char *);
352 len = va_arg (ap, size_t);
353 comment = va_arg (ap, const char *);
354 #endif
355
356 if (len == (size_t) -1)
357 len = strlen (str);
358
359 if (flag_debug_asm && comment)
360 {
361 fputs ("\t.ascii \"", asm_out_file);
362 for (i = 0; i < len; i++)
363 {
364 int c = str[i];
365 if (c == '\"' || c == '\\')
366 fputc ('\\', asm_out_file);
367 if (ISPRINT(c))
368 fputc (c, asm_out_file);
369 else
370 fprintf (asm_out_file, "\\%o", c);
371 }
372 fprintf (asm_out_file, "\\0\"\t%s ", ASM_COMMENT_START);
373 vfprintf (asm_out_file, comment, ap);
374 fputc ('\n', asm_out_file);
375 }
376 else
377 {
378 /* If an explicit length was given, we can't assume there
379 is a null termination in the string buffer. */
380 if (orig_len == (size_t) -1)
381 len += 1;
382 ASM_OUTPUT_ASCII (asm_out_file, str, len);
383 if (orig_len != (size_t) -1)
384 fprintf (asm_out_file, "%s0\n", ASM_BYTE_OP);
385 }
386
387 va_end (ap);
388 }
389 \f
390
391 /* Return the size of an unsigned LEB128 quantity. */
392
393 int
394 size_of_uleb128 (value)
395 unsigned HOST_WIDE_INT value;
396 {
397 int size = 0, byte;
398
399 do
400 {
401 byte = (value & 0x7f);
402 value >>= 7;
403 size += 1;
404 }
405 while (value != 0);
406
407 return size;
408 }
409
410 /* Return the size of a signed LEB128 quantity. */
411
412 int
413 size_of_sleb128 (value)
414 HOST_WIDE_INT value;
415 {
416 int size = 0, byte;
417
418 do
419 {
420 byte = (value & 0x7f);
421 value >>= 7;
422 size += 1;
423 }
424 while (!((value == 0 && (byte & 0x40) == 0)
425 || (value == -1 && (byte & 0x40) != 0)));
426
427 return size;
428 }
429
430 /* Given an encoding, return the number of bytes the format occupies.
431 This is only defined for fixed-size encodings, and so does not
432 include leb128. */
433
434 int
435 size_of_encoded_value (encoding)
436 int encoding;
437 {
438 if (encoding == DW_EH_PE_omit)
439 return 0;
440
441 switch (encoding & 0x07)
442 {
443 case DW_EH_PE_absptr:
444 return POINTER_SIZE / BITS_PER_UNIT;
445 case DW_EH_PE_udata2:
446 return 2;
447 case DW_EH_PE_udata4:
448 return 4;
449 case DW_EH_PE_udata8:
450 return 8;
451 }
452 abort ();
453 }
454
455 /* Yield a name for a given pointer encoding. */
456
457 const char *
458 eh_data_format_name (format)
459 int format;
460 {
461 #if HAVE_DESIGNATED_INITIALIZERS
462 #define S(p, v) [p] = v,
463 #else
464 #define S(p, v) case p: return v;
465 #endif
466
467 #if HAVE_DESIGNATED_INITIALIZERS
468 __extension__ static const char * const format_names[256] = {
469 #else
470 switch (format) {
471 #endif
472
473 S(DW_EH_PE_absptr, "absolute")
474 S(DW_EH_PE_omit, "omit")
475 S(DW_EH_PE_aligned, "aligned absolute")
476
477 S(DW_EH_PE_uleb128, "uleb128")
478 S(DW_EH_PE_udata2, "udata2")
479 S(DW_EH_PE_udata4, "udata4")
480 S(DW_EH_PE_udata8, "udata8")
481 S(DW_EH_PE_sleb128, "sleb128")
482 S(DW_EH_PE_sdata2, "sdata2")
483 S(DW_EH_PE_sdata4, "sdata4")
484 S(DW_EH_PE_sdata8, "sdata8")
485
486 S(DW_EH_PE_absptr | DW_EH_PE_pcrel, "pcrel")
487 S(DW_EH_PE_uleb128 | DW_EH_PE_pcrel, "pcrel uleb128")
488 S(DW_EH_PE_udata2 | DW_EH_PE_pcrel, "pcrel udata2")
489 S(DW_EH_PE_udata4 | DW_EH_PE_pcrel, "pcrel udata4")
490 S(DW_EH_PE_udata8 | DW_EH_PE_pcrel, "pcrel udata8")
491 S(DW_EH_PE_sleb128 | DW_EH_PE_pcrel, "pcrel sleb128")
492 S(DW_EH_PE_sdata2 | DW_EH_PE_pcrel, "pcrel sdata2")
493 S(DW_EH_PE_sdata4 | DW_EH_PE_pcrel, "pcrel sdata4")
494 S(DW_EH_PE_sdata8 | DW_EH_PE_pcrel, "pcrel sdata8")
495
496 S(DW_EH_PE_absptr | DW_EH_PE_textrel, "textrel")
497 S(DW_EH_PE_uleb128 | DW_EH_PE_textrel, "textrel uleb128")
498 S(DW_EH_PE_udata2 | DW_EH_PE_textrel, "textrel udata2")
499 S(DW_EH_PE_udata4 | DW_EH_PE_textrel, "textrel udata4")
500 S(DW_EH_PE_udata8 | DW_EH_PE_textrel, "textrel udata8")
501 S(DW_EH_PE_sleb128 | DW_EH_PE_textrel, "textrel sleb128")
502 S(DW_EH_PE_sdata2 | DW_EH_PE_textrel, "textrel sdata2")
503 S(DW_EH_PE_sdata4 | DW_EH_PE_textrel, "textrel sdata4")
504 S(DW_EH_PE_sdata8 | DW_EH_PE_textrel, "textrel sdata8")
505
506 S(DW_EH_PE_absptr | DW_EH_PE_datarel, "datarel")
507 S(DW_EH_PE_uleb128 | DW_EH_PE_datarel, "datarel uleb128")
508 S(DW_EH_PE_udata2 | DW_EH_PE_datarel, "datarel udata2")
509 S(DW_EH_PE_udata4 | DW_EH_PE_datarel, "datarel udata4")
510 S(DW_EH_PE_udata8 | DW_EH_PE_datarel, "datarel udata8")
511 S(DW_EH_PE_sleb128 | DW_EH_PE_datarel, "datarel sleb128")
512 S(DW_EH_PE_sdata2 | DW_EH_PE_datarel, "datarel sdata2")
513 S(DW_EH_PE_sdata4 | DW_EH_PE_datarel, "datarel sdata4")
514 S(DW_EH_PE_sdata8 | DW_EH_PE_datarel, "datarel sdata8")
515
516 S(DW_EH_PE_absptr | DW_EH_PE_funcrel, "funcrel")
517 S(DW_EH_PE_uleb128 | DW_EH_PE_funcrel, "funcrel uleb128")
518 S(DW_EH_PE_udata2 | DW_EH_PE_funcrel, "funcrel udata2")
519 S(DW_EH_PE_udata4 | DW_EH_PE_funcrel, "funcrel udata4")
520 S(DW_EH_PE_udata8 | DW_EH_PE_funcrel, "funcrel udata8")
521 S(DW_EH_PE_sleb128 | DW_EH_PE_funcrel, "funcrel sleb128")
522 S(DW_EH_PE_sdata2 | DW_EH_PE_funcrel, "funcrel sdata2")
523 S(DW_EH_PE_sdata4 | DW_EH_PE_funcrel, "funcrel sdata4")
524 S(DW_EH_PE_sdata8 | DW_EH_PE_funcrel, "funcrel sdata8")
525
526 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel,
527 "indirect pcrel")
528 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel,
529 "indirect pcrel uleb128")
530 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_pcrel,
531 "indirect pcrel udata2")
532 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_pcrel,
533 "indirect pcrel udata4")
534 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_pcrel,
535 "indirect pcrel udata8")
536 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_pcrel,
537 "indirect pcrel sleb128")
538 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_pcrel,
539 "indirect pcrel sdata2")
540 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_pcrel,
541 "indirect pcrel sdata4")
542 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_pcrel,
543 "indirect pcrel sdata8")
544
545 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_textrel,
546 "indirect textrel")
547 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_textrel,
548 "indirect textrel uleb128")
549 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_textrel,
550 "indirect textrel udata2")
551 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_textrel,
552 "indirect textrel udata4")
553 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_textrel,
554 "indirect textrel udata8")
555 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_textrel,
556 "indirect textrel sleb128")
557 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_textrel,
558 "indirect textrel sdata2")
559 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_textrel,
560 "indirect textrel sdata4")
561 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_textrel,
562 "indirect textrel sdata8")
563
564 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_datarel,
565 "indirect datarel")
566 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_datarel,
567 "indirect datarel uleb128")
568 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_datarel,
569 "indirect datarel udata2")
570 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_datarel,
571 "indirect datarel udata4")
572 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_datarel,
573 "indirect datarel udata8")
574 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_datarel,
575 "indirect datarel sleb128")
576 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_datarel,
577 "indirect datarel sdata2")
578 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_datarel,
579 "indirect datarel sdata4")
580 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_datarel,
581 "indirect datarel sdata8")
582
583 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_funcrel,
584 "indirect funcrel")
585 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_funcrel,
586 "indirect funcrel uleb128")
587 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_funcrel,
588 "indirect funcrel udata2")
589 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_funcrel,
590 "indirect funcrel udata4")
591 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_funcrel,
592 "indirect funcrel udata8")
593 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_funcrel,
594 "indirect funcrel sleb128")
595 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_funcrel,
596 "indirect funcrel sdata2")
597 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_funcrel,
598 "indirect funcrel sdata4")
599 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_funcrel,
600 "indirect funcrel sdata8")
601
602 #if HAVE_DESIGNATED_INITIALIZERS
603 };
604
605 if (format < 0 || format > 0xff || format_names[format] == NULL)
606 abort ();
607 return format_names[format];
608 #else
609 }
610 abort ();
611 #endif
612 }
613
614 /* Output an unsigned LEB128 quantity. */
615
616 void
617 dw2_asm_output_data_uleb128 VPARAMS ((unsigned HOST_WIDE_INT value,
618 const char *comment, ...))
619 {
620 #ifndef ANSI_PROTOTYPES
621 unsigned HOST_WIDE_INT value;
622 const char *comment;
623 #endif
624 va_list ap;
625
626 VA_START (ap, comment);
627
628 #ifndef ANSI_PROTOTYPES
629 value = va_arg (ap, unsigned HOST_WIDE_INT);
630 comment = va_arg (ap, const char *);
631 #endif
632
633 #ifdef HAVE_AS_LEB128
634 fputs ("\t.uleb128 ", asm_out_file);
635 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
636
637 if (flag_debug_asm && comment)
638 {
639 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
640 vfprintf (asm_out_file, comment, ap);
641 }
642 #else
643 {
644 unsigned HOST_WIDE_INT work = value;
645
646 fputs (ASM_BYTE_OP, asm_out_file);
647 do
648 {
649 int byte = (work & 0x7f);
650 work >>= 7;
651 if (work != 0)
652 /* More bytes to follow. */
653 byte |= 0x80;
654
655 fprintf (asm_out_file, "0x%x", byte);
656 if (work != 0)
657 fputc (',', asm_out_file);
658 }
659 while (work != 0);
660
661 if (flag_debug_asm)
662 {
663 fprintf (asm_out_file, "\t%s uleb128 ", ASM_COMMENT_START);
664 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
665 if (comment)
666 {
667 fputs ("; ", asm_out_file);
668 vfprintf (asm_out_file, comment, ap);
669 }
670 }
671 }
672 #endif
673 fputc ('\n', asm_out_file);
674
675 va_end (ap);
676 }
677
678 /* Output an signed LEB128 quantity. */
679
680 void
681 dw2_asm_output_data_sleb128 VPARAMS ((HOST_WIDE_INT value,
682 const char *comment, ...))
683 {
684 #ifndef ANSI_PROTOTYPES
685 HOST_WIDE_INT value;
686 const char *comment;
687 #endif
688 va_list ap;
689
690 VA_START (ap, comment);
691
692 #ifndef ANSI_PROTOTYPES
693 value = va_arg (ap, HOST_WIDE_INT);
694 comment = va_arg (ap, const char *);
695 #endif
696
697 #ifdef HAVE_AS_LEB128
698 fputs ("\t.sleb128 ", asm_out_file);
699 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, value);
700
701 if (flag_debug_asm && comment)
702 {
703 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
704 vfprintf (asm_out_file, comment, ap);
705 }
706 #else
707 {
708 HOST_WIDE_INT work = value;
709 int more, byte;
710
711 fputs (ASM_BYTE_OP, asm_out_file);
712 do
713 {
714 byte = (work & 0x7f);
715 /* arithmetic shift */
716 work >>= 7;
717 more = !((work == 0 && (byte & 0x40) == 0)
718 || (work == -1 && (byte & 0x40) != 0));
719 if (more)
720 byte |= 0x80;
721
722 fprintf (asm_out_file, "0x%x", byte);
723 if (more)
724 fputc (',', asm_out_file);
725 }
726 while (more);
727
728 if (flag_debug_asm)
729 {
730 fprintf (asm_out_file, "\t%s sleb128 ", ASM_COMMENT_START);
731 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, value);
732 if (comment)
733 {
734 fputs ("; ", asm_out_file);
735 vfprintf (asm_out_file, comment, ap);
736 }
737 }
738 }
739 #endif
740 fputc ('\n', asm_out_file);
741
742 va_end (ap);
743 }
744
745 void
746 dw2_asm_output_delta_uleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
747 const char *lab2 ATTRIBUTE_UNUSED,
748 const char *comment, ...))
749 {
750 #ifndef ANSI_PROTOTYPES
751 const char *lab1, *lab2;
752 const char *comment;
753 #endif
754 va_list ap;
755
756 VA_START (ap, comment);
757
758 #ifndef ANSI_PROTOTYPES
759 lab1 = va_arg (ap, const char *);
760 lab2 = va_arg (ap, const char *);
761 comment = va_arg (ap, const char *);
762 #endif
763
764 #ifdef HAVE_AS_LEB128
765 fputs ("\t.uleb128 ", asm_out_file);
766 assemble_name (asm_out_file, lab1);
767 fputc ('-', asm_out_file);
768 assemble_name (asm_out_file, lab2);
769 #else
770 abort ();
771 #endif
772
773 if (flag_debug_asm && comment)
774 {
775 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
776 vfprintf (asm_out_file, comment, ap);
777 }
778 fputc ('\n', asm_out_file);
779
780 va_end (ap);
781 }
782
783 void
784 dw2_asm_output_delta_sleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
785 const char *lab2 ATTRIBUTE_UNUSED,
786 const char *comment, ...))
787 {
788 #ifndef ANSI_PROTOTYPES
789 const char *lab1, *lab2;
790 const char *comment;
791 #endif
792 va_list ap;
793
794 VA_START (ap, comment);
795
796 #ifndef ANSI_PROTOTYPES
797 lab1 = va_arg (ap, const char *);
798 lab2 = va_arg (ap, const char *);
799 comment = va_arg (ap, const char *);
800 #endif
801
802 #ifdef HAVE_AS_LEB128
803 fputs ("\t.sleb128 ", asm_out_file);
804 assemble_name (asm_out_file, lab1);
805 fputc ('-', asm_out_file);
806 assemble_name (asm_out_file, lab2);
807 #else
808 abort ();
809 #endif
810
811 if (flag_debug_asm && comment)
812 {
813 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
814 vfprintf (asm_out_file, comment, ap);
815 }
816 fputc ('\n', asm_out_file);
817
818 va_end (ap);
819 }
820 \f
821 static rtx dw2_force_const_mem PARAMS ((rtx));
822 static int dw2_output_indirect_constant_1 PARAMS ((splay_tree_node, void *));
823
824 static splay_tree indirect_pool;
825
826 /* Put X, a SYMBOL_REF, in memory. Return a SYMBOL_REF to the allocated
827 memory. Differs from force_const_mem in that a single pool is used for
828 the entire unit of translation, and the memory is not guaranteed to be
829 "near" the function in any interesting sense. */
830
831 static rtx
832 dw2_force_const_mem (x)
833 rtx x;
834 {
835 splay_tree_node node;
836 const char *const_sym;
837
838 if (! indirect_pool)
839 indirect_pool = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
840
841 if (GET_CODE (x) != SYMBOL_REF)
842 abort ();
843 node = splay_tree_lookup (indirect_pool, (splay_tree_key) XSTR (x, 0));
844 if (node)
845 const_sym = (const char *) node->value;
846 else
847 {
848 extern int const_labelno;
849 char label[32];
850 tree id;
851
852 ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
853 ++const_labelno;
854 const_sym = ggc_strdup (label);
855
856 id = maybe_get_identifier (XSTR (x, 0));
857 if (id)
858 TREE_SYMBOL_REFERENCED (id) = 1;
859
860 splay_tree_insert (indirect_pool, (splay_tree_key) XSTR (x, 0),
861 (splay_tree_value) const_sym);
862 }
863
864 return gen_rtx_SYMBOL_REF (Pmode, const_sym);
865 }
866
867 /* A helper function for dw2_output_indirect_constants called through
868 splay_tree_foreach. Emit one queued constant to memory. */
869
870 static int
871 dw2_output_indirect_constant_1 (node, data)
872 splay_tree_node node;
873 void* data ATTRIBUTE_UNUSED;
874 {
875 const char *label, *sym;
876 rtx sym_ref;
877
878 label = (const char *) node->value;
879 sym = (const char *) node->key;
880 sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
881
882 ASM_OUTPUT_LABEL (asm_out_file, label);
883 assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
884
885 return 0;
886 }
887
888 /* Emit the constants queued through dw2_force_const_mem. */
889
890 void
891 dw2_output_indirect_constants ()
892 {
893 if (! indirect_pool)
894 return;
895
896 /* Assume that the whole reason we're emitting these symbol references
897 indirectly is that they contain dynamic relocations, and are thus
898 read-write. If there was no possibility of a dynamic relocation, we
899 might as well have used a direct relocation. */
900 data_section ();
901
902 /* Everything we're emitting is a pointer. Align appropriately. */
903 assemble_align (POINTER_SIZE);
904
905 splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL);
906 }
907
908 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed. */
909
910 void
911 dw2_asm_output_encoded_addr_rtx VPARAMS ((int encoding,
912 rtx addr,
913 const char *comment, ...))
914 {
915 #ifndef ANSI_PROTOTYPES
916 int encoding;
917 rtx addr;
918 const char *comment;
919 #endif
920 va_list ap;
921 int size;
922
923 VA_START (ap, comment);
924
925 #ifndef ANSI_PROTOTYPES
926 encoding = va_arg (ap, int);
927 addr = va_arg (ap, rtx);
928 comment = va_arg (ap, const char *);
929 #endif
930
931 size = size_of_encoded_value (encoding);
932
933 if (encoding == DW_EH_PE_aligned)
934 {
935 assemble_align (POINTER_SIZE);
936 encoding = DW_EH_PE_absptr;
937 }
938
939 /* NULL is _always_ represented as a plain zero. */
940 if (addr == const0_rtx)
941 assemble_integer (addr, size, BITS_PER_UNIT, 1);
942 else
943 {
944 restart:
945 /* Allow the target first crack at emitting this. Some of the
946 special relocations require special directives instead of
947 just ".4byte" or whatever. */
948 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
949 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
950 addr, done);
951 #endif
952
953 /* Indirection is used to get dynamic relocations out of a
954 read-only section. */
955 if (encoding & DW_EH_PE_indirect)
956 {
957 /* It is very tempting to use force_const_mem so that we share data
958 with the normal constant pool. However, we've already emitted
959 the constant pool for this function. Moreover, we'd like to
960 share these constants across the entire unit of translation,
961 or better, across the entire application (or DSO). */
962 addr = dw2_force_const_mem (addr);
963 encoding &= ~DW_EH_PE_indirect;
964 goto restart;
965 }
966
967 switch (encoding & 0xF0)
968 {
969 case DW_EH_PE_absptr:
970 #ifdef UNALIGNED_INT_ASM_OP
971 fputs (unaligned_integer_asm_op (size), asm_out_file);
972 output_addr_const (asm_out_file, addr);
973 #else
974 assemble_integer (addr, size, BITS_PER_UNIT, 1);
975 #endif
976 break;
977
978 case DW_EH_PE_pcrel:
979 if (GET_CODE (addr) != SYMBOL_REF)
980 abort ();
981 #ifdef ASM_OUTPUT_DWARF_PCREL
982 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
983 #else
984 #ifdef UNALIGNED_INT_ASM_OP
985 fputs (unaligned_integer_asm_op (size), asm_out_file);
986 assemble_name (asm_out_file, XSTR (addr, 0));
987 fputc ('-', asm_out_file);
988 fputc ('.', asm_out_file);
989 #else
990 abort ();
991 #endif
992 #endif
993 break;
994
995 default:
996 /* Other encodings should have been handled by
997 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
998 abort ();
999 }
1000
1001 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
1002 done:;
1003 #endif
1004 }
1005
1006 if (flag_debug_asm && comment)
1007 {
1008 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
1009 vfprintf (asm_out_file, comment, ap);
1010 }
1011 fputc ('\n', asm_out_file);
1012
1013 va_end (ap);
1014 }