===================================================================
@@ -268,9 +272,17 @@ typedef union GTY(()) dw_cfi_oprnd_struct {
}
dw_cfi_oprnd;
+/* Use the first out-of-band opcode number as a marker for the start of
+ epilogues. */
+#define DW_CFA_INTERNAL_start_epilogue 0x100
+#define CFI_T enum dwarf_call_frame_info
+
+static enum dw_cfi_oprnd_type dw_cfi_oprnd1_desc (unsigned int cfi);
+static enum dw_cfi_oprnd_type dw_cfi_oprnd2_desc (unsigned int cfi);
+
typedef struct GTY(()) dw_cfi_struct {
dw_cfi_ref dw_cfi_next;
- enum dwarf_call_frame_info dw_cfi_opc;
+ unsigned int dw_cfi_opc;
dw_cfi_oprnd GTY ((desc ("dw_cfi_oprnd1_desc (%1.dw_cfi_opc)")))
dw_cfi_oprnd1;
dw_cfi_oprnd GTY ((desc ("dw_cfi_oprnd2_desc (%1.dw_cfi_opc)")))
@@ -821,9 +833,15 @@ add_fde_cfi (const char *label, dw_cfi_ref cfi)
}
list_head = &cie_cfi_head;
-
- if (dwarf2out_do_cfi_asm ())
+
+ if (cfi->dw_cfi_opc == DW_CFA_INTERNAL_start_epilogue)
{
+ dw_fde_ref fde = current_fde ();
+ gcc_assert (fde != NULL);
+ list_head = &fde->dw_fde_cfi;
+ }
+ else if (dwarf2out_do_cfi_asm ())
+ {
if (label)
{
dw_fde_ref fde = current_fde ();
@@ -2894,12 +2912,22 @@ dwarf2out_cfi_begin_epilogue (rtx insn)
return;
/* 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. */
+ basic block of the function. If so, we don't need save/restore.
+ However, we do mark the position so that we can skip the epilogue
+ in _eh frames where required. */
gcc_assert (i != NULL);
i = next_real_insn (i);
if (i == NULL)
- return;
+ {
+ dw_cfi_ref cfi_epi_start;
+ /* Emit a marker for the epilogue start. */
+ cfi_epi_start = new_cfi ();
+ cfi_epi_start->dw_cfi_opc = DW_CFA_INTERNAL_start_epilogue;
+ add_fde_cfi ("", cfi_epi_start);
+ return;
+ }
+
/* 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
@@ -2941,11 +2969,9 @@ dwarf2out_frame_debug_restore_state (void)
}
/* Describe for the GTY machinery what parts of dw_cfi_oprnd1 are used. */
-static enum dw_cfi_oprnd_type dw_cfi_oprnd1_desc
- (enum dwarf_call_frame_info cfi);
static enum dw_cfi_oprnd_type
-dw_cfi_oprnd1_desc (enum dwarf_call_frame_info cfi)
+dw_cfi_oprnd1_desc (unsigned int cfi)
{
switch (cfi)
{
@@ -2953,6 +2979,7 @@ static enum dw_cfi_oprnd_type
case DW_CFA_GNU_window_save:
case DW_CFA_remember_state:
case DW_CFA_restore_state:
+ case DW_CFA_INTERNAL_start_epilogue:
return dw_cfi_oprnd_unused;
case DW_CFA_set_loc:
@@ -2990,11 +3017,9 @@ static enum dw_cfi_oprnd_type
}
/* Describe for the GTY machinery what parts of dw_cfi_oprnd2 are used. */
-static enum dw_cfi_oprnd_type dw_cfi_oprnd2_desc
- (enum dwarf_call_frame_info cfi);
static enum dw_cfi_oprnd_type
-dw_cfi_oprnd2_desc (enum dwarf_call_frame_info cfi)
+dw_cfi_oprnd2_desc (unsigned int cfi)
{
switch (cfi)
{
@@ -3090,6 +3115,7 @@ switch_to_frame_table_section (int for_eh, bool ba
debug_frame_section = get_section (DEBUG_FRAME_SECTION,
SECTION_DEBUG, NULL);
switch_to_section (debug_frame_section);
+ TGT_ASM_DBG_SECTION_LABEL (debug_frame_section);
}
}
@@ -3121,6 +3147,8 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int fo
dw2_asm_output_data (1, (cfi->dw_cfi_opc | (r & 0x3f)),
"DW_CFA_restore, column %#lx", r);
}
+ else if (cfi->dw_cfi_opc == DW_CFA_INTERNAL_start_epilogue)
+ ; /* This is a nop. */
else
{
dw2_asm_output_data (1, cfi->dw_cfi_opc,
@@ -3303,6 +3331,10 @@ output_cfi_directive (dw_cfi_ref cfi)
cfi->dw_cfi_oprnd1.dw_cfi_offset);
break;
+ case DW_CFA_INTERNAL_start_epilogue:
+ ; /* nop. */
+ break;
+
case DW_CFA_remember_state:
fprintf (asm_out_file, "\t.cfi_remember_state\n");
break;
@@ -3498,6 +3530,44 @@ output_cfis (dw_cfi_ref cfi, bool do_cfi_asm, dw_f
}
}
+/* Output cfi skipping save/restore and epilogues in _eh frames
+ for targets that do not want them. */
+
+static dw_cfi_ref
+emit_cfi_or_skip_epilogue (dw_cfi_ref cfi, dw_fde_ref fde, bool for_eh)
+{
+ if (for_eh
+ && !flag_asynchronous_unwind_tables)
+ {
+ if (cfi->dw_cfi_opc == DW_CFA_remember_state)
+ {
+ if (flag_debug_asm)
+ fputs (ASM_COMMENT_START"\t\t\t"ASM_COMMENT_START
+ " DW_CFA_remember/restore_state pair skipped\n",asm_out_file);
+ /* Skip to the restore, unless there's an error and we fall off
+ the end. */
+ while (cfi->dw_cfi_next
+ && cfi->dw_cfi_opc != DW_CFA_restore_state)
+ cfi = cfi->dw_cfi_next;
+ return cfi;
+ }
+ if (cfi->dw_cfi_opc == DW_CFA_INTERNAL_start_epilogue)
+ {
+ if (flag_debug_asm)
+ fputs (ASM_COMMENT_START"\t\t\t"ASM_COMMENT_START
+ " DW_CFA_INTERNAL_start_epilogue\n",asm_out_file);
+ /* Skip to the end. */
+ while (cfi->dw_cfi_next)
+ cfi = cfi->dw_cfi_next;
+ return cfi;
+ }
+ }
+
+ /* If it's not a special case, then just carry on. */
+ output_cfi (cfi, fde, for_eh);
+ return cfi;
+}
+
/* Output one FDE. */
static void
@@ -3613,13 +3683,13 @@ output_fde (dw_fde_ref fde, bool for_eh, bool seco
fde->dw_fde_current_label = begin;
if (!fde->dw_fde_switched_sections)
for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next)
- output_cfi (cfi, fde, for_eh);
+ cfi = emit_cfi_or_skip_epilogue (cfi, fde, for_eh);
else if (!second)
{
if (fde->dw_fde_switch_cfi)
for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next)
{
- output_cfi (cfi, fde, for_eh);
+ cfi = emit_cfi_or_skip_epilogue (cfi, fde, for_eh);
if (cfi == fde->dw_fde_switch_cfi)
break;
}
@@ -3627,7 +3697,6 @@ output_fde (dw_fde_ref fde, bool for_eh, bool seco
else
{
dw_cfi_ref cfi_next = fde->dw_fde_cfi;
-
if (fde->dw_fde_switch_cfi)
{
cfi_next = fde->dw_fde_switch_cfi->dw_cfi_next;
@@ -3636,7 +3705,7 @@ output_fde (dw_fde_ref fde, bool for_eh, bool seco
fde->dw_fde_switch_cfi->dw_cfi_next = cfi_next;
}
for (cfi = cfi_next; cfi != NULL; cfi = cfi->dw_cfi_next)
- output_cfi (cfi, fde, for_eh);
+ cfi = emit_cfi_or_skip_epilogue (cfi, fde, for_eh);
}
/* If we are to emit a ref/link from function bodies to their frame tables,
===================================================================
@@ -1798,9 +1801,9 @@ process_options (void)
if (flag_rename_registers == AUTODETECT_VALUE)
flag_rename_registers = flag_unroll_loops || flag_peel_loops;
- if (flag_non_call_exceptions)
+ if (flag_non_call_exceptions && flag_asynchronous_unwind_tables == 2)
flag_asynchronous_unwind_tables = 1;
- if (flag_asynchronous_unwind_tables)
+ if (flag_asynchronous_unwind_tables || flag_non_call_exceptions)
flag_unwind_tables = 1;
if (flag_value_profile_transformations)
===================================================================
@@ -1,6 +1,7 @@
// PR rtl-optimization/36419
// { dg-do run { target { { i?86-*-* x86_64-*-* } && ilp32 } } }
// { dg-options "-Os -fasynchronous-unwind-tables -mpreferred-stack-boundary=4" }
+// { dg-warning "this architecture does not fully support" "" { target *-*-darwin* } 0 }
extern "C" void abort ();
===================================================================
@@ -2,6 +2,7 @@
// { dg-do run { target { { i?86-*-* x86_64-*-* } && ilp32 } } }
// { dg-require-effective-target fpic }
// { dg-options "-Os -fasynchronous-unwind-tables -fpic -fno-inline" }
+// { dg-warning "this architecture does not fully support" "" { target *-*-darwin* } 0 }
#include <stdarg.h>
===================================================================
@@ -1866,14 +1897,30 @@ darwin_kextabi_p (void) {
return flag_apple_kext;
}
+/* Invoked from SUBSUBTARGET_OVERRIDE_OPTIONS from rs6000.c and
+ i386.c, this is processed after any arch-specific overrides. */
void
darwin_override_options (void)
{
+ bool darwin9plus = strverscmp (darwin_macosx_version_min, "10.5") >= 0;
+
/* Don't emit DWARF3/4 unless specifically selected. This is a
workaround for tool bugs. */
if (dwarf_strict < 0)
dwarf_strict = 1;
+ /* Do not set asynchronous_unwinding (yet) unless the user specifically
+ asks, warn that it might not work (for Wall). */
+ if (flag_asynchronous_unwind_tables)
+ {
+ if (flag_asynchronous_unwind_tables == 2)
+ flag_asynchronous_unwind_tables = 0;
+ else
+ warning (OPT_Wall,
+ "this architecture does not fully support"
+ " -fasynchronous-unwind-tables");
+ }
+
/* Disable -freorder-blocks-and-partition for darwin_emit_unwind_label. */
if (flag_reorder_blocks_and_partition
&& (targetm.asm_out.emit_unwind_label == darwin_emit_unwind_label))
@@ -1885,6 +1932,10 @@ darwin_override_options (void)
flag_reorder_blocks = 1;
}
+ if (flag_non_call_exceptions == 1
+ || flag_asynchronous_unwind_tables == 1)
+ flag_unwind_tables = 1;
+
if (flag_mkernel || flag_apple_kext)
{
/* -mkernel implies -fapple-kext for C++ */
@@ -1897,18 +1948,21 @@ darwin_override_options (void)
flag_exceptions = 0;
/* No -fnon-call-exceptions data in kexts. */
flag_non_call_exceptions = 0;
+ /* so no tables either.. */
+ flag_unwind_tables = 0;
+ flag_asynchronous_unwind_tables = 0;
/* We still need to emit branch islands for kernel context. */
darwin_emit_branch_islands = true;
}
+
if (flag_var_tracking
- && strverscmp (darwin_macosx_version_min, "10.5") >= 0
+ && darwin9plus
&& debug_info_level >= DINFO_LEVEL_NORMAL
&& debug_hooks->var_location != do_nothing_debug_hooks.var_location)
flag_var_tracking_uninit = 1;
/* It is assumed that branch island stubs are needed for earlier systems. */
- if (darwin_macosx_version_min
- && strverscmp (darwin_macosx_version_min, "10.5") < 0)
+ if (! darwin9plus)
darwin_emit_branch_islands = true;
}
===================================================================
@@ -245,6 +245,41 @@ extern int darwin_emit_branch_islands;
SUBTARGET_C_COMMON_OVERRIDE_OPTIONS; \
} while (0)
+#undef SUBTARGET_OVERRIDE_OPTIONS
+#define SUBTARGET_OVERRIDE_OPTIONS \
+do { \
+ bool darwin9plus = strverscmp (darwin_macosx_version_min, "10.5") >= 0;\
+ /* If no unwind model is set, then decide on a default based \
+ on Darwin rev. */ \
+ if (flag_omit_frame_pointer >= 1 && flag_unwind_tables == 0) \
+ { \
+ if (darwin9plus) \
+ /* Emit Unwind tables. */ \
+ flag_unwind_tables = 1; \
+ else \
+ { \
+ if (flag_omit_frame_pointer == 1) \
+ /* The user has asked to omit fp - emit Unwind tables. */ \
+ flag_unwind_tables = 1; \
+ else \
+ /* Use the frame pointer. */ \
+ flag_omit_frame_pointer = 0; \
+ } \
+ } \
+ /* Do not allow the subtarget to switch off frame pointers for \
+ earlier versions of Darwin. */ \
+ if (flag_omit_frame_pointer == 2 && !darwin9plus) \
+ flag_omit_frame_pointer = 0; \
+ if (flag_omit_frame_pointer >= 1 && flag_unwind_tables == 1) \
+ target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS; \
+ /* Do not set asynchronous_unwinding (yet) unless the user \
+ specifically asks,. */ \
+ if (flag_asynchronous_unwind_tables == 2) \
+ flag_asynchronous_unwind_tables = 0; \
+ if (TARGET_64BIT && MACHO_DYNAMIC_NO_PIC_P) \
+ target_flags &= ~MASK_MACHO_DYNAMIC_NO_PIC; \
+} while (0)
+
/* Darwin on x86_64 uses dwarf-2 by default. Pre-darwin9 32-bit
compiles default to stabs+. darwin9+ defaults to dwarf-2. */
#ifndef DARWIN_PREFER_DWARF