dwarf2cfi: Introduce dw_trace_info.
This patch only introduces the structure definition and adjusts the existing routines to use the new cur_trace global to access the variables that were moved into the structure. * dwarf2cfi.c (dw_trace_info): New. (dw_label_info): New. (cie_return_save): New. (cur_trace): New. (queued_args_size): Rename from args_size. Update all users. (cfa_store, cfa_temp, regs_saved_in_regs): Remove. (def_cfa_1): Use cur_trace instead of cfa_*. (dwarf2out_stack_adjust, record_reg_saved_in_reg): Likewise. (clobbers_queued_reg_save, reg_saved_in): Likewise. (dwarf2out_frame_debug_expr): Likewise. (create_cie_data): Split out from ... (execute_dwarf2_frame): ... here. Initialize cur_trace. From-SVN: r176704
This commit is contained in:
parent
6ffc63e112
commit
43215a89ec
|
@ -1,3 +1,18 @@
|
|||
2011-07-23 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* dwarf2cfi.c (dw_trace_info): New.
|
||||
(dw_label_info): New.
|
||||
(cie_return_save): New.
|
||||
(cur_trace): New.
|
||||
(queued_args_size): Rename from args_size. Update all users.
|
||||
(cfa_store, cfa_temp, regs_saved_in_regs): Remove.
|
||||
(def_cfa_1): Use cur_trace instead of cfa_*.
|
||||
(dwarf2out_stack_adjust, record_reg_saved_in_reg): Likewise.
|
||||
(clobbers_queued_reg_save, reg_saved_in): Likewise.
|
||||
(dwarf2out_frame_debug_expr): Likewise.
|
||||
(create_cie_data): Split out from ...
|
||||
(execute_dwarf2_frame): ... here. Initialize cur_trace.
|
||||
|
||||
2011-07-23 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* dwarf2cfi.c (regs_saved_in_regs): Allocate from heap, not gc.
|
||||
|
|
440
gcc/dwarf2cfi.c
440
gcc/dwarf2cfi.c
|
@ -74,7 +74,98 @@ typedef struct GTY(()) dw_cfi_row_struct
|
|||
HOST_WIDE_INT args_size;
|
||||
} dw_cfi_row;
|
||||
|
||||
|
||||
/* The caller's ORIG_REG is saved in SAVED_IN_REG. */
|
||||
typedef struct GTY(()) reg_saved_in_data_struct {
|
||||
rtx orig_reg;
|
||||
rtx saved_in_reg;
|
||||
} reg_saved_in_data;
|
||||
|
||||
DEF_VEC_O (reg_saved_in_data);
|
||||
DEF_VEC_ALLOC_O (reg_saved_in_data, heap);
|
||||
|
||||
/* Since we no longer have a proper CFG, we're going to create a facsimile
|
||||
of one on the fly while processing the frame-related insns.
|
||||
|
||||
We create dw_trace structures for each instruction trace beginning at
|
||||
at a label following a barrier (or beginning of the function), and
|
||||
ending at a barrier (or the end of the function).
|
||||
|
||||
As we encounter control transfer insns, we propagate the "current"
|
||||
row state across the edges to the starts of traces. If an edge goes
|
||||
to a label that is not the start of a trace, we ignore it. This
|
||||
assumes that previous compiler transformations were correct, and that
|
||||
we will reach the same row state from any source. (We can perform some
|
||||
limited validation of this assumption, but without the full CFG we
|
||||
cannot be sure of full validation coverage. It is expensive, so we
|
||||
only do so with checking enabled.)
|
||||
|
||||
All traces are members of the TRACE_INFO array, in the order in which
|
||||
they appear in the instruction stream.
|
||||
|
||||
All labels are given an LUID that indexes the LABEL_INFO array. If
|
||||
the label is the start of a trace, the TRACE pointer will be non-NULL
|
||||
and point into the TRACE_INFO array. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* The label that begins the trace. This will be NULL for the first
|
||||
trace beginning at function entry. */
|
||||
rtx label;
|
||||
|
||||
/* The row state at the beginning and end of the trace. */
|
||||
dw_cfi_row *enter_row, *exit_row;
|
||||
|
||||
/* The following variables contain data used in interpreting frame related
|
||||
expressions. These are not part of the "real" row state as defined by
|
||||
Dwarf, but it seems like they need to be propagated into a trace in case
|
||||
frame related expressions have been sunk. */
|
||||
/* ??? This seems fragile. These variables are fragments of a larger
|
||||
expression. If we do not keep the entire expression together, we risk
|
||||
not being able to put it together properly. Consider forcing targets
|
||||
to generate self-contained expressions and dropping all of the magic
|
||||
interpretation code in this file. Or at least refusing to shrink wrap
|
||||
any frame related insn that doesn't contain a complete expression. */
|
||||
|
||||
/* The register used for saving registers to the stack, and its offset
|
||||
from the CFA. */
|
||||
dw_cfa_location cfa_store;
|
||||
|
||||
/* A temporary register holding an integral value used in adjusting SP
|
||||
or setting up the store_reg. The "offset" field holds the integer
|
||||
value, not an offset. */
|
||||
dw_cfa_location cfa_temp;
|
||||
|
||||
/* A set of registers saved in other registers. This is the inverse of
|
||||
the row->reg_save info, if the entry is a DW_CFA_register. This is
|
||||
implemented as a flat array because it normally contains zero or 1
|
||||
entry, depending on the target. IA-64 is the big spender here, using
|
||||
a maximum of 5 entries. */
|
||||
VEC(reg_saved_in_data, heap) *regs_saved_in_regs;
|
||||
|
||||
} dw_trace_info;
|
||||
|
||||
DEF_VEC_O (dw_trace_info);
|
||||
DEF_VEC_ALLOC_O (dw_trace_info, heap);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
dw_trace_info *trace;
|
||||
|
||||
#ifdef ENABLE_CHECKING
|
||||
dw_cfi_row *check_row;
|
||||
#endif
|
||||
} dw_label_info;
|
||||
|
||||
DEF_VEC_O (dw_label_info);
|
||||
DEF_VEC_ALLOC_O (dw_label_info, heap);
|
||||
|
||||
/* The variables making up the pseudo-cfg, as described above. */
|
||||
#if 0
|
||||
static VEC (int, heap) *uid_luid;
|
||||
static VEC (dw_label_info, heap) *label_info;
|
||||
static VEC (dw_trace_info, heap) *trace_info;
|
||||
#endif
|
||||
|
||||
/* A vector of call frame insns for the CIE. */
|
||||
cfi_vec cie_cfi_vec;
|
||||
|
||||
|
@ -82,6 +173,8 @@ cfi_vec cie_cfi_vec;
|
|||
state provided by the CIE. */
|
||||
static GTY(()) dw_cfi_row *cie_cfi_row;
|
||||
|
||||
static GTY(()) reg_saved_in_data *cie_return_save;
|
||||
|
||||
static GTY(()) unsigned long dwarf2out_cfi_label_num;
|
||||
|
||||
/* The insn after which a new CFI note should be emitted. */
|
||||
|
@ -90,6 +183,34 @@ static rtx add_cfi_insn;
|
|||
/* When non-null, add_cfi will add the CFI to this vector. */
|
||||
static cfi_vec *add_cfi_vec;
|
||||
|
||||
/* The current instruction trace. */
|
||||
static dw_trace_info *cur_trace;
|
||||
|
||||
/* The current, i.e. most recently generated, row of the CFI table. */
|
||||
static dw_cfi_row *cur_row;
|
||||
|
||||
/* The row state from a preceeding DW_CFA_remember_state. */
|
||||
static dw_cfi_row *remember_row;
|
||||
|
||||
/* We delay emitting a register save until either (a) we reach the end
|
||||
of the prologue or (b) the register is clobbered. This clusters
|
||||
register saves so that there are fewer pc advances. */
|
||||
|
||||
typedef struct {
|
||||
rtx reg;
|
||||
rtx saved_reg;
|
||||
HOST_WIDE_INT cfa_offset;
|
||||
} queued_reg_save;
|
||||
|
||||
DEF_VEC_O (queued_reg_save);
|
||||
DEF_VEC_ALLOC_O (queued_reg_save, heap);
|
||||
|
||||
static VEC(queued_reg_save, heap) *queued_reg_saves;
|
||||
|
||||
/* The (really) current value for DW_CFA_GNU_args_size. We delay actually
|
||||
emitting this data, i.e. updating CUR_ROW, without async unwind. */
|
||||
static HOST_WIDE_INT queued_args_size;
|
||||
|
||||
/* True if remember_state should be emitted before following CFI directive. */
|
||||
static bool emit_cfa_remember;
|
||||
|
||||
|
@ -464,25 +585,6 @@ lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc, dw_cfa_location *remember)
|
|||
}
|
||||
}
|
||||
|
||||
/* The current, i.e. most recently generated, row of the CFI table. */
|
||||
static dw_cfi_row *cur_row;
|
||||
|
||||
/* The row state from a preceeding DW_CFA_remember_state. */
|
||||
static dw_cfi_row *remember_row;
|
||||
|
||||
/* The register used for saving registers to the stack, and its offset
|
||||
from the CFA. */
|
||||
static dw_cfa_location cfa_store;
|
||||
|
||||
/* A temporary register holding an integral value used in adjusting SP
|
||||
or setting up the store_reg. The "offset" field holds the integer
|
||||
value, not an offset. */
|
||||
static dw_cfa_location cfa_temp;
|
||||
|
||||
/* The (really) current value for DW_CFA_GNU_args_size. We delay actually
|
||||
emitting this data, i.e. updating CUR_ROW, without async unwind. */
|
||||
static HOST_WIDE_INT args_size;
|
||||
|
||||
/* Determine if two dw_cfa_location structures define the same data. */
|
||||
|
||||
bool
|
||||
|
@ -621,8 +723,8 @@ def_cfa_1 (dw_cfa_location *new_cfa)
|
|||
{
|
||||
dw_cfi_ref cfi;
|
||||
|
||||
if (cfa_store.reg == new_cfa->reg && new_cfa->indirect == 0)
|
||||
cfa_store.offset = new_cfa->offset;
|
||||
if (cur_trace->cfa_store.reg == new_cfa->reg && new_cfa->indirect == 0)
|
||||
cur_trace->cfa_store.offset = new_cfa->offset;
|
||||
|
||||
cfi = def_cfa_0 (&cur_row->cfa, new_cfa);
|
||||
if (cfi)
|
||||
|
@ -972,8 +1074,16 @@ dwarf2out_stack_adjust (HOST_WIDE_INT offset)
|
|||
if (loc.reg == dw_stack_pointer_regnum)
|
||||
loc.offset += offset;
|
||||
|
||||
if (cfa_store.reg == dw_stack_pointer_regnum)
|
||||
cfa_store.offset += offset;
|
||||
if (cur_trace->cfa_store.reg == dw_stack_pointer_regnum)
|
||||
cur_trace->cfa_store.offset += offset;
|
||||
|
||||
#ifndef STACK_GROWS_DOWNWARD
|
||||
offset = -offset;
|
||||
#endif
|
||||
|
||||
queued_args_size += offset;
|
||||
if (queued_args_size < 0)
|
||||
queued_args_size = 0;
|
||||
|
||||
/* ??? The assumption seems to be that if A_O_A, the only CFA adjustments
|
||||
involving the stack pointer are inside the prologue and marked as
|
||||
|
@ -983,17 +1093,9 @@ dwarf2out_stack_adjust (HOST_WIDE_INT offset)
|
|||
if (ACCUMULATE_OUTGOING_ARGS)
|
||||
return;
|
||||
|
||||
#ifndef STACK_GROWS_DOWNWARD
|
||||
offset = -offset;
|
||||
#endif
|
||||
|
||||
args_size += offset;
|
||||
if (args_size < 0)
|
||||
args_size = 0;
|
||||
|
||||
def_cfa_1 (&loc);
|
||||
if (flag_asynchronous_unwind_tables)
|
||||
dwarf2out_args_size (args_size);
|
||||
dwarf2out_args_size (queued_args_size);
|
||||
}
|
||||
|
||||
/* Check INSN to see if it looks like a push or a stack adjustment, and
|
||||
|
@ -1035,7 +1137,8 @@ dwarf2out_notice_stack_adjust (rtx insn, bool after_p)
|
|||
if (GET_CODE (insn) == SET)
|
||||
insn = SET_SRC (insn);
|
||||
gcc_assert (GET_CODE (insn) == CALL);
|
||||
dwarf2out_args_size (INTVAL (XEXP (insn, 1)));
|
||||
gcc_assert (queued_args_size == INTVAL (XEXP (insn, 1)));
|
||||
dwarf2out_args_size (queued_args_size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1043,7 +1146,7 @@ dwarf2out_notice_stack_adjust (rtx insn, bool after_p)
|
|||
if (CALL_P (insn) && !after_p)
|
||||
{
|
||||
if (!flag_asynchronous_unwind_tables)
|
||||
dwarf2out_args_size (args_size);
|
||||
dwarf2out_args_size (queued_args_size);
|
||||
return;
|
||||
}
|
||||
else if (BARRIER_P (insn))
|
||||
|
@ -1061,13 +1164,13 @@ dwarf2out_notice_stack_adjust (rtx insn, bool after_p)
|
|||
offset = 0;
|
||||
}
|
||||
|
||||
offset -= args_size;
|
||||
offset -= queued_args_size;
|
||||
#ifndef STACK_GROWS_DOWNWARD
|
||||
offset = -offset;
|
||||
#endif
|
||||
}
|
||||
else if (GET_CODE (PATTERN (insn)) == SET)
|
||||
offset = stack_adjust_offset (PATTERN (insn), args_size, 0);
|
||||
offset = stack_adjust_offset (PATTERN (insn), queued_args_size, 0);
|
||||
else if (GET_CODE (PATTERN (insn)) == PARALLEL
|
||||
|| GET_CODE (PATTERN (insn)) == SEQUENCE)
|
||||
{
|
||||
|
@ -1076,7 +1179,7 @@ dwarf2out_notice_stack_adjust (rtx insn, bool after_p)
|
|||
for (offset = 0, 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),
|
||||
args_size, offset);
|
||||
queued_args_size, offset);
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
@ -1087,38 +1190,6 @@ dwarf2out_notice_stack_adjust (rtx insn, bool after_p)
|
|||
dwarf2out_stack_adjust (offset);
|
||||
}
|
||||
|
||||
/* We delay emitting a register save until either (a) we reach the end
|
||||
of the prologue or (b) the register is clobbered. This clusters
|
||||
register saves so that there are fewer pc advances. */
|
||||
|
||||
typedef struct {
|
||||
rtx reg;
|
||||
rtx saved_reg;
|
||||
HOST_WIDE_INT cfa_offset;
|
||||
} queued_reg_save;
|
||||
|
||||
DEF_VEC_O (queued_reg_save);
|
||||
DEF_VEC_ALLOC_O (queued_reg_save, heap);
|
||||
|
||||
static VEC(queued_reg_save, heap) *queued_reg_saves;
|
||||
|
||||
/* The caller's ORIG_REG is saved in SAVED_IN_REG. */
|
||||
typedef struct GTY(()) reg_saved_in_data {
|
||||
rtx orig_reg;
|
||||
rtx saved_in_reg;
|
||||
} reg_saved_in_data;
|
||||
|
||||
DEF_VEC_O (reg_saved_in_data);
|
||||
DEF_VEC_ALLOC_O (reg_saved_in_data, heap);
|
||||
|
||||
/* A set of registers saved in other registers. This is implemented as
|
||||
a flat array because it normally contains zero or 1 entry, depending
|
||||
on the target. IA-64 is the big spender here, using a maximum of
|
||||
5 entries. */
|
||||
static VEC(reg_saved_in_data, heap) *regs_saved_in_regs;
|
||||
|
||||
static GTY(()) reg_saved_in_data *cie_return_save;
|
||||
|
||||
/* Short-hand inline for the very common D_F_R (REGNO (x)) operation. */
|
||||
/* ??? This ought to go into dwarf2out.h, except that dwarf2out.h is
|
||||
used in places where rtl is prohibited. */
|
||||
|
@ -1148,11 +1219,12 @@ record_reg_saved_in_reg (rtx dest, rtx src)
|
|||
reg_saved_in_data *elt;
|
||||
size_t i;
|
||||
|
||||
FOR_EACH_VEC_ELT (reg_saved_in_data, regs_saved_in_regs, i, elt)
|
||||
FOR_EACH_VEC_ELT (reg_saved_in_data, cur_trace->regs_saved_in_regs, i, elt)
|
||||
if (compare_reg_or_pc (elt->orig_reg, src))
|
||||
{
|
||||
if (dest == NULL)
|
||||
VEC_unordered_remove(reg_saved_in_data, regs_saved_in_regs, i);
|
||||
VEC_unordered_remove (reg_saved_in_data,
|
||||
cur_trace->regs_saved_in_regs, i);
|
||||
else
|
||||
elt->saved_in_reg = dest;
|
||||
return;
|
||||
|
@ -1161,7 +1233,8 @@ record_reg_saved_in_reg (rtx dest, rtx src)
|
|||
if (dest == NULL)
|
||||
return;
|
||||
|
||||
elt = VEC_safe_push(reg_saved_in_data, heap, regs_saved_in_regs, NULL);
|
||||
elt = VEC_safe_push (reg_saved_in_data, heap,
|
||||
cur_trace->regs_saved_in_regs, NULL);
|
||||
elt->orig_reg = src;
|
||||
elt->saved_in_reg = dest;
|
||||
}
|
||||
|
@ -1236,7 +1309,8 @@ clobbers_queued_reg_save (const_rtx insn)
|
|||
if (modified_in_p (q->reg, insn))
|
||||
return true;
|
||||
|
||||
FOR_EACH_VEC_ELT (reg_saved_in_data, regs_saved_in_regs, ir, rir)
|
||||
FOR_EACH_VEC_ELT (reg_saved_in_data,
|
||||
cur_trace->regs_saved_in_regs, ir, rir)
|
||||
if (compare_reg_or_pc (q->reg, rir->orig_reg)
|
||||
&& modified_in_p (rir->saved_in_reg, insn))
|
||||
return true;
|
||||
|
@ -1259,7 +1333,7 @@ reg_saved_in (rtx reg)
|
|||
if (q->saved_reg && regn == REGNO (q->saved_reg))
|
||||
return q->reg;
|
||||
|
||||
FOR_EACH_VEC_ELT (reg_saved_in_data, regs_saved_in_regs, i, rir)
|
||||
FOR_EACH_VEC_ELT (reg_saved_in_data, cur_trace->regs_saved_in_regs, i, rir)
|
||||
if (regn == REGNO (rir->saved_in_reg))
|
||||
return rir->orig_reg;
|
||||
|
||||
|
@ -1371,7 +1445,7 @@ dwarf2out_frame_debug_cfa_offset (rtx set)
|
|||
span = NULL;
|
||||
sregno = DWARF_FRAME_RETURN_COLUMN;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
span = targetm.dwarf_register_span (src);
|
||||
sregno = dwf_regno (src);
|
||||
|
@ -1727,7 +1801,8 @@ dwarf2out_frame_debug_expr (rtx expr)
|
|||
{
|
||||
/* Stack adjustment combining might combine some post-prologue
|
||||
stack adjustment into a prologue stack adjustment. */
|
||||
HOST_WIDE_INT offset = stack_adjust_offset (elem, args_size, 0);
|
||||
HOST_WIDE_INT offset
|
||||
= stack_adjust_offset (elem, queued_args_size, 0);
|
||||
|
||||
if (offset != 0)
|
||||
dwarf2out_stack_adjust (offset);
|
||||
|
@ -1768,8 +1843,8 @@ dwarf2out_frame_debug_expr (rtx expr)
|
|||
FP. So we just rely on the backends to only set
|
||||
RTX_FRAME_RELATED_P on appropriate insns. */
|
||||
cfa.reg = dwf_regno (dest);
|
||||
cfa_temp.reg = cfa.reg;
|
||||
cfa_temp.offset = cfa.offset;
|
||||
cur_trace->cfa_temp.reg = cfa.reg;
|
||||
cur_trace->cfa_temp.offset = cfa.offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1806,8 +1881,9 @@ dwarf2out_frame_debug_expr (rtx expr)
|
|||
offset = INTVAL (XEXP (src, 1));
|
||||
break;
|
||||
case REG:
|
||||
gcc_assert (dwf_regno (XEXP (src, 1)) == cfa_temp.reg);
|
||||
offset = cfa_temp.offset;
|
||||
gcc_assert (dwf_regno (XEXP (src, 1))
|
||||
== cur_trace->cfa_temp.reg);
|
||||
offset = cur_trace->cfa_temp.offset;
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
|
@ -1829,8 +1905,8 @@ dwarf2out_frame_debug_expr (rtx expr)
|
|||
offset = -offset;
|
||||
if (cfa.reg == dw_stack_pointer_regnum)
|
||||
cfa.offset += offset;
|
||||
if (cfa_store.reg == dw_stack_pointer_regnum)
|
||||
cfa_store.offset += offset;
|
||||
if (cur_trace->cfa_store.reg == dw_stack_pointer_regnum)
|
||||
cur_trace->cfa_store.offset += offset;
|
||||
}
|
||||
else if (dest == hard_frame_pointer_rtx)
|
||||
{
|
||||
|
@ -1863,28 +1939,29 @@ dwarf2out_frame_debug_expr (rtx expr)
|
|||
cfa.offset += offset;
|
||||
cfa.reg = dwf_regno (dest);
|
||||
/* Or used to save regs to the stack. */
|
||||
cfa_temp.reg = cfa.reg;
|
||||
cfa_temp.offset = cfa.offset;
|
||||
cur_trace->cfa_temp.reg = cfa.reg;
|
||||
cur_trace->cfa_temp.offset = cfa.offset;
|
||||
}
|
||||
|
||||
/* Rule 5 */
|
||||
else if (REG_P (XEXP (src, 0))
|
||||
&& dwf_regno (XEXP (src, 0)) == cfa_temp.reg
|
||||
&& dwf_regno (XEXP (src, 0)) == cur_trace->cfa_temp.reg
|
||||
&& XEXP (src, 1) == stack_pointer_rtx)
|
||||
{
|
||||
/* Setting a scratch register that we will use instead
|
||||
of SP for saving registers to the stack. */
|
||||
gcc_assert (cfa.reg == dw_stack_pointer_regnum);
|
||||
cfa_store.reg = dwf_regno (dest);
|
||||
cfa_store.offset = cfa.offset - cfa_temp.offset;
|
||||
cur_trace->cfa_store.reg = dwf_regno (dest);
|
||||
cur_trace->cfa_store.offset
|
||||
= cfa.offset - cur_trace->cfa_temp.offset;
|
||||
}
|
||||
|
||||
/* Rule 9 */
|
||||
else if (GET_CODE (src) == LO_SUM
|
||||
&& CONST_INT_P (XEXP (src, 1)))
|
||||
{
|
||||
cfa_temp.reg = dwf_regno (dest);
|
||||
cfa_temp.offset = INTVAL (XEXP (src, 1));
|
||||
cur_trace->cfa_temp.reg = dwf_regno (dest);
|
||||
cur_trace->cfa_temp.offset = INTVAL (XEXP (src, 1));
|
||||
}
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
@ -1893,18 +1970,18 @@ dwarf2out_frame_debug_expr (rtx expr)
|
|||
|
||||
/* Rule 6 */
|
||||
case CONST_INT:
|
||||
cfa_temp.reg = dwf_regno (dest);
|
||||
cfa_temp.offset = INTVAL (src);
|
||||
cur_trace->cfa_temp.reg = dwf_regno (dest);
|
||||
cur_trace->cfa_temp.offset = INTVAL (src);
|
||||
break;
|
||||
|
||||
/* Rule 7 */
|
||||
case IOR:
|
||||
gcc_assert (REG_P (XEXP (src, 0))
|
||||
&& dwf_regno (XEXP (src, 0)) == cfa_temp.reg
|
||||
&& dwf_regno (XEXP (src, 0)) == cur_trace->cfa_temp.reg
|
||||
&& CONST_INT_P (XEXP (src, 1)));
|
||||
|
||||
cfa_temp.reg = dwf_regno (dest);
|
||||
cfa_temp.offset |= INTVAL (XEXP (src, 1));
|
||||
cur_trace->cfa_temp.reg = dwf_regno (dest);
|
||||
cur_trace->cfa_temp.offset |= INTVAL (XEXP (src, 1));
|
||||
break;
|
||||
|
||||
/* Skip over HIGH, assuming it will be followed by a LO_SUM,
|
||||
|
@ -1931,10 +2008,11 @@ dwarf2out_frame_debug_expr (rtx expr)
|
|||
Thus we must flush whatever we have queued first. */
|
||||
dwarf2out_flush_queued_reg_saves ();
|
||||
|
||||
gcc_assert (cfa_store.reg == dwf_regno (XEXP (src, 0)));
|
||||
gcc_assert (cur_trace->cfa_store.reg
|
||||
== dwf_regno (XEXP (src, 0)));
|
||||
fde->stack_realign = 1;
|
||||
fde->stack_realignment = INTVAL (XEXP (src, 1));
|
||||
cfa_store.offset = 0;
|
||||
cur_trace->cfa_store.offset = 0;
|
||||
|
||||
if (cfa.reg != dw_stack_pointer_regnum
|
||||
&& cfa.reg != dw_frame_pointer_regnum)
|
||||
|
@ -1965,16 +2043,16 @@ dwarf2out_frame_debug_expr (rtx expr)
|
|||
offset = -INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1));
|
||||
|
||||
gcc_assert (REGNO (XEXP (XEXP (dest, 0), 0)) == STACK_POINTER_REGNUM
|
||||
&& cfa_store.reg == dw_stack_pointer_regnum);
|
||||
&& cur_trace->cfa_store.reg == dw_stack_pointer_regnum);
|
||||
|
||||
cfa_store.offset += offset;
|
||||
cur_trace->cfa_store.offset += offset;
|
||||
if (cfa.reg == dw_stack_pointer_regnum)
|
||||
cfa.offset = cfa_store.offset;
|
||||
cfa.offset = cur_trace->cfa_store.offset;
|
||||
|
||||
if (GET_CODE (XEXP (dest, 0)) == POST_MODIFY)
|
||||
offset -= cfa_store.offset;
|
||||
offset -= cur_trace->cfa_store.offset;
|
||||
else
|
||||
offset = -cfa_store.offset;
|
||||
offset = -cur_trace->cfa_store.offset;
|
||||
break;
|
||||
|
||||
/* Rule 11 */
|
||||
|
@ -1987,9 +2065,9 @@ dwarf2out_frame_debug_expr (rtx expr)
|
|||
|
||||
gcc_assert ((REGNO (XEXP (XEXP (dest, 0), 0))
|
||||
== STACK_POINTER_REGNUM)
|
||||
&& cfa_store.reg == dw_stack_pointer_regnum);
|
||||
&& cur_trace->cfa_store.reg == dw_stack_pointer_regnum);
|
||||
|
||||
cfa_store.offset += offset;
|
||||
cur_trace->cfa_store.offset += offset;
|
||||
|
||||
/* Rule 18: If stack is aligned, we will use FP as a
|
||||
reference to represent the address of the stored
|
||||
|
@ -1999,16 +2077,16 @@ dwarf2out_frame_debug_expr (rtx expr)
|
|||
&& src == hard_frame_pointer_rtx)
|
||||
{
|
||||
gcc_assert (cfa.reg != dw_frame_pointer_regnum);
|
||||
cfa_store.offset = 0;
|
||||
cur_trace->cfa_store.offset = 0;
|
||||
}
|
||||
|
||||
if (cfa.reg == dw_stack_pointer_regnum)
|
||||
cfa.offset = cfa_store.offset;
|
||||
cfa.offset = cur_trace->cfa_store.offset;
|
||||
|
||||
if (GET_CODE (XEXP (dest, 0)) == POST_DEC)
|
||||
offset += -cfa_store.offset;
|
||||
offset += -cur_trace->cfa_store.offset;
|
||||
else
|
||||
offset = -cfa_store.offset;
|
||||
offset = -cur_trace->cfa_store.offset;
|
||||
break;
|
||||
|
||||
/* Rule 12 */
|
||||
|
@ -2029,12 +2107,12 @@ dwarf2out_frame_debug_expr (rtx expr)
|
|||
|
||||
if (cfa.reg == regno)
|
||||
offset -= cfa.offset;
|
||||
else if (cfa_store.reg == regno)
|
||||
offset -= cfa_store.offset;
|
||||
else if (cur_trace->cfa_store.reg == regno)
|
||||
offset -= cur_trace->cfa_store.offset;
|
||||
else
|
||||
{
|
||||
gcc_assert (cfa_temp.reg == regno);
|
||||
offset -= cfa_temp.offset;
|
||||
gcc_assert (cur_trace->cfa_temp.reg == regno);
|
||||
offset -= cur_trace->cfa_temp.offset;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -2047,21 +2125,22 @@ dwarf2out_frame_debug_expr (rtx expr)
|
|||
|
||||
if (cfa.reg == regno)
|
||||
offset = -cfa.offset;
|
||||
else if (cfa_store.reg == regno)
|
||||
offset = -cfa_store.offset;
|
||||
else if (cur_trace->cfa_store.reg == regno)
|
||||
offset = -cur_trace->cfa_store.offset;
|
||||
else
|
||||
{
|
||||
gcc_assert (cfa_temp.reg == regno);
|
||||
offset = -cfa_temp.offset;
|
||||
gcc_assert (cur_trace->cfa_temp.reg == regno);
|
||||
offset = -cur_trace->cfa_temp.offset;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* Rule 14 */
|
||||
case POST_INC:
|
||||
gcc_assert (cfa_temp.reg == dwf_regno (XEXP (XEXP (dest, 0), 0)));
|
||||
offset = -cfa_temp.offset;
|
||||
cfa_temp.offset -= GET_MODE_SIZE (GET_MODE (dest));
|
||||
gcc_assert (cur_trace->cfa_temp.reg
|
||||
== dwf_regno (XEXP (XEXP (dest, 0), 0)));
|
||||
offset = -cur_trace->cfa_temp.offset;
|
||||
cur_trace->cfa_temp.offset -= GET_MODE_SIZE (GET_MODE (dest));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -2453,7 +2532,7 @@ add_cfis_to_fde (void)
|
|||
}
|
||||
|
||||
/* Scan the function and create the initial set of CFI notes. */
|
||||
|
||||
|
||||
static void
|
||||
create_cfi_notes (void)
|
||||
{
|
||||
|
@ -2692,6 +2771,60 @@ initial_return_save (rtx rtl)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
create_cie_data (void)
|
||||
{
|
||||
dw_cfa_location loc;
|
||||
dw_trace_info cie_trace;
|
||||
|
||||
dw_stack_pointer_regnum = DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM);
|
||||
dw_frame_pointer_regnum = DWARF_FRAME_REGNUM (HARD_FRAME_POINTER_REGNUM);
|
||||
|
||||
memset (&cie_trace, 0, sizeof(cie_trace));
|
||||
cur_trace = &cie_trace;
|
||||
|
||||
add_cfi_vec = &cie_cfi_vec;
|
||||
cie_cfi_row = cur_row = new_cfi_row ();
|
||||
|
||||
/* On entry, the Canonical Frame Address is at SP. */
|
||||
memset(&loc, 0, sizeof (loc));
|
||||
loc.reg = dw_stack_pointer_regnum;
|
||||
loc.offset = INCOMING_FRAME_SP_OFFSET;
|
||||
def_cfa_1 (&loc);
|
||||
|
||||
if (targetm.debug_unwind_info () == UI_DWARF2
|
||||
|| targetm_common.except_unwind_info (&global_options) == UI_DWARF2)
|
||||
{
|
||||
initial_return_save (INCOMING_RETURN_ADDR_RTX);
|
||||
|
||||
/* For a few targets, we have the return address incoming into a
|
||||
register, but choose a different return column. This will result
|
||||
in a DW_CFA_register for the return, and an entry in
|
||||
regs_saved_in_regs to match. If the target later stores that
|
||||
return address register to the stack, we want to be able to emit
|
||||
the DW_CFA_offset against the return column, not the intermediate
|
||||
save register. Save the contents of regs_saved_in_regs so that
|
||||
we can re-initialize it at the start of each function. */
|
||||
switch (VEC_length (reg_saved_in_data, cie_trace.regs_saved_in_regs))
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
cie_return_save = ggc_alloc_reg_saved_in_data ();
|
||||
*cie_return_save = *VEC_index (reg_saved_in_data,
|
||||
cie_trace.regs_saved_in_regs, 0);
|
||||
VEC_free (reg_saved_in_data, heap, cie_trace.regs_saved_in_regs);
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
|
||||
add_cfi_vec = NULL;
|
||||
cur_row = NULL;
|
||||
cur_trace = NULL;
|
||||
}
|
||||
|
||||
/* Annotate the function with NOTE_INSN_CFI notes to record the CFI
|
||||
state at each location within the function. These notes will be
|
||||
emitted during pass_final. */
|
||||
|
@ -2699,68 +2832,26 @@ initial_return_save (rtx rtl)
|
|||
static unsigned int
|
||||
execute_dwarf2_frame (void)
|
||||
{
|
||||
dw_trace_info dummy_trace;
|
||||
|
||||
gcc_checking_assert (queued_reg_saves == NULL);
|
||||
gcc_checking_assert (regs_saved_in_regs == NULL);
|
||||
|
||||
/* The first time we're called, compute the incoming frame state. */
|
||||
if (cie_cfi_vec == NULL)
|
||||
{
|
||||
dw_cfa_location loc;
|
||||
create_cie_data ();
|
||||
|
||||
dw_stack_pointer_regnum = DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM);
|
||||
dw_frame_pointer_regnum = DWARF_FRAME_REGNUM (HARD_FRAME_POINTER_REGNUM);
|
||||
|
||||
add_cfi_vec = &cie_cfi_vec;
|
||||
cie_cfi_row = cur_row = new_cfi_row ();
|
||||
|
||||
/* On entry, the Canonical Frame Address is at SP. */
|
||||
memset(&loc, 0, sizeof (loc));
|
||||
loc.reg = dw_stack_pointer_regnum;
|
||||
loc.offset = INCOMING_FRAME_SP_OFFSET;
|
||||
def_cfa_1 (&loc);
|
||||
|
||||
if (targetm.debug_unwind_info () == UI_DWARF2
|
||||
|| targetm_common.except_unwind_info (&global_options) == UI_DWARF2)
|
||||
{
|
||||
initial_return_save (INCOMING_RETURN_ADDR_RTX);
|
||||
|
||||
/* For a few targets, we have the return address incoming into a
|
||||
register, but choose a different return column. This will result
|
||||
in a DW_CFA_register for the return, and an entry in
|
||||
regs_saved_in_regs to match. If the target later stores that
|
||||
return address register to the stack, we want to be able to emit
|
||||
the DW_CFA_offset against the return column, not the intermediate
|
||||
save register. Save the contents of regs_saved_in_regs so that
|
||||
we can re-initialize it at the start of each function. */
|
||||
switch (VEC_length (reg_saved_in_data, regs_saved_in_regs))
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
cie_return_save = ggc_alloc_reg_saved_in_data ();
|
||||
*cie_return_save = *VEC_index (reg_saved_in_data,
|
||||
regs_saved_in_regs, 0);
|
||||
VEC_pop (reg_saved_in_data, regs_saved_in_regs);
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
|
||||
add_cfi_vec = NULL;
|
||||
}
|
||||
memset (&dummy_trace, 0, sizeof(dummy_trace));
|
||||
cur_trace = &dummy_trace;
|
||||
|
||||
/* Set up state for generating call frame debug info. */
|
||||
cur_row = copy_cfi_row (cie_cfi_row);
|
||||
if (cie_return_save)
|
||||
VEC_safe_push (reg_saved_in_data, heap,
|
||||
regs_saved_in_regs, cie_return_save);
|
||||
cur_trace->regs_saved_in_regs, cie_return_save);
|
||||
|
||||
cfa_store = cur_row->cfa;
|
||||
args_size = 0;
|
||||
|
||||
memset (&cfa_temp, 0, sizeof(cfa_temp));
|
||||
cfa_temp.reg = INVALID_REGNUM;
|
||||
cur_trace->cfa_store = cur_row->cfa;
|
||||
cur_trace->cfa_temp.reg = INVALID_REGNUM;
|
||||
queued_args_size = 0;
|
||||
|
||||
dwarf2out_alloc_current_fde ();
|
||||
|
||||
|
@ -2771,11 +2862,12 @@ execute_dwarf2_frame (void)
|
|||
/* Reset all function-specific information, particularly for GC. */
|
||||
XDELETEVEC (barrier_args_size);
|
||||
barrier_args_size = NULL;
|
||||
VEC_free (reg_saved_in_data, heap, regs_saved_in_regs);
|
||||
VEC_free (reg_saved_in_data, heap, cur_trace->regs_saved_in_regs);
|
||||
VEC_free (queued_reg_save, heap, queued_reg_saves);
|
||||
|
||||
free_cfi_row (cur_row);
|
||||
cur_row = NULL;
|
||||
cur_trace = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2864,7 +2956,7 @@ output_cfa_loc (dw_cfi_ref cfi, int for_eh)
|
|||
|
||||
if (cfi->dw_cfi_opc == DW_CFA_expression)
|
||||
{
|
||||
unsigned r =
|
||||
unsigned r =
|
||||
DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
|
||||
dw2_asm_output_data (1, r, NULL);
|
||||
loc = cfi->dw_cfi_oprnd2.dw_cfi_loc;
|
||||
|
@ -2890,7 +2982,7 @@ output_cfa_loc_raw (dw_cfi_ref cfi)
|
|||
|
||||
if (cfi->dw_cfi_opc == DW_CFA_expression)
|
||||
{
|
||||
unsigned r =
|
||||
unsigned r =
|
||||
DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
|
||||
fprintf (asm_out_file, "%#x,", r);
|
||||
loc = cfi->dw_cfi_oprnd2.dw_cfi_loc;
|
||||
|
|
Loading…
Reference in New Issue