This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

IA-64 gcc unwind/EH patch, and shared library bug fix


This makes gcc consistent with the recent GNU as changes to the unwind support.
With this patch, the g++ EH testcases work with the current GNU as again,
except for g++.mike/eh50.C and g++.mike/eh51.C.

This also fixes a problem with building shared libraries.  The crt*.asm files
had an invalid call to a global function.  I fixed it by moving the function
and making it local.  This undoes a change I had suggested to fix a bug, so I
asked for a testcase for the original bug so I can check to see if I broke
anything.

2000-06-06  James E. Wilson  <wilson@bletchleypark.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.

Index: frame.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/frame.h,v
retrieving revision 1.12
diff -p -r1.12 frame.h
*** frame.h	2000/05/25 15:21:50	1.12
--- frame.h	2000/06/07 02:23:49
*************** typedef struct ia64_frame_state
*** 256,267 ****
  
  typedef struct unwind_info_ptr 
  {
!   unsigned short version;
!   unsigned short flags;
!   unsigned int length;
    unsigned char unwind_descriptors[1];
  } unwind_info_ptr;
  
  
  extern unwind_info_ptr *__build_ia64_frame_state (unsigned char *, 
  						  ia64_frame_state *, void *,
--- 256,268 ----
  
  typedef struct unwind_info_ptr 
  {
!   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 *,
Index: config/ia64/crtbegin.asm
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/crtbegin.asm,v
retrieving revision 1.4
diff -p -r1.4 crtbegin.asm
*** crtbegin.asm	2000/05/25 15:21:50	1.4
--- crtbegin.asm	2000/06/07 02:23:50
*************** __do_frame_setup:
*** 296,333 ****
  #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#
--- 296,298 ----
Index: config/ia64/crtend.asm
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/crtend.asm,v
retrieving revision 1.4
diff -p -r1.4 crtend.asm
*** crtend.asm	2000/05/25 15:21:50	1.4
--- crtend.asm	2000/06/07 02:23:50
*************** __do_global_ctors_aux:
*** 113,119 ****
  
  .section .init,"ax","progbits"
  	{ .mlx
- 	  // __do_frame_setup_aux is in crtbegin.asm
  	  movl r2 = @gprel(__do_frame_setup_aux#)
  	  ;;
  	}
--- 113,118 ----
*************** __do_global_ctors_aux:
*** 123,134 ****
  	  ;;
  	  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
  	  br.call.sptk.many b0 = b6
  	  ;;
          }
  
--- 122,163 ----
  	  ;;
  	  mov b6 = r2
  	}
! 	{ .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#
Index: config/ia64/frame-ia64.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/frame-ia64.c,v
retrieving revision 1.1
diff -p -r1.1 frame-ia64.c
*** frame-ia64.c	2000/05/25 15:21:51	1.1
--- frame-ia64.c	2000/06/07 02:23:50
*************** bad_record (ptr, offset)
*** 247,269 ****
  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 *);
  
  
  /* 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. 
     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;
  {
    unsigned char val = *ptr++;
  
--- 247,268 ----
  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 *, 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. 
!    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 (header, data, ptr)
!      unwind_record *header;
!      unwind_record *data;
!      unsigned char *ptr;
  {
    unsigned char val = *ptr++;
  
*************** get_unwind_record (prologue_flag, data, 
*** 275,282 ****
    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);
    else
      return read_B_record (data, val, ptr);
  }
--- 274,281 ----
    if (val == UNW_X1 || val == UNW_X2 || val == UNW_X3 || val == UNW_X4)
      return read_X_record (data, val, ptr);
  
!   if (header->type != body)
!     return read_P_record (data, val, ptr, header);
    else
      return read_B_record (data, val, ptr);
  }
*************** static unsigned char P8_additional_field
*** 534,543 ****
  
  
  static unsigned char *
! read_P_record (data, val, ptr)
       unwind_record *data;
       unsigned char val;
       unsigned char *ptr;
  {
    if ((val & 0xe0) == 0x80)
      {
--- 533,543 ----
  
  
  static unsigned char *
! read_P_record (data, val, ptr, header)
       unwind_record *data;
       unsigned char val;
       unsigned char *ptr;
+      unwind_record *header;
  {
    if ((val & 0xe0) == 0x80)
      {
*************** read_P_record (data, val, ptr)
*** 575,587 ****
  
    if (val == UNW_P4)
      {
!       /* P4 format.  Currently unimplemented.  */
!       int len = 0;  /* TODO.. get prologue rlen. */
!       int size = (len * 2 + 7) / 8;
  
        data->type = spill_mask;
        data->record.p.imask = (unsigned char *) malloc (size);
!       /* memcpy (data->record.p.imask, ptr, size);  */
        return ptr+size;
      }
  
--- 575,586 ----
  
    if (val == UNW_P4)
      {
!       /* 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);
        return ptr+size;
      }
  
*************** read_P_record (data, val, ptr)
*** 617,623 ****
          {
  	  case P7_T_SIZE:
  	    data->record.p.t = read_uleb128 (&ptr);
! 	    data->record.p.size = read_uleb128 (&ptr);
  	    break;
  	  case P7_T:
  	    data->record.p.t = read_uleb128 (&ptr);
--- 616,622 ----
          {
  	  case P7_T_SIZE:
  	    data->record.p.t = read_uleb128 (&ptr);
! 	    data->record.p.size = read_uleb128 (&ptr) << 4;
  	    break;
  	  case P7_T:
  	    data->record.p.t = read_uleb128 (&ptr);
*************** execute_one_ia64_descriptor (addr, frame
*** 733,743 ****
       long *len;
  {
    unwind_record r;
    ia64_reg_loc *loc_ptr = NULL;
    int grmask = 0, frmask = 0;
  
    *len = -1;
!   addr = get_unwind_record (1, &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 
--- 732,745 ----
       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 (&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 
*************** execute_one_ia64_descriptor (addr, frame
*** 748,753 ****
--- 750,756 ----
        case prologue:
        case body:
  	*len = r.record.r.rlen;
+ 	memcpy (&region_header, &r, sizeof (unwind_record));
  	break;
        case prologue_gr:
          {
*************** execute_one_ia64_descriptor (addr, frame
*** 780,785 ****
--- 783,789 ----
  	      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:
*************** __build_ia64_frame_state (pc, frame, bsp
*** 1312,1318 ****
    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;
    pc_offset = (pc - start_pc) / 16 * 3;
  
    init_ia64_unwind_frame (frame);
--- 1316,1322 ----
    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 + IA64_UNW_HDR_LENGTH (unw_info_ptr->header) * 8;
    pc_offset = (pc - start_pc) / 16 * 3;
  
    init_ia64_unwind_frame (frame);
*************** __get_personality (ptr)
*** 1345,1351 ****
       unwind_info_ptr *ptr;
  {
    void **p;
!   p = (void **) (ptr->unwind_descriptors + ptr->length * 8);
    return *p;
  }
  
--- 1349,1356 ----
       unwind_info_ptr *ptr;
  {
    void **p;
!   p = (void **) (ptr->unwind_descriptors
! 		 + IA64_UNW_HDR_LENGTH (ptr->header) * 8);
    return *p;
  }
  
*************** __get_except_table (ptr)
*** 1354,1364 ****
       unwind_info_ptr *ptr;
  {
    void **p, *table;
!   p = (void **) (ptr->unwind_descriptors + ptr->length * 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);
    return table;
  }
  
--- 1359,1371 ----
       unwind_info_ptr *ptr;
  {
    void **p, *table;
!   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
! 		    + IA64_UNW_HDR_LENGTH (ptr->header) * 8 + 8);
    return table;
  }
  
*************** print_all_records (f, mem, size)
*** 1595,1606 ****
  {
    unsigned char *end = mem + size;
    unwind_record r;
  
    fprintf (f, "UNWIND IMAGE:\n");
    while (mem < end) 
      {
!       mem = get_unwind_record (1, &r, mem);
        print_record (f, &r);
      }
    fprintf (f, "--end unwind image--\n\n");
  }
--- 1602,1624 ----
  {
    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 (&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");
  }
Index: config/ia64/ia64.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64.c,v
retrieving revision 1.20
diff -p -r1.20 ia64.c
*** ia64.c	2000/06/01 00:14:13	1.20
--- ia64.c	2000/06/07 02:23:50
*************** process_set (asm_out_file, pat)
*** 3117,3124 ****
  	      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_emitted = 1;
  		}
  	    }
--- 3117,3123 ----
  	      if (!spill_offset_emitted)
  	        {
  		  fprintf (asm_out_file, "\t.spill %d\n",
! 			   (-(spill_offset - 8) + 16));
  		  spill_offset_emitted = 1;
  		}
  	    }
*************** process_set (asm_out_file, pat)
*** 3138,3147 ****
  		  /* register 9 is ar.unat.  */
  		  if (tmp_saved == 9)
  		    fprintf (asm_out_file, "\t.savesp ar.unat, %d\n",
! 			     (sp_offset - 8) / 4);
  		  else if (tmp_saved == 5)
  		    fprintf (asm_out_file, "\t.savesp pr, %d\n",
! 			     (sp_offset - 8) / 4);
  		  else if (tmp_saved >= BR_REG (1) && tmp_saved <= BR_REG (5))
  		    {
  		      /* BR regs are saved this way too.  */
--- 3137,3146 ----
  		  /* register 9 is ar.unat.  */
  		  if (tmp_saved == 9)
  		    fprintf (asm_out_file, "\t.savesp ar.unat, %d\n",
! 			     (sp_offset - 8));
  		  else if (tmp_saved == 5)
  		    fprintf (asm_out_file, "\t.savesp pr, %d\n",
! 			     (sp_offset - 8));
  		  else if (tmp_saved >= BR_REG (1) && tmp_saved <= BR_REG (5))
  		    {
  		      /* BR regs are saved this way too.  */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]