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