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