aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>2000-08-08 02:08:55 -0700
committerRichard Henderson <rth@gcc.gnu.org>2000-08-08 02:08:55 -0700
commitdb2e2f480c906879dad6930e4fe0784a52814426 (patch)
treea56e49b5ea637aa6a95652c40bb2747a9110ca5d
parent2a3e384f15e6f10fc62b27c6671d899b083fed97 (diff)
downloadgcc-db2e2f480c906879dad6930e4fe0784a52814426.zip
gcc-db2e2f480c906879dad6930e4fe0784a52814426.tar.gz
gcc-db2e2f480c906879dad6930e4fe0784a52814426.tar.bz2
frame.h (ia64_frame_state): Add my_psp.
* frame.h (ia64_frame_state): Add my_psp. * libgcc2.c (ia64_throw_helper): Add throw_sp argument. (__throw): Pass it in. Don't clobber r7. * config/ia64/frame-ia64.c (init_ia64_reg_loc): Mark inline. (execute_one_ia64_descriptor) [mem_stack_v]: Sets psp.when and nothing to do with sp. (normalize_reg_loc): Use frame->my_psp. (frame_translate): Handle frame-pointer-less functions. Set spill_base correctly, in absence of being told. (__build_ia64_frame_state): New sp argument. Fill in frame->my_sp. (__ia64_backtrace_helper): New sp argument. Use builtin_return_address instead of label addresses. (print_record) [mem_stack_v]: No size member. From-SVN: r35565
-rw-r--r--gcc/ChangeLog20
-rw-r--r--gcc/config/ia64/frame-ia64.c113
-rw-r--r--gcc/frame.h4
-rw-r--r--gcc/libgcc2.c33
4 files changed, 113 insertions, 57 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8b6db10..52dbb26 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,25 @@
2000-08-08 Richard Henderson <rth@cygnus.com>
+ * frame.h (ia64_frame_state): Add my_psp.
+ * libgcc2.c (ia64_throw_helper): Add throw_sp argument.
+ (__throw): Pass it in. Don't clobber r7.
+ * config/ia64/frame-ia64.c (init_ia64_reg_loc): Mark inline.
+ (execute_one_ia64_descriptor) [mem_stack_v]: Sets psp.when
+ and nothing to do with sp.
+ (normalize_reg_loc): Use frame->my_psp.
+ (frame_translate): Handle frame-pointer-less functions. Set
+ spill_base correctly, in absence of being told.
+ (__build_ia64_frame_state): New sp argument. Fill in frame->my_sp.
+ (__ia64_backtrace_helper): New sp argument. Use
+ builtin_return_address instead of label addresses.
+ (print_record) [mem_stack_v]: No size member.
+
+2000-08-08 Richard Henderson <rth@cygnus.com>
+
+ * regclass.c (choose_hard_reg_mode): Iterate over all CC modes.
+
+2000-08-08 Richard Henderson <rth@cygnus.com>
+
* tm.texi (LOCAL_REGNO): Document.
* flow.c (LOCAL_REGNO, EPILOGUE_USES): Provide default.
(mark_regs_live_at_end): Don't mark LOCAL_REGNO registers.
diff --git a/gcc/config/ia64/frame-ia64.c b/gcc/config/ia64/frame-ia64.c
index 4ff78dd..efddd9f 100644
--- a/gcc/config/ia64/frame-ia64.c
+++ b/gcc/config/ia64/frame-ia64.c
@@ -678,7 +678,7 @@ read_P_record (data, val, ptr, header)
/* Frame processing routines. */
/* Initialize a single register structure. */
-static void
+static inline void
init_ia64_reg_loc (reg, size)
ia64_reg_loc *reg;
short size;
@@ -692,7 +692,7 @@ init_ia64_reg_loc (reg, size)
/* Iniitialize an entire frame to the default of nothing. */
static void
init_ia64_unwind_frame (frame)
- ia64_frame_state *frame ;
+ ia64_frame_state *frame;
{
int x;
@@ -741,7 +741,7 @@ execute_one_ia64_descriptor (addr, frame, len)
*len = -1;
addr = get_unwind_record (&region_header, &r, addr);
- /* process it in 2 phases, the first phase will either do the work,
+ /* Process it in 2 phases, the first phase will either do the work,
or set up a pointer to the records we care about
(ie a special purpose ar perhaps, and the second will actually
fill in the record. */
@@ -787,10 +787,12 @@ execute_one_ia64_descriptor (addr, frame, len)
break;
}
case mem_stack_f:
- case mem_stack_v:
- frame->sp.when = r.record.p.t;
frame->sp.l.offset = r.record.p.size;
frame->sp.loc_type = IA64_UNW_LOC_TYPE_OFFSET;
+ frame->sp.when = r.record.p.t;
+ break;
+ case mem_stack_v:
+ frame->psp.when = r.record.p.t;
break;
case psp_gr:
case psp_sprel:
@@ -1091,7 +1093,7 @@ normalize_reg_loc (frame, reg)
case IA64_UNW_LOC_TYPE_BR:
break;
case IA64_UNW_LOC_TYPE_SPOFF:
- /* offset from the stack pointer, calculate the memory address
+ /* Offset from the stack pointer, calculate the memory address
now. */
tmp = (unsigned char *)frame->my_sp + reg->l.offset * 4;
reg->l.mem = tmp;
@@ -1100,7 +1102,7 @@ normalize_reg_loc (frame, reg)
case IA64_UNW_LOC_TYPE_PSPOFF:
/* Actualy go get the value of the PSP add the offset, and thats
the mem location we can find this value at. */
- tmp = (*(unsigned char **)(frame->psp.l.mem)) + 16 - reg->l.offset * 4;
+ tmp = (unsigned char *)frame->my_psp + 16 - reg->l.offset * 4;
reg->l.mem = tmp;
reg->loc_type = IA64_UNW_LOC_TYPE_MEM;
break;
@@ -1114,7 +1116,8 @@ normalize_reg_loc (frame, reg)
}
}
-/* this function looks at a reg_loc and determines if its going
+
+/* This function looks at a reg_loc and determines if its going
to be an executed record or not between time start and end.
It is executed if it is exectued at START time. It is NOT
executed if it happens at END time. */
@@ -1173,7 +1176,7 @@ copy_reg_value (src, dest)
else
{
void **d;
- if (src->reg_size> 16)
+ if (src->reg_size > 16)
abort ();
if (dest->loc_type != IA64_UNW_LOC_TYPE_MEM)
abort ();
@@ -1218,7 +1221,9 @@ process_state_between (frame, start, end)
/* PSP, RP, SP, and PFS are handled seperately from here. */
/* GR's, FR's and BR's are saved at an arbitrary point, so we
- should handle them at teh very beginning. */
+ should handle them at the very beginning. */
+ /* ??? Err, no they aren't. There's the spill_mask record that
+ tells us when each is processed. */
if (start == 0)
{
for (x = 0; x < 4 ; x++)
@@ -1252,25 +1257,52 @@ frame_translate (frame, unwind_time)
ia64_frame_state *frame;
long unwind_time;
{
- /* First, establish values of PFS and PSP and RP, if needed. */
-
- normalize_reg_loc (frame, &frame->pfs);
- normalize_reg_loc (frame, &frame->psp);
- normalize_reg_loc (frame, &frame->rp);
-
+ /* ??? Is this supposed to mark the end of the stack? */
if (frame->rp.loc_type == IA64_UNW_LOC_TYPE_NONE)
return;
- /* The stack pointer at the function start is the PSP value
- saved away. */
- frame->my_sp = __get_real_reg_value (&frame->psp);
+ /* At function entry, SP == PSP. */
+ frame->my_psp = frame->my_sp;
+ if (frame->psp.loc_type != IA64_UNW_LOC_TYPE_NONE)
+ {
+ /* We've saved a frame pointer somewhere. This will be the
+ canonical PSP for the function. */
+ normalize_reg_loc (frame, &frame->psp);
+ if (frame->psp.when < unwind_time)
+ frame->my_psp = __get_real_reg_value (&frame->psp);
+ }
+ else if (frame->sp.loc_type == IA64_UNW_LOC_TYPE_OFFSET)
+ {
+ /* We've a fixed sized stack frame. The PSP is at a known offset. */
+
+ if (frame->sp.when < unwind_time)
+ frame->my_psp = frame->my_sp + frame->sp.l.offset;
+ }
+ /* Otherwise the stack frame size was zero and no adjustment needed. */
- if (frame->psp.loc_type != IA64_UNW_LOC_TYPE_MEM)
- abort ();
+ /* Find PFS, RP and the spill base. All of which might have
+ addresses based off the PSP computed above. */
+ normalize_reg_loc (frame, &frame->pfs);
+ normalize_reg_loc (frame, &frame->rp);
- /* spill base is set up off the PSP register, which should now
- have its value. */
- normalize_reg_loc (frame, &frame->spill_base);
+ if (frame->spill_base.loc_type != IA64_UNW_LOC_TYPE_NONE)
+ normalize_reg_loc (frame, &frame->spill_base);
+ else
+ {
+ /* Otherwise we're supposed to infer it from the size of the
+ saved GR/BR/FR registers, putting the top at psp+16. */
+ long size = 0, i;
+ for (i = 0; i < 4; ++i)
+ if (frame->gr[i].when >= 0)
+ size += 8;
+ for (i = 0; i < 5; ++i)
+ if (frame->br[i].when >= 0)
+ size += 8;
+ for (i = 0; i < 20; ++i)
+ if (frame->fr[i].when >= 0)
+ size += 16;
+ frame->spill_base.l.mem = frame->my_psp + 16 - size;
+ }
/* If the SP is adjusted, process records up to where it
is adjusted, then adjust it, then process the rest. */
@@ -1279,24 +1311,23 @@ frame_translate (frame, unwind_time)
process_state_between (frame, 0, frame->sp.when);
if (frame->sp.loc_type != IA64_UNW_LOC_TYPE_OFFSET)
abort ();
- frame->my_sp =
- (unsigned char *)frame->my_sp - frame->sp.l.offset;
+ frame->my_sp = frame->my_psp - frame->sp.l.offset;
process_state_between (frame, frame->sp.when, unwind_time);
}
else
process_state_between (frame, 0, unwind_time);
}
-/* this function will set a frame_state with all the required fields
+/* This function will set a frame_state with all the required fields
from a functions unwind descriptors.
pc is the location we need info up until (ie, the unwind point)
frame is the frame_state structure to be set up.
Returns a pointer to the unwind info pointer for the frame. */
unwind_info_ptr *
-__build_ia64_frame_state (pc, frame, bsp, pc_base_ptr)
+__build_ia64_frame_state (pc, frame, bsp, sp, pc_base_ptr)
unsigned char *pc;
ia64_frame_state *frame;
- void *bsp;
+ void *bsp, *sp;
void **pc_base_ptr;
{
long len;
@@ -1321,8 +1352,9 @@ __build_ia64_frame_state (pc, frame, bsp, pc_base_ptr)
init_ia64_unwind_frame (frame);
frame->my_bsp = bsp;
+ frame->my_sp = sp;
- /* stop when we get to the end of the descriptor list, or if we
+ /* Stop when we get to the end of the descriptor list, or if we
encounter a region whose initial offset is already past the
PC we are unwinding too. */
@@ -1336,6 +1368,7 @@ __build_ia64_frame_state (pc, frame, bsp, pc_base_ptr)
last_region_size = len;
}
}
+
/* Now we go get the actual values. */
frame_translate (frame, pc_offset);
if (pc_base_ptr)
@@ -1385,10 +1418,10 @@ __calc_caller_bsp (pfs, bsp)
}
static int
-ia64_backtrace_helper (void **array, void *throw_pc,
- ia64_frame_state *throw_frame,
- ia64_frame_state *frame, void *bsp, int size)
+ia64_backtrace_helper (void **array, ia64_frame_state *throw_frame,
+ ia64_frame_state *frame, void *bsp, void *sp, int size)
{
+ void *throw_pc = __builtin_return_address (0);
void *pc = NULL;
int frame_count = 0;
unwind_info_ptr *info;
@@ -1396,7 +1429,7 @@ ia64_backtrace_helper (void **array, void *throw_pc,
__builtin_ia64_flushrs (); /* Make the local register stacks available. */
/* Start at our stack frame, get our state. */
- info = __build_ia64_frame_state (throw_pc, throw_frame, bsp, NULL);
+ info = __build_ia64_frame_state (throw_pc, throw_frame, bsp, sp, NULL);
*frame = *throw_frame;
@@ -1406,7 +1439,7 @@ ia64_backtrace_helper (void **array, void *throw_pc,
--pc;
bsp = __calc_caller_bsp
((long)__get_real_reg_value (&frame->pfs), frame->my_bsp);
- info = __build_ia64_frame_state (pc, frame, bsp, NULL);
+ info = __build_ia64_frame_state (pc, frame, bsp, frame->my_psp, NULL);
if (frame->rp.loc_type == IA64_UNW_LOC_TYPE_NONE) /* We've finished. */
break;
}
@@ -1419,6 +1452,7 @@ ia64_backtrace_helper (void **array, void *throw_pc,
int
__ia64_backtrace (void **array, int size)
{
+ register void *stack_pointer __asm__("r12");
ia64_frame_state my_frame;
ia64_frame_state originator; /* For the context handler is in. */
void *bsp;
@@ -1428,11 +1462,10 @@ __ia64_backtrace (void **array, int size)
registers. */
__builtin_unwind_init ();
-label_ia64:
bsp = __builtin_ia64_bsp ();
- return ia64_backtrace_helper (array, &&label_ia64, &my_frame,
- &originator, bsp, size);
+ return ia64_backtrace_helper (array, &my_frame, &originator, bsp,
+ stack_pointer, size);
}
@@ -1482,10 +1515,12 @@ print_record (f, ptr)
ptr->record.r.grsave);
break;
case mem_stack_f:
- case mem_stack_v:
fprintf (f, "(P7) t = %d, size = %d", ptr->record.p.t,
ptr->record.p.size);
break;
+ case mem_stack_v:
+ fprintf (f, "(P7) t = %d", ptr->record.p.t);
+ break;
case psp_gr:
case rp_gr:
case pfs_gr:
diff --git a/gcc/frame.h b/gcc/frame.h
index dc44561..472d358 100644
--- a/gcc/frame.h
+++ b/gcc/frame.h
@@ -248,6 +248,7 @@ typedef struct ia64_frame_state
ia64_reg_loc sp;
ia64_reg_loc psp;
ia64_reg_loc spill_base;
+ void *my_psp;
void *my_sp;
void *my_bsp;
} ia64_frame_state;
@@ -267,7 +268,8 @@ typedef struct unwind_info_ptr
#define IA64_UNW_HDR_VERSION(x) (((x) >> 48) & 0xffffUL)
extern unwind_info_ptr *__build_ia64_frame_state (unsigned char *,
- ia64_frame_state *, void *,
+ ia64_frame_state *,
+ void *, void *,
void **);
extern void *__get_real_reg_value (ia64_reg_loc *);
extern void *__get_personality (unwind_info_ptr *);
diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c
index 6403676..6163386 100644
--- a/gcc/libgcc2.c
+++ b/gcc/libgcc2.c
@@ -4046,10 +4046,8 @@ __ia64_personality_v1 (void *pc, old_exception_table *table)
}
static void
-ia64_throw_helper (throw_frame, caller, throw_bsp)
- ia64_frame_state *throw_frame;
- ia64_frame_state *caller;
- void *throw_bsp;
+ia64_throw_helper (ia64_frame_state *throw_frame, ia64_frame_state *caller,
+ void *throw_bsp, void *throw_sp)
{
void *throw_pc = __builtin_return_address (0);
unwind_info_ptr *info;
@@ -4061,7 +4059,8 @@ ia64_throw_helper (throw_frame, caller, throw_bsp)
__builtin_ia64_flushrs (); /* Make the local register stacks available. */
/* Start at our stack frame, get our state. */
- __build_ia64_frame_state (throw_pc, throw_frame, throw_bsp, &pc_base);
+ __build_ia64_frame_state (throw_pc, throw_frame, throw_bsp, throw_sp,
+ &pc_base);
/* Now we have to find the proper frame for pc, and see if there
is a handler for it. if not, we keep going back frames until
@@ -4078,8 +4077,10 @@ ia64_throw_helper (throw_frame, caller, throw_bsp)
/* We only care about the RP right now, so we dont need to keep
any other information about a call frame right now. */
pc = __get_real_reg_value (&caller->rp) - 1;
- bsp = __calc_caller_bsp ((long)__get_real_reg_value (&caller->pfs), caller->my_bsp);
- info = __build_ia64_frame_state (pc, caller, bsp, &pc_base);
+ bsp = __calc_caller_bsp ((long)__get_real_reg_value (&caller->pfs),
+ caller->my_bsp);
+ info = __build_ia64_frame_state (pc, caller, bsp, caller->my_psp,
+ &pc_base);
/* If we couldn't find the next frame, we lose. */
if (! info)
@@ -4099,7 +4100,7 @@ ia64_throw_helper (throw_frame, caller, throw_bsp)
}
if (!handler)
- __terminate ();
+ __terminate ();
/* Handler is a segment relative address, so we must adjust it here. */
handler += (long) pc_base;
@@ -4116,8 +4117,9 @@ ia64_throw_helper (throw_frame, caller, throw_bsp)
for ( ; frame_count > 0; frame_count--)
{
pc = __get_real_reg_value (&caller->rp) - 1;
- bsp = __calc_caller_bsp ((long)__get_real_reg_value (&caller->pfs), caller->my_bsp);
- __build_ia64_frame_state (pc, caller, bsp, &pc_base);
+ bsp = __calc_caller_bsp ((long)__get_real_reg_value (&caller->pfs),
+ caller->my_bsp);
+ __build_ia64_frame_state (pc, caller, bsp, caller->my_psp, &pc_base);
/* Any regs that were saved can be put in the throw frame now. */
/* We don't want to copy any saved register from the
target destination, but we do want to load up it's frame. */
@@ -4130,12 +4132,13 @@ ia64_throw_helper (throw_frame, caller, throw_bsp)
/* TODO, do we need to do anything to make the values we wrote 'stick'? */
/* DO we need to go through the whole loadrs seqeunce? */
-
}
+
void
__throw ()
{
+ register void *stack_pointer __asm__("r12");
struct eh_context *eh = (*get_eh_context) ();
ia64_frame_state my_frame;
ia64_frame_state originator; /* For the context handler is in. */
@@ -4149,6 +4152,7 @@ __throw ()
__terminate ();
__builtin_unwind_init ();
+
/* We have to call another routine to actually process the frame
information, which will force all of __throw's local registers into
backing store. */
@@ -4156,7 +4160,7 @@ __throw ()
/* Get the value of ar.bsp while we're here. */
bsp = __builtin_ia64_bsp ();
- ia64_throw_helper (&my_frame, &originator, bsp);
+ ia64_throw_helper (&my_frame, &originator, bsp, stack_pointer);
/* Now we have to fudge the bsp by the amount in our (__throw)
frame marker, since the return is going to adjust it by that much. */
@@ -4166,11 +4170,6 @@ __throw ()
offset = (char *)my_frame.my_bsp - (char *)tmp_bsp;
tmp_bsp = (char *)originator.my_bsp + offset;
- /* A throw handler is trated like a non-local goto, which is architeched
- to set the FP (or PSP) in r7 before branching. gr[0-3] map to
- r4-r7, so we want gr[3]. */
- __set_real_reg_value (&my_frame.gr[3], __get_real_reg_value (&originator.psp));
-
__builtin_eh_return (tmp_bsp, offset, originator.my_sp);
/* The return address was already set by throw_helper. */