Blame SOURCES/gcc44-pr49146.patch

f28b6a
2013-05-17  Richard Henderson  <rth@redhat.com>
f28b6a
f28b6a
	PR target/49146
f28b6a
	* unwind-dw2.c (UNWIND_COLUMN_IN_RANGE): New macro.
f28b6a
	(execute_cfa_program): Use it when storing to fs->regs.
f28b6a
f28b6a
--- gcc/unwind-dw2.c	(revision 199018)
f28b6a
+++ gcc/unwind-dw2.c	(revision 199019)
f28b6a
@@ -55,6 +55,35 @@
f28b6a
 #define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
f28b6a
 #endif
f28b6a
 
f28b6a
+/* ??? For the public function interfaces, we tend to gcc_assert that the
f28b6a
+   column numbers are in range.  For the dwarf2 unwind info this does happen,
f28b6a
+   although so far in a case that doesn't actually matter.
f28b6a
+
f28b6a
+   See PR49146, in which a call from x86_64 ms abi to x86_64 unix abi stores
f28b6a
+   the call-saved xmm registers and annotates them.  We havn't bothered
f28b6a
+   providing support for the xmm registers for the x86_64 port primarily
f28b6a
+   because the 64-bit windows targets don't use dwarf2 unwind, using sjlj or
f28b6a
+   SEH instead.  Adding the support for unix targets would generally be a
f28b6a
+   waste.  However, some runtime libraries supplied with ICC do contain such
f28b6a
+   an unorthodox transition, as well as the unwind info to match.  This loss
f28b6a
+   of register restoration doesn't matter in practice, because the exception
f28b6a
+   is caught in the native unix abi, where all of the xmm registers are 
f28b6a
+   call clobbered.
f28b6a
+
f28b6a
+   Ideally, we'd record some bit to notice when we're failing to restore some
f28b6a
+   register recorded in the unwind info, but to do that we need annotation on
f28b6a
+   the unix->ms abi edge, so that we know when the register data may be
f28b6a
+   discarded.  And since this edge is also within the ICC library, we're
f28b6a
+   unlikely to be able to get the new annotation.
f28b6a
+
f28b6a
+   Barring a magic solution to restore the ms abi defined 128-bit xmm registers
f28b6a
+   (as distictly opposed to the full runtime width) without causing extra
f28b6a
+   overhead for normal unix abis, the best solution seems to be to simply
f28b6a
+   ignore unwind data for unknown columns.  */
f28b6a
+
f28b6a
+#define UNWIND_COLUMN_IN_RANGE(x) \
f28b6a
+    __builtin_expect((x) <= DWARF_FRAME_REGISTERS, 1)
f28b6a
+
f28b6a
 /* This is the register and unwind state for a particular frame.  This
f28b6a
    provides the information necessary to unwind up past a frame and return
f28b6a
    to its caller.  */
f28b6a
@@ -897,14 +926,19 @@ execute_cfa_program (const unsigned char
f28b6a
 	  reg = insn & 0x3f;
f28b6a
 	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
f28b6a
 	  offset = (_Unwind_Sword) utmp * fs->data_align;
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
f28b6a
-	    = REG_SAVED_OFFSET;
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
f28b6a
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
f28b6a
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
f28b6a
+	    {
f28b6a
+	      fs->regs.reg[reg].how = REG_SAVED_OFFSET;
f28b6a
+	      fs->regs.reg[reg].loc.offset = offset;
f28b6a
+	    }
f28b6a
 	}
f28b6a
       else if ((insn & 0xc0) == DW_CFA_restore)
f28b6a
 	{
f28b6a
 	  reg = insn & 0x3f;
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_UNSAVED;
f28b6a
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
f28b6a
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
f28b6a
+	    fs->regs.reg[reg].how = REG_UNSAVED;
f28b6a
 	}
f28b6a
       else switch (insn)
f28b6a
 	{
f28b6a
@@ -935,26 +969,35 @@ execute_cfa_program (const unsigned char
f28b6a
 	  insn_ptr = read_uleb128 (insn_ptr, ®);
f28b6a
 	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
f28b6a
 	  offset = (_Unwind_Sword) utmp * fs->data_align;
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
f28b6a
-	    = REG_SAVED_OFFSET;
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
f28b6a
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
f28b6a
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
f28b6a
+	    {
f28b6a
+	      fs->regs.reg[reg].how = REG_SAVED_OFFSET;
f28b6a
+	      fs->regs.reg[reg].loc.offset = offset;
f28b6a
+	    }
f28b6a
 	  break;
f28b6a
 
f28b6a
 	case DW_CFA_restore_extended:
f28b6a
 	  insn_ptr = read_uleb128 (insn_ptr, ®);
f28b6a
 	  /* FIXME, this is wrong; the CIE might have said that the
f28b6a
 	     register was saved somewhere.  */
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
f28b6a
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
f28b6a
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
f28b6a
+	    fs->regs.reg[reg].how = REG_UNSAVED;
f28b6a
 	  break;
f28b6a
 
f28b6a
 	case DW_CFA_same_value:
f28b6a
 	  insn_ptr = read_uleb128 (insn_ptr, ®);
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
f28b6a
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
f28b6a
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
f28b6a
+	    fs->regs.reg[reg].how = REG_UNSAVED;
f28b6a
 	  break;
f28b6a
 
f28b6a
 	case DW_CFA_undefined:
f28b6a
 	  insn_ptr = read_uleb128 (insn_ptr, ®);
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNDEFINED;
f28b6a
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
f28b6a
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
f28b6a
+	    fs->regs.reg[reg].how = REG_UNDEFINED;
f28b6a
 	  break;
f28b6a
 
f28b6a
 	case DW_CFA_nop:
f28b6a
@@ -965,9 +1008,12 @@ execute_cfa_program (const unsigned char
f28b6a
 	    _uleb128_t reg2;
f28b6a
 	    insn_ptr = read_uleb128 (insn_ptr, ®);
f28b6a
 	    insn_ptr = read_uleb128 (insn_ptr, ®2;;
f28b6a
-	    fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_REG;
f28b6a
-	    fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.reg =
f28b6a
-	      (_Unwind_Word)reg2;
f28b6a
+	    reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
f28b6a
+	    if (UNWIND_COLUMN_IN_RANGE (reg))
f28b6a
+	      {
f28b6a
+	        fs->regs.reg[reg].how = REG_SAVED_REG;
f28b6a
+	        fs->regs.reg[reg].loc.reg = (_Unwind_Word)reg2;
f28b6a
+	      }
f28b6a
 	  }
f28b6a
 	  break;
f28b6a
 
f28b6a
@@ -1025,8 +1071,12 @@ execute_cfa_program (const unsigned char
f28b6a
 
f28b6a
 	case DW_CFA_expression:
f28b6a
 	  insn_ptr = read_uleb128 (insn_ptr, ®);
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_EXP;
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
f28b6a
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
f28b6a
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
f28b6a
+	    {
f28b6a
+	      fs->regs.reg[reg].how = REG_SAVED_EXP;
f28b6a
+	      fs->regs.reg[reg].loc.exp = insn_ptr;
f28b6a
+	    }
f28b6a
 	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
f28b6a
 	  insn_ptr += utmp;
f28b6a
 	  break;
f28b6a
@@ -1036,9 +1086,12 @@ execute_cfa_program (const unsigned char
f28b6a
 	  insn_ptr = read_uleb128 (insn_ptr, ®);
f28b6a
 	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
f28b6a
 	  offset = stmp * fs->data_align;
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
f28b6a
-	    = REG_SAVED_OFFSET;
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
f28b6a
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
f28b6a
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
f28b6a
+	    {
f28b6a
+	      fs->regs.reg[reg].how = REG_SAVED_OFFSET;
f28b6a
+	      fs->regs.reg[reg].loc.offset = offset;
f28b6a
+	    }
f28b6a
 	  break;
f28b6a
 
f28b6a
 	case DW_CFA_def_cfa_sf:
f28b6a
@@ -1061,25 +1114,34 @@ execute_cfa_program (const unsigned char
f28b6a
 	  insn_ptr = read_uleb128 (insn_ptr, ®);
f28b6a
 	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
f28b6a
 	  offset = (_Unwind_Sword) utmp * fs->data_align;
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
f28b6a
-	    = REG_SAVED_VAL_OFFSET;
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
f28b6a
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
f28b6a
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
f28b6a
+	    {
f28b6a
+	      fs->regs.reg[reg].how = REG_SAVED_VAL_OFFSET;
f28b6a
+	      fs->regs.reg[reg].loc.offset = offset;
f28b6a
+	    }
f28b6a
 	  break;
f28b6a
 
f28b6a
 	case DW_CFA_val_offset_sf:
f28b6a
 	  insn_ptr = read_uleb128 (insn_ptr, ®);
f28b6a
 	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
f28b6a
 	  offset = stmp * fs->data_align;
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
f28b6a
-	    = REG_SAVED_VAL_OFFSET;
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
f28b6a
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
f28b6a
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
f28b6a
+	    {
f28b6a
+	      fs->regs.reg[reg].how = REG_SAVED_VAL_OFFSET;
f28b6a
+	      fs->regs.reg[reg].loc.offset = offset;
f28b6a
+	    }
f28b6a
 	  break;
f28b6a
 
f28b6a
 	case DW_CFA_val_expression:
f28b6a
 	  insn_ptr = read_uleb128 (insn_ptr, ®);
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
f28b6a
-	    = REG_SAVED_VAL_EXP;
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
f28b6a
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
f28b6a
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
f28b6a
+	    {
f28b6a
+	      fs->regs.reg[reg].how = REG_SAVED_VAL_EXP;
f28b6a
+	      fs->regs.reg[reg].loc.exp = insn_ptr;
f28b6a
+	    }
f28b6a
 	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
f28b6a
 	  insn_ptr += utmp;
f28b6a
 	  break;
f28b6a
@@ -1104,9 +1166,12 @@ execute_cfa_program (const unsigned char
f28b6a
 	  insn_ptr = read_uleb128 (insn_ptr, ®);
f28b6a
 	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
f28b6a
 	  offset = (_Unwind_Word) utmp * fs->data_align;
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
f28b6a
-	    = REG_SAVED_OFFSET;
f28b6a
-	  fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = -offset;
f28b6a
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
f28b6a
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
f28b6a
+	    {
f28b6a
+	      fs->regs.reg[reg].how = REG_SAVED_OFFSET;
f28b6a
+	      fs->regs.reg[reg].loc.offset = -offset;
f28b6a
+	    }
f28b6a
 	  break;
f28b6a
 
f28b6a
 	default: