Commit 0021b564 by Jason Merrill

dwarf2 EH support

From-SVN: r15255
parent 0680d170
......@@ -2849,7 +2849,7 @@ init_decl_processing ()
tree traditional_ptr_type_node;
/* Data types of memcpy and strlen. */
tree memcpy_ftype, memset_ftype, strlen_ftype;
tree void_ftype_any;
tree void_ftype_any, ptr_ftype_void, ptr_ftype_ptr;
int wchar_type_size;
tree temp;
tree array_domain_type;
......@@ -3165,6 +3165,11 @@ init_decl_processing ()
sizetype,
endlink))));
ptr_ftype_void = build_function_type (ptr_type_node, endlink);
ptr_ftype_ptr
= build_function_type (ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node, endlink));
builtin_function ("__builtin_constant_p", default_function_type,
BUILT_IN_CONSTANT_P, NULL_PTR);
......@@ -3186,6 +3191,36 @@ init_decl_processing ()
build_function_type (ptr_type_node, NULL_TREE),
BUILT_IN_AGGREGATE_INCOMING_ADDRESS, NULL_PTR);
/* Hooks for the DWARF 2 __throw routine. */
builtin_function ("__builtin_unwind_init",
build_function_type (void_type_node, endlink),
BUILT_IN_UNWIND_INIT, NULL_PTR);
builtin_function ("__builtin_fp", ptr_ftype_void, BUILT_IN_FP, NULL_PTR);
builtin_function ("__builtin_sp", ptr_ftype_void, BUILT_IN_SP, NULL_PTR);
builtin_function ("__builtin_dwarf_fp_regnum",
build_function_type (unsigned_type_node, endlink),
BUILT_IN_DWARF_FP_REGNUM, NULL_PTR);
builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr,
BUILT_IN_FROB_RETURN_ADDR, NULL_PTR);
builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
BUILT_IN_EXTRACT_RETURN_ADDR, NULL_PTR);
builtin_function ("__builtin_set_return_addr_reg",
build_function_type (void_type_node,
tree_cons (NULL_TREE,
ptr_type_node,
endlink)),
BUILT_IN_SET_RETURN_ADDR_REG, NULL_PTR);
builtin_function ("__builtin_eh_stub", ptr_ftype_void,
BUILT_IN_EH_STUB, NULL_PTR);
builtin_function
("__builtin_set_eh_regs",
build_function_type (void_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE,
type_for_mode (ptr_mode, 0),
endlink))),
BUILT_IN_SET_EH_REGS, NULL_PTR);
builtin_function ("__builtin_alloca",
build_function_type (ptr_type_node,
tree_cons (NULL_TREE,
......
......@@ -239,6 +239,7 @@ static char *initname, *fininame; /* names of init and fini funcs */
static struct head constructors; /* list of constructors found */
static struct head destructors; /* list of destructors found */
static struct head exports; /* list of exported symbols */
static struct head frame_tables; /* list of frame unwind info tables */
struct obstack temporary_obstack;
struct obstack permanent_obstack;
......@@ -599,13 +600,16 @@ is_ctor_dtor (s)
#ifdef NO_DOT_IN_LABEL
{ "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 },
{ "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 },
{ "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, 5, 0 },
#else
{ "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 },
{ "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 },
{ "GLOBAL_.F.", sizeof ("GLOBAL_.F.")-1, 5, 0 },
#endif
#else
{ "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 },
{ "GLOBAL_$D$", sizeof ("GLOBAL_$D$")-1, 2, 0 },
{ "GLOBAL_$F$", sizeof ("GLOBAL_$F$")-1, 5, 0 },
#endif
{ "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 },
{ "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 },
......@@ -993,6 +997,7 @@ main (argc, argv)
num_c_args++;
}
obstack_free (&temporary_obstack, temporary_firstobj);
++num_c_args;
c_ptr = c_argv = (char **) xcalloc (sizeof (char *), num_c_args);
......@@ -1288,6 +1293,7 @@ main (argc, argv)
shared_obj = 1;
}
obstack_free (&temporary_obstack, temporary_firstobj);
*c_ptr++ = "-fno-exceptions";
#ifdef COLLECT_EXPORT_LIST
/* The AIX linker will discard static constructors in object files if
......@@ -1396,7 +1402,8 @@ main (argc, argv)
}
if (constructors.number == 0 && destructors.number == 0
#ifdef LDD_SUFFIX
&& frame_tables.number == 0
#ifdef SCAN_LIBRARIES
/* If we will be running these functions ourselves, we want to emit
stubs into the shared library so that we don't have to relink
dependent programs when we add static objects. */
......@@ -1690,6 +1697,7 @@ write_c_file_stat (stream, name)
char *name;
{
char *prefix, *p, *q;
int frames = (frame_tables.number > 0);
/* Figure out name of output_file, stripping off .so version. */
p = rindex (output_file, '/');
......@@ -1743,15 +1751,38 @@ write_c_file_stat (stream, name)
fprintf (stream, "static int count;\n");
fprintf (stream, "typedef void entry_pt();\n");
write_list_with_asm (stream, "extern entry_pt ", constructors.first);
if (frames)
{
write_list_with_asm (stream, "extern void *", frame_tables.first);
fprintf (stream, "\tstatic void *frame_table[] = {\n");
write_list (stream, "\t\t&", frame_tables.first);
fprintf (stream, "\t0\n};\n");
fprintf (stream, "extern void __register_frame_table (void *);\n");
fprintf (stream, "extern void __deregister_frame (void *);\n");
fprintf (stream, "static void reg_frame () {\n");
fprintf (stream, "\t__register_frame_table (frame_table);\n");
fprintf (stream, "\t}\n");
fprintf (stream, "static void dereg_frame () {\n");
fprintf (stream, "\t__deregister_frame (frame_table);\n");
fprintf (stream, "\t}\n");
}
fprintf (stream, "void %s() {\n", initname);
if (constructors.number > 0)
if (constructors.number > 0 || frames)
{
fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
write_list (stream, "\t\t", constructors.first);
if (frames)
fprintf (stream, "\treg_frame,\n");
fprintf (stream, "\t};\n");
fprintf (stream, "\tentry_pt **p;\n");
fprintf (stream, "\tif (count++ != 0) return;\n");
fprintf (stream, "\tp = ctors + %d;\n", constructors.number);
fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames);
fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
}
else
......@@ -1759,16 +1790,18 @@ write_c_file_stat (stream, name)
fprintf (stream, "}\n");
write_list_with_asm (stream, "extern entry_pt ", destructors.first);
fprintf (stream, "void %s() {\n", fininame);
if (destructors.number > 0)
if (destructors.number > 0 || frames)
{
fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
write_list (stream, "\t\t", destructors.first);
if (frames)
fprintf (stream, "\tdereg_frame,\n");
fprintf (stream, "\t};\n");
fprintf (stream, "\tentry_pt **p;\n");
fprintf (stream, "\tif (--count != 0) return;\n");
fprintf (stream, "\tp = dtors;\n");
fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
destructors.number);
destructors.number + frames);
}
fprintf (stream, "}\n");
......@@ -1788,20 +1821,46 @@ write_c_file_glob (stream, name)
{
/* Write the tables as C code */
int frames = (frame_tables.number > 0);
fprintf (stream, "typedef void entry_pt();\n\n");
write_list_with_asm (stream, "extern entry_pt ", constructors.first);
if (frames)
{
write_list_with_asm (stream, "extern void *", frame_tables.first);
fprintf (stream, "\tstatic void *frame_table[] = {\n");
write_list (stream, "\t\t&", frame_tables.first);
fprintf (stream, "\t0\n};\n");
fprintf (stream, "extern void __register_frame_table (void *);\n");
fprintf (stream, "extern void __deregister_frame (void *);\n");
fprintf (stream, "static void reg_frame () {\n");
fprintf (stream, "\t__register_frame_table (frame_table);\n");
fprintf (stream, "\t}\n");
fprintf (stream, "static void dereg_frame () {\n");
fprintf (stream, "\t__deregister_frame (frame_table);\n");
fprintf (stream, "\t}\n");
}
fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number);
fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames);
write_list (stream, "\t", constructors.first);
if (frames)
fprintf (stream, "\treg_frame,\n");
fprintf (stream, "\t0\n};\n\n");
write_list_with_asm (stream, "extern entry_pt ", destructors.first);
fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number);
fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames);
write_list (stream, "\t", destructors.first);
if (frames)
fprintf (stream, "\tdereg_frame,\n");
fprintf (stream, "\t0\n};\n\n");
fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
......@@ -1985,6 +2044,10 @@ scan_prog_file (prog_name, which_pass)
#endif
break;
case 5:
if (which_pass != PASS_LIB)
add_to_list (&frame_tables, name);
default: /* not a constructor or destructor */
continue;
}
......
......@@ -1866,6 +1866,7 @@ function_prologue (file, size)
int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
|| current_function_uses_const_pool);
long tsize = get_frame_size ();
int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset;
/* pic references don't explicitly mention pic_offset_table_rtx */
if (TARGET_SCHEDULE_PROLOGUE)
......@@ -1881,13 +1882,34 @@ function_prologue (file, size)
if (frame_pointer_needed)
{
output_asm_insn ("push%L1 %1", xops);
if (dwarf2out_do_frame ())
{
char *l = (char *) dwarf2out_cfi_label ();
cfa_store_offset += 4;
cfa_offset = cfa_store_offset;
dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, -cfa_store_offset);
}
output_asm_insn (AS2 (mov%L0,%0,%1), xops);
if (dwarf2out_do_frame ())
dwarf2out_def_cfa ("", FRAME_POINTER_REGNUM, cfa_offset);
}
if (tsize == 0)
;
else if (! TARGET_STACK_PROBE || tsize < CHECK_STACK_LIMIT)
output_asm_insn (AS2 (sub%L0,%2,%0), xops);
{
output_asm_insn (AS2 (sub%L0,%2,%0), xops);
if (dwarf2out_do_frame ())
{
cfa_store_offset += tsize;
if (! frame_pointer_needed)
{
cfa_offset = cfa_store_offset;
dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset);
}
}
}
else
{
xops[3] = gen_rtx (REG, SImode, 0);
......@@ -1913,6 +1935,17 @@ function_prologue (file, size)
{
xops[0] = gen_rtx (REG, SImode, regno);
output_asm_insn ("push%L0 %0", xops);
if (dwarf2out_do_frame ())
{
char *l = (char *) dwarf2out_cfi_label ();
cfa_store_offset += 4;
if (! frame_pointer_needed)
{
cfa_offset = cfa_store_offset;
dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
}
dwarf2out_reg_save (l, regno, -cfa_store_offset);
}
}
if (pic_reg_used && TARGET_DEEP_BRANCH_PREDICTION)
......
......@@ -249,6 +249,10 @@ Boston, MA 02111-1307, USA. */
(TARGET_LONG64 ? ".section\t.dtors,1,2,0,8" : ".section\t.dtors,1,2,0,4")
#endif /* defined (CRT_BEGIN) || defined (CRT_END) */
/* dwarf2out will handle padding this data properly. We definitely don't
want it 8-byte aligned on n32. */
#define EH_FRAME_SECTION_ASM_OP ".section\t.eh_frame,1,2,0,1"
/* A default list of other sections which we might be "in" at any given
time. For targets that use additional sections (e.g. .tdesc) you
should override this definition in the target-specific file which
......@@ -538,5 +542,5 @@ do { \
%{!static: \
%{!shared: %{!non_shared: %{!call_shared: -call_shared -no_unresolved}}}} \
%{rpath} -init __do_global_ctors -fini __do_global_dtors \
%{shared:-hidden_symbol __do_global_ctors,__do_global_dtors} \
%{shared:-hidden_symbol __do_global_ctors,__do_global_dtors,__EH_FRAME_BEGIN__} \
-_SYSTYPE_SVR4 %{mabi=32: -32}%{mabi=n32: -n32}%{mabi=64: -64} %{!mabi*: -n32}"
......@@ -5241,6 +5241,9 @@ function_prologue (file, size)
sp_str, sp_str, tsize);
fprintf (file, "\t.cprestore %d\n", current_frame_info.args_size);
}
if (dwarf2out_do_frame ())
dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, tsize);
}
}
......
......@@ -948,12 +948,11 @@ while (0)
#define DBX_REGISTER_NUMBER(REGNO) mips_dbx_regno[ (REGNO) ]
/* The mapping from gcc register number to DWARF 2 CFA column number.
This mapping does not allow for tracking DBX register 0, since column 0
is used for the frame address, but since register 0 is fixed this is
not really a problem. */
This mapping does not allow for tracking register 0, since SGI's broken
dwarf reader thinks column 0 is used for the frame address, but since
register 0 is fixed this is not a problem. */
#define DWARF_FRAME_REGNUM(REG) \
(REG == GP_REG_FIRST + 31 ? DWARF_FRAME_RETURN_COLUMN \
: DBX_REGISTER_NUMBER (REG))
(REG == GP_REG_FIRST + 31 ? DWARF_FRAME_RETURN_COLUMN : REG)
/* The DWARF 2 CFA column which tracks the return address. */
#define DWARF_FRAME_RETURN_COLUMN (FP_REG_LAST + 1)
......
......@@ -2910,10 +2910,8 @@ save_regs (file, low, high, base, offset, n_regs, real_offset)
{
fprintf (file, "\tstx %s,[%s+%d]\n",
reg_names[i], base, offset + 4 * n_regs);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
dwarf2out_reg_save ("", i, real_offset + 4 * n_regs);
#endif
n_regs += 2;
}
}
......@@ -2927,34 +2925,28 @@ save_regs (file, low, high, base, offset, n_regs, real_offset)
{
fprintf (file, "\tstd %s,[%s+%d]\n",
reg_names[i], base, offset + 4 * n_regs);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
{
char *l = (char *) dwarf2out_cfi_label ();
dwarf2out_reg_save (l, i, real_offset + 4 * n_regs);
dwarf2out_reg_save (l, i+1, real_offset + 4 * n_regs + 4);
}
#endif
n_regs += 2;
}
else
{
fprintf (file, "\tst %s,[%s+%d]\n",
reg_names[i], base, offset + 4 * n_regs);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
dwarf2out_reg_save ("", i, real_offset + 4 * n_regs);
#endif
n_regs += 2;
}
else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
{
fprintf (file, "\tst %s,[%s+%d]\n",
reg_names[i+1], base, offset + 4 * n_regs + 4);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
dwarf2out_reg_save ("", i + 1, real_offset + 4 * n_regs + 4);
#endif
n_regs += 2;
}
}
......@@ -3196,8 +3188,7 @@ output_function_prologue (file, size, leaf_function)
}
}
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG && actual_fsize)
if (dwarf2out_do_frame () && actual_fsize)
{
char *label = (char *) dwarf2out_cfi_label ();
......@@ -3217,7 +3208,6 @@ output_function_prologue (file, size, leaf_function)
dwarf2out_return_reg (label, 31);
}
}
#endif
/* If doing anything with PIC, do it now. */
if (! flag_pic)
......@@ -4739,15 +4729,13 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op, doublewo
fprintf (file, "\t%s %s,[%s+%d]\n",
doubleword_op, reg_names[regno],
base_reg, offset);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
{
char *l = (char *) dwarf2out_cfi_label ();
dwarf2out_reg_save (l, regno, offset + base_offset);
dwarf2out_reg_save
(l, regno+1, offset+base_offset + UNITS_PER_WORD);
}
#endif
}
else
fprintf (file, "\t%s [%s+%d],%s\n",
......@@ -4764,10 +4752,8 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op, doublewo
fprintf (file, "\t%s %s,[%s+%d]\n",
word_op, reg_names[regno],
base_reg, offset);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
dwarf2out_reg_save ("", regno, offset + base_offset);
#endif
}
else
fprintf (file, "\t%s [%s+%d],%s\n",
......@@ -4790,10 +4776,8 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op, doublewo
fprintf (file, "\t%s %s,[%s+%d]\n",
word_op, reg_names[regno],
base_reg, offset);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
dwarf2out_reg_save ("", regno, offset + base_offset);
#endif
}
else
fprintf (file, "\t%s [%s+%d],%s\n",
......@@ -4891,8 +4875,7 @@ sparc_flat_output_function_prologue (file, size)
reg_offset += 4;
}
}
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
{
char *l = (char *) dwarf2out_cfi_label ();
if (gmask & FRAME_POINTER_MASK)
......@@ -4904,15 +4887,12 @@ sparc_flat_output_function_prologue (file, size)
else
dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, size);
}
#endif
if (gmask & RETURN_ADDR_MASK)
{
fprintf (file, "\tst %s,[%s+%d]\n",
reg_names[RETURN_ADDR_REGNUM], sp_str, reg_offset);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
dwarf2out_return_save ("", reg_offset - size);
#endif
reg_offset += 4;
}
sparc_flat_save_restore (file, sp_str, reg_offset,
......@@ -4951,8 +4931,7 @@ sparc_flat_output_function_prologue (file, size)
offset += 4;
}
}
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
{
char *l = (char *) dwarf2out_cfi_label ();
if (gmask & FRAME_POINTER_MASK)
......@@ -4964,17 +4943,14 @@ sparc_flat_output_function_prologue (file, size)
else
dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, size1);
}
#endif
if (gmask & RETURN_ADDR_MASK)
{
fprintf (file, "\tst %s,[%s+%d]\n",
reg_names[RETURN_ADDR_REGNUM], sp_str, offset);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
/* offset - size1 == reg_offset - size
if reg_offset were updated above like offset. */
dwarf2out_return_save ("", offset - size1);
#endif
offset += 4;
}
sparc_flat_save_restore (file, sp_str, offset,
......@@ -4983,11 +4959,9 @@ sparc_flat_output_function_prologue (file, size)
"st", "std", -size1);
fprintf (file, "\tset %d,%s\n\tsub %s,%s,%s\n",
size - size1, t1_str, sp_str, t1_str, sp_str);
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
if (! (gmask & FRAME_POINTER_MASK))
dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, size);
#endif
}
}
......
......@@ -25,3 +25,6 @@ Boston, MA 02111-1307, USA. */
#define DBX_USE_BINCL
#include "sparc/sparc.h"
/* The Sun as doesn't like unaligned data. */
#define DWARF2_UNWIND_INFO 0
......@@ -91,6 +91,7 @@ Boston, MA 02111-1307, USA. */
#define STRING_ASM_OP ".asciz"
#define COMMON_ASM_OP ".common"
#define SKIP_ASM_OP ".skip"
#define UNALIGNED_DOUBLE_INT_ASM_OP ".uaxword"
#define UNALIGNED_INT_ASM_OP ".uaword"
#define UNALIGNED_SHORT_ASM_OP ".uahalf"
#define PUSHSECTION_ASM_OP ".pushsection"
......@@ -179,6 +180,8 @@ do { ASM_OUTPUT_ALIGN ((FILE), Pmode == SImode ? 2 : 3); \
#define CTORS_SECTION_ASM_OP ".section\t\".ctors\",#alloc,#write"
#undef DTORS_SECTION_ASM_OP
#define DTORS_SECTION_ASM_OP ".section\t\".dtors\",#alloc,#write"
#undef EH_FRAME_SECTION_ASM_OP
#define EH_FRAME_SECTION_ASM_OP ".section\t\".eh_frame\",#alloc,#write"
/* A C statement to output something to the assembler file to switch to section
NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or
......
......@@ -2934,7 +2934,7 @@ finish_file ()
rest_of_decl_compilation (TREE_VALUE (vars), 0, 1, 1);
vars = static_aggregates;
if (static_ctors || vars || exception_table_p ())
if (static_ctors || vars || register_exception_table_p ())
needs_messing_up = 1;
if (static_dtors)
needs_cleaning = 1;
......@@ -3033,7 +3033,7 @@ finish_file ()
push_momentary ();
expand_start_bindings (0);
if (exception_table_p ())
if (register_exception_table_p ())
register_exception_table ();
while (vars)
......
......@@ -33,6 +33,7 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "except.h"
#include "function.h"
#include "defaults.h"
rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
......@@ -609,7 +610,8 @@ do_unwind (inner_throw_label)
rtx inner_throw_label;
{
#if defined (SPARC_STACK_ALIGN) /* was sparc */
/* This doesn't work for the flat model sparc, I bet. */
/* This doesn't work for the flat model sparc, nor does it need to
as the default unwinder is only used to unwind non-flat frames. */
tree fcall;
tree params;
rtx next_pc;
......@@ -704,6 +706,7 @@ do_unwind (inner_throw_label)
void
expand_builtin_throw ()
{
#ifndef DWARF2_UNWIND_INFO
tree fcall;
tree params;
rtx handler;
......@@ -897,6 +900,7 @@ expand_builtin_throw ()
pop_momentary ();
finish_function (lineno, 0, 0);
#endif /* DWARF2_UNWIND_INFO */
}
......@@ -1149,7 +1153,6 @@ expand_throw (exp)
expand_expr (object, const0_rtx, VOIDmode, 0);
end_anon_func ();
mark_addressable (cleanup);
}
if (cleanup == empty_fndecl)
......
......@@ -1185,29 +1185,28 @@ arrays. Exception specifications are now handled. Thrown objects are
now cleaned up all the time. We can now tell if we have an active
exception being thrown or not (__eh_type != 0). We use this to call
terminate if someone does a throw; without there being an active
exception object. uncaught_exception () works.
exception object. uncaught_exception () works. Exception handling
should work right if you optimize. Exception handling should work with
-fpic or -fPIC.
The below points out some flaws in g++'s exception handling, as it now
stands.
Only exact type matching or reference matching of throw types works when
-fno-rtti is used. Only works on a SPARC (like Suns), SPARClite, i386,
arm, rs6000, PowerPC, Alpha, mips, VAX, m68k and z8k machines. Partial
support is in for all other machines, but a stack unwinder called
__unwind_function has to be written, and added to libgcc2 for them. The
new EH code doesn't rely upon the __unwind_function for C++ code,
instead it creates per function unwinders right inside the function,
unfortunately, on many platforms the definition of RETURN_ADDR_RTX in
the tm.h file for the machine port is wrong. The HPPA has a brain dead
abi that prevents exception handling from just working. See below for
details on __unwind_function. Don't expect exception handling to work
right if you optimize, in fact the compiler will probably core dump.
RTL_EXPRs for EH cond variables for && and || exprs should probably be
wrapped in UNSAVE_EXPRs, and RTL_EXPRs tweaked so that they can be
unsaved, and the UNSAVE_EXPR code should be in the backend, or
alternatively, UNSAVE_EXPR should be ripped out and exactly one
finalization allowed to be expanded by the backend. I talked with
kenner about this, and we have to allow multiple expansions.
-fno-rtti is used. Only works on a SPARC (like Suns) (both -mflat and
-mno-flat models work), SPARClite, Hitachi SH, i386, arm, rs6000,
PowerPC, Alpha, mips, VAX, m68k and z8k machines. SPARC v9 may not
work. HPPA is mostly done, but throwing between a shared library and
user code doesn't yet work. Some targets have support for data-driven
unwinding. Partial support is in for all other machines, but a stack
unwinder called __unwind_function has to be written, and added to
libgcc2 for them. The new EH code doesn't rely upon the
__unwind_function for C++ code, instead it creates per function
unwinders right inside the function, unfortunately, on many platforms
the definition of RETURN_ADDR_RTX in the tm.h file for the machine port
is wrong. See below for details on __unwind_function. RTL_EXPRs for EH
cond variables for && and || exprs should probably be wrapped in
UNSAVE_EXPRs, and RTL_EXPRs tweaked so that they can be unsaved.
We only do pointer conversions on exception matching a la 15.3 p2 case
3: `A handler with type T, const T, T&, or const T& is a match for a
......@@ -1397,6 +1396,33 @@ things: first, a way to figure out where the frame pointer was stored,
and second, a functional @code{__builtin_return_address} implementation
for except.c to be able to use it.
Or just support DWARF 2 unwind info.
@subsection New Backend Exception Support
This subsection discusses various aspects of the design of the
data-driven model being implemented for the exception handling backend.
The goal is to generate enough data during the compilation of user code,
such that we can dynamically unwind through functions at run time with a
single routine (@code{__throw}) that lives in libgcc.a, built by the
compiler, and dispatch into associated exception handlers.
This information is generated by the DWARF 2 debugging backend, and
includes all of the information __throw needs to unwind an arbitrary
frame. It specifies where all of the saved registers and the return
address can be found at any point in the function.
Major disadvantages when enabling exceptions are:
@itemize @bullet
@item
Code that uses caller saved registers, can't, when flow can be
transfered into that code from an exception handler. In high performace
code this should not usually be true, so the effects should be minimal.
@end itemize
@subsection Backend Exception Support
The backend must be extended to fully support exceptions. Right now
......
......@@ -52,6 +52,7 @@ Boston, MA 02111-1307, USA. */
do not apply. */
#include "tm.h"
#include "defaults.h"
/* Provide default definitions for the pseudo-ops used to switch to the
.ctors and .dtors sections.
......@@ -75,6 +76,9 @@ Boston, MA 02111-1307, USA. */
#ifndef DTORS_SECTION_ASM_OP
#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\""
#endif
#if !defined (EH_FRAME_SECTION_ASM_OP) && defined (DWARF2_UNWIND_INFO) && defined(ASM_OUTPUT_SECTION_NAME)
#define EH_FRAME_SECTION_ASM_OP ".section\t.eh_frame,\"aw\""
#endif
#ifdef OBJECT_FORMAT_ELF
......@@ -118,6 +122,7 @@ typedef void (*func_ptr) (void);
the list we left off processing, and we resume at that point,
should we be re-invoked. */
static char __EH_FRAME_BEGIN__[];
static func_ptr __DTOR_LIST__[];
static void
__do_global_dtors_aux ()
......@@ -128,6 +133,10 @@ __do_global_dtors_aux ()
p++;
(*(p-1)) ();
}
#ifdef EH_FRAME_SECTION_ASM_OP
__deregister_frame (__EH_FRAME_BEGIN__);
#endif
}
/* Stick a call to __do_global_dtors_aux into the .fini section. */
......@@ -143,6 +152,29 @@ fini_dummy ()
asm (TEXT_SECTION_ASM_OP);
}
#ifdef EH_FRAME_SECTION_ASM_OP
/* Stick a call to __register_frame into the .init section. For some reason
calls with no arguments work more reliably in .init, so stick the call
in another function. */
static void
frame_dummy ()
{
__register_frame (__EH_FRAME_BEGIN__);
}
static void
init_dummy ()
{
asm (INIT_SECTION_ASM_OP);
frame_dummy ();
#ifdef FORCE_INIT_SECTION_ALIGN
FORCE_INIT_SECTION_ALIGN;
#endif
asm (TEXT_SECTION_ASM_OP);
}
#endif /* EH_FRAME_SECTION_ASM_OP */
#else /* OBJECT_FORMAT_ELF */
/* The function __do_global_ctors_aux is compiled twice (once in crtbegin.o
......@@ -200,7 +232,9 @@ __do_global_ctors_aux () /* prologue goes in .init section */
#ifdef HAS_INIT_SECTION
/* This case is used by the Irix 6 port, which supports named sections but
not an SVR4-style .fini section. __do_global_dtors can be non-static
in this case because the -fini switch to ld binds strongly. */
in this case because we protect it with -hidden_symbol. */
static char __EH_FRAME_BEGIN__[];
static func_ptr __DTOR_LIST__[];
void
__do_global_dtors ()
......@@ -208,6 +242,10 @@ __do_global_dtors ()
func_ptr *p;
for (p = __DTOR_LIST__ + 1; *p; p++)
(*p) ();
#ifdef EH_FRAME_SECTION_ASM_OP
__deregister_frame (__EH_FRAME_BEGIN__);
#endif
}
#endif
......@@ -244,6 +282,17 @@ asm (DTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
STATIC func_ptr __DTOR_LIST__[1] = { (func_ptr) (-1) };
#endif
#ifdef EH_FRAME_SECTION_ASM_OP
/* Stick a label at the beginning of the frame unwind info so we can register
and deregister it with the exception handling library code. */
asm (EH_FRAME_SECTION_ASM_OP);
#ifdef INIT_SECTION_ASM_OP
STATIC
#endif
char __EH_FRAME_BEGIN__[] = { };
#endif /* EH_FRAME_SECTION_ASM_OP */
#endif /* defined(CRT_BEGIN) */
#ifdef CRT_END
......@@ -327,12 +376,16 @@ __do_global_ctors_aux () /* prologue goes in .text section */
#ifdef HAS_INIT_SECTION
/* This case is used by the Irix 6 port, which supports named sections but
not an SVR4-style .init section. __do_global_ctors can be non-static
in this case because the -init switch to ld binds strongly. */
in this case because we protect it with -hidden_symbol. */
extern char __EH_FRAME_BEGIN__[];
static func_ptr __CTOR_END__[];
void
__do_global_ctors ()
{
func_ptr *p;
#ifdef EH_FRAME_SECTION_ASM_OP
__register_frame (__EH_FRAME_BEGIN__);
#endif
for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
(*p) ();
}
......@@ -363,4 +416,13 @@ asm (DTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
STATIC func_ptr __DTOR_END__[1] = { (func_ptr) 0 };
#endif
#ifdef EH_FRAME_SECTION_ASM_OP
/* Terminate the frame unwind info section with a 4byte 0 as a sentinel;
this would be the 'length' field in a real FDE. */
typedef unsigned int ui32 __attribute__ ((mode (SI)));
asm (EH_FRAME_SECTION_ASM_OP);
STATIC ui32 __FRAME_END__[] = { 0 };
#endif /* EH_FRAME_SECTION */
#endif /* defined(CRT_END) */
......@@ -136,6 +136,6 @@ do { fprintf (FILE, "\t%s\t", ASM_LONG); \
/* If we have a definition of INCOMING_RETURN_ADDR_RTX, assume that
the rest of the DWARF 2 frame unwind support is also provided. */
#ifdef INCOMING_RETURN_ADDR_RTX
#define DWARF2_UNWIND_INFO
#if !defined (DWARF2_UNWIND_INFO) && defined (INCOMING_RETURN_ADDR_RTX)
#define DWARF2_UNWIND_INFO 1
#endif
......@@ -496,7 +496,8 @@ enum dwarf_call_frame_info
DW_CFA_MIPS_advance_loc8 = 0x1d,
/* GNU extensions */
DW_CFA_GNU_window_save = 0x2d
DW_CFA_GNU_window_save = 0x2d,
DW_CFA_GNU_args_size = 0x2e
};
#define DW_CIE_ID 0xffffffff
......
......@@ -281,3 +281,15 @@ extern int protect_cleanup_actions_with_terminate;
#ifdef TREE_CODE
extern tree protect_with_terminate PROTO((tree));
#endif
/* Various hooks for the DWARF 2 __throw routine. */
void expand_builtin_unwind_init PROTO((void));
rtx expand_builtin_dwarf_fp_regnum PROTO((void));
rtx expand_builtin_eh_stub PROTO((void));
#ifdef TREE_CODE
rtx expand_builtin_frob_return_addr PROTO((tree));
rtx expand_builtin_extract_return_addr PROTO((tree));
void expand_builtin_set_return_addr_reg PROTO((tree));
void expand_builtin_set_eh_regs PROTO((tree, tree));
#endif
......@@ -955,9 +955,9 @@ final_start_function (first, file, optimize)
last_linenum = high_block_linenum = high_function_linenum
= NOTE_LINE_NUMBER (first);
#ifdef DWARF2_DEBUGGING_INFO
#if defined (DWARF2_UNWIND_INFO)
/* Output DWARF definition of the function. */
if (write_symbols == DWARF2_DEBUG)
if (dwarf2out_do_frame ())
dwarf2out_begin_prologue ();
#endif
......@@ -992,6 +992,11 @@ final_start_function (first, file, optimize)
profile_function (file);
#endif /* PROFILE_BEFORE_PROLOGUE */
#if defined (DWARF2_UNWIND_INFO) && defined (HAVE_prologue)
if (dwarf2out_do_frame ())
dwarf2out_frame_debug (NULL_RTX);
#endif
#ifdef FUNCTION_PROLOGUE
/* First output the function prologue: code to set up the stack frame. */
FUNCTION_PROLOGUE (file, get_frame_size ());
......@@ -1142,8 +1147,8 @@ final_end_function (first, file, optimize)
dwarfout_end_epilogue ();
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
#if defined (DWARF2_UNWIND_INFO)
if (dwarf2out_do_frame ())
dwarf2out_end_epilogue ();
#endif
......@@ -1265,11 +1270,6 @@ final (first, file, optimize, prescan)
last_ignored_compare = 0;
new_block = 1;
#if defined (DWARF2_DEBUGGING_INFO) && defined (HAVE_prologue)
if (write_symbols == DWARF2_DEBUG)
dwarf2out_frame_debug (NULL_RTX);
#endif
check_exception_handler_labels ();
/* Make a map indicating which line numbers appear in this function.
......@@ -2171,12 +2171,21 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
output_asm_insn (template, recog_operand);
#if defined (DWARF2_DEBUGGING_INFO) && defined (HAVE_prologue)
#if defined (DWARF2_UNWIND_INFO)
#if !defined (ACCUMULATE_OUTGOING_ARGS)
/* If we push arguments, we need to check all insns for stack
adjustments. */
if (dwarf2out_do_frame ())
dwarf2out_frame_debug (insn);
#else
#if defined (HAVE_prologue)
/* If this insn is part of the prologue, emit DWARF v2
call frame info. */
if (write_symbols == DWARF2_DEBUG && RTX_FRAME_RELATED_P (insn))
if (RTX_FRAME_RELATED_P (insn) && dwarf2out_do_frame ())
dwarf2out_frame_debug (insn);
#endif
#endif
#endif
#if 0
/* It's not at all clear why we did this and doing so interferes
......
This diff is collapsed. Click to expand it.
......@@ -5987,6 +5987,26 @@ A C expression to output text to mark the end of an exception region.
This macro need not be defined on most platforms.
@findex EXCEPTION_SECTION
@item EXCEPTION_SECTION ()
A C expression to switch to the section in which the main
exception table is to be placed (@pxref{Sections}). The default is a
section named @code{.gcc_except_table} on machines that support named
sections via @code{ASM_OUTPUT_SECTION_NAME}, otherwise if @samp{-fpic}
or @samp{-fPIC} is in effect, the @code{data_section}, otherwise the
@code{readonly_data_section}.
@findex EH_FRAME_SECTION_ASM_OP
@item EH_FRAME_SECTION_ASM_OP
If defined, a C string constant for the assembler operation to switch to
the section for exception handling frame unwind information. If not
defined, GNU CC will provide a default definition if the target supports
named sections. @file{crtstuff.c} uses this macro to switch to the
appropriate section.
You should define this symbol if your target supports DWARF 2 frame
unwind information and the default definition does not work.
@findex OMIT_EH_TABLE
@item OMIT_EH_TABLE ()
A C expression that is nonzero if the normal exception table output
......@@ -6011,6 +6031,23 @@ for details on when to define this, and how.
@item MASK_RETURN_ADDR
An rtx used to mask the return address found via RETURN_ADDR_RTX, so
that it does not contain any extraneous set bits in it.
@findex DWARF2_UNWIND_INFO
@item DWARF2_UNWIND_INFO
Define this macro to 0 if your target supports DWARF 2 frame unwind
information, but it does not yet work with exception handling.
Otherwise, if your target supports this information (if it defines
@samp{INCOMING_RETURN_ADDR_RTX} and either @samp{UNALIGNED_INT_ASM_OP}
or @samp{OBJECT_FORMAT_ELF}), GCC will provide a default definition of
1.
If this macro is defined to 1, the DWARF 2 unwinder will be the default
exception handling mechanism; otherwise, setjmp/longjmp will be used by
default.
If this macro is defined to anything, the DWARF 2 unwinder will be used
instead of inline unwinders and __unwind_function in the non-setjmp case.
@end table
@node Alignment Output
......
......@@ -2463,6 +2463,10 @@ compile_file (name)
if (write_symbols == DWARF_DEBUG)
TIMEVAR (symout_time, dwarfout_init (asm_out_file, main_input_filename));
#endif
#ifdef DWARF2_UNWIND_INFO
if (dwarf2out_do_frame ())
dwarf2out_frame_init ();
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
TIMEVAR (symout_time, dwarf2out_init (asm_out_file, main_input_filename));
......@@ -2597,8 +2601,7 @@ compile_file (name)
/* Now that all possible functions have been output, we can dump
the exception table. */
if (exception_table_p ())
output_exception_table ();
output_exception_table ();
for (i = 0; i < len; i++)
{
......@@ -2713,6 +2716,11 @@ compile_file (name)
});
#endif
#ifdef DWARF2_UNWIND_INFO
if (dwarf2out_do_frame ())
dwarf2out_frame_finish ();
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
TIMEVAR (symout_time,
......
......@@ -101,6 +101,16 @@ enum built_in_function
BUILT_IN_SETJMP,
BUILT_IN_LONGJMP,
/* Various hooks for the DWARF 2 __throw routine. */
BUILT_IN_FP, BUILT_IN_SP,
BUILT_IN_UNWIND_INIT,
BUILT_IN_DWARF_FP_REGNUM,
BUILT_IN_FROB_RETURN_ADDR,
BUILT_IN_EXTRACT_RETURN_ADDR,
BUILT_IN_SET_RETURN_ADDR_REG,
BUILT_IN_EH_STUB,
BUILT_IN_SET_EH_REGS,
/* C++ extensions */
BUILT_IN_NEW,
BUILT_IN_VEC_NEW,
......
......@@ -170,6 +170,9 @@ static enum in_section { no_section, in_text, in_data, in_named
#ifdef BSS_SECTION_ASM_OP
, in_bss
#endif
#ifdef EH_FRAME_SECTION_ASM_OP
, in_eh_frame
#endif
#ifdef EXTRA_SECTIONS
, EXTRA_SECTIONS
#endif
......@@ -401,6 +404,18 @@ asm_output_aligned_bss (file, decl, name, size, align)
#endif /* BSS_SECTION_ASM_OP */
#ifdef EH_FRAME_SECTION_ASM_OP
void
eh_frame_section ()
{
if (in_section != in_eh_frame)
{
fprintf (asm_out_file, "%s\n", EH_FRAME_SECTION_ASM_OP);
in_section = in_eh_frame;
}
}
#endif
/* Switch to the section for function DECL.
If DECL is NULL_TREE, switch to the text section.
......@@ -461,15 +476,15 @@ variable_section (decl, reloc)
void
exception_section ()
{
#if defined (EXCEPTION_SECTION)
EXCEPTION_SECTION ();
#else
#ifdef ASM_OUTPUT_SECTION_NAME
named_section (NULL_TREE, ".gcc_except_table", 0);
#else
if (flag_pic)
data_section ();
else
#if defined (EXCEPTION_SECTION)
EXCEPTION_SECTION ();
#else
readonly_data_section ();
#endif
#endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment