1/* Dwarf2 assembler output helper routines.
2   Copyright (C) 2001-2020 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
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
8Software Foundation; either version 3, or (at your option) any later
9version.
10
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.
15
16You should have received a copy of the GNU General Public License
17along 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
46void
47dw2_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
66void
67dw2_asm_output_data_raw (int size, unsigned HOST_WIDE_INT value)
68{
69  unsigned char bytes[8];
70  int i;
71
72  for (i = 0; i < 8; ++i)
73    {
74      bytes[i] = value & 0xff;
75      value >>= 8;
76    }
77
78  if (BYTES_BIG_ENDIAN)
79    {
80      for (i = size - 1; i > 0; --i)
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
94void
95dw2_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
130void
131dw2_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
160void
161dw2_asm_output_vms_delta (int size ATTRIBUTE_UNUSED,
162			  const char *lab1, const char *lab2,
163			  const char *comment, ...)
164{
165  va_list ap;
166
167  va_start (ap, comment);
168
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
188void
189dw2_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
213void
214dw2_asm_output_offset (int size, const char *label, HOST_WIDE_INT offset,
215		       section *base ATTRIBUTE_UNUSED,
216		       const char *comment, ...)
217{
218  va_list ap;
219
220  va_start (ap, comment);
221
222#ifdef ASM_OUTPUT_DWARF_OFFSET
223  ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label, offset, base);
224#else
225  dw2_assemble_integer (size, gen_rtx_PLUS (Pmode,
226					    gen_rtx_SYMBOL_REF (Pmode, label),
227					    gen_int_mode (offset, Pmode)));
228#endif
229
230  if (flag_debug_asm && comment)
231    {
232      fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
233      vfprintf (asm_out_file, comment, ap);
234    }
235  fputc ('\n', asm_out_file);
236
237  va_end (ap);
238}
239
240#if 0
241
242/* Output a self-relative reference to a label, possibly in a
243   different section or object file.  */
244
245void
246dw2_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
276void
277dw2_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
298void
299dw2_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
325void
326dw2_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
379int
380size_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
396int
397size_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
417int
418size_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
440const char *
441eh_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
600void
601dw2_asm_output_data_uleb128_raw (unsigned HOST_WIDE_INT value)
602{
603  while (1)
604    {
605      int byte = (value & 0x7f);
606      value >>= 7;
607      if (value != 0)
608	/* More bytes to follow.  */
609	byte |= 0x80;
610
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
620void
621dw2_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
684void
685dw2_asm_output_data_sleb128_raw (HOST_WIDE_INT value)
686{
687  int byte, more;
688
689  while (1)
690    {
691      byte = (value & 0x7f);
692      value >>= 7;
693      more = !((value == 0 && (byte & 0x40) == 0)
694		|| (value == -1 && (byte & 0x40) != 0));
695      if (more)
696	byte |= 0x80;
697
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
707void
708dw2_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
775void
776dw2_asm_output_symname_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
777				const char *comment, ...)
778{
779  va_list ap;
780
781  va_start (ap, comment);
782
783#ifdef HAVE_AS_LEB128
784  fputs ("\t.uleb128 ", asm_out_file);
785  assemble_name (asm_out_file, lab1);
786#else
787  gcc_unreachable ();
788#endif
789
790  if (flag_debug_asm && comment)
791    {
792      fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
793      vfprintf (asm_out_file, comment, ap);
794    }
795  fputc ('\n', asm_out_file);
796
797  va_end (ap);
798}
799
800void
801dw2_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
838void
839dw2_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
865static GTY(()) hash_map<const char *, tree> *indirect_pool;
866
867static 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
880static int
881compare_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
906rtx
907dw2_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
958static int
959dw2_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
1004void
1005dw2_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
1025void
1026dw2_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"
1117