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 : 84494214 : dw2_assemble_integer (int size, rtx x)
48 : : {
49 : 90249940 : 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 : 84494214 : const char *op = integer_asm_op (size, false);
96 : :
97 : 84494214 : if (op)
98 : : {
99 : 84494214 : fputs (op, asm_out_file);
100 : 84494214 : if (CONST_INT_P (x))
101 : 27984 : fprint_whex (asm_out_file, (unsigned HOST_WIDE_INT) INTVAL (x));
102 : : else
103 : 84466230 : 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 : 296881156 : dw2_asm_output_data (int size, unsigned HOST_WIDE_INT value,
142 : : const char *comment, ...)
143 : : {
144 : 296881156 : va_list ap;
145 : 296881156 : const char *op = integer_asm_op (size, false);
146 : :
147 : 296881156 : va_start (ap, comment);
148 : :
149 : 296881156 : if (size * 8 < HOST_BITS_PER_WIDE_INT)
150 : 296716237 : value &= ~(HOST_WIDE_INT_M1U << (size * 8));
151 : :
152 : 296881156 : if (op)
153 : : {
154 : 296879718 : fputs (op, asm_out_file);
155 : 296879718 : fprint_whex (asm_out_file, value);
156 : : }
157 : : else
158 : 1438 : assemble_integer (GEN_INT (value), size, BITS_PER_UNIT, 1);
159 : :
160 : 296881156 : if (flag_debug_asm && comment)
161 : : {
162 : 91977 : fputs ("\t" ASM_COMMENT_START " ", asm_out_file);
163 : 91977 : vfprintf (asm_out_file, comment, ap);
164 : : }
165 : 296881156 : putc ('\n', asm_out_file);
166 : :
167 : 296881156 : va_end (ap);
168 : 296881156 : }
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 : 4351544 : dw2_asm_output_delta (int size, const char *lab1, const char *lab2,
178 : : const char *comment, ...)
179 : : {
180 : 4351544 : va_list ap;
181 : :
182 : 4351544 : 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 : 13054632 : dw2_assemble_integer (size,
188 : 13054632 : gen_rtx_MINUS (Pmode,
189 : : gen_rtx_SYMBOL_REF (Pmode, lab1),
190 : : gen_rtx_SYMBOL_REF (Pmode, lab2)));
191 : : #endif
192 : 4351544 : if (flag_debug_asm && comment)
193 : : {
194 : 3956 : fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
195 : 3956 : vfprintf (asm_out_file, comment, ap);
196 : : }
197 : 4351544 : fputc ('\n', asm_out_file);
198 : :
199 : 4351544 : va_end (ap);
200 : 4351544 : }
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 : 50263171 : dw2_asm_output_offset (int size, const char *label,
236 : : section *base ATTRIBUTE_UNUSED,
237 : : const char *comment, ...)
238 : : {
239 : 50263171 : va_list ap;
240 : :
241 : 50263171 : 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 : 50263171 : dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
247 : : #endif
248 : :
249 : 50263171 : if (flag_debug_asm && comment)
250 : : {
251 : 24221 : fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
252 : 24221 : vfprintf (asm_out_file, comment, ap);
253 : : }
254 : 50263171 : fputc ('\n', asm_out_file);
255 : :
256 : 50263171 : va_end (ap);
257 : 50263171 : }
258 : :
259 : : void
260 : 28449 : dw2_asm_output_offset (int size, const char *label, HOST_WIDE_INT offset,
261 : : section *base ATTRIBUTE_UNUSED,
262 : : const char *comment, ...)
263 : : {
264 : 28449 : va_list ap;
265 : :
266 : 28449 : 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 : 28449 : 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 : 28449 : 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 : 28449 : fputc ('\n', asm_out_file);
282 : :
283 : 28449 : va_end (ap);
284 : 28449 : }
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 : 28621306 : dw2_asm_output_addr (int size, const char *label,
324 : : const char *comment, ...)
325 : : {
326 : 28621306 : va_list ap;
327 : :
328 : 28621306 : va_start (ap, comment);
329 : :
330 : 28621306 : dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
331 : :
332 : 28621306 : if (flag_debug_asm && comment)
333 : : {
334 : 8566 : fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
335 : 8566 : vfprintf (asm_out_file, comment, ap);
336 : : }
337 : 28621306 : fputc ('\n', asm_out_file);
338 : :
339 : 28621306 : va_end (ap);
340 : 28621306 : }
341 : :
342 : : /* Similar, but use an RTX expression instead of a text label. */
343 : :
344 : : void
345 : 1224969 : dw2_asm_output_addr_rtx (int size, rtx addr,
346 : : const char *comment, ...)
347 : : {
348 : 1224969 : va_list ap;
349 : :
350 : 1224969 : va_start (ap, comment);
351 : :
352 : 1224969 : dw2_assemble_integer (size, addr);
353 : :
354 : 1224969 : if (flag_debug_asm && comment)
355 : : {
356 : 262 : fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
357 : 262 : vfprintf (asm_out_file, comment, ap);
358 : : }
359 : 1224969 : fputc ('\n', asm_out_file);
360 : :
361 : 1224969 : va_end (ap);
362 : 1224969 : }
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 : 2777495 : dw2_asm_output_nstring (const char *str, size_t orig_len,
373 : : const char *comment, ...)
374 : : {
375 : 2777495 : size_t i, len;
376 : 2777495 : va_list ap;
377 : :
378 : 2777495 : va_start (ap, comment);
379 : :
380 : 2777495 : len = orig_len;
381 : :
382 : 2777495 : if (len == (size_t) -1)
383 : 2777181 : len = strlen (str);
384 : :
385 : 2777495 : if (flag_debug_asm && comment)
386 : : {
387 : 6023 : if (XCOFF_DEBUGGING_INFO)
388 : : fputs ("\t.byte \"", asm_out_file);
389 : : else
390 : 6023 : fputs ("\t.ascii \"", asm_out_file);
391 : :
392 : 68969 : for (i = 0; i < len; i++)
393 : : {
394 : 62946 : int c = str[i];
395 : 62946 : if (c == '\"')
396 : 0 : fputc (XCOFF_DEBUGGING_INFO ? '\"' : '\\', asm_out_file);
397 : 62946 : else if (c == '\\')
398 : 0 : fputc ('\\', asm_out_file);
399 : 62946 : if (ISPRINT (c))
400 : 62946 : fputc (c, asm_out_file);
401 : : else
402 : 0 : fprintf (asm_out_file, "\\%o", c);
403 : : }
404 : 6023 : fprintf (asm_out_file, "\\0\"\t%s ", ASM_COMMENT_START);
405 : 6023 : vfprintf (asm_out_file, comment, ap);
406 : 6023 : fputc ('\n', asm_out_file);
407 : 6023 : }
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 : 2771472 : if (orig_len == (size_t) -1)
413 : 2771166 : len += 1;
414 : 2771472 : ASM_OUTPUT_ASCII (asm_out_file, str, len);
415 : 2771472 : if (orig_len != (size_t) -1)
416 : 306 : assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1);
417 : : }
418 : :
419 : 2777495 : va_end (ap);
420 : 2777495 : }
421 : :
422 : :
423 : : /* Return the size of an unsigned LEB128 quantity. */
424 : :
425 : : int
426 : 102677596 : size_of_uleb128 (unsigned HOST_WIDE_INT value)
427 : : {
428 : 102677596 : int size = 0;
429 : :
430 : 112582082 : do
431 : : {
432 : 112582082 : value >>= 7;
433 : 112582082 : size += 1;
434 : : }
435 : 112582082 : while (value != 0);
436 : :
437 : 102677596 : return size;
438 : : }
439 : :
440 : : /* Return the size of a signed LEB128 quantity. */
441 : :
442 : : int
443 : 35990416 : size_of_sleb128 (HOST_WIDE_INT value)
444 : : {
445 : 35990416 : int size = 0, byte;
446 : :
447 : 56489905 : do
448 : : {
449 : 56489905 : byte = (value & 0x7f);
450 : 56489905 : value >>= 7;
451 : 56489905 : size += 1;
452 : : }
453 : 56489905 : while (!((value == 0 && (byte & 0x40) == 0)
454 : 25099625 : || (value == -1 && (byte & 0x40) != 0)));
455 : :
456 : 35990416 : 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 : 43426 : size_of_encoded_value (int encoding)
465 : : {
466 : 43426 : if (encoding == DW_EH_PE_omit)
467 : : return 0;
468 : :
469 : 43426 : switch (encoding & 0x07)
470 : : {
471 : 3061 : case DW_EH_PE_absptr:
472 : 3061 : 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 : 213537 : eh_data_format_name (int format)
488 : : {
489 : : #if HAVE_DESIGNATED_INITIALIZERS
490 : : #define S(p, v) [p] = v,
491 : : #elif __cpp_constexpr >= 201304L
492 : : #define S(p, v) names[p] = v;
493 : : #else
494 : : #define S(p, v) case p: return v;
495 : : #endif
496 : :
497 : : #if HAVE_DESIGNATED_INITIALIZERS
498 : : __extension__ static const char * const format_names[256] = {
499 : : #elif __cpp_constexpr >= 201304L
500 : 213537 : static constexpr struct format_names_s {
501 : : const char *names[256];
502 : : constexpr format_names_s () : names {}
503 : : {
504 : : #else
505 : : switch (format)
506 : : {
507 : : #endif
508 : :
509 : : S(DW_EH_PE_absptr, "absolute")
510 : : S(DW_EH_PE_omit, "omit")
511 : : S(DW_EH_PE_aligned, "aligned absolute")
512 : :
513 : : S(DW_EH_PE_uleb128, "uleb128")
514 : : S(DW_EH_PE_udata2, "udata2")
515 : : S(DW_EH_PE_udata4, "udata4")
516 : : S(DW_EH_PE_udata8, "udata8")
517 : : S(DW_EH_PE_sleb128, "sleb128")
518 : : S(DW_EH_PE_sdata2, "sdata2")
519 : : S(DW_EH_PE_sdata4, "sdata4")
520 : : S(DW_EH_PE_sdata8, "sdata8")
521 : :
522 : : S(DW_EH_PE_absptr | DW_EH_PE_pcrel, "pcrel")
523 : : S(DW_EH_PE_uleb128 | DW_EH_PE_pcrel, "pcrel uleb128")
524 : : S(DW_EH_PE_udata2 | DW_EH_PE_pcrel, "pcrel udata2")
525 : : S(DW_EH_PE_udata4 | DW_EH_PE_pcrel, "pcrel udata4")
526 : : S(DW_EH_PE_udata8 | DW_EH_PE_pcrel, "pcrel udata8")
527 : : S(DW_EH_PE_sleb128 | DW_EH_PE_pcrel, "pcrel sleb128")
528 : : S(DW_EH_PE_sdata2 | DW_EH_PE_pcrel, "pcrel sdata2")
529 : : S(DW_EH_PE_sdata4 | DW_EH_PE_pcrel, "pcrel sdata4")
530 : : S(DW_EH_PE_sdata8 | DW_EH_PE_pcrel, "pcrel sdata8")
531 : :
532 : : S(DW_EH_PE_absptr | DW_EH_PE_textrel, "textrel")
533 : : S(DW_EH_PE_uleb128 | DW_EH_PE_textrel, "textrel uleb128")
534 : : S(DW_EH_PE_udata2 | DW_EH_PE_textrel, "textrel udata2")
535 : : S(DW_EH_PE_udata4 | DW_EH_PE_textrel, "textrel udata4")
536 : : S(DW_EH_PE_udata8 | DW_EH_PE_textrel, "textrel udata8")
537 : : S(DW_EH_PE_sleb128 | DW_EH_PE_textrel, "textrel sleb128")
538 : : S(DW_EH_PE_sdata2 | DW_EH_PE_textrel, "textrel sdata2")
539 : : S(DW_EH_PE_sdata4 | DW_EH_PE_textrel, "textrel sdata4")
540 : : S(DW_EH_PE_sdata8 | DW_EH_PE_textrel, "textrel sdata8")
541 : :
542 : : S(DW_EH_PE_absptr | DW_EH_PE_datarel, "datarel")
543 : : S(DW_EH_PE_uleb128 | DW_EH_PE_datarel, "datarel uleb128")
544 : : S(DW_EH_PE_udata2 | DW_EH_PE_datarel, "datarel udata2")
545 : : S(DW_EH_PE_udata4 | DW_EH_PE_datarel, "datarel udata4")
546 : : S(DW_EH_PE_udata8 | DW_EH_PE_datarel, "datarel udata8")
547 : : S(DW_EH_PE_sleb128 | DW_EH_PE_datarel, "datarel sleb128")
548 : : S(DW_EH_PE_sdata2 | DW_EH_PE_datarel, "datarel sdata2")
549 : : S(DW_EH_PE_sdata4 | DW_EH_PE_datarel, "datarel sdata4")
550 : : S(DW_EH_PE_sdata8 | DW_EH_PE_datarel, "datarel sdata8")
551 : :
552 : : S(DW_EH_PE_absptr | DW_EH_PE_funcrel, "funcrel")
553 : : S(DW_EH_PE_uleb128 | DW_EH_PE_funcrel, "funcrel uleb128")
554 : : S(DW_EH_PE_udata2 | DW_EH_PE_funcrel, "funcrel udata2")
555 : : S(DW_EH_PE_udata4 | DW_EH_PE_funcrel, "funcrel udata4")
556 : : S(DW_EH_PE_udata8 | DW_EH_PE_funcrel, "funcrel udata8")
557 : : S(DW_EH_PE_sleb128 | DW_EH_PE_funcrel, "funcrel sleb128")
558 : : S(DW_EH_PE_sdata2 | DW_EH_PE_funcrel, "funcrel sdata2")
559 : : S(DW_EH_PE_sdata4 | DW_EH_PE_funcrel, "funcrel sdata4")
560 : : S(DW_EH_PE_sdata8 | DW_EH_PE_funcrel, "funcrel sdata8")
561 : :
562 : : S(DW_EH_PE_indirect | DW_EH_PE_absptr, "indirect absolute")
563 : :
564 : : S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel,
565 : : "indirect pcrel")
566 : : S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel,
567 : : "indirect pcrel uleb128")
568 : : S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_pcrel,
569 : : "indirect pcrel udata2")
570 : : S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_pcrel,
571 : : "indirect pcrel udata4")
572 : : S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_pcrel,
573 : : "indirect pcrel udata8")
574 : : S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_pcrel,
575 : : "indirect pcrel sleb128")
576 : : S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_pcrel,
577 : : "indirect pcrel sdata2")
578 : : S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_pcrel,
579 : : "indirect pcrel sdata4")
580 : : S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_pcrel,
581 : : "indirect pcrel sdata8")
582 : :
583 : : S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_textrel,
584 : : "indirect textrel")
585 : : S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_textrel,
586 : : "indirect textrel uleb128")
587 : : S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_textrel,
588 : : "indirect textrel udata2")
589 : : S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_textrel,
590 : : "indirect textrel udata4")
591 : : S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_textrel,
592 : : "indirect textrel udata8")
593 : : S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_textrel,
594 : : "indirect textrel sleb128")
595 : : S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_textrel,
596 : : "indirect textrel sdata2")
597 : : S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_textrel,
598 : : "indirect textrel sdata4")
599 : : S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_textrel,
600 : : "indirect textrel sdata8")
601 : :
602 : : S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_datarel,
603 : : "indirect datarel")
604 : : S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_datarel,
605 : : "indirect datarel uleb128")
606 : : S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_datarel,
607 : : "indirect datarel udata2")
608 : : S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_datarel,
609 : : "indirect datarel udata4")
610 : : S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_datarel,
611 : : "indirect datarel udata8")
612 : : S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_datarel,
613 : : "indirect datarel sleb128")
614 : : S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_datarel,
615 : : "indirect datarel sdata2")
616 : : S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_datarel,
617 : : "indirect datarel sdata4")
618 : : S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_datarel,
619 : : "indirect datarel sdata8")
620 : :
621 : : S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_funcrel,
622 : : "indirect funcrel")
623 : : S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_funcrel,
624 : : "indirect funcrel uleb128")
625 : : S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_funcrel,
626 : : "indirect funcrel udata2")
627 : : S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_funcrel,
628 : : "indirect funcrel udata4")
629 : : S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_funcrel,
630 : : "indirect funcrel udata8")
631 : : S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_funcrel,
632 : : "indirect funcrel sleb128")
633 : : S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_funcrel,
634 : : "indirect funcrel sdata2")
635 : : S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_funcrel,
636 : : "indirect funcrel sdata4")
637 : : S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_funcrel,
638 : : "indirect funcrel sdata8")
639 : :
640 : : #if HAVE_DESIGNATED_INITIALIZERS
641 : : };
642 : :
643 : : gcc_assert (format >= 0 && format < 0x100 && format_names[format]);
644 : :
645 : : return format_names[format];
646 : : #elif __cpp_constexpr >= 201304L
647 : : }
648 : : } format_names;
649 : :
650 : 213537 : gcc_assert (format >= 0 && format < 0x100 && format_names.names[format]);
651 : :
652 : 213537 : return format_names.names[format];
653 : : #else
654 : : }
655 : : gcc_unreachable ();
656 : : #endif
657 : : }
658 : :
659 : : /* Output an unsigned LEB128 quantity, but only the byte values. */
660 : :
661 : : void
662 : 150166 : dw2_asm_output_data_uleb128_raw (unsigned HOST_WIDE_INT value)
663 : : {
664 : 150298 : while (1)
665 : : {
666 : 150232 : int byte = (value & 0x7f);
667 : 150232 : value >>= 7;
668 : 150232 : if (value != 0)
669 : : /* More bytes to follow. */
670 : 66 : byte |= 0x80;
671 : :
672 : 150232 : fprintf (asm_out_file, "%#x", byte);
673 : 150232 : if (value == 0)
674 : : break;
675 : 66 : fputc (',', asm_out_file);
676 : 66 : }
677 : 150166 : }
678 : :
679 : : /* Output an unsigned LEB128 quantity. */
680 : :
681 : : void
682 : 144112641 : dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value,
683 : : const char *comment, ...)
684 : : {
685 : 144112641 : va_list ap;
686 : :
687 : 144112641 : va_start (ap, comment);
688 : :
689 : 144112641 : if (HAVE_AS_LEB128)
690 : : {
691 : 144112641 : fputs ("\t.uleb128 ", asm_out_file);
692 : 144112641 : fprint_whex (asm_out_file, value);
693 : :
694 : 144112641 : if (flag_debug_asm && comment)
695 : : {
696 : 112611 : fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
697 : 112611 : vfprintf (asm_out_file, comment, ap);
698 : : }
699 : : }
700 : : else
701 : : {
702 : : unsigned HOST_WIDE_INT work = value;
703 : : const char *byte_op = targetm.asm_out.byte_op;
704 : :
705 : : if (byte_op)
706 : : fputs (byte_op, asm_out_file);
707 : : do
708 : : {
709 : : int byte = (work & 0x7f);
710 : : work >>= 7;
711 : : if (work != 0)
712 : : /* More bytes to follow. */
713 : : byte |= 0x80;
714 : :
715 : : if (byte_op)
716 : : {
717 : : fprintf (asm_out_file, "%#x", byte);
718 : : if (work != 0)
719 : : fputc (',', asm_out_file);
720 : : }
721 : : else
722 : : assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
723 : : }
724 : : while (work != 0);
725 : :
726 : : if (flag_debug_asm)
727 : : {
728 : : fprintf (asm_out_file, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX,
729 : : ASM_COMMENT_START, value);
730 : : if (comment)
731 : : {
732 : : fputs ("; ", asm_out_file);
733 : : vfprintf (asm_out_file, comment, ap);
734 : : }
735 : : }
736 : : }
737 : :
738 : 144112641 : putc ('\n', asm_out_file);
739 : :
740 : 144112641 : va_end (ap);
741 : 144112641 : }
742 : :
743 : : /* Output an signed LEB128 quantity, but only the byte values. */
744 : :
745 : : void
746 : 53645 : dw2_asm_output_data_sleb128_raw (HOST_WIDE_INT value)
747 : : {
748 : 75442 : int byte, more;
749 : :
750 : 97239 : while (1)
751 : : {
752 : 75442 : byte = (value & 0x7f);
753 : 75442 : value >>= 7;
754 : 75442 : more = !((value == 0 && (byte & 0x40) == 0)
755 : 37393 : || (value == -1 && (byte & 0x40) != 0));
756 : : if (more)
757 : 21797 : byte |= 0x80;
758 : :
759 : 75442 : fprintf (asm_out_file, "%#x", byte);
760 : 75442 : if (!more)
761 : : break;
762 : 21797 : fputc (',', asm_out_file);
763 : : }
764 : 53645 : }
765 : :
766 : : /* Output a signed LEB128 quantity. */
767 : :
768 : : void
769 : 13253205 : dw2_asm_output_data_sleb128 (HOST_WIDE_INT value,
770 : : const char *comment, ...)
771 : : {
772 : 13253205 : va_list ap;
773 : :
774 : 13253205 : va_start (ap, comment);
775 : :
776 : 13253205 : if (HAVE_AS_LEB128)
777 : : {
778 : 13253205 : fprintf (asm_out_file, "\t.sleb128 " HOST_WIDE_INT_PRINT_DEC, value);
779 : :
780 : 13253205 : if (flag_debug_asm && comment)
781 : : {
782 : 141 : fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
783 : 141 : vfprintf (asm_out_file, comment, ap);
784 : : }
785 : : }
786 : : else
787 : : {
788 : : HOST_WIDE_INT work = value;
789 : : int more, byte;
790 : : const char *byte_op = targetm.asm_out.byte_op;
791 : :
792 : : if (byte_op)
793 : : fputs (byte_op, asm_out_file);
794 : : do
795 : : {
796 : : byte = (work & 0x7f);
797 : : /* arithmetic shift */
798 : : work >>= 7;
799 : : more = !((work == 0 && (byte & 0x40) == 0)
800 : : || (work == -1 && (byte & 0x40) != 0));
801 : : if (more)
802 : : byte |= 0x80;
803 : :
804 : : if (byte_op)
805 : : {
806 : : fprintf (asm_out_file, "%#x", byte);
807 : : if (more)
808 : : fputc (',', asm_out_file);
809 : : }
810 : : else
811 : : assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
812 : : }
813 : : while (more);
814 : :
815 : : if (flag_debug_asm)
816 : : {
817 : : fprintf (asm_out_file, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC,
818 : : ASM_COMMENT_START, value);
819 : : if (comment)
820 : : {
821 : : fputs ("; ", asm_out_file);
822 : : vfprintf (asm_out_file, comment, ap);
823 : : }
824 : : }
825 : : }
826 : :
827 : 13253205 : fputc ('\n', asm_out_file);
828 : :
829 : 13253205 : va_end (ap);
830 : 13253205 : }
831 : :
832 : : /* Output symbol LAB1 as an unsigned LEB128 quantity. LAB1 should be
833 : : an assembler-computed constant, e.g. a view number, because we
834 : : can't have relocations in LEB128 quantities. */
835 : :
836 : : void
837 : 38299703 : dw2_asm_output_symname_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
838 : : const char *comment, ...)
839 : : {
840 : 38299703 : va_list ap;
841 : :
842 : 38299703 : va_start (ap, comment);
843 : :
844 : : #ifdef HAVE_AS_LEB128
845 : 38299703 : fputs ("\t.uleb128 ", asm_out_file);
846 : 38299703 : assemble_name (asm_out_file, lab1);
847 : : #else
848 : : gcc_unreachable ();
849 : : #endif
850 : :
851 : 38299703 : if (flag_debug_asm && comment)
852 : : {
853 : 319 : fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
854 : 319 : vfprintf (asm_out_file, comment, ap);
855 : : }
856 : 38299703 : fputc ('\n', asm_out_file);
857 : :
858 : 38299703 : va_end (ap);
859 : 38299703 : }
860 : :
861 : : void
862 : 48806425 : dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
863 : : const char *lab2 ATTRIBUTE_UNUSED,
864 : : const char *comment, ...)
865 : : {
866 : 48806425 : va_list ap;
867 : :
868 : 48806425 : va_start (ap, comment);
869 : :
870 : 48806425 : gcc_assert (HAVE_AS_LEB128);
871 : :
872 : 48806425 : fputs ("\t.uleb128 ", asm_out_file);
873 : 48806425 : assemble_name (asm_out_file, lab1);
874 : 48806425 : putc ('-', asm_out_file);
875 : : /* dwarf2out.cc might give us a label expression (e.g. .LVL548-1)
876 : : as second argument. If so, make it a subexpression, to make
877 : : sure the substraction is done in the right order. */
878 : 48806425 : if (strchr (lab2, '-') != NULL)
879 : : {
880 : 408 : putc ('(', asm_out_file);
881 : 408 : assemble_name (asm_out_file, lab2);
882 : 408 : putc (')', asm_out_file);
883 : : }
884 : : else
885 : 48806017 : assemble_name (asm_out_file, lab2);
886 : :
887 : 48806425 : if (flag_debug_asm && comment)
888 : : {
889 : 330 : fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
890 : 330 : vfprintf (asm_out_file, comment, ap);
891 : : }
892 : 48806425 : fputc ('\n', asm_out_file);
893 : :
894 : 48806425 : va_end (ap);
895 : 48806425 : }
896 : :
897 : : #if 0
898 : :
899 : : void
900 : : dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED,
901 : : const char *lab2 ATTRIBUTE_UNUSED,
902 : : const char *comment, ...)
903 : : {
904 : : va_list ap;
905 : :
906 : : va_start (ap, comment);
907 : :
908 : : gcc_assert (HAVE_AS_LEB128);
909 : :
910 : : fputs ("\t.sleb128 ", asm_out_file);
911 : : assemble_name (asm_out_file, lab1);
912 : : putc ('-', asm_out_file);
913 : : assemble_name (asm_out_file, lab2);
914 : :
915 : : if (flag_debug_asm && comment)
916 : : {
917 : : fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
918 : : vfprintf (asm_out_file, comment, ap);
919 : : }
920 : : fputc ('\n', asm_out_file);
921 : :
922 : : va_end (ap);
923 : : }
924 : : #endif /* 0 */
925 : :
926 : : static GTY(()) hash_map<const char *, tree> *indirect_pool;
927 : :
928 : : static GTY(()) int dw2_const_labelno;
929 : :
930 : : #if defined(HAVE_GAS_HIDDEN)
931 : : # define USE_LINKONCE_INDIRECT (SUPPORTS_ONE_ONLY && !XCOFF_DEBUGGING_INFO)
932 : : #else
933 : : # define USE_LINKONCE_INDIRECT 0
934 : : #endif
935 : :
936 : : /* Compare two std::pair<const char *, tree> by their first element.
937 : : Returns <0, 0, or
938 : : >0 to indicate whether K1 is less than, equal to, or greater than
939 : : K2, respectively. */
940 : :
941 : : static int
942 : 742 : compare_strings (const void *a, const void *b)
943 : : {
944 : 742 : const char *s1 = ((const std::pair<const char *, tree> *) a)->first;
945 : 742 : const char *s2 = ((const std::pair<const char *, tree> *) b)->first;
946 : 742 : int ret;
947 : :
948 : 742 : if (s1 == s2)
949 : : return 0;
950 : :
951 : 742 : ret = strcmp (s1, s2);
952 : :
953 : : /* The strings are always those from IDENTIFIER_NODEs, and,
954 : : therefore, we should never have two copies of the same
955 : : string. */
956 : 742 : gcc_assert (ret);
957 : :
958 : : return ret;
959 : : }
960 : :
961 : : /* Put X, a SYMBOL_REF, in memory. Return a SYMBOL_REF to the allocated
962 : : memory. Differs from force_const_mem in that a single pool is used for
963 : : the entire unit of translation, and the memory is not guaranteed to be
964 : : "near" the function in any interesting sense. IS_PUBLIC controls whether
965 : : the symbol can be shared across the entire application (or DSO). */
966 : :
967 : : rtx
968 : 6526 : dw2_force_const_mem (rtx x, bool is_public)
969 : : {
970 : 6526 : const char *key;
971 : 6526 : tree decl_id;
972 : :
973 : 6526 : if (! indirect_pool)
974 : 610 : indirect_pool = hash_map<const char *, tree>::create_ggc (64);
975 : :
976 : 6526 : gcc_assert (GET_CODE (x) == SYMBOL_REF);
977 : :
978 : 6526 : key = XSTR (x, 0);
979 : 6526 : tree *slot = indirect_pool->get (key);
980 : 6526 : if (slot)
981 : 5738 : decl_id = *slot;
982 : : else
983 : : {
984 : 788 : tree id;
985 : 788 : const char *str = targetm.strip_name_encoding (key);
986 : :
987 : 788 : if (is_public && USE_LINKONCE_INDIRECT)
988 : : {
989 : 773 : char *ref_name = XALLOCAVEC (char, strlen (str) + sizeof "DW.ref.");
990 : :
991 : 773 : sprintf (ref_name, "DW.ref.%s", str);
992 : 773 : gcc_assert (!maybe_get_identifier (ref_name));
993 : 773 : decl_id = get_identifier (ref_name);
994 : 773 : TREE_PUBLIC (decl_id) = 1;
995 : : }
996 : : else
997 : : {
998 : 15 : char label[32];
999 : :
1000 : 15 : ASM_GENERATE_INTERNAL_LABEL (label, "LDFCM", dw2_const_labelno);
1001 : 15 : ++dw2_const_labelno;
1002 : 15 : gcc_assert (!maybe_get_identifier (label));
1003 : 15 : decl_id = get_identifier (label);
1004 : : }
1005 : :
1006 : 788 : id = maybe_get_identifier (str);
1007 : 788 : if (id)
1008 : 788 : TREE_SYMBOL_REFERENCED (id) = 1;
1009 : :
1010 : 788 : indirect_pool->put (key, decl_id);
1011 : : }
1012 : :
1013 : 6526 : return gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (decl_id));
1014 : : }
1015 : :
1016 : : /* A helper function for dw2_output_indirect_constants. Emit one queued
1017 : : constant to memory. */
1018 : :
1019 : : static int
1020 : 788 : dw2_output_indirect_constant_1 (const char *sym, tree id)
1021 : : {
1022 : 788 : rtx sym_ref;
1023 : 788 : tree decl;
1024 : :
1025 : 788 : decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, id, ptr_type_node);
1026 : 788 : SET_DECL_ASSEMBLER_NAME (decl, id);
1027 : 788 : DECL_ARTIFICIAL (decl) = 1;
1028 : 788 : DECL_IGNORED_P (decl) = 1;
1029 : 788 : DECL_INITIAL (decl) = build_fold_addr_expr (decl);
1030 : 788 : TREE_READONLY (decl) = 1;
1031 : 788 : TREE_STATIC (decl) = 1;
1032 : :
1033 : 788 : if (TREE_PUBLIC (id))
1034 : : {
1035 : 773 : TREE_PUBLIC (decl) = 1;
1036 : 773 : make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
1037 : 773 : if (USE_LINKONCE_INDIRECT)
1038 : 773 : DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
1039 : : }
1040 : :
1041 : 788 : sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
1042 : : /* Disable ASan for decl because redzones cause ABI breakage between GCC and
1043 : : libstdc++ for `.LDFCM*' variables. See PR 78651 for details. */
1044 : 788 : unsigned int save_flag_sanitize = flag_sanitize;
1045 : 788 : flag_sanitize &= ~(SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS
1046 : : | SANITIZE_KERNEL_ADDRESS);
1047 : : /* And also temporarily disable -fsection-anchors. These indirect constants
1048 : : are never referenced from code, so it doesn't make any sense to aggregate
1049 : : them in blocks. */
1050 : 788 : int save_flag_section_anchors = flag_section_anchors;
1051 : 788 : flag_section_anchors = 0;
1052 : 788 : assemble_variable (decl, 1, 1, 1);
1053 : 788 : flag_section_anchors = save_flag_section_anchors;
1054 : 788 : flag_sanitize = save_flag_sanitize;
1055 : 1204 : assemble_integer (sym_ref, POINTER_SIZE_UNITS, POINTER_SIZE, 1);
1056 : : /* The following is a hack recognized by use_blocks_for_decl_p to disable
1057 : : section anchor handling of the decl. */
1058 : 788 : DECL_INITIAL (decl) = decl;
1059 : :
1060 : 788 : return 0;
1061 : : }
1062 : :
1063 : : /* Emit the constants queued through dw2_force_const_mem. */
1064 : :
1065 : : void
1066 : 224060 : dw2_output_indirect_constants (void)
1067 : : {
1068 : 224060 : if (!indirect_pool)
1069 : 223450 : return;
1070 : :
1071 : 610 : auto_vec<std::pair<const char *, tree> > temp (indirect_pool->elements ());
1072 : 610 : for (hash_map<const char *, tree>::iterator iter = indirect_pool->begin ();
1073 : 2186 : iter != indirect_pool->end (); ++iter)
1074 : 788 : temp.quick_push (*iter);
1075 : :
1076 : 610 : temp.qsort (compare_strings);
1077 : :
1078 : 1398 : for (unsigned int i = 0; i < temp.length (); i++)
1079 : 788 : dw2_output_indirect_constant_1 (temp[i].first, temp[i].second);
1080 : 610 : }
1081 : :
1082 : : /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.
1083 : : If PUBLIC is set and the encoding is DW_EH_PE_indirect, the indirect
1084 : : reference is shared across the entire application (or DSO). */
1085 : :
1086 : : void
1087 : 21248 : dw2_asm_output_encoded_addr_rtx (int encoding, rtx addr, bool is_public,
1088 : : const char *comment, ...)
1089 : : {
1090 : 21248 : int size;
1091 : 21248 : va_list ap;
1092 : :
1093 : 21248 : va_start (ap, comment);
1094 : :
1095 : 21248 : size = size_of_encoded_value (encoding);
1096 : :
1097 : 21248 : if (encoding == DW_EH_PE_aligned)
1098 : : {
1099 : 0 : assemble_align (POINTER_SIZE);
1100 : 0 : assemble_integer (addr, size, POINTER_SIZE, 1);
1101 : 0 : va_end (ap);
1102 : 0 : return;
1103 : : }
1104 : :
1105 : : /* NULL is _always_ represented as a plain zero, as is 1 for Ada's
1106 : : "all others". */
1107 : 21248 : if (addr == const0_rtx || addr == const1_rtx)
1108 : 16473 : assemble_integer (addr, size, BITS_PER_UNIT, 1);
1109 : : else
1110 : : {
1111 : 4775 : restart:
1112 : : /* Allow the target first crack at emitting this. Some of the
1113 : : special relocations require special directives instead of
1114 : : just ".4byte" or whatever. */
1115 : : #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
1116 : : ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
1117 : : addr, done);
1118 : : #endif
1119 : :
1120 : : /* Indirection is used to get dynamic relocations out of a
1121 : : read-only section. */
1122 : 4775 : if (encoding & DW_EH_PE_indirect)
1123 : : {
1124 : : /* It is very tempting to use force_const_mem so that we share data
1125 : : with the normal constant pool. However, we've already emitted
1126 : : the constant pool for this function. Moreover, we'd like to
1127 : : share these constants across the entire unit of translation and
1128 : : even, if possible, across the entire application (or DSO). */
1129 : 531 : addr = dw2_force_const_mem (addr, is_public);
1130 : 531 : encoding &= ~DW_EH_PE_indirect;
1131 : 531 : goto restart;
1132 : : }
1133 : :
1134 : 4775 : switch (encoding & 0xF0)
1135 : : {
1136 : 4244 : case DW_EH_PE_absptr:
1137 : 4244 : dw2_assemble_integer (size, addr);
1138 : 4244 : break;
1139 : :
1140 : : #ifdef ASM_OUTPUT_DWARF_DATAREL
1141 : : case DW_EH_PE_datarel:
1142 : : gcc_assert (GET_CODE (addr) == SYMBOL_REF);
1143 : : ASM_OUTPUT_DWARF_DATAREL (asm_out_file, size, XSTR (addr, 0));
1144 : : break;
1145 : : #endif
1146 : :
1147 : 531 : case DW_EH_PE_pcrel:
1148 : 531 : gcc_assert (GET_CODE (addr) == SYMBOL_REF);
1149 : : #ifdef ASM_OUTPUT_DWARF_PCREL
1150 : : ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
1151 : : #else
1152 : 531 : dw2_assemble_integer (size, gen_rtx_MINUS (Pmode, addr, pc_rtx));
1153 : : #endif
1154 : 531 : break;
1155 : :
1156 : 0 : default:
1157 : : /* Other encodings should have been handled by
1158 : : ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
1159 : 0 : gcc_unreachable ();
1160 : : }
1161 : :
1162 : : #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
1163 : : done:;
1164 : : #endif
1165 : : }
1166 : :
1167 : 21248 : if (flag_debug_asm && comment)
1168 : : {
1169 : 0 : fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
1170 : 0 : vfprintf (asm_out_file, comment, ap);
1171 : : }
1172 : 21248 : fputc ('\n', asm_out_file);
1173 : :
1174 : 21248 : va_end (ap);
1175 : : }
1176 : :
1177 : : #include "gt-dwarf2asm.h"
|