summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwilson <wilson@138bc75d-0d04-0410-961f-82ee72b054a4>2000-06-07 02:27:51 +0000
committerwilson <wilson@138bc75d-0d04-0410-961f-82ee72b054a4>2000-06-07 02:27:51 +0000
commitdf946265e70e7333ea2175155d7cb497f827444f (patch)
tree73c8dc5478aae00eb8cc397f7cd0b011add7148d
parent13c13ccb728a7f0a0564585f9a99828b01767ec1 (diff)
downloadgcc-df946265e70e7333ea2175155d7cb497f827444f.tar.gz
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. ... git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@34441 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog20
-rw-r--r--gcc/config/ia64/crtbegin.asm35
-rw-r--r--gcc/config/ia64/crtend.asm41
-rw-r--r--gcc/config/ia64/frame-ia64.c60
-rw-r--r--gcc/config/ia64/ia64.c7
-rw-r--r--gcc/frame.h7
6 files changed, 101 insertions, 69 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a0db4b4f5d6..2f8e558fa82 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/ia64/crtbegin.asm b/gcc/config/ia64/crtbegin.asm
index 0e49e20662d..3f2b2f7080a 100644
--- a/gcc/config/ia64/crtbegin.asm
+++ b/gcc/config/ia64/crtbegin.asm
@@ -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#
diff --git a/gcc/config/ia64/crtend.asm b/gcc/config/ia64/crtend.asm
index 9216cfc7fb7..07b71ea5c10 100644
--- a/gcc/config/ia64/crtend.asm
+++ b/gcc/config/ia64/crtend.asm
@@ -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#
diff --git a/gcc/config/ia64/frame-ia64.c b/gcc/config/ia64/frame-ia64.c
index 763bc49c0bc..4ff78dd4a4d 100644
--- a/gcc/config/ia64/frame-ia64.c
+++ b/gcc/config/ia64/frame-ia64.c
@@ -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");
}
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 8328d7f9b56..e9eade30b93 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -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. */
diff --git a/gcc/frame.h b/gcc/frame.h
index 384e5eb66ca..85c5e436d5b 100644
--- a/gcc/frame.h
+++ b/gcc/frame.h
@@ -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 *,