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