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