#include "output.h"
#include "dwarf2asm.h"
#include "dwarf2out.h"
+#include "dwarf2.h"
#include "toplev.h"
#include "hashtab.h"
#include "intl.h"
/* Protect cleanup actions with must-not-throw regions, with a call
to the given failure handler. */
-tree protect_cleanup_actions;
+tree (*lang_protect_cleanup_actions) PARAMS ((void));
/* Return true if type A catches type B. */
int (*lang_eh_type_covers) PARAMS ((tree a, tree b));
static struct eh_region *expand_eh_region_end PARAMS ((void));
-static rtx get_exception_filter PARAMS ((void));
+static rtx get_exception_filter PARAMS ((struct function *));
static void collect_eh_region_array PARAMS ((void));
static void resolve_fixup_regions PARAMS ((void));
static void push_uleb128 PARAMS ((varray_type *,
unsigned int));
static void push_sleb128 PARAMS ((varray_type *, int));
-static const char *eh_data_format_name PARAMS ((int));
#ifndef HAVE_AS_LEB128
static int dw2_size_of_call_site_table PARAMS ((void));
static int sjlj_size_of_call_site_table PARAMS ((void));
init_eh ()
{
ggc_add_rtx_root (&exception_handler_labels, 1);
- ggc_add_tree_root (&protect_cleanup_actions, 1);
if (! flag_exceptions)
return;
tree handler;
{
struct eh_region *region;
+ tree protect_cleanup_actions;
rtx around_label;
rtx data_save[2];
emit_label (region->label);
+ /* Give the language a chance to specify an action to be taken if an
+ exception is thrown that would propogate out of the HANDLER. */
+ protect_cleanup_actions
+ = (lang_protect_cleanup_actions
+ ? (*lang_protect_cleanup_actions) ()
+ : NULL_TREE);
+
if (protect_cleanup_actions)
expand_eh_region_start ();
/* In case this cleanup involves an inline destructor with a try block in
it, we need to save the EH return data registers around it. */
data_save[0] = gen_reg_rtx (Pmode);
- emit_move_insn (data_save[0], get_exception_pointer ());
+ emit_move_insn (data_save[0], get_exception_pointer (cfun));
data_save[1] = gen_reg_rtx (word_mode);
- emit_move_insn (data_save[1], get_exception_filter ());
+ emit_move_insn (data_save[1], get_exception_filter (cfun));
expand_expr (handler, const0_rtx, VOIDmode, 0);
emit_label (region->label);
expand_expr (failure, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ /* We must adjust the stack before we reach the AROUND_LABEL because
+ the call to FAILURE does not occur on all paths to the
+ AROUND_LABEL. */
+ do_pending_stack_adjust ();
emit_label (around_label);
}
within a handler. */
rtx
-get_exception_pointer ()
+get_exception_pointer (fun)
+ struct function *fun;
{
- rtx exc_ptr = cfun->eh->exc_ptr;
- if (! exc_ptr)
+ rtx exc_ptr = fun->eh->exc_ptr;
+ if (fun == cfun && ! exc_ptr)
{
exc_ptr = gen_reg_rtx (Pmode);
- cfun->eh->exc_ptr = exc_ptr;
+ fun->eh->exc_ptr = exc_ptr;
}
return exc_ptr;
}
within a handler. */
static rtx
-get_exception_filter ()
+get_exception_filter (fun)
+ struct function *fun;
{
- rtx filter = cfun->eh->filter;
- if (! filter)
+ rtx filter = fun->eh->filter;
+ if (fun == cfun && ! filter)
{
filter = gen_reg_rtx (word_mode);
- cfun->eh->filter = filter;
+ fun->eh->filter = filter;
}
return filter;
}
for (i = 1; i <= n; ++i)
{
struct eh_region *fixup = cfun->eh->region_array[i];
- struct eh_region *cleanup;
+ struct eh_region *cleanup = 0;
if (! fixup || fixup->type != ERT_FIXUP)
continue;
emit_move_insn (cfun->eh->exc_ptr,
gen_rtx_REG (Pmode, EH_RETURN_DATA_REGNO (0)));
emit_move_insn (cfun->eh->filter,
- gen_rtx_REG (Pmode, EH_RETURN_DATA_REGNO (1)));
+ gen_rtx_REG (word_mode, EH_RETURN_DATA_REGNO (1)));
seq = get_insns ();
end_sequence ();
start_sequence ();
+ /* We're storing this libcall's address into memory instead of
+ calling it directly. Thus, we must call assemble_external_libcall
+ here, as we can not depend on emit_library_call to do it for us. */
+ assemble_external_libcall (eh_personality_libfunc);
mem = change_address (fc, Pmode,
plus_constant (XEXP (fc, 0), sjlj_fc_personality_ofs));
emit_move_insn (mem, eh_personality_libfunc);
/* These registers are used by the landing pads. Make sure they
have been generated. */
- get_exception_pointer ();
- get_exception_filter ();
+ get_exception_pointer (cfun);
+ get_exception_filter (cfun);
/* Construct the landing pads. */
{
rtx addr = expand_expr (addr_tree, NULL_RTX, Pmode, 0);
+#ifdef POINTERS_EXTEND_UNSIGNED
+ addr = convert_memory_address (Pmode, addr);
+#endif
+
#ifdef RETURN_ADDR_OFFSET
addr = force_reg (Pmode, addr);
addr = plus_constant (addr, -RETURN_ADDR_OFFSET);
stackadj = expand_expr (stackadj_tree, cfun->eh->ehr_stackadj, VOIDmode, 0);
handler = expand_expr (handler_tree, cfun->eh->ehr_handler, VOIDmode, 0);
+#ifdef POINTERS_EXTEND_UNSIGNED
+ stackadj = convert_memory_address (Pmode, stackadj);
+ handler = convert_memory_address (Pmode, handler);
+#endif
+
if (! cfun->eh->ehr_label)
{
cfun->eh->ehr_stackadj = copy_to_reg (stackadj);
}
\f
-#define DW_EH_PE_absptr 0x00
-#define DW_EH_PE_omit 0xff
-
-#define DW_EH_PE_uleb128 0x01
-#define DW_EH_PE_udata2 0x02
-#define DW_EH_PE_udata4 0x03
-#define DW_EH_PE_udata8 0x04
-#define DW_EH_PE_sleb128 0x09
-#define DW_EH_PE_sdata2 0x0A
-#define DW_EH_PE_sdata4 0x0B
-#define DW_EH_PE_sdata8 0x0C
-#define DW_EH_PE_signed 0x08
-
-#define DW_EH_PE_pcrel 0x10
-#define DW_EH_PE_textrel 0x20
-#define DW_EH_PE_datarel 0x30
-#define DW_EH_PE_funcrel 0x40
-
-static const char *
-eh_data_format_name (format)
- int format;
-{
- switch (format)
- {
- case DW_EH_PE_absptr: return "absolute";
- case DW_EH_PE_omit: return "omit";
-
- case DW_EH_PE_uleb128: return "uleb128";
- case DW_EH_PE_udata2: return "udata2";
- case DW_EH_PE_udata4: return "udata4";
- case DW_EH_PE_udata8: return "udata8";
- case DW_EH_PE_sleb128: return "sleb128";
- case DW_EH_PE_sdata2: return "sdata2";
- case DW_EH_PE_sdata4: return "sdata4";
- case DW_EH_PE_sdata8: return "sdata8";
-
- case DW_EH_PE_uleb128 | DW_EH_PE_pcrel: return "pcrel uleb128";
- case DW_EH_PE_udata2 | DW_EH_PE_pcrel: return "pcrel udata2";
- case DW_EH_PE_udata4 | DW_EH_PE_pcrel: return "pcrel udata4";
- case DW_EH_PE_udata8 | DW_EH_PE_pcrel: return "pcrel udata8";
- case DW_EH_PE_sleb128 | DW_EH_PE_pcrel: return "pcrel sleb128";
- case DW_EH_PE_sdata2 | DW_EH_PE_pcrel: return "pcrel sdata2";
- case DW_EH_PE_sdata4 | DW_EH_PE_pcrel: return "pcrel sdata4";
- case DW_EH_PE_sdata8 | DW_EH_PE_pcrel: return "pcrel sdata8";
-
- case DW_EH_PE_uleb128 | DW_EH_PE_textrel: return "textrel uleb128";
- case DW_EH_PE_udata2 | DW_EH_PE_textrel: return "textrel udata2";
- case DW_EH_PE_udata4 | DW_EH_PE_textrel: return "textrel udata4";
- case DW_EH_PE_udata8 | DW_EH_PE_textrel: return "textrel udata8";
- case DW_EH_PE_sleb128 | DW_EH_PE_textrel: return "textrel sleb128";
- case DW_EH_PE_sdata2 | DW_EH_PE_textrel: return "textrel sdata2";
- case DW_EH_PE_sdata4 | DW_EH_PE_textrel: return "textrel sdata4";
- case DW_EH_PE_sdata8 | DW_EH_PE_textrel: return "textrel sdata8";
-
- case DW_EH_PE_uleb128 | DW_EH_PE_datarel: return "datarel uleb128";
- case DW_EH_PE_udata2 | DW_EH_PE_datarel: return "datarel udata2";
- case DW_EH_PE_udata4 | DW_EH_PE_datarel: return "datarel udata4";
- case DW_EH_PE_udata8 | DW_EH_PE_datarel: return "datarel udata8";
- case DW_EH_PE_sleb128 | DW_EH_PE_datarel: return "datarel sleb128";
- case DW_EH_PE_sdata2 | DW_EH_PE_datarel: return "datarel sdata2";
- case DW_EH_PE_sdata4 | DW_EH_PE_datarel: return "datarel sdata4";
- case DW_EH_PE_sdata8 | DW_EH_PE_datarel: return "datarel sdata8";
-
- case DW_EH_PE_uleb128 | DW_EH_PE_funcrel: return "funcrel uleb128";
- case DW_EH_PE_udata2 | DW_EH_PE_funcrel: return "funcrel udata2";
- case DW_EH_PE_udata4 | DW_EH_PE_funcrel: return "funcrel udata4";
- case DW_EH_PE_udata8 | DW_EH_PE_funcrel: return "funcrel udata8";
- case DW_EH_PE_sleb128 | DW_EH_PE_funcrel: return "funcrel sleb128";
- case DW_EH_PE_sdata2 | DW_EH_PE_funcrel: return "funcrel sdata2";
- case DW_EH_PE_sdata4 | DW_EH_PE_funcrel: return "funcrel sdata4";
- case DW_EH_PE_sdata8 | DW_EH_PE_funcrel: return "funcrel sdata8";
-
- default:
- abort ();
- }
-}
-
#ifndef HAVE_AS_LEB128
static int
dw2_size_of_call_site_table ()
void
output_function_exception_table ()
{
- int format, i, n;
+ int tt_format, cs_format, lp_format, i, n;
#ifdef HAVE_AS_LEB128
char ttype_label[32];
char cs_after_size_label[32];
#endif
int have_tt_data;
int funcdef_number;
+ int tt_format_size;
/* Not all functions need anything. */
if (! cfun->uses_eh_lsda)
? sjlj_funcdef_number
: current_funcdef_number);
+#ifdef IA64_UNWIND_INFO
+ fputs ("\t.personality\t", asm_out_file);
+ output_addr_const (asm_out_file, eh_personality_libfunc);
+ fputs ("\n\t.handlerdata\n", asm_out_file);
+ /* Note that varasm still thinks we're in the function's code section.
+ The ".endp" directive that will immediately follow will take us back. */
+#else
exception_section ();
+#endif
have_tt_data = (VARRAY_ACTIVE_SIZE (cfun->eh->ttype_data) > 0
|| VARRAY_ACTIVE_SIZE (cfun->eh->ehspec_data) > 0);
- if (have_tt_data)
- assemble_eh_align (GET_MODE_ALIGNMENT (ptr_mode));
+ /* Indicate the format of the @TType entries. */
+ if (! have_tt_data)
+ tt_format = DW_EH_PE_omit;
+ else
+ {
+ tt_format = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
+#ifdef HAVE_AS_LEB128
+ ASM_GENERATE_INTERNAL_LABEL (ttype_label, "LLSDATT", funcdef_number);
+#endif
+ tt_format_size = size_of_encoded_value (tt_format);
+
+ assemble_eh_align (tt_format_size * BITS_PER_UNIT);
+ }
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LLSDA", funcdef_number);
be most useful in moving the landing pads completely out of
line to another section, but it could also be used to minimize
the size of uleb128 landing pad offsets. */
- format = DW_EH_PE_omit;
- dw2_asm_output_data (1, format, "@LPStart format (%s)",
- eh_data_format_name (format));
+ lp_format = DW_EH_PE_omit;
+ dw2_asm_output_data (1, lp_format, "@LPStart format (%s)",
+ eh_data_format_name (lp_format));
/* @LPStart pointer would go here. */
- /* Indicate the format of the @TType entries. */
- if (! have_tt_data)
- format = DW_EH_PE_omit;
- else
- {
- /* ??? Define a ASM_PREFERRED_DATA_FORMAT to say what
- sort of dynamic-relocation-free reference to emit. */
- format = 0;
-#ifdef HAVE_AS_LEB128
- ASM_GENERATE_INTERNAL_LABEL (ttype_label, "LLSDATT", funcdef_number);
-#endif
- }
- dw2_asm_output_data (1, format, "@TType format (%s)",
- eh_data_format_name (format));
+ dw2_asm_output_data (1, tt_format, "@TType format (%s)",
+ eh_data_format_name (tt_format));
#ifndef HAVE_AS_LEB128
if (USING_SJLJ_EXCEPTIONS)
ASM_OUTPUT_LABEL (asm_out_file, ttype_after_disp_label);
#else
/* Ug. Alignment queers things. */
- unsigned int before_disp, after_disp, last_disp, disp, align;
+ unsigned int before_disp, after_disp, last_disp, disp;
- align = POINTER_SIZE / BITS_PER_UNIT;
before_disp = 1 + 1;
after_disp = (1 + size_of_uleb128 (call_site_len)
+ call_site_len
+ VARRAY_ACTIVE_SIZE (cfun->eh->action_record_data)
- + VARRAY_ACTIVE_SIZE (cfun->eh->ttype_data) * align);
+ + (VARRAY_ACTIVE_SIZE (cfun->eh->ttype_data)
+ * tt_format_size));
disp = after_disp;
do
last_disp = disp;
disp_size = size_of_uleb128 (disp);
pad = before_disp + disp_size + after_disp;
- if (pad % align)
- pad = align - (pad % align);
+ if (pad % tt_format_size)
+ pad = tt_format_size - (pad % tt_format_size);
else
pad = 0;
disp = after_disp + pad;
/* Indicate the format of the call-site offsets. */
#ifdef HAVE_AS_LEB128
- format = DW_EH_PE_uleb128;
+ cs_format = DW_EH_PE_uleb128;
#else
- format = DW_EH_PE_udata4;
+ cs_format = DW_EH_PE_udata4;
#endif
- dw2_asm_output_data (1, format, "call-site format (%s)",
- eh_data_format_name (format));
+ dw2_asm_output_data (1, cs_format, "call-site format (%s)",
+ eh_data_format_name (cs_format));
#ifdef HAVE_AS_LEB128
ASM_GENERATE_INTERNAL_LABEL (cs_after_size_label, "LLSDACSB",
(i ? NULL : "Action record table"));
if (have_tt_data)
- assemble_eh_align (GET_MODE_ALIGNMENT (ptr_mode));
+ assemble_eh_align (tt_format_size * BITS_PER_UNIT);
i = VARRAY_ACTIVE_SIZE (cfun->eh->ttype_data);
while (i-- > 0)
else
type = lookup_type_for_runtime (type);
- /* ??? Handle ASM_PREFERRED_DATA_FORMAT. */
- output_constant (type, GET_MODE_SIZE (ptr_mode));
+ dw2_asm_output_encoded_addr_rtx (tt_format,
+ expand_expr (type, NULL_RTX, VOIDmode,
+ EXPAND_INITIALIZER),
+ NULL);
}
#ifdef HAVE_AS_LEB128