&& sreg == INVALID_REGNUM)
{
cfi->dw_cfi_opc = DW_CFA_expression;
- cfi->dw_cfi_oprnd2.dw_cfi_reg_num = reg;
- cfi->dw_cfi_oprnd1.dw_cfi_loc
+ cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
+ cfi->dw_cfi_oprnd2.dw_cfi_loc
= build_cfa_aligned_loc (offset, fde->stack_realignment);
}
else if (sreg == INVALID_REGNUM)
&& cfa.indirect == 0
&& cfa.reg != HARD_FRAME_POINTER_REGNUM
effects: Use DW_CFA_def_cfa_expression to define cfa
- cfa.reg == fde->drap_reg
-
- Rule 20:
- (set reg fde->drap_reg)
- constraints: fde->vdrap_reg == INVALID_REGNUM
- effects: fde->vdrap_reg = reg.
- (set mem fde->drap_reg)
- constraints: fde->drap_reg_saved == 1
- effects: none. */
+ cfa.reg == fde->drap_reg */
static void
dwarf2out_frame_debug_expr (rtx expr, const char *label)
fde = current_fde ();
- if (REG_P (src)
- && fde
- && fde->drap_reg == REGNO (src)
- && (fde->drap_reg_saved
- || REG_P (dest)))
- {
- /* Rule 20 */
- /* If we are saving dynamic realign argument pointer to a
- register, the destination is virtual dynamic realign
- argument pointer. It may be used to access argument. */
- if (REG_P (dest))
- {
- gcc_assert (fde->vdrap_reg == INVALID_REGNUM);
- fde->vdrap_reg = REGNO (dest);
- }
- return;
- }
-
switch (GET_CODE (dest))
{
case REG:
handled_one = true;
break;
+ case REG_CFA_SET_VDRAP:
+ n = XEXP (note, 0);
+ if (REG_P (n))
+ {
+ dw_fde_ref fde = current_fde ();
+ if (fde)
+ {
+ gcc_assert (fde->vdrap_reg == INVALID_REGNUM);
+ if (REG_P (n))
+ fde->vdrap_reg = REGNO (n);
+ }
+ }
+ handled_one = true;
+ break;
+
default:
break;
}
case DW_CFA_same_value:
case DW_CFA_def_cfa_register:
case DW_CFA_register:
+ case DW_CFA_expression:
return dw_cfi_oprnd_reg_num;
case DW_CFA_def_cfa_offset:
return dw_cfi_oprnd_offset;
case DW_CFA_def_cfa_expression:
- case DW_CFA_expression:
return dw_cfi_oprnd_loc;
default:
case DW_CFA_register:
return dw_cfi_oprnd_reg_num;
+ case DW_CFA_expression:
+ return dw_cfi_oprnd_loc;
+
default:
return dw_cfi_oprnd_unused;
}
unsigned long size;
if (cfi->dw_cfi_opc == DW_CFA_expression)
- dw2_asm_output_data (1, cfi->dw_cfi_oprnd2.dw_cfi_reg_num, NULL);
+ {
+ dw2_asm_output_data (1, cfi->dw_cfi_oprnd1.dw_cfi_reg_num, NULL);
+ loc = cfi->dw_cfi_oprnd2.dw_cfi_loc;
+ }
+ else
+ loc = cfi->dw_cfi_oprnd1.dw_cfi_loc;
/* Output the size of the block. */
- loc = cfi->dw_cfi_oprnd1.dw_cfi_loc;
size = size_of_locs (loc);
dw2_asm_output_data_uleb128 (size, NULL);
unsigned long size;
if (cfi->dw_cfi_opc == DW_CFA_expression)
- fprintf (asm_out_file, "0x%x,", cfi->dw_cfi_oprnd2.dw_cfi_reg_num);
+ {
+ fprintf (asm_out_file, "0x%x,", cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+ loc = cfi->dw_cfi_oprnd2.dw_cfi_loc;
+ }
+ else
+ loc = cfi->dw_cfi_oprnd1.dw_cfi_loc;
/* Output the size of the block. */
- loc = cfi->dw_cfi_oprnd1.dw_cfi_loc;
size = size_of_locs (loc);
dw2_asm_output_data_uleb128_raw (size);
fputc (',', asm_out_file);
static void dwarf2out_undef (unsigned int, const char *);
static void dwarf2out_start_source_file (unsigned, const char *);
static void dwarf2out_end_source_file (unsigned);
+static void dwarf2out_function_decl (tree);
static void dwarf2out_begin_block (unsigned, unsigned);
static void dwarf2out_end_block (unsigned, unsigned);
static bool dwarf2out_ignore_block (const_tree);
dwarf2out_end_epilogue,
dwarf2out_begin_function,
debug_nothing_int, /* end_function */
- dwarf2out_decl, /* function_decl */
+ dwarf2out_function_decl, /* function_decl */
dwarf2out_global_decl,
dwarf2out_type_decl, /* type_decl */
dwarf2out_imported_module_or_decl,
struct GTY ((chain_next ("%h.next"))) var_loc_node {
rtx GTY (()) var_loc_note;
const char * GTY (()) label;
- const char * GTY (()) section_label;
struct var_loc_node * GTY (()) next;
};
return new_loc_descr (DW_OP_fbreg, offset, 0);
}
}
- else if (fde
- && fde->drap_reg != INVALID_REGNUM
+ else if (!optimize
+ && fde
&& (fde->drap_reg == REGNO (reg)
|| fde->vdrap_reg == REGNO (reg)))
{
/* Use cfa+offset to represent the location of arguments passed
- on stack when drap is used to align stack. */
+ on the stack when drap is used to align stack.
+ Only do this when not optimizing, for optimized code var-tracking
+ is supposed to track where the arguments live and the register
+ used as vdrap or drap in some spot might be used for something
+ else in other part of the routine. */
return new_loc_descr (DW_OP_fbreg, offset, 0);
}
{
rtx rtl = *rtlp;
+ if (GET_CODE (rtl) == UNSPEC)
+ {
+ /* If delegitimize_address couldn't do anything with the UNSPEC, assume
+ we can't express it in the debug info. */
+#ifdef ENABLE_CHECKING
+ inform (current_function_decl
+ ? DECL_SOURCE_LOCATION (current_function_decl)
+ : UNKNOWN_LOCATION,
+ "non-delegitimized UNSPEC %d found in variable location",
+ XINT (rtl, 1));
+#endif
+ expansion_failed (NULL_TREE, rtl,
+ "UNSPEC hasn't been delegitimized.\n");
+ return 1;
+ }
+
if (GET_CODE (rtl) != SYMBOL_REF)
return 0;
case POPCOUNT:
case PARITY:
case ASM_OPERANDS:
+ case VEC_MERGE:
+ case VEC_SELECT:
+ case VEC_CONCAT:
+ case VEC_DUPLICATE:
case UNSPEC:
case HIGH:
/* If delegitimize_address couldn't do anything with the UNSPEC, we
case VAR_LOCATION:
/* Single part. */
- if (GET_CODE (XEXP (rtl, 1)) != PARALLEL)
+ if (GET_CODE (PAT_VAR_LOCATION_LOC (rtl)) != PARALLEL)
{
- loc_result = loc_descriptor (XEXP (XEXP (rtl, 1), 0), mode,
- initialized);
+ rtx loc = PAT_VAR_LOCATION_LOC (rtl);
+ if (GET_CODE (loc) == EXPR_LIST)
+ loc = XEXP (loc, 0);
+ loc_result = loc_descriptor (loc, mode, initialized);
break;
}
{
gcc_assert (GET_CODE (varloc) == VAR_LOCATION);
/* Single part. */
- if (GET_CODE (XEXP (varloc, 1)) != PARALLEL)
+ if (GET_CODE (PAT_VAR_LOCATION_LOC (varloc)) != PARALLEL)
{
- varloc = XEXP (XEXP (varloc, 1), 0);
+ varloc = PAT_VAR_LOCATION_LOC (varloc);
+ if (GET_CODE (varloc) == EXPR_LIST)
+ varloc = XEXP (varloc, 0);
mode = GET_MODE (varloc);
if (MEM_P (varloc))
{
&& !DECL_HARD_REGISTER (decl)
&& DECL_MODE (decl) != VOIDmode)
{
- rtl = DECL_RTL (decl);
- /* Reset DECL_RTL back, as various parts of the compiler expects
- DECL_RTL set meaning it is actually going to be output. */
- SET_DECL_RTL (decl, NULL);
+ rtl = make_decl_rtl_for_debug (decl);
if (!MEM_P (rtl)
|| GET_CODE (XEXP (rtl, 0)) != SYMBOL_REF
|| SYMBOL_REF_DECL (XEXP (rtl, 0)) != decl)
node = loc_list->first;
rtl = NOTE_VAR_LOCATION_LOC (node->var_loc_note);
- if (GET_CODE (rtl) != PARALLEL)
+ if (GET_CODE (rtl) == EXPR_LIST)
rtl = XEXP (rtl, 0);
if ((CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING)
&& add_const_value_attribute (die, rtl))
dw_die_ref context_die)
{
tree node_or_origin = node ? node : origin;
+ tree ultimate_origin;
dw_die_ref parm_die
= new_die (DW_TAG_formal_parameter, context_die, node);
switch (TREE_CODE_CLASS (TREE_CODE (node_or_origin)))
{
case tcc_declaration:
- if (!origin)
- origin = decl_ultimate_origin (node);
+ ultimate_origin = decl_ultimate_origin (node_or_origin);
+ if (node || ultimate_origin)
+ origin = ultimate_origin;
if (origin != NULL)
add_abstract_origin_attribute (parm_die, origin);
else
HOST_WIDE_INT off;
tree com_decl;
tree decl_or_origin = decl ? decl : origin;
+ tree ultimate_origin;
dw_die_ref var_die;
dw_die_ref old_die = decl ? lookup_decl_die (decl) : NULL;
dw_die_ref origin_die;
int declaration = (DECL_EXTERNAL (decl_or_origin)
|| class_or_namespace_scope_p (context_die));
- if (!origin)
- origin = decl_ultimate_origin (decl);
-
+ ultimate_origin = decl_ultimate_origin (decl_or_origin);
+ if (decl || ultimate_origin)
+ origin = ultimate_origin;
com_decl = fortran_common (decl_or_origin, &off);
/* Symbol in common gets emitted as a child of the common block, in the form
{
dw_die_ref die;
tree decl_or_origin = decl ? decl : origin;
- tree ultimate_origin = origin ? decl_ultimate_origin (origin) : NULL;
-
- if (ultimate_origin)
- origin = ultimate_origin;
if (TREE_CODE (decl_or_origin) == FUNCTION_DECL)
die = lookup_decl_die (decl_or_origin);
gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
{
tree decl_or_origin = decl ? decl : origin;
- tree class_origin = NULL;
+ tree class_origin = NULL, ultimate_origin;
if (DECL_P (decl_or_origin) && DECL_IGNORED_P (decl_or_origin))
return;
/* If we're emitting a clone, emit info for the abstract instance. */
if (origin || DECL_ORIGIN (decl) != decl)
- dwarf2out_abstract_function (origin ? origin : DECL_ABSTRACT_ORIGIN (decl));
+ dwarf2out_abstract_function (origin
+ ? DECL_ORIGIN (origin)
+ : DECL_ABSTRACT_ORIGIN (decl));
/* If we're emitting an out-of-line copy of an inline function,
emit info for the abstract instance and set up to refer to it. */
complicated because of the possibility that the VAR_DECL really
represents an inlined instance of a formal parameter for an inline
function. */
- if (!origin)
- origin = decl_ultimate_origin (decl);
- if (origin != NULL_TREE && TREE_CODE (origin) == PARM_DECL)
+ ultimate_origin = decl_ultimate_origin (decl_or_origin);
+ if (ultimate_origin != NULL_TREE
+ && TREE_CODE (ultimate_origin) == PARM_DECL)
gen_formal_parameter_die (decl, origin,
true /* Emit name attribute. */,
context_die);
gen_decl_die (decl, NULL, context_die);
}
+/* Write the debugging output for DECL. */
+
+static void
+dwarf2out_function_decl (tree decl)
+{
+ dwarf2out_decl (decl);
+
+ htab_empty (decl_loc_table);
+}
+
/* Output a marker (i.e. a label) for the beginning of the generated code for
a lexical block. */
newloc->label = last_postcall_label;
}
- if (cfun && in_cold_section_p)
- newloc->section_label = crtl->subsections.cold_section_label;
- else
- newloc->section_label = text_section_label;
-
last_var_location_insn = next_real;
last_in_cold_section_p = in_cold_section_p;
}
static void
dwarf2out_begin_function (tree fun)
{
- htab_empty (decl_loc_table);
-
if (function_section (fun) != text_section)
have_multiple_function_sections = true;