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