From 9e800206badd2be563d344e4a0aee83e3ac96f03 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 19 May 2001 17:35:24 -0700 Subject: [PATCH] except.c (dw2_build_landing_pads): Use word_mode, not Pmode, as ncessary. * except.c (dw2_build_landing_pads): Use word_mode, not Pmode, as ncessary. (expand_eh_return): Convert between word_mode and Pmode. * unwind-dw2.c (extract_cie_info): Do not assume words and pointers are the same size. (execute_stack_op): Likewise. (execute_cfa_program): Likewise. (uw_frame_state_for): Likewise. (uw_update_context_1): Likewise. * unwind.inc (_Unwind_Reason_Code): Likewise. * config/mips/mips.h (EH_RETURN_DATA_REGNO): Define. (EH_RETURN_STACKADJ_RTX): Likewise. * config/mips/mips.c (compute_frame_size): Make space for saving EH return registers. (mips_expand_epilogue): Handle EH stack adjustments. * config/mips/mips.md (eh_return): New pattern. (eh_set_lr_si): Likewise. (eh_set_lr_di): Likewise. Add splitter to perform EH return after reload. From-SVN: r42332 --- gcc/ChangeLog | 22 ++++++++ gcc/config/mips/mips.c | 40 ++++++++++++--- gcc/config/mips/mips.h | 4 ++ gcc/config/mips/mips.md | 87 +++++++++++++++++++++++++++++++ gcc/except.c | 16 +++++- gcc/unwind-dw2.c | 111 +++++++++++++++++++++------------------- gcc/unwind.inc | 4 +- 7 files changed, 221 insertions(+), 63 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b5d739cce83..8b4ebf3c8eb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +Sat May 19 18:23:04 2001 Richard Henderson + + * except.c (dw2_build_landing_pads): Use word_mode, not Pmode, + as ncessary. + (expand_eh_return): Convert between word_mode and Pmode. + * unwind-dw2.c (extract_cie_info): Do not assume words and pointers + are the same size. + (execute_stack_op): Likewise. + (execute_cfa_program): Likewise. + (uw_frame_state_for): Likewise. + (uw_update_context_1): Likewise. + * unwind.inc (_Unwind_Reason_Code): Likewise. + * config/mips/mips.h (EH_RETURN_DATA_REGNO): Define. + (EH_RETURN_STACKADJ_RTX): Likewise. + * config/mips/mips.c (compute_frame_size): Make space for saving + EH return registers. + (mips_expand_epilogue): Handle EH stack adjustments. + * config/mips/mips.md (eh_return): New pattern. + (eh_set_lr_si): Likewise. + (eh_set_lr_di): Likewise. + Add splitter to perform EH return after reload. + 2001-05-19 Mark Mitchell * jump.c (mark_jump_label): Tidy previous change. diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index f2081377259..c90857e3050 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -6244,6 +6244,20 @@ compute_frame_size (size) } } + /* We need to restore these for the handler. */ + if (current_function_calls_eh_return) + { + int i; + for (i = 0; ; ++i) + { + regno = EH_RETURN_DATA_REGNO (i); + if (regno == INVALID_REGNUM) + break; + gp_reg_size += GET_MODE_SIZE (gpr_mode); + mask |= 1L << (regno - GP_REG_FIRST); + } + } + /* Calculate space needed for fp registers. */ if (TARGET_FLOAT64 || TARGET_SINGLE_FLOAT) { @@ -7534,13 +7548,27 @@ mips_expand_epilogue () if (tsize > 32767 && TARGET_MIPS16) abort (); + if (current_function_calls_eh_return) + { + rtx eh_ofs = EH_RETURN_STACKADJ_RTX; + if (Pmode == DImode) + emit_insn (gen_adddi3 (eh_ofs, eh_ofs, tsize_rtx)); + else + emit_insn (gen_addsi3 (eh_ofs, eh_ofs, tsize_rtx)); + tsize_rtx = eh_ofs; + } + emit_insn (gen_blockage ()); - if (Pmode == DImode && tsize != 0) - emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx, - tsize_rtx)); - else if (tsize != 0) - emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, - tsize_rtx)); + + if (tsize != 0 || current_function_calls_eh_return) + { + if (Pmode == DImode) + emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx, + tsize_rtx)); + else + emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, + tsize_rtx)); + } } /* The mips16 loads the return address into $7, not $31. */ diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 08f35fa7c2d..3d3ea807fbd 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -1105,6 +1105,10 @@ while (0) /* Before the prologue, RA lives in r31. */ #define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (VOIDmode, GP_REG_FIRST + 31) +/* Describe how we implement __builtin_eh_return. */ +#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + GP_ARG_FIRST : INVALID_REGNUM) +#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, GP_REG_FIRST + 3) + /* Overrides for the COFF debug format. */ #define PUT_SDB_SCL(a) \ do { \ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 31ee4d63c29..5b8d00e9288 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -26,6 +26,26 @@ ;; ??? Currently does not have define_function_unit support for the R8000. ;; Must include new entries for fmadd in addition to existing entries. +;; UNSPEC values used in mips.md +;; Number USE +;; 0 movsi_ul +;; 1 movsi_us, get_fnaddr +;; 2 loadgp +;; 3 eh_set_return +;; 20 builtin_setjmp_setup +;; +;; UNSPEC_VOLATILE values +;; 0 blockage +;; 3 builtin_longjmp +;; 10 consttable_qi +;; 11 consttable_hi +;; 12 consttable_si +;; 13 consttable_di +;; 14 consttable_sf +;; 15 consttable_df +;; 16 align_2 +;; 17 align_4 +;; 18 align_8 ;; .................... @@ -9484,6 +9504,73 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\;j\\t%2" (set_attr "mode" "none") (set_attr "length" "16")]) +;; This is used in compiling the unwind routines. +(define_expand "eh_return" + [(use (match_operand 0 "general_operand" "")) + (use (match_operand 1 "general_operand" ""))] + "" + " +{ + enum machine_mode gpr_mode = TARGET_64BIT ? DImode : SImode; + + if (GET_MODE (operands[1]) != gpr_mode) + operands[1] = convert_to_mode (gpr_mode, operands[1], 0); + if (TARGET_64BIT) + emit_insn (gen_eh_set_lr_di (operands[1])); + else + emit_insn (gen_eh_set_lr_si (operands[1])); + + emit_move_insn (EH_RETURN_STACKADJ_RTX, operands[0]); + DONE; +}") + +;; Clobber the return address on the stack. We can't expand this +;; until we know where it will be put in the stack frame. + +(define_insn "eh_set_lr_si" + [(unspec [(match_operand:SI 0 "register_operand" "r")] 3) + (clobber (match_scratch:SI 1 "=&r"))] + "! TARGET_64BIT" + "#") + +(define_insn "eh_set_lr_di" + [(unspec [(match_operand:DI 0 "register_operand" "r")] 3) + (clobber (match_scratch:DI 1 "=&r"))] + "TARGET_64BIT" + "#") + +(define_split + [(unspec [(match_operand 0 "register_operand" "r")] 3) + (clobber (match_scratch 1 "=&r"))] + "reload_completed" + [(const_int 0)] + " +{ + HOST_WIDE_INT gp_offset; + rtx base; + + compute_frame_size (get_frame_size ()); + if (((current_frame_info.mask >> 31) & 1) == 0) + abort (); + gp_offset = current_frame_info.gp_sp_offset; + + if (gp_offset < 32768) + base = stack_pointer_rtx; + else + { + base = operands[1]; + emit_move_insn (base, GEN_INT (gp_offset)); + if (Pmode == DImode) + emit_insn (gen_adddi3 (base, base, stack_pointer_rtx)); + else + emit_insn (gen_addsi3 (base, base, stack_pointer_rtx)); + gp_offset = 0; + } + emit_move_insn (gen_rtx_MEM (GET_MODE (operands[0]), + plus_constant (base, gp_offset)), + operands[0]); + DONE; +}") ;; ;; .................... diff --git a/gcc/except.c b/gcc/except.c index 48efbf9b8fc..c7493e7d930 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -1897,7 +1897,7 @@ dw2_build_landing_pads () 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 (); @@ -3035,6 +3035,8 @@ expand_eh_return () else #endif { + rtx handler; + ra = EH_RETURN_HANDLER_RTX; if (! ra) { @@ -3043,7 +3045,17 @@ expand_eh_return () } emit_move_insn (sa, cfun->eh->ehr_stackadj); - emit_move_insn (ra, cfun->eh->ehr_handler); + + handler = cfun->eh->ehr_handler; + if (GET_MODE (ra) != Pmode) + { +#ifdef POINTERS_EXTEND_UNSIGNED + handler = convert_memory_address (GET_MODE (ra), handler); +#else + handler = convert_to_mode (GET_MODE (ra), handler, 0); +#endif + } + emit_move_insn (ra, handler); } emit_label (around_label); diff --git a/gcc/unwind-dw2.c b/gcc/unwind-dw2.c index 20deb5721f9..3011bc7341f 100644 --- a/gcc/unwind-dw2.c +++ b/gcc/unwind-dw2.c @@ -218,15 +218,12 @@ extract_cie_info (struct dwarf_cie *cie, struct _Unwind_Context *context, const unsigned char *aug = cie->augmentation; const unsigned char *p = aug + strlen (aug) + 1; const unsigned char *ret = NULL; - _Unwind_Word code_align; - _Unwind_Sword data_align; + _Unwind_Ptr tmp; /* Immediately following the augmentation are the code and data alignment and return address column. */ - p = read_uleb128 (p, &code_align); - p = read_sleb128 (p, &data_align); - fs->code_align = code_align; - fs->data_align = data_align; + p = read_uleb128 (p, &tmp); fs->code_align = tmp; + p = read_sleb128 (p, &tmp); fs->data_align = (saddr) tmp; fs->retaddr_column = *p++; fs->lsda_encoding = DW_EH_PE_omit; @@ -235,9 +232,8 @@ extract_cie_info (struct dwarf_cie *cie, struct _Unwind_Context *context, the size. */ if (*aug == 'z') { - _Unwind_Word i; - p = read_uleb128 (p, &i); - ret = p + i; + p = read_uleb128 (p, &tmp); + ret = p + tmp; fs->saw_z = 1; ++aug; @@ -303,6 +299,7 @@ execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end, enum dwarf_location_atom op = *op_ptr++; _Unwind_Word result, reg; _Unwind_Sword offset; + _Unwind_Ptr ptrtmp; switch (op) { @@ -379,11 +376,12 @@ execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end, op_ptr += 8; break; case DW_OP_constu: - op_ptr = read_uleb128 (op_ptr, &result); + op_ptr = read_uleb128 (op_ptr, &ptrtmp); + result = ptrtmp; break; case DW_OP_consts: - op_ptr = read_sleb128 (op_ptr, &offset); - result = offset; + op_ptr = read_sleb128 (op_ptr, &ptrtmp); + result = (saddr)ptrtmp; break; case DW_OP_reg0: @@ -421,7 +419,7 @@ execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end, result = _Unwind_GetGR (context, op - DW_OP_reg0); break; case DW_OP_regx: - op_ptr = read_uleb128 (op_ptr, ®); + op_ptr = read_uleb128 (op_ptr, &ptrtmp); reg = ptrtmp; result = _Unwind_GetGR (context, reg); break; @@ -457,12 +455,12 @@ execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end, case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31: - op_ptr = read_sleb128 (op_ptr, &offset); + op_ptr = read_sleb128 (op_ptr, &ptrtmp); offset = (saddr)ptrtmp; result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset; break; case DW_OP_bregx: - op_ptr = read_uleb128 (op_ptr, ®); - op_ptr = read_sleb128 (op_ptr, &offset); + op_ptr = read_uleb128 (op_ptr, &ptrtmp); reg = ptrtmp; + op_ptr = read_sleb128 (op_ptr, &ptrtmp); offset = (saddr)ptrtmp; result = _Unwind_GetGR (context, reg) + offset; break; @@ -559,7 +557,7 @@ execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end, result = ~result; break; case DW_OP_plus_uconst: - op_ptr = read_uleb128 (op_ptr, ®); + op_ptr = read_uleb128 (op_ptr, &ptrtmp); reg = ptrtmp; result += reg; break; } @@ -698,16 +696,17 @@ execute_cfa_program (const unsigned char *insn_ptr, while (insn_ptr < insn_end && fs->pc < context->ra) { unsigned char insn = *insn_ptr++; - _Unwind_Word reg, uoffset; + _Unwind_Word reg; _Unwind_Sword offset; + _Unwind_Ptr ptrtmp; if (insn & DW_CFA_advance_loc) fs->pc += (insn & 0x3f) * fs->code_align; else if (insn & DW_CFA_offset) { reg = insn & 0x3f; - insn_ptr = read_uleb128 (insn_ptr, &uoffset); - offset = (_Unwind_Sword)uoffset * fs->data_align; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + offset = ptrtmp * fs->data_align; fs->regs.reg[reg].how = REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = offset; } @@ -724,28 +723,28 @@ execute_cfa_program (const unsigned char *insn_ptr, break; case DW_CFA_advance_loc1: - fs->pc += read_1u (insn_ptr); + fs->pc += read_1u (insn_ptr) * fs->code_align; insn_ptr += 1; break; case DW_CFA_advance_loc2: - fs->pc += read_2u (insn_ptr); + fs->pc += read_2u (insn_ptr) * fs->code_align; insn_ptr += 2; break; case DW_CFA_advance_loc4: - fs->pc += read_4u (insn_ptr); + fs->pc += read_4u (insn_ptr) * fs->code_align; insn_ptr += 4; break; case DW_CFA_offset_extended: - insn_ptr = read_uleb128 (insn_ptr, ®); - insn_ptr = read_uleb128 (insn_ptr, &uoffset); - offset = (_Unwind_Sword)uoffset * fs->data_align; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + offset = ptrtmp * fs->data_align; fs->regs.reg[reg].how = REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = offset; break; case DW_CFA_restore_extended: - insn_ptr = read_uleb128 (insn_ptr, ®); + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; fs->regs.reg[reg].how = REG_UNSAVED; break; @@ -757,8 +756,8 @@ execute_cfa_program (const unsigned char *insn_ptr, case DW_CFA_register: { _Unwind_Word reg2; - insn_ptr = read_uleb128 (insn_ptr, ®); - insn_ptr = read_uleb128 (insn_ptr, ®2); + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg2 = ptrtmp; fs->regs.reg[reg].how = REG_SAVED_REG; fs->regs.reg[reg].loc.reg = reg2; } @@ -790,55 +789,60 @@ execute_cfa_program (const unsigned char *insn_ptr, break; case DW_CFA_def_cfa: - insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg); - insn_ptr = read_uleb128 (insn_ptr, &uoffset); - fs->cfa_offset = uoffset; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + fs->cfa_reg = ptrtmp; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + fs->cfa_offset = ptrtmp; fs->cfa_how = CFA_REG_OFFSET; break; case DW_CFA_def_cfa_register: - insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg); + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + fs->cfa_reg = ptrtmp; fs->cfa_how = CFA_REG_OFFSET; break; case DW_CFA_def_cfa_offset: - insn_ptr = read_uleb128 (insn_ptr, &uoffset); - fs->cfa_offset = uoffset; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + fs->cfa_offset = ptrtmp; /* cfa_how deliberately not set. */ break; case DW_CFA_def_cfa_expression: - insn_ptr = read_uleb128 (insn_ptr, &uoffset); + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); fs->cfa_exp = insn_ptr; fs->cfa_how = CFA_EXP; - insn_ptr += uoffset; + insn_ptr += ptrtmp; break; case DW_CFA_expression: - insn_ptr = read_uleb128 (insn_ptr, ®); - insn_ptr = read_uleb128 (insn_ptr, &uoffset); + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); fs->regs.reg[reg].how = REG_SAVED_EXP; fs->regs.reg[reg].loc.exp = insn_ptr; - insn_ptr += uoffset; + insn_ptr += ptrtmp; break; /* From the 2.1 draft. */ case DW_CFA_offset_extended_sf: - insn_ptr = read_uleb128 (insn_ptr, ®); - insn_ptr = read_sleb128 (insn_ptr, &offset); - offset *= fs->data_align; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; + insn_ptr = read_sleb128 (insn_ptr, &ptrtmp); + offset = (saddr)ptrtmp * fs->data_align; fs->regs.reg[reg].how = REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = offset; break; case DW_CFA_def_cfa_sf: - insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg); - insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset); + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + fs->cfa_reg = ptrtmp; + insn_ptr = read_sleb128 (insn_ptr, &ptrtmp); + fs->cfa_offset = (saddr)ptrtmp; fs->cfa_how = CFA_REG_OFFSET; break; case DW_CFA_def_cfa_offset_sf: - insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_offset); + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + fs->cfa_offset = ptrtmp; /* cfa_how deliberately not set. */ break; @@ -852,15 +856,16 @@ execute_cfa_program (const unsigned char *insn_ptr, break; case DW_CFA_GNU_args_size: - insn_ptr = read_uleb128 (insn_ptr, &context->args_size); + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + context->args_size = ptrtmp; break; case DW_CFA_GNU_negative_offset_extended: /* Obsoleted by DW_CFA_offset_extended_sf, but used by older PowerPC code. */ - insn_ptr = read_uleb128 (insn_ptr, ®); - insn_ptr = read_uleb128 (insn_ptr, &uoffset); - offset = (_Unwind_Sword)uoffset * fs->data_align; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); reg = ptrtmp; + insn_ptr = read_uleb128 (insn_ptr, &ptrtmp); + offset = ptrtmp * fs->data_align; fs->regs.reg[reg].how = REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = -offset; break; @@ -916,7 +921,7 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) insn = NULL; if (fs->saw_z) { - _Unwind_Word i; + _Unwind_Ptr i; aug = read_uleb128 (aug, &i); insn = aug + i; } @@ -964,7 +969,7 @@ uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs) that this will not be a problem. */ { const unsigned char *exp = fs->cfa_exp; - _Unwind_Word len; + _Unwind_Ptr len; exp = read_uleb128 (exp, &len); cfa = (void *) (_Unwind_Ptr) @@ -992,7 +997,7 @@ uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs) case REG_SAVED_EXP: { const unsigned char *exp = fs->regs.reg[i].loc.exp; - _Unwind_Word len; + _Unwind_Ptr len; _Unwind_Ptr val; exp = read_uleb128 (exp, &len); diff --git a/gcc/unwind.inc b/gcc/unwind.inc index a1d1a432f63..85636d40c03 100644 --- a/gcc/unwind.inc +++ b/gcc/unwind.inc @@ -135,8 +135,8 @@ static _Unwind_Reason_Code _Unwind_ForcedUnwind_Phase2(struct _Unwind_Exception *exc, struct _Unwind_Context *context) { - _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) exc->private_1; - void *stop_argument = (void *) exc->private_2; + _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) (_Unwind_Ptr) exc->private_1; + void *stop_argument = (void *) (_Unwind_Ptr) exc->private_2; _Unwind_Reason_Code code, stop_code; while (1) -- 2.30.2