Fix gas/gcc unwind/EH discrepancies. And a shared library build problem.

* frame.h (struct unwind_info_ptr): Collapse version, flags, and length
	fields into header field.
	(IA64_UNW_HDR_LENGTH, IA64_UNW_HDR_FLAGS, IA64_UNW_HDR_VERSION): New
	macros to access length, flags, and version info from header field.
	* config/ia64/crtbegin.asm (__do_frame_setup_aux): Delete here.
	...

From-SVN: r34441
This commit is contained in:
James E. Wilson 2000-06-07 02:27:51 +00:00 committed by Jim Wilson
parent 24c40136c3
commit c0240be463
6 changed files with 101 additions and 69 deletions

View File

@ -1,3 +1,23 @@
2000-06-06 James E. Wilson <wilson@cygnus.com>
* frame.h (struct unwind_info_ptr): Collapse version, flags, and length
fields into header field.
(IA64_UNW_HDR_LENGTH, IA64_UNW_HDR_FLAGS, IA64_UNW_HDR_VERSION): New
macros to access length, flags, and version info from header field.
* config/ia64/crtbegin.asm (__do_frame_setup_aux): Delete here.
* config/ia64/crtend.asm (__do_frame_setup_aux): Add here.
(__do_global_ctors_aux): Fix caller.
* config/ia64/frame-ia64.c (get_unwind_record): Change parameter
prologue_flag to header. Pass to read_P_record.
(read_P_record): New argument header. Implement P4 format.
Multiply P7_T_SIZE by 16.
(execute_one_ia64_descriptor): New static local region_header. Pass to
get_unwind_record. Copy r to region_header if r is a header record.
(print_all_records): Likewise.
(__build_ia64_frame_state): Use IA64_UNW_HDR_LENGTH.
(__get_personality, __get_except_table): Likewise.
* config/ia64/ia64.c (process_set): Do not divide offsets by 4.
2000-06-06 Philipp Thomas <pthomas@suse.de>
* configure.in (AC_C_INLINE): Added.

View File

@ -296,38 +296,3 @@ __do_frame_setup:
#endif
.weak __deregister_frame_info#
.weak __register_frame_info#
.text
.align 16
.global __do_frame_setup_aux#
.proc __do_frame_setup_aux#
__do_frame_setup_aux:
/*
if (__register_frame_info_aux)
__register_frame_info_aux(__EH_FRAME_END__)
*/
alloc loc0 = ar.pfs, 0, 3, 1, 0
addl r14 = @ltoff(@fptr(__register_frame_info_aux#)), gp
mov loc1 = b0
;;
// r16 contains the address of a pointer to __EH_FRAME_END__.
ld8 out0 = [r16]
ld8 r15 = [r14]
mov loc2 = gp
;;
cmp.eq p6, p7 = 0, r15
(p6) br.cond.dptk 1f
ld8 r8 = [r15], 8
;;
ld8 gp = [r15]
mov b6 = r8
;;
br.call.sptk.many b0 = b6
;;
1:
mov gp = loc2
mov ar.pfs = loc0
mov b0 = loc1
br.ret.sptk.many b0
.endp __do_frame_setup#
.weak __register_frame_info_aux#

View File

@ -113,7 +113,6 @@ __do_global_ctors_aux:
.section .init,"ax","progbits"
{ .mlx
// __do_frame_setup_aux is in crtbegin.asm
movl r2 = @gprel(__do_frame_setup_aux#)
;;
}
@ -123,12 +122,42 @@ __do_global_ctors_aux:
;;
mov b6 = r2
}
{ .mib
// __do_frame_setup_aux needs the address of __EH_FRAME_END__,
// so we pass it in r16. This is rather evil, but we have no
// output registers.
addl r16 = @ltoff(__EH_FRAME_END__#), gp
{ .bbb
br.call.sptk.many b0 = b6
;;
}
.text
.align 16
.proc __do_frame_setup_aux#
__do_frame_setup_aux:
/*
if (__register_frame_info_aux)
__register_frame_info_aux(__EH_FRAME_END__)
*/
alloc loc0 = ar.pfs, 0, 3, 1, 0
addl r14 = @ltoff(@fptr(__register_frame_info_aux#)), gp
mov loc1 = b0
;;
ld8 r15 = [r14]
addl r16 = @ltoff(__EH_FRAME_END__#), gp
mov loc2 = gp
;;
cmp.eq p6, p7 = 0, r15
(p6) br.cond.dptk 1f
ld8 r8 = [r15], 8
ld8 out0 = [r16]
;;
ld8 gp = [r15]
mov b6 = r8
;;
br.call.sptk.many b0 = b6
;;
1:
mov gp = loc2
mov ar.pfs = loc0
mov b0 = loc1
br.ret.sptk.many b0
.endp __do_frame_setup_aux#
.weak __register_frame_info_aux#

View File

@ -247,23 +247,22 @@ bad_record (ptr, offset)
static unsigned char *read_R_record (unwind_record *, unsigned char, unsigned char *);
static unsigned char *read_X_record (unwind_record *, unsigned char, unsigned char *);
static unsigned char *read_B_record (unwind_record *, unsigned char, unsigned char *);
static unsigned char *read_P_record (unwind_record *, unsigned char, unsigned char *);
static unsigned char *read_P_record (unwind_record *, unsigned char, unsigned char *, unwind_record *);
/* This routine will determine what type of record the memory pointer
is refering to, and fill in the appropriate fields for that record type.
PROLOGUE_FLAG is TRUE if we are currently processing a PROLOGUE
body.
HEADER is a pointer to the last region header unwind record.
DATA is a pointer to an unwind record which will be filled in.
PTR is a pointer to the current location in the unwind table where we
will read the next record from.
The return value is the start of the next record. */
extern unsigned char *
get_unwind_record (prologue_flag, data, ptr)
int prologue_flag;
unwind_record *data;
unsigned char *ptr;
get_unwind_record (header, data, ptr)
unwind_record *header;
unwind_record *data;
unsigned char *ptr;
{
unsigned char val = *ptr++;
@ -275,8 +274,8 @@ get_unwind_record (prologue_flag, data, ptr)
if (val == UNW_X1 || val == UNW_X2 || val == UNW_X3 || val == UNW_X4)
return read_X_record (data, val, ptr);
if (prologue_flag)
return read_P_record (data, val, ptr);
if (header->type != body)
return read_P_record (data, val, ptr, header);
else
return read_B_record (data, val, ptr);
}
@ -534,10 +533,11 @@ static unsigned char P8_additional_fields [] = {
static unsigned char *
read_P_record (data, val, ptr)
read_P_record (data, val, ptr, header)
unwind_record *data;
unsigned char val;
unsigned char *ptr;
unwind_record *header;
{
if ((val & 0xe0) == 0x80)
{
@ -575,13 +575,12 @@ read_P_record (data, val, ptr)
if (val == UNW_P4)
{
/* P4 format. Currently unimplemented. */
int len = 0; /* TODO.. get prologue rlen. */
int size = (len * 2 + 7) / 8;
/* P4 format. */
int size = (header->record.r.rlen * 2 + 7) / 8;
data->type = spill_mask;
data->record.p.imask = (unsigned char *) malloc (size);
/* memcpy (data->record.p.imask, ptr, size); */
memcpy (data->record.p.imask, ptr, size);
return ptr+size;
}
@ -617,7 +616,7 @@ read_P_record (data, val, ptr)
{
case P7_T_SIZE:
data->record.p.t = read_uleb128 (&ptr);
data->record.p.size = read_uleb128 (&ptr);
data->record.p.size = read_uleb128 (&ptr) << 4;
break;
case P7_T:
data->record.p.t = read_uleb128 (&ptr);
@ -733,11 +732,14 @@ execute_one_ia64_descriptor (addr, frame, len)
long *len;
{
unwind_record r;
/* The last region_header. Needed to distinguish between prologue and body
descriptors. Also needed for length of P4 format. */
static unwind_record region_header;
ia64_reg_loc *loc_ptr = NULL;
int grmask = 0, frmask = 0;
*len = -1;
addr = get_unwind_record (1, &r, addr);
addr = get_unwind_record (&region_header, &r, addr);
/* process it in 2 phases, the first phase will either do the work,
or set up a pointer to the records we care about
@ -748,6 +750,7 @@ execute_one_ia64_descriptor (addr, frame, len)
case prologue:
case body:
*len = r.record.r.rlen;
memcpy (&region_header, &r, sizeof (unwind_record));
break;
case prologue_gr:
{
@ -780,6 +783,7 @@ execute_one_ia64_descriptor (addr, frame, len)
frame->pr.loc_type = IA64_UNW_LOC_TYPE_GR;
frame->pr.l.regno = reg++;
}
memcpy (&region_header, &r, sizeof (unwind_record));
break;
}
case mem_stack_f:
@ -1312,7 +1316,7 @@ __build_ia64_frame_state (pc, frame, bsp, pc_base_ptr)
start_pc = pc_base + entry->start_offset;
unw_info_ptr = ((struct unwind_info_ptr *)(pc_base + entry->unwind_offset));
addr = unw_info_ptr->unwind_descriptors;
end = addr + unw_info_ptr->length * 8;
end = addr + IA64_UNW_HDR_LENGTH (unw_info_ptr->header) * 8;
pc_offset = (pc - start_pc) / 16 * 3;
init_ia64_unwind_frame (frame);
@ -1345,7 +1349,8 @@ __get_personality (ptr)
unwind_info_ptr *ptr;
{
void **p;
p = (void **) (ptr->unwind_descriptors + ptr->length * 8);
p = (void **) (ptr->unwind_descriptors
+ IA64_UNW_HDR_LENGTH (ptr->header) * 8);
return *p;
}
@ -1354,11 +1359,13 @@ __get_except_table (ptr)
unwind_info_ptr *ptr;
{
void **p, *table;
p = (void **) (ptr->unwind_descriptors + ptr->length * 8);
p = (void **) (ptr->unwind_descriptors
+ IA64_UNW_HDR_LENGTH (ptr->header) * 8);
/* If there is no personality, there is no handler data. */
if (*p == 0)
return 0;
table = (void *) (ptr->unwind_descriptors + ptr->length * 8 + 8);
table = (void *) (ptr->unwind_descriptors
+ IA64_UNW_HDR_LENGTH (ptr->header) * 8 + 8);
return table;
}
@ -1595,12 +1602,23 @@ print_all_records (f, mem, size)
{
unsigned char *end = mem + size;
unwind_record r;
static unwind_record region_header;
fprintf (f, "UNWIND IMAGE:\n");
while (mem < end)
{
mem = get_unwind_record (1, &r, mem);
mem = get_unwind_record (&region_header, &r, mem);
print_record (f, &r);
switch (r.type)
{
case prologue:
case body:
case prologue_gr:
memcpy (region_header, r, sizeof (unwind_record));
break;
default:
break;
}
}
fprintf (f, "--end unwind image--\n\n");
}

View File

@ -3117,8 +3117,7 @@ process_set (asm_out_file, pat)
if (!spill_offset_emitted)
{
fprintf (asm_out_file, "\t.spill %d\n",
/* (frame_size + 16 - spill_offset ) / 4); */
(-(spill_offset - 8) + 16) / 4);
(-(spill_offset - 8) + 16));
spill_offset_emitted = 1;
}
}
@ -3138,10 +3137,10 @@ process_set (asm_out_file, pat)
/* register 9 is ar.unat. */
if (tmp_saved == 9)
fprintf (asm_out_file, "\t.savesp ar.unat, %d\n",
(sp_offset - 8) / 4);
(sp_offset - 8));
else if (tmp_saved == 5)
fprintf (asm_out_file, "\t.savesp pr, %d\n",
(sp_offset - 8) / 4);
(sp_offset - 8));
else if (tmp_saved >= BR_REG (1) && tmp_saved <= BR_REG (5))
{
/* BR regs are saved this way too. */

View File

@ -256,12 +256,13 @@ typedef struct ia64_frame_state
typedef struct unwind_info_ptr
{
unsigned short version;
unsigned short flags;
unsigned int length;
unsigned long header; /* version, flags, & length */
unsigned char unwind_descriptors[1];
} unwind_info_ptr;
#define IA64_UNW_HDR_LENGTH(x) ((x) & 0x00000000ffffffffUL)
#define IA64_UNW_HDR_FLAGS(x) (((x) >> 32) & 0xffffUL)
#define IA64_UNW_HDR_VERSION(x) (((x) >> 48) & 0xffffUL)
extern unwind_info_ptr *__build_ia64_frame_state (unsigned char *,
ia64_frame_state *, void *,