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