===================================================================
@@ -465,12 +465,11 @@ static void initial_return_save (rtx);
static HOST_WIDE_INT stack_adjust_offset (const_rtx, HOST_WIDE_INT,
HOST_WIDE_INT);
static void output_cfi (dw_cfi_ref, dw_fde_ref, int);
-static void output_cfi_directive (dw_cfi_ref);
+static void output_cfi_directive (FILE *, dw_cfi_ref);
static void output_call_frame_info (int);
static void dwarf2out_note_section_used (void);
static bool clobbers_queued_reg_save (const_rtx);
static void dwarf2out_frame_debug_expr (rtx);
-static void dwarf2out_cfi_begin_epilogue (rtx);
static void dwarf2out_frame_debug_restore_state (void);
/* Support for complex CFA locations. */
@@ -823,9 +822,6 @@ new_cfi (void)
/* The insn after which a new CFI note should be emitted. */
static rtx cfi_insn;
-/* True if remember_state should be emitted before following CFI directive. */
-static bool emit_cfa_remember;
-
/* True if any CFI directives were emitted at the current insn. */
static bool any_cfis_emitted;
@@ -868,28 +864,34 @@ dwarf2out_maybe_emit_cfi_label (void)
}
}
+static void
+add_cfa_remember (void)
+{
+ dw_cfi_ref cfi_remember;
+
+ /* Emit the state save. */
+ cfi_remember = new_cfi ();
+ cfi_remember->dw_cfi_opc = DW_CFA_remember_state;
+ add_fde_cfi (cfi_remember);
+}
+
+/* Nonnull if add_fde_cfi should not just emit a NOTE_INSN_CFI, but
+ also add the CFI to this vector. */
+static cfi_vec *cfi_insn_vec;
+
/* Add CFI to the current fde at the PC value indicated by LABEL if specified,
or to the CIE if LABEL is NULL. */
static void
add_fde_cfi (dw_cfi_ref cfi)
{
- if (emit_cfa_remember)
- {
- dw_cfi_ref cfi_remember;
-
- /* Emit the state save. */
- emit_cfa_remember = false;
- cfi_remember = new_cfi ();
- cfi_remember->dw_cfi_opc = DW_CFA_remember_state;
- add_fde_cfi (cfi_remember);
- }
-
any_cfis_emitted = true;
if (cfi_insn != NULL)
{
cfi_insn = emit_note_after (NOTE_INSN_CFI, cfi_insn);
NOTE_CFI (cfi_insn) = cfi;
+ if (cfi_insn_vec != NULL)
+ VEC_safe_push (dw_cfi_ref, gc, *cfi_insn_vec, cfi);
}
else
{
@@ -980,12 +982,6 @@ static dw_cfa_location old_cfa;
from the CFA. */
static dw_cfa_location cfa_store;
-/* The current save location around an epilogue. */
-static dw_cfa_location cfa_remember;
-
-/* Like cfa_remember, but a copy of old_cfa. */
-static dw_cfa_location old_cfa_remember;
-
/* The running total of the size of arguments pushed onto the stack. */
static HOST_WIDE_INT args_size;
@@ -1339,179 +1335,6 @@ stack_adjust_offset (const_rtx pattern,
return offset;
}
-/* Precomputed args_size for CODE_LABELs and BARRIERs preceeding them,
- indexed by INSN_UID. */
-
-static HOST_WIDE_INT *barrier_args_size;
-
-/* Helper function for compute_barrier_args_size. Handle one insn. */
-
-static HOST_WIDE_INT
-compute_barrier_args_size_1 (rtx insn, HOST_WIDE_INT cur_args_size,
- VEC (rtx, heap) **next)
-{
- HOST_WIDE_INT offset = 0;
- int i;
-
- if (! RTX_FRAME_RELATED_P (insn))
- {
- if (prologue_epilogue_contains (insn))
- /* Nothing */;
- else if (GET_CODE (PATTERN (insn)) == SET)
- offset = stack_adjust_offset (PATTERN (insn), cur_args_size, 0);
- else if (GET_CODE (PATTERN (insn)) == PARALLEL
- || GET_CODE (PATTERN (insn)) == SEQUENCE)
- {
- /* There may be stack adjustments inside compound insns. Search
- for them. */
- for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
- if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
- offset += stack_adjust_offset (XVECEXP (PATTERN (insn), 0, i),
- cur_args_size, offset);
- }
- }
- else
- {
- rtx expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
-
- if (expr)
- {
- expr = XEXP (expr, 0);
- if (GET_CODE (expr) == PARALLEL
- || GET_CODE (expr) == SEQUENCE)
- for (i = 1; i < XVECLEN (expr, 0); i++)
- {
- rtx elem = XVECEXP (expr, 0, i);
-
- if (GET_CODE (elem) == SET && !RTX_FRAME_RELATED_P (elem))
- offset += stack_adjust_offset (elem, cur_args_size, offset);
- }
- }
- }
-
-#ifndef STACK_GROWS_DOWNWARD
- offset = -offset;
-#endif
-
- cur_args_size += offset;
- if (cur_args_size < 0)
- cur_args_size = 0;
-
- if (JUMP_P (insn))
- {
- rtx dest = JUMP_LABEL (insn);
-
- if (dest)
- {
- if (barrier_args_size [INSN_UID (dest)] < 0)
- {
- barrier_args_size [INSN_UID (dest)] = cur_args_size;
- VEC_safe_push (rtx, heap, *next, dest);
- }
- }
- }
-
- return cur_args_size;
-}
-
-/* Walk the whole function and compute args_size on BARRIERs. */
-
-static void
-compute_barrier_args_size (void)
-{
- int max_uid = get_max_uid (), i;
- rtx insn;
- VEC (rtx, heap) *worklist, *next, *tmp;
-
- barrier_args_size = XNEWVEC (HOST_WIDE_INT, max_uid);
- for (i = 0; i < max_uid; i++)
- barrier_args_size[i] = -1;
-
- worklist = VEC_alloc (rtx, heap, 20);
- next = VEC_alloc (rtx, heap, 20);
- insn = get_insns ();
- barrier_args_size[INSN_UID (insn)] = 0;
- VEC_quick_push (rtx, worklist, insn);
- for (;;)
- {
- while (!VEC_empty (rtx, worklist))
- {
- rtx prev, body, first_insn;
- HOST_WIDE_INT cur_args_size;
-
- first_insn = insn = VEC_pop (rtx, worklist);
- cur_args_size = barrier_args_size[INSN_UID (insn)];
- prev = prev_nonnote_insn (insn);
- if (prev && BARRIER_P (prev))
- barrier_args_size[INSN_UID (prev)] = cur_args_size;
-
- for (; insn; insn = NEXT_INSN (insn))
- {
- if (INSN_DELETED_P (insn) || NOTE_P (insn))
- continue;
- if (BARRIER_P (insn))
- break;
-
- if (LABEL_P (insn))
- {
- if (insn == first_insn)
- continue;
- else if (barrier_args_size[INSN_UID (insn)] < 0)
- {
- barrier_args_size[INSN_UID (insn)] = cur_args_size;
- continue;
- }
- else
- {
- /* The insns starting with this label have been
- already scanned or are in the worklist. */
- break;
- }
- }
-
- body = PATTERN (insn);
- if (GET_CODE (body) == SEQUENCE)
- {
- HOST_WIDE_INT dest_args_size = cur_args_size;
- for (i = 1; i < XVECLEN (body, 0); i++)
- if (INSN_ANNULLED_BRANCH_P (XVECEXP (body, 0, 0))
- && INSN_FROM_TARGET_P (XVECEXP (body, 0, i)))
- dest_args_size
- = compute_barrier_args_size_1 (XVECEXP (body, 0, i),
- dest_args_size, &next);
- else
- cur_args_size
- = compute_barrier_args_size_1 (XVECEXP (body, 0, i),
- cur_args_size, &next);
-
- if (INSN_ANNULLED_BRANCH_P (XVECEXP (body, 0, 0)))
- compute_barrier_args_size_1 (XVECEXP (body, 0, 0),
- dest_args_size, &next);
- else
- cur_args_size
- = compute_barrier_args_size_1 (XVECEXP (body, 0, 0),
- cur_args_size, &next);
- }
- else
- cur_args_size
- = compute_barrier_args_size_1 (insn, cur_args_size, &next);
- }
- }
-
- if (VEC_empty (rtx, next))
- break;
-
- /* Swap WORKLIST with NEXT and truncate NEXT for next iteration. */
- tmp = next;
- next = worklist;
- worklist = tmp;
- VEC_truncate (rtx, next, 0);
- }
-
- VEC_free (rtx, heap, worklist);
- VEC_free (rtx, heap, next);
-}
-
/* Add a CFI to update the running total of the size of arguments
pushed onto the stack. */
@@ -1608,25 +1431,7 @@ dwarf2out_notice_stack_adjust (rtx insn,
return;
}
else if (BARRIER_P (insn))
- {
- /* Don't call compute_barrier_args_size () if the only
- BARRIER is at the end of function. */
- if (barrier_args_size == NULL && next_nonnote_insn (insn))
- compute_barrier_args_size ();
- if (barrier_args_size == NULL)
- offset = 0;
- else
- {
- offset = barrier_args_size[INSN_UID (insn)];
- if (offset < 0)
- offset = 0;
- }
-
- offset -= args_size;
-#ifndef STACK_GROWS_DOWNWARD
- offset = -offset;
-#endif
- }
+ return;
else if (GET_CODE (PATTERN (insn)) == SET)
offset = stack_adjust_offset (PATTERN (insn), args_size, 0);
else if (GET_CODE (PATTERN (insn)) == PARALLEL
@@ -2054,9 +1859,12 @@ add_cfis_to_fde (void)
next = NEXT_INSN (insn);
if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
- /* Don't attempt to advance_loc4 between labels in different
- sections. */
- first = true;
+ {
+ fde->dw_fde_switch_cfi_index = VEC_length (dw_cfi_ref, fde->dw_fde_cfi);
+ /* Don't attempt to advance_loc4 between labels in different
+ sections. */
+ first = true;
+ }
if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_CFI)
{
@@ -2097,6 +1905,17 @@ add_cfis_to_fde (void)
}
}
+/* A subroutine of dwarf2out_frame_debug_init, emit a CFA_restore_state. */
+
+void
+dwarf2out_frame_debug_restore_state (void)
+{
+ dw_cfi_ref cfi = new_cfi ();
+
+ cfi->dw_cfi_opc = DW_CFA_restore_state;
+ add_fde_cfi (cfi);
+}
+
/* Record call frame debugging information for an expression EXPR,
which either sets SP or FP (adjusting how we calculate the frame
address) or saves a register to the stack or another register.
@@ -2797,9 +2616,6 @@ dwarf2out_frame_debug (rtx insn, bool af
else
cfi_insn = PREV_INSN (insn);
- if (!NONJUMP_INSN_P (insn) || clobbers_queued_reg_save (insn))
- dwarf2out_flush_queued_reg_saves ();
-
if (!RTX_FRAME_RELATED_P (insn))
{
/* ??? This should be done unconditionally since stack adjustments
@@ -2945,56 +2761,224 @@ dwarf2out_frame_debug_init (void)
num_regs_saved_in_regs = 0;
}
-/* After the (optional) text prologue has been written, emit CFI insns
- and update the FDE for frame-related instructions. */
+/* Copy a CFI vector, except for args_size opcodes. */
+static cfi_vec
+copy_cfi_vec_parts (cfi_vec in_vec)
+{
+ int length = VEC_length (dw_cfi_ref, in_vec);
+ /* Ensure we always have a pointer to a vector, not just NULL. */
+ cfi_vec new_vec = VEC_alloc (dw_cfi_ref, gc, length > 0 ? length : 1);
+ int i;
+ for (i = 0; i < length; i++)
+ {
+ dw_cfi_ref elt = VEC_index (dw_cfi_ref, in_vec, i);
+ if (elt->dw_cfi_opc == DW_CFA_GNU_args_size)
+ continue;
-void
-dwarf2out_frame_debug_after_prologue (void)
+ VEC_quick_push (dw_cfi_ref, new_vec, elt);
+ }
+ return new_vec;
+}
+
+/* Record the state of the CFI program at a point in the program. */
+typedef struct
{
- rtx insn;
- if (barrier_args_size)
+ /* The CFI instructions up to this point. */
+ cfi_vec cfis;
+ /* Copies of the global variables with the same name. */
+ dw_cfa_location cfa, cfa_store, old_cfa;
+ /* True if we have seen this point during a scan in scan_until_barrier. */
+ bool visited;
+ /* True if this point was used as a starting point for such a scan. */
+ bool used_as_start;
+ /* Other than CFI instructions and CFA state, the only thing necessary to
+ be tracked is the argument size. */
+ int args_size;
+ /* Nonzero for states that must be remembered and restored. If higher
+ than one, the first restores will be immediately followed by another
+ remember. */
+ int n_restores;
+} jump_target_info;
+
+/* Return true if we'll want to save or restore CFI state at INSN. This is
+ true for labels and barriers, and certain notes. */
+static bool
+save_point_p (rtx insn)
+{
+ return (BARRIER_P (insn) || LABEL_P (insn)
+ || (NOTE_P (insn)
+ && (NOTE_KIND (insn) == NOTE_INSN_FUNCTION_BEG
+ || NOTE_KIND (insn) == NOTE_INSN_PROLOGUE_END
+ || NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)));
+}
+
+/* Save the current state in INFO. */
+
+static void
+record_current_state (jump_target_info *info)
+{
+ info->cfis = copy_cfi_vec_parts (*cfi_insn_vec);
+ info->args_size = args_size;
+ info->cfa = cfa;
+ info->old_cfa = old_cfa;
+ info->cfa_store = cfa_store;
+}
+
+/* LABEL is the target of a jump we encountered while scanning the
+ function. Record it in START_POINTS as a potential new starting point
+ for the scan, unless we've visited it before. UID_LUID gives a
+ mapping for uids used to index INFO, which holds the CFI
+ information for labels and barriers. */
+static void
+maybe_record_jump_target (rtx label, VEC (rtx, heap) **start_points,
+ int *uid_luid, jump_target_info *info)
+{
+ int uid;
+
+ if (GET_CODE (label) == LABEL_REF)
+ label = XEXP (label, 0);
+ gcc_assert (LABEL_P (label));
+ uid = INSN_UID (label);
+ info += uid_luid[uid];
+ if (info->visited || info->cfis)
+ return;
+
+ if (dump_file)
+ fprintf (dump_file, "recording label %d as possible jump target\n", uid);
+
+ VEC_safe_push (rtx, heap, *start_points, label);
+ record_current_state (info);
+}
+
+/* Return true if VEC1 and VEC2 are identical up to the length of VEC1. */
+static bool
+vec_is_prefix_of (cfi_vec vec1, cfi_vec vec2)
+{
+ int i;
+ int len1 = VEC_length (dw_cfi_ref, vec1);
+ int len2 = VEC_length (dw_cfi_ref, vec2);
+ if (len1 > len2)
+ return false;
+ for (i = 0; i < len1; i++)
+ if (VEC_index (dw_cfi_ref, vec1, i) != VEC_index (dw_cfi_ref, vec1, i))
+ return false;
+ return true;
+}
+
+/* Append entries to FDE's cfi vector. PREFIX and FULL are two
+ existing vectors, where PREFIX is contained in FULL as a prefix. */
+
+static void
+append_extra_cfis (cfi_vec prefix, cfi_vec full)
+{
+ int i;
+ int len = VEC_length (dw_cfi_ref, full);
+ int prefix_len = VEC_length (dw_cfi_ref, prefix);
+
+ gcc_assert (prefix_len <= len);
+ for (i = 0; i < prefix_len; i++)
{
- XDELETEVEC (barrier_args_size);
- barrier_args_size = NULL;
+ dw_cfi_ref elt, elt2;
+
+ elt = VEC_index (dw_cfi_ref, full, i);
+ elt2 = VEC_index (dw_cfi_ref, prefix, i);
+ gcc_assert (elt == elt2);
}
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ for (; i < len; i++)
{
- rtx pat;
- if (BARRIER_P (insn))
- {
- dwarf2out_frame_debug (insn, false);
- continue;
- }
- else if (NOTE_P (insn))
+ dw_cfi_ref elt = VEC_index (dw_cfi_ref, full, i);
+ add_fde_cfi (elt);
+ }
+}
+
+extern void debug_cfi_vec (FILE *, cfi_vec v);
+void debug_cfi_vec (FILE *f, cfi_vec v)
+{
+ int ix;
+ dw_cfi_ref cfi;
+
+ FOR_EACH_VEC_ELT (dw_cfi_ref, v, ix, cfi)
+ output_cfi_directive (f, cfi);
+}
+
+static bool
+switch_note_p (rtx insn)
+{
+ return NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS;
+}
+
+/* From the current starting point in INSN, scan forwards until we hit a
+ barrier, the end of the function, or a label we've previously used as
+ a starting point.
+ UID_LUID is a mapping to linear uids used to map an insn to an entry in
+ POINT_INFO, if save_point_p is true for a given insn. */
+
+static void
+scan_until_barrier (rtx insn, jump_target_info *point_info, int *uid_luid,
+ VEC (rtx, heap) **start_points)
+{
+ rtx next;
+ for (; insn != NULL_RTX; insn = next)
+ {
+ int uid = INSN_UID (insn);
+ rtx pat, note;
+
+ next = NEXT_INSN (insn);
+ if (save_point_p (insn))
{
- switch (NOTE_KIND (insn))
- {
- case NOTE_INSN_EPILOGUE_BEG:
-#if defined (HAVE_epilogue)
- dwarf2out_cfi_begin_epilogue (insn);
-#endif
+ int luid = uid_luid[uid];
+ jump_target_info *info = point_info + luid;
+ if (info->used_as_start)
+ {
+ if (dump_file)
+ fprintf (dump_file,
+ "Stopping scan at insn %d; previously reached\n",
+ uid);
break;
- case NOTE_INSN_CFA_RESTORE_STATE:
- cfi_insn = insn;
- dwarf2out_frame_debug_restore_state ();
- cfi_insn = NULL;
+ }
+ info->visited = true;
+ if (BARRIER_P (insn))
+ gcc_assert (info->cfis == NULL);
+ if (switch_note_p (insn))
+ {
+ /* Don't record the state, it was set to a clean slate in
+ the caller. */
+ if (dump_file)
+ fprintf (dump_file,
+ "Stopping scan at text section switch %d\n", uid);
+ break;
+ }
+ record_current_state (info);
+ if (BARRIER_P (insn))
+ {
+ if (dump_file)
+ fprintf (dump_file, "Stopping scan at barrier %d\n", uid);
break;
}
- continue;
}
+
if (!NONDEBUG_INSN_P (insn))
continue;
pat = PATTERN (insn);
if (asm_noperands (pat) >= 0)
continue;
+
if (GET_CODE (pat) == SEQUENCE)
{
- int j;
- for (j = 1; j < XVECLEN (pat, 0); j++)
- dwarf2out_frame_debug (XVECEXP (pat, 0, j), false);
+ int i;
+ for (i = 1; i < XVECLEN (pat, 0); i++)
+ dwarf2out_frame_debug (XVECEXP (pat, 0, i), false);
insn = XVECEXP (pat, 0, 0);
}
+ if (!NONJUMP_INSN_P (insn) || clobbers_queued_reg_save (insn)
+ || (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_PROLOGUE_END))
+ {
+ cfi_insn = PREV_INSN (insn);
+ dwarf2out_flush_queued_reg_saves ();
+ cfi_insn = NULL_RTX;
+ }
+
if (CALL_P (insn) && dwarf2out_do_frame ())
dwarf2out_frame_debug (insn, false);
if (dwarf2out_do_frame ()
@@ -3003,115 +2987,463 @@ dwarf2out_frame_debug_after_prologue (vo
#endif
)
dwarf2out_frame_debug (insn, true);
- }
- add_cfis_to_fde ();
+ if (JUMP_P (insn))
+ {
+ rtx label = JUMP_LABEL (insn);
+ if (label)
+ {
+ rtx next = next_real_insn (label);
+ if (next != NULL_RTX && addr_vec_p (next))
+ {
+ int i;
+ rtx pat = PATTERN (next);
+ int eltnum = GET_CODE (pat) == ADDR_DIFF_VEC ? 1 : 0;
+
+ for (i = 0; i < XVECLEN (pat, eltnum); i++)
+ maybe_record_jump_target (XVECEXP (pat, eltnum, i),
+ start_points, uid_luid,
+ point_info);
+ }
+ else
+ maybe_record_jump_target (label, start_points, uid_luid,
+ point_info);
+ }
+ }
+ note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+ if (note)
+ {
+ eh_landing_pad lp;
+
+ lp = get_eh_landing_pad_from_rtx (insn);
+ if (lp)
+ maybe_record_jump_target (lp->landing_pad, start_points,
+ uid_luid, point_info);
+ }
+ }
}
-void
-dwarf2out_emit_cfi (dw_cfi_ref cfi)
+/* A subroutine of dwarf2out_debug_after_prologue. Given the vector
+ of potential starting points in *START_POINTS, pick the best one to
+ use for the next scan. Return NULL_RTX if there's nothing left to
+ scan.
+ UID_LUID and START_POINTS are as in scan_until_barrier. */
+
+static rtx
+find_best_starting_point (jump_target_info *point_info, int *uid_luid,
+ VEC (rtx, heap) **start_points)
{
- if (dwarf2out_do_cfi_asm ())
- output_cfi_directive (cfi);
+ int i;
+ rtx insn;
+ int best_idx;
+ bool best_has_barrier;
+ jump_target_info *restart_info;
+
+ FOR_EACH_VEC_ELT_REVERSE (rtx, *start_points, i, insn)
+ {
+ restart_info = point_info + uid_luid[INSN_UID (insn)];
+ if (restart_info->visited)
+ VEC_ordered_remove (rtx, *start_points, i);
+ }
+
+ best_idx = -1;
+ best_has_barrier = false;
+ FOR_EACH_VEC_ELT (rtx, *start_points, i, insn)
+ {
+ rtx prev;
+ bool this_has_barrier;
+
+ restart_info = point_info + uid_luid[INSN_UID (insn)];
+ prev = prev_nonnote_nondebug_insn (insn);
+ this_has_barrier = (prev
+ && (BARRIER_P (prev) || switch_note_p (prev)));
+ if (best_idx < 0
+ || (!best_has_barrier && this_has_barrier))
+ {
+ best_idx = i;
+ best_has_barrier = this_has_barrier;
+ }
+ }
+
+ if (best_idx < 0)
+ {
+ rtx link;
+ for (link = forced_labels; link; link = XEXP (link, 1))
+ {
+ insn = XEXP (link, 0);
+ restart_info = point_info + uid_luid[INSN_UID (insn)];
+ if (!restart_info->visited)
+ return insn;
+ }
+ return NULL_RTX;
+ }
+ insn = VEC_index (rtx, *start_points, best_idx);
+ VEC_ordered_remove (rtx, *start_points, best_idx);
+ return insn;
}
-/* Determine if we need to save and restore CFI information around
- this epilogue. If we do need to save/restore, then emit the save
- now, and insert a NOTE_INSN_CFA_RESTORE_STATE at the appropriate
- place in the stream. */
+/* After the (optional) text prologue has been written, emit CFI insns
+ and update the FDE for frame-related instructions. */
void
-dwarf2out_cfi_begin_epilogue (rtx insn)
+dwarf2out_frame_debug_after_prologue (void)
{
- bool saw_frp = false;
- rtx i;
+ int max_uid = get_max_uid ();
+ int i, n_saves_restores, prologue_end_point, switch_note_point;
+ rtx insn, save_point;
+ VEC (rtx, heap) *start_points;
+ int n_points;
+ int *uid_luid;
+ bool remember_needed;
+ jump_target_info *point_info, *save_point_info;
+ cfi_vec current_vec;
+
+ n_points = 0;
+ for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
+ if (save_point_p (insn))
+ n_points++;
+ uid_luid = XCNEWVEC (int, max_uid);
+ n_points = 0;
+ prologue_end_point = -1;
+ switch_note_point = -1;
+ for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
+ if (save_point_p (insn))
+ {
+ if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_PROLOGUE_END)
+ prologue_end_point = n_points;
+ else if (switch_note_p (insn))
+ switch_note_point = n_points;
+ uid_luid[INSN_UID (insn)] = n_points++;
+ }
+
+ point_info = XCNEWVEC (jump_target_info, n_points);
+ for (i = 0; i < n_points; i++)
+ point_info[i].args_size = -1;
+
+ start_points = VEC_alloc (rtx, heap, 20);
+ insn = get_insns ();
+ current_vec = VEC_alloc (dw_cfi_ref, gc, 10);
+
+ /* At a NOTE_INSN_SWITCH_TEXT_SECTIONS we'll emit a cfi_startproc.
+ Ensure the state at this note reflects that. */
+ if (switch_note_point != -1)
+ {
+ cfi_insn_vec = ¤t_vec;
+ record_current_state (point_info + switch_note_point);
+ cfi_insn_vec = NULL;
+ }
+ args_size = old_args_size = 0;
- /* Scan forward to the return insn, noticing if there are possible
- frame related insns. */
- for (i = NEXT_INSN (insn); i ; i = NEXT_INSN (i))
+ for (;;)
{
- if (!INSN_P (i))
- continue;
+ HOST_WIDE_INT offset;
+ jump_target_info *restart_info;
- /* Look for both regular and sibcalls to end the block. Various
- optimization passes may cause us to jump to a common epilogue
- tail, so we also accept simplejumps. */
- if (returnjump_p (i) || simplejump_p (i))
- break;
- if (CALL_P (i) && SIBLING_CALL_P (i))
+ /* Scan the insns and emit NOTE_CFIs where necessary. */
+ cfi_insn_vec = ¤t_vec;
+ scan_until_barrier (insn, point_info, uid_luid, &start_points);
+ cfi_insn_vec = NULL;
+
+ insn = find_best_starting_point (point_info, uid_luid, &start_points);
+
+ if (insn == NULL_RTX)
break;
- if (GET_CODE (PATTERN (i)) == SEQUENCE)
- {
- int idx;
- rtx seq = PATTERN (i);
+ if (dump_file)
+ fprintf (dump_file, "restarting scan at label %d", INSN_UID (insn));
- if (returnjump_p (XVECEXP (seq, 0, 0)))
- break;
- if (CALL_P (XVECEXP (seq, 0, 0))
- && SIBLING_CALL_P (XVECEXP (seq, 0, 0)))
- break;
+ restart_info = point_info + uid_luid[INSN_UID (insn)];
+ restart_info->visited = true;
+ restart_info->used_as_start = true;
+ /* If find_best_starting_point returned a forced label, use the
+ state at the NOTE_INSN_PROLOGUE_END note. */
+ if (restart_info->cfis == NULL)
+ {
+ cfi_vec *v = &restart_info->cfis;
+ gcc_assert (prologue_end_point != -1);
+ restart_info = point_info + prologue_end_point;
+ *v = copy_cfi_vec_parts (restart_info->cfis);
+ }
+
+ gcc_assert (LABEL_P (insn));
+ current_vec = copy_cfi_vec_parts (restart_info->cfis);
+ cfa = restart_info->cfa;
+ old_cfa = restart_info->old_cfa;
+ cfa_store = restart_info->cfa_store;
+ offset = restart_info->args_size;
+ if (offset >= 0)
+ {
+ if (dump_file && offset != args_size)
+ fprintf (dump_file, ", args_size " HOST_WIDE_INT_PRINT_DEC
+ " -> " HOST_WIDE_INT_PRINT_DEC,
+ args_size, offset);
- for (idx = 0; idx < XVECLEN (seq, 0); idx++)
- if (RTX_FRAME_RELATED_P (XVECEXP (seq, 0, idx)))
- saw_frp = true;
+ offset -= args_size;
+#ifndef STACK_GROWS_DOWNWARD
+ offset = -offset;
+#endif
+ if (offset != 0)
+ {
+ cfi_insn = prev_nonnote_nondebug_insn (insn);
+ dwarf2out_stack_adjust (offset);
+ cfi_insn = NULL_RTX;
+ }
+ }
+ if (dump_file)
+ {
+ fprintf (dump_file, "\n");
+ if (dump_flags & TDF_DETAILS)
+ debug_cfi_vec (dump_file, current_vec);
}
- if (RTX_FRAME_RELATED_P (i))
- saw_frp = true;
+ insn = NEXT_INSN (insn);
}
- /* If the port doesn't emit epilogue unwind info, we don't need a
- save/restore pair. */
- if (!saw_frp)
- return;
+ VEC_free (rtx, heap, start_points);
- /* Otherwise, search forward to see if the return insn was the last
- basic block of the function. If so, we don't need save/restore. */
- gcc_assert (i != NULL);
- i = next_real_insn (i);
- if (i == NULL)
- return;
+ /* Now splice the various CFI fragments together into a coherent whole. */
- /* Insert the restore before that next real insn in the stream, and before
- a potential NOTE_INSN_EPILOGUE_BEG -- we do need these notes to be
- properly nested. This should be after any label or alignment. This
- will be pushed into the CFI stream by the function below. */
- while (1)
+ /* First, discover discontinuities, and where necessary search for suitable
+ remember/restore points. */
+ save_point = NULL_RTX;
+ save_point_info = NULL;
+ n_saves_restores = 0;
+ for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
{
- rtx p = PREV_INSN (i);
- if (!NOTE_P (p))
- break;
- if (NOTE_KIND (p) == NOTE_INSN_BASIC_BLOCK)
- break;
- i = p;
+ jump_target_info *info, *barrier_info, *candidate_info;
+ rtx prev;
+
+ if (insn == save_point)
+ {
+ save_point = NULL_RTX;
+ save_point_info = NULL;
+ info = point_info + uid_luid[INSN_UID (insn)];
+ info->n_restores = n_saves_restores;
+ n_saves_restores = 0;
+ if (dump_file)
+ fprintf (dump_file, "finalize save point %d\n", INSN_UID (insn));
+ }
+
+ /* Look for labels that were used as starting points and are
+ preceded by a BARRIER. */
+ if (!LABEL_P (insn))
+ continue;
+
+ info = point_info + uid_luid[INSN_UID (insn)];
+ if (!info->used_as_start)
+ continue;
+ barrier_info = NULL;
+ for (prev = PREV_INSN (insn); prev; prev = PREV_INSN (prev))
+ {
+ if (!BARRIER_P (prev) && !LABEL_P (prev))
+ continue;
+ barrier_info = point_info + uid_luid[INSN_UID (prev)];
+ /* Skip through barriers we haven't visited; they may occur
+ for things like jump tables. */
+ if ((BARRIER_P (prev) && barrier_info->visited)
+ || (LABEL_P (prev) && barrier_info->used_as_start)
+ || switch_note_p (prev))
+ break;
+ }
+ if (!BARRIER_P (prev))
+ continue;
+
+ if (dump_file)
+ fprintf (dump_file, "State transition at barrier %d, label %d ... ",
+ INSN_UID (prev), INSN_UID (insn));
+
+ /* If the state at the barrier can easily be transformed into the state
+ at the label, we don't need save/restore points. */
+ if (vec_is_prefix_of (barrier_info->cfis, info->cfis))
+ {
+ if (dump_file)
+ fprintf (dump_file, "prefix\n");
+ continue;
+ }
+
+ /* A save/restore is necessary. Walk backwards to find the best
+ save point. First see if we know a save point already and if
+ it's suitable. */
+ n_saves_restores++;
+ if (save_point)
+ {
+ prev = save_point;
+ if (vec_is_prefix_of (save_point_info->cfis, info->cfis))
+ {
+ if (dump_file)
+ fprintf (dump_file, "reuse save point\n");
+ continue;
+ }
+ }
+
+ for (;;)
+ {
+ prev = PREV_INSN (prev);
+ /* We should eventually encounter the NOTE_INSN_FUNCTION_BEG,
+ which must be a suitable save point fo anything. */
+ gcc_assert (prev != NULL_RTX);
+
+ if (!save_point_p (prev))
+ continue;
+
+ candidate_info = point_info + uid_luid[INSN_UID (prev)];
+ /* We don't necessarily get to see this note during
+ scanning. Record an empty CFI vector for it so that it is
+ usable as a restore point. */
+ if (switch_note_p (prev))
+ {
+ if (candidate_info->cfis == NULL)
+ candidate_info->cfis = VEC_alloc (dw_cfi_ref, gc, 1);
+ }
+
+ if (candidate_info->cfis != NULL
+ && vec_is_prefix_of (candidate_info->cfis, info->cfis)
+ && (save_point == NULL
+ || vec_is_prefix_of (candidate_info->cfis,
+ save_point_info->cfis)))
+ {
+ if (dump_file)
+ fprintf (dump_file, "save point %d\n", INSN_UID (prev));
+ save_point = prev;
+ save_point_info = candidate_info;
+ break;
+ }
+ }
}
- emit_note_before (NOTE_INSN_CFA_RESTORE_STATE, i);
- emit_cfa_remember = true;
+ save_point = NULL_RTX;
+ save_point_info = NULL;
+ remember_needed = false;
+
+ /* This value is now used to distinguish between NOTE_CFI added up
+ to now and those added by the next loop. */
+ max_uid = get_max_uid ();
- /* And emulate the state save. */
- gcc_assert (!cfa_remember.in_use);
- cfa_remember = cfa;
- old_cfa_remember = old_cfa;
- cfa_remember.in_use = 1;
-}
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+ jump_target_info *info;
-/* A "subroutine" of dwarf2out_cfi_begin_epilogue. Emit the restore
- required. */
+ if (INSN_UID (insn) < max_uid
+ && NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_CFI
+ && remember_needed)
+ {
+ cfi_insn = PREV_INSN (insn);
+ add_cfa_remember ();
+ cfi_insn = NULL_RTX;
+ remember_needed = false;
+ }
-static void
-dwarf2out_frame_debug_restore_state (void)
-{
- dw_cfi_ref cfi = new_cfi ();
+ if (!save_point_p (insn))
+ continue;
- cfi->dw_cfi_opc = DW_CFA_restore_state;
- add_fde_cfi (cfi);
+ cfi_insn = insn;
+ info = point_info + uid_luid[INSN_UID (insn)];
+
+ if (info->n_restores > 0)
+ {
+ gcc_assert (save_point_info == NULL);
+ save_point_info = info;
+ remember_needed = true;
+ }
+ if (switch_note_p (insn))
+ {
+ jump_target_info *label_info;
+ rtx next = insn;
+
+ cfi_insn = insn;
+ if (remember_needed)
+ add_cfa_remember ();
+ remember_needed = false;
+
+ /* Find the next label, and emit extra CFIs as necessary to
+ achieve the correct state. */
+ do
+ {
+ if (LABEL_P (next))
+ {
+ label_info = point_info + uid_luid[INSN_UID (next)];
+ if (label_info->used_as_start)
+ break;
+ }
+ insn = next;
+ next = NEXT_INSN (next);
+ }
+ while (next != NULL_RTX);
+ if (next == NULL_RTX)
+ break;
+ append_extra_cfis (NULL, label_info->cfis);
+ cfi_insn = NULL_RTX;
+ }
+ else if (BARRIER_P (insn))
+ {
+ jump_target_info *label_info;
+ cfi_vec new_cfi_vec;
+ cfi_vec barrier_cfi = info->cfis;
+ rtx next = insn;
+
+ /* Find the start of the next sequence we processed. */
+ do
+ {
+ if (LABEL_P (next))
+ {
+ label_info = point_info + uid_luid[INSN_UID (next)];
+ if (label_info->used_as_start)
+ break;
+ }
+ if (switch_note_p (next))
+ break;
+ insn = next;
+ next = NEXT_INSN (next);
+ }
+ while (next != NULL_RTX);
+ if (next == NULL_RTX)
+ break;
+ if (!LABEL_P (next))
+ continue;
- gcc_assert (cfa_remember.in_use);
- cfa = cfa_remember;
- old_cfa = old_cfa_remember;
- cfa_remember.in_use = 0;
+ /* Emit extra CFIs as necessary to achieve the correct state. */
+ new_cfi_vec = label_info->cfis;
+ cfi_insn = next;
+ if (vec_is_prefix_of (barrier_cfi, new_cfi_vec))
+ {
+ if (VEC_length (dw_cfi_ref, barrier_cfi)
+ != VEC_length (dw_cfi_ref, new_cfi_vec))
+ {
+ /* If the barrier was a point needing a restore, we must
+ add the remember here as we ignore the newly added
+ CFI notes. */
+ if (info->n_restores > 0)
+ add_cfa_remember ();
+ remember_needed = false;
+ append_extra_cfis (barrier_cfi, new_cfi_vec);
+ }
+ }
+ else
+ {
+ save_point_info->n_restores--;
+ dwarf2out_frame_debug_restore_state ();
+
+ if (save_point_info->n_restores > 0)
+ add_cfa_remember ();
+ gcc_assert (!remember_needed);
+ append_extra_cfis (save_point_info->cfis, new_cfi_vec);
+ if (save_point_info->n_restores == 0)
+ save_point_info = NULL;
+ }
+ cfi_insn = NULL_RTX;
+ }
+ }
+ free (uid_luid);
+ free (point_info);
+
+ add_cfis_to_fde ();
+}
+
+void
+dwarf2out_emit_cfi (dw_cfi_ref cfi)
+{
+ if (dwarf2out_do_cfi_asm ())
+ output_cfi_directive (asm_out_file, cfi);
}
/* Describe for the GTY machinery what parts of dw_cfi_oprnd1 are used. */
@@ -3411,7 +3743,7 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref f
/* Similar, but do it via assembler directives instead. */
static void
-output_cfi_directive (dw_cfi_ref cfi)
+output_cfi_directive (FILE *f, dw_cfi_ref cfi)
{
unsigned long r, r2;
@@ -3426,82 +3758,96 @@ output_cfi_directive (dw_cfi_ref cfi)
/* Should only be created by add_fde_cfi in a code path not
followed when emitting via directives. The assembler is
going to take care of this for us. */
- gcc_unreachable ();
+ if (f == asm_out_file)
+ gcc_unreachable ();
+ fprintf (f, "\t.cfi_advance_loc\n");
+ break;
case DW_CFA_offset:
case DW_CFA_offset_extended:
case DW_CFA_offset_extended_sf:
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
- fprintf (asm_out_file, "\t.cfi_offset %lu, "HOST_WIDE_INT_PRINT_DEC"\n",
+ fprintf (f, "\t.cfi_offset %lu, "HOST_WIDE_INT_PRINT_DEC"\n",
r, cfi->dw_cfi_oprnd2.dw_cfi_offset);
break;
case DW_CFA_restore:
case DW_CFA_restore_extended:
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
- fprintf (asm_out_file, "\t.cfi_restore %lu\n", r);
+ fprintf (f, "\t.cfi_restore %lu\n", r);
break;
case DW_CFA_undefined:
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
- fprintf (asm_out_file, "\t.cfi_undefined %lu\n", r);
+ fprintf (f, "\t.cfi_undefined %lu\n", r);
break;
case DW_CFA_same_value:
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
- fprintf (asm_out_file, "\t.cfi_same_value %lu\n", r);
+ fprintf (f, "\t.cfi_same_value %lu\n", r);
break;
case DW_CFA_def_cfa:
case DW_CFA_def_cfa_sf:
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
- fprintf (asm_out_file, "\t.cfi_def_cfa %lu, "HOST_WIDE_INT_PRINT_DEC"\n",
+ fprintf (f, "\t.cfi_def_cfa %lu, "HOST_WIDE_INT_PRINT_DEC"\n",
r, cfi->dw_cfi_oprnd2.dw_cfi_offset);
break;
case DW_CFA_def_cfa_register:
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
- fprintf (asm_out_file, "\t.cfi_def_cfa_register %lu\n", r);
+ fprintf (f, "\t.cfi_def_cfa_register %lu\n", r);
break;
case DW_CFA_register:
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
r2 = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, 1);
- fprintf (asm_out_file, "\t.cfi_register %lu, %lu\n", r, r2);
+ fprintf (f, "\t.cfi_register %lu, %lu\n", r, r2);
break;
case DW_CFA_def_cfa_offset:
case DW_CFA_def_cfa_offset_sf:
- fprintf (asm_out_file, "\t.cfi_def_cfa_offset "
+ fprintf (f, "\t.cfi_def_cfa_offset "
HOST_WIDE_INT_PRINT_DEC"\n",
cfi->dw_cfi_oprnd1.dw_cfi_offset);
break;
case DW_CFA_remember_state:
- fprintf (asm_out_file, "\t.cfi_remember_state\n");
+ fprintf (f, "\t.cfi_remember_state\n");
break;
case DW_CFA_restore_state:
- fprintf (asm_out_file, "\t.cfi_restore_state\n");
+ fprintf (f, "\t.cfi_restore_state\n");
break;
case DW_CFA_GNU_args_size:
- fprintf (asm_out_file, "\t.cfi_escape %#x,", DW_CFA_GNU_args_size);
+ if (f != asm_out_file)
+ {
+ fprintf (f, "\t.cfi_GNU_args_size"HOST_WIDE_INT_PRINT_DEC "\n",
+ cfi->dw_cfi_oprnd1.dw_cfi_offset);
+ break;
+ }
+ fprintf (f, "\t.cfi_escape %#x,", DW_CFA_GNU_args_size);
dw2_asm_output_data_uleb128_raw (cfi->dw_cfi_oprnd1.dw_cfi_offset);
if (flag_debug_asm)
- fprintf (asm_out_file, "\t%s args_size "HOST_WIDE_INT_PRINT_DEC,
+ fprintf (f, "\t%s args_size "HOST_WIDE_INT_PRINT_DEC,
ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_offset);
- fputc ('\n', asm_out_file);
+ fputc ('\n', f);
break;
case DW_CFA_GNU_window_save:
- fprintf (asm_out_file, "\t.cfi_window_save\n");
+ fprintf (f, "\t.cfi_window_save\n");
break;
case DW_CFA_def_cfa_expression:
case DW_CFA_expression:
- fprintf (asm_out_file, "\t.cfi_escape %#x,", cfi->dw_cfi_opc);
+ if (f != asm_out_file)
+ {
+ fprintf (f, "\t.cfi_cfa_{def_,}expression\n");
+ break;
+ }
+ fprintf (f, "\t.cfi_escape %#x,", cfi->dw_cfi_opc);
output_cfa_loc_raw (cfi);
- fputc ('\n', asm_out_file);
+ fputc ('\n', f);
break;
default:
@@ -3510,14 +3856,11 @@ output_cfi_directive (dw_cfi_ref cfi)
}
/* Output CFIs from VEC, up to index UPTO, to bring current FDE to the
- same state as after executing CFIs in CFI chain. DO_CFI_ASM is
- true if .cfi_* directives shall be emitted, false otherwise. If it
- is false, FDE and FOR_EH are the other arguments to pass to
- output_cfi. */
+ same state as after executing CFIs in CFI chain. FDE and FOR_EH
+ are the other arguments to pass to output_cfi. */
static void
-output_cfis (cfi_vec vec, int upto, bool do_cfi_asm,
- dw_fde_ref fde, bool for_eh)
+output_cfis (cfi_vec vec, int upto, dw_fde_ref fde, bool for_eh)
{
int ix;
struct dw_cfi_struct cfi_buf;
@@ -3611,12 +3954,7 @@ output_cfis (cfi_vec vec, int upto, bool
if (cfi2 != NULL
&& cfi2->dw_cfi_opc != DW_CFA_restore
&& cfi2->dw_cfi_opc != DW_CFA_restore_extended)
- {
- if (do_cfi_asm)
- output_cfi_directive (cfi2);
- else
- output_cfi (cfi2, fde, for_eh);
- }
+ output_cfi (cfi2, fde, for_eh);
}
if (cfi_cfa && cfi_cfa_offset && cfi_cfa_offset != cfi_cfa)
{
@@ -3645,30 +3983,20 @@ output_cfis (cfi_vec vec, int upto, bool
else if (cfi_cfa_offset)
cfi_cfa = cfi_cfa_offset;
if (cfi_cfa)
- {
- if (do_cfi_asm)
- output_cfi_directive (cfi_cfa);
- else
- output_cfi (cfi_cfa, fde, for_eh);
- }
+ output_cfi (cfi_cfa, fde, for_eh);
+
cfi_cfa = NULL;
cfi_cfa_offset = NULL;
if (cfi_args_size
&& cfi_args_size->dw_cfi_oprnd1.dw_cfi_offset)
- {
- if (do_cfi_asm)
- output_cfi_directive (cfi_args_size);
- else
- output_cfi (cfi_args_size, fde, for_eh);
- }
+ output_cfi (cfi_args_size, fde, for_eh);
+
cfi_args_size = NULL;
if (cfi == NULL)
{
VEC_free (dw_cfi_ref, heap, regs);
return;
}
- else if (do_cfi_asm)
- output_cfi_directive (cfi);
else
output_cfi (cfi, fde, for_eh);
break;
@@ -3678,14 +4006,6 @@ output_cfis (cfi_vec vec, int upto, bool
}
}
-/* Like output_cfis, but emit all CFIs in the vector. */
-static void
-output_all_cfis (cfi_vec vec, bool do_cfi_asm,
- dw_fde_ref fde, bool for_eh)
-{
- output_cfis (vec, VEC_length (dw_cfi_ref, vec), do_cfi_asm, fde, for_eh);
-}
-
/* Output one FDE. */
static void
@@ -3801,7 +4121,7 @@ output_fde (dw_fde_ref fde, bool for_eh,
if (fde->dw_fde_switch_cfi_index > 0)
{
from = fde->dw_fde_switch_cfi_index;
- output_cfis (fde->dw_fde_cfi, from, false, fde, for_eh);
+ output_cfis (fde->dw_fde_cfi, from, fde, for_eh);
}
for (i = from; i < until; i++)
output_cfi (VEC_index (dw_cfi_ref, fde->dw_fde_cfi, i),
@@ -4379,13 +4699,8 @@ dwarf2out_switch_text_section (void)
|| (cold_text_section && sect == cold_text_section));
if (dwarf2out_do_cfi_asm ())
- {
- dwarf2out_do_cfi_startproc (true);
- /* As this is a different FDE, insert all current CFI instructions
- again. */
- output_all_cfis (fde->dw_fde_cfi, true, fde, true);
- }
- fde->dw_fde_switch_cfi_index = VEC_length (dw_cfi_ref, fde->dw_fde_cfi);
+ dwarf2out_do_cfi_startproc (true);
+
var_location_switch_text_section ();
set_cur_line_info_table (sect);
@@ -5490,7 +5805,7 @@ output_loc_operands_raw (dw_loc_descr_re
dw2_asm_output_data_uleb128_raw (r);
}
break;
-
+
case DW_OP_constu:
case DW_OP_plus_uconst:
case DW_OP_piece:
@@ -12472,7 +12787,7 @@ output_one_line_info_table (dw_line_info
dw2_asm_output_data (1, DW_LNS_set_prologue_end,
"set prologue end");
break;
-
+
case LI_set_epilogue_begin:
dw2_asm_output_data (1, DW_LNS_set_epilogue_begin,
"set epilogue begin");
@@ -14799,7 +15114,7 @@ static bool
decl_by_reference_p (tree decl)
{
return ((TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL
- || TREE_CODE (decl) == VAR_DECL)
+ || TREE_CODE (decl) == VAR_DECL)
&& DECL_BY_REFERENCE (decl));
}
@@ -20724,7 +21039,7 @@ gen_type_die_with_usage (tree type, dw_d
if (DECL_CONTEXT (TYPE_NAME (type))
&& TREE_CODE (DECL_CONTEXT (TYPE_NAME (type))) == NAMESPACE_DECL)
context_die = get_context_die (DECL_CONTEXT (TYPE_NAME (type)));
-
+
gen_decl_die (TYPE_NAME (type), NULL, context_die);
return;
}
@@ -21954,7 +22269,7 @@ gen_scheduled_generic_parms_dies (void)
if (generic_type_instances == NULL)
return;
-
+
FOR_EACH_VEC_ELT (tree, generic_type_instances, i, t)
gen_generic_params_dies (t);
}
@@ -23863,7 +24178,7 @@ dwarf2out_finish (const char *filename)
if (!VEC_empty (pubname_entry, pubtype_table))
{
bool empty = false;
-
+
if (flag_eliminate_unused_debug_types)
{
/* The pubtypes table might be emptied by pruning unused items. */
===================================================================
@@ -709,6 +709,15 @@ comparison_dominates_p (enum rtx_code co
return 0;
}
+/* Return true if INSN is an ADDR_VEC or ADDR_DIFF_VEC. */
+bool
+addr_vec_p (const_rtx insn)
+{
+ return (JUMP_P (insn)
+ && (GET_CODE (PATTERN (insn)) == ADDR_VEC
+ || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC));
+}
+
/* Return 1 if INSN is an unconditional jump and nothing else. */
int
===================================================================
@@ -2307,6 +2307,7 @@ extern int any_condjump_p (const_rtx);
extern int any_uncondjump_p (const_rtx);
extern rtx pc_set (const_rtx);
extern rtx condjump_label (const_rtx);
+extern bool addr_vec_p (const_rtx);
extern int simplejump_p (const_rtx);
extern int returnjump_p (rtx);
extern int eh_returnjump_p (rtx);