LCOV - code coverage report
Current view: top level - gcc - dwarf2cfi.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 66.7 % 1704 1136
Test Date: 2026-02-28 14:20:25 Functions: 89.5 % 76 68
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Dwarf2 Call Frame Information helper routines.
       2              :    Copyright (C) 1992-2026 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              : #include "config.h"
      21              : #include "system.h"
      22              : #include "coretypes.h"
      23              : #include "target.h"
      24              : #include "function.h"
      25              : #include "rtl.h"
      26              : #include "tree.h"
      27              : #include "tree-pass.h"
      28              : #include "memmodel.h"
      29              : #include "tm_p.h"
      30              : #include "emit-rtl.h"
      31              : #include "stor-layout.h"
      32              : #include "cfgbuild.h"
      33              : #include "dwarf2out.h"
      34              : #include "dwarf2asm.h"
      35              : #include "common/common-target.h"
      36              : 
      37              : #include "except.h"           /* expand_builtin_dwarf_sp_column */
      38              : #include "profile-count.h"    /* For expr.h */
      39              : #include "expr.h"             /* init_return_column_size */
      40              : #include "output.h"           /* asm_out_file */
      41              : #include "debug.h"            /* dwarf2out_do_frame, dwarf2out_do_cfi_asm */
      42              : #include "flags.h"            /* dwarf_debuginfo_p */
      43              : 
      44              : /* ??? Poison these here until it can be done generically.  They've been
      45              :    totally replaced in this file; make sure it stays that way.  */
      46              : #undef DWARF2_UNWIND_INFO
      47              : #undef DWARF2_FRAME_INFO
      48              : #if (GCC_VERSION >= 3000)
      49              :  #pragma GCC poison DWARF2_UNWIND_INFO DWARF2_FRAME_INFO
      50              : #endif
      51              : 
      52              : #ifndef INCOMING_RETURN_ADDR_RTX
      53              : #define INCOMING_RETURN_ADDR_RTX  (gcc_unreachable (), NULL_RTX)
      54              : #endif
      55              : 
      56              : #ifndef DEFAULT_INCOMING_FRAME_SP_OFFSET
      57              : #define DEFAULT_INCOMING_FRAME_SP_OFFSET INCOMING_FRAME_SP_OFFSET
      58              : #endif
      59              : 
      60              : 
      61              : /* Signing method used for return address authentication.
      62              :    (AArch64 extension)  */
      63              : typedef enum
      64              : {
      65              :   ra_no_signing = 0x0,
      66              :   ra_signing_sp = 0x1,
      67              : } ra_signing_method_t;
      68              : 
      69              : /* A collected description of an entire row of the abstract CFI table.  */
      70              : struct GTY(()) dw_cfi_row
      71              : {
      72              :   /* The expression that computes the CFA, expressed in two different ways.
      73              :      The CFA member for the simple cases, and the full CFI expression for
      74              :      the complex cases.  The later will be a DW_CFA_cfa_expression.  */
      75              :   dw_cfa_location cfa;
      76              :   dw_cfi_ref cfa_cfi;
      77              : 
      78              :   /* The expressions for any register column that is saved.  */
      79              :   cfi_vec reg_save;
      80              : 
      81              :   /* SPARC extension for DW_CFA_GNU_window_save.
      82              :      True if the register window is saved.  */
      83              :   bool window_save;
      84              : 
      85              :   /* AArch64 extension for DW_CFA_AARCH64_negate_ra_state.
      86              :      Enum which stores the return address state.  */
      87              :   ra_signing_method_t ra_state;
      88              : };
      89              : 
      90              : /* The caller's ORIG_REG is saved in SAVED_IN_REG.  */
      91              : struct GTY(()) reg_saved_in_data {
      92              :   rtx orig_reg;
      93              :   rtx saved_in_reg;
      94              : };
      95              : 
      96              : 
      97              : /* Since we no longer have a proper CFG, we're going to create a facsimile
      98              :    of one on the fly while processing the frame-related insns.
      99              : 
     100              :    We create dw_trace_info structures for each extended basic block beginning
     101              :    and ending at a "save point".  Save points are labels, barriers, certain
     102              :    notes, and of course the beginning and end of the function.
     103              : 
     104              :    As we encounter control transfer insns, we propagate the "current"
     105              :    row state across the edges to the starts of traces.  When checking is
     106              :    enabled, we validate that we propagate the same data from all sources.
     107              : 
     108              :    All traces are members of the TRACE_INFO array, in the order in which
     109              :    they appear in the instruction stream.
     110              : 
     111              :    All save points are present in the TRACE_INDEX hash, mapping the insn
     112              :    starting a trace to the dw_trace_info describing the trace.  */
     113              : 
     114              : struct dw_trace_info
     115              : {
     116              :   /* The insn that begins the trace.  */
     117              :   rtx_insn *head;
     118              : 
     119              :   /* The row state at the beginning and end of the trace.  */
     120              :   dw_cfi_row *beg_row, *end_row;
     121              : 
     122              :   /* Tracking for DW_CFA_GNU_args_size.  The "true" sizes are those we find
     123              :      while scanning insns.  However, the args_size value is irrelevant at
     124              :      any point except can_throw_internal_p insns.  Therefore the "delay"
     125              :      sizes the values that must actually be emitted for this trace.  */
     126              :   poly_int64 beg_true_args_size, end_true_args_size;
     127              :   poly_int64 beg_delay_args_size, end_delay_args_size;
     128              : 
     129              :   /* The first EH insn in the trace, where beg_delay_args_size must be set.  */
     130              :   rtx_insn *eh_head;
     131              : 
     132              :   /* The following variables contain data used in interpreting frame related
     133              :      expressions.  These are not part of the "real" row state as defined by
     134              :      Dwarf, but it seems like they need to be propagated into a trace in case
     135              :      frame related expressions have been sunk.  */
     136              :   /* ??? This seems fragile.  These variables are fragments of a larger
     137              :      expression.  If we do not keep the entire expression together, we risk
     138              :      not being able to put it together properly.  Consider forcing targets
     139              :      to generate self-contained expressions and dropping all of the magic
     140              :      interpretation code in this file.  Or at least refusing to shrink wrap
     141              :      any frame related insn that doesn't contain a complete expression.  */
     142              : 
     143              :   /* The register used for saving registers to the stack, and its offset
     144              :      from the CFA.  */
     145              :   dw_cfa_location cfa_store;
     146              : 
     147              :   /* A temporary register holding an integral value used in adjusting SP
     148              :      or setting up the store_reg.  The "offset" field holds the integer
     149              :      value, not an offset.  */
     150              :   dw_cfa_location cfa_temp;
     151              : 
     152              :   /* A set of registers saved in other registers.  This is the inverse of
     153              :      the row->reg_save info, if the entry is a DW_CFA_register.  This is
     154              :      implemented as a flat array because it normally contains zero or 1
     155              :      entry, depending on the target.  IA-64 is the big spender here, using
     156              :      a maximum of 5 entries.  */
     157              :   vec<reg_saved_in_data> regs_saved_in_regs;
     158              : 
     159              :   /* An identifier for this trace.  Used only for debugging dumps.  */
     160              :   unsigned id;
     161              : 
     162              :   /* True if this trace immediately follows NOTE_INSN_SWITCH_TEXT_SECTIONS.  */
     163              :   bool switch_sections;
     164              : 
     165              :   /* True if we've seen different values incoming to beg_true_args_size.  */
     166              :   bool args_size_undefined;
     167              : 
     168              :   /* True if we've seen an insn with a REG_ARGS_SIZE note before EH_HEAD.  */
     169              :   bool args_size_defined_for_eh;
     170              : };
     171              : 
     172              : 
     173              : /* Hashtable helpers.  */
     174              : 
     175              : struct trace_info_hasher : nofree_ptr_hash <dw_trace_info>
     176              : {
     177              :   static inline hashval_t hash (const dw_trace_info *);
     178              :   static inline bool equal (const dw_trace_info *, const dw_trace_info *);
     179              : };
     180              : 
     181              : inline hashval_t
     182    124392410 : trace_info_hasher::hash (const dw_trace_info *ti)
     183              : {
     184    124392410 :   return INSN_UID (ti->head);
     185              : }
     186              : 
     187              : inline bool
     188    143301096 : trace_info_hasher::equal (const dw_trace_info *a, const dw_trace_info *b)
     189              : {
     190    143301096 :   return a->head == b->head;
     191              : }
     192              : 
     193              : 
     194              : /* The variables making up the pseudo-cfg, as described above.  */
     195              : static vec<dw_trace_info> trace_info;
     196              : static vec<dw_trace_info *> trace_work_list;
     197              : static hash_table<trace_info_hasher> *trace_index;
     198              : 
     199              : /* A vector of call frame insns for the CIE.  */
     200              : cfi_vec cie_cfi_vec;
     201              : 
     202              : /* The state of the first row of the FDE table, which includes the
     203              :    state provided by the CIE.  */
     204              : static GTY(()) dw_cfi_row *cie_cfi_row;
     205              : 
     206              : static GTY(()) reg_saved_in_data *cie_return_save;
     207              : 
     208              : static GTY(()) unsigned long dwarf2out_cfi_label_num;
     209              : 
     210              : /* The insn after which a new CFI note should be emitted.  */
     211              : static rtx_insn *add_cfi_insn;
     212              : 
     213              : /* When non-null, add_cfi will add the CFI to this vector.  */
     214              : static cfi_vec *add_cfi_vec;
     215              : 
     216              : /* The current instruction trace.  */
     217              : static dw_trace_info *cur_trace;
     218              : 
     219              : /* The current, i.e. most recently generated, row of the CFI table.  */
     220              : static dw_cfi_row *cur_row;
     221              : 
     222              : /* A copy of the current CFA, for use during the processing of a
     223              :    single insn.  */
     224              : static dw_cfa_location *cur_cfa;
     225              : 
     226              : /* We delay emitting a register save until either (a) we reach the end
     227              :    of the prologue or (b) the register is clobbered.  This clusters
     228              :    register saves so that there are fewer pc advances.  */
     229              : 
     230              : struct queued_reg_save {
     231              :   rtx reg;
     232              :   rtx saved_reg;
     233              :   poly_int64 cfa_offset;
     234              : };
     235              : 
     236              : 
     237              : static vec<queued_reg_save> queued_reg_saves;
     238              : 
     239              : /* True if any CFI directives were emitted at the current insn.  */
     240              : static bool any_cfis_emitted;
     241              : 
     242              : /* Short-hand for commonly used register numbers.  */
     243              : static struct cfa_reg dw_stack_pointer_regnum;
     244              : static struct cfa_reg dw_frame_pointer_regnum;
     245              : 
     246              : /* Hook used by __throw.  */
     247              : 
     248              : rtx
     249           48 : expand_builtin_dwarf_sp_column (void)
     250              : {
     251           48 :   unsigned int dwarf_regnum = DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM);
     252           48 :   return GEN_INT (DWARF2_FRAME_REG_OUT (dwarf_regnum, 1));
     253              : }
     254              : 
     255              : /* MEM is a memory reference for the register size table, each element of
     256              :    which has mode MODE.  Initialize column C as a return address column.  */
     257              : 
     258              : static void
     259            8 : init_return_column_size (scalar_int_mode mode, rtx mem, unsigned int c)
     260              : {
     261            8 :   HOST_WIDE_INT offset = c * GET_MODE_SIZE (mode);
     262            8 :   HOST_WIDE_INT size = GET_MODE_SIZE (Pmode);
     263            8 :   emit_move_insn (adjust_address (mem, mode, offset),
     264            8 :                   gen_int_mode (size, mode));
     265            8 : }
     266              : 
     267              : /* Datastructure used by expand_builtin_init_dwarf_reg_sizes and
     268              :    init_one_dwarf_reg_size to communicate on what has been done by the
     269              :    latter.  */
     270              : 
     271              : struct init_one_dwarf_reg_state
     272              : {
     273              :   /* Whether the dwarf return column was initialized.  */
     274              :   bool wrote_return_column;
     275              : 
     276              :   /* For each hard register REGNO, whether init_one_dwarf_reg_size
     277              :      was given REGNO to process already.  */
     278              :   bool processed_regno [FIRST_PSEUDO_REGISTER];
     279              : 
     280              : };
     281              : 
     282              : /* Helper for expand_builtin_init_dwarf_reg_sizes.  Generate code to
     283              :    initialize the dwarf register size table entry corresponding to register
     284              :    REGNO in REGMODE.  TABLE is the table base address, SLOTMODE is the mode to
     285              :    use for the size entry to initialize, and INIT_STATE is the communication
     286              :    datastructure conveying what we're doing to our caller.  */
     287              : 
     288              : static
     289          736 : void init_one_dwarf_reg_size (int regno, machine_mode regmode,
     290              :                               rtx table, machine_mode slotmode,
     291              :                               init_one_dwarf_reg_state *init_state)
     292              : {
     293          736 :   const unsigned int dnum = DWARF_FRAME_REGNUM (regno);
     294          736 :   const unsigned int rnum = DWARF2_FRAME_REG_OUT (dnum, 1);
     295          736 :   const unsigned int dcol = DWARF_REG_TO_UNWIND_COLUMN (rnum);
     296              : 
     297         1472 :   poly_int64 slotoffset = dcol * GET_MODE_SIZE (slotmode);
     298         1472 :   poly_int64 regsize = GET_MODE_SIZE (regmode);
     299              : 
     300          736 :   init_state->processed_regno[regno] = true;
     301              : 
     302          736 :   if (rnum >= DWARF_FRAME_REGISTERS)
     303          548 :     return;
     304              : 
     305          312 :   if (dnum == DWARF_FRAME_RETURN_COLUMN)
     306              :     {
     307            0 :       if (regmode == VOIDmode)
     308              :         return;
     309            0 :       init_state->wrote_return_column = true;
     310              :     }
     311              : 
     312              :   /* ??? When is this true?  Should it be a test based on DCOL instead?  */
     313          188 :   if (maybe_lt (slotoffset, 0))
     314              :     return;
     315              : 
     316          188 :   emit_move_insn (adjust_address (table, slotmode, slotoffset),
     317              :                   gen_int_mode (regsize, slotmode));
     318              : }
     319              : 
     320              : /* Generate code to initialize the dwarf register size table located
     321              :    at the provided ADDRESS.  */
     322              : 
     323              : void
     324            8 : expand_builtin_init_dwarf_reg_sizes (tree address)
     325              : {
     326            8 :   unsigned int i;
     327            8 :   scalar_int_mode mode = SCALAR_INT_TYPE_MODE (char_type_node);
     328            8 :   rtx addr = expand_normal (address);
     329            8 :   rtx mem = gen_rtx_MEM (BLKmode, addr);
     330              : 
     331            8 :   init_one_dwarf_reg_state init_state;
     332              : 
     333            8 :   memset ((char *)&init_state, 0, sizeof (init_state));
     334              : 
     335          744 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     336              :     {
     337          736 :       machine_mode save_mode;
     338          736 :       rtx span;
     339              : 
     340              :       /* No point in processing a register multiple times.  This could happen
     341              :          with register spans, e.g. when a reg is first processed as a piece of
     342              :          a span, then as a register on its own later on.  */
     343              : 
     344          736 :       if (init_state.processed_regno[i])
     345            0 :         continue;
     346              : 
     347          736 :       save_mode = targetm.dwarf_frame_reg_mode (i);
     348          736 :       span = targetm.dwarf_register_span (gen_rtx_REG (save_mode, i));
     349              : 
     350          736 :       if (!span)
     351          736 :         init_one_dwarf_reg_size (i, save_mode, mem, mode, &init_state);
     352              :       else
     353              :         {
     354            0 :           for (int si = 0; si < XVECLEN (span, 0); si++)
     355              :             {
     356            0 :               rtx reg = XVECEXP (span, 0, si);
     357              : 
     358            0 :               init_one_dwarf_reg_size
     359            0 :                 (REGNO (reg), GET_MODE (reg), mem, mode, &init_state);
     360              :             }
     361              :         }
     362              :     }
     363              : 
     364            8 :   if (!init_state.wrote_return_column)
     365           12 :     init_return_column_size (mode, mem, DWARF_FRAME_RETURN_COLUMN);
     366              : 
     367              : #ifdef DWARF_ALT_FRAME_RETURN_COLUMN
     368              :   init_return_column_size (mode, mem, DWARF_ALT_FRAME_RETURN_COLUMN);
     369              : #endif
     370              : 
     371            8 :   targetm.init_dwarf_reg_sizes_extra (address);
     372            8 : }
     373              : 
     374              : 
     375              : static dw_trace_info *
     376     16258850 : get_trace_info (rtx_insn *insn)
     377              : {
     378     16258850 :   dw_trace_info dummy;
     379     16258850 :   dummy.head = insn;
     380     16258850 :   return trace_index->find_with_hash (&dummy, INSN_UID (insn));
     381              : }
     382              : 
     383              : static bool
     384    384392005 : save_point_p (rtx_insn *insn)
     385              : {
     386              :   /* Labels, except those that are really jump tables.  */
     387    384392005 :   if (LABEL_P (insn))
     388     10510764 :     return inside_basic_block_p (insn);
     389              : 
     390              :   /* We split traces at the prologue/epilogue notes because those
     391              :      are points at which the unwind info is usually stable.  This
     392              :      makes it easier to find spots with identical unwind info so
     393              :      that we can use remember/restore_state opcodes.  */
     394    373881241 :   if (NOTE_P (insn))
     395    187051830 :     switch (NOTE_KIND (insn))
     396              :       {
     397      6089280 :       case NOTE_INSN_PROLOGUE_END:
     398      6089280 :       case NOTE_INSN_EPILOGUE_BEG:
     399      6089280 :         return true;
     400              :       }
     401              : 
     402              :   return false;
     403              : }
     404              : 
     405              : /* Divide OFF by DWARF_CIE_DATA_ALIGNMENT, asserting no remainder.  */
     406              : 
     407              : static inline HOST_WIDE_INT
     408           41 : div_data_align (HOST_WIDE_INT off)
     409              : {
     410           41 :   HOST_WIDE_INT r = off / DWARF_CIE_DATA_ALIGNMENT;
     411           41 :   gcc_assert (r * DWARF_CIE_DATA_ALIGNMENT == off);
     412           41 :   return r;
     413              : }
     414              : 
     415              : /* Return true if we need a signed version of a given opcode
     416              :    (e.g. DW_CFA_offset_extended_sf vs DW_CFA_offset_extended).  */
     417              : 
     418              : static inline bool
     419              : need_data_align_sf_opcode (HOST_WIDE_INT off)
     420              : {
     421              :   return DWARF_CIE_DATA_ALIGNMENT < 0 ? off > 0 : off < 0;
     422              : }
     423              : 
     424              : /* Return a pointer to a newly allocated Call Frame Instruction.  */
     425              : 
     426              : static inline dw_cfi_ref
     427     11971920 : new_cfi (void)
     428              : {
     429     23943840 :   dw_cfi_ref cfi = ggc_alloc<dw_cfi_node> ();
     430              : 
     431     11971920 :   cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0;
     432     11971920 :   cfi->dw_cfi_oprnd2.dw_cfi_reg_num = 0;
     433              : 
     434     11971920 :   return cfi;
     435              : }
     436              : 
     437              : /* Return a newly allocated CFI row, with no defined data.  */
     438              : 
     439              : static dw_cfi_row *
     440       209004 : new_cfi_row (void)
     441              : {
     442            0 :   dw_cfi_row *row = ggc_cleared_alloc<dw_cfi_row> ();
     443              : 
     444       209004 :   row->cfa.reg.set_by_dwreg (INVALID_REGNUM);
     445              : 
     446       209004 :   return row;
     447              : }
     448              : 
     449              : /* Return a copy of an existing CFI row.  */
     450              : 
     451              : static dw_cfi_row *
     452     21320442 : copy_cfi_row (dw_cfi_row *src)
     453              : {
     454     21320442 :   dw_cfi_row *dst = ggc_alloc<dw_cfi_row> ();
     455              : 
     456     21320442 :   *dst = *src;
     457     21320442 :   dst->reg_save = vec_safe_copy (src->reg_save);
     458              : 
     459     21320442 :   return dst;
     460              : }
     461              : 
     462              : /* Return a copy of an existing CFA location.  */
     463              : 
     464              : static dw_cfa_location *
     465            0 : copy_cfa (dw_cfa_location *src)
     466              : {
     467            0 :   dw_cfa_location *dst = ggc_alloc<dw_cfa_location> ();
     468            0 :   *dst = *src;
     469            0 :   return dst;
     470              : }
     471              : 
     472              : /* Generate a new label for the CFI info to refer to.  */
     473              : 
     474              : static char *
     475         5726 : dwarf2out_cfi_label (void)
     476              : {
     477         5726 :   int num = dwarf2out_cfi_label_num++;
     478         5726 :   char label[20];
     479              : 
     480         5726 :   ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", num);
     481              : 
     482         5726 :   return xstrdup (label);
     483              : }
     484              : 
     485              : /* Add CFI either to the current insn stream or to a vector, or both.  */
     486              : 
     487              : static void
     488     12313690 : add_cfi (dw_cfi_ref cfi)
     489              : {
     490     12313690 :   any_cfis_emitted = true;
     491              : 
     492     12313690 :   if (add_cfi_insn != NULL)
     493              :     {
     494     11895682 :       add_cfi_insn = emit_note_after (NOTE_INSN_CFI, add_cfi_insn);
     495     11895682 :       NOTE_CFI (add_cfi_insn) = cfi;
     496              :     }
     497              : 
     498     12313690 :   if (add_cfi_vec != NULL)
     499       418008 :     vec_safe_push (*add_cfi_vec, cfi);
     500     12313690 : }
     501              : 
     502              : static void
     503        93987 : add_cfi_args_size (poly_int64 size)
     504              : {
     505              :   /* We don't yet have a representation for polynomial sizes.  */
     506        93987 :   HOST_WIDE_INT const_size = size.to_constant ();
     507              : 
     508        93987 :   dw_cfi_ref cfi = new_cfi ();
     509              : 
     510              :   /* While we can occasionally have args_size < 0 internally, this state
     511              :      should not persist at a point we actually need an opcode.  */
     512        93987 :   gcc_assert (const_size >= 0);
     513              : 
     514        93987 :   cfi->dw_cfi_opc = DW_CFA_GNU_args_size;
     515        93987 :   cfi->dw_cfi_oprnd1.dw_cfi_offset = const_size;
     516              : 
     517        93987 :   add_cfi (cfi);
     518        93987 : }
     519              : 
     520              : static void
     521      1361539 : add_cfi_restore (unsigned reg)
     522              : {
     523      1361539 :   dw_cfi_ref cfi = new_cfi ();
     524              : 
     525      1361539 :   cfi->dw_cfi_opc = (reg & ~0x3f ? DW_CFA_restore_extended : DW_CFA_restore);
     526      1361539 :   cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
     527              : 
     528      1361539 :   add_cfi (cfi);
     529      1361539 : }
     530              : 
     531              : /* Perform ROW->REG_SAVE[COLUMN] = CFI.  CFI may be null, indicating
     532              :    that the register column is no longer saved.  */
     533              : 
     534              : static void
     535      3286385 : update_row_reg_save (dw_cfi_row *row, unsigned column, dw_cfi_ref cfi)
     536              : {
     537      3286385 :   if (vec_safe_length (row->reg_save) <= column)
     538       563235 :     vec_safe_grow_cleared (row->reg_save, column + 1, true);
     539      3286385 :   (*row->reg_save)[column] = cfi;
     540      3286385 : }
     541              : 
     542              : /* This function fills in aa dw_cfa_location structure from a dwarf location
     543              :    descriptor sequence.  */
     544              : 
     545              : static void
     546            0 : get_cfa_from_loc_descr (dw_cfa_location *cfa, struct dw_loc_descr_node *loc)
     547              : {
     548            0 :   struct dw_loc_descr_node *ptr;
     549            0 :   cfa->offset = 0;
     550            0 :   cfa->base_offset = 0;
     551            0 :   cfa->indirect = 0;
     552            0 :   cfa->reg.set_by_dwreg (INVALID_REGNUM);
     553              : 
     554            0 :   for (ptr = loc; ptr != NULL; ptr = ptr->dw_loc_next)
     555              :     {
     556            0 :       enum dwarf_location_atom op = ptr->dw_loc_opc;
     557              : 
     558            0 :       switch (op)
     559              :         {
     560            0 :         case DW_OP_reg0:
     561            0 :         case DW_OP_reg1:
     562            0 :         case DW_OP_reg2:
     563            0 :         case DW_OP_reg3:
     564            0 :         case DW_OP_reg4:
     565            0 :         case DW_OP_reg5:
     566            0 :         case DW_OP_reg6:
     567            0 :         case DW_OP_reg7:
     568            0 :         case DW_OP_reg8:
     569            0 :         case DW_OP_reg9:
     570            0 :         case DW_OP_reg10:
     571            0 :         case DW_OP_reg11:
     572            0 :         case DW_OP_reg12:
     573            0 :         case DW_OP_reg13:
     574            0 :         case DW_OP_reg14:
     575            0 :         case DW_OP_reg15:
     576            0 :         case DW_OP_reg16:
     577            0 :         case DW_OP_reg17:
     578            0 :         case DW_OP_reg18:
     579            0 :         case DW_OP_reg19:
     580            0 :         case DW_OP_reg20:
     581            0 :         case DW_OP_reg21:
     582            0 :         case DW_OP_reg22:
     583            0 :         case DW_OP_reg23:
     584            0 :         case DW_OP_reg24:
     585            0 :         case DW_OP_reg25:
     586            0 :         case DW_OP_reg26:
     587            0 :         case DW_OP_reg27:
     588            0 :         case DW_OP_reg28:
     589            0 :         case DW_OP_reg29:
     590            0 :         case DW_OP_reg30:
     591            0 :         case DW_OP_reg31:
     592            0 :           cfa->reg.set_by_dwreg (op - DW_OP_reg0);
     593            0 :           break;
     594            0 :         case DW_OP_regx:
     595            0 :           cfa->reg.set_by_dwreg (ptr->dw_loc_oprnd1.v.val_int);
     596            0 :           break;
     597            0 :         case DW_OP_breg0:
     598            0 :         case DW_OP_breg1:
     599            0 :         case DW_OP_breg2:
     600            0 :         case DW_OP_breg3:
     601            0 :         case DW_OP_breg4:
     602            0 :         case DW_OP_breg5:
     603            0 :         case DW_OP_breg6:
     604            0 :         case DW_OP_breg7:
     605            0 :         case DW_OP_breg8:
     606            0 :         case DW_OP_breg9:
     607            0 :         case DW_OP_breg10:
     608            0 :         case DW_OP_breg11:
     609            0 :         case DW_OP_breg12:
     610            0 :         case DW_OP_breg13:
     611            0 :         case DW_OP_breg14:
     612            0 :         case DW_OP_breg15:
     613            0 :         case DW_OP_breg16:
     614            0 :         case DW_OP_breg17:
     615            0 :         case DW_OP_breg18:
     616            0 :         case DW_OP_breg19:
     617            0 :         case DW_OP_breg20:
     618            0 :         case DW_OP_breg21:
     619            0 :         case DW_OP_breg22:
     620            0 :         case DW_OP_breg23:
     621            0 :         case DW_OP_breg24:
     622            0 :         case DW_OP_breg25:
     623            0 :         case DW_OP_breg26:
     624            0 :         case DW_OP_breg27:
     625            0 :         case DW_OP_breg28:
     626            0 :         case DW_OP_breg29:
     627            0 :         case DW_OP_breg30:
     628            0 :         case DW_OP_breg31:
     629            0 :         case DW_OP_bregx:
     630            0 :           if (cfa->reg.reg == INVALID_REGNUM)
     631              :             {
     632            0 :               unsigned regno
     633              :                 = (op == DW_OP_bregx
     634            0 :                    ? ptr->dw_loc_oprnd1.v.val_int : op - DW_OP_breg0);
     635            0 :               cfa->reg.set_by_dwreg (regno);
     636            0 :               cfa->base_offset = ptr->dw_loc_oprnd1.v.val_int;
     637              :             }
     638              :           else
     639              :             {
     640              :               /* Handle case when span can cover multiple registers.  We
     641              :                  only support the simple case of consecutive registers
     642              :                  all with the same size.  DWARF that we are dealing with
     643              :                  will look something like:
     644              :                  <DW_OP_bregx: (r49) 0; DW_OP_const1u: 32; DW_OP_shl;
     645              :                   DW_OP_bregx: (r48) 0; DW_OP_plus> */
     646              : 
     647            0 :               unsigned regno
     648              :                 = (op == DW_OP_bregx
     649            0 :                    ? ptr->dw_loc_oprnd1.v.val_int : op - DW_OP_breg0);
     650            0 :               gcc_assert (regno == cfa->reg.reg - 1);
     651            0 :               cfa->reg.span++;
     652              :               /* From all the consecutive registers used, we want to set
     653              :                  cfa->reg.reg to lower number register.  */
     654            0 :               cfa->reg.reg = regno;
     655              :               /* The offset was the shift value.  Use it to get the
     656              :                  span_width and then set it to 0.  */
     657            0 :               cfa->reg.span_width = cfa->offset.to_constant () / 8;
     658            0 :               cfa->offset = 0;
     659              :             }
     660              :           break;
     661            0 :         case DW_OP_deref:
     662            0 :           cfa->indirect = 1;
     663            0 :           break;
     664              :         case DW_OP_shl:
     665              :           break;
     666            0 :         case DW_OP_lit0:
     667            0 :         case DW_OP_lit1:
     668            0 :         case DW_OP_lit2:
     669            0 :         case DW_OP_lit3:
     670            0 :         case DW_OP_lit4:
     671            0 :         case DW_OP_lit5:
     672            0 :         case DW_OP_lit6:
     673            0 :         case DW_OP_lit7:
     674            0 :         case DW_OP_lit8:
     675            0 :         case DW_OP_lit9:
     676            0 :         case DW_OP_lit10:
     677            0 :         case DW_OP_lit11:
     678            0 :         case DW_OP_lit12:
     679            0 :         case DW_OP_lit13:
     680            0 :         case DW_OP_lit14:
     681            0 :         case DW_OP_lit15:
     682            0 :         case DW_OP_lit16:
     683            0 :         case DW_OP_lit17:
     684            0 :         case DW_OP_lit18:
     685            0 :         case DW_OP_lit19:
     686            0 :         case DW_OP_lit20:
     687            0 :         case DW_OP_lit21:
     688            0 :         case DW_OP_lit22:
     689            0 :         case DW_OP_lit23:
     690            0 :         case DW_OP_lit24:
     691            0 :         case DW_OP_lit25:
     692            0 :         case DW_OP_lit26:
     693            0 :         case DW_OP_lit27:
     694            0 :         case DW_OP_lit28:
     695            0 :         case DW_OP_lit29:
     696            0 :         case DW_OP_lit30:
     697            0 :         case DW_OP_lit31:
     698            0 :           gcc_assert (known_eq (cfa->offset, 0));
     699            0 :           cfa->offset = op - DW_OP_lit0;
     700            0 :           break;
     701            0 :         case DW_OP_const1u:
     702            0 :         case DW_OP_const1s:
     703            0 :         case DW_OP_const2u:
     704            0 :         case DW_OP_const2s:
     705            0 :         case DW_OP_const4s:
     706            0 :         case DW_OP_const8s:
     707            0 :         case DW_OP_constu:
     708            0 :         case DW_OP_consts:
     709            0 :           gcc_assert (known_eq (cfa->offset, 0));
     710            0 :           cfa->offset = ptr->dw_loc_oprnd1.v.val_int;
     711            0 :           break;
     712            0 :         case DW_OP_minus:
     713            0 :           cfa->offset = -cfa->offset;
     714            0 :           break;
     715              :         case DW_OP_plus:
     716              :           /* The offset is already in place.  */
     717              :           break;
     718            0 :         case DW_OP_plus_uconst:
     719            0 :           cfa->offset = ptr->dw_loc_oprnd1.v.val_unsigned;
     720            0 :           break;
     721            0 :         default:
     722            0 :           gcc_unreachable ();
     723              :         }
     724              :     }
     725            0 : }
     726              : 
     727              : /* Find the previous value for the CFA, iteratively.  CFI is the opcode
     728              :    to interpret, *LOC will be updated as necessary, *REMEMBER is used for
     729              :    one level of remember/restore state processing.  */
     730              : 
     731              : void
     732        17054 : lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc, dw_cfa_location *remember)
     733              : {
     734        17054 :   switch (cfi->dw_cfi_opc)
     735              :     {
     736         3224 :     case DW_CFA_def_cfa_offset:
     737         3224 :     case DW_CFA_def_cfa_offset_sf:
     738         3224 :       loc->offset = cfi->dw_cfi_oprnd1.dw_cfi_offset;
     739         3224 :       break;
     740         2022 :     case DW_CFA_def_cfa_register:
     741         2022 :       loc->reg.set_by_dwreg (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
     742         2022 :       break;
     743         5402 :     case DW_CFA_def_cfa:
     744         5402 :     case DW_CFA_def_cfa_sf:
     745         5402 :       loc->reg.set_by_dwreg (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
     746         5402 :       loc->offset = cfi->dw_cfi_oprnd2.dw_cfi_offset;
     747         5402 :       break;
     748            0 :     case DW_CFA_def_cfa_expression:
     749            0 :       if (cfi->dw_cfi_oprnd2.dw_cfi_cfa_loc)
     750            0 :         *loc = *cfi->dw_cfi_oprnd2.dw_cfi_cfa_loc;
     751              :       else
     752            0 :         get_cfa_from_loc_descr (loc, cfi->dw_cfi_oprnd1.dw_cfi_loc);
     753              :       break;
     754              : 
     755          124 :     case DW_CFA_remember_state:
     756          124 :       gcc_assert (!remember->in_use);
     757          124 :       *remember = *loc;
     758          124 :       remember->in_use = 1;
     759          124 :       break;
     760          124 :     case DW_CFA_restore_state:
     761          124 :       gcc_assert (remember->in_use);
     762          124 :       *loc = *remember;
     763          124 :       remember->in_use = 0;
     764          124 :       break;
     765              : 
     766              :     default:
     767              :       break;
     768              :     }
     769        17054 : }
     770              : 
     771              : /* Determine if two dw_cfa_location structures define the same data.  */
     772              : 
     773              : bool
     774    120286795 : cfa_equal_p (const dw_cfa_location *loc1, const dw_cfa_location *loc2)
     775              : {
     776    120286795 :   return (loc1->reg == loc2->reg
     777    119056907 :           && known_eq (loc1->offset, loc2->offset)
     778    112203389 :           && loc1->indirect == loc2->indirect
     779    232490184 :           && (loc1->indirect == 0
     780       994817 :               || known_eq (loc1->base_offset, loc2->base_offset)));
     781              : }
     782              : 
     783              : /* Determine if two CFI operands are identical.  */
     784              : 
     785              : static bool
     786       295416 : cfi_oprnd_equal_p (enum dw_cfi_oprnd_type t, dw_cfi_oprnd *a, dw_cfi_oprnd *b)
     787              : {
     788       295416 :   switch (t)
     789              :     {
     790              :     case dw_cfi_oprnd_unused:
     791              :       return true;
     792       147696 :     case dw_cfi_oprnd_reg_num:
     793       147696 :       return a->dw_cfi_reg_num == b->dw_cfi_reg_num;
     794       147684 :     case dw_cfi_oprnd_offset:
     795       147684 :       return a->dw_cfi_offset == b->dw_cfi_offset;
     796            0 :     case dw_cfi_oprnd_addr:
     797            0 :       return (a->dw_cfi_addr == b->dw_cfi_addr
     798            0 :               || strcmp (a->dw_cfi_addr, b->dw_cfi_addr) == 0);
     799           24 :     case dw_cfi_oprnd_loc:
     800           24 :       return loc_descr_equal_p (a->dw_cfi_loc, b->dw_cfi_loc);
     801           12 :     case dw_cfi_oprnd_cfa_loc:
     802              :       /* If any of them is NULL, don't dereference either.  */
     803           12 :       if (!a->dw_cfi_cfa_loc || !b->dw_cfi_cfa_loc)
     804           12 :         return a->dw_cfi_cfa_loc == b->dw_cfi_cfa_loc;
     805            0 :       return cfa_equal_p (a->dw_cfi_cfa_loc, b->dw_cfi_cfa_loc);
     806              :     }
     807            0 :   gcc_unreachable ();
     808              : }
     809              : 
     810              : /* Determine if two CFI entries are identical.  */
     811              : 
     812              : static bool
     813    258719932 : cfi_equal_p (dw_cfi_ref a, dw_cfi_ref b)
     814              : {
     815              :   /* Make things easier for our callers, including missing operands.  */
     816    258719932 :   if (a == b)
     817              :     return true;
     818       709352 :   if (a == NULL || b == NULL)
     819              :     return false;
     820              : 
     821              :   /* Obviously, the opcodes must match.  */
     822       147708 :   dwarf_call_frame_info opc = a->dw_cfi_opc;
     823       147708 :   if (opc != b->dw_cfi_opc)
     824              :     return false;
     825              : 
     826              :   /* Compare the two operands, re-using the type of the operands as
     827              :      already exposed elsewhere.  */
     828       147708 :   return (cfi_oprnd_equal_p (dw_cfi_oprnd1_desc (opc),
     829              :                              &a->dw_cfi_oprnd1, &b->dw_cfi_oprnd1)
     830       147708 :           && cfi_oprnd_equal_p (dw_cfi_oprnd2_desc (opc),
     831              :                                 &a->dw_cfi_oprnd2, &b->dw_cfi_oprnd2));
     832              : }
     833              : 
     834              : /* Determine if two CFI_ROW structures are identical.  */
     835              : 
     836              : static bool
     837     16863164 : cfi_row_equal_p (dw_cfi_row *a, dw_cfi_row *b)
     838              : {
     839     16863164 :   size_t i, n_a, n_b, n_max;
     840              : 
     841     16863164 :   if (a->cfa_cfi)
     842              :     {
     843       102746 :       if (!cfi_equal_p (a->cfa_cfi, b->cfa_cfi))
     844              :         return false;
     845              :     }
     846     16760418 :   else if (!cfa_equal_p (&a->cfa, &b->cfa))
     847              :     return false;
     848              : 
     849     16164746 :   n_a = vec_safe_length (a->reg_save);
     850     16164746 :   n_b = vec_safe_length (b->reg_save);
     851     16164746 :   n_max = MAX (n_a, n_b);
     852              : 
     853    274122609 :   for (i = 0; i < n_max; ++i)
     854              :     {
     855    258171979 :       dw_cfi_ref r_a = NULL, r_b = NULL;
     856              : 
     857    258171979 :       if (i < n_a)
     858    258171979 :         r_a = (*a->reg_save)[i];
     859    258171979 :       if (i < n_b)
     860    258144466 :         r_b = (*b->reg_save)[i];
     861              : 
     862    258171979 :       if (!cfi_equal_p (r_a, r_b))
     863              :         return false;
     864              :     }
     865              : 
     866     15950630 :   if (a->window_save != b->window_save)
     867              :     return false;
     868              : 
     869     15950630 :   if (a->ra_state != b->ra_state)
     870              :     return false;
     871              : 
     872              :   return true;
     873              : }
     874              : 
     875              : /* The CFA is now calculated from NEW_CFA.  Consider OLD_CFA in determining
     876              :    what opcode to emit.  Returns the CFI opcode to effect the change, or
     877              :    NULL if NEW_CFA == OLD_CFA.  */
     878              : 
     879              : static dw_cfi_ref
     880    103517240 : def_cfa_0 (dw_cfa_location *old_cfa, dw_cfa_location *new_cfa)
     881              : {
     882    103517240 :   dw_cfi_ref cfi;
     883              : 
     884              :   /* If nothing changed, no need to issue any call frame instructions.  */
     885    103517240 :   if (cfa_equal_p (old_cfa, new_cfa))
     886              :     return NULL;
     887              : 
     888      7379368 :   cfi = new_cfi ();
     889              : 
     890      7379368 :   HOST_WIDE_INT const_offset;
     891      7379368 :   if (new_cfa->reg == old_cfa->reg
     892      6200444 :       && new_cfa->reg.span == 1
     893      6200444 :       && !new_cfa->indirect
     894      6200444 :       && !old_cfa->indirect
     895     13579812 :       && new_cfa->offset.is_constant (&const_offset))
     896              :     {
     897              :       /* Construct a "DW_CFA_def_cfa_offset <offset>" instruction, indicating
     898              :          the CFA register did not change but the offset did.  The data
     899              :          factoring for DW_CFA_def_cfa_offset_sf happens in output_cfi, or
     900              :          in the assembler via the .cfi_def_cfa_offset directive.  */
     901      6200444 :       if (const_offset < 0)
     902            1 :         cfi->dw_cfi_opc = DW_CFA_def_cfa_offset_sf;
     903              :       else
     904      6200443 :         cfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
     905      6200444 :       cfi->dw_cfi_oprnd1.dw_cfi_offset = const_offset;
     906              :     }
     907      1178924 :   else if (new_cfa->offset.is_constant ()
     908      1178924 :            && known_eq (new_cfa->offset, old_cfa->offset)
     909       478030 :            && old_cfa->reg.reg != INVALID_REGNUM
     910       478030 :            && new_cfa->reg.span == 1
     911       478030 :            && !new_cfa->indirect
     912       470963 :            && !old_cfa->indirect)
     913              :     {
     914              :       /* Construct a "DW_CFA_def_cfa_register <register>" instruction,
     915              :          indicating the CFA register has changed to <register> but the
     916              :          offset has not changed.  This requires the old CFA to have
     917              :          been set as a register plus offset rather than a general
     918              :          DW_CFA_def_cfa_expression.  */
     919       463909 :       cfi->dw_cfi_opc = DW_CFA_def_cfa_register;
     920       463909 :       cfi->dw_cfi_oprnd1.dw_cfi_reg_num = new_cfa->reg.reg;
     921              :     }
     922       715015 :   else if (new_cfa->indirect == 0
     923       707948 :            && new_cfa->offset.is_constant (&const_offset)
     924       715015 :            && new_cfa->reg.span == 1)
     925              :     {
     926              :       /* Construct a "DW_CFA_def_cfa <register> <offset>" instruction,
     927              :          indicating the CFA register has changed to <register> with
     928              :          the specified offset.  The data factoring for DW_CFA_def_cfa_sf
     929              :          happens in output_cfi, or in the assembler via the .cfi_def_cfa
     930              :          directive.  */
     931       707948 :       if (const_offset < 0)
     932            0 :         cfi->dw_cfi_opc = DW_CFA_def_cfa_sf;
     933              :       else
     934       707948 :         cfi->dw_cfi_opc = DW_CFA_def_cfa;
     935       707948 :       cfi->dw_cfi_oprnd1.dw_cfi_reg_num = new_cfa->reg.reg;
     936       707948 :       cfi->dw_cfi_oprnd2.dw_cfi_offset = const_offset;
     937              :     }
     938              :   else
     939              :     {
     940              :       /* Construct a DW_CFA_def_cfa_expression instruction to
     941              :          calculate the CFA using a full location expression since no
     942              :          register-offset pair is available.  */
     943         7067 :       struct dw_loc_descr_node *loc_list;
     944              : 
     945         7067 :       cfi->dw_cfi_opc = DW_CFA_def_cfa_expression;
     946         7067 :       loc_list = build_cfa_loc (new_cfa, 0);
     947         7067 :       cfi->dw_cfi_oprnd1.dw_cfi_loc = loc_list;
     948         7067 :       if (!new_cfa->offset.is_constant ()
     949              :           || !new_cfa->base_offset.is_constant ())
     950              :         /* It's hard to reconstruct the CFA location for a polynomial
     951              :            expression, so just cache it instead.  */
     952              :         cfi->dw_cfi_oprnd2.dw_cfi_cfa_loc = copy_cfa (new_cfa);
     953              :       else
     954         7067 :         cfi->dw_cfi_oprnd2.dw_cfi_cfa_loc = NULL;
     955              :     }
     956              : 
     957              :   return cfi;
     958              : }
     959              : 
     960              : /* Similarly, but take OLD_CFA from CUR_ROW, and update it after the fact.  */
     961              : 
     962              : static void
     963     93594556 : def_cfa_1 (dw_cfa_location *new_cfa)
     964              : {
     965     93594556 :   dw_cfi_ref cfi;
     966              : 
     967     93594556 :   if (cur_trace->cfa_store.reg == new_cfa->reg && new_cfa->indirect == 0)
     968     59352991 :     cur_trace->cfa_store.offset = new_cfa->offset;
     969              : 
     970     93594556 :   cfi = def_cfa_0 (&cur_row->cfa, new_cfa);
     971     93594556 :   if (cfi)
     972              :     {
     973      7167333 :       cur_row->cfa = *new_cfa;
     974     14334666 :       cur_row->cfa_cfi = (cfi->dw_cfi_opc == DW_CFA_def_cfa_expression
     975      7167333 :                           ? cfi : NULL);
     976              : 
     977      7167333 :       add_cfi (cfi);
     978              :     }
     979     93594556 : }
     980              : 
     981              : /* Add the CFI for saving a register.  REG is the CFA column number.
     982              :    If SREG is INVALID_REGISTER, the register is saved at OFFSET from the CFA;
     983              :    otherwise it is saved in SREG.  */
     984              : 
     985              : static void
     986      2256071 : reg_save (unsigned int reg, struct cfa_reg sreg, poly_int64 offset)
     987              : {
     988      2256071 :   dw_fde_ref fde = cfun ? cfun->fde : NULL;
     989      2256071 :   dw_cfi_ref cfi = new_cfi ();
     990              : 
     991      2256071 :   cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
     992              : 
     993      2256071 :   if (sreg.reg == INVALID_REGNUM)
     994              :     {
     995      2256054 :       HOST_WIDE_INT const_offset;
     996              :       /* When stack is aligned, store REG using DW_CFA_expression with FP.  */
     997      2256054 :       if (fde && fde->stack_realign)
     998              :         {
     999        17955 :           cfi->dw_cfi_opc = DW_CFA_expression;
    1000        17955 :           cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
    1001        17955 :           cfi->dw_cfi_oprnd2.dw_cfi_loc
    1002        17955 :             = build_cfa_aligned_loc (&cur_row->cfa, offset,
    1003              :                                      fde->stack_realignment);
    1004              :         }
    1005      2238099 :       else if (offset.is_constant (&const_offset))
    1006              :         {
    1007      2238099 :           if (need_data_align_sf_opcode (const_offset))
    1008            0 :             cfi->dw_cfi_opc = DW_CFA_offset_extended_sf;
    1009      2238099 :           else if (reg & ~0x3f)
    1010           80 :             cfi->dw_cfi_opc = DW_CFA_offset_extended;
    1011              :           else
    1012      2238019 :             cfi->dw_cfi_opc = DW_CFA_offset;
    1013      2238099 :           cfi->dw_cfi_oprnd2.dw_cfi_offset = const_offset;
    1014              :         }
    1015              :       else
    1016              :         {
    1017              :           cfi->dw_cfi_opc = DW_CFA_expression;
    1018              :           cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
    1019              :           cfi->dw_cfi_oprnd2.dw_cfi_loc
    1020              :             = build_cfa_loc (&cur_row->cfa, offset);
    1021              :         }
    1022              :     }
    1023           17 :   else if (sreg.reg == reg)
    1024              :     {
    1025              :       /* While we could emit something like DW_CFA_same_value or
    1026              :          DW_CFA_restore, we never expect to see something like that
    1027              :          in a prologue.  This is more likely to be a bug.  A backend
    1028              :          can always bypass this by using REG_CFA_RESTORE directly.  */
    1029            0 :       gcc_unreachable ();
    1030              :     }
    1031           17 :   else if (sreg.span > 1)
    1032              :     {
    1033            0 :       cfi->dw_cfi_opc = DW_CFA_expression;
    1034            0 :       cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
    1035            0 :       cfi->dw_cfi_oprnd2.dw_cfi_loc = build_span_loc (sreg);
    1036              :     }
    1037              :   else
    1038              :     {
    1039           17 :       cfi->dw_cfi_opc = DW_CFA_register;
    1040           17 :       cfi->dw_cfi_oprnd2.dw_cfi_reg_num = sreg.reg;
    1041              :     }
    1042              : 
    1043      2256071 :   add_cfi (cfi);
    1044      2256071 :   update_row_reg_save (cur_row, reg, cfi);
    1045      2256071 : }
    1046              : 
    1047              : /* A subroutine of scan_trace.  Check INSN for a REG_ARGS_SIZE note
    1048              :    and adjust data structures to match.  */
    1049              : 
    1050              : static void
    1051     93385488 : notice_args_size (rtx_insn *insn)
    1052              : {
    1053     93385488 :   poly_int64 args_size, delta;
    1054     93385488 :   rtx note;
    1055              : 
    1056     93385488 :   note = find_reg_note (insn, REG_ARGS_SIZE, NULL);
    1057     93385488 :   if (note == NULL)
    1058     89455460 :     return;
    1059              : 
    1060      4742392 :   if (!cur_trace->eh_head)
    1061      4439907 :     cur_trace->args_size_defined_for_eh = true;
    1062              : 
    1063      4742392 :   args_size = get_args_size (note);
    1064      4742392 :   delta = args_size - cur_trace->end_true_args_size;
    1065      4742392 :   if (known_eq (delta, 0))
    1066              :     return;
    1067              : 
    1068      3930028 :   cur_trace->end_true_args_size = args_size;
    1069              : 
    1070              :   /* If the CFA is computed off the stack pointer, then we must adjust
    1071              :      the computation of the CFA as well.  */
    1072      3930028 :   if (cur_cfa->reg == dw_stack_pointer_regnum)
    1073              :     {
    1074      2794047 :       gcc_assert (!cur_cfa->indirect);
    1075              : 
    1076              :       /* Convert a change in args_size (always a positive in the
    1077              :          direction of stack growth) to a change in stack pointer.  */
    1078      2794047 :       if (!STACK_GROWS_DOWNWARD)
    1079              :         delta = -delta;
    1080              : 
    1081      3930028 :       cur_cfa->offset += delta;
    1082              :     }
    1083              : }
    1084              : 
    1085              : /* A subroutine of scan_trace.  INSN is can_throw_internal.  Update the
    1086              :    data within the trace related to EH insns and args_size.  */
    1087              : 
    1088              : static void
    1089       638141 : notice_eh_throw (rtx_insn *insn)
    1090              : {
    1091       638141 :   poly_int64 args_size = cur_trace->end_true_args_size;
    1092       638141 :   if (cur_trace->eh_head == NULL)
    1093              :     {
    1094       372480 :       cur_trace->eh_head = insn;
    1095       372480 :       cur_trace->beg_delay_args_size = args_size;
    1096       372480 :       cur_trace->end_delay_args_size = args_size;
    1097              :     }
    1098       265661 :   else if (maybe_ne (cur_trace->end_delay_args_size, args_size))
    1099              :     {
    1100        46374 :       cur_trace->end_delay_args_size = args_size;
    1101              : 
    1102              :       /* ??? If the CFA is the stack pointer, search backward for the last
    1103              :          CFI note and insert there.  Given that the stack changed for the
    1104              :          args_size change, there *must* be such a note in between here and
    1105              :          the last eh insn.  */
    1106        46374 :       add_cfi_args_size (args_size);
    1107              :     }
    1108       638141 : }
    1109              : 
    1110              : /* Short-hand inline for the very common D_F_R (REGNO (x)) operation.  */
    1111              : /* ??? This ought to go into dwarf2out.h, except that dwarf2out.h is
    1112              :    used in places where rtl is prohibited.  */
    1113              : 
    1114              : static inline unsigned
    1115     14960199 : dwf_regno (const_rtx reg)
    1116              : {
    1117     14960199 :   gcc_assert (REGNO (reg) < FIRST_PSEUDO_REGISTER);
    1118     14960199 :   return DWARF_FRAME_REGNUM (REGNO (reg));
    1119              : }
    1120              : 
    1121              : /* Like dwf_regno, but when the value can span multiple registers.  */
    1122              : 
    1123              : static struct cfa_reg
    1124      7892748 : dwf_cfa_reg (rtx reg)
    1125              : {
    1126      7892748 :   struct cfa_reg result;
    1127              : 
    1128      7892748 :   result.reg = dwf_regno (reg);
    1129      7892748 :   result.span = 1;
    1130      7892748 :   result.span_width = 0;
    1131              : 
    1132      7892748 :   rtx span = targetm.dwarf_register_span (reg);
    1133      7892748 :   if (span)
    1134              :     {
    1135              :       /* We only support the simple case of consecutive registers all with the
    1136              :          same size.  */
    1137            0 :       result.span = XVECLEN (span, 0);
    1138            0 :       result.span_width = GET_MODE_SIZE (GET_MODE (XVECEXP (span, 0, 0)))
    1139            0 :                           .to_constant ();
    1140              : 
    1141            0 :       if (CHECKING_P)
    1142              :         {
    1143              :           /* Ensure that the above assumption is accurate.  */
    1144            0 :           for (unsigned int i = 0; i < result.span; i++)
    1145              :             {
    1146            0 :               gcc_assert (GET_MODE_SIZE (GET_MODE (XVECEXP (span, 0, i)))
    1147              :                           .to_constant ()  == result.span_width);
    1148            0 :               gcc_assert (REG_P (XVECEXP (span, 0, i)));
    1149            0 :               gcc_assert (dwf_regno (XVECEXP (span, 0, i)) == result.reg + i);
    1150              :             }
    1151              :         }
    1152              :     }
    1153              : 
    1154      7892748 :   return result;
    1155              : }
    1156              : 
    1157              : /* More efficient comparisons that don't call targetm.dwarf_register_span
    1158              :    unnecessarily.  These cfa_reg vs. rtx comparisons should be done at
    1159              :    least for call-saved REGs that might not be CFA related (like stack
    1160              :    pointer, hard frame pointer or DRAP registers are), in other cases it is
    1161              :    just a compile time and memory optimization.  */
    1162              : 
    1163              : static bool
    1164      3989813 : operator== (cfa_reg &cfa, rtx reg)
    1165              : {
    1166      3989813 :   unsigned int regno = dwf_regno (reg);
    1167      3989813 :   if (cfa.reg != regno)
    1168              :     return false;
    1169      2631285 :   struct cfa_reg other = dwf_cfa_reg (reg);
    1170      2631285 :   return cfa == other;
    1171              : }
    1172              : 
    1173              : static inline bool
    1174         7067 : operator!= (cfa_reg &cfa, rtx reg)
    1175              : {
    1176         7067 :   return !(cfa == reg);
    1177              : }
    1178              : 
    1179              : /* Compare X and Y for equivalence.  The inputs may be REGs or PC_RTX.  */
    1180              : 
    1181              : static bool
    1182      1320847 : compare_reg_or_pc (rtx x, rtx y)
    1183              : {
    1184      1320847 :   if (REG_P (x) && REG_P (y))
    1185      1320847 :     return REGNO (x) == REGNO (y);
    1186            0 :   return x == y;
    1187              : }
    1188              : 
    1189              : /* Record SRC as being saved in DEST.  DEST may be null to delete an
    1190              :    existing entry.  SRC may be a register or PC_RTX.  */
    1191              : 
    1192              : static void
    1193      2001989 : record_reg_saved_in_reg (rtx dest, rtx src)
    1194              : {
    1195      2001989 :   reg_saved_in_data *elt;
    1196      2001989 :   size_t i;
    1197              : 
    1198      2001989 :   FOR_EACH_VEC_ELT (cur_trace->regs_saved_in_regs, i, elt)
    1199            0 :     if (compare_reg_or_pc (elt->orig_reg, src))
    1200              :       {
    1201            0 :         if (dest == NULL)
    1202            0 :           cur_trace->regs_saved_in_regs.unordered_remove (i);
    1203              :         else
    1204            0 :           elt->saved_in_reg = dest;
    1205      2001972 :         return;
    1206              :       }
    1207              : 
    1208      2001989 :   if (dest == NULL)
    1209              :     return;
    1210              : 
    1211           17 :   reg_saved_in_data e = {src, dest};
    1212           17 :   cur_trace->regs_saved_in_regs.safe_push (e);
    1213              : }
    1214              : 
    1215              : /* Add an entry to QUEUED_REG_SAVES saying that REG is now saved at
    1216              :    SREG, or if SREG is NULL then it is saved at OFFSET to the CFA.  */
    1217              : 
    1218              : static void
    1219      2002039 : queue_reg_save (rtx reg, rtx sreg, poly_int64 offset)
    1220              : {
    1221      2002039 :   queued_reg_save *q;
    1222      2002039 :   queued_reg_save e = {reg, sreg, offset};
    1223      2002039 :   size_t i;
    1224              : 
    1225              :   /* Duplicates waste space, but it's also necessary to remove them
    1226              :      for correctness, since the queue gets output in reverse order.  */
    1227      3322886 :   FOR_EACH_VEC_ELT (queued_reg_saves, i, q)
    1228      2641694 :     if (compare_reg_or_pc (q->reg, reg))
    1229              :       {
    1230            0 :         *q = e;
    1231            0 :         return;
    1232              :       }
    1233              : 
    1234      2002039 :   queued_reg_saves.safe_push (e);
    1235              : }
    1236              : 
    1237              : /* Output all the entries in QUEUED_REG_SAVES.  */
    1238              : 
    1239              : static void
    1240     30783677 : dwarf2out_flush_queued_reg_saves (void)
    1241              : {
    1242     30783677 :   queued_reg_save *q;
    1243     30783677 :   size_t i;
    1244              : 
    1245     32785649 :   FOR_EACH_VEC_ELT (queued_reg_saves, i, q)
    1246              :     {
    1247      2001972 :       unsigned int reg;
    1248      2001972 :       struct cfa_reg sreg;
    1249              : 
    1250      2001972 :       record_reg_saved_in_reg (q->saved_reg, q->reg);
    1251              : 
    1252      2001972 :       if (q->reg == pc_rtx)
    1253            0 :         reg = DWARF_FRAME_RETURN_COLUMN;
    1254              :       else
    1255      2001972 :         reg = dwf_regno (q->reg);
    1256      2001972 :       if (q->saved_reg)
    1257            0 :         sreg = dwf_cfa_reg (q->saved_reg);
    1258              :       else
    1259      2001972 :         sreg.set_by_dwreg (INVALID_REGNUM);
    1260      2001972 :       reg_save (reg, sreg, q->cfa_offset);
    1261              :     }
    1262              : 
    1263     30783677 :   queued_reg_saves.truncate (0);
    1264     30783677 : }
    1265              : 
    1266              : /* Does INSN clobber any register which QUEUED_REG_SAVES lists a saved
    1267              :    location for?  Or, does it clobber a register which we've previously
    1268              :    said that some other register is saved in, and for which we now
    1269              :    have a new location for?  */
    1270              : 
    1271              : static bool
    1272     79626371 : clobbers_queued_reg_save (const_rtx insn)
    1273              : {
    1274     79626371 :   queued_reg_save *q;
    1275     79626371 :   size_t iq;
    1276              : 
    1277     85091269 :   FOR_EACH_VEC_ELT (queued_reg_saves, iq, q)
    1278              :     {
    1279      5598361 :       size_t ir;
    1280      5598361 :       reg_saved_in_data *rir;
    1281              : 
    1282      5598361 :       if (modified_in_p (q->reg, insn))
    1283     79626371 :         return true;
    1284              : 
    1285      5464898 :       FOR_EACH_VEC_ELT (cur_trace->regs_saved_in_regs, ir, rir)
    1286            0 :         if (compare_reg_or_pc (q->reg, rir->orig_reg)
    1287            0 :             && modified_in_p (rir->saved_in_reg, insn))
    1288              :           return true;
    1289              :     }
    1290              : 
    1291              :   return false;
    1292              : }
    1293              : 
    1294              : /* What register, if any, is currently saved in REG?  */
    1295              : 
    1296              : static rtx
    1297      2480032 : reg_saved_in (rtx reg)
    1298              : {
    1299      2480032 :   unsigned int regn = REGNO (reg);
    1300      2480032 :   queued_reg_save *q;
    1301      2480032 :   reg_saved_in_data *rir;
    1302      2480032 :   size_t i;
    1303              : 
    1304      3806835 :   FOR_EACH_VEC_ELT (queued_reg_saves, i, q)
    1305      1326803 :     if (q->saved_reg && regn == REGNO (q->saved_reg))
    1306            0 :       return q->reg;
    1307              : 
    1308      2480032 :   FOR_EACH_VEC_ELT (cur_trace->regs_saved_in_regs, i, rir)
    1309            0 :     if (regn == REGNO (rir->saved_in_reg))
    1310            0 :       return rir->orig_reg;
    1311              : 
    1312              :   return NULL_RTX;
    1313              : }
    1314              : 
    1315              : /* A subroutine of dwarf2out_frame_debug, process a REG_DEF_CFA note.  */
    1316              : 
    1317              : static void
    1318       474292 : dwarf2out_frame_debug_def_cfa (rtx pat)
    1319              : {
    1320       474292 :   memset (cur_cfa, 0, sizeof (*cur_cfa));
    1321              : 
    1322       474292 :   pat = strip_offset (pat, &cur_cfa->offset);
    1323       474292 :   if (MEM_P (pat))
    1324              :     {
    1325            0 :       cur_cfa->indirect = 1;
    1326            0 :       pat = strip_offset (XEXP (pat, 0), &cur_cfa->base_offset);
    1327              :     }
    1328              :   /* ??? If this fails, we could be calling into the _loc functions to
    1329              :      define a full expression.  So far no port does that.  */
    1330       474292 :   gcc_assert (REG_P (pat));
    1331       474292 :   cur_cfa->reg = dwf_cfa_reg (pat);
    1332       474292 : }
    1333              : 
    1334              : /* A subroutine of dwarf2out_frame_debug, process a REG_ADJUST_CFA note.  */
    1335              : 
    1336              : static void
    1337      2101251 : dwarf2out_frame_debug_adjust_cfa (rtx pat)
    1338              : {
    1339      2101251 :   rtx src, dest;
    1340              : 
    1341      2101251 :   gcc_assert (GET_CODE (pat) == SET);
    1342      2101251 :   dest = XEXP (pat, 0);
    1343      2101251 :   src = XEXP (pat, 1);
    1344              : 
    1345      2101251 :   switch (GET_CODE (src))
    1346              :     {
    1347      2101147 :     case PLUS:
    1348      2101147 :       gcc_assert (cur_cfa->reg == XEXP (src, 0));
    1349      2101147 :       cur_cfa->offset -= rtx_to_poly_int64 (XEXP (src, 1));
    1350      2101147 :       break;
    1351              : 
    1352              :     case REG:
    1353              :       break;
    1354              : 
    1355            0 :     default:
    1356            0 :       gcc_unreachable ();
    1357              :     }
    1358              : 
    1359      2101251 :   cur_cfa->reg = dwf_cfa_reg (dest);
    1360      2101251 :   gcc_assert (cur_cfa->indirect == 0);
    1361      2101251 : }
    1362              : 
    1363              : /* A subroutine of dwarf2out_frame_debug, process a REG_CFA_OFFSET note.  */
    1364              : 
    1365              : static void
    1366        45078 : dwarf2out_frame_debug_cfa_offset (rtx set)
    1367              : {
    1368        45078 :   poly_int64 offset;
    1369        45078 :   rtx src, addr, span;
    1370        45078 :   unsigned int sregno;
    1371              : 
    1372        45078 :   src = XEXP (set, 1);
    1373        45078 :   addr = XEXP (set, 0);
    1374        45078 :   gcc_assert (MEM_P (addr));
    1375        45078 :   addr = XEXP (addr, 0);
    1376              : 
    1377              :   /* As documented, only consider extremely simple addresses.  */
    1378        45078 :   switch (GET_CODE (addr))
    1379              :     {
    1380            0 :     case REG:
    1381            0 :       gcc_assert (cur_cfa->reg == addr);
    1382            0 :       offset = -cur_cfa->offset;
    1383            0 :       break;
    1384        45078 :     case PLUS:
    1385        45078 :       gcc_assert (cur_cfa->reg == XEXP (addr, 0));
    1386        45078 :       offset = rtx_to_poly_int64 (XEXP (addr, 1)) - cur_cfa->offset;
    1387        45078 :       break;
    1388            0 :     default:
    1389            0 :       gcc_unreachable ();
    1390              :     }
    1391              : 
    1392        45078 :   if (src == pc_rtx)
    1393              :     {
    1394            0 :       span = NULL;
    1395            0 :       sregno = DWARF_FRAME_RETURN_COLUMN;
    1396              :     }
    1397              :   else
    1398              :     {
    1399        45078 :       span = targetm.dwarf_register_span (src);
    1400        45078 :       sregno = dwf_regno (src);
    1401              :     }
    1402              : 
    1403              :   /* ??? We'd like to use queue_reg_save, but we need to come up with
    1404              :      a different flushing heuristic for epilogues.  */
    1405        45078 :   struct cfa_reg invalid;
    1406        45078 :   invalid.set_by_dwreg (INVALID_REGNUM);
    1407        45078 :   if (!span)
    1408        45078 :     reg_save (sregno, invalid, offset);
    1409              :   else
    1410              :     {
    1411              :       /* We have a PARALLEL describing where the contents of SRC live.
    1412              :          Adjust the offset for each piece of the PARALLEL.  */
    1413            0 :       poly_int64 span_offset = offset;
    1414              : 
    1415            0 :       gcc_assert (GET_CODE (span) == PARALLEL);
    1416              : 
    1417            0 :       const int par_len = XVECLEN (span, 0);
    1418            0 :       for (int par_index = 0; par_index < par_len; par_index++)
    1419              :         {
    1420            0 :           rtx elem = XVECEXP (span, 0, par_index);
    1421            0 :           sregno = dwf_regno (src);
    1422            0 :           reg_save (sregno, invalid, span_offset);
    1423            0 :           span_offset += GET_MODE_SIZE (GET_MODE (elem));
    1424              :         }
    1425              :     }
    1426        45078 : }
    1427              : 
    1428              : /* A subroutine of dwarf2out_frame_debug, process a REG_CFA_REGISTER note.  */
    1429              : 
    1430              : static void
    1431           17 : dwarf2out_frame_debug_cfa_register (rtx set)
    1432              : {
    1433           17 :   rtx src, dest;
    1434           17 :   unsigned sregno;
    1435           17 :   struct cfa_reg dregno;
    1436              : 
    1437           17 :   src = XEXP (set, 1);
    1438           17 :   dest = XEXP (set, 0);
    1439              : 
    1440           17 :   record_reg_saved_in_reg (dest, src);
    1441           17 :   if (src == pc_rtx)
    1442           17 :     sregno = DWARF_FRAME_RETURN_COLUMN;
    1443              :   else
    1444            0 :     sregno = dwf_regno (src);
    1445              : 
    1446           17 :   dregno = dwf_cfa_reg (dest);
    1447              : 
    1448              :   /* ??? We'd like to use queue_reg_save, but we need to come up with
    1449              :      a different flushing heuristic for epilogues.  */
    1450           17 :   reg_save (sregno, dregno, 0);
    1451           17 : }
    1452              : 
    1453              : /* A subroutine of dwarf2out_frame_debug, process a REG_CFA_EXPRESSION note.  */
    1454              : 
    1455              : static void
    1456        25681 : dwarf2out_frame_debug_cfa_expression (rtx set)
    1457              : {
    1458        25681 :   rtx src, dest, span;
    1459        25681 :   dw_cfi_ref cfi = new_cfi ();
    1460        25681 :   unsigned regno;
    1461              : 
    1462        25681 :   dest = SET_DEST (set);
    1463        25681 :   src = SET_SRC (set);
    1464              : 
    1465        25681 :   gcc_assert (REG_P (src));
    1466        25681 :   gcc_assert (MEM_P (dest));
    1467              : 
    1468        25681 :   span = targetm.dwarf_register_span (src);
    1469        25681 :   gcc_assert (!span);
    1470              : 
    1471        25681 :   regno = dwf_regno (src);
    1472              : 
    1473        25681 :   cfi->dw_cfi_opc = DW_CFA_expression;
    1474        25681 :   cfi->dw_cfi_oprnd1.dw_cfi_reg_num = regno;
    1475        25681 :   cfi->dw_cfi_oprnd2.dw_cfi_loc
    1476        25681 :     = mem_loc_descriptor (XEXP (dest, 0), get_address_mode (dest),
    1477        25681 :                           GET_MODE (dest), VAR_INIT_STATUS_INITIALIZED);
    1478              : 
    1479              :   /* ??? We'd like to use queue_reg_save, were the interface different,
    1480              :      and, as above, we could manage flushing for epilogues.  */
    1481        25681 :   add_cfi (cfi);
    1482        25681 :   update_row_reg_save (cur_row, regno, cfi);
    1483        25681 : }
    1484              : 
    1485              : /* A subroutine of dwarf2out_frame_debug, process a REG_CFA_VAL_EXPRESSION
    1486              :    note.  */
    1487              : 
    1488              : static void
    1489            0 : dwarf2out_frame_debug_cfa_val_expression (rtx set)
    1490              : {
    1491            0 :   rtx dest = SET_DEST (set);
    1492            0 :   gcc_assert (REG_P (dest));
    1493              : 
    1494            0 :   rtx span = targetm.dwarf_register_span (dest);
    1495            0 :   gcc_assert (!span);
    1496              : 
    1497            0 :   rtx src = SET_SRC (set);
    1498            0 :   dw_cfi_ref cfi = new_cfi ();
    1499            0 :   cfi->dw_cfi_opc = DW_CFA_val_expression;
    1500            0 :   cfi->dw_cfi_oprnd1.dw_cfi_reg_num = dwf_regno (dest);
    1501            0 :   cfi->dw_cfi_oprnd2.dw_cfi_loc
    1502            0 :     = mem_loc_descriptor (src, GET_MODE (src),
    1503            0 :                           GET_MODE (dest), VAR_INIT_STATUS_INITIALIZED);
    1504            0 :   add_cfi (cfi);
    1505            0 :   update_row_reg_save (cur_row, dwf_regno (dest), cfi);
    1506            0 : }
    1507              : 
    1508              : /* A subroutine of dwarf2out_frame_debug, process a REG_CFA_RESTORE
    1509              :    note. When called with EMIT_CFI set to false emitting a CFI
    1510              :    statement is suppressed.  */
    1511              : 
    1512              : static void
    1513      1004633 : dwarf2out_frame_debug_cfa_restore (rtx reg, bool emit_cfi)
    1514              : {
    1515      1004633 :   gcc_assert (REG_P (reg));
    1516              : 
    1517      1004633 :   rtx span = targetm.dwarf_register_span (reg);
    1518      1004633 :   if (!span)
    1519              :     {
    1520      1004633 :       unsigned int regno = dwf_regno (reg);
    1521      1004633 :       if (emit_cfi)
    1522      1004633 :         add_cfi_restore (regno);
    1523      1004633 :       update_row_reg_save (cur_row, regno, NULL);
    1524              :     }
    1525              :   else
    1526              :     {
    1527              :       /* We have a PARALLEL describing where the contents of REG live.
    1528              :          Restore the register for each piece of the PARALLEL.  */
    1529            0 :       gcc_assert (GET_CODE (span) == PARALLEL);
    1530              : 
    1531            0 :       const int par_len = XVECLEN (span, 0);
    1532            0 :       for (int par_index = 0; par_index < par_len; par_index++)
    1533              :         {
    1534            0 :           reg = XVECEXP (span, 0, par_index);
    1535            0 :           gcc_assert (REG_P (reg));
    1536            0 :           unsigned int regno = dwf_regno (reg);
    1537            0 :           if (emit_cfi)
    1538            0 :             add_cfi_restore (regno);
    1539            0 :           update_row_reg_save (cur_row, regno, NULL);
    1540              :         }
    1541              :     }
    1542      1004633 : }
    1543              : 
    1544              : /* A subroutine of dwarf2out_frame_debug, process a REG_CFA_WINDOW_SAVE.
    1545              : 
    1546              :    ??? Perhaps we should note in the CIE where windows are saved (instead
    1547              :    of assuming 0(cfa)) and what registers are in the window.  */
    1548              : 
    1549              : static void
    1550            0 : dwarf2out_frame_debug_cfa_window_save (void)
    1551              : {
    1552            0 :   dw_cfi_ref cfi = new_cfi ();
    1553              : 
    1554            0 :   cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
    1555            0 :   add_cfi (cfi);
    1556            0 :   cur_row->window_save = true;
    1557            0 : }
    1558              : 
    1559              : /* A subroutine of dwarf2out_frame_debug, process REG_CFA_NEGATE_RA_STATE.  */
    1560              : 
    1561              : static void
    1562            0 : dwarf2out_frame_debug_cfa_negate_ra_state (void)
    1563              : {
    1564            0 :   dw_cfi_ref cfi = new_cfi ();
    1565            0 :   cfi->dw_cfi_opc = DW_CFA_AARCH64_negate_ra_state;
    1566            0 :   cur_row->ra_state
    1567            0 :     = (cur_row->ra_state == ra_no_signing
    1568            0 :       ? ra_signing_sp
    1569              :       : ra_no_signing);
    1570            0 :   add_cfi (cfi);
    1571            0 : }
    1572              : 
    1573              : /* Record call frame debugging information for an expression EXPR,
    1574              :    which either sets SP or FP (adjusting how we calculate the frame
    1575              :    address) or saves a register to the stack or another register.
    1576              :    LABEL indicates the address of EXPR.
    1577              : 
    1578              :    This function encodes a state machine mapping rtxes to actions on
    1579              :    cfa, cfa_store, and cfa_temp.reg.  We describe these rules so
    1580              :    users need not read the source code.
    1581              : 
    1582              :   The High-Level Picture
    1583              : 
    1584              :   Changes in the register we use to calculate the CFA: Currently we
    1585              :   assume that if you copy the CFA register into another register, we
    1586              :   should take the other one as the new CFA register; this seems to
    1587              :   work pretty well.  If it's wrong for some target, it's simple
    1588              :   enough not to set RTX_FRAME_RELATED_P on the insn in question.
    1589              : 
    1590              :   Changes in the register we use for saving registers to the stack:
    1591              :   This is usually SP, but not always.  Again, we deduce that if you
    1592              :   copy SP into another register (and SP is not the CFA register),
    1593              :   then the new register is the one we will be using for register
    1594              :   saves.  This also seems to work.
    1595              : 
    1596              :   Register saves: There's not much guesswork about this one; if
    1597              :   RTX_FRAME_RELATED_P is set on an insn which modifies memory, it's a
    1598              :   register save, and the register used to calculate the destination
    1599              :   had better be the one we think we're using for this purpose.
    1600              :   It's also assumed that a copy from a call-saved register to another
    1601              :   register is saving that register if RTX_FRAME_RELATED_P is set on
    1602              :   that instruction.  If the copy is from a call-saved register to
    1603              :   the *same* register, that means that the register is now the same
    1604              :   value as in the caller.
    1605              : 
    1606              :   Except: If the register being saved is the CFA register, and the
    1607              :   offset is nonzero, we are saving the CFA, so we assume we have to
    1608              :   use DW_CFA_def_cfa_expression.  If the offset is 0, we assume that
    1609              :   the intent is to save the value of SP from the previous frame.
    1610              : 
    1611              :   In addition, if a register has previously been saved to a different
    1612              :   register,
    1613              : 
    1614              :   Invariants / Summaries of Rules
    1615              : 
    1616              :   cfa          current rule for calculating the CFA.  It usually
    1617              :                consists of a register and an offset.  This is
    1618              :                actually stored in *cur_cfa, but abbreviated
    1619              :                for the purposes of this documentation.
    1620              :   cfa_store    register used by prologue code to save things to the stack
    1621              :                cfa_store.offset is the offset from the value of
    1622              :                cfa_store.reg to the actual CFA
    1623              :   cfa_temp     register holding an integral value.  cfa_temp.offset
    1624              :                stores the value, which will be used to adjust the
    1625              :                stack pointer.  cfa_temp is also used like cfa_store,
    1626              :                to track stores to the stack via fp or a temp reg.
    1627              : 
    1628              :   Rules  1- 4: Setting a register's value to cfa.reg or an expression
    1629              :                with cfa.reg as the first operand changes the cfa.reg and its
    1630              :                cfa.offset.  Rule 1 and 4 also set cfa_temp.reg and
    1631              :                cfa_temp.offset.
    1632              : 
    1633              :   Rules  6- 9: Set a non-cfa.reg register value to a constant or an
    1634              :                expression yielding a constant.  This sets cfa_temp.reg
    1635              :                and cfa_temp.offset.
    1636              : 
    1637              :   Rule 5:      Create a new register cfa_store used to save items to the
    1638              :                stack.
    1639              : 
    1640              :   Rules 10-14: Save a register to the stack.  Define offset as the
    1641              :                difference of the original location and cfa_store's
    1642              :                location (or cfa_temp's location if cfa_temp is used).
    1643              : 
    1644              :   Rules 16-20: If AND operation happens on sp in prologue, we assume
    1645              :                stack is realigned.  We will use a group of DW_OP_XXX
    1646              :                expressions to represent the location of the stored
    1647              :                register instead of CFA+offset.
    1648              : 
    1649              :   The Rules
    1650              : 
    1651              :   "{a,b}" indicates a choice of a xor b.
    1652              :   "<reg>:cfa.reg" indicates that <reg> must equal cfa.reg.
    1653              : 
    1654              :   Rule 1:
    1655              :   (set <reg1> <reg2>:cfa.reg)
    1656              :   effects: cfa.reg = <reg1>
    1657              :            cfa.offset unchanged
    1658              :            cfa_temp.reg = <reg1>
    1659              :            cfa_temp.offset = cfa.offset
    1660              : 
    1661              :   Rule 2:
    1662              :   (set sp ({minus,plus,losum} {sp,fp}:cfa.reg
    1663              :                               {<const_int>,<reg>:cfa_temp.reg}))
    1664              :   effects: cfa.reg = sp if fp used
    1665              :            cfa.offset += {+/- <const_int>, cfa_temp.offset} if cfa.reg==sp
    1666              :            cfa_store.offset += {+/- <const_int>, cfa_temp.offset}
    1667              :              if cfa_store.reg==sp
    1668              : 
    1669              :   Rule 3:
    1670              :   (set fp ({minus,plus,losum} <reg>:cfa.reg <const_int>))
    1671              :   effects: cfa.reg = fp
    1672              :            cfa_offset += +/- <const_int>
    1673              : 
    1674              :   Rule 4:
    1675              :   (set <reg1> ({plus,losum} <reg2>:cfa.reg <const_int>))
    1676              :   constraints: <reg1> != fp
    1677              :                <reg1> != sp
    1678              :   effects: cfa.reg = <reg1>
    1679              :            cfa_temp.reg = <reg1>
    1680              :            cfa_temp.offset = cfa.offset
    1681              : 
    1682              :   Rule 5:
    1683              :   (set <reg1> (plus <reg2>:cfa_temp.reg sp:cfa.reg))
    1684              :   constraints: <reg1> != fp
    1685              :                <reg1> != sp
    1686              :   effects: cfa_store.reg = <reg1>
    1687              :            cfa_store.offset = cfa.offset - cfa_temp.offset
    1688              : 
    1689              :   Rule 6:
    1690              :   (set <reg> <const_int>)
    1691              :   effects: cfa_temp.reg = <reg>
    1692              :            cfa_temp.offset = <const_int>
    1693              : 
    1694              :   Rule 7:
    1695              :   (set <reg1>:cfa_temp.reg (ior <reg2>:cfa_temp.reg <const_int>))
    1696              :   effects: cfa_temp.reg = <reg1>
    1697              :            cfa_temp.offset |= <const_int>
    1698              : 
    1699              :   Rule 8:
    1700              :   (set <reg> (high <exp>))
    1701              :   effects: none
    1702              : 
    1703              :   Rule 9:
    1704              :   (set <reg> (lo_sum <exp> <const_int>))
    1705              :   effects: cfa_temp.reg = <reg>
    1706              :            cfa_temp.offset = <const_int>
    1707              : 
    1708              :   Rule 10:
    1709              :   (set (mem ({pre,post}_modify sp:cfa_store (???? <reg1> <const_int>))) <reg2>)
    1710              :   effects: cfa_store.offset -= <const_int>
    1711              :            cfa.offset = cfa_store.offset if cfa.reg == sp
    1712              :            cfa.reg = sp
    1713              :            cfa.base_offset = -cfa_store.offset
    1714              : 
    1715              :   Rule 11:
    1716              :   (set (mem ({pre_inc,pre_dec,post_dec} sp:cfa_store.reg)) <reg>)
    1717              :   effects: cfa_store.offset += -/+ mode_size(mem)
    1718              :            cfa.offset = cfa_store.offset if cfa.reg == sp
    1719              :            cfa.reg = sp
    1720              :            cfa.base_offset = -cfa_store.offset
    1721              : 
    1722              :   Rule 12:
    1723              :   (set (mem ({minus,plus,losum} <reg1>:{cfa_store,cfa_temp} <const_int>))
    1724              : 
    1725              :        <reg2>)
    1726              :   effects: cfa.reg = <reg1>
    1727              :            cfa.base_offset = -/+ <const_int> - {cfa_store,cfa_temp}.offset
    1728              : 
    1729              :   Rule 13:
    1730              :   (set (mem <reg1>:{cfa_store,cfa_temp}) <reg2>)
    1731              :   effects: cfa.reg = <reg1>
    1732              :            cfa.base_offset = -{cfa_store,cfa_temp}.offset
    1733              : 
    1734              :   Rule 14:
    1735              :   (set (mem (post_inc <reg1>:cfa_temp <const_int>)) <reg2>)
    1736              :   effects: cfa.reg = <reg1>
    1737              :            cfa.base_offset = -cfa_temp.offset
    1738              :            cfa_temp.offset -= mode_size(mem)
    1739              : 
    1740              :   Rule 15:
    1741              :   (set <reg> {unspec, unspec_volatile})
    1742              :   effects: target-dependent
    1743              : 
    1744              :   Rule 16:
    1745              :   (set sp (and: sp <const_int>))
    1746              :   constraints: cfa_store.reg == sp
    1747              :   effects: cfun->fde.stack_realign = 1
    1748              :            cfa_store.offset = 0
    1749              :            fde->drap_reg = cfa.reg if cfa.reg != sp and cfa.reg != fp
    1750              : 
    1751              :   Rule 17:
    1752              :   (set (mem ({pre_inc, pre_dec} sp)) (mem (plus (cfa.reg) (const_int))))
    1753              :   effects: cfa_store.offset += -/+ mode_size(mem)
    1754              : 
    1755              :   Rule 18:
    1756              :   (set (mem ({pre_inc, pre_dec} sp)) fp)
    1757              :   constraints: fde->stack_realign == 1
    1758              :   effects: cfa_store.offset = 0
    1759              :            cfa.reg != HARD_FRAME_POINTER_REGNUM
    1760              : 
    1761              :   Rule 19:
    1762              :   (set (mem ({pre_inc, pre_dec} sp)) cfa.reg)
    1763              :   constraints: fde->stack_realign == 1
    1764              :                && cfa.offset == 0
    1765              :                && cfa.indirect == 0
    1766              :                && cfa.reg != HARD_FRAME_POINTER_REGNUM
    1767              :   effects: Use DW_CFA_def_cfa_expression to define cfa
    1768              :            cfa.reg == fde->drap_reg  */
    1769              : 
    1770              : static void
    1771      3095846 : dwarf2out_frame_debug_expr (rtx expr)
    1772              : {
    1773      3095846 :   rtx src, dest, span;
    1774      3095846 :   poly_int64 offset;
    1775      3095846 :   dw_fde_ref fde;
    1776              : 
    1777              :   /* If RTX_FRAME_RELATED_P is set on a PARALLEL, process each member of
    1778              :      the PARALLEL independently. The first element is always processed if
    1779              :      it is a SET. This is for backward compatibility.   Other elements
    1780              :      are processed only if they are SETs and the RTX_FRAME_RELATED_P
    1781              :      flag is set in them.  */
    1782      3095846 :   if (GET_CODE (expr) == PARALLEL || GET_CODE (expr) == SEQUENCE)
    1783              :     {
    1784       304245 :       int par_index;
    1785       304245 :       int limit = XVECLEN (expr, 0);
    1786       304245 :       rtx elem;
    1787              : 
    1788              :       /* PARALLELs have strict read-modify-write semantics, so we
    1789              :          ought to evaluate every rvalue before changing any lvalue.
    1790              :          It's cumbersome to do that in general, but there's an
    1791              :          easy approximation that is enough for all current users:
    1792              :          handle register saves before register assignments.  */
    1793       304245 :       if (GET_CODE (expr) == PARALLEL)
    1794      1288503 :         for (par_index = 0; par_index < limit; par_index++)
    1795              :           {
    1796       984277 :             elem = XVECEXP (expr, 0, par_index);
    1797       984277 :             if (GET_CODE (elem) == SET
    1798       390014 :                 && MEM_P (SET_DEST (elem))
    1799      1077198 :                 && (RTX_FRAME_RELATED_P (elem) || par_index == 0))
    1800           88 :               dwarf2out_frame_debug_expr (elem);
    1801              :           }
    1802              : 
    1803      1288579 :       for (par_index = 0; par_index < limit; par_index++)
    1804              :         {
    1805       984334 :           elem = XVECEXP (expr, 0, par_index);
    1806       984334 :           if (GET_CODE (elem) == SET
    1807       390071 :               && (!MEM_P (SET_DEST (elem)) || GET_CODE (expr) == SEQUENCE)
    1808      1281484 :               && (RTX_FRAME_RELATED_P (elem) || par_index == 0))
    1809       297150 :             dwarf2out_frame_debug_expr (elem);
    1810              :         }
    1811      3095846 :       return;
    1812              :     }
    1813              : 
    1814      2791601 :   gcc_assert (GET_CODE (expr) == SET);
    1815              : 
    1816      2791601 :   src = SET_SRC (expr);
    1817      2791601 :   dest = SET_DEST (expr);
    1818              : 
    1819      2791601 :   if (REG_P (src))
    1820              :     {
    1821      2480032 :       rtx rsi = reg_saved_in (src);
    1822      2480032 :       if (rsi)
    1823      2791601 :         src = rsi;
    1824              :     }
    1825              : 
    1826      2791601 :   fde = cfun->fde;
    1827              : 
    1828      2791601 :   switch (GET_CODE (dest))
    1829              :     {
    1830       775428 :     case REG:
    1831       775428 :       switch (GET_CODE (src))
    1832              :         {
    1833              :           /* Setting FP from SP.  */
    1834       470926 :         case REG:
    1835       470926 :           if (cur_cfa->reg == src)
    1836              :             {
    1837              :               /* Rule 1 */
    1838              :               /* Update the CFA rule wrt SP or FP.  Make sure src is
    1839              :                  relative to the current CFA register.
    1840              : 
    1841              :                  We used to require that dest be either SP or FP, but the
    1842              :                  ARM copies SP to a temporary register, and from there to
    1843              :                  FP.  So we just rely on the backends to only set
    1844              :                  RTX_FRAME_RELATED_P on appropriate insns.  */
    1845       463859 :               cur_cfa->reg = dwf_cfa_reg (dest);
    1846       463859 :               cur_trace->cfa_temp.reg = cur_cfa->reg;
    1847       463859 :               cur_trace->cfa_temp.offset = cur_cfa->offset;
    1848              :             }
    1849              :           else
    1850              :             {
    1851              :               /* Saving a register in a register.  */
    1852         7067 :               gcc_assert (!fixed_regs [REGNO (dest)]
    1853              :                           /* For the SPARC and its register window.  */
    1854              :                           || (dwf_regno (src) == DWARF_FRAME_RETURN_COLUMN));
    1855              : 
    1856              :               /* After stack is aligned, we can only save SP in FP
    1857              :                  if drap register is used.  In this case, we have
    1858              :                  to restore stack pointer with the CFA value and we
    1859              :                  don't generate this DWARF information.  */
    1860         7067 :               if (fde
    1861         7067 :                   && fde->stack_realign
    1862        14134 :                   && REGNO (src) == STACK_POINTER_REGNUM)
    1863              :                 {
    1864         7067 :                   gcc_assert (REGNO (dest) == HARD_FRAME_POINTER_REGNUM
    1865              :                               && fde->drap_reg != INVALID_REGNUM
    1866              :                               && cur_cfa->reg != src
    1867              :                               && fde->rule18);
    1868         7067 :                   fde->rule18 = 0;
    1869              :                   /* The save of hard frame pointer has been deferred
    1870              :                      until this point when Rule 18 applied.  Emit it now.  */
    1871         7067 :                   queue_reg_save (dest, NULL_RTX, 0);
    1872              :                   /* And as the instruction modifies the hard frame pointer,
    1873              :                      flush the queue as well.  */
    1874         7067 :                   dwarf2out_flush_queued_reg_saves ();
    1875              :                 }
    1876              :               else
    1877            0 :                 queue_reg_save (src, dest, 0);
    1878              :             }
    1879              :           break;
    1880              : 
    1881       297435 :         case PLUS:
    1882       297435 :         case MINUS:
    1883       297435 :         case LO_SUM:
    1884       297435 :           if (dest == stack_pointer_rtx)
    1885              :             {
    1886              :               /* Rule 2 */
    1887              :               /* Adjusting SP.  */
    1888       290368 :               if (REG_P (XEXP (src, 1)))
    1889              :                 {
    1890            0 :                   gcc_assert (cur_trace->cfa_temp.reg == XEXP (src, 1));
    1891            0 :                   offset = cur_trace->cfa_temp.offset;
    1892              :                 }
    1893       290368 :               else if (!poly_int_rtx_p (XEXP (src, 1), &offset))
    1894            0 :                 gcc_unreachable ();
    1895              : 
    1896       290368 :               if (XEXP (src, 0) == hard_frame_pointer_rtx)
    1897              :                 {
    1898              :                   /* Restoring SP from FP in the epilogue.  */
    1899            0 :                   gcc_assert (cur_cfa->reg == dw_frame_pointer_regnum);
    1900            0 :                   cur_cfa->reg = dw_stack_pointer_regnum;
    1901              :                 }
    1902       290368 :               else if (GET_CODE (src) == LO_SUM)
    1903              :                 /* Assume we've set the source reg of the LO_SUM from sp.  */
    1904              :                 ;
    1905              :               else
    1906       290368 :                 gcc_assert (XEXP (src, 0) == stack_pointer_rtx);
    1907              : 
    1908       290368 :               if (GET_CODE (src) != MINUS)
    1909       290368 :                 offset = -offset;
    1910       290368 :               if (cur_cfa->reg == dw_stack_pointer_regnum)
    1911           51 :                 cur_cfa->offset += offset;
    1912       290368 :               if (cur_trace->cfa_store.reg == dw_stack_pointer_regnum)
    1913       290368 :                 cur_trace->cfa_store.offset += offset;
    1914              :             }
    1915         7067 :           else if (dest == hard_frame_pointer_rtx)
    1916              :             {
    1917              :               /* Rule 3 */
    1918              :               /* Either setting the FP from an offset of the SP,
    1919              :                  or adjusting the FP */
    1920            0 :               gcc_assert (frame_pointer_needed);
    1921              : 
    1922            0 :               gcc_assert (REG_P (XEXP (src, 0))
    1923              :                           && cur_cfa->reg == XEXP (src, 0));
    1924            0 :               offset = rtx_to_poly_int64 (XEXP (src, 1));
    1925            0 :               if (GET_CODE (src) != MINUS)
    1926            0 :                 offset = -offset;
    1927            0 :               cur_cfa->offset += offset;
    1928            0 :               cur_cfa->reg = dw_frame_pointer_regnum;
    1929              :             }
    1930              :           else
    1931              :             {
    1932         7067 :               gcc_assert (GET_CODE (src) != MINUS);
    1933              : 
    1934              :               /* Rule 4 */
    1935         7067 :               if (REG_P (XEXP (src, 0))
    1936         7067 :                   && cur_cfa->reg == XEXP (src, 0)
    1937        14134 :                   && poly_int_rtx_p (XEXP (src, 1), &offset))
    1938              :                 {
    1939              :                   /* Setting a temporary CFA register that will be copied
    1940              :                      into the FP later on.  */
    1941         7067 :                   offset = -offset;
    1942         7067 :                   cur_cfa->offset += offset;
    1943         7067 :                   cur_cfa->reg = dwf_cfa_reg (dest);
    1944              :                   /* Or used to save regs to the stack.  */
    1945         7067 :                   cur_trace->cfa_temp.reg = cur_cfa->reg;
    1946         7067 :                   cur_trace->cfa_temp.offset = cur_cfa->offset;
    1947              :                 }
    1948              : 
    1949              :               /* Rule 5 */
    1950            0 :               else if (REG_P (XEXP (src, 0))
    1951            0 :                        && cur_trace->cfa_temp.reg == XEXP (src, 0)
    1952            0 :                        && XEXP (src, 1) == stack_pointer_rtx)
    1953              :                 {
    1954              :                   /* Setting a scratch register that we will use instead
    1955              :                      of SP for saving registers to the stack.  */
    1956            0 :                   gcc_assert (cur_cfa->reg == dw_stack_pointer_regnum);
    1957            0 :                   cur_trace->cfa_store.reg = dwf_cfa_reg (dest);
    1958            0 :                   cur_trace->cfa_store.offset
    1959            0 :                     = cur_cfa->offset - cur_trace->cfa_temp.offset;
    1960              :                 }
    1961              : 
    1962              :               /* Rule 9 */
    1963            0 :               else if (GET_CODE (src) == LO_SUM
    1964            0 :                        && poly_int_rtx_p (XEXP (src, 1),
    1965            0 :                                           &cur_trace->cfa_temp.offset))
    1966            0 :                 cur_trace->cfa_temp.reg = dwf_cfa_reg (dest);
    1967              :               else
    1968            0 :                 gcc_unreachable ();
    1969              :             }
    1970              :           break;
    1971              : 
    1972              :           /* Rule 6 */
    1973            0 :         case CONST_INT:
    1974            0 :         case CONST_POLY_INT:
    1975            0 :           cur_trace->cfa_temp.reg = dwf_cfa_reg (dest);
    1976            0 :           cur_trace->cfa_temp.offset = rtx_to_poly_int64 (src);
    1977            0 :           break;
    1978              : 
    1979              :           /* Rule 7 */
    1980            0 :         case IOR:
    1981            0 :           gcc_assert (REG_P (XEXP (src, 0))
    1982              :                       && cur_trace->cfa_temp.reg == XEXP (src, 0)
    1983              :                       && CONST_INT_P (XEXP (src, 1)));
    1984              : 
    1985            0 :           cur_trace->cfa_temp.reg = dwf_cfa_reg (dest);
    1986            0 :           if (!can_ior_p (cur_trace->cfa_temp.offset, INTVAL (XEXP (src, 1)),
    1987            0 :                           &cur_trace->cfa_temp.offset))
    1988              :             /* The target shouldn't generate this kind of CFI note if we
    1989              :                can't represent it.  */
    1990              :             gcc_unreachable ();
    1991              :           break;
    1992              : 
    1993              :           /* Skip over HIGH, assuming it will be followed by a LO_SUM,
    1994              :              which will fill in all of the bits.  */
    1995              :           /* Rule 8 */
    1996              :         case HIGH:
    1997              :           break;
    1998              : 
    1999              :           /* Rule 15 */
    2000            0 :         case UNSPEC:
    2001            0 :         case UNSPEC_VOLATILE:
    2002              :           /* All unspecs should be represented by REG_CFA_* notes.  */
    2003            0 :           gcc_unreachable ();
    2004         7067 :           return;
    2005              : 
    2006              :           /* Rule 16 */
    2007         7067 :         case AND:
    2008              :           /* If this AND operation happens on stack pointer in prologue,
    2009              :              we assume the stack is realigned and we extract the
    2010              :              alignment.  */
    2011         7067 :           if (fde && XEXP (src, 0) == stack_pointer_rtx)
    2012              :             {
    2013              :               /* We interpret reg_save differently with stack_realign set.
    2014              :                  Thus we must flush whatever we have queued first.  */
    2015         7067 :               dwarf2out_flush_queued_reg_saves ();
    2016              : 
    2017         7067 :               gcc_assert (cur_trace->cfa_store.reg
    2018              :                           == XEXP (src, 0));
    2019         7067 :               fde->stack_realign = 1;
    2020         7067 :               fde->stack_realignment = INTVAL (XEXP (src, 1));
    2021         7067 :               cur_trace->cfa_store.offset = 0;
    2022              : 
    2023         7067 :               if (cur_cfa->reg != dw_stack_pointer_regnum
    2024         7067 :                   && cur_cfa->reg != dw_frame_pointer_regnum)
    2025              :                 {
    2026         7067 :                   gcc_assert (cur_cfa->reg.span == 1);
    2027         7067 :                   fde->drap_reg = cur_cfa->reg.reg;
    2028              :                 }
    2029              :             }
    2030              :           return;
    2031              : 
    2032            0 :         default:
    2033            0 :           gcc_unreachable ();
    2034              :         }
    2035              :       break;
    2036              : 
    2037      2016173 :     case MEM:
    2038              : 
    2039              :       /* Saving a register to the stack.  Make sure dest is relative to the
    2040              :          CFA register.  */
    2041      2016173 :       switch (GET_CODE (XEXP (dest, 0)))
    2042              :         {
    2043              :           /* Rule 10 */
    2044              :           /* With a push.  */
    2045            0 :         case PRE_MODIFY:
    2046            0 :         case POST_MODIFY:
    2047              :           /* We can't handle variable size modifications.  */
    2048            0 :           offset = -rtx_to_poly_int64 (XEXP (XEXP (XEXP (dest, 0), 1), 1));
    2049              : 
    2050            0 :           gcc_assert (REGNO (XEXP (XEXP (dest, 0), 0)) == STACK_POINTER_REGNUM
    2051              :                       && cur_trace->cfa_store.reg == dw_stack_pointer_regnum);
    2052              : 
    2053            0 :           cur_trace->cfa_store.offset += offset;
    2054            0 :           if (cur_cfa->reg == dw_stack_pointer_regnum)
    2055            0 :             cur_cfa->offset = cur_trace->cfa_store.offset;
    2056              : 
    2057            0 :           if (GET_CODE (XEXP (dest, 0)) == POST_MODIFY)
    2058            0 :             offset -= cur_trace->cfa_store.offset;
    2059              :           else
    2060            0 :             offset = -cur_trace->cfa_store.offset;
    2061              :           break;
    2062              : 
    2063              :           /* Rule 11 */
    2064      1481510 :         case PRE_INC:
    2065      1481510 :         case PRE_DEC:
    2066      1481510 :         case POST_DEC:
    2067      2963020 :           offset = GET_MODE_SIZE (GET_MODE (dest));
    2068      1481510 :           if (GET_CODE (XEXP (dest, 0)) == PRE_INC)
    2069            0 :             offset = -offset;
    2070              : 
    2071      1481510 :           gcc_assert ((REGNO (XEXP (XEXP (dest, 0), 0))
    2072              :                        == STACK_POINTER_REGNUM)
    2073              :                       && cur_trace->cfa_store.reg == dw_stack_pointer_regnum);
    2074              : 
    2075      1481510 :           cur_trace->cfa_store.offset += offset;
    2076              : 
    2077              :           /* Rule 18: If stack is aligned, we will use FP as a
    2078              :              reference to represent the address of the stored
    2079              :              regiser.  */
    2080      1481510 :           if (fde
    2081      1481510 :               && fde->stack_realign
    2082        32083 :               && REG_P (src)
    2083      1506526 :               && REGNO (src) == HARD_FRAME_POINTER_REGNUM)
    2084              :             {
    2085         7067 :               gcc_assert (cur_cfa->reg != dw_frame_pointer_regnum);
    2086         7067 :               cur_trace->cfa_store.offset = 0;
    2087         7067 :               fde->rule18 = 1;
    2088              :             }
    2089              : 
    2090      1481510 :           if (cur_cfa->reg == dw_stack_pointer_regnum)
    2091      1221831 :             cur_cfa->offset = cur_trace->cfa_store.offset;
    2092              : 
    2093      1481510 :           if (GET_CODE (XEXP (dest, 0)) == POST_DEC)
    2094            0 :             offset += -cur_trace->cfa_store.offset;
    2095              :           else
    2096      1481510 :             offset = -cur_trace->cfa_store.offset;
    2097              :           break;
    2098              : 
    2099              :           /* Rule 12 */
    2100              :           /* With an offset.  */
    2101       524830 :         case PLUS:
    2102       524830 :         case MINUS:
    2103       524830 :         case LO_SUM:
    2104       524830 :           {
    2105       524830 :             struct cfa_reg regno;
    2106              : 
    2107       524830 :             gcc_assert (REG_P (XEXP (XEXP (dest, 0), 0)));
    2108       524830 :             offset = rtx_to_poly_int64 (XEXP (XEXP (dest, 0), 1));
    2109       524830 :             if (GET_CODE (XEXP (dest, 0)) == MINUS)
    2110            0 :               offset = -offset;
    2111              : 
    2112       524830 :             regno = dwf_cfa_reg (XEXP (XEXP (dest, 0), 0));
    2113              : 
    2114       524830 :             if (cur_cfa->reg == regno)
    2115       524825 :               offset -= cur_cfa->offset;
    2116            5 :             else if (cur_trace->cfa_store.reg == regno)
    2117            5 :               offset -= cur_trace->cfa_store.offset;
    2118              :             else
    2119              :               {
    2120            0 :                 gcc_assert (cur_trace->cfa_temp.reg == regno);
    2121            0 :                 offset -= cur_trace->cfa_temp.offset;
    2122              :               }
    2123              :           }
    2124       524830 :           break;
    2125              : 
    2126              :           /* Rule 13 */
    2127              :           /* Without an offset.  */
    2128         9833 :         case REG:
    2129         9833 :           {
    2130         9833 :             struct cfa_reg regno = dwf_cfa_reg (XEXP (dest, 0));
    2131              : 
    2132         9833 :             if (cur_cfa->reg == regno)
    2133         9828 :               offset = -cur_cfa->offset;
    2134            5 :             else if (cur_trace->cfa_store.reg == regno)
    2135            5 :               offset = -cur_trace->cfa_store.offset;
    2136              :             else
    2137              :               {
    2138            0 :                 gcc_assert (cur_trace->cfa_temp.reg == regno);
    2139            0 :                 offset = -cur_trace->cfa_temp.offset;
    2140              :               }
    2141              :           }
    2142         9833 :           break;
    2143              : 
    2144              :           /* Rule 14 */
    2145            0 :         case POST_INC:
    2146            0 :           gcc_assert (cur_trace->cfa_temp.reg == XEXP (XEXP (dest, 0), 0));
    2147            0 :           offset = -cur_trace->cfa_temp.offset;
    2148            0 :           cur_trace->cfa_temp.offset -= GET_MODE_SIZE (GET_MODE (dest));
    2149            0 :           break;
    2150              : 
    2151            0 :         default:
    2152            0 :           gcc_unreachable ();
    2153              :         }
    2154              : 
    2155              :       /* Rule 17 */
    2156              :       /* If the source operand of this MEM operation is a memory,
    2157              :          we only care how much stack grew.  */
    2158      2016173 :       if (MEM_P (src))
    2159              :         break;
    2160              : 
    2161      2009106 :       if (REG_P (src)
    2162      2009106 :           && REGNO (src) != STACK_POINTER_REGNUM
    2163      2009106 :           && REGNO (src) != HARD_FRAME_POINTER_REGNUM
    2164      3360567 :           && cur_cfa->reg == src)
    2165              :         {
    2166              :           /* We're storing the current CFA reg into the stack.  */
    2167              : 
    2168         7067 :           if (known_eq (cur_cfa->offset, 0))
    2169              :             {
    2170              :               /* Rule 19 */
    2171              :               /* If stack is aligned, putting CFA reg into stack means
    2172              :                  we can no longer use reg + offset to represent CFA.
    2173              :                  Here we use DW_CFA_def_cfa_expression instead.  The
    2174              :                  result of this expression equals to the original CFA
    2175              :                  value.  */
    2176         7067 :               if (fde
    2177         7067 :                   && fde->stack_realign
    2178         7067 :                   && cur_cfa->indirect == 0
    2179        14134 :                   && cur_cfa->reg != dw_frame_pointer_regnum)
    2180              :                 {
    2181         7067 :                   gcc_assert (fde->drap_reg == cur_cfa->reg.reg);
    2182              : 
    2183         7067 :                   cur_cfa->indirect = 1;
    2184         7067 :                   cur_cfa->reg = dw_frame_pointer_regnum;
    2185         7067 :                   cur_cfa->base_offset = offset;
    2186         7067 :                   cur_cfa->offset = 0;
    2187              : 
    2188         7067 :                   fde->drap_reg_saved = 1;
    2189         7067 :                   break;
    2190              :                 }
    2191              : 
    2192              :               /* If the source register is exactly the CFA, assume
    2193              :                  we're saving SP like any other register; this happens
    2194              :                  on the ARM.  */
    2195            0 :               queue_reg_save (stack_pointer_rtx, NULL_RTX, offset);
    2196            0 :               break;
    2197              :             }
    2198              :           else
    2199              :             {
    2200              :               /* Otherwise, we'll need to look in the stack to
    2201              :                  calculate the CFA.  */
    2202            0 :               rtx x = XEXP (dest, 0);
    2203              : 
    2204            0 :               if (!REG_P (x))
    2205            0 :                 x = XEXP (x, 0);
    2206            0 :               gcc_assert (REG_P (x));
    2207              : 
    2208            0 :               cur_cfa->reg = dwf_cfa_reg (x);
    2209            0 :               cur_cfa->base_offset = offset;
    2210            0 :               cur_cfa->indirect = 1;
    2211            0 :               break;
    2212              :             }
    2213              :         }
    2214              : 
    2215      2002039 :       if (REG_P (src))
    2216      2002039 :         span = targetm.dwarf_register_span (src);
    2217              :       else
    2218              :         span = NULL;
    2219              : 
    2220      2002039 :       if (!span)
    2221              :         {
    2222      2002039 :           if (fde->rule18)
    2223              :             /* Just verify the hard frame pointer save when doing dynamic
    2224              :                realignment uses expected offset.  The actual queue_reg_save
    2225              :                needs to be deferred until the instruction that sets
    2226              :                hard frame pointer to stack pointer, see PR99334 for
    2227              :                details.  */
    2228         7067 :             gcc_assert (known_eq (offset, 0));
    2229              :           else
    2230      1994972 :             queue_reg_save (src, NULL_RTX, offset);
    2231              :         }
    2232              :       else
    2233              :         {
    2234              :           /* We have a PARALLEL describing where the contents of SRC live.
    2235              :              Queue register saves for each piece of the PARALLEL.  */
    2236            0 :           poly_int64 span_offset = offset;
    2237              : 
    2238            0 :           gcc_assert (GET_CODE (span) == PARALLEL);
    2239              : 
    2240            0 :           const int par_len = XVECLEN (span, 0);
    2241            0 :           for (int par_index = 0; par_index < par_len; par_index++)
    2242              :             {
    2243            0 :               rtx elem = XVECEXP (span, 0, par_index);
    2244            0 :               queue_reg_save (elem, NULL_RTX, span_offset);
    2245            0 :               span_offset += GET_MODE_SIZE (GET_MODE (elem));
    2246              :             }
    2247              :         }
    2248              :       break;
    2249              : 
    2250            0 :     default:
    2251            0 :       gcc_unreachable ();
    2252              :     }
    2253              : }
    2254              : 
    2255              : /* Record call frame debugging information for INSN, which either sets
    2256              :    SP or FP (adjusting how we calculate the frame address) or saves a
    2257              :    register to the stack.  */
    2258              : 
    2259              : static void
    2260      5793626 : dwarf2out_frame_debug (rtx_insn *insn)
    2261              : {
    2262      5793626 :   rtx note, n, pat;
    2263      5793626 :   bool handled_one = false;
    2264              : 
    2265     12232859 :   for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
    2266      6439575 :     switch (REG_NOTE_KIND (note))
    2267              :       {
    2268          342 :       case REG_FRAME_RELATED_EXPR:
    2269          342 :         pat = XEXP (note, 0);
    2270          342 :         goto do_frame_expr;
    2271              : 
    2272       474292 :       case REG_CFA_DEF_CFA:
    2273       474292 :         dwarf2out_frame_debug_def_cfa (XEXP (note, 0));
    2274       474292 :         handled_one = true;
    2275       474292 :         break;
    2276              : 
    2277      2101251 :       case REG_CFA_ADJUST_CFA:
    2278      2101251 :         n = XEXP (note, 0);
    2279      2101251 :         if (n == NULL)
    2280              :           {
    2281            0 :             n = PATTERN (insn);
    2282            0 :             if (GET_CODE (n) == PARALLEL)
    2283            0 :               n = XVECEXP (n, 0, 0);
    2284              :           }
    2285      2101251 :         dwarf2out_frame_debug_adjust_cfa (n);
    2286      2101251 :         handled_one = true;
    2287      2101251 :         break;
    2288              : 
    2289        45078 :       case REG_CFA_OFFSET:
    2290        45078 :         n = XEXP (note, 0);
    2291        45078 :         if (n == NULL)
    2292            0 :           n = single_set (insn);
    2293        45078 :         dwarf2out_frame_debug_cfa_offset (n);
    2294        45078 :         handled_one = true;
    2295        45078 :         break;
    2296              : 
    2297           17 :       case REG_CFA_REGISTER:
    2298           17 :         n = XEXP (note, 0);
    2299           17 :         if (n == NULL)
    2300              :           {
    2301            0 :             n = PATTERN (insn);
    2302            0 :             if (GET_CODE (n) == PARALLEL)
    2303            0 :               n = XVECEXP (n, 0, 0);
    2304              :           }
    2305           17 :         dwarf2out_frame_debug_cfa_register (n);
    2306           17 :         handled_one = true;
    2307           17 :         break;
    2308              : 
    2309        25681 :       case REG_CFA_EXPRESSION:
    2310        25681 :       case REG_CFA_VAL_EXPRESSION:
    2311        25681 :         n = XEXP (note, 0);
    2312        25681 :         if (n == NULL)
    2313            0 :           n = single_set (insn);
    2314              : 
    2315        25681 :         if (REG_NOTE_KIND (note) == REG_CFA_EXPRESSION)
    2316        25681 :           dwarf2out_frame_debug_cfa_expression (n);
    2317              :         else
    2318            0 :           dwarf2out_frame_debug_cfa_val_expression (n);
    2319              : 
    2320              :         handled_one = true;
    2321              :         break;
    2322              : 
    2323      1004633 :       case REG_CFA_RESTORE:
    2324      1004633 :       case REG_CFA_NO_RESTORE:
    2325      1004633 :         n = XEXP (note, 0);
    2326      1004633 :         if (n == NULL)
    2327              :           {
    2328            0 :             n = PATTERN (insn);
    2329            0 :             if (GET_CODE (n) == PARALLEL)
    2330            0 :               n = XVECEXP (n, 0, 0);
    2331            0 :             n = XEXP (n, 0);
    2332              :           }
    2333      1004633 :         dwarf2out_frame_debug_cfa_restore (n, REG_NOTE_KIND (note) == REG_CFA_RESTORE);
    2334      1004633 :         handled_one = true;
    2335      1004633 :         break;
    2336              : 
    2337          274 :       case REG_CFA_SET_VDRAP:
    2338          274 :         n = XEXP (note, 0);
    2339          274 :         if (REG_P (n))
    2340              :           {
    2341          274 :             dw_fde_ref fde = cfun->fde;
    2342          274 :             if (fde)
    2343              :               {
    2344          274 :                 gcc_assert (fde->vdrap_reg == INVALID_REGNUM);
    2345          274 :                 if (REG_P (n))
    2346          274 :                   fde->vdrap_reg = dwf_regno (n);
    2347              :               }
    2348              :           }
    2349              :         handled_one = true;
    2350              :         break;
    2351              : 
    2352            0 :       case REG_CFA_NEGATE_RA_STATE:
    2353            0 :         dwarf2out_frame_debug_cfa_negate_ra_state ();
    2354            0 :         handled_one = true;
    2355            0 :         break;
    2356              : 
    2357            0 :       case REG_CFA_WINDOW_SAVE:
    2358            0 :         dwarf2out_frame_debug_cfa_window_save ();
    2359            0 :         handled_one = true;
    2360            0 :         break;
    2361              : 
    2362              :       case REG_CFA_FLUSH_QUEUE:
    2363              :         /* The actual flush happens elsewhere.  */
    2364      3683242 :         handled_one = true;
    2365              :         break;
    2366              : 
    2367              :       default:
    2368              :         break;
    2369              :       }
    2370              : 
    2371      5793284 :   if (!handled_one)
    2372              :     {
    2373      2798266 :       pat = PATTERN (insn);
    2374      2798608 :     do_frame_expr:
    2375      2798608 :       dwarf2out_frame_debug_expr (pat);
    2376              : 
    2377              :       /* Check again.  A parallel can save and update the same register.
    2378              :          We could probably check just once, here, but this is safer than
    2379              :          removing the check at the start of the function.  */
    2380      2798608 :       if (clobbers_queued_reg_save (pat))
    2381            0 :         dwarf2out_flush_queued_reg_saves ();
    2382              :     }
    2383      5793626 : }
    2384              : 
    2385              : /* Emit CFI info to change the state from OLD_ROW to NEW_ROW.  */
    2386              : 
    2387              : static void
    2388      9924566 : change_cfi_row (dw_cfi_row *old_row, dw_cfi_row *new_row)
    2389              : {
    2390      9924566 :   size_t i, n_old, n_new, n_max;
    2391      9924566 :   dw_cfi_ref cfi;
    2392              : 
    2393      9924566 :   if (new_row->cfa_cfi && !cfi_equal_p (old_row->cfa_cfi, new_row->cfa_cfi))
    2394         1882 :     add_cfi (new_row->cfa_cfi);
    2395              :   else
    2396              :     {
    2397      9922684 :       cfi = def_cfa_0 (&old_row->cfa, &new_row->cfa);
    2398      9922684 :       if (cfi)
    2399       212035 :         add_cfi (cfi);
    2400              :     }
    2401              : 
    2402      9924566 :   n_old = vec_safe_length (old_row->reg_save);
    2403      9924566 :   n_new = vec_safe_length (new_row->reg_save);
    2404      9924566 :   n_max = MAX (n_old, n_new);
    2405              : 
    2406    169871935 :   for (i = 0; i < n_max; ++i)
    2407              :     {
    2408    159947369 :       dw_cfi_ref r_old = NULL, r_new = NULL;
    2409              : 
    2410    159947369 :       if (i < n_old)
    2411    159947369 :         r_old = (*old_row->reg_save)[i];
    2412    159947369 :       if (i < n_new)
    2413    159919496 :         r_new = (*new_row->reg_save)[i];
    2414              : 
    2415    159947369 :       if (r_old == r_new)
    2416              :         ;
    2417       750373 :       else if (r_new == NULL)
    2418       356906 :         add_cfi_restore (i);
    2419       393467 :       else if (!cfi_equal_p (r_old, r_new))
    2420       345614 :         add_cfi (r_new);
    2421              :     }
    2422              : 
    2423      9924566 :   if (!old_row->window_save && new_row->window_save)
    2424              :     {
    2425            0 :       dw_cfi_ref cfi = new_cfi ();
    2426              : 
    2427            0 :       gcc_assert (!old_row->ra_state && !new_row->ra_state);
    2428            0 :       cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
    2429            0 :       add_cfi (cfi);
    2430              :     }
    2431              : 
    2432      9924566 :   if (old_row->ra_state != new_row->ra_state)
    2433              :     {
    2434            0 :       dw_cfi_ref cfi = new_cfi ();
    2435              : 
    2436            0 :       gcc_assert (!old_row->window_save && !new_row->window_save);
    2437            0 :       cfi->dw_cfi_opc = DW_CFA_AARCH64_negate_ra_state;
    2438            0 :       add_cfi (cfi);
    2439              :     }
    2440      9924566 : }
    2441              : 
    2442              : /* Examine CFI and return true if a cfi label and set_loc is needed
    2443              :    beforehand.  Even when generating CFI assembler instructions, we
    2444              :    still have to add the cfi to the list so that lookup_cfa_1 works
    2445              :    later on.  When -g2 and above we even need to force emitting of
    2446              :    CFI labels and add to list a DW_CFA_set_loc for convert_cfa_to_fb_loc_list
    2447              :    purposes.  If we're generating DWARF3 output we use DW_OP_call_frame_cfa
    2448              :    and so don't use convert_cfa_to_fb_loc_list.  */
    2449              : 
    2450              : static bool
    2451     11895682 : cfi_label_required_p (dw_cfi_ref cfi)
    2452              : {
    2453     11895682 :   if (!dwarf2out_do_cfi_asm ())
    2454              :     return true;
    2455              : 
    2456     11895607 :   if (dwarf_version == 2
    2457         9959 :       && debug_info_level > DINFO_LEVEL_TERSE
    2458     11903563 :       && dwarf_debuginfo_p ())
    2459              :     {
    2460         7956 :       switch (cfi->dw_cfi_opc)
    2461              :         {
    2462              :         case DW_CFA_def_cfa_offset:
    2463              :         case DW_CFA_def_cfa_offset_sf:
    2464              :         case DW_CFA_def_cfa_register:
    2465              :         case DW_CFA_def_cfa:
    2466              :         case DW_CFA_def_cfa_sf:
    2467              :         case DW_CFA_def_cfa_expression:
    2468              :         case DW_CFA_restore_state:
    2469              :           return true;
    2470              :         default:
    2471              :           return false;
    2472              :         }
    2473              :     }
    2474              :   return false;
    2475              : }
    2476              : 
    2477              : /* Walk the function, looking for NOTE_INSN_CFI notes.  Add the CFIs to the
    2478              :    function's FDE, adding CFI labels and set_loc/advance_loc opcodes as
    2479              :    necessary.  */
    2480              : static void
    2481      1471310 : add_cfis_to_fde (void)
    2482              : {
    2483      1471310 :   dw_fde_ref fde = cfun->fde;
    2484      1471310 :   rtx_insn *insn, *next;
    2485              : 
    2486    209975248 :   for (insn = get_insns (); insn; insn = next)
    2487              :     {
    2488    208503938 :       next = NEXT_INSN (insn);
    2489              : 
    2490    208503938 :       if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
    2491       117516 :         fde->dw_fde_switch_cfi_index = vec_safe_length (fde->dw_fde_cfi);
    2492              : 
    2493    208503938 :       if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_CFI)
    2494              :         {
    2495      8508795 :           bool required = cfi_label_required_p (NOTE_CFI (insn));
    2496     23983327 :           while (next)
    2497     15473678 :             if (NOTE_P (next) && NOTE_KIND (next) == NOTE_INSN_CFI)
    2498              :               {
    2499      3386887 :                 required |= cfi_label_required_p (NOTE_CFI (next));
    2500      3386887 :                 next = NEXT_INSN (next);
    2501              :               }
    2502     12086791 :             else if (active_insn_p (next)
    2503     12086791 :                      || (NOTE_P (next) && (NOTE_KIND (next)
    2504              :                                            == NOTE_INSN_SWITCH_TEXT_SECTIONS)))
    2505              :               break;
    2506              :             else
    2507      3578850 :               next = NEXT_INSN (next);
    2508      8508795 :           if (required)
    2509              :             {
    2510         5726 :               int num = dwarf2out_cfi_label_num;
    2511         5726 :               const char *label = dwarf2out_cfi_label ();
    2512         5726 :               dw_cfi_ref xcfi;
    2513              : 
    2514              :               /* Set the location counter to the new label.  */
    2515         5726 :               xcfi = new_cfi ();
    2516         5726 :               xcfi->dw_cfi_opc = DW_CFA_advance_loc4;
    2517         5726 :               xcfi->dw_cfi_oprnd1.dw_cfi_addr = label;
    2518         5726 :               vec_safe_push (fde->dw_fde_cfi, xcfi);
    2519              : 
    2520         5726 :               rtx_note *tmp = emit_note_before (NOTE_INSN_CFI_LABEL, insn);
    2521         5726 :               NOTE_LABEL_NUMBER (tmp) = num;
    2522              :             }
    2523              : 
    2524     15474532 :           do
    2525              :             {
    2526     15474532 :               if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_CFI)
    2527     11895682 :                 vec_safe_push (fde->dw_fde_cfi, NOTE_CFI (insn));
    2528     15474532 :               insn = NEXT_INSN (insn);
    2529              :             }
    2530     15474532 :           while (insn != next);
    2531              :         }
    2532              :     }
    2533      1471310 : }
    2534              : 
    2535              : static void dump_cfi_row (FILE *f, dw_cfi_row *row);
    2536              : 
    2537              : /* If LABEL is the start of a trace, then initialize the state of that
    2538              :    trace from CUR_TRACE and CUR_ROW.  */
    2539              : 
    2540              : static void
    2541     16258850 : maybe_record_trace_start (rtx_insn *start, rtx_insn *origin)
    2542              : {
    2543     16258850 :   dw_trace_info *ti;
    2544              : 
    2545     16258850 :   ti = get_trace_info (start);
    2546     16258850 :   gcc_assert (ti != NULL);
    2547              : 
    2548     16258850 :   if (dump_file)
    2549              :     {
    2550          595 :       fprintf (dump_file, "   saw edge from trace %u to %u (via %s %d)\n",
    2551              :                cur_trace->id, ti->id,
    2552          176 :                (origin ? rtx_name[(int) GET_CODE (origin)] : "fallthru"),
    2553          176 :                (origin ? INSN_UID (origin) : 0));
    2554              :     }
    2555              : 
    2556     16258850 :   poly_int64 args_size = cur_trace->end_true_args_size;
    2557     16258850 :   if (ti->beg_row == NULL)
    2558              :     {
    2559              :       /* This is the first time we've encountered this trace.  Propagate
    2560              :          state across the edge and push the trace onto the work list.  */
    2561      9924566 :       ti->beg_row = copy_cfi_row (cur_row);
    2562      9924566 :       ti->beg_true_args_size = args_size;
    2563              : 
    2564      9924566 :       ti->cfa_store = cur_trace->cfa_store;
    2565      9924566 :       ti->cfa_temp = cur_trace->cfa_temp;
    2566      9924566 :       ti->regs_saved_in_regs = cur_trace->regs_saved_in_regs.copy ();
    2567              : 
    2568      9924566 :       trace_work_list.safe_push (ti);
    2569              : 
    2570      9924566 :       if (dump_file)
    2571          301 :         fprintf (dump_file, "\tpush trace %u to worklist\n", ti->id);
    2572              :     }
    2573              :   else
    2574              :     {
    2575              : 
    2576              :       /* We ought to have the same state incoming to a given trace no
    2577              :          matter how we arrive at the trace.  Anything else means we've
    2578              :          got some kind of optimization error.  */
    2579              : #if CHECKING_P
    2580      6334284 :       if (!cfi_row_equal_p (cur_row, ti->beg_row))
    2581              :         {
    2582            0 :           if (dump_file)
    2583              :             {
    2584            0 :               fprintf (dump_file, "Inconsistent CFI state!\n");
    2585            0 :               fprintf (dump_file, "SHOULD have:\n");
    2586            0 :               dump_cfi_row (dump_file, ti->beg_row);
    2587            0 :               fprintf (dump_file, "DO have:\n");
    2588            0 :               dump_cfi_row (dump_file, cur_row);
    2589              :             }
    2590              : 
    2591            0 :           gcc_unreachable ();
    2592              :         }
    2593              : #endif
    2594              : 
    2595              :       /* The args_size is allowed to conflict if it isn't actually used.  */
    2596      6334284 :       if (maybe_ne (ti->beg_true_args_size, args_size))
    2597            0 :         ti->args_size_undefined = true;
    2598              :     }
    2599     16258850 : }
    2600              : 
    2601              : /* Similarly, but handle the args_size and CFA reset across EH
    2602              :    and non-local goto edges.  */
    2603              : 
    2604              : static void
    2605       673690 : maybe_record_trace_start_abnormal (rtx_insn *start, rtx_insn *origin)
    2606              : {
    2607       673690 :   poly_int64 save_args_size, delta;
    2608       673690 :   dw_cfa_location save_cfa;
    2609              : 
    2610       673690 :   save_args_size = cur_trace->end_true_args_size;
    2611       673690 :   if (known_eq (save_args_size, 0))
    2612              :     {
    2613       559404 :       maybe_record_trace_start (start, origin);
    2614       559404 :       return;
    2615              :     }
    2616              : 
    2617       114286 :   delta = -save_args_size;
    2618       114286 :   cur_trace->end_true_args_size = 0;
    2619              : 
    2620       114286 :   save_cfa = cur_row->cfa;
    2621       114286 :   if (cur_row->cfa.reg == dw_stack_pointer_regnum)
    2622              :     {
    2623              :       /* Convert a change in args_size (always a positive in the
    2624              :          direction of stack growth) to a change in stack pointer.  */
    2625            0 :       if (!STACK_GROWS_DOWNWARD)
    2626              :         delta = -delta;
    2627              : 
    2628            0 :       cur_row->cfa.offset += delta;
    2629              :     }
    2630              : 
    2631       114286 :   maybe_record_trace_start (start, origin);
    2632              : 
    2633       114286 :   cur_trace->end_true_args_size = save_args_size;
    2634       114286 :   cur_row->cfa = save_cfa;
    2635              : }
    2636              : 
    2637              : /* Propagate CUR_TRACE state to the destinations implied by INSN.  */
    2638              : /* ??? Sadly, this is in large part a duplicate of make_edges.  */
    2639              : 
    2640              : static void
    2641     93385488 : create_trace_edges (rtx_insn *insn)
    2642              : {
    2643     93385488 :   rtx tmp;
    2644     93385488 :   int i, n;
    2645              : 
    2646     93385488 :   if (JUMP_P (insn))
    2647              :     {
    2648     10369099 :       rtx_jump_table_data *table;
    2649              : 
    2650     10369099 :       if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
    2651          894 :         return;
    2652              : 
    2653     10368205 :       if (tablejump_p (insn, NULL, &table))
    2654              :         {
    2655         8021 :           rtvec vec = table->get_labels ();
    2656              : 
    2657         8021 :           n = GET_NUM_ELEM (vec);
    2658       170372 :           for (i = 0; i < n; ++i)
    2659              :             {
    2660       162351 :               rtx_insn *lab = as_a <rtx_insn *> (XEXP (RTVEC_ELT (vec, i), 0));
    2661       162351 :               maybe_record_trace_start (lab, insn);
    2662              :             }
    2663              : 
    2664              :           /* Handle casesi dispatch insns.  */
    2665         8021 :           if ((tmp = tablejump_casesi_pattern (insn)) != NULL_RTX)
    2666              :             {
    2667            0 :               rtx_insn * lab = label_ref_label (XEXP (SET_SRC (tmp), 2));
    2668            0 :               maybe_record_trace_start (lab, insn);
    2669              :             }
    2670              :         }
    2671     10360184 :       else if (computed_jump_p (insn))
    2672              :         {
    2673              :           rtx_insn *temp;
    2674              :           unsigned int i;
    2675     10370073 :           FOR_EACH_VEC_SAFE_ELT (forced_labels, i, temp)
    2676         1498 :             maybe_record_trace_start (temp, insn);
    2677              :         }
    2678     10359760 :       else if (returnjump_p (insn))
    2679              :         ;
    2680      8754604 :       else if ((tmp = extract_asm_operands (PATTERN (insn))) != NULL)
    2681              :         {
    2682          581 :           n = ASM_OPERANDS_LABEL_LENGTH (tmp);
    2683         1392 :           for (i = 0; i < n; ++i)
    2684              :             {
    2685          811 :               rtx_insn *lab =
    2686          811 :                 as_a <rtx_insn *> (XEXP (ASM_OPERANDS_LABEL (tmp, i), 0));
    2687          811 :               maybe_record_trace_start (lab, insn);
    2688              :             }
    2689              :         }
    2690              :       else
    2691              :         {
    2692      8754023 :           rtx_insn *lab = JUMP_LABEL_AS_INSN (insn);
    2693      8754023 :           gcc_assert (lab != NULL);
    2694      8754023 :           maybe_record_trace_start (lab, insn);
    2695              :         }
    2696              :     }
    2697     83016389 :   else if (CALL_P (insn))
    2698              :     {
    2699              :       /* Sibling calls don't have edges inside this function.  */
    2700      6081041 :       if (SIBLING_CALL_P (insn))
    2701              :         return;
    2702              : 
    2703              :       /* Process non-local goto edges.  */
    2704      5952493 :       if (can_nonlocal_goto (insn))
    2705        38244 :         for (rtx_insn_list *lab = nonlocal_goto_handler_labels;
    2706        38244 :              lab;
    2707        35549 :              lab = lab->next ())
    2708        35549 :           maybe_record_trace_start_abnormal (lab->insn (), insn);
    2709              :     }
    2710     76935348 :   else if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (PATTERN (insn)))
    2711              :     {
    2712            0 :       int i, n = seq->len ();
    2713            0 :       for (i = 0; i < n; ++i)
    2714            0 :         create_trace_edges (seq->insn (i));
    2715              :       return;
    2716              :     }
    2717              : 
    2718              :   /* Process EH edges.  */
    2719     93256046 :   if (CALL_P (insn) || cfun->can_throw_non_call_exceptions)
    2720              :     {
    2721     24968215 :       eh_landing_pad lp = get_eh_landing_pad_from_rtx (insn);
    2722     24968215 :       if (lp)
    2723       638141 :         maybe_record_trace_start_abnormal (lp->landing_pad, insn);
    2724              :     }
    2725              : }
    2726              : 
    2727              : /* A subroutine of scan_trace.  Do what needs to be done "after" INSN.  */
    2728              : 
    2729              : static void
    2730     93385488 : scan_insn_after (rtx_insn *insn)
    2731              : {
    2732     93385488 :   if (RTX_FRAME_RELATED_P (insn))
    2733      5793626 :     dwarf2out_frame_debug (insn);
    2734     93385488 :   notice_args_size (insn);
    2735     93385488 : }
    2736              : 
    2737              : /* Scan the trace beginning at INSN and create the CFI notes for the
    2738              :    instructions therein.  */
    2739              : 
    2740              : static void
    2741     11395876 : scan_trace (dw_trace_info *trace, bool entry)
    2742              : {
    2743     11395876 :   rtx_insn *prev, *insn = trace->head;
    2744     11395876 :   dw_cfa_location this_cfa;
    2745              : 
    2746     11395876 :   if (dump_file)
    2747          770 :     fprintf (dump_file, "Processing trace %u : start at %s %d\n",
    2748          385 :              trace->id, rtx_name[(int) GET_CODE (insn)],
    2749          385 :              INSN_UID (insn));
    2750              : 
    2751     11395876 :   trace->end_row = copy_cfi_row (trace->beg_row);
    2752     11395876 :   trace->end_true_args_size = trace->beg_true_args_size;
    2753              : 
    2754     11395876 :   cur_trace = trace;
    2755     11395876 :   cur_row = trace->end_row;
    2756              : 
    2757     11395876 :   this_cfa = cur_row->cfa;
    2758     11395876 :   cur_cfa = &this_cfa;
    2759              : 
    2760              :   /* If the current function starts with a non-standard incoming frame
    2761              :      sp offset, emit a note before the first instruction.  */
    2762     11395876 :   if (entry
    2763      2942556 :       && DEFAULT_INCOMING_FRAME_SP_OFFSET != INCOMING_FRAME_SP_OFFSET)
    2764              :     {
    2765           64 :       add_cfi_insn = insn;
    2766           64 :       gcc_assert (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_DELETED);
    2767           64 :       this_cfa.offset = INCOMING_FRAME_SP_OFFSET;
    2768           64 :       def_cfa_1 (&this_cfa);
    2769              :     }
    2770              : 
    2771     11395876 :   for (prev = insn, insn = NEXT_INSN (insn);
    2772    190348154 :        insn;
    2773    178952278 :        prev = insn, insn = NEXT_INSN (insn))
    2774              :     {
    2775    190348115 :       rtx_insn *control;
    2776              : 
    2777              :       /* Do everything that happens "before" the insn.  */
    2778    190348115 :       add_cfi_insn = prev;
    2779              : 
    2780              :       /* Notice the end of a trace.  */
    2781    190348115 :       if (BARRIER_P (insn))
    2782              :         {
    2783              :           /* Don't bother saving the unneeded queued registers at all.  */
    2784      4729360 :           queued_reg_saves.truncate (0);
    2785      4729360 :           break;
    2786              :         }
    2787    185618755 :       if (save_point_p (insn))
    2788              :         {
    2789              :           /* Propagate across fallthru edges.  */
    2790      6666477 :           dwarf2out_flush_queued_reg_saves ();
    2791      6666477 :           maybe_record_trace_start (insn, NULL);
    2792      6666477 :           break;
    2793              :         }
    2794              : 
    2795    178952278 :       if (DEBUG_INSN_P (insn) || !inside_basic_block_p (insn))
    2796     85566790 :         continue;
    2797              : 
    2798              :       /* Handle all changes to the row state.  Sequences require special
    2799              :          handling for the positioning of the notes.  */
    2800     93385488 :       if (rtx_sequence *pat = dyn_cast <rtx_sequence *> (PATTERN (insn)))
    2801              :         {
    2802            0 :           rtx_insn *elt;
    2803            0 :           int i, n = pat->len ();
    2804              : 
    2805            0 :           control = pat->insn (0);
    2806            0 :           if (can_throw_internal (control))
    2807            0 :             notice_eh_throw (control);
    2808            0 :           dwarf2out_flush_queued_reg_saves ();
    2809              : 
    2810            0 :           if (JUMP_P (control) && INSN_ANNULLED_BRANCH_P (control))
    2811              :             {
    2812              :               /* ??? Hopefully multiple delay slots are not annulled.  */
    2813            0 :               gcc_assert (n == 2);
    2814            0 :               gcc_assert (!RTX_FRAME_RELATED_P (control));
    2815            0 :               gcc_assert (!find_reg_note (control, REG_ARGS_SIZE, NULL));
    2816              : 
    2817            0 :               elt = pat->insn (1);
    2818              : 
    2819            0 :               if (INSN_FROM_TARGET_P (elt))
    2820              :                 {
    2821            0 :                   cfi_vec save_row_reg_save;
    2822              : 
    2823              :                   /* If ELT is an instruction from target of an annulled
    2824              :                      branch, the effects are for the target only and so
    2825              :                      the args_size and CFA along the current path
    2826              :                      shouldn't change.  */
    2827            0 :                   add_cfi_insn = NULL;
    2828            0 :                   poly_int64 restore_args_size = cur_trace->end_true_args_size;
    2829            0 :                   cur_cfa = &cur_row->cfa;
    2830            0 :                   save_row_reg_save = vec_safe_copy (cur_row->reg_save);
    2831              : 
    2832            0 :                   scan_insn_after (elt);
    2833              : 
    2834              :                   /* ??? Should we instead save the entire row state?  */
    2835            0 :                   gcc_assert (!queued_reg_saves.length ());
    2836              : 
    2837            0 :                   create_trace_edges (control);
    2838              : 
    2839            0 :                   cur_trace->end_true_args_size = restore_args_size;
    2840            0 :                   cur_row->cfa = this_cfa;
    2841            0 :                   cur_row->reg_save = save_row_reg_save;
    2842            0 :                   cur_cfa = &this_cfa;
    2843              :                 }
    2844              :               else
    2845              :                 {
    2846              :                   /* If ELT is a annulled branch-taken instruction (i.e.
    2847              :                      executed only when branch is not taken), the args_size
    2848              :                      and CFA should not change through the jump.  */
    2849            0 :                   create_trace_edges (control);
    2850              : 
    2851              :                   /* Update and continue with the trace.  */
    2852            0 :                   add_cfi_insn = insn;
    2853            0 :                   scan_insn_after (elt);
    2854            0 :                   def_cfa_1 (&this_cfa);
    2855              :                 }
    2856            0 :               continue;
    2857            0 :             }
    2858              : 
    2859              :           /* The insns in the delay slot should all be considered to happen
    2860              :              "before" a call insn.  Consider a call with a stack pointer
    2861              :              adjustment in the delay slot.  The backtrace from the callee
    2862              :              should include the sp adjustment.  Unfortunately, that leaves
    2863              :              us with an unavoidable unwinding error exactly at the call insn
    2864              :              itself.  For jump insns we'd prefer to avoid this error by
    2865              :              placing the notes after the sequence.  */
    2866            0 :           if (JUMP_P (control))
    2867            0 :             add_cfi_insn = insn;
    2868              : 
    2869            0 :           for (i = 1; i < n; ++i)
    2870              :             {
    2871            0 :               elt = pat->insn (i);
    2872            0 :               scan_insn_after (elt);
    2873              :             }
    2874              : 
    2875              :           /* Make sure any register saves are visible at the jump target.  */
    2876            0 :           dwarf2out_flush_queued_reg_saves ();
    2877            0 :           any_cfis_emitted = false;
    2878              : 
    2879              :           /* However, if there is some adjustment on the call itself, e.g.
    2880              :              a call_pop, that action should be considered to happen after
    2881              :              the call returns.  */
    2882            0 :           add_cfi_insn = insn;
    2883            0 :           scan_insn_after (control);
    2884              :         }
    2885              :       else
    2886              :         {
    2887              :           /* Flush data before calls and jumps, and of course if necessary.  */
    2888     93385488 :           if (can_throw_internal (insn))
    2889              :             {
    2890       638141 :               notice_eh_throw (insn);
    2891       638141 :               dwarf2out_flush_queued_reg_saves ();
    2892              :             }
    2893     92747347 :           else if (!NONJUMP_INSN_P (insn)
    2894     76827763 :                    || clobbers_queued_reg_save (insn)
    2895    169441647 :                    || find_reg_note (insn, REG_CFA_FLUSH_QUEUE, NULL))
    2896     16080288 :             dwarf2out_flush_queued_reg_saves ();
    2897     93385488 :           any_cfis_emitted = false;
    2898              : 
    2899     93385488 :           add_cfi_insn = insn;
    2900     93385488 :           scan_insn_after (insn);
    2901     93385488 :           control = insn;
    2902              :         }
    2903              : 
    2904              :       /* Between frame-related-p and args_size we might have otherwise
    2905              :          emitted two cfa adjustments.  Do it now.  */
    2906     93385488 :       def_cfa_1 (&this_cfa);
    2907              : 
    2908              :       /* Minimize the number of advances by emitting the entire queue
    2909              :          once anything is emitted.  */
    2910     93385488 :       if (any_cfis_emitted
    2911     93385488 :           || find_reg_note (insn, REG_CFA_FLUSH_QUEUE, NULL))
    2912      7384637 :         dwarf2out_flush_queued_reg_saves ();
    2913              : 
    2914              :       /* Note that a test for control_flow_insn_p does exactly the
    2915              :          same tests as are done to actually create the edges.  So
    2916              :          always call the routine and let it not create edges for
    2917              :          non-control-flow insns.  */
    2918     93385488 :       create_trace_edges (control);
    2919              :     }
    2920              : 
    2921     11395876 :   gcc_assert (!cfun->fde || !cfun->fde->rule18);
    2922     11395876 :   add_cfi_insn = NULL;
    2923     11395876 :   cur_row = NULL;
    2924     11395876 :   cur_trace = NULL;
    2925     11395876 :   cur_cfa = NULL;
    2926     11395876 : }
    2927              : 
    2928              : /* Scan the function and create the initial set of CFI notes.  */
    2929              : 
    2930              : static void
    2931      1471310 : create_cfi_notes (void)
    2932              : {
    2933      1471310 :   dw_trace_info *ti;
    2934              : 
    2935      1471310 :   gcc_checking_assert (!queued_reg_saves.exists ());
    2936      1471310 :   gcc_checking_assert (!trace_work_list.exists ());
    2937              : 
    2938              :   /* Always begin at the entry trace.  */
    2939      1471310 :   ti = &trace_info[0];
    2940      1471310 :   scan_trace (ti, true);
    2941              : 
    2942     12867186 :   while (!trace_work_list.is_empty ())
    2943              :     {
    2944      9924566 :       ti = trace_work_list.pop ();
    2945      9924566 :       scan_trace (ti, false);
    2946              :     }
    2947              : 
    2948      1471310 :   queued_reg_saves.release ();
    2949      1471310 :   trace_work_list.release ();
    2950      1471310 : }
    2951              : 
    2952              : /* Return the insn before the first NOTE_INSN_CFI after START.  */
    2953              : 
    2954              : static rtx_insn *
    2955       424774 : before_next_cfi_note (rtx_insn *start)
    2956              : {
    2957       424774 :   rtx_insn *prev = start;
    2958      1990859 :   while (start)
    2959              :     {
    2960      1990859 :       if (NOTE_P (start) && NOTE_KIND (start) == NOTE_INSN_CFI)
    2961       424774 :         return prev;
    2962      1566085 :       prev = start;
    2963      1566085 :       start = NEXT_INSN (start);
    2964              :     }
    2965            0 :   gcc_unreachable ();
    2966              : }
    2967              : 
    2968              : /* Insert CFI notes between traces to properly change state between them.  */
    2969              : 
    2970              : static void
    2971      1471310 : connect_traces (void)
    2972              : {
    2973      1471310 :   unsigned i, n;
    2974      1471310 :   dw_trace_info *prev_ti, *ti;
    2975              : 
    2976              :   /* ??? Ideally, we should have both queued and processed every trace.
    2977              :      However the current representation of constant pools on various targets
    2978              :      is indistinguishable from unreachable code.  Assume for the moment that
    2979              :      we can simply skip over such traces.  */
    2980              :   /* ??? Consider creating a DATA_INSN rtx code to indicate that
    2981              :      these are not "real" instructions, and should not be considered.
    2982              :      This could be generically useful for tablejump data as well.  */
    2983              :   /* Remove all unprocessed traces from the list.  */
    2984      1471310 :   unsigned ix, ix2;
    2985     11395877 :   VEC_ORDERED_REMOVE_IF_FROM_TO (trace_info, ix, ix2, ti, 1,
    2986              :                                  trace_info.length (), ti->beg_row == NULL);
    2987     12867186 :   FOR_EACH_VEC_ELT (trace_info, ix, ti)
    2988     11395876 :     gcc_assert (ti->end_row != NULL);
    2989              : 
    2990              :   /* Work from the end back to the beginning.  This lets us easily insert
    2991              :      remember/restore_state notes in the correct order wrt other notes.  */
    2992      1471310 :   n = trace_info.length ();
    2993      1471310 :   prev_ti = &trace_info[n - 1];
    2994     11395876 :   for (i = n - 1; i > 0; --i)
    2995              :     {
    2996      9924566 :       dw_cfi_row *old_row;
    2997              : 
    2998      9924566 :       ti = prev_ti;
    2999      9924566 :       prev_ti = &trace_info[i - 1];
    3000              : 
    3001      9924566 :       add_cfi_insn = ti->head;
    3002              : 
    3003              :       /* In dwarf2out_switch_text_section, we'll begin a new FDE
    3004              :          for the portion of the function in the alternate text
    3005              :          section.  The row state at the very beginning of that
    3006              :          new FDE will be exactly the row state from the CIE.  */
    3007      9924566 :       if (ti->switch_sections)
    3008        64340 :         old_row = cie_cfi_row;
    3009              :       else
    3010              :         {
    3011      9860226 :           old_row = prev_ti->end_row;
    3012              :           /* If there's no change from the previous end state, fine.  */
    3013      9860226 :           if (cfi_row_equal_p (old_row, ti->beg_row))
    3014              :             ;
    3015              :           /* Otherwise check for the common case of sharing state with
    3016              :              the beginning of an epilogue, but not the end.  Insert
    3017              :              remember/restore opcodes in that case.  */
    3018       668654 :           else if (cfi_row_equal_p (prev_ti->beg_row, ti->beg_row))
    3019              :             {
    3020       424774 :               dw_cfi_ref cfi;
    3021              : 
    3022              :               /* Note that if we blindly insert the remember at the
    3023              :                  start of the trace, we can wind up increasing the
    3024              :                  size of the unwind info due to extra advance opcodes.
    3025              :                  Instead, put the remember immediately before the next
    3026              :                  state change.  We know there must be one, because the
    3027              :                  state at the beginning and head of the trace differ.  */
    3028       424774 :               add_cfi_insn = before_next_cfi_note (prev_ti->head);
    3029       424774 :               cfi = new_cfi ();
    3030       424774 :               cfi->dw_cfi_opc = DW_CFA_remember_state;
    3031       424774 :               add_cfi (cfi);
    3032              : 
    3033       424774 :               add_cfi_insn = ti->head;
    3034       424774 :               cfi = new_cfi ();
    3035       424774 :               cfi->dw_cfi_opc = DW_CFA_restore_state;
    3036       424774 :               add_cfi (cfi);
    3037              : 
    3038              :               /* If the target unwinder does not save the CFA as part of the
    3039              :                  register state, we need to restore it separately.  */
    3040       424774 :               if (targetm.asm_out.should_restore_cfa_state ()
    3041       424774 :                   && (cfi = def_cfa_0 (&old_row->cfa, &ti->beg_row->cfa)))
    3042            0 :                 add_cfi (cfi);
    3043              : 
    3044       424774 :               old_row = prev_ti->beg_row;
    3045              :             }
    3046              :           /* Otherwise, we'll simply change state from the previous end.  */
    3047              :         }
    3048              : 
    3049      9924566 :       change_cfi_row (old_row, ti->beg_row);
    3050              : 
    3051      9924566 :       if (dump_file && add_cfi_insn != ti->head)
    3052              :         {
    3053           16 :           rtx_insn *note;
    3054              : 
    3055           16 :           fprintf (dump_file, "Fixup between trace %u and %u:\n",
    3056              :                    prev_ti->id, ti->id);
    3057              : 
    3058           16 :           note = ti->head;
    3059           26 :           do
    3060              :             {
    3061           26 :               note = NEXT_INSN (note);
    3062           26 :               gcc_assert (NOTE_P (note) && NOTE_KIND (note) == NOTE_INSN_CFI);
    3063           26 :               output_cfi_directive (dump_file, NOTE_CFI (note));
    3064              :             }
    3065           26 :           while (note != add_cfi_insn);
    3066              :         }
    3067              :     }
    3068              : 
    3069              :   /* Connect args_size between traces that have can_throw_internal insns.  */
    3070      1471310 :   if (cfun->eh->lp_array)
    3071              :     {
    3072              :       poly_int64 prev_args_size = 0;
    3073              : 
    3074     12867186 :       for (i = 0; i < n; ++i)
    3075              :         {
    3076     11395876 :           ti = &trace_info[i];
    3077              : 
    3078     11395876 :           if (ti->switch_sections)
    3079        64340 :             prev_args_size = 0;
    3080              : 
    3081     11395876 :           if (ti->eh_head == NULL)
    3082     11023396 :             continue;
    3083              : 
    3084              :           /* We require either the incoming args_size values to match or the
    3085              :              presence of an insn setting it before the first EH insn.  */
    3086       372480 :           gcc_assert (!ti->args_size_undefined || ti->args_size_defined_for_eh);
    3087              : 
    3088              :           /* In the latter case, we force the creation of a CFI note.  */
    3089       372480 :           if (ti->args_size_undefined
    3090       372480 :               || maybe_ne (ti->beg_delay_args_size, prev_args_size))
    3091              :             {
    3092              :               /* ??? Search back to previous CFI note.  */
    3093        47613 :               add_cfi_insn = PREV_INSN (ti->eh_head);
    3094        47613 :               add_cfi_args_size (ti->beg_delay_args_size);
    3095              :             }
    3096              : 
    3097       372480 :           prev_args_size = ti->end_delay_args_size;
    3098              :         }
    3099              :     }
    3100      1471310 : }
    3101              : 
    3102              : /* Set up the pseudo-cfg of instruction traces, as described at the
    3103              :    block comment at the top of the file.  */
    3104              : 
    3105              : static void
    3106      1471310 : create_pseudo_cfg (void)
    3107              : {
    3108      1471310 :   bool saw_barrier, switch_sections;
    3109      1471310 :   dw_trace_info ti;
    3110      1471310 :   rtx_insn *insn;
    3111      1471310 :   unsigned i;
    3112              : 
    3113              :   /* The first trace begins at the start of the function,
    3114              :      and begins with the CIE row state.  */
    3115      1471310 :   trace_info.create (16);
    3116      1471310 :   memset (&ti, 0, sizeof (ti));
    3117      1471310 :   ti.head = get_insns ();
    3118      1471310 :   ti.beg_row = cie_cfi_row;
    3119      1471310 :   ti.cfa_store = cie_cfi_row->cfa;
    3120      1471310 :   ti.cfa_temp.reg.set_by_dwreg (INVALID_REGNUM);
    3121      1471310 :   trace_info.quick_push (ti);
    3122              : 
    3123      1471310 :   if (cie_return_save)
    3124            0 :     ti.regs_saved_in_regs.safe_push (*cie_return_save);
    3125              : 
    3126              :   /* Walk all the insns, collecting start of trace locations.  */
    3127      1471310 :   saw_barrier = false;
    3128      1471310 :   switch_sections = false;
    3129    205045303 :   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
    3130              :     {
    3131    203573993 :       if (BARRIER_P (insn))
    3132              :         saw_barrier = true;
    3133    198837590 :       else if (NOTE_P (insn)
    3134     98506702 :                && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
    3135              :         {
    3136              :           /* We should have just seen a barrier.  */
    3137        64340 :           gcc_assert (saw_barrier);
    3138              :           switch_sections = true;
    3139              :         }
    3140              :       /* Watch out for save_point notes between basic blocks.
    3141              :          In particular, a note after a barrier.  Do not record these,
    3142              :          delaying trace creation until the label.  */
    3143    198773250 :       else if (save_point_p (insn)
    3144    198773250 :                && (LABEL_P (insn) || !saw_barrier))
    3145              :         {
    3146      9924567 :           memset (&ti, 0, sizeof (ti));
    3147      9924567 :           ti.head = insn;
    3148      9924567 :           ti.switch_sections = switch_sections;
    3149      9924567 :           ti.id = trace_info.length ();
    3150      9924567 :           trace_info.safe_push (ti);
    3151              : 
    3152      9924567 :           saw_barrier = false;
    3153      9924567 :           switch_sections = false;
    3154              :         }
    3155              :     }
    3156              : 
    3157              :   /* Create the trace index after we've finished building trace_info,
    3158              :      avoiding stale pointer problems due to reallocation.  */
    3159      1471310 :   trace_index
    3160      2942620 :     = new hash_table<trace_info_hasher> (trace_info.length ());
    3161      1471310 :   dw_trace_info *tp;
    3162     12867187 :   FOR_EACH_VEC_ELT (trace_info, i, tp)
    3163              :     {
    3164     11395877 :       dw_trace_info **slot;
    3165              : 
    3166     11395877 :       if (dump_file)
    3167          770 :         fprintf (dump_file, "Creating trace %u : start at %s %d%s\n", tp->id,
    3168          385 :                  rtx_name[(int) GET_CODE (tp->head)], INSN_UID (tp->head),
    3169          385 :                  tp->switch_sections ? " (section switch)" : "");
    3170              : 
    3171     11395877 :       slot = trace_index->find_slot_with_hash (tp, INSN_UID (tp->head), INSERT);
    3172     11395877 :       gcc_assert (*slot == NULL);
    3173     11395877 :       *slot = tp;
    3174              :     }
    3175      1471310 : }
    3176              : 
    3177              : /* Record the initial position of the return address.  RTL is
    3178              :    INCOMING_RETURN_ADDR_RTX.  */
    3179              : 
    3180              : static void
    3181       209004 : initial_return_save (rtx rtl)
    3182              : {
    3183       209004 :   struct cfa_reg reg;
    3184       209004 :   reg.set_by_dwreg (INVALID_REGNUM);
    3185       209004 :   poly_int64 offset = 0;
    3186              : 
    3187       209004 :   switch (GET_CODE (rtl))
    3188              :     {
    3189            0 :     case REG:
    3190              :       /* RA is in a register.  */
    3191            0 :       reg = dwf_cfa_reg (rtl);
    3192            0 :       break;
    3193              : 
    3194       209004 :     case MEM:
    3195              :       /* RA is on the stack.  */
    3196       209004 :       rtl = XEXP (rtl, 0);
    3197       209004 :       switch (GET_CODE (rtl))
    3198              :         {
    3199       209004 :         case REG:
    3200       209004 :           gcc_assert (REGNO (rtl) == STACK_POINTER_REGNUM);
    3201              :           offset = 0;
    3202              :           break;
    3203              : 
    3204            0 :         case PLUS:
    3205            0 :           gcc_assert (REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM);
    3206            0 :           offset = rtx_to_poly_int64 (XEXP (rtl, 1));
    3207            0 :           break;
    3208              : 
    3209            0 :         case MINUS:
    3210            0 :           gcc_assert (REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM);
    3211            0 :           offset = -rtx_to_poly_int64 (XEXP (rtl, 1));
    3212            0 :           break;
    3213              : 
    3214            0 :         default:
    3215            0 :           gcc_unreachable ();
    3216              :         }
    3217              : 
    3218              :       break;
    3219              : 
    3220            0 :     case PLUS:
    3221              :       /* The return address is at some offset from any value we can
    3222              :          actually load.  For instance, on the SPARC it is in %i7+8. Just
    3223              :          ignore the offset for now; it doesn't matter for unwinding frames.  */
    3224            0 :       gcc_assert (CONST_INT_P (XEXP (rtl, 1)));
    3225            0 :       initial_return_save (XEXP (rtl, 0));
    3226              :       return;
    3227              : 
    3228            0 :     default:
    3229            0 :       gcc_unreachable ();
    3230              :     }
    3231              : 
    3232       214524 :   if (reg.reg != DWARF_FRAME_RETURN_COLUMN)
    3233              :     {
    3234       209004 :       if (reg.reg != INVALID_REGNUM)
    3235            0 :         record_reg_saved_in_reg (rtl, pc_rtx);
    3236       214524 :       reg_save (DWARF_FRAME_RETURN_COLUMN, reg, offset - cur_row->cfa.offset);
    3237              :     }
    3238              : }
    3239              : 
    3240              : static void
    3241       209004 : create_cie_data (void)
    3242              : {
    3243       209004 :   dw_cfa_location loc;
    3244       209004 :   dw_trace_info cie_trace;
    3245              : 
    3246       209004 :   dw_stack_pointer_regnum = dwf_cfa_reg (stack_pointer_rtx);
    3247              : 
    3248       209004 :   memset (&cie_trace, 0, sizeof (cie_trace));
    3249       209004 :   cur_trace = &cie_trace;
    3250              : 
    3251       209004 :   add_cfi_vec = &cie_cfi_vec;
    3252       209004 :   cie_cfi_row = cur_row = new_cfi_row ();
    3253              : 
    3254              :   /* On entry, the Canonical Frame Address is at SP.  */
    3255       209004 :   memset (&loc, 0, sizeof (loc));
    3256       209004 :   loc.reg = dw_stack_pointer_regnum;
    3257              :   /* create_cie_data is called just once per TU, and when using .cfi_startproc
    3258              :      is even done by the assembler rather than the compiler.  If the target
    3259              :      has different incoming frame sp offsets depending on what kind of
    3260              :      function it is, use a single constant offset for the target and
    3261              :      if needed, adjust before the first instruction in insn stream.  */
    3262       214524 :   loc.offset = DEFAULT_INCOMING_FRAME_SP_OFFSET;
    3263       209004 :   def_cfa_1 (&loc);
    3264              : 
    3265       209004 :   if (targetm.debug_unwind_info () == UI_DWARF2
    3266       209004 :       || targetm_common.except_unwind_info (&global_options) == UI_DWARF2)
    3267              :     {
    3268       214589 :       initial_return_save (INCOMING_RETURN_ADDR_RTX);
    3269              : 
    3270              :       /* For a few targets, we have the return address incoming into a
    3271              :          register, but choose a different return column.  This will result
    3272              :          in a DW_CFA_register for the return, and an entry in
    3273              :          regs_saved_in_regs to match.  If the target later stores that
    3274              :          return address register to the stack, we want to be able to emit
    3275              :          the DW_CFA_offset against the return column, not the intermediate
    3276              :          save register.  Save the contents of regs_saved_in_regs so that
    3277              :          we can re-initialize it at the start of each function.  */
    3278       209004 :       switch (cie_trace.regs_saved_in_regs.length ())
    3279              :         {
    3280              :         case 0:
    3281              :           break;
    3282            0 :         case 1:
    3283            0 :           cie_return_save = ggc_alloc<reg_saved_in_data> ();
    3284            0 :           *cie_return_save = cie_trace.regs_saved_in_regs[0];
    3285            0 :           cie_trace.regs_saved_in_regs.release ();
    3286            0 :           break;
    3287            0 :         default:
    3288            0 :           gcc_unreachable ();
    3289              :         }
    3290              :     }
    3291              : 
    3292       209004 :   add_cfi_vec = NULL;
    3293       209004 :   cur_row = NULL;
    3294       209004 :   cur_trace = NULL;
    3295       209004 : }
    3296              : 
    3297              : /* Annotate the function with NOTE_INSN_CFI notes to record the CFI
    3298              :    state at each location within the function.  These notes will be
    3299              :    emitted during pass_final.  */
    3300              : 
    3301              : static void
    3302      1471310 : execute_dwarf2_frame (void)
    3303              : {
    3304              :   /* Different HARD_FRAME_POINTER_REGNUM might coexist in the same file.  */
    3305      1471310 :   dw_frame_pointer_regnum = dwf_cfa_reg (hard_frame_pointer_rtx);
    3306              : 
    3307              :   /* The first time we're called, compute the incoming frame state.  */
    3308      1471310 :   if (cie_cfi_vec == NULL)
    3309       209004 :     create_cie_data ();
    3310              : 
    3311      1471310 :   dwarf2out_alloc_current_fde ();
    3312              : 
    3313      1471310 :   create_pseudo_cfg ();
    3314              : 
    3315              :   /* Do the work.  */
    3316      1471310 :   create_cfi_notes ();
    3317      1471310 :   connect_traces ();
    3318      1471310 :   add_cfis_to_fde ();
    3319              : 
    3320              :   /* Free all the data we allocated.  */
    3321      1471310 :   {
    3322      1471310 :     size_t i;
    3323      1471310 :     dw_trace_info *ti;
    3324              : 
    3325     14338496 :     FOR_EACH_VEC_ELT (trace_info, i, ti)
    3326     11395876 :       ti->regs_saved_in_regs.release ();
    3327              :   }
    3328      1471310 :   trace_info.release ();
    3329              : 
    3330      1471310 :   delete trace_index;
    3331      1471310 :   trace_index = NULL;
    3332      1471310 : }
    3333              : 
    3334              : /* Convert a DWARF call frame info. operation to its string name */
    3335              : 
    3336              : static const char *
    3337          225 : dwarf_cfi_name (unsigned int cfi_opc)
    3338              : {
    3339            0 :   const char *name = get_DW_CFA_name (cfi_opc);
    3340              : 
    3341          225 :   if (name != NULL)
    3342          225 :     return name;
    3343              : 
    3344              :   return "DW_CFA_<unknown>";
    3345              : }
    3346              : 
    3347              : /* This routine will generate the correct assembly data for a location
    3348              :    description based on a cfi entry with a complex address.  */
    3349              : 
    3350              : static void
    3351            0 : output_cfa_loc (dw_cfi_ref cfi, int for_eh)
    3352              : {
    3353            0 :   dw_loc_descr_ref loc;
    3354            0 :   unsigned long size;
    3355              : 
    3356            0 :   if (cfi->dw_cfi_opc == DW_CFA_expression
    3357            0 :       || cfi->dw_cfi_opc == DW_CFA_val_expression)
    3358              :     {
    3359            0 :       unsigned r =
    3360              :         DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
    3361            0 :       dw2_asm_output_data (1, r, NULL);
    3362            0 :       loc = cfi->dw_cfi_oprnd2.dw_cfi_loc;
    3363            0 :     }
    3364              :   else
    3365            0 :     loc = cfi->dw_cfi_oprnd1.dw_cfi_loc;
    3366              : 
    3367              :   /* Output the size of the block.  */
    3368            0 :   size = size_of_locs (loc);
    3369            0 :   dw2_asm_output_data_uleb128 (size, NULL);
    3370              : 
    3371              :   /* Now output the operations themselves.  */
    3372            0 :   output_loc_sequence (loc, for_eh);
    3373            0 : }
    3374              : 
    3375              : /* Similar, but used for .cfi_escape.  */
    3376              : 
    3377              : static void
    3378        55260 : output_cfa_loc_raw (dw_cfi_ref cfi)
    3379              : {
    3380        55260 :   dw_loc_descr_ref loc;
    3381        55260 :   unsigned long size;
    3382              : 
    3383        55260 :   if (cfi->dw_cfi_opc == DW_CFA_expression
    3384         8949 :       || cfi->dw_cfi_opc == DW_CFA_val_expression)
    3385              :     {
    3386        46311 :       unsigned r =
    3387              :         DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
    3388        46311 :       fprintf (asm_out_file, "%#x,", r);
    3389        46311 :       loc = cfi->dw_cfi_oprnd2.dw_cfi_loc;
    3390        46311 :     }
    3391              :   else
    3392         8949 :     loc = cfi->dw_cfi_oprnd1.dw_cfi_loc;
    3393              : 
    3394              :   /* Output the size of the block.  */
    3395        55260 :   size = size_of_locs (loc);
    3396        55260 :   dw2_asm_output_data_uleb128_raw (size);
    3397        55260 :   fputc (',', asm_out_file);
    3398              : 
    3399              :   /* Now output the operations themselves.  */
    3400        55260 :   output_loc_sequence_raw (loc);
    3401        55260 : }
    3402              : 
    3403              : /* Output a Call Frame Information opcode and its operand(s).  */
    3404              : 
    3405              : void
    3406          266 : output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
    3407              : {
    3408          266 :   unsigned long r;
    3409          266 :   HOST_WIDE_INT off;
    3410              : 
    3411          266 :   if (cfi->dw_cfi_opc == DW_CFA_advance_loc)
    3412            0 :     dw2_asm_output_data (1, (cfi->dw_cfi_opc
    3413            0 :                              | (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f)),
    3414              :                          "DW_CFA_advance_loc " HOST_WIDE_INT_PRINT_HEX,
    3415              :                          ((unsigned HOST_WIDE_INT)
    3416            0 :                           cfi->dw_cfi_oprnd1.dw_cfi_offset));
    3417          266 :   else if (cfi->dw_cfi_opc == DW_CFA_offset)
    3418              :     {
    3419           41 :       r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
    3420           41 :       dw2_asm_output_data (1, (cfi->dw_cfi_opc | (r & 0x3f)),
    3421              :                            "DW_CFA_offset, column %#lx", r);
    3422           41 :       off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
    3423           41 :       dw2_asm_output_data_uleb128 (off, NULL);
    3424              :     }
    3425          225 :   else if (cfi->dw_cfi_opc == DW_CFA_restore)
    3426              :     {
    3427            0 :       r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
    3428            0 :       dw2_asm_output_data (1, (cfi->dw_cfi_opc | (r & 0x3f)),
    3429              :                            "DW_CFA_restore, column %#lx", r);
    3430              :     }
    3431              :   else
    3432              :     {
    3433          450 :       dw2_asm_output_data (1, cfi->dw_cfi_opc,
    3434              :                            "%s", dwarf_cfi_name (cfi->dw_cfi_opc));
    3435              : 
    3436          225 :       switch (cfi->dw_cfi_opc)
    3437              :         {
    3438            0 :         case DW_CFA_set_loc:
    3439            0 :           if (for_eh)
    3440            0 :             dw2_asm_output_encoded_addr_rtx (
    3441              :                 ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0),
    3442            0 :                 gen_rtx_SYMBOL_REF (Pmode, cfi->dw_cfi_oprnd1.dw_cfi_addr),
    3443              :                 false, NULL);
    3444              :           else
    3445            0 :             dw2_asm_output_addr (DWARF2_ADDR_SIZE,
    3446              :                                  cfi->dw_cfi_oprnd1.dw_cfi_addr, NULL);
    3447            0 :           fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
    3448            0 :           break;
    3449              : 
    3450            0 :         case DW_CFA_advance_loc1:
    3451            0 :           dw2_asm_output_delta (1, cfi->dw_cfi_oprnd1.dw_cfi_addr,
    3452              :                                 fde->dw_fde_current_label, NULL);
    3453            0 :           fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
    3454            0 :           break;
    3455              : 
    3456            0 :         case DW_CFA_advance_loc2:
    3457            0 :           dw2_asm_output_delta (2, cfi->dw_cfi_oprnd1.dw_cfi_addr,
    3458              :                                 fde->dw_fde_current_label, NULL);
    3459            0 :           fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
    3460            0 :           break;
    3461              : 
    3462          100 :         case DW_CFA_advance_loc4:
    3463          100 :           dw2_asm_output_delta (4, cfi->dw_cfi_oprnd1.dw_cfi_addr,
    3464              :                                 fde->dw_fde_current_label, NULL);
    3465          100 :           fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
    3466          100 :           break;
    3467              : 
    3468            0 :         case DW_CFA_MIPS_advance_loc8:
    3469            0 :           dw2_asm_output_delta (8, cfi->dw_cfi_oprnd1.dw_cfi_addr,
    3470              :                                 fde->dw_fde_current_label, NULL);
    3471            0 :           fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
    3472            0 :           break;
    3473              : 
    3474            0 :         case DW_CFA_offset_extended:
    3475            0 :           r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
    3476            0 :           dw2_asm_output_data_uleb128 (r, NULL);
    3477            0 :           off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
    3478            0 :           dw2_asm_output_data_uleb128 (off, NULL);
    3479            0 :           break;
    3480              : 
    3481           33 :         case DW_CFA_def_cfa:
    3482           33 :           r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
    3483           33 :           dw2_asm_output_data_uleb128 (r, NULL);
    3484           33 :           dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL);
    3485           33 :           break;
    3486              : 
    3487            0 :         case DW_CFA_offset_extended_sf:
    3488            0 :           r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
    3489            0 :           dw2_asm_output_data_uleb128 (r, NULL);
    3490            0 :           off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
    3491            0 :           dw2_asm_output_data_sleb128 (off, NULL);
    3492            0 :           break;
    3493              : 
    3494            0 :         case DW_CFA_def_cfa_sf:
    3495            0 :           r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
    3496            0 :           dw2_asm_output_data_uleb128 (r, NULL);
    3497            0 :           off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
    3498            0 :           dw2_asm_output_data_sleb128 (off, NULL);
    3499            0 :           break;
    3500              : 
    3501           16 :         case DW_CFA_restore_extended:
    3502           16 :         case DW_CFA_undefined:
    3503           16 :         case DW_CFA_same_value:
    3504           16 :         case DW_CFA_def_cfa_register:
    3505           16 :           r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
    3506           16 :           dw2_asm_output_data_uleb128 (r, NULL);
    3507           16 :           break;
    3508              : 
    3509            0 :         case DW_CFA_register:
    3510            0 :           r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
    3511            0 :           dw2_asm_output_data_uleb128 (r, NULL);
    3512            0 :           r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, for_eh);
    3513            0 :           dw2_asm_output_data_uleb128 (r, NULL);
    3514            0 :           break;
    3515              : 
    3516           52 :         case DW_CFA_def_cfa_offset:
    3517           52 :         case DW_CFA_GNU_args_size:
    3518           52 :           dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL);
    3519           52 :           break;
    3520              : 
    3521            0 :         case DW_CFA_def_cfa_offset_sf:
    3522            0 :           off = div_data_align (cfi->dw_cfi_oprnd1.dw_cfi_offset);
    3523            0 :           dw2_asm_output_data_sleb128 (off, NULL);
    3524            0 :           break;
    3525              : 
    3526            0 :         case DW_CFA_def_cfa_expression:
    3527            0 :         case DW_CFA_expression:
    3528            0 :         case DW_CFA_val_expression:
    3529            0 :           output_cfa_loc (cfi, for_eh);
    3530            0 :           break;
    3531              : 
    3532            0 :         case DW_CFA_GNU_negative_offset_extended:
    3533              :           /* Obsoleted by DW_CFA_offset_extended_sf.  */
    3534            0 :           gcc_unreachable ();
    3535              : 
    3536              :         default:
    3537              :           break;
    3538              :         }
    3539              :     }
    3540          266 : }
    3541              : 
    3542              : /* Similar, but do it via assembler directives instead.  */
    3543              : 
    3544              : void
    3545     11895972 : output_cfi_directive (FILE *f, dw_cfi_ref cfi)
    3546              : {
    3547     11895972 :   unsigned long r, r2;
    3548              : 
    3549     11895972 :   switch (cfi->dw_cfi_opc)
    3550              :     {
    3551            0 :     case DW_CFA_advance_loc:
    3552            0 :     case DW_CFA_advance_loc1:
    3553            0 :     case DW_CFA_advance_loc2:
    3554            0 :     case DW_CFA_advance_loc4:
    3555            0 :     case DW_CFA_MIPS_advance_loc8:
    3556            0 :     case DW_CFA_set_loc:
    3557              :       /* Should only be created in a code path not followed when emitting
    3558              :          via directives.  The assembler is going to take care of this for
    3559              :          us.  But this routines is also used for debugging dumps, so
    3560              :          print something.  */
    3561            0 :       gcc_assert (f != asm_out_file);
    3562            0 :       fprintf (f, "\t.cfi_advance_loc\n");
    3563            0 :       break;
    3564              : 
    3565      2372116 :     case DW_CFA_offset:
    3566      2372116 :     case DW_CFA_offset_extended:
    3567      2372116 :     case DW_CFA_offset_extended_sf:
    3568      2372116 :       r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
    3569      2372116 :       fprintf (f, "\t.cfi_offset %lu, " HOST_WIDE_INT_PRINT_DEC"\n",
    3570              :                r, cfi->dw_cfi_oprnd2.dw_cfi_offset);
    3571      2372116 :       break;
    3572              : 
    3573      1361563 :     case DW_CFA_restore:
    3574      1361563 :     case DW_CFA_restore_extended:
    3575      1361563 :       r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
    3576      1361563 :       fprintf (f, "\t.cfi_restore %lu\n", r);
    3577      1361563 :       break;
    3578              : 
    3579            0 :     case DW_CFA_undefined:
    3580            0 :       r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
    3581            0 :       fprintf (f, "\t.cfi_undefined %lu\n", r);
    3582            0 :       break;
    3583              : 
    3584            0 :     case DW_CFA_same_value:
    3585            0 :       r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
    3586            0 :       fprintf (f, "\t.cfi_same_value %lu\n", r);
    3587            0 :       break;
    3588              : 
    3589       498984 :     case DW_CFA_def_cfa:
    3590       498984 :     case DW_CFA_def_cfa_sf:
    3591       498984 :       r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
    3592       498984 :       fprintf (f, "\t.cfi_def_cfa %lu, " HOST_WIDE_INT_PRINT_DEC"\n",
    3593              :                r, cfi->dw_cfi_oprnd2.dw_cfi_offset);
    3594       498984 :       break;
    3595              : 
    3596       463950 :     case DW_CFA_def_cfa_register:
    3597       463950 :       r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
    3598       463950 :       fprintf (f, "\t.cfi_def_cfa_register %lu\n", r);
    3599       463950 :       break;
    3600              : 
    3601           17 :     case DW_CFA_register:
    3602           17 :       r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
    3603           17 :       r2 = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, 1);
    3604           17 :       fprintf (f, "\t.cfi_register %lu, %lu\n", r, r2);
    3605           17 :       break;
    3606              : 
    3607      6200541 :     case DW_CFA_def_cfa_offset:
    3608      6200541 :     case DW_CFA_def_cfa_offset_sf:
    3609      6200541 :       fprintf (f, "\t.cfi_def_cfa_offset "
    3610              :                HOST_WIDE_INT_PRINT_DEC"\n",
    3611              :                cfi->dw_cfi_oprnd1.dw_cfi_offset);
    3612      6200541 :       break;
    3613              : 
    3614       424774 :     case DW_CFA_remember_state:
    3615       424774 :       fprintf (f, "\t.cfi_remember_state\n");
    3616       424774 :       break;
    3617       424780 :     case DW_CFA_restore_state:
    3618       424780 :       fprintf (f, "\t.cfi_restore_state\n");
    3619       424780 :       break;
    3620              : 
    3621        93987 :     case DW_CFA_GNU_args_size:
    3622        93987 :       if (f == asm_out_file)
    3623              :         {
    3624        93987 :           fprintf (f, "\t.cfi_escape %#x,", DW_CFA_GNU_args_size);
    3625        93987 :           dw2_asm_output_data_uleb128_raw (cfi->dw_cfi_oprnd1.dw_cfi_offset);
    3626        93987 :           if (flag_debug_asm)
    3627            0 :             fprintf (f, "\t%s args_size " HOST_WIDE_INT_PRINT_DEC,
    3628              :                      ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_offset);
    3629        93987 :           fputc ('\n', f);
    3630              :         }
    3631              :       else
    3632              :         {
    3633            0 :           fprintf (f, "\t.cfi_GNU_args_size " HOST_WIDE_INT_PRINT_DEC "\n",
    3634              :                    cfi->dw_cfi_oprnd1.dw_cfi_offset);
    3635              :         }
    3636              :       break;
    3637              : 
    3638        55260 :     case DW_CFA_def_cfa_expression:
    3639        55260 :     case DW_CFA_expression:
    3640        55260 :     case DW_CFA_val_expression:
    3641        55260 :       if (f != asm_out_file)
    3642              :         {
    3643            0 :           fprintf (f, "\t.cfi_%scfa_%sexpression ...\n",
    3644              :                    cfi->dw_cfi_opc == DW_CFA_def_cfa_expression ? "def_" : "",
    3645              :                    cfi->dw_cfi_opc == DW_CFA_val_expression ? "val_" : "");
    3646            0 :           break;
    3647              :         }
    3648        55260 :       fprintf (f, "\t.cfi_escape %#x,", cfi->dw_cfi_opc);
    3649        55260 :       output_cfa_loc_raw (cfi);
    3650        55260 :       fputc ('\n', f);
    3651        55260 :       break;
    3652              : 
    3653            0 :     default:
    3654            0 :       if (!targetm.output_cfi_directive (f, cfi))
    3655            0 :         gcc_unreachable ();
    3656              :     }
    3657     11895972 : }
    3658              : 
    3659              : void
    3660     11895720 : dwarf2out_emit_cfi (dw_cfi_ref cfi)
    3661              : {
    3662     11895720 :   if (dwarf2out_do_cfi_asm ())
    3663     11895645 :     output_cfi_directive (asm_out_file, cfi);
    3664     11895720 : }
    3665              : 
    3666              : static void
    3667            0 : dump_cfi_row (FILE *f, dw_cfi_row *row)
    3668              : {
    3669            0 :   dw_cfi_ref cfi;
    3670            0 :   unsigned i;
    3671              : 
    3672            0 :   cfi = row->cfa_cfi;
    3673            0 :   if (!cfi)
    3674              :     {
    3675            0 :       dw_cfa_location dummy;
    3676            0 :       memset (&dummy, 0, sizeof (dummy));
    3677            0 :       dummy.reg.set_by_dwreg (INVALID_REGNUM);
    3678            0 :       cfi = def_cfa_0 (&dummy, &row->cfa);
    3679              :     }
    3680            0 :   output_cfi_directive (f, cfi);
    3681              : 
    3682            0 :   FOR_EACH_VEC_SAFE_ELT (row->reg_save, i, cfi)
    3683            0 :     if (cfi)
    3684            0 :       output_cfi_directive (f, cfi);
    3685            0 : }
    3686              : 
    3687              : void debug_cfi_row (dw_cfi_row *row);
    3688              : 
    3689              : void
    3690            0 : debug_cfi_row (dw_cfi_row *row)
    3691              : {
    3692            0 :   dump_cfi_row (stderr, row);
    3693            0 : }
    3694              : 
    3695              : 
    3696              : /* Save the result of dwarf2out_do_frame across PCH.
    3697              :    This variable is tri-state, with 0 unset, >0 true, <0 false.  */
    3698              : static GTY(()) signed char saved_do_cfi_asm = 0;
    3699              : 
    3700              : /* Decide whether to emit EH frame unwind information for the current
    3701              :    translation unit.  */
    3702              : 
    3703              : bool
    3704      1811184 : dwarf2out_do_eh_frame (void)
    3705              : {
    3706      1811184 :   return
    3707          217 :     (flag_unwind_tables || flag_exceptions)
    3708      1811204 :     && targetm_common.except_unwind_info (&global_options) == UI_DWARF2;
    3709              : }
    3710              : 
    3711              : /* Decide whether we want to emit frame unwind information for the current
    3712              :    translation unit.  */
    3713              : 
    3714              : bool
    3715      4264120 : dwarf2out_do_frame (void)
    3716              : {
    3717              :   /* We want to emit correct CFA location expressions or lists, so we
    3718              :      have to return true if we're going to generate debug info, even if
    3719              :      we're not going to output frame or unwind info.  */
    3720      4264120 :   if (dwarf_debuginfo_p () || dwarf_based_debuginfo_p ())
    3721      1255262 :     return true;
    3722              : 
    3723      3008858 :   if (saved_do_cfi_asm > 0)
    3724              :     return true;
    3725              : 
    3726       282189 :   if (targetm.debug_unwind_info () == UI_DWARF2)
    3727              :     return true;
    3728              : 
    3729       282189 :   if (dwarf2out_do_eh_frame ())
    3730              :     return true;
    3731              : 
    3732              :   return false;
    3733              : }
    3734              : 
    3735              : /* Decide whether to emit frame unwind via assembler directives.  */
    3736              : 
    3737              : bool
    3738     27389883 : dwarf2out_do_cfi_asm (void)
    3739              : {
    3740     27389883 :   int enc;
    3741              : 
    3742     27389883 :   if (saved_do_cfi_asm != 0)
    3743     27118431 :     return saved_do_cfi_asm > 0;
    3744              : 
    3745              :   /* Assume failure for a moment.  */
    3746       271452 :   saved_do_cfi_asm = -1;
    3747              : 
    3748       271452 :   if (!flag_dwarf2_cfi_asm || !dwarf2out_do_frame ())
    3749           39 :     return false;
    3750       271413 :   if (!HAVE_GAS_CFI_PERSONALITY_DIRECTIVE)
    3751              :     return false;
    3752              : 
    3753              :   /* Make sure the personality encoding is one the assembler can support.
    3754              :      In particular, aligned addresses can't be handled.  */
    3755       271413 :   enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2,/*global=*/1);
    3756       271413 :   if ((enc & 0x70) != 0 && (enc & 0x70) != DW_EH_PE_pcrel)
    3757              :     return false;
    3758       271413 :   enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0,/*global=*/0);
    3759       271413 :   if ((enc & 0x70) != 0 && (enc & 0x70) != DW_EH_PE_pcrel)
    3760              :     return false;
    3761              : 
    3762              :   /* If we can't get the assembler to emit only .debug_frame, and we don't need
    3763              :      dwarf2 unwind info for exceptions, then emit .debug_frame by hand.  */
    3764       271413 :   if (!HAVE_GAS_CFI_SECTIONS_DIRECTIVE && !dwarf2out_do_eh_frame ())
    3765              :     return false;
    3766              : 
    3767              :   /* Success!  */
    3768       271413 :   saved_do_cfi_asm = 1;
    3769       271413 :   return true;
    3770              : }
    3771              : 
    3772              : namespace {
    3773              : 
    3774              : const pass_data pass_data_dwarf2_frame =
    3775              : {
    3776              :   RTL_PASS, /* type */
    3777              :   "dwarf2", /* name */
    3778              :   OPTGROUP_NONE, /* optinfo_flags */
    3779              :   TV_FINAL, /* tv_id */
    3780              :   0, /* properties_required */
    3781              :   0, /* properties_provided */
    3782              :   0, /* properties_destroyed */
    3783              :   0, /* todo_flags_start */
    3784              :   0, /* todo_flags_finish */
    3785              : };
    3786              : 
    3787              : class pass_dwarf2_frame : public rtl_opt_pass
    3788              : {
    3789              : public:
    3790       285722 :   pass_dwarf2_frame (gcc::context *ctxt)
    3791       571444 :     : rtl_opt_pass (pass_data_dwarf2_frame, ctxt)
    3792              :   {}
    3793              : 
    3794              :   /* opt_pass methods: */
    3795              :   bool gate (function *) final override;
    3796      1471310 :   unsigned int execute (function *) final override
    3797              :   {
    3798      1471310 :     execute_dwarf2_frame ();
    3799      1471310 :     return 0;
    3800              :   }
    3801              : 
    3802              : }; // class pass_dwarf2_frame
    3803              : 
    3804              : bool
    3805      1471370 : pass_dwarf2_frame::gate (function *)
    3806              : {
    3807              :   /* Targets which still implement the prologue in assembler text
    3808              :      cannot use the generic dwarf2 unwinding.  */
    3809      1471370 :   if (!targetm.have_prologue ())
    3810              :     return false;
    3811              : 
    3812              :   /* ??? What to do for UI_TARGET unwinding?  They might be able to benefit
    3813              :      from the optimized shrink-wrapping annotations that we will compute.
    3814              :      For now, only produce the CFI notes for dwarf2.  */
    3815      1471370 :   return dwarf2out_do_frame ();
    3816              : }
    3817              : 
    3818              : } // anon namespace
    3819              : 
    3820              : rtl_opt_pass *
    3821       285722 : make_pass_dwarf2_frame (gcc::context *ctxt)
    3822              : {
    3823       285722 :   return new pass_dwarf2_frame (ctxt);
    3824              : }
    3825              : 
    3826       256621 : void dwarf2cfi_cc_finalize ()
    3827              : {
    3828       256621 :   add_cfi_insn = NULL;
    3829       256621 :   add_cfi_vec = NULL;
    3830       256621 :   cur_trace = NULL;
    3831       256621 :   cur_row = NULL;
    3832       256621 :   cur_cfa = NULL;
    3833       256621 : }
    3834              : 
    3835              : #include "gt-dwarf2cfi.h"
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.