named_section_eh_frame_section (void)
{
#ifdef EH_FRAME_SECTION_NAME
-#ifdef HAVE_LD_RO_RW_SECTION_MIXING
- int fde_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0);
- int per_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
- int lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
int flags;
- flags = (! flag_pic
- || ((fde_encoding & 0x70) != DW_EH_PE_absptr
- && (fde_encoding & 0x70) != DW_EH_PE_aligned
- && (per_encoding & 0x70) != DW_EH_PE_absptr
- && (per_encoding & 0x70) != DW_EH_PE_aligned
- && (lsda_encoding & 0x70) != DW_EH_PE_absptr
- && (lsda_encoding & 0x70) != DW_EH_PE_aligned))
- ? 0 : SECTION_WRITE;
+ if (EH_TABLES_CAN_BE_READ_ONLY)
+ {
+ int fde_encoding;
+ int per_encoding;
+ int lsda_encoding;
+
+ fde_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0);
+ per_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
+ lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
+ flags = (! flag_pic
+ || ((fde_encoding & 0x70) != DW_EH_PE_absptr
+ && (fde_encoding & 0x70) != DW_EH_PE_aligned
+ && (per_encoding & 0x70) != DW_EH_PE_absptr
+ && (per_encoding & 0x70) != DW_EH_PE_aligned
+ && (lsda_encoding & 0x70) != DW_EH_PE_absptr
+ && (lsda_encoding & 0x70) != DW_EH_PE_aligned))
+ ? 0 : SECTION_WRITE;
+ }
+ else
+ flags = SECTION_WRITE;
named_section_flags (EH_FRAME_SECTION_NAME, flags);
-#else
- named_section_flags (EH_FRAME_SECTION_NAME, SECTION_WRITE);
-#endif
#endif
}
static HOST_WIDE_INT stack_adjust_offset (rtx);
static void output_cfi (dw_cfi_ref, dw_fde_ref, int);
static void output_call_frame_info (int);
-static void dwarf2out_stack_adjust (rtx);
+static void dwarf2out_stack_adjust (rtx, bool);
static void flush_queued_reg_saves (void);
static bool clobbers_queued_reg_save (rtx);
static void dwarf2out_frame_debug_expr (rtx, const char *);
much extra space it needs to pop off the stack. */
static void
-dwarf2out_stack_adjust (rtx insn)
+dwarf2out_stack_adjust (rtx insn, bool after_p)
{
HOST_WIDE_INT offset;
const char *label;
if (prologue_epilogue_contains (insn) || sibcall_epilogue_contains (insn))
return;
- if (!flag_asynchronous_unwind_tables && CALL_P (insn))
+ /* If only calls can throw, and we have a frame pointer,
+ save up adjustments until we see the CALL_INSN. */
+ if (!flag_asynchronous_unwind_tables && cfa.reg != STACK_POINTER_REGNUM)
{
- /* Extract the size of the args from the CALL rtx itself. */
- insn = PATTERN (insn);
- if (GET_CODE (insn) == PARALLEL)
- insn = XVECEXP (insn, 0, 0);
- if (GET_CODE (insn) == SET)
- insn = SET_SRC (insn);
- gcc_assert (GET_CODE (insn) == CALL);
-
- dwarf2out_args_size ("", INTVAL (XEXP (insn, 1)));
+ if (CALL_P (insn) && !after_p)
+ {
+ /* Extract the size of the args from the CALL rtx itself. */
+ insn = PATTERN (insn);
+ if (GET_CODE (insn) == PARALLEL)
+ insn = XVECEXP (insn, 0, 0);
+ if (GET_CODE (insn) == SET)
+ insn = SET_SRC (insn);
+ gcc_assert (GET_CODE (insn) == CALL);
+ dwarf2out_args_size ("", INTVAL (XEXP (insn, 1)));
+ }
return;
}
- /* If only calls can throw, and we have a frame pointer,
- save up adjustments until we see the CALL_INSN. */
- else if (!flag_asynchronous_unwind_tables && cfa.reg != STACK_POINTER_REGNUM)
- return;
-
- if (BARRIER_P (insn))
+ if (CALL_P (insn) && !after_p)
+ {
+ if (!flag_asynchronous_unwind_tables)
+ dwarf2out_args_size ("", args_size);
+ return;
+ }
+ else if (BARRIER_P (insn))
{
/* When we see a BARRIER, we know to reset args_size to 0. Usually
the compiler will have already emitted a stack adjustment, but
label = dwarf2out_cfi_label ();
def_cfa_1 (label, &cfa);
- dwarf2out_args_size (label, args_size);
+ if (flag_asynchronous_unwind_tables)
+ dwarf2out_args_size (label, args_size);
}
#endif
(set (mem (postinc <reg1>:cfa_temp <const_int>)) <reg2>)
effects: cfa.reg = <reg1>
cfa.base_offset = -cfa_temp.offset
- cfa_temp.offset -= mode_size(mem) */
+ cfa_temp.offset -= mode_size(mem)
+
+ Rule 15:
+ (set <reg> {unspec, unspec_volatile})
+ effects: target-dependent */
static void
dwarf2out_frame_debug_expr (rtx expr, const char *label)
{
/* Saving a register in a register. */
gcc_assert (call_used_regs [REGNO (dest)]
- && !fixed_regs [REGNO (dest)]);
+ && (!fixed_regs [REGNO (dest)]
+ /* For the SPARC and its register window. */
+ || DWARF_FRAME_REGNUM (REGNO (src))
+ == DWARF_FRAME_RETURN_COLUMN));
queue_reg_save (label, src, dest, 0);
}
break;
case HIGH:
break;
+ /* Rule 15 */
+ case UNSPEC:
+ case UNSPEC_VOLATILE:
+ gcc_assert (targetm.dwarf_handle_frame_unspec);
+ targetm.dwarf_handle_frame_unspec (label, expr, XINT (src, 1));
+ break;
+
default:
gcc_unreachable ();
}
/* Record call frame debugging information for INSN, which either
sets SP or FP (adjusting how we calculate the frame address) or saves a
- register to the stack. If INSN is NULL_RTX, initialize our state. */
+ register to the stack. If INSN is NULL_RTX, initialize our state.
+
+ If AFTER_P is false, we're being called before the insn is emitted,
+ otherwise after. Call instructions get invoked twice. */
void
-dwarf2out_frame_debug (rtx insn)
+dwarf2out_frame_debug (rtx insn, bool after_p)
{
const char *label;
rtx src;
if (! RTX_FRAME_RELATED_P (insn))
{
if (!ACCUMULATE_OUTGOING_ARGS)
- dwarf2out_stack_adjust (insn);
-
+ dwarf2out_stack_adjust (insn, after_p);
return;
}
/* If we make FDEs linkonce, we may have to emit an empty label for
an FDE that wouldn't otherwise be emitted. We want to avoid
having an FDE kept around when the function it refers to is
- discarded. (Example where this matters: a primary function
+ discarded. Example where this matters: a primary function
template in C++ requires EH information, but an explicit
specialization doesn't. */
if (TARGET_USES_WEAK_UNWIND_INFO
for (i = 0; i < fde_table_in_use; i++)
if ((fde_table[i].nothrow || fde_table[i].all_throwers_are_sibcalls)
&& !fde_table[i].uses_eh_lsda
- && ! DECL_ONE_ONLY (fde_table[i].decl))
+ && ! DECL_WEAK (fde_table[i].decl))
targetm.asm_out.unwind_label (asm_out_file, fde_table[i].decl,
for_eh, /* empty */ 1);
for (i = 0; i < fde_table_in_use; i++)
if (fde_table[i].uses_eh_lsda)
any_eh_needed = any_lsda_needed = true;
- else if (TARGET_USES_WEAK_UNWIND_INFO
- && DECL_ONE_ONLY (fde_table[i].decl))
+ else if (TARGET_USES_WEAK_UNWIND_INFO && DECL_WEAK (fde_table[i].decl))
any_eh_needed = true;
else if (! fde_table[i].nothrow
&& ! fde_table[i].all_throwers_are_sibcalls)
/* Don't emit EH unwind info for leaf functions that don't need it. */
if (for_eh && !flag_asynchronous_unwind_tables && flag_exceptions
&& (fde->nothrow || fde->all_throwers_are_sibcalls)
- && (! TARGET_USES_WEAK_UNWIND_INFO || ! DECL_ONE_ONLY (fde->decl))
+ && ! (TARGET_USES_WEAK_UNWIND_INFO && DECL_WEAK (fde_table[i].decl))
&& !fde->uses_eh_lsda)
continue;
static const char *decl_start_label (tree);
#endif
static void gen_array_type_die (tree, dw_die_ref);
-static void gen_set_type_die (tree, dw_die_ref);
#if 0
static void gen_entry_point_die (tree, dw_die_ref);
#endif
case CHAR_TYPE:
return 1;
- case SET_TYPE:
case ARRAY_TYPE:
case RECORD_TYPE:
case UNION_TYPE:
}
break;
+ case FIX_TRUNC_EXPR:
+ case FIX_CEIL_EXPR:
+ case FIX_FLOOR_EXPR:
+ case FIX_ROUND_EXPR:
+ return 0;
+
default:
/* Leave front-end specific codes as simply unknown. This comes
up, for instance, with the C STMT_EXPR. */
{
if (rtl == NULL_RTX || is_pseudo_reg (rtl))
{
- tree declared_type = type_main_variant (TREE_TYPE (decl));
- tree passed_type = type_main_variant (DECL_ARG_TYPE (decl));
+ tree declared_type = TREE_TYPE (decl);
+ tree passed_type = DECL_ARG_TYPE (decl);
+ enum machine_mode dmode = TYPE_MODE (declared_type);
+ enum machine_mode pmode = TYPE_MODE (passed_type);
/* This decl represents a formal parameter which was optimized out.
Note that DECL_INCOMING_RTL may be NULL in here, but we handle
all cases where (rtl == NULL_RTX) just below. */
- if (declared_type == passed_type)
- rtl = DECL_INCOMING_RTL (decl);
- else if (! BYTES_BIG_ENDIAN
- && TREE_CODE (declared_type) == INTEGER_TYPE
- && (GET_MODE_SIZE (TYPE_MODE (declared_type))
- <= GET_MODE_SIZE (TYPE_MODE (passed_type))))
+ if (dmode == pmode)
rtl = DECL_INCOMING_RTL (decl);
+ else if (SCALAR_INT_MODE_P (dmode)
+ && GET_MODE_SIZE (dmode) <= GET_MODE_SIZE (pmode)
+ && DECL_INCOMING_RTL (decl))
+ {
+ rtx inc = DECL_INCOMING_RTL (decl);
+ if (REG_P (inc))
+ rtl = inc;
+ else if (MEM_P (inc))
+ {
+ if (BYTES_BIG_ENDIAN)
+ rtl = adjust_address_nv (inc, dmode,
+ GET_MODE_SIZE (pmode)
+ - GET_MODE_SIZE (dmode));
+ else
+ rtl = inc;
+ }
+ }
}
/* If the parm was passed in registers, but lives on the stack, then
add_type_attribute (array_die, element_type, 0, 0, context_die);
}
-static void
-gen_set_type_die (tree type, dw_die_ref context_die)
-{
- dw_die_ref type_die
- = new_die (DW_TAG_set_type, scope_die_for (type, context_die), type);
-
- equate_type_number_to_die (type, type_die);
- add_type_attribute (type_die, TREE_TYPE (type), 0, 0, context_die);
-}
-
#if 0
static void
gen_entry_point_die (tree decl, dw_die_ref context_die)
}
#endif
}
+ /* Add the calling convention attribute if requested. */
+ add_calling_convention_attribute (subr_die, TREE_TYPE (decl));
+
}
/* Generate a DIE to represent a declared data object. */
equate_type_number_to_die (type, subr_die);
add_prototyped_attribute (subr_die, type);
add_type_attribute (subr_die, return_type, 0, 0, context_die);
- add_calling_convention_attribute (subr_die, type);
gen_formal_types_die (type, subr_die);
}
gen_ptr_to_mbr_type_die (type, context_die);
break;
- case SET_TYPE:
- gen_type_die (TYPE_DOMAIN (type), context_die);
- gen_set_type_die (type, context_die);
- break;
-
case FILE_TYPE:
gen_type_die (TREE_TYPE (type), context_die);
/* No way to represent these in Dwarf yet! */