xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/dwarf2asm.c (revision e6c7e151de239c49d2e38720a061ed9d1fa99309)
1 /* Dwarf2 assembler output helper routines.
2    Copyright (C) 2001-2017 Free Software Foundation, Inc.
3 
4 This file is part of GCC.
5 
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10 
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19 
20 
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "target.h"
25 #include "rtl.h"
26 #include "tree.h"
27 #include "memmodel.h"
28 #include "tm_p.h"
29 #include "stringpool.h"
30 #include "varasm.h"
31 #include "output.h"
32 #include "dwarf2asm.h"
33 #include "dwarf2.h"
34 #include "function.h"
35 #include "emit-rtl.h"
36 #include "fold-const.h"
37 
38 #ifndef XCOFF_DEBUGGING_INFO
39 #define XCOFF_DEBUGGING_INFO 0
40 #endif
41 
42 
43 /* Output an unaligned integer with the given value and size.  Prefer not
44    to print a newline, since the caller may want to add a comment.  */
45 
46 void
47 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 
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 void
772 dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
773 			      const char *lab2 ATTRIBUTE_UNUSED,
774 			      const char *comment, ...)
775 {
776   va_list ap;
777 
778   va_start (ap, comment);
779 
780   gcc_assert (HAVE_AS_LEB128);
781 
782   fputs ("\t.uleb128 ", asm_out_file);
783   assemble_name (asm_out_file, lab1);
784   putc ('-', asm_out_file);
785   assemble_name (asm_out_file, lab2);
786 
787   if (flag_debug_asm && comment)
788     {
789       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
790       vfprintf (asm_out_file, comment, ap);
791     }
792   fputc ('\n', asm_out_file);
793 
794   va_end (ap);
795 }
796 
797 #if 0
798 
799 void
800 dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED,
801 			      const char *lab2 ATTRIBUTE_UNUSED,
802 			      const char *comment, ...)
803 {
804   va_list ap;
805 
806   va_start (ap, comment);
807 
808   gcc_assert (HAVE_AS_LEB128);
809 
810   fputs ("\t.sleb128 ", asm_out_file);
811   assemble_name (asm_out_file, lab1);
812   putc ('-', asm_out_file);
813   assemble_name (asm_out_file, lab2);
814 
815   if (flag_debug_asm && comment)
816     {
817       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
818       vfprintf (asm_out_file, comment, ap);
819     }
820   fputc ('\n', asm_out_file);
821 
822   va_end (ap);
823 }
824 #endif /* 0 */
825 
826 static GTY(()) hash_map<const char *, tree> *indirect_pool;
827 
828 static GTY(()) int dw2_const_labelno;
829 
830 #if defined(HAVE_GAS_HIDDEN)
831 # define USE_LINKONCE_INDIRECT (SUPPORTS_ONE_ONLY && !XCOFF_DEBUGGING_INFO)
832 #else
833 # define USE_LINKONCE_INDIRECT 0
834 #endif
835 
836 /* Compare two std::pair<const char *, tree> by their first element.
837    Returns <0, 0, or
838    >0 to indicate whether K1 is less than, equal to, or greater than
839    K2, respectively.  */
840 
841 static int
842 compare_strings (const void *a, const void *b)
843 {
844   const char *s1 = ((const std::pair<const char *, tree> *) a)->first;
845   const char *s2 = ((const std::pair<const char *, tree> *) b)->first;
846   int ret;
847 
848   if (s1 == s2)
849     return 0;
850 
851   ret = strcmp (s1, s2);
852 
853   /* The strings are always those from IDENTIFIER_NODEs, and,
854      therefore, we should never have two copies of the same
855      string.  */
856   gcc_assert (ret);
857 
858   return ret;
859 }
860 
861 /* Put X, a SYMBOL_REF, in memory.  Return a SYMBOL_REF to the allocated
862    memory.  Differs from force_const_mem in that a single pool is used for
863    the entire unit of translation, and the memory is not guaranteed to be
864    "near" the function in any interesting sense.  IS_PUBLIC controls whether
865    the symbol can be shared across the entire application (or DSO).  */
866 
867 rtx
868 dw2_force_const_mem (rtx x, bool is_public)
869 {
870   const char *key;
871   tree decl_id;
872 
873   if (! indirect_pool)
874     indirect_pool = hash_map<const char *, tree>::create_ggc (64);
875 
876   gcc_assert (GET_CODE (x) == SYMBOL_REF);
877 
878   key = XSTR (x, 0);
879   tree *slot = indirect_pool->get (key);
880   if (slot)
881     decl_id = *slot;
882   else
883     {
884       tree id;
885       const char *str = targetm.strip_name_encoding (key);
886 
887       if (is_public && USE_LINKONCE_INDIRECT)
888 	{
889 	  char *ref_name = XALLOCAVEC (char, strlen (str) + sizeof "DW.ref.");
890 
891 	  sprintf (ref_name, "DW.ref.%s", str);
892 	  gcc_assert (!maybe_get_identifier (ref_name));
893 	  decl_id = get_identifier (ref_name);
894 	  TREE_PUBLIC (decl_id) = 1;
895 	}
896       else
897 	{
898 	  char label[32];
899 
900 	  ASM_GENERATE_INTERNAL_LABEL (label, "LDFCM", dw2_const_labelno);
901 	  ++dw2_const_labelno;
902 	  gcc_assert (!maybe_get_identifier (label));
903 	  decl_id = get_identifier (label);
904 	}
905 
906       id = maybe_get_identifier (str);
907       if (id)
908 	TREE_SYMBOL_REFERENCED (id) = 1;
909 
910       indirect_pool->put (key, decl_id);
911     }
912 
913   return gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (decl_id));
914 }
915 
916 /* A helper function for dw2_output_indirect_constants.  Emit one queued
917    constant to memory.  */
918 
919 static int
920 dw2_output_indirect_constant_1 (const char *sym, tree id)
921 {
922   rtx sym_ref;
923   tree decl;
924 
925   decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, id, ptr_type_node);
926   SET_DECL_ASSEMBLER_NAME (decl, id);
927   DECL_ARTIFICIAL (decl) = 1;
928   DECL_IGNORED_P (decl) = 1;
929   DECL_INITIAL (decl) = build_fold_addr_expr (decl);
930   TREE_READONLY (decl) = 1;
931   TREE_STATIC (decl) = 1;
932 
933   if (TREE_PUBLIC (id))
934     {
935       TREE_PUBLIC (decl) = 1;
936       make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
937       if (USE_LINKONCE_INDIRECT)
938 	DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
939     }
940 
941   sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
942   /* Disable ASan for decl because redzones cause ABI breakage between GCC and
943      libstdc++ for `.LDFCM*' variables.  See PR 78651 for details.  */
944   unsigned int save_flag_sanitize = flag_sanitize;
945   flag_sanitize &= ~(SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS
946 		     | SANITIZE_KERNEL_ADDRESS);
947   /* And also temporarily disable -fsection-anchors.  These indirect constants
948      are never referenced from code, so it doesn't make any sense to aggregate
949      them in blocks.  */
950   int save_flag_section_anchors = flag_section_anchors;
951   flag_section_anchors = 0;
952   assemble_variable (decl, 1, 1, 1);
953   flag_section_anchors = save_flag_section_anchors;
954   flag_sanitize = save_flag_sanitize;
955   assemble_integer (sym_ref, POINTER_SIZE_UNITS, POINTER_SIZE, 1);
956   /* The following is a hack recognized by use_blocks_for_decl_p to disable
957      section anchor handling of the decl.  */
958   DECL_INITIAL (decl) = decl;
959 
960   return 0;
961 }
962 
963 /* Emit the constants queued through dw2_force_const_mem.  */
964 
965 void
966 dw2_output_indirect_constants (void)
967 {
968   if (!indirect_pool)
969     return;
970 
971   auto_vec<std::pair<const char *, tree> > temp (indirect_pool->elements ());
972   for (hash_map<const char *, tree>::iterator iter = indirect_pool->begin ();
973        iter != indirect_pool->end (); ++iter)
974     temp.quick_push (*iter);
975 
976   temp.qsort (compare_strings);
977 
978   for (unsigned int i = 0; i < temp.length (); i++)
979     dw2_output_indirect_constant_1 (temp[i].first, temp[i].second);
980 }
981 
982 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.
983    If PUBLIC is set and the encoding is DW_EH_PE_indirect, the indirect
984    reference is shared across the entire application (or DSO).  */
985 
986 void
987 dw2_asm_output_encoded_addr_rtx (int encoding, rtx addr, bool is_public,
988 				 const char *comment, ...)
989 {
990   int size;
991   va_list ap;
992 
993   va_start (ap, comment);
994 
995   size = size_of_encoded_value (encoding);
996 
997   if (encoding == DW_EH_PE_aligned)
998     {
999       assemble_align (POINTER_SIZE);
1000       assemble_integer (addr, size, POINTER_SIZE, 1);
1001       va_end (ap);
1002       return;
1003     }
1004 
1005   /* NULL is _always_ represented as a plain zero, as is 1 for Ada's
1006      "all others".  */
1007   if (addr == const0_rtx || addr == const1_rtx)
1008     assemble_integer (addr, size, BITS_PER_UNIT, 1);
1009   else
1010     {
1011     restart:
1012       /* Allow the target first crack at emitting this.  Some of the
1013 	 special relocations require special directives instead of
1014 	 just ".4byte" or whatever.  */
1015 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
1016       ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
1017 					 addr, done);
1018 #endif
1019 
1020       /* Indirection is used to get dynamic relocations out of a
1021 	 read-only section.  */
1022       if (encoding & DW_EH_PE_indirect)
1023 	{
1024 	  /* It is very tempting to use force_const_mem so that we share data
1025 	     with the normal constant pool.  However, we've already emitted
1026 	     the constant pool for this function.  Moreover, we'd like to
1027 	     share these constants across the entire unit of translation and
1028 	     even, if possible, across the entire application (or DSO).  */
1029 	  addr = dw2_force_const_mem (addr, is_public);
1030 	  encoding &= ~DW_EH_PE_indirect;
1031 	  goto restart;
1032 	}
1033 
1034       switch (encoding & 0xF0)
1035 	{
1036 	case DW_EH_PE_absptr:
1037 	  dw2_assemble_integer (size, addr);
1038 	  break;
1039 
1040 #ifdef ASM_OUTPUT_DWARF_DATAREL
1041 	case DW_EH_PE_datarel:
1042 	  gcc_assert (GET_CODE (addr) == SYMBOL_REF);
1043 	  ASM_OUTPUT_DWARF_DATAREL (asm_out_file, size, XSTR (addr, 0));
1044 	  break;
1045 #endif
1046 
1047 	case DW_EH_PE_pcrel:
1048 	  gcc_assert (GET_CODE (addr) == SYMBOL_REF);
1049 #ifdef ASM_OUTPUT_DWARF_PCREL
1050 	  ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
1051 #else
1052 	  dw2_assemble_integer (size, gen_rtx_MINUS (Pmode, addr, pc_rtx));
1053 #endif
1054 	  break;
1055 
1056 	default:
1057 	  /* Other encodings should have been handled by
1058 	     ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX.  */
1059 	  gcc_unreachable ();
1060 	}
1061 
1062 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
1063     done:;
1064 #endif
1065     }
1066 
1067   if (flag_debug_asm && comment)
1068     {
1069       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
1070       vfprintf (asm_out_file, comment, ap);
1071     }
1072   fputc ('\n', asm_out_file);
1073 
1074   va_end (ap);
1075 }
1076 
1077 #include "gt-dwarf2asm.h"
1078