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