]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/dwarf2asm.c
Fix typo in c-parser.c.
[thirdparty/gcc.git] / gcc / dwarf2asm.c
CommitLineData
2e4b9b8c 1/* Dwarf2 assembler output helper routines.
8d9254fc 2 Copyright (C) 2001-2020 Free Software Foundation, Inc.
2e4b9b8c 3
1322177d 4This file is part of GCC.
2e4b9b8c 5
1322177d
LB
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
9dcd6f09 8Software Foundation; either version 3, or (at your option) any later
1322177d 9version.
2e4b9b8c 10
1322177d
LB
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
2e4b9b8c
RH
15
16You should have received a copy of the GNU General Public License
9dcd6f09
NC
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
2e4b9b8c
RH
19
20
21#include "config.h"
22#include "system.h"
4977bab6 23#include "coretypes.h"
957060b5
AM
24#include "target.h"
25#include "rtl.h"
2a1ee410 26#include "tree.h"
4d0cdd0c 27#include "memmodel.h"
957060b5 28#include "tm_p.h"
d8a2d370
DN
29#include "stringpool.h"
30#include "varasm.h"
2e4b9b8c
RH
31#include "output.h"
32#include "dwarf2asm.h"
a80b0574 33#include "dwarf2.h"
7180b1a6
RB
34#include "function.h"
35#include "emit-rtl.h"
90841d43 36#include "fold-const.h"
2e4b9b8c 37
51fbbb92
DE
38#ifndef XCOFF_DEBUGGING_INFO
39#define XCOFF_DEBUGGING_INFO 0
40#endif
41
2e4b9b8c 42\f
301d03af
RS
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
46void
7080f735 47dw2_assemble_integer (int size, rtx x)
2e4b9b8c 48{
301d03af
RS
49 const char *op = integer_asm_op (size, FALSE);
50
51 if (op)
2e4b9b8c 52 {
301d03af 53 fputs (op, asm_out_file);
481683e1 54 if (CONST_INT_P (x))
5e3929ed 55 fprint_whex (asm_out_file, (unsigned HOST_WIDE_INT) INTVAL (x));
301d03af
RS
56 else
57 output_addr_const (asm_out_file, x);
2e4b9b8c 58 }
301d03af
RS
59 else
60 assemble_integer (x, size, BITS_PER_UNIT, 1);
2e4b9b8c 61}
3a538a66 62
2e4b9b8c 63
d4ea4622
RH
64/* Output a value of a given size in target byte order. */
65
66void
67dw2_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)
a3f1cee4
UB
81 fprintf (asm_out_file, "%#x,", bytes[i]);
82 fprintf (asm_out_file, "%#x", bytes[0]);
d4ea4622
RH
83 }
84 else
85 {
86 for (i = 0; i < size - 1; ++i)
a3f1cee4
UB
87 fprintf (asm_out_file, "%#x,", bytes[i]);
88 fprintf (asm_out_file, "%#x", bytes[i]);
d4ea4622
RH
89 }
90}
91
105f48ae 92/* Output an immediate constant in a given SIZE in bytes. */
8e7fa2c8 93
2e4b9b8c 94void
e34d07f2
KG
95dw2_asm_output_data (int size, unsigned HOST_WIDE_INT value,
96 const char *comment, ...)
2e4b9b8c 97{
e34d07f2 98 va_list ap;
d61772b2 99 const char *op = integer_asm_op (size, FALSE);
7080f735 100
e34d07f2 101 va_start (ap, comment);
2e4b9b8c 102
da6af203 103 if (size * 8 < HOST_BITS_PER_WIDE_INT)
dd4786fe 104 value &= ~(HOST_WIDE_INT_M1U << (size * 8));
da6af203 105
d61772b2 106 if (op)
5e3929ed
DA
107 {
108 fputs (op, asm_out_file);
109 fprint_whex (asm_out_file, value);
110 }
d61772b2
GK
111 else
112 assemble_integer (GEN_INT (value), size, BITS_PER_UNIT, 1);
2e4b9b8c
RH
113
114 if (flag_debug_asm && comment)
115 {
5e3929ed 116 fputs ("\t" ASM_COMMENT_START " ", asm_out_file);
2e4b9b8c
RH
117 vfprintf (asm_out_file, comment, ap);
118 }
5e3929ed 119 putc ('\n', asm_out_file);
2e4b9b8c 120
e34d07f2 121 va_end (ap);
2e4b9b8c
RH
122}
123
8e7fa2c8
RH
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
2e4b9b8c 130void
e34d07f2
KG
131dw2_asm_output_delta (int size, const char *lab1, const char *lab2,
132 const char *comment, ...)
2e4b9b8c 133{
e34d07f2 134 va_list ap;
7080f735 135
e34d07f2 136 va_start (ap, comment);
2e4b9b8c 137
7606e68f
SS
138#ifdef ASM_OUTPUT_DWARF_DELTA
139 ASM_OUTPUT_DWARF_DELTA (asm_out_file, size, lab1, lab2);
140#else
301d03af
RS
141 dw2_assemble_integer (size,
142 gen_rtx_MINUS (Pmode,
143 gen_rtx_SYMBOL_REF (Pmode, lab1),
144 gen_rtx_SYMBOL_REF (Pmode, lab2)));
7606e68f 145#endif
2e4b9b8c
RH
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
e34d07f2 153 va_end (ap);
2e4b9b8c
RH
154}
155
2cea0398 156#ifdef ASM_OUTPUT_DWARF_VMS_DELTA
67ad2ae7
DR
157/* Output the difference between two symbols in instruction units
158 in a given size. */
159
160void
161dw2_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
67ad2ae7
DR
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);
67ad2ae7
DR
176
177 va_end (ap);
178}
2cea0398 179#endif
67ad2ae7 180
192d0f89
GK
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. */
8e7fa2c8 187
2e4b9b8c 188void
79252435
SB
189dw2_asm_output_offset (int size, const char *label,
190 section *base ATTRIBUTE_UNUSED,
e34d07f2 191 const char *comment, ...)
2e4b9b8c 192{
e34d07f2 193 va_list ap;
7080f735 194
e34d07f2 195 va_start (ap, comment);
2e4b9b8c 196
8e7fa2c8 197#ifdef ASM_OUTPUT_DWARF_OFFSET
7180b1a6 198 ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label, 0, base);
8e7fa2c8 199#else
301d03af 200 dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
2e4b9b8c
RH
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
e34d07f2 210 va_end (ap);
2e4b9b8c
RH
211}
212
7180b1a6
RB
213void
214dw2_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
c8f4fe99
BE
240#if 0
241
8e7fa2c8
RH
242/* Output a self-relative reference to a label, possibly in a
243 different section or object file. */
244
2e4b9b8c 245void
e34d07f2
KG
246dw2_asm_output_pcrel (int size ATTRIBUTE_UNUSED,
247 const char *label ATTRIBUTE_UNUSED,
248 const char *comment, ...)
2e4b9b8c 249{
e34d07f2 250 va_list ap;
7080f735 251
e34d07f2 252 va_start (ap, comment);
2e4b9b8c 253
8e7fa2c8
RH
254#ifdef ASM_OUTPUT_DWARF_PCREL
255 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label);
256#else
301d03af
RS
257 dw2_assemble_integer (size,
258 gen_rtx_MINUS (Pmode,
259 gen_rtx_SYMBOL_REF (Pmode, label),
260 pc_rtx));
8e7fa2c8
RH
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
e34d07f2 270 va_end (ap);
8e7fa2c8 271}
c8f4fe99 272#endif /* 0 */
8e7fa2c8
RH
273
274/* Output an absolute reference to a label. */
275
276void
e34d07f2
KG
277dw2_asm_output_addr (int size, const char *label,
278 const char *comment, ...)
8e7fa2c8 279{
e34d07f2 280 va_list ap;
7080f735 281
e34d07f2 282 va_start (ap, comment);
8e7fa2c8 283
301d03af 284 dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
2e4b9b8c
RH
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
e34d07f2 293 va_end (ap);
2e4b9b8c
RH
294}
295
8e7fa2c8
RH
296/* Similar, but use an RTX expression instead of a text label. */
297
2e4b9b8c 298void
e34d07f2
KG
299dw2_asm_output_addr_rtx (int size, rtx addr,
300 const char *comment, ...)
2e4b9b8c 301{
e34d07f2 302 va_list ap;
7080f735 303
e34d07f2 304 va_start (ap, comment);
2e4b9b8c 305
301d03af 306 dw2_assemble_integer (size, addr);
2e4b9b8c
RH
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
e34d07f2 315 va_end (ap);
2e4b9b8c
RH
316}
317
1e290ba1
JB
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. */
b8698a0f 324
2e4b9b8c 325void
e34d07f2
KG
326dw2_asm_output_nstring (const char *str, size_t orig_len,
327 const char *comment, ...)
2e4b9b8c 328{
7a75edb7 329 size_t i, len;
e34d07f2 330 va_list ap;
2e4b9b8c 331
e34d07f2 332 va_start (ap, comment);
2e4b9b8c 333
7a75edb7 334 len = orig_len;
2e4b9b8c
RH
335
336 if (len == (size_t) -1)
337 len = strlen (str);
338
339 if (flag_debug_asm && comment)
340 {
51fbbb92
DE
341 if (XCOFF_DEBUGGING_INFO)
342 fputs ("\t.byte \"", asm_out_file);
343 else
344 fputs ("\t.ascii \"", asm_out_file);
345
2e4b9b8c
RH
346 for (i = 0; i < len; i++)
347 {
348 int c = str[i];
7e78cfda
DE
349 if (c == '\"')
350 fputc (XCOFF_DEBUGGING_INFO ? '\"' : '\\', asm_out_file);
351 else if (c == '\\')
2e4b9b8c 352 fputc ('\\', asm_out_file);
c3284718 353 if (ISPRINT (c))
2e4b9b8c
RH
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)
301d03af 370 assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1);
2e4b9b8c
RH
371 }
372
e34d07f2 373 va_end (ap);
2e4b9b8c
RH
374}
375\f
376
377/* Return the size of an unsigned LEB128 quantity. */
378
379int
7080f735 380size_of_uleb128 (unsigned HOST_WIDE_INT value)
2e4b9b8c 381{
4977bab6 382 int size = 0;
2e4b9b8c
RH
383
384 do
385 {
2e4b9b8c
RH
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
396int
7080f735 397size_of_sleb128 (HOST_WIDE_INT value)
2e4b9b8c
RH
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
b627d6fe 413/* Given an encoding, return the number of bytes the format occupies.
3a538a66 414 This is only defined for fixed-size encodings, and so does not
b627d6fe
RH
415 include leb128. */
416
417int
7080f735 418size_of_encoded_value (int encoding)
b627d6fe
RH
419{
420 if (encoding == DW_EH_PE_omit)
421 return 0;
422
423 switch (encoding & 0x07)
424 {
425 case DW_EH_PE_absptr:
50b6ee8b 426 return POINTER_SIZE_UNITS;
b627d6fe
RH
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;
ced3f397
NS
433 default:
434 gcc_unreachable ();
b627d6fe 435 }
b627d6fe
RH
436}
437
e1f9550a
RH
438/* Yield a name for a given pointer encoding. */
439
440const char *
7080f735 441eh_data_format_name (int format)
e1f9550a
RH
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")
099c8b17 457 S(DW_EH_PE_aligned, "aligned absolute")
e1f9550a
RH
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
f90811a2 468 S(DW_EH_PE_absptr | DW_EH_PE_pcrel, "pcrel")
e1f9550a
RH
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
f90811a2 478 S(DW_EH_PE_absptr | DW_EH_PE_textrel, "textrel")
e1f9550a
RH
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
f90811a2 488 S(DW_EH_PE_absptr | DW_EH_PE_datarel, "datarel")
e1f9550a
RH
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
f90811a2 498 S(DW_EH_PE_absptr | DW_EH_PE_funcrel, "funcrel")
e1f9550a
RH
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
49576e25
RS
508 S(DW_EH_PE_indirect | DW_EH_PE_absptr, "indirect absolute")
509
f90811a2
RH
510 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel,
511 "indirect pcrel")
e1f9550a
RH
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
f90811a2
RH
529 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_textrel,
530 "indirect textrel")
e1f9550a
RH
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
f90811a2
RH
548 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_datarel,
549 "indirect datarel")
e1f9550a
RH
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
f90811a2
RH
567 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_funcrel,
568 "indirect funcrel")
e1f9550a
RH
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
ced3f397 589 gcc_assert (format >= 0 && format < 0x100 && format_names[format]);
b8698a0f 590
e1f9550a
RH
591 return format_names[format];
592#else
593 }
ced3f397 594 gcc_unreachable ();
e1f9550a
RH
595#endif
596}
597
d4ea4622
RH
598/* Output an unsigned LEB128 quantity, but only the byte values. */
599
600void
601dw2_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
a3f1cee4 611 fprintf (asm_out_file, "%#x", byte);
d4ea4622
RH
612 if (value == 0)
613 break;
614 fputc (',', asm_out_file);
615 }
616}
617
2e4b9b8c
RH
618/* Output an unsigned LEB128 quantity. */
619
620void
e34d07f2
KG
621dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value,
622 const char *comment, ...)
2e4b9b8c 623{
e34d07f2 624 va_list ap;
7080f735 625
e34d07f2 626 va_start (ap, comment);
2e4b9b8c 627
61214be1 628 if (HAVE_AS_LEB128)
2e4b9b8c 629 {
61214be1
TS
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 }
2e4b9b8c 638 }
61214be1 639 else
2e4b9b8c 640 {
61214be1
TS
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
2e4b9b8c 647 {
61214be1
TS
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 }
2e4b9b8c
RH
674 }
675 }
61214be1 676
5e3929ed 677 putc ('\n', asm_out_file);
2e4b9b8c 678
e34d07f2 679 va_end (ap);
2e4b9b8c
RH
680}
681
d4ea4622
RH
682/* Output an signed LEB128 quantity, but only the byte values. */
683
684void
685dw2_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
a3f1cee4 698 fprintf (asm_out_file, "%#x", byte);
d4ea4622
RH
699 if (!more)
700 break;
701 fputc (',', asm_out_file);
702 }
703}
704
09da1532 705/* Output a signed LEB128 quantity. */
2e4b9b8c
RH
706
707void
e34d07f2
KG
708dw2_asm_output_data_sleb128 (HOST_WIDE_INT value,
709 const char *comment, ...)
2e4b9b8c 710{
e34d07f2 711 va_list ap;
7080f735 712
e34d07f2 713 va_start (ap, comment);
2e4b9b8c 714
61214be1 715 if (HAVE_AS_LEB128)
2e4b9b8c 716 {
61214be1
TS
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 }
2e4b9b8c 724 }
61214be1 725 else
2e4b9b8c 726 {
61214be1
TS
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
2e4b9b8c 734 {
61214be1
TS
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 }
2e4b9b8c
RH
763 }
764 }
61214be1 765
2e4b9b8c
RH
766 fputc ('\n', asm_out_file);
767
e34d07f2 768 va_end (ap);
2e4b9b8c
RH
769}
770
bd2b9f1e
AO
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
775void
776dw2_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
2e4b9b8c 800void
e34d07f2
KG
801dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
802 const char *lab2 ATTRIBUTE_UNUSED,
803 const char *comment, ...)
2e4b9b8c 804{
e34d07f2
KG
805 va_list ap;
806
807 va_start (ap, comment);
2e4b9b8c 808
61214be1
TS
809 gcc_assert (HAVE_AS_LEB128);
810
da6af203 811 fputs ("\t.uleb128 ", asm_out_file);
2e4b9b8c 812 assemble_name (asm_out_file, lab1);
5e3929ed 813 putc ('-', asm_out_file);
7728669d
MW
814 /* dwarf2out.c might give us a label expression (e.g. .LVL548-1)
815 as second argument. If so, make it a subexpression, to make
816 sure the substraction is done in the right order. */
817 if (strchr (lab2, '-') != NULL)
818 {
819 putc ('(', asm_out_file);
820 assemble_name (asm_out_file, lab2);
821 putc (')', asm_out_file);
822 }
823 else
824 assemble_name (asm_out_file, lab2);
2e4b9b8c
RH
825
826 if (flag_debug_asm && comment)
827 {
828 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
829 vfprintf (asm_out_file, comment, ap);
830 }
831 fputc ('\n', asm_out_file);
832
e34d07f2 833 va_end (ap);
2e4b9b8c
RH
834}
835
c8f4fe99
BE
836#if 0
837
2e4b9b8c 838void
e34d07f2
KG
839dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED,
840 const char *lab2 ATTRIBUTE_UNUSED,
841 const char *comment, ...)
2e4b9b8c 842{
e34d07f2 843 va_list ap;
7080f735 844
e34d07f2 845 va_start (ap, comment);
2e4b9b8c 846
61214be1
TS
847 gcc_assert (HAVE_AS_LEB128);
848
da6af203 849 fputs ("\t.sleb128 ", asm_out_file);
2e4b9b8c 850 assemble_name (asm_out_file, lab1);
5e3929ed 851 putc ('-', asm_out_file);
2e4b9b8c 852 assemble_name (asm_out_file, lab2);
2e4b9b8c
RH
853
854 if (flag_debug_asm && comment)
855 {
856 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
857 vfprintf (asm_out_file, comment, ap);
858 }
859 fputc ('\n', asm_out_file);
860
e34d07f2 861 va_end (ap);
2e4b9b8c 862}
c8f4fe99 863#endif /* 0 */
2a1ee410 864\f
de144fb2 865static GTY(()) hash_map<const char *, tree> *indirect_pool;
17211ab5
GK
866
867static GTY(()) int dw2_const_labelno;
2a1ee410 868
f31d9224
DE
869#if defined(HAVE_GAS_HIDDEN)
870# define USE_LINKONCE_INDIRECT (SUPPORTS_ONE_ONLY && !XCOFF_DEBUGGING_INFO)
d6d26764
JJ
871#else
872# define USE_LINKONCE_INDIRECT 0
873#endif
874
de144fb2
TS
875/* Compare two std::pair<const char *, tree> by their first element.
876 Returns <0, 0, or
dc1327cd
AO
877 >0 to indicate whether K1 is less than, equal to, or greater than
878 K2, respectively. */
879
880static int
de144fb2 881compare_strings (const void *a, const void *b)
dc1327cd 882{
de144fb2
TS
883 const char *s1 = ((const std::pair<const char *, tree> *) a)->first;
884 const char *s2 = ((const std::pair<const char *, tree> *) b)->first;
dc1327cd
AO
885 int ret;
886
887 if (s1 == s2)
888 return 0;
889
890 ret = strcmp (s1, s2);
891
892 /* The strings are always those from IDENTIFIER_NODEs, and,
893 therefore, we should never have two copies of the same
894 string. */
895 gcc_assert (ret);
896
897 return ret;
898}
899
e1f9550a
RH
900/* Put X, a SYMBOL_REF, in memory. Return a SYMBOL_REF to the allocated
901 memory. Differs from force_const_mem in that a single pool is used for
902 the entire unit of translation, and the memory is not guaranteed to be
d858f359 903 "near" the function in any interesting sense. IS_PUBLIC controls whether
b03e9863 904 the symbol can be shared across the entire application (or DSO). */
e1f9550a 905
d4ea4622 906rtx
d858f359 907dw2_force_const_mem (rtx x, bool is_public)
2a1ee410 908{
a2649528 909 const char *key;
78bd9046 910 tree decl_id;
2a1ee410
RH
911
912 if (! indirect_pool)
de144fb2 913 indirect_pool = hash_map<const char *, tree>::create_ggc (64);
2a1ee410 914
ced3f397 915 gcc_assert (GET_CODE (x) == SYMBOL_REF);
1ee9fb20 916
a2649528 917 key = XSTR (x, 0);
de144fb2
TS
918 tree *slot = indirect_pool->get (key);
919 if (slot)
920 decl_id = *slot;
2a1ee410
RH
921 else
922 {
2a1ee410 923 tree id;
a2649528 924 const char *str = targetm.strip_name_encoding (key);
2a1ee410 925
d858f359 926 if (is_public && USE_LINKONCE_INDIRECT)
d6d26764 927 {
f883e0a7 928 char *ref_name = XALLOCAVEC (char, strlen (str) + sizeof "DW.ref.");
d6d26764 929
1ee9fb20 930 sprintf (ref_name, "DW.ref.%s", str);
78bd9046
AO
931 gcc_assert (!maybe_get_identifier (ref_name));
932 decl_id = get_identifier (ref_name);
933 TREE_PUBLIC (decl_id) = 1;
d6d26764
JJ
934 }
935 else
936 {
d6d26764
JJ
937 char label[32];
938
17211ab5
GK
939 ASM_GENERATE_INTERNAL_LABEL (label, "LDFCM", dw2_const_labelno);
940 ++dw2_const_labelno;
78bd9046
AO
941 gcc_assert (!maybe_get_identifier (label));
942 decl_id = get_identifier (label);
d6d26764 943 }
2a1ee410 944
1ee9fb20 945 id = maybe_get_identifier (str);
2a1ee410
RH
946 if (id)
947 TREE_SYMBOL_REFERENCED (id) = 1;
948
de144fb2 949 indirect_pool->put (key, decl_id);
2a1ee410
RH
950 }
951
78bd9046 952 return gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (decl_id));
2a1ee410
RH
953}
954
de144fb2
TS
955/* A helper function for dw2_output_indirect_constants. Emit one queued
956 constant to memory. */
e1f9550a 957
2a1ee410 958static int
de144fb2 959dw2_output_indirect_constant_1 (const char *sym, tree id)
2a1ee410 960{
2a1ee410 961 rtx sym_ref;
de144fb2 962 tree decl;
78bd9046 963
c2255bc4 964 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, id, ptr_type_node);
9937ab02 965 SET_DECL_ASSEMBLER_NAME (decl, id);
78bd9046
AO
966 DECL_ARTIFICIAL (decl) = 1;
967 DECL_IGNORED_P (decl) = 1;
90841d43 968 DECL_INITIAL (decl) = build_fold_addr_expr (decl);
3895ec53 969 TREE_READONLY (decl) = 1;
56f3e9ac 970 TREE_STATIC (decl) = 1;
78bd9046
AO
971
972 if (TREE_PUBLIC (id))
973 {
974 TREE_PUBLIC (decl) = 1;
fc26fae3 975 make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
ee610fcd
RO
976 if (USE_LINKONCE_INDIRECT)
977 DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
78bd9046 978 }
78bd9046 979
2a1ee410 980 sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
058494f9
MO
981 /* Disable ASan for decl because redzones cause ABI breakage between GCC and
982 libstdc++ for `.LDFCM*' variables. See PR 78651 for details. */
983 unsigned int save_flag_sanitize = flag_sanitize;
984 flag_sanitize &= ~(SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS
985 | SANITIZE_KERNEL_ADDRESS);
d64257a4
JJ
986 /* And also temporarily disable -fsection-anchors. These indirect constants
987 are never referenced from code, so it doesn't make any sense to aggregate
988 them in blocks. */
989 int save_flag_section_anchors = flag_section_anchors;
990 flag_section_anchors = 0;
b03e9863 991 assemble_variable (decl, 1, 1, 1);
d64257a4 992 flag_section_anchors = save_flag_section_anchors;
058494f9 993 flag_sanitize = save_flag_sanitize;
50b6ee8b 994 assemble_integer (sym_ref, POINTER_SIZE_UNITS, POINTER_SIZE, 1);
f13ed3ed
JJ
995 /* The following is a hack recognized by use_blocks_for_decl_p to disable
996 section anchor handling of the decl. */
997 DECL_INITIAL (decl) = decl;
2a1ee410
RH
998
999 return 0;
1000}
1001
e1f9550a
RH
1002/* Emit the constants queued through dw2_force_const_mem. */
1003
2a1ee410 1004void
7080f735 1005dw2_output_indirect_constants (void)
2a1ee410 1006{
de144fb2
TS
1007 if (!indirect_pool)
1008 return;
1009
1010 auto_vec<std::pair<const char *, tree> > temp (indirect_pool->elements ());
1011 for (hash_map<const char *, tree>::iterator iter = indirect_pool->begin ();
1012 iter != indirect_pool->end (); ++iter)
1013 temp.quick_push (*iter);
1014
21c0a521 1015 temp.qsort (compare_strings);
de144fb2 1016
21c0a521 1017 for (unsigned int i = 0; i < temp.length (); i++)
de144fb2 1018 dw2_output_indirect_constant_1 (temp[i].first, temp[i].second);
2a1ee410
RH
1019}
1020
b03e9863
EB
1021/* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.
1022 If PUBLIC is set and the encoding is DW_EH_PE_indirect, the indirect
1023 reference is shared across the entire application (or DSO). */
e1f9550a 1024
2a1ee410 1025void
d858f359 1026dw2_asm_output_encoded_addr_rtx (int encoding, rtx addr, bool is_public,
e34d07f2 1027 const char *comment, ...)
2a1ee410
RH
1028{
1029 int size;
e34d07f2 1030 va_list ap;
7080f735 1031
e34d07f2 1032 va_start (ap, comment);
e1f9550a
RH
1033
1034 size = size_of_encoded_value (encoding);
2a1ee410 1035
099c8b17
RH
1036 if (encoding == DW_EH_PE_aligned)
1037 {
1038 assemble_align (POINTER_SIZE);
9f5cd0c5 1039 assemble_integer (addr, size, POINTER_SIZE, 1);
0edf1bb2 1040 va_end (ap);
9f5cd0c5 1041 return;
099c8b17
RH
1042 }
1043
3248917b
RK
1044 /* NULL is _always_ represented as a plain zero, as is 1 for Ada's
1045 "all others". */
1046 if (addr == const0_rtx || addr == const1_rtx)
c8af3574 1047 assemble_integer (addr, size, BITS_PER_UNIT, 1);
e1f9550a 1048 else
2a1ee410 1049 {
e1f9550a
RH
1050 restart:
1051 /* Allow the target first crack at emitting this. Some of the
3a538a66 1052 special relocations require special directives instead of
e1f9550a 1053 just ".4byte" or whatever. */
2a1ee410 1054#ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
e1f9550a
RH
1055 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
1056 addr, done);
2a1ee410
RH
1057#endif
1058
e1f9550a
RH
1059 /* Indirection is used to get dynamic relocations out of a
1060 read-only section. */
1061 if (encoding & DW_EH_PE_indirect)
1062 {
1063 /* It is very tempting to use force_const_mem so that we share data
1064 with the normal constant pool. However, we've already emitted
1065 the constant pool for this function. Moreover, we'd like to
b03e9863
EB
1066 share these constants across the entire unit of translation and
1067 even, if possible, across the entire application (or DSO). */
d858f359 1068 addr = dw2_force_const_mem (addr, is_public);
e1f9550a
RH
1069 encoding &= ~DW_EH_PE_indirect;
1070 goto restart;
1071 }
2a1ee410 1072
e1f9550a
RH
1073 switch (encoding & 0xF0)
1074 {
1075 case DW_EH_PE_absptr:
301d03af 1076 dw2_assemble_integer (size, addr);
e1f9550a 1077 break;
2a1ee410 1078
04218b35
AD
1079#ifdef ASM_OUTPUT_DWARF_DATAREL
1080 case DW_EH_PE_datarel:
1081 gcc_assert (GET_CODE (addr) == SYMBOL_REF);
1082 ASM_OUTPUT_DWARF_DATAREL (asm_out_file, size, XSTR (addr, 0));
1083 break;
1084#endif
1085
e1f9550a 1086 case DW_EH_PE_pcrel:
ced3f397 1087 gcc_assert (GET_CODE (addr) == SYMBOL_REF);
2a1ee410 1088#ifdef ASM_OUTPUT_DWARF_PCREL
e1f9550a 1089 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
2a1ee410 1090#else
301d03af 1091 dw2_assemble_integer (size, gen_rtx_MINUS (Pmode, addr, pc_rtx));
2a1ee410 1092#endif
e1f9550a 1093 break;
2a1ee410 1094
e1f9550a 1095 default:
3a538a66 1096 /* Other encodings should have been handled by
e1f9550a 1097 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
ced3f397 1098 gcc_unreachable ();
e1f9550a 1099 }
2a1ee410
RH
1100
1101#ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
e1f9550a 1102 done:;
2a1ee410 1103#endif
e1f9550a
RH
1104 }
1105
1106 if (flag_debug_asm && comment)
1107 {
1108 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
1109 vfprintf (asm_out_file, comment, ap);
1110 }
2a1ee410 1111 fputc ('\n', asm_out_file);
e1f9550a 1112
e34d07f2 1113 va_end (ap);
2a1ee410 1114}
17211ab5
GK
1115
1116#include "gt-dwarf2asm.h"