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