Mercurial > hg > CbC > CbC_gcc
diff gcc/config/ia64/unwind-ia64.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children |
line wrap: on
line diff
--- a/gcc/config/ia64/unwind-ia64.c Sun Feb 07 18:28:00 2010 +0900 +++ b/gcc/config/ia64/unwind-ia64.c Fri Feb 12 23:39:51 2010 +0900 @@ -41,12 +41,12 @@ #ifndef __USING_SJLJ_EXCEPTIONS__ -#define UNW_VER(x) ((x) >> 48) -#define UNW_FLAG_MASK 0x0000ffff00000000 -#define UNW_FLAG_OSMASK 0x0000f00000000000 -#define UNW_FLAG_EHANDLER(x) ((x) & 0x0000000100000000L) -#define UNW_FLAG_UHANDLER(x) ((x) & 0x0000000200000000L) -#define UNW_LENGTH(x) ((x) & 0x00000000ffffffffL) + +/* By default, assume personality routine interface compatibility with + our expectations. */ +#ifndef MD_UNW_COMPATIBLE_PERSONALITY_P +#define MD_UNW_COMPATIBLE_PERSONALITY_P(HEADER) 1 +#endif enum unw_application_register { @@ -204,6 +204,9 @@ unsigned long *pfs_loc; /* Save location for pfs in current (corr. to sp) frame. Target contains cfm for caller. */ + unsigned long *signal_pfs_loc;/* Save location for pfs in current + signal frame. Target contains + pfs for caller. */ unsigned long *pri_unat_loc; unsigned long *unat_loc; unsigned long *lc_loc; @@ -439,7 +442,13 @@ { switch (abreg) { +#if TARGET_ABI_OPEN_VMS + /* OpenVMS Calling Standard specifies R3 - R31. */ + case 0x03 ... 0x1f: return UNW_REG_R2 + (abreg - 0x02); +#else + /* Standard Intel ABI specifies GR 4 - 7. */ case 0x04 ... 0x07: return UNW_REG_R4 + (abreg - 0x04); +#endif case 0x22 ... 0x25: return UNW_REG_F2 + (abreg - 0x22); case 0x30 ... 0x3f: return UNW_REG_F16 + (abreg - 0x30); case 0x41 ... 0x45: return UNW_REG_B1 + (abreg - 0x41); @@ -1730,14 +1739,14 @@ void * _Unwind_FindEnclosingFunction (void *pc) { - struct unw_table_entry *ent; + struct unw_table_entry *entp, ent; unsigned long segment_base, gp; - ent = _Unwind_FindTableEntry (pc, &segment_base, &gp); - if (ent == NULL) + entp = _Unwind_FindTableEntry (pc, &segment_base, &gp, &ent); + if (entp == NULL) return NULL; else - return (void *)(segment_base + ent->start_offset); + return (void *)(segment_base + entp->start_offset); } /* Get the value of the CFA as saved in CONTEXT. In GCC/Dwarf2 parlance, @@ -1765,7 +1774,7 @@ static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) { - struct unw_table_entry *ent; + struct unw_table_entry *entp, ent; unsigned long *unw, header, length; unsigned char *insn, *insn_end; unsigned long segment_base; @@ -1776,9 +1785,9 @@ r->when = UNW_WHEN_NEVER; context->lsda = 0; - ent = _Unwind_FindTableEntry ((void *) context->rp, - &segment_base, &context->gp); - if (ent == NULL) + entp = _Unwind_FindTableEntry ((void *) context->rp, + &segment_base, &context->gp, &ent); + if (entp == NULL) { /* Couldn't find unwind info for this function. Try an os-specific fallback mechanism. This will necessarily @@ -1786,6 +1795,7 @@ #ifdef MD_FALLBACK_FRAME_STATE_FOR if (MD_FALLBACK_FRAME_STATE_FOR (context, fs) == _URC_NO_REASON) return _URC_NO_REASON; +#endif /* [SCRA 11.4.1] A leaf function with no memory stack, no exception handlers, and which keeps the return value in B0 does not need @@ -1794,29 +1804,42 @@ This can only happen in the frame after unwinding through a signal handler. Avoid infinite looping by requiring that B0 != RP. RP == 0 terminates the chain. */ - if (context->br_loc[0] && *context->br_loc[0] != context->rp + if (context->br_loc[0] + && *context->br_loc[0] != context->rp && context->rp != 0) - { - fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_BR; - fs->curr.reg[UNW_REG_RP].when = -1; - fs->curr.reg[UNW_REG_RP].val = 0; - return _URC_NO_REASON; - } -#endif + goto skip_unwind_info; + return _URC_END_OF_STACK; } - context->region_start = ent->start_offset + segment_base; + context->region_start = entp->start_offset + segment_base; fs->when_target = ((context->rp & -16) - context->region_start) / 16 * 3 + (context->rp & 15); - unw = (unsigned long *) (ent->info_offset + segment_base); + unw = (unsigned long *) (entp->info_offset + segment_base); header = *unw; length = UNW_LENGTH (header); - /* ??? Perhaps check UNW_VER / UNW_FLAG_OSMASK. */ + /* Some operating systems use the personality routine slot in way not + compatible with what we expect. For instance, OpenVMS uses this slot to + designate "condition handlers" with very different arguments than what we + would be providing. Such cases are typically identified from OS specific + bits in the unwind information block header, and checked by the target + MD_UNW_COMPATIBLE_PERSONALITY_P macro. - if (UNW_FLAG_EHANDLER (header) | UNW_FLAG_UHANDLER (header)) + We just pretend there is no personality from our standpoint in such + situations, and expect GCC not to set the identifying bits itself so that + compatible personalities for GCC compiled code are called. + + Of course, this raises the question of what combinations of native/GCC + calls can be expected to behave properly exception handling-wise. We are + not to provide a magic answer here, merely to prevent crashes assuming + users know what they are doing. + + ??? Perhaps check UNW_VER / UNW_FLAG_OSMASK as well. */ + + if (MD_UNW_COMPATIBLE_PERSONALITY_P (header) + && (UNW_FLAG_EHANDLER (header) | UNW_FLAG_UHANDLER (header))) { fs->personality = *(_Unwind_Personality_Fn *) (unw[length + 1] + context->gp); @@ -1850,7 +1873,8 @@ r->where = UNW_WHERE_NONE; } - /* If RP did't get saved, generate entry for the return link register. */ +skip_unwind_info: + /* If RP didn't get saved, generate entry for the return link register. */ if (fs->curr.reg[UNW_REG_RP].when >= fs->when_target) { fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_BR; @@ -1858,6 +1882,27 @@ fs->curr.reg[UNW_REG_RP].val = fs->return_link_reg; } + /* There is a subtlety for the frame after unwinding through a signal + handler: should we restore the cfm as usual or the pfs? We can't + restore both because we use br.ret to resume execution of user code. + For other frames the procedure is by definition non-leaf so the pfs + is saved and restored and thus effectively dead in the body; only + the cfm need therefore be restored. + + Here we have 2 cases: + - either the pfs is saved and restored and thus effectively dead + like in regular frames; then we do nothing special and restore + the cfm. + - or the pfs is not saved and thus live; but in that case the + procedure is necessarily leaf so the cfm is effectively dead + and we restore the pfs. */ + if (context->signal_pfs_loc) + { + if (fs->curr.reg[UNW_REG_PFS].when >= fs->when_target) + context->pfs_loc = context->signal_pfs_loc; + context->signal_pfs_loc = NULL; + } + return _URC_NO_REASON; } @@ -2081,7 +2126,7 @@ uw_init_context_1 (CONTEXT, __builtin_ia64_bsp ()); \ } while (0) -static void +static void __attribute__((noinline)) uw_init_context_1 (struct _Unwind_Context *context, void *bsp) { void *rp = __builtin_extract_return_addr (__builtin_return_address (0));