]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/dwarf2asm.c
* doc/tm.texi (SDB and DWARF): Add extra parameter to
[thirdparty/gcc.git] / gcc / dwarf2asm.c
1 /* Dwarf2 assembler output helper routines.
2 Copyright (C) 2001, 2002, 2003, 2004, 2005 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, 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301, USA. */
20
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "flags.h"
27 #include "tree.h"
28 #include "rtl.h"
29 #include "output.h"
30 #include "target.h"
31 #include "dwarf2asm.h"
32 #include "dwarf2.h"
33 #include "splay-tree.h"
34 #include "ggc.h"
35 #include "tm_p.h"
36
37
38 /* How to start an assembler comment. */
39 #ifndef ASM_COMMENT_START
40 #define ASM_COMMENT_START ";#"
41 #endif
42
43 \f
44 /* Output an unaligned integer with the given value and size. Prefer not
45 to print a newline, since the caller may want to add a comment. */
46
47 void
48 dw2_assemble_integer (int size, rtx x)
49 {
50 const char *op = integer_asm_op (size, FALSE);
51
52 if (op)
53 {
54 fputs (op, asm_out_file);
55 if (GET_CODE (x) == CONST_INT)
56 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
57 else
58 output_addr_const (asm_out_file, x);
59 }
60 else
61 assemble_integer (x, size, BITS_PER_UNIT, 1);
62 }
63
64
65 /* Output an immediate constant in a given size. */
66
67 void
68 dw2_asm_output_data (int size, unsigned HOST_WIDE_INT value,
69 const char *comment, ...)
70 {
71 va_list ap;
72
73 va_start (ap, comment);
74
75 if (size * 8 < HOST_BITS_PER_WIDE_INT)
76 value &= ~(~(unsigned HOST_WIDE_INT) 0 << (size * 8));
77
78 dw2_assemble_integer (size, GEN_INT (value));
79
80 if (flag_debug_asm && comment)
81 {
82 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
83 vfprintf (asm_out_file, comment, ap);
84 }
85 fputc ('\n', asm_out_file);
86
87 va_end (ap);
88 }
89
90 /* Output the difference between two symbols in a given size. */
91 /* ??? There appear to be assemblers that do not like such
92 subtraction, but do support ASM_SET_OP. It's unfortunately
93 impossible to do here, since the ASM_SET_OP for the difference
94 symbol must appear after both symbols are defined. */
95
96 void
97 dw2_asm_output_delta (int size, const char *lab1, const char *lab2,
98 const char *comment, ...)
99 {
100 va_list ap;
101
102 va_start (ap, comment);
103
104 #ifdef ASM_OUTPUT_DWARF_DELTA
105 ASM_OUTPUT_DWARF_DELTA (asm_out_file, size, lab1, lab2);
106 #else
107 dw2_assemble_integer (size,
108 gen_rtx_MINUS (Pmode,
109 gen_rtx_SYMBOL_REF (Pmode, lab1),
110 gen_rtx_SYMBOL_REF (Pmode, lab2)));
111 #endif
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 a section-relative reference to a LABEL, which was placed in
123 BASE. In general this can only be done for debugging symbols.
124 E.g. on most targets with the GNU linker, this is accomplished with
125 a direct reference and the knowledge that the debugging section
126 will be placed at VMA 0. Some targets have special relocations for
127 this that we must use. */
128
129 void
130 dw2_asm_output_offset (int size, const char *label, section * base,
131 const char *comment, ...)
132 {
133 va_list ap;
134
135 va_start (ap, comment);
136
137 #ifdef ASM_OUTPUT_DWARF_OFFSET
138 ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label, base);
139 #else
140 dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
141 #endif
142
143 if (flag_debug_asm && comment)
144 {
145 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
146 vfprintf (asm_out_file, comment, ap);
147 }
148 fputc ('\n', asm_out_file);
149
150 va_end (ap);
151 }
152
153 #if 0
154
155 /* Output a self-relative reference to a label, possibly in a
156 different section or object file. */
157
158 void
159 dw2_asm_output_pcrel (int size ATTRIBUTE_UNUSED,
160 const char *label ATTRIBUTE_UNUSED,
161 const char *comment, ...)
162 {
163 va_list ap;
164
165 va_start (ap, comment);
166
167 #ifdef ASM_OUTPUT_DWARF_PCREL
168 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label);
169 #else
170 dw2_assemble_integer (size,
171 gen_rtx_MINUS (Pmode,
172 gen_rtx_SYMBOL_REF (Pmode, label),
173 pc_rtx));
174 #endif
175
176 if (flag_debug_asm && comment)
177 {
178 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
179 vfprintf (asm_out_file, comment, ap);
180 }
181 fputc ('\n', asm_out_file);
182
183 va_end (ap);
184 }
185 #endif /* 0 */
186
187 /* Output an absolute reference to a label. */
188
189 void
190 dw2_asm_output_addr (int size, const char *label,
191 const char *comment, ...)
192 {
193 va_list ap;
194
195 va_start (ap, comment);
196
197 dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
198
199 if (flag_debug_asm && comment)
200 {
201 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
202 vfprintf (asm_out_file, comment, ap);
203 }
204 fputc ('\n', asm_out_file);
205
206 va_end (ap);
207 }
208
209 /* Similar, but use an RTX expression instead of a text label. */
210
211 void
212 dw2_asm_output_addr_rtx (int size, rtx addr,
213 const char *comment, ...)
214 {
215 va_list ap;
216
217 va_start (ap, comment);
218
219 dw2_assemble_integer (size, addr);
220
221 if (flag_debug_asm && comment)
222 {
223 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
224 vfprintf (asm_out_file, comment, ap);
225 }
226 fputc ('\n', asm_out_file);
227
228 va_end (ap);
229 }
230
231 /* Output the first ORIG_LEN characters of STR as a string.
232 If ORIG_LEN is equal to -1, ignore this parameter and output
233 the entire STR instead.
234 If COMMENT is not NULL and comments in the debug information
235 have been requested by the user, append the given COMMENT
236 to the generated output. */
237
238 void
239 dw2_asm_output_nstring (const char *str, size_t orig_len,
240 const char *comment, ...)
241 {
242 size_t i, len;
243 va_list ap;
244
245 va_start (ap, comment);
246
247 len = orig_len;
248
249 if (len == (size_t) -1)
250 len = strlen (str);
251
252 if (flag_debug_asm && comment)
253 {
254 fputs ("\t.ascii \"", asm_out_file);
255 for (i = 0; i < len; i++)
256 {
257 int c = str[i];
258 if (c == '\"' || c == '\\')
259 fputc ('\\', asm_out_file);
260 if (ISPRINT(c))
261 fputc (c, asm_out_file);
262 else
263 fprintf (asm_out_file, "\\%o", c);
264 }
265 fprintf (asm_out_file, "\\0\"\t%s ", ASM_COMMENT_START);
266 vfprintf (asm_out_file, comment, ap);
267 fputc ('\n', asm_out_file);
268 }
269 else
270 {
271 /* If an explicit length was given, we can't assume there
272 is a null termination in the string buffer. */
273 if (orig_len == (size_t) -1)
274 len += 1;
275 ASM_OUTPUT_ASCII (asm_out_file, str, len);
276 if (orig_len != (size_t) -1)
277 assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1);
278 }
279
280 va_end (ap);
281 }
282 \f
283
284 /* Return the size of an unsigned LEB128 quantity. */
285
286 int
287 size_of_uleb128 (unsigned HOST_WIDE_INT value)
288 {
289 int size = 0;
290
291 do
292 {
293 value >>= 7;
294 size += 1;
295 }
296 while (value != 0);
297
298 return size;
299 }
300
301 /* Return the size of a signed LEB128 quantity. */
302
303 int
304 size_of_sleb128 (HOST_WIDE_INT value)
305 {
306 int size = 0, byte;
307
308 do
309 {
310 byte = (value & 0x7f);
311 value >>= 7;
312 size += 1;
313 }
314 while (!((value == 0 && (byte & 0x40) == 0)
315 || (value == -1 && (byte & 0x40) != 0)));
316
317 return size;
318 }
319
320 /* Given an encoding, return the number of bytes the format occupies.
321 This is only defined for fixed-size encodings, and so does not
322 include leb128. */
323
324 int
325 size_of_encoded_value (int encoding)
326 {
327 if (encoding == DW_EH_PE_omit)
328 return 0;
329
330 switch (encoding & 0x07)
331 {
332 case DW_EH_PE_absptr:
333 return POINTER_SIZE / BITS_PER_UNIT;
334 case DW_EH_PE_udata2:
335 return 2;
336 case DW_EH_PE_udata4:
337 return 4;
338 case DW_EH_PE_udata8:
339 return 8;
340 default:
341 gcc_unreachable ();
342 }
343 }
344
345 /* Yield a name for a given pointer encoding. */
346
347 const char *
348 eh_data_format_name (int format)
349 {
350 #if HAVE_DESIGNATED_INITIALIZERS
351 #define S(p, v) [p] = v,
352 #else
353 #define S(p, v) case p: return v;
354 #endif
355
356 #if HAVE_DESIGNATED_INITIALIZERS
357 __extension__ static const char * const format_names[256] = {
358 #else
359 switch (format) {
360 #endif
361
362 S(DW_EH_PE_absptr, "absolute")
363 S(DW_EH_PE_omit, "omit")
364 S(DW_EH_PE_aligned, "aligned absolute")
365
366 S(DW_EH_PE_uleb128, "uleb128")
367 S(DW_EH_PE_udata2, "udata2")
368 S(DW_EH_PE_udata4, "udata4")
369 S(DW_EH_PE_udata8, "udata8")
370 S(DW_EH_PE_sleb128, "sleb128")
371 S(DW_EH_PE_sdata2, "sdata2")
372 S(DW_EH_PE_sdata4, "sdata4")
373 S(DW_EH_PE_sdata8, "sdata8")
374
375 S(DW_EH_PE_absptr | DW_EH_PE_pcrel, "pcrel")
376 S(DW_EH_PE_uleb128 | DW_EH_PE_pcrel, "pcrel uleb128")
377 S(DW_EH_PE_udata2 | DW_EH_PE_pcrel, "pcrel udata2")
378 S(DW_EH_PE_udata4 | DW_EH_PE_pcrel, "pcrel udata4")
379 S(DW_EH_PE_udata8 | DW_EH_PE_pcrel, "pcrel udata8")
380 S(DW_EH_PE_sleb128 | DW_EH_PE_pcrel, "pcrel sleb128")
381 S(DW_EH_PE_sdata2 | DW_EH_PE_pcrel, "pcrel sdata2")
382 S(DW_EH_PE_sdata4 | DW_EH_PE_pcrel, "pcrel sdata4")
383 S(DW_EH_PE_sdata8 | DW_EH_PE_pcrel, "pcrel sdata8")
384
385 S(DW_EH_PE_absptr | DW_EH_PE_textrel, "textrel")
386 S(DW_EH_PE_uleb128 | DW_EH_PE_textrel, "textrel uleb128")
387 S(DW_EH_PE_udata2 | DW_EH_PE_textrel, "textrel udata2")
388 S(DW_EH_PE_udata4 | DW_EH_PE_textrel, "textrel udata4")
389 S(DW_EH_PE_udata8 | DW_EH_PE_textrel, "textrel udata8")
390 S(DW_EH_PE_sleb128 | DW_EH_PE_textrel, "textrel sleb128")
391 S(DW_EH_PE_sdata2 | DW_EH_PE_textrel, "textrel sdata2")
392 S(DW_EH_PE_sdata4 | DW_EH_PE_textrel, "textrel sdata4")
393 S(DW_EH_PE_sdata8 | DW_EH_PE_textrel, "textrel sdata8")
394
395 S(DW_EH_PE_absptr | DW_EH_PE_datarel, "datarel")
396 S(DW_EH_PE_uleb128 | DW_EH_PE_datarel, "datarel uleb128")
397 S(DW_EH_PE_udata2 | DW_EH_PE_datarel, "datarel udata2")
398 S(DW_EH_PE_udata4 | DW_EH_PE_datarel, "datarel udata4")
399 S(DW_EH_PE_udata8 | DW_EH_PE_datarel, "datarel udata8")
400 S(DW_EH_PE_sleb128 | DW_EH_PE_datarel, "datarel sleb128")
401 S(DW_EH_PE_sdata2 | DW_EH_PE_datarel, "datarel sdata2")
402 S(DW_EH_PE_sdata4 | DW_EH_PE_datarel, "datarel sdata4")
403 S(DW_EH_PE_sdata8 | DW_EH_PE_datarel, "datarel sdata8")
404
405 S(DW_EH_PE_absptr | DW_EH_PE_funcrel, "funcrel")
406 S(DW_EH_PE_uleb128 | DW_EH_PE_funcrel, "funcrel uleb128")
407 S(DW_EH_PE_udata2 | DW_EH_PE_funcrel, "funcrel udata2")
408 S(DW_EH_PE_udata4 | DW_EH_PE_funcrel, "funcrel udata4")
409 S(DW_EH_PE_udata8 | DW_EH_PE_funcrel, "funcrel udata8")
410 S(DW_EH_PE_sleb128 | DW_EH_PE_funcrel, "funcrel sleb128")
411 S(DW_EH_PE_sdata2 | DW_EH_PE_funcrel, "funcrel sdata2")
412 S(DW_EH_PE_sdata4 | DW_EH_PE_funcrel, "funcrel sdata4")
413 S(DW_EH_PE_sdata8 | DW_EH_PE_funcrel, "funcrel sdata8")
414
415 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel,
416 "indirect pcrel")
417 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel,
418 "indirect pcrel uleb128")
419 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_pcrel,
420 "indirect pcrel udata2")
421 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_pcrel,
422 "indirect pcrel udata4")
423 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_pcrel,
424 "indirect pcrel udata8")
425 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_pcrel,
426 "indirect pcrel sleb128")
427 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_pcrel,
428 "indirect pcrel sdata2")
429 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_pcrel,
430 "indirect pcrel sdata4")
431 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_pcrel,
432 "indirect pcrel sdata8")
433
434 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_textrel,
435 "indirect textrel")
436 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_textrel,
437 "indirect textrel uleb128")
438 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_textrel,
439 "indirect textrel udata2")
440 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_textrel,
441 "indirect textrel udata4")
442 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_textrel,
443 "indirect textrel udata8")
444 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_textrel,
445 "indirect textrel sleb128")
446 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_textrel,
447 "indirect textrel sdata2")
448 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_textrel,
449 "indirect textrel sdata4")
450 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_textrel,
451 "indirect textrel sdata8")
452
453 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_datarel,
454 "indirect datarel")
455 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_datarel,
456 "indirect datarel uleb128")
457 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_datarel,
458 "indirect datarel udata2")
459 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_datarel,
460 "indirect datarel udata4")
461 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_datarel,
462 "indirect datarel udata8")
463 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_datarel,
464 "indirect datarel sleb128")
465 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_datarel,
466 "indirect datarel sdata2")
467 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_datarel,
468 "indirect datarel sdata4")
469 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_datarel,
470 "indirect datarel sdata8")
471
472 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_funcrel,
473 "indirect funcrel")
474 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_funcrel,
475 "indirect funcrel uleb128")
476 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_funcrel,
477 "indirect funcrel udata2")
478 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_funcrel,
479 "indirect funcrel udata4")
480 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_funcrel,
481 "indirect funcrel udata8")
482 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_funcrel,
483 "indirect funcrel sleb128")
484 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_funcrel,
485 "indirect funcrel sdata2")
486 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_funcrel,
487 "indirect funcrel sdata4")
488 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_funcrel,
489 "indirect funcrel sdata8")
490
491 #if HAVE_DESIGNATED_INITIALIZERS
492 };
493
494 gcc_assert (format >= 0 && format < 0x100 && format_names[format]);
495
496 return format_names[format];
497 #else
498 }
499 gcc_unreachable ();
500 #endif
501 }
502
503 /* Output an unsigned LEB128 quantity. */
504
505 void
506 dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value,
507 const char *comment, ...)
508 {
509 va_list ap;
510
511 va_start (ap, comment);
512
513 #ifdef HAVE_AS_LEB128
514 fprintf (asm_out_file, "\t.uleb128 " HOST_WIDE_INT_PRINT_HEX , value);
515
516 if (flag_debug_asm && comment)
517 {
518 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
519 vfprintf (asm_out_file, comment, ap);
520 }
521 #else
522 {
523 unsigned HOST_WIDE_INT work = value;
524 const char *byte_op = targetm.asm_out.byte_op;
525
526 if (byte_op)
527 fputs (byte_op, asm_out_file);
528 do
529 {
530 int byte = (work & 0x7f);
531 work >>= 7;
532 if (work != 0)
533 /* More bytes to follow. */
534 byte |= 0x80;
535
536 if (byte_op)
537 {
538 fprintf (asm_out_file, "0x%x", byte);
539 if (work != 0)
540 fputc (',', asm_out_file);
541 }
542 else
543 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
544 }
545 while (work != 0);
546
547 if (flag_debug_asm)
548 {
549 fprintf (asm_out_file, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX,
550 ASM_COMMENT_START, value);
551 if (comment)
552 {
553 fputs ("; ", asm_out_file);
554 vfprintf (asm_out_file, comment, ap);
555 }
556 }
557 }
558 #endif
559 fputc ('\n', asm_out_file);
560
561 va_end (ap);
562 }
563
564 /* Output a signed LEB128 quantity. */
565
566 void
567 dw2_asm_output_data_sleb128 (HOST_WIDE_INT value,
568 const char *comment, ...)
569 {
570 va_list ap;
571
572 va_start (ap, comment);
573
574 #ifdef HAVE_AS_LEB128
575 fprintf (asm_out_file, "\t.sleb128 " HOST_WIDE_INT_PRINT_DEC, value);
576
577 if (flag_debug_asm && comment)
578 {
579 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
580 vfprintf (asm_out_file, comment, ap);
581 }
582 #else
583 {
584 HOST_WIDE_INT work = value;
585 int more, byte;
586 const char *byte_op = targetm.asm_out.byte_op;
587
588 if (byte_op)
589 fputs (byte_op, asm_out_file);
590 do
591 {
592 byte = (work & 0x7f);
593 /* arithmetic shift */
594 work >>= 7;
595 more = !((work == 0 && (byte & 0x40) == 0)
596 || (work == -1 && (byte & 0x40) != 0));
597 if (more)
598 byte |= 0x80;
599
600 if (byte_op)
601 {
602 fprintf (asm_out_file, "0x%x", byte);
603 if (more)
604 fputc (',', asm_out_file);
605 }
606 else
607 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
608 }
609 while (more);
610
611 if (flag_debug_asm)
612 {
613 fprintf (asm_out_file, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC,
614 ASM_COMMENT_START, value);
615 if (comment)
616 {
617 fputs ("; ", asm_out_file);
618 vfprintf (asm_out_file, comment, ap);
619 }
620 }
621 }
622 #endif
623 fputc ('\n', asm_out_file);
624
625 va_end (ap);
626 }
627
628 void
629 dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
630 const char *lab2 ATTRIBUTE_UNUSED,
631 const char *comment, ...)
632 {
633 va_list ap;
634
635 va_start (ap, comment);
636
637 #ifdef HAVE_AS_LEB128
638 fputs ("\t.uleb128 ", asm_out_file);
639 assemble_name (asm_out_file, lab1);
640 fputc ('-', asm_out_file);
641 assemble_name (asm_out_file, lab2);
642 #else
643 gcc_unreachable ();
644 #endif
645
646 if (flag_debug_asm && comment)
647 {
648 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
649 vfprintf (asm_out_file, comment, ap);
650 }
651 fputc ('\n', asm_out_file);
652
653 va_end (ap);
654 }
655
656 #if 0
657
658 void
659 dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED,
660 const char *lab2 ATTRIBUTE_UNUSED,
661 const char *comment, ...)
662 {
663 va_list ap;
664
665 va_start (ap, comment);
666
667 #ifdef HAVE_AS_LEB128
668 fputs ("\t.sleb128 ", asm_out_file);
669 assemble_name (asm_out_file, lab1);
670 fputc ('-', asm_out_file);
671 assemble_name (asm_out_file, lab2);
672 #else
673 gcc_unreachable ();
674 #endif
675
676 if (flag_debug_asm && comment)
677 {
678 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
679 vfprintf (asm_out_file, comment, ap);
680 }
681 fputc ('\n', asm_out_file);
682
683 va_end (ap);
684 }
685 #endif /* 0 */
686 \f
687 static rtx dw2_force_const_mem (rtx, bool);
688 static int dw2_output_indirect_constant_1 (splay_tree_node, void *);
689
690 static GTY((param1_is (char *), param2_is (tree))) splay_tree indirect_pool;
691
692 static GTY(()) int dw2_const_labelno;
693
694 #if defined(HAVE_GAS_HIDDEN) && defined(SUPPORTS_ONE_ONLY)
695 # define USE_LINKONCE_INDIRECT 1
696 #else
697 # define USE_LINKONCE_INDIRECT 0
698 #endif
699
700 /* Put X, a SYMBOL_REF, in memory. Return a SYMBOL_REF to the allocated
701 memory. Differs from force_const_mem in that a single pool is used for
702 the entire unit of translation, and the memory is not guaranteed to be
703 "near" the function in any interesting sense. PUBLIC controls whether
704 the symbol can be shared across the entire application (or DSO). */
705
706 static rtx
707 dw2_force_const_mem (rtx x, bool public)
708 {
709 splay_tree_node node;
710 const char *str;
711 tree decl;
712
713 if (! indirect_pool)
714 indirect_pool = splay_tree_new_ggc (splay_tree_compare_pointers);
715
716 gcc_assert (GET_CODE (x) == SYMBOL_REF);
717
718 str = targetm.strip_name_encoding (XSTR (x, 0));
719 node = splay_tree_lookup (indirect_pool, (splay_tree_key) str);
720 if (node)
721 decl = (tree) node->value;
722 else
723 {
724 tree id;
725
726 if (public && USE_LINKONCE_INDIRECT)
727 {
728 char *ref_name = alloca (strlen (str) + sizeof "DW.ref.");
729
730 sprintf (ref_name, "DW.ref.%s", str);
731 id = get_identifier (ref_name);
732 decl = build_decl (VAR_DECL, id, ptr_type_node);
733 DECL_ARTIFICIAL (decl) = 1;
734 DECL_IGNORED_P (decl) = 1;
735 TREE_PUBLIC (decl) = 1;
736 DECL_INITIAL (decl) = decl;
737 make_decl_one_only (decl);
738 }
739 else
740 {
741 char label[32];
742
743 ASM_GENERATE_INTERNAL_LABEL (label, "LDFCM", dw2_const_labelno);
744 ++dw2_const_labelno;
745 id = get_identifier (label);
746 decl = build_decl (VAR_DECL, id, ptr_type_node);
747 DECL_ARTIFICIAL (decl) = 1;
748 DECL_IGNORED_P (decl) = 1;
749 TREE_STATIC (decl) = 1;
750 DECL_INITIAL (decl) = decl;
751 }
752
753 id = maybe_get_identifier (str);
754 if (id)
755 TREE_SYMBOL_REFERENCED (id) = 1;
756
757 splay_tree_insert (indirect_pool, (splay_tree_key) str,
758 (splay_tree_value) decl);
759 }
760
761 return XEXP (DECL_RTL (decl), 0);
762 }
763
764 /* A helper function for dw2_output_indirect_constants called through
765 splay_tree_foreach. Emit one queued constant to memory. */
766
767 static int
768 dw2_output_indirect_constant_1 (splay_tree_node node,
769 void *data ATTRIBUTE_UNUSED)
770 {
771 const char *sym;
772 rtx sym_ref;
773 tree decl;
774
775 sym = (const char *) node->key;
776 decl = (tree) node->value;
777 sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
778 if (TREE_PUBLIC (decl) && USE_LINKONCE_INDIRECT)
779 fprintf (asm_out_file, "\t.hidden %sDW.ref.%s\n", user_label_prefix, sym);
780 assemble_variable (decl, 1, 1, 1);
781 assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
782
783 return 0;
784 }
785
786 /* Emit the constants queued through dw2_force_const_mem. */
787
788 void
789 dw2_output_indirect_constants (void)
790 {
791 if (indirect_pool)
792 splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL);
793 }
794
795 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.
796 If PUBLIC is set and the encoding is DW_EH_PE_indirect, the indirect
797 reference is shared across the entire application (or DSO). */
798
799 void
800 dw2_asm_output_encoded_addr_rtx (int encoding, rtx addr, bool public,
801 const char *comment, ...)
802 {
803 int size;
804 va_list ap;
805
806 va_start (ap, comment);
807
808 size = size_of_encoded_value (encoding);
809
810 if (encoding == DW_EH_PE_aligned)
811 {
812 assemble_align (POINTER_SIZE);
813 assemble_integer (addr, size, POINTER_SIZE, 1);
814 return;
815 }
816
817 /* NULL is _always_ represented as a plain zero, as is 1 for Ada's
818 "all others". */
819 if (addr == const0_rtx || addr == const1_rtx)
820 assemble_integer (addr, size, BITS_PER_UNIT, 1);
821 else
822 {
823 restart:
824 /* Allow the target first crack at emitting this. Some of the
825 special relocations require special directives instead of
826 just ".4byte" or whatever. */
827 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
828 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
829 addr, done);
830 #endif
831
832 /* Indirection is used to get dynamic relocations out of a
833 read-only section. */
834 if (encoding & DW_EH_PE_indirect)
835 {
836 /* It is very tempting to use force_const_mem so that we share data
837 with the normal constant pool. However, we've already emitted
838 the constant pool for this function. Moreover, we'd like to
839 share these constants across the entire unit of translation and
840 even, if possible, across the entire application (or DSO). */
841 addr = dw2_force_const_mem (addr, public);
842 encoding &= ~DW_EH_PE_indirect;
843 goto restart;
844 }
845
846 switch (encoding & 0xF0)
847 {
848 case DW_EH_PE_absptr:
849 dw2_assemble_integer (size, addr);
850 break;
851
852 case DW_EH_PE_pcrel:
853 gcc_assert (GET_CODE (addr) == SYMBOL_REF);
854 #ifdef ASM_OUTPUT_DWARF_PCREL
855 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
856 #else
857 dw2_assemble_integer (size, gen_rtx_MINUS (Pmode, addr, pc_rtx));
858 #endif
859 break;
860
861 default:
862 /* Other encodings should have been handled by
863 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
864 gcc_unreachable ();
865 }
866
867 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
868 done:;
869 #endif
870 }
871
872 if (flag_debug_asm && comment)
873 {
874 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
875 vfprintf (asm_out_file, comment, ap);
876 }
877 fputc ('\n', asm_out_file);
878
879 va_end (ap);
880 }
881
882 #include "gt-dwarf2asm.h"