Commit c0240be4 by James E. Wilson Committed by Jim Wilson

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
parent 24c40136
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> 2000-06-06 Philipp Thomas <pthomas@suse.de>
* configure.in (AC_C_INLINE): Added. * configure.in (AC_C_INLINE): Added.
......
...@@ -296,38 +296,3 @@ __do_frame_setup: ...@@ -296,38 +296,3 @@ __do_frame_setup:
#endif #endif
.weak __deregister_frame_info# .weak __deregister_frame_info#
.weak __register_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#
...@@ -113,7 +113,6 @@ __do_global_ctors_aux: ...@@ -113,7 +113,6 @@ __do_global_ctors_aux:
.section .init,"ax","progbits" .section .init,"ax","progbits"
{ .mlx { .mlx
// __do_frame_setup_aux is in crtbegin.asm
movl r2 = @gprel(__do_frame_setup_aux#) movl r2 = @gprel(__do_frame_setup_aux#)
;; ;;
} }
...@@ -123,12 +122,42 @@ __do_global_ctors_aux: ...@@ -123,12 +122,42 @@ __do_global_ctors_aux:
;; ;;
mov b6 = r2 mov b6 = r2
} }
{ .mib { .bbb
// __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
br.call.sptk.many b0 = b6 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#
...@@ -247,23 +247,22 @@ bad_record (ptr, offset) ...@@ -247,23 +247,22 @@ bad_record (ptr, offset)
static unsigned char *read_R_record (unwind_record *, unsigned char, unsigned char *); 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_X_record (unwind_record *, unsigned char, unsigned char *);
static unsigned char *read_B_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 /* This routine will determine what type of record the memory pointer
is refering to, and fill in the appropriate fields for that record type. is refering to, and fill in the appropriate fields for that record type.
PROLOGUE_FLAG is TRUE if we are currently processing a PROLOGUE HEADER is a pointer to the last region header unwind record.
body.
DATA is a pointer to an unwind record which will be filled in. 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 PTR is a pointer to the current location in the unwind table where we
will read the next record from. will read the next record from.
The return value is the start of the next record. */ The return value is the start of the next record. */
extern unsigned char * extern unsigned char *
get_unwind_record (prologue_flag, data, ptr) get_unwind_record (header, data, ptr)
int prologue_flag; unwind_record *header;
unwind_record *data; unwind_record *data;
unsigned char *ptr; unsigned char *ptr;
{ {
unsigned char val = *ptr++; unsigned char val = *ptr++;
...@@ -275,8 +274,8 @@ get_unwind_record (prologue_flag, data, 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) if (val == UNW_X1 || val == UNW_X2 || val == UNW_X3 || val == UNW_X4)
return read_X_record (data, val, ptr); return read_X_record (data, val, ptr);
if (prologue_flag) if (header->type != body)
return read_P_record (data, val, ptr); return read_P_record (data, val, ptr, header);
else else
return read_B_record (data, val, ptr); return read_B_record (data, val, ptr);
} }
...@@ -534,10 +533,11 @@ static unsigned char P8_additional_fields [] = { ...@@ -534,10 +533,11 @@ static unsigned char P8_additional_fields [] = {
static unsigned char * static unsigned char *
read_P_record (data, val, ptr) read_P_record (data, val, ptr, header)
unwind_record *data; unwind_record *data;
unsigned char val; unsigned char val;
unsigned char *ptr; unsigned char *ptr;
unwind_record *header;
{ {
if ((val & 0xe0) == 0x80) if ((val & 0xe0) == 0x80)
{ {
...@@ -575,13 +575,12 @@ read_P_record (data, val, ptr) ...@@ -575,13 +575,12 @@ read_P_record (data, val, ptr)
if (val == UNW_P4) if (val == UNW_P4)
{ {
/* P4 format. Currently unimplemented. */ /* P4 format. */
int len = 0; /* TODO.. get prologue rlen. */ int size = (header->record.r.rlen * 2 + 7) / 8;
int size = (len * 2 + 7) / 8;
data->type = spill_mask; data->type = spill_mask;
data->record.p.imask = (unsigned char *) malloc (size); 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; return ptr+size;
} }
...@@ -617,7 +616,7 @@ read_P_record (data, val, ptr) ...@@ -617,7 +616,7 @@ read_P_record (data, val, ptr)
{ {
case P7_T_SIZE: case P7_T_SIZE:
data->record.p.t = read_uleb128 (&ptr); data->record.p.t = read_uleb128 (&ptr);
data->record.p.size = read_uleb128 (&ptr); data->record.p.size = read_uleb128 (&ptr) << 4;
break; break;
case P7_T: case P7_T:
data->record.p.t = read_uleb128 (&ptr); data->record.p.t = read_uleb128 (&ptr);
...@@ -733,11 +732,14 @@ execute_one_ia64_descriptor (addr, frame, len) ...@@ -733,11 +732,14 @@ execute_one_ia64_descriptor (addr, frame, len)
long *len; long *len;
{ {
unwind_record r; 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; ia64_reg_loc *loc_ptr = NULL;
int grmask = 0, frmask = 0; int grmask = 0, frmask = 0;
*len = -1; *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, /* process it in 2 phases, the first phase will either do the work,
or set up a pointer to the records we care about or set up a pointer to the records we care about
...@@ -748,6 +750,7 @@ execute_one_ia64_descriptor (addr, frame, len) ...@@ -748,6 +750,7 @@ execute_one_ia64_descriptor (addr, frame, len)
case prologue: case prologue:
case body: case body:
*len = r.record.r.rlen; *len = r.record.r.rlen;
memcpy (&region_header, &r, sizeof (unwind_record));
break; break;
case prologue_gr: case prologue_gr:
{ {
...@@ -780,6 +783,7 @@ execute_one_ia64_descriptor (addr, frame, len) ...@@ -780,6 +783,7 @@ execute_one_ia64_descriptor (addr, frame, len)
frame->pr.loc_type = IA64_UNW_LOC_TYPE_GR; frame->pr.loc_type = IA64_UNW_LOC_TYPE_GR;
frame->pr.l.regno = reg++; frame->pr.l.regno = reg++;
} }
memcpy (&region_header, &r, sizeof (unwind_record));
break; break;
} }
case mem_stack_f: case mem_stack_f:
...@@ -1312,7 +1316,7 @@ __build_ia64_frame_state (pc, frame, bsp, pc_base_ptr) ...@@ -1312,7 +1316,7 @@ __build_ia64_frame_state (pc, frame, bsp, pc_base_ptr)
start_pc = pc_base + entry->start_offset; start_pc = pc_base + entry->start_offset;
unw_info_ptr = ((struct unwind_info_ptr *)(pc_base + entry->unwind_offset)); unw_info_ptr = ((struct unwind_info_ptr *)(pc_base + entry->unwind_offset));
addr = unw_info_ptr->unwind_descriptors; 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; pc_offset = (pc - start_pc) / 16 * 3;
init_ia64_unwind_frame (frame); init_ia64_unwind_frame (frame);
...@@ -1345,7 +1349,8 @@ __get_personality (ptr) ...@@ -1345,7 +1349,8 @@ __get_personality (ptr)
unwind_info_ptr *ptr; unwind_info_ptr *ptr;
{ {
void **p; void **p;
p = (void **) (ptr->unwind_descriptors + ptr->length * 8); p = (void **) (ptr->unwind_descriptors
+ IA64_UNW_HDR_LENGTH (ptr->header) * 8);
return *p; return *p;
} }
...@@ -1354,11 +1359,13 @@ __get_except_table (ptr) ...@@ -1354,11 +1359,13 @@ __get_except_table (ptr)
unwind_info_ptr *ptr; unwind_info_ptr *ptr;
{ {
void **p, *table; 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 there is no personality, there is no handler data. */
if (*p == 0) if (*p == 0)
return 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; return table;
} }
...@@ -1595,12 +1602,23 @@ print_all_records (f, mem, size) ...@@ -1595,12 +1602,23 @@ print_all_records (f, mem, size)
{ {
unsigned char *end = mem + size; unsigned char *end = mem + size;
unwind_record r; unwind_record r;
static unwind_record region_header;
fprintf (f, "UNWIND IMAGE:\n"); fprintf (f, "UNWIND IMAGE:\n");
while (mem < end) while (mem < end)
{ {
mem = get_unwind_record (1, &r, mem); mem = get_unwind_record (&region_header, &r, mem);
print_record (f, &r); 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"); fprintf (f, "--end unwind image--\n\n");
} }
......
...@@ -3117,8 +3117,7 @@ process_set (asm_out_file, pat) ...@@ -3117,8 +3117,7 @@ process_set (asm_out_file, pat)
if (!spill_offset_emitted) if (!spill_offset_emitted)
{ {
fprintf (asm_out_file, "\t.spill %d\n", fprintf (asm_out_file, "\t.spill %d\n",
/* (frame_size + 16 - spill_offset ) / 4); */ (-(spill_offset - 8) + 16));
(-(spill_offset - 8) + 16) / 4);
spill_offset_emitted = 1; spill_offset_emitted = 1;
} }
} }
...@@ -3138,10 +3137,10 @@ process_set (asm_out_file, pat) ...@@ -3138,10 +3137,10 @@ process_set (asm_out_file, pat)
/* register 9 is ar.unat. */ /* register 9 is ar.unat. */
if (tmp_saved == 9) if (tmp_saved == 9)
fprintf (asm_out_file, "\t.savesp ar.unat, %d\n", fprintf (asm_out_file, "\t.savesp ar.unat, %d\n",
(sp_offset - 8) / 4); (sp_offset - 8));
else if (tmp_saved == 5) else if (tmp_saved == 5)
fprintf (asm_out_file, "\t.savesp pr, %d\n", 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)) else if (tmp_saved >= BR_REG (1) && tmp_saved <= BR_REG (5))
{ {
/* BR regs are saved this way too. */ /* BR regs are saved this way too. */
......
...@@ -256,12 +256,13 @@ typedef struct ia64_frame_state ...@@ -256,12 +256,13 @@ typedef struct ia64_frame_state
typedef struct unwind_info_ptr typedef struct unwind_info_ptr
{ {
unsigned short version; unsigned long header; /* version, flags, & length */
unsigned short flags;
unsigned int length;
unsigned char unwind_descriptors[1]; unsigned char unwind_descriptors[1];
} unwind_info_ptr; } 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 *, extern unwind_info_ptr *__build_ia64_frame_state (unsigned char *,
ia64_frame_state *, void *, ia64_frame_state *, void *,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment