[llvm-commits] [125638] arm EABI patch (Lauro Ramos Venancio)

johannes at apple.com johannes at apple.com
Mon Apr 2 17:13:00 PDT 2007


Revision: 125638
Author:   johannes
Date:     2007-04-02 17:13:00 -0700 (Mon, 02 Apr 2007)

Log Message:
-----------
arm EABI patch (Lauro Ramos Venancio)

Modified Paths:
--------------
    apple-local/branches/llvm/gcc/Makefile.in
    apple-local/branches/llvm/gcc/ada/misc.c
    apple-local/branches/llvm/gcc/c-decl.c
    apple-local/branches/llvm/gcc/config/arm/arm.c
    apple-local/branches/llvm/gcc/config/arm/arm.h
    apple-local/branches/llvm/gcc/config/arm/bpabi.h
    apple-local/branches/llvm/gcc/config/arm/elf.h
    apple-local/branches/llvm/gcc/config/arm/lib1funcs.asm
    apple-local/branches/llvm/gcc/config/arm/libgcc-bpabi.ver
    apple-local/branches/llvm/gcc/config/arm/t-bpabi
    apple-local/branches/llvm/gcc/config/arm/t-symbian
    apple-local/branches/llvm/gcc/config/i386/t-netware
    apple-local/branches/llvm/gcc/config/ia64/ia64.h
    apple-local/branches/llvm/gcc/cp/Make-lang.in
    apple-local/branches/llvm/gcc/cp/decl.c
    apple-local/branches/llvm/gcc/cp/except.c
    apple-local/branches/llvm/gcc/except.c
    apple-local/branches/llvm/gcc/except.h
    apple-local/branches/llvm/gcc/java/decl.c
    apple-local/branches/llvm/gcc/objc/objc-act.c
    apple-local/branches/llvm/gcc/optabs.c
    apple-local/branches/llvm/gcc/opts.c
    apple-local/branches/llvm/gcc/target-def.h
    apple-local/branches/llvm/gcc/target.h
    apple-local/branches/llvm/gcc/unwind-c.c

Modified: apple-local/branches/llvm/gcc/Makefile.in
===================================================================
--- apple-local/branches/llvm/gcc/Makefile.in	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/Makefile.in	2007-04-03 00:13:00 UTC (rev 125638)
@@ -340,10 +340,11 @@
 	 $(srcdir)/ginclude/stddef.h \
 	 $(srcdir)/ginclude/tgmath.h \
 	 $(srcdir)/ginclude/varargs.h \
-	 $(srcdir)/unwind.h \
 	 $(EXTRA_HEADERS)
 # APPLE LOCAL end radar 2872232 add tgmath.h
 
+UNWIND_H = $(srcdir)/unwind-generic.h
+
 # The GCC to use for compiling libgcc.a and crt*.o.
 # Usually the one we just built.
 # Don't use this as a dependency--use $(GCC_PASSES) or $(GCC_PARTS).
@@ -582,7 +583,7 @@
    $(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c $(srcdir)/unwind-c.c
 LIB2ADDEHSTATIC = $(LIB2ADDEH)
 LIB2ADDEHSHARED = $(LIB2ADDEH)
-LIB2ADDEHDEP = unwind.h unwind-pe.h unwind.inc unwind-dw2-fde.h unwind-dw2.h
+LIB2ADDEHDEP = $(UNWIND_H) unwind-pe.h unwind.inc unwind-dw2-fde.h unwind-dw2.h
 
 # Don't build libunwind by default.
 LIBUNWIND =
@@ -3129,7 +3130,7 @@
 # be rebuilt.
 
 # Build the include directory
-stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) xlimits.h
+stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) xlimits.h $(UNWIND_H)
 # Copy in the headers provided with gcc.
 # The sed command gets just the last file name component;
 # this is necessary because VPATH could add a dirname.
@@ -3147,6 +3148,7 @@
 	done
 	rm -f include/limits.h
 	cp xlimits.h include/limits.h
+	cp $(UNWIND_H) include/unwind.h
 	chmod a+r include/limits.h
 # Install the README
 	rm -f include/README
@@ -3772,6 +3774,7 @@
 	    $(DESTDIR)$(itoolsdatadir)/include/$$realfile ; \
 	done
 	$(INSTALL_DATA) xlimits.h $(DESTDIR)$(itoolsdatadir)/include/limits.h
+	$(INSTALL_DATA) $(UNWIND_H) $(DESTDIR)$(itoolsdatadir)/include/unwind.h
 	$(INSTALL_DATA) $(srcdir)/gsyslimits.h \
 	  $(DESTDIR)$(itoolsdatadir)/gsyslimits.h
 	$(INSTALL_DATA) macro_list $(DESTDIR)$(itoolsdatadir)/macro_list

Modified: apple-local/branches/llvm/gcc/ada/misc.c
===================================================================
--- apple-local/branches/llvm/gcc/ada/misc.c	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/ada/misc.c	2007-04-03 00:13:00 UTC (rev 125638)
@@ -478,6 +478,9 @@
   using_eh_for_cleanups ();
 
   eh_personality_libfunc = init_one_libfunc ("__gnat_eh_personality");
+  /* APPLE LOCAL begin LLVM */
+  default_init_unwind_resume_libfunc ();
+  /* APPLE LOCAL end LLVM */
   lang_eh_type_covers = gnat_eh_type_covers;
   lang_eh_runtime_type = gnat_eh_runtime_type;
 

Modified: apple-local/branches/llvm/gcc/c-decl.c
===================================================================
--- apple-local/branches/llvm/gcc/c-decl.c	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/c-decl.c	2007-04-03 00:13:00 UTC (rev 125638)
@@ -3765,6 +3765,9 @@
 		= init_one_libfunc (USING_SJLJ_EXCEPTIONS
 				    ? "__gcc_personality_sj0"
 				    : "__gcc_personality_v0");
+              /* APPLE LOCAL begin LLVM */
+	      default_init_unwind_resume_libfunc ();
+              /* APPLE LOCAL end LLVM */
 	      using_eh_for_cleanups ();
 	    }
 

Modified: apple-local/branches/llvm/gcc/config/arm/arm.c
===================================================================
--- apple-local/branches/llvm/gcc/config/arm/arm.c	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/config/arm/arm.c	2007-04-03 00:13:00 UTC (rev 125638)
@@ -171,6 +171,14 @@
 static bool arm_promote_prototypes (tree);
 static bool arm_default_short_enums (void);
 static bool arm_align_anon_bitfield (void);
+/* APPLE LOCAL begin LLVM */
+static bool arm_return_in_msb (tree);
+static bool arm_must_pass_in_stack (enum machine_mode, tree);
+#ifdef TARGET_UNWIND_INFO
+static void arm_unwind_emit (FILE *, rtx);
+static bool arm_output_ttype (rtx);
+#endif
+/* APPLE LOCAL end LLVM */
 
 static tree arm_cxx_guard_type (void);
 static bool arm_cxx_guard_mask_bit (void);
@@ -182,6 +190,9 @@
 static void arm_cxx_determine_class_data_visibility (tree);
 static bool arm_cxx_class_data_always_comdat (void);
 /* APPLE LOCAL end mainline 4.2 2006-03-01 4311680 */
+/* APPLE LOCAL begin LLVM */
+static bool arm_cxx_use_aeabi_atexit (void);
+/* APPLE LOCAL end LLVM */
 static void arm_init_libfuncs (void);
 static unsigned HOST_WIDE_INT arm_shift_truncation_mask (enum machine_mode);
 
@@ -325,6 +336,30 @@
 #define TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT arm_cxx_class_data_always_comdat
 
 /* APPLE LOCAL end mainline 4.2 2006-03-01 4311680 */
+
+/* APPLE LOCAL begin LLVM */
+#undef TARGET_CXX_USE_AEABI_ATEXIT
+#define TARGET_CXX_USE_AEABI_ATEXIT arm_cxx_use_aeabi_atexit
+
+#undef TARGET_RETURN_IN_MSB
+#define TARGET_RETURN_IN_MSB arm_return_in_msb
+
+#undef TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK arm_must_pass_in_stack
+
+#ifdef TARGET_UNWIND_INFO
+#undef TARGET_UNWIND_EMIT
+#define TARGET_UNWIND_EMIT arm_unwind_emit
+
+/* EABI unwinding tables use a different format for the typeinfo tables.  */
+#undef TARGET_ASM_TTYPE
+#define TARGET_ASM_TTYPE arm_output_ttype
+
+#undef TARGET_ARM_EABI_UNWINDER
+#define TARGET_ARM_EABI_UNWINDER true
+#endif /* TARGET_UNWIND_INFO */
+/* APPLE LOCAL end LLVM */
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Obstack for minipool constant handling.  */
@@ -2316,11 +2351,25 @@
   int unsignedp ATTRIBUTE_UNUSED;
   rtx r ATTRIBUTE_UNUSED;
 
-
   mode = TYPE_MODE (type);
   /* Promote integer types.  */
   if (INTEGRAL_TYPE_P (type))
     PROMOTE_FUNCTION_MODE (mode, unsignedp, type);
+
+  /* APPLE LOCAL begin LLVM */
+  /* Promotes small structs returned in a register to full-word size
+     for big-endian AAPCS.  */
+  if (arm_return_in_msb (type))
+    {
+      HOST_WIDE_INT size = int_size_in_bytes (type);
+      if (size % UNITS_PER_WORD != 0)
+	{
+	  size += UNITS_PER_WORD - size % UNITS_PER_WORD;
+	  mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
+	}
+    }
+  /* APPLE LOCAL end LLVM */
+
   return LIBCALL_VALUE(mode);
 }
 
@@ -4886,7 +4935,20 @@
   return GENERAL_REGS;
 }
 
+/* APPLE LOCAL begin LLVM */
+/* Values which must be returned in the most-significant end of the return
+   register.  */
 
+static bool
+arm_return_in_msb (tree valtype)
+{
+  return (TARGET_AAPCS_BASED
+          && BYTES_BIG_ENDIAN
+          && (AGGREGATE_TYPE_P (valtype)
+              || TREE_CODE (valtype) == COMPLEX_TYPE));
+}
+/* APPLE LOCAL end LLVM */
+
 /* Returns TRUE if INSN is an "LDR REG, ADDR" instruction.
    Use by the Cirrus Maverick code which has to workaround
    a hardware bug triggered by such instructions.  */
@@ -6462,6 +6524,60 @@
 			    gen_lowpart (QImode, scratch)));
     }
 }
+
+/* APPLE LOCAL begin LLVM */
+/* Return true if a type must be passed in memory. For AAPCS, small aggregates
+   (padded to the size of a word) should be passed in a register.  */
+
+static bool
+arm_must_pass_in_stack (enum machine_mode mode, tree type)
+{
+  if (TARGET_AAPCS_BASED)
+    return must_pass_in_stack_var_size (mode, type);
+  else
+    return must_pass_in_stack_var_size_or_pad (mode, type);
+}
+
+
+/* For use by FUNCTION_ARG_PADDING (MODE, TYPE).
+   Return true if an argument passed on the stack should be padded upwards,
+   i.e. if the least-significant byte has useful data.  */
+
+bool
+arm_pad_arg_upward (enum machine_mode mode, tree type)
+{
+  if (!TARGET_AAPCS_BASED)
+    return DEFAULT_FUNCTION_ARG_PADDING(mode, type);
+
+  if (type && BYTES_BIG_ENDIAN && INTEGRAL_TYPE_P (type))
+    return false;
+
+  return true;
+}
+
+
+/* Similarly, for use by BLOCK_REG_PADDING (MODE, TYPE, FIRST).
+   For non-AAPCS, return !BYTES_BIG_ENDIAN if the least significant
+   byte of the register has useful data, and return the opposite if the
+   most significant byte does.
+   For AAPCS, small aggregates and small complex types are always padded
+   upwards.  */
+
+bool
+arm_pad_reg_upward (enum machine_mode mode ATTRIBUTE_UNUSED,
+                    tree type, int first ATTRIBUTE_UNUSED)
+{
+  if (TARGET_AAPCS_BASED
+      && BYTES_BIG_ENDIAN
+      && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE)
+      && int_size_in_bytes (type) <= 4)
+    return true;
+
+  /* Otherwise, use default padding.  */
+  return !BYTES_BIG_ENDIAN;
+}
+/* APPLE LOCAL end LLVM */
+
 
 /* Print a symbolic form of X to the debug file, F.  */
 static void
@@ -12690,6 +12806,23 @@
       return;
     }
 
+  /* APPLE LOCAL begin LLVM */
+  if (ARM_EABI_UNWIND_TABLES && push)
+    {
+      fprintf (f, "\t.save\t{");
+      for (regno = 0; regno < 15; regno++)
+	{
+	  if (real_regs & (1 << regno))
+	    {
+	      if (real_regs & ((1 << regno) -1))
+		fprintf (f, ", ");
+	      asm_fprintf (f, "%r", regno);
+	    }
+	}
+      fprintf (f, "}\n");
+    }
+  /* APPLE LOCAL end LLVM */
+
   fprintf (f, "\t%s\t{", push ? "push" : "pop");
 
   /* Look at the low registers first.  */
@@ -13374,6 +13507,13 @@
 
   if (current_function_pretend_args_size)
     {
+      /* APPLE LOCAL begin LLVM */
+      /* Output unwind directive for the stack adjustment.  */
+      if (ARM_EABI_UNWIND_TABLES)
+	fprintf (f, "\t.pad #%d\n",
+		 current_function_pretend_args_size);
+      /* APPLE LOCAL end LLVM */
+
       if (cfun->machine->uses_anonymous_args)
 	{
 	  int num_pushes;
@@ -13435,6 +13575,11 @@
 
       work_register = thumb_find_work_register (live_regs_mask);
 
+      /* APPLE LOCAL begin LLVM */
+      if (ARM_EABI_UNWIND_TABLES)
+	asm_fprintf (f, "\t.pad #16\n");
+      /* APPLE LOCAL end LLVM */
+
       asm_fprintf
 	(f, "\tsub\t%r, %r, #16\t%@ Create stack backtrace structure\n",
 	 SP_REGNUM, SP_REGNUM);
@@ -14511,6 +14656,14 @@
 /* APPLE LOCAL end mainline 4.2 2006-03-01 4311680 */
 }
 
+/* APPLE LOCAL begin LLVM */
+static bool
+arm_cxx_use_aeabi_atexit (void)
+{
+  return TARGET_AAPCS_BASED;
+}
+/* APPLE LOCAL end LLVM */
+
 void
 arm_set_return_address (rtx source, rtx scratch)
 {
@@ -14624,3 +14777,290 @@
 {
   return mode == SImode ? 255 : 0;
 }
+
+
+/* APPLE LOCAL begin LLVM */
+/* Map internal gcc register numbers to DWARF2 register numbers.  */
+
+unsigned int
+arm_dbx_register_number (unsigned int regno)
+{
+  if (regno < 16)
+    return regno;
+
+  /* TODO: Legacy targets output FPA regs as registers 16-23 for backwards
+     compatibility.  The EABI defines them as registers 96-103.  */
+  if (IS_FPA_REGNUM (regno))
+    return (TARGET_AAPCS_BASED ? 96 : 16) + regno - FIRST_FPA_REGNUM;
+
+  if (IS_VFP_REGNUM (regno))
+    return 64 + regno - FIRST_VFP_REGNUM;
+
+  if (IS_IWMMXT_GR_REGNUM (regno))
+    return 104 + regno - FIRST_IWMMXT_GR_REGNUM;
+
+  if (IS_IWMMXT_REGNUM (regno))
+    return 112 + regno - FIRST_IWMMXT_REGNUM;
+
+  abort ();
+}
+
+
+#ifdef TARGET_UNWIND_INFO
+/* Emit unwind directives for a store-multiple instruction.  This should
+   only ever be generated by the function prologue code, so we expect it
+   to have a particular form.  */
+
+static void
+arm_unwind_emit_stm (FILE * asm_out_file, rtx p)
+{
+  int i;
+  HOST_WIDE_INT offset;
+  HOST_WIDE_INT nregs;
+  int reg_size;
+  unsigned reg;
+  unsigned lastreg;
+  rtx e;
+
+  /* First insn will adjust the stack pointer.  */
+  e = XVECEXP (p, 0, 0);
+  if (GET_CODE (e) != SET
+      || GET_CODE (XEXP (e, 0)) != REG
+      || REGNO (XEXP (e, 0)) != SP_REGNUM
+      || GET_CODE (XEXP (e, 1)) != PLUS)
+    abort ();
+
+  offset = -INTVAL (XEXP (XEXP (e, 1), 1));
+  nregs = XVECLEN (p, 0) - 1;
+
+  reg = REGNO (XEXP (XVECEXP (p, 0, 1), 1));
+  if (reg < 16)
+    {
+      /* The function prologue may also push pc, but not annotate it as it is
+	 never restored.  We turn this into an stack pointer adjustment.  */
+      if (nregs * 4 == offset - 4)
+	{
+	  fprintf (asm_out_file, "\t.pad #4\n");
+	  offset -= 4;
+	}
+      reg_size = 4;
+    }
+  else if (IS_VFP_REGNUM (reg))
+    {
+      /* FPA register saves use an additional word.  */
+      offset -= 4;
+      reg_size = 8;
+    }
+  else if (reg >= FIRST_FPA_REGNUM && reg <= LAST_FPA_REGNUM)
+    {
+      /* FPA registers are done differently.  */
+      asm_fprintf (asm_out_file, "\t.save %r, %lld\n", reg, nregs);
+      return;
+    }
+  else
+    /* Unknown register type.  */
+    abort ();
+
+  /* If the stack increment doesn't match the size of the saved registers,
+     something has gone horribly wrong.  */
+  if (offset != nregs * reg_size)
+    abort ();
+
+  fprintf (asm_out_file, "\t.save {");
+
+  offset = 0;
+  lastreg = 0;
+  /* The remaining insns will describe the stores.  */
+  for (i = 1; i <= nregs; i++)
+    {
+      /* Expect (set (mem <addr>) (reg)).
+         Where <addr> is (reg:SP) or (plus (reg:SP) (const_int)).  */
+      e = XVECEXP (p, 0, i);
+      if (GET_CODE (e) != SET
+	  || GET_CODE (XEXP (e, 0)) != MEM
+	  || GET_CODE (XEXP (e, 1)) != REG)
+	abort ();
+      
+      reg = REGNO (XEXP (e, 1));
+      if (reg < lastreg)
+	abort ();
+	  
+      if (i != 1)
+	fprintf (asm_out_file, ", ");
+      /* We can't use %r for vfp because we need to use the
+	 double precision register names.  */
+      if (IS_VFP_REGNUM (reg))
+	asm_fprintf (asm_out_file, "d%d", (reg - FIRST_VFP_REGNUM) / 2);
+      else
+	asm_fprintf (asm_out_file, "%r", reg);
+
+#ifdef ENABLE_CHECKING
+      /* Check that the addresses are consecutive.  */
+      e = XEXP (XEXP (e, 0), 0);
+      if (GET_CODE (e) == PLUS)
+	{
+	  offset += reg_size;
+	  if (GET_CODE (XEXP (e, 0)) != REG
+	      || REGNO (XEXP (e, 0)) != SP_REGNUM
+	      || GET_CODE (XEXP (e, 1)) != CONST_INT
+	      || offset != INTVAL (XEXP (e, 1)))
+	    abort ();
+	}
+      else if (i != 1
+	       || GET_CODE (e) != REG
+	       || REGNO (e) != SP_REGNUM)
+	abort ();
+#endif
+    }
+  fprintf (asm_out_file, "}\n");
+}
+
+/*  Emit unwind directives for a SET.  */
+
+static void
+arm_unwind_emit_set (FILE * asm_out_file, rtx p)
+{
+  rtx e0;
+  rtx e1;
+
+  e0 = XEXP (p, 0);
+  e1 = XEXP (p, 1);
+  switch (GET_CODE (e0))
+    {
+    case MEM:
+      /* Pushing a single register.  */
+      if (GET_CODE (XEXP (e0, 0)) != PRE_DEC
+	  || GET_CODE (XEXP (XEXP (e0, 0), 0)) != REG
+	  || REGNO (XEXP (XEXP (e0, 0), 0)) != SP_REGNUM)
+	abort ();
+
+      asm_fprintf (asm_out_file, "\t.save ");
+      if (IS_VFP_REGNUM (REGNO (e1)))
+	asm_fprintf(asm_out_file, "{d%d}\n",
+		    (REGNO (e1) - FIRST_VFP_REGNUM) / 2);
+      else
+	asm_fprintf(asm_out_file, "{%r}\n", REGNO (e1));
+      break;
+
+    case REG:
+      if (REGNO (e0) == SP_REGNUM)
+	{
+	  /* A stack increment.  */
+	  if (GET_CODE (e1) != PLUS
+	      || GET_CODE (XEXP (e1, 0)) != REG
+	      || REGNO (XEXP (e1, 0)) != SP_REGNUM
+	      || GET_CODE (XEXP (e1, 1)) != CONST_INT)
+	    abort ();
+
+	  asm_fprintf (asm_out_file, "\t.pad #%lld\n",
+		       -INTVAL (XEXP (e1, 1)));
+	}
+      else if (REGNO (e0) == HARD_FRAME_POINTER_REGNUM)
+	{
+	  HOST_WIDE_INT offset;
+	  unsigned reg;
+	  
+	  if (GET_CODE (e1) == PLUS)
+	    {
+	      if (GET_CODE (XEXP (e1, 0)) != REG
+		  || GET_CODE (XEXP (e1, 1)) != CONST_INT)
+		abort ();
+	      reg = REGNO (XEXP (e1, 0));
+	      offset = INTVAL (XEXP (e1, 1));
+	      asm_fprintf (asm_out_file, "\t.setfp %r, %r, #%lld\n",
+			   HARD_FRAME_POINTER_REGNUM, reg,
+			   INTVAL (XEXP (e1, 1)));
+	    }
+	  else if (GET_CODE (e1) == REG)
+	    {
+	      reg = REGNO (e1);
+	      asm_fprintf (asm_out_file, "\t.setfp %r, %r\n",
+			   HARD_FRAME_POINTER_REGNUM, reg);
+	    }
+	  else
+	    abort ();
+	}
+      else if (GET_CODE (e1) == REG && REGNO (e1) == SP_REGNUM)
+	{
+	  /* Move from sp to reg.  */
+	  asm_fprintf (asm_out_file, "\t.movsp %r\n", REGNO (e0));
+	}
+      else
+	abort ();
+      break;
+
+    default:
+      abort ();
+    }
+}
+
+
+/* Emit unwind directives for the given insn.  */
+
+static void
+arm_unwind_emit (FILE * asm_out_file, rtx insn)
+{
+  rtx pat;
+
+  if (!ARM_EABI_UNWIND_TABLES)
+    return;
+
+  if (GET_CODE (insn) == NOTE || !RTX_FRAME_RELATED_P (insn))
+    return;
+
+  pat = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
+  if (pat)
+    pat = XEXP (pat, 0);
+  else
+    pat = PATTERN (insn);
+
+  switch (GET_CODE (pat))
+    {
+    case SET:
+      arm_unwind_emit_set (asm_out_file, pat);
+      break;
+
+    case SEQUENCE:
+      /* Store multiple.  */
+      arm_unwind_emit_stm (asm_out_file, pat);
+      break;
+
+    default:
+      abort();
+    }
+}
+
+
+/* Output a reference from a function exception table to the type_info
+   object X.  The EABI specifies that the symbol should be relocated by
+   an R_ARM_TARGET2 relocation.  */
+
+static bool
+arm_output_ttype (rtx x)
+{
+  fputs ("\t.word\t", asm_out_file);
+  output_addr_const (asm_out_file, x);
+  /* Use special relocations for symbol references.  */
+  if (GET_CODE (x) != CONST_INT)
+    fputs ("(TARGET2)", asm_out_file);
+  fputc ('\n', asm_out_file);
+
+  return TRUE;
+}
+#endif /* TARGET_UNWIND_INFO */
+
+
+/* Output unwind directives for the start/end of a function.  */
+
+void
+arm_output_fn_unwind (FILE * f, bool prologue)
+{
+  if (!ARM_EABI_UNWIND_TABLES)
+    return;
+
+  if (prologue)
+    fputs ("\t.fnstart\n", f);
+  else
+    fputs ("\t.fnend\n", f);
+}
+/* APPLE LOCAL end LLVM */

Modified: apple-local/branches/llvm/gcc/config/arm/arm.h
===================================================================
--- apple-local/branches/llvm/gcc/config/arm/arm.h	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/config/arm/arm.h	2007-04-03 00:13:00 UTC (rev 125638)
@@ -609,10 +609,13 @@
       (MODE) = SImode;				\
     }
 
+/* APPLE LOCAL begin LLVM */
 #define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE)	\
-  if (GET_MODE_CLASS (MODE) == MODE_INT		\
-      && GET_MODE_SIZE (MODE) < 4)      	\
-    (MODE) = SImode;				\
+  if ((GET_MODE_CLASS (MODE) == MODE_INT		\
+       || GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT)    \
+      && GET_MODE_SIZE (MODE) < 4)                      \
+    (MODE) = SImode;				        \
+/* APPLE LOCAL end LLVM */
 
 /* Define this if most significant bit is lowest numbered
    in instructions that operate on numbered bit-fields.  */
@@ -992,8 +995,13 @@
 #define FIRST_HI_REGNUM		8
 #define LAST_HI_REGNUM		11
 
+/* APPLE LOCAL begin LLVM */
+#ifndef TARGET_UNWIND_INFO
 /* We use sjlj exceptions for backwards compatibility.  */
 #define MUST_USE_SJLJ_EXCEPTIONS 1
+#endif
+/* APPLE LOCAL end LLVM */
+
 /* We can generate DWARF2 Unwind info, even though we don't use it.  */
 #define DWARF2_UNWIND_INFO 1
 
@@ -1041,6 +1049,10 @@
 /* ARM floating pointer registers.  */
 #define FIRST_FPA_REGNUM 	16
 #define LAST_FPA_REGNUM  	23
+/* APPLE LOCAL begin LLVM */
+#define IS_FPA_REGNUM(REGNUM) \
+  (((REGNUM) >= FIRST_FPA_REGNUM) && ((REGNUM) <= LAST_FPA_REGNUM))
+/* APPLE LOCAL end LLVM */
 
 #define FIRST_IWMMXT_GR_REGNUM	43
 #define LAST_IWMMXT_GR_REGNUM	46
@@ -1073,6 +1085,10 @@
 /* VFP adds 32 + 1 more.  */
 #define FIRST_PSEUDO_REGISTER   96
 
+/* APPLE LOCAL begin LLVM */
+#define DBX_REGISTER_NUMBER(REGNO) arm_dbx_register_number (REGNO)
+/* APPLE LOCAL end LLVM */
+
 /* Value should be nonzero if functions must have frame pointers.
    Zero means the frame pointer need not be set up (and parms may be accessed
    via the stack pointer) in functions that seem suitable.
@@ -1764,6 +1780,19 @@
 #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
   arm_function_arg (&(CUM), (MODE), (TYPE), (NAMED))
 
+/* APPLE LOCAL begin LLVM */
+#define FUNCTION_ARG_PADDING(MODE, TYPE) \
+  (arm_pad_arg_upward (MODE, TYPE) ? upward : downward)
+
+#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
+  (arm_pad_reg_upward (MODE, TYPE, FIRST) ? upward : downward)
+
+/* For AAPCS, padding should never be below the argument. For other ABIs,
+ * mimic the default.  */
+#define PAD_VARARGS_DOWN \
+  ((TARGET_AAPCS_BASED) ? 0 : BYTES_BIG_ENDIAN)
+/* APPLE LOCAL end LLVM */
+
 /* Initialize a variable CUM of type CUMULATIVE_ARGS
    for a call to a function whose data type is FNTYPE.
    For a library call, FNTYPE is 0.
@@ -2128,6 +2157,17 @@
   if (!TARGET_LONG_CALLS || ! DECL_SECTION_NAME (DECL)) \
     arm_encode_call_attribute (DECL, SHORT_CALL_FLAG_CHAR)
 
+/* APPLE LOCAL begin LLVM */
+#define ARM_OUTPUT_FN_UNWIND(F, PROLOGUE) arm_output_fn_unwind (F, PROLOGUE)
+
+#ifdef TARGET_UNWIND_INFO
+#define ARM_EABI_UNWIND_TABLES \
+  ((!USING_SJLJ_EXCEPTIONS && flag_exceptions) || flag_unwind_tables)
+#else
+#define ARM_EABI_UNWIND_TABLES 0
+#endif
+/* APPLE LOCAL end LLVM */
+
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
    and check its validity for a certain class.
    We have two alternate definitions for each of them.

Modified: apple-local/branches/llvm/gcc/config/arm/bpabi.h
===================================================================
--- apple-local/branches/llvm/gcc/config/arm/bpabi.h	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/config/arm/bpabi.h	2007-04-03 00:13:00 UTC (rev 125638)
@@ -26,6 +26,11 @@
 /* Assume that AAPCS ABIs should adhere to the full BPABI.  */ 
 #define TARGET_BPABI (TARGET_AAPCS_BASED)
 
+/* APPLE LOCAL begin LLVM */
+/* BPABI targets use EABI frame unwinding tables.  */
+#define TARGET_UNWIND_INFO 1
+/* APPLE LOCAL end LLVM */
+
 /* Section 4.1 of the AAPCS requires the use of VFP format.  */
 /* APPLE LOCAL begin LLVM */
 #undef FPUTYPE_DEFAULT

Modified: apple-local/branches/llvm/gcc/config/arm/elf.h
===================================================================
--- apple-local/branches/llvm/gcc/config/arm/elf.h	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/config/arm/elf.h	2007-04-03 00:13:00 UTC (rev 125638)
@@ -77,6 +77,9 @@
       ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function");	\
       ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL));		\
       ASM_OUTPUT_LABEL(FILE, NAME);				\
+/* APPLE LOCAL begin LLVM */ \
+      ARM_OUTPUT_FN_UNWIND (FILE, TRUE);			\
+/* APPLE LOCAL end LLVM */ \
     }								\
   while (0)
 
@@ -85,6 +88,9 @@
 #define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL)		\
   do								\
     {								\
+/* APPLE LOCAL begin LLVM */ \
+      ARM_OUTPUT_FN_UNWIND (FILE, FALSE);			\
+/* APPLE LOCAL end LLVM */ \
       ARM_DECLARE_FUNCTION_SIZE (FILE, FNAME, DECL);		\
       if (!flag_inhibit_size_directive)				\
 	ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME);			\

Modified: apple-local/branches/llvm/gcc/config/arm/lib1funcs.asm
===================================================================
--- apple-local/branches/llvm/gcc/config/arm/lib1funcs.asm	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/config/arm/lib1funcs.asm	2007-04-03 00:13:00 UTC (rev 125638)
@@ -637,6 +637,9 @@
 #ifdef L_udivsi3
 
 	FUNC_START udivsi3
+/* APPLE LOCAL begin LLVM */
+       	FUNC_ALIAS aeabi_uidiv udivsi3
+/* APPLE LOCAL end LLVM */
 
 #ifdef __thumb__
 
@@ -747,6 +750,9 @@
 #ifdef L_divsi3
 
 	FUNC_START divsi3	
+/* APPLE LOCAL begin LLVM */
+        FUNC_ALIAS aeabi_idiv divsi3
+/* APPLE LOCAL end LLVM */
 
 #ifdef __thumb__
 	cmp	divisor, #0
@@ -1230,4 +1236,7 @@
 #include "ieee754-df.S"
 #include "ieee754-sf.S"
 #include "bpabi.S"
+/* APPLE LOCAL begin LLVM */
+#include "libunwind.S"
+/* APPLE LOCAL end LLVM */
 #endif /* __symbian__ */

Modified: apple-local/branches/llvm/gcc/config/arm/libgcc-bpabi.ver
===================================================================
--- apple-local/branches/llvm/gcc/config/arm/libgcc-bpabi.ver	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/config/arm/libgcc-bpabi.ver	2007-04-03 00:13:00 UTC (rev 125638)
@@ -42,6 +42,9 @@
   __aeabi_fsub
   __aeabi_i2d
   __aeabi_i2f
+#APPLE LOCAL begin LLVM
+  __aeabi_idiv
+#APPLE LOCAL end LLVM
   __aeabi_idiv0
   __aeabi_idivmod
   __aeabi_l2d
@@ -55,9 +58,32 @@
   __aeabi_lmul
   __aeabi_ui2d
   __aeabi_ui2f
+#APPLE LOCAL begin LLVM
+  __aeabi_uidiv
+#APPLE LOCAL end LLVM
   __aeabi_uidivmod
   __aeabi_uldivmod
   __aeabi_ulcmp
   __aeabi_ul2d
   __aeabi_ul2f
+#APPLE LOCAL begin LLVM
+  __aeabi_uread4
+  __aeabi_uread8
+  __aeabi_uwrite4
+  __aeabi_uwrite8
+
+  # Exception-Handling
+  # \S 7.5
+  _Unwind_Complete
+  _Unwind_VRS_Get
+  _Unwind_VRS_Set
+  _Unwind_VRS_Pop
+  # \S 9.2
+  __aeabi_unwind_cpp_pr0
+  __aeabi_unwind_cpp_pr1
+  __aeabi_unwind_cpp_pr2
+  # The libstdc++ exception-handling personality routine uses this 
+  # GNU-specific entry point.
+  __gnu_unwind_frame
+#APPLE LOCAL end LLVM
 }

Modified: apple-local/branches/llvm/gcc/config/arm/t-bpabi
===================================================================
--- apple-local/branches/llvm/gcc/config/arm/t-bpabi	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/config/arm/t-bpabi	2007-04-03 00:13:00 UTC (rev 125638)
@@ -1,9 +1,20 @@
 # Add the bpabi.S functions.
-LIB1ASMFUNCS += _aeabi_lcmp _aeabi_ulcmp _aeabi_ldivmod _aeabi_uldivmod
+#APPLE LOCAL begin LLVM
+LIB1ASMFUNCS += _aeabi_lcmp _aeabi_ulcmp _aeabi_ldivmod _aeabi_uldivmod \
+  _unwind
+#APPLE LOCAL end LLVM
 
 # Add the BPABI C functions.
-LIB2FUNCS_EXTRA = $(srcdir)/config/arm/bpabi.c
+#APPLE LOCAL begin LLVM
+LIB2FUNCS_EXTRA = $(srcdir)/config/arm/bpabi.c \
+		  $(srcdir)/config/arm/unaligned-funcs.c
 
+UNWIND_H = $(srcdir)/config/arm/unwind-arm.h
+LIB2ADDEH = $(srcdir)/config/arm/unwind-arm.c \
+  $(srcdir)/config/arm/pr-support.c $(srcdir)/unwind-c.c
+LIB2ADDEHDEP = $(UNWIND_H)
+#APPLE LOCAL end LLVM
+
 # Add the BPABI names.
 SHLIB_MAPFILES += $(srcdir)/config/arm/libgcc-bpabi.ver
 

Modified: apple-local/branches/llvm/gcc/config/arm/t-symbian
===================================================================
--- apple-local/branches/llvm/gcc/config/arm/t-symbian	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/config/arm/t-symbian	2007-04-03 00:13:00 UTC (rev 125638)
@@ -12,6 +12,13 @@
 	_truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
 	_fixsfsi _fixunssfsi
 
+#APPLE LOCAL begin LLVM
+# Include the gcc personality routine
+UNWIND_H = $(srcdir)/config/arm/unwind-arm.h
+LIB2ADDEH = $(srcdir)/unwind-c.c
+LIB2ADDEHDEP = $(UNWIND_H)
+#APPLE LOCAL end LLVM
+
 # Create a multilib for processors with VFP floating-point, and a
 # multilib for those without -- using the soft-float ABI in both
 # cases.  Symbian OS object should be compiled with interworking

Modified: apple-local/branches/llvm/gcc/config/i386/t-netware
===================================================================
--- apple-local/branches/llvm/gcc/config/i386/t-netware	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/config/i386/t-netware	2007-04-03 00:13:00 UTC (rev 125638)
@@ -6,5 +6,4 @@
 # We don't need some of GCC's own include files.
 USER_H = $(srcdir)/ginclude/stdarg.h \
          $(srcdir)/ginclude/varargs.h \
-         $(srcdir)/unwind.h \
     $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS)

Modified: apple-local/branches/llvm/gcc/config/ia64/ia64.h
===================================================================
--- apple-local/branches/llvm/gcc/config/ia64/ia64.h	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/config/ia64/ia64.h	2007-04-03 00:13:00 UTC (rev 125638)
@@ -2176,6 +2176,10 @@
 
 #define TARGET_UNWIND_INFO	1
 
+/* APPLE LOCAL begin LLVM */
+#define TARGET_UNWIND_TABLES_DEFAULT true
+/* APPLE LOCAL end LLVM */
+
 #define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 15 : INVALID_REGNUM)
 
 /* This function contains machine specific function data.  */

Modified: apple-local/branches/llvm/gcc/cp/Make-lang.in
===================================================================
--- apple-local/branches/llvm/gcc/cp/Make-lang.in	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/cp/Make-lang.in	2007-04-03 00:13:00 UTC (rev 125638)
@@ -291,8 +291,8 @@
 # APPLE LOCAL end mainline
 cp/ptree.o: cp/ptree.c $(CXX_TREE_H) $(TM_H)
 cp/rtti.o: cp/rtti.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h convert.h
-cp/except.o: cp/except.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) except.h toplev.h \
-  cp/cfns.h $(EXPR_H) libfuncs.h tree-inline.h
+cp/except.o: cp/except.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) except.h \
+  toplev.h cp/cfns.h $(EXPR_H) libfuncs.h tree-inline.h $(TARGET_H)
 cp/expr.o: cp/expr.c $(CXX_TREE_H) $(TM_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \
   except.h $(TM_P_H)
 # APPLE LOCAL begin mainline

Modified: apple-local/branches/llvm/gcc/cp/decl.c
===================================================================
--- apple-local/branches/llvm/gcc/cp/decl.c	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/cp/decl.c	2007-04-03 00:13:00 UTC (rev 125638)
@@ -5216,6 +5216,9 @@
   tree fn_type;
   tree fn_ptr_type;
   const char *name;
+  /* APPLE LOCAL begin LLVM */
+  bool use_aeabi_atexit;
+  /* APPLE LOCAL end LLVM */
 
   if (atexit_node)
     return atexit_node;
@@ -5229,6 +5232,9 @@
 	 We build up the argument types and then then function type
 	 itself.  */
 
+      /* APPLE LOCAL begin LLVM */
+      use_aeabi_atexit = targetm.cxx.use_aeabi_atexit ();
+      /* APPLE LOCAL end LLVM */
       /* First, build the pointer-to-function type for the first
 	 argument.  */
       arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
@@ -5236,12 +5242,27 @@
       fn_ptr_type = build_pointer_type (fn_type);
       /* Then, build the rest of the argument types.  */
       arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
-      arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
-      arg_types = tree_cons (NULL_TREE, fn_ptr_type, arg_types);
+      /* APPLE LOCAL begin LLVM */
+      if (use_aeabi_atexit)
+	{
+	  arg_types = tree_cons (NULL_TREE, fn_ptr_type, arg_types);
+	  arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
+	}
+      else
+	{
+	  arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
+	  arg_types = tree_cons (NULL_TREE, fn_ptr_type, arg_types);
+	}
+      /* APPLE LOCAL end LLVM */
       /* And the final __cxa_atexit type.  */
       fn_type = build_function_type (integer_type_node, arg_types);
       fn_ptr_type = build_pointer_type (fn_type);
-      name = "__cxa_atexit";
+      /* APPLE LOCAL begin LLVM */
+      if (use_aeabi_atexit)
+	name = "__aeabi_atexit";
+      else
+	name = "__cxa_atexit";
+      /* APPLE LOCAL end LLVM */
     }
   else
     {
@@ -5402,8 +5423,18 @@
       args = tree_cons (NULL_TREE,
 			build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0),
 			NULL_TREE);
-      args = tree_cons (NULL_TREE, null_pointer_node, args);
-      args = tree_cons (NULL_TREE, cleanup, args);
+      /* APPLE LOCAL begin LLVM */
+      if (targetm.cxx.use_aeabi_atexit ())
+	{
+	  args = tree_cons (NULL_TREE, cleanup, args);
+	  args = tree_cons (NULL_TREE, null_pointer_node, args);
+	}
+      else
+	{
+	  args = tree_cons (NULL_TREE, null_pointer_node, args);
+	  args = tree_cons (NULL_TREE, cleanup, args);
+	}
+      /* APPLE LOCAL end LLVM */
     }
   else
     args = tree_cons (NULL_TREE, cleanup, NULL_TREE);

Modified: apple-local/branches/llvm/gcc/cp/except.c
===================================================================
--- apple-local/branches/llvm/gcc/cp/except.c	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/cp/except.c	2007-04-03 00:13:00 UTC (rev 125638)
@@ -38,6 +38,9 @@
 #include "toplev.h"
 #include "tree-inline.h"
 #include "tree-iterator.h"
+/* APPLE LOCAL begin LLVM */
+#include "target.h"
+/* APPLE LOCAL end LLVM */
 
 static void push_eh_cleanup (tree);
 static tree prepare_eh_type (tree);
@@ -79,6 +82,12 @@
   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
 					     ? "__gxx_personality_sj0"
 					     : "__gxx_personality_v0");
+/* APPLE LOCAL begin LLVM */
+  if (targetm.arm_eabi_unwinder)
+    unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
+  else
+    default_init_unwind_resume_libfunc ();
+/* APPLE LOCAL end LLVM */
 
   lang_eh_runtime_type = build_eh_type_type;
   lang_protect_cleanup_actions = &cp_protect_cleanup_actions;

Modified: apple-local/branches/llvm/gcc/except.c
===================================================================
--- apple-local/branches/llvm/gcc/except.c	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/except.c	2007-04-03 00:13:00 UTC (rev 125638)
@@ -235,7 +235,9 @@
   int built_landing_pads;
   int last_region_number;
 
-  varray_type ttype_data;
+/* APPLE LOCAL begin LLVM */
+  VEC(tree) *ttype_data;
+/* APPLE LOCAL end LLVM */
   varray_type ehspec_data;
   varray_type action_record_data;
 
@@ -967,10 +969,14 @@
 
       n = xmalloc (sizeof (*n));
       n->t = type;
-      n->filter = VARRAY_ACTIVE_SIZE (cfun->eh->ttype_data) + 1;
+/* APPLE LOCAL begin LLVM */
+      n->filter = VEC_length (tree, cfun->eh->ttype_data) + 1;
+/* APPLE LOCAL end LLVM */
       *slot = n;
 
-      VARRAY_PUSH_TREE (cfun->eh->ttype_data, type);
+/* APPLE LOCAL begin LLVM */
+      VEC_safe_push (tree, cfun->eh->ttype_data, type);
+/* APPLE LOCAL end LLVM */
     }
 
   return n->filter;
@@ -998,12 +1004,25 @@
       n->filter = -(VARRAY_ACTIVE_SIZE (cfun->eh->ehspec_data) + 1);
       *slot = n;
 
-      /* Look up each type in the list and encode its filter
-	 value as a uleb128.  Terminate the list with 0.  */
+/* APPLE LOCAL begin LLVM */
+      /* Generate a 0 terminated list of filter values.  */
       for (; list ; list = TREE_CHAIN (list))
-	push_uleb128 (&cfun->eh->ehspec_data,
-		      add_ttypes_entry (ttypes_hash, TREE_VALUE (list)));
-      VARRAY_PUSH_UCHAR (cfun->eh->ehspec_data, 0);
+	{
+	  if (targetm.arm_eabi_unwinder)
+	    VARRAY_PUSH_TREE (cfun->eh->ehspec_data, TREE_VALUE (list));
+	  else
+	    {
+	      /* Look up each type in the list and encode its filter
+		 value as a uleb128.  */
+	      push_uleb128 (&cfun->eh->ehspec_data,
+		  add_ttypes_entry (ttypes_hash, TREE_VALUE (list)));
+	    }
+	}
+      if (targetm.arm_eabi_unwinder)
+	VARRAY_PUSH_TREE (cfun->eh->ehspec_data, NULL_TREE);
+      else
+	VARRAY_PUSH_UCHAR (cfun->eh->ehspec_data, 0);
+/* APPLE LOCAL end LLVM */
     }
 
   return n->filter;
@@ -1020,8 +1039,13 @@
   int i;
   htab_t ttypes, ehspec;
 
-  VARRAY_TREE_INIT (cfun->eh->ttype_data, 16, "ttype_data");
-  VARRAY_UCHAR_INIT (cfun->eh->ehspec_data, 64, "ehspec_data");
+/* APPLE LOCAL begin LLVM */
+  cfun->eh->ttype_data = VEC_alloc (tree, 16);
+  if (targetm.arm_eabi_unwinder)
+    VARRAY_TREE_INIT (cfun->eh->ehspec_data, 64, "ehspec_data");
+  else
+    VARRAY_UCHAR_INIT (cfun->eh->ehspec_data, 64, "ehspec_data");
+/* APPLE LOCAL end LLVM */
 
   ttypes = htab_create (31, ttypes_filter_hash, ttypes_filter_eq, free);
   ehspec = htab_create (31, ehspec_filter_hash, ehspec_filter_eq, free);
@@ -3228,6 +3252,56 @@
     readonly_data_section ();
 }
 
+
+/* APPLE LOCAL begin LLVM */
+/* Output a reference from an exception table to the type_info object TYPE.
+   TT_FORMAT and TT_FORMAT_SIZE descibe the DWARF encoding method used for
+   the value.  */
+
+static void
+output_ttype (tree type, int tt_format, int tt_format_size)
+{
+  rtx value;
+
+  if (type == NULL_TREE)
+    value = const0_rtx;
+  else
+    {
+      struct cgraph_varpool_node *node;
+
+      type = lookup_type_for_runtime (type);
+      value = expand_expr (type, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
+
+      /* Let cgraph know that the rtti decl is used.  Not all of the
+	 paths below go through assemble_integer, which would take
+	 care of this for us.  */
+      STRIP_NOPS (type);
+      if (TREE_CODE (type) == ADDR_EXPR)
+	{
+	  type = TREE_OPERAND (type, 0);
+	  if (TREE_CODE (type) == VAR_DECL)
+	    {
+	      node = cgraph_varpool_node (type);
+	      if (node)
+		cgraph_varpool_mark_needed_node (node);
+	    }
+	}
+      else if (TREE_CODE (type) != INTEGER_CST)
+	abort ();
+    }
+
+  /* Allow the target to override the type table entry format.  */
+  if (targetm.asm_out.ttype (value))
+    return;
+
+  if (tt_format == DW_EH_PE_absptr || tt_format == DW_EH_PE_aligned)
+    assemble_integer (value, tt_format_size,
+		      tt_format_size * BITS_PER_UNIT, 1);
+  else
+    dw2_asm_output_encoded_addr_rtx (tt_format, value, NULL);
+}
+/* APPLE LOCAL end LLVM */
+
 void
 output_function_exception_table (void)
 {
@@ -3263,8 +3337,10 @@
   targetm.asm_out.except_table_label (asm_out_file);
 
   /* APPLE LOCAL end mainline */
-  have_tt_data = (VARRAY_ACTIVE_SIZE (cfun->eh->ttype_data) > 0
+/*   APPLE LOCAL begin LLVM */
+  have_tt_data = (VEC_length (tree, cfun->eh->ttype_data) > 0
 		  || VARRAY_ACTIVE_SIZE (cfun->eh->ehspec_data) > 0);
+/* APPLE LOCAL end LLVM */
 
   /* Indicate the format of the @TType entries.  */
   if (! have_tt_data)
@@ -3326,7 +3402,9 @@
       after_disp = (1 + size_of_uleb128 (call_site_len)
 		    + call_site_len
 		    + VARRAY_ACTIVE_SIZE (cfun->eh->action_record_data)
-		    + (VARRAY_ACTIVE_SIZE (cfun->eh->ttype_data)
+/* APPLE LOCAL begin LLVM */
+		    + (VEC_length (tree, cfun->eh->ttype_data)
+/* APPLE LOCAL end LLVM */
 		       * tt_format_size));
 
       disp = after_disp;
@@ -3388,44 +3466,15 @@
   if (have_tt_data)
     assemble_align (tt_format_size * BITS_PER_UNIT);
 
-  i = VARRAY_ACTIVE_SIZE (cfun->eh->ttype_data);
+/* APPLE LOCAL begin LLVM */
+  i = VEC_length (tree, cfun->eh->ttype_data);
+/* APPLE LOCAL end LLVM */
   while (i-- > 0)
     {
-      tree type = VARRAY_TREE (cfun->eh->ttype_data, i);
-      rtx value;
-
-      if (type == NULL_TREE)
-	value = const0_rtx;
-      else
-	{
-	  struct cgraph_varpool_node *node;
-
-	  type = lookup_type_for_runtime (type);
-	  value = expand_expr (type, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
-
-	  /* Let cgraph know that the rtti decl is used.  Not all of the
-	     paths below go through assemble_integer, which would take
-	     care of this for us.  */
-	  STRIP_NOPS (type);
-	  if (TREE_CODE (type) == ADDR_EXPR)
-	    {
-	      type = TREE_OPERAND (type, 0);
-	      if (TREE_CODE (type) == VAR_DECL)
-		{
-	          node = cgraph_varpool_node (type);
-	          if (node)
-		    cgraph_varpool_mark_needed_node (node);
-		}
-	    }
-	  else
-	    gcc_assert (TREE_CODE (type) == INTEGER_CST);
-	}
-
-      if (tt_format == DW_EH_PE_absptr || tt_format == DW_EH_PE_aligned)
-	assemble_integer (value, tt_format_size,
-			  tt_format_size * BITS_PER_UNIT, 1);
-      else
-	dw2_asm_output_encoded_addr_rtx (tt_format, value, NULL);
+/* APPLE LOCAL begin LLVM */
+      tree type = VEC_index (tree, cfun->eh->ttype_data, i);
+      output_ttype (type, tt_format, tt_format_size);
+/* APPLE LOCAL end LLVM */
     }
 
 #ifdef HAVE_AS_LEB128
@@ -3436,10 +3485,35 @@
   /* ??? Decode and interpret the data for flag_debug_asm.  */
   n = VARRAY_ACTIVE_SIZE (cfun->eh->ehspec_data);
   for (i = 0; i < n; ++i)
-    dw2_asm_output_data (1, VARRAY_UCHAR (cfun->eh->ehspec_data, i),
-			 (i ? NULL : "Exception specification table"));
+/* APPLE LOCAL begin LLVM */
+    {
+      if (targetm.arm_eabi_unwinder)
+	{
+	  tree type = VARRAY_TREE (cfun->eh->ehspec_data, i);
+	  output_ttype (type, tt_format, tt_format_size);
+	}
+      else
+	dw2_asm_output_data (1, VARRAY_UCHAR (cfun->eh->ehspec_data, i),
+			     (i ? NULL : "Exception specification table"));
+    }
+/* APPLE LOCAL end LLVM */
 
   function_section (current_function_decl);
 }
 
+
+
+/* APPLE LOCAL begin LLVM */
+/* Initialize unwind_resume_libfunc.  */
+
+void
+default_init_unwind_resume_libfunc (void)
+{
+  /* The default c++ routines aren't actually c++ specific, so use those.  */
+  unwind_resume_libfunc =
+    init_one_libfunc ( USING_SJLJ_EXCEPTIONS ? "_Unwind_SjLj_Resume"
+					     : "_Unwind_Resume");
+}
+/* APPLE LOCAL end LLVM */
+
 #include "gt-except.h"

Modified: apple-local/branches/llvm/gcc/except.h
===================================================================
--- apple-local/branches/llvm/gcc/except.h	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/except.h	2007-04-03 00:13:00 UTC (rev 125638)
@@ -84,6 +84,9 @@
 extern int check_handled (tree, tree);
 
 extern void sjlj_emit_function_exit_after (rtx);
+/* APPLE LOCAL begin LLVM */
+extern void default_init_unwind_resume_libfunc (void);
+/* APPLE LOCAL end LLVM */
 
 extern struct eh_region *gen_eh_region_cleanup (struct eh_region *,
 						struct eh_region *);

Modified: apple-local/branches/llvm/gcc/java/decl.c
===================================================================
--- apple-local/branches/llvm/gcc/java/decl.c	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/java/decl.c	2007-04-03 00:13:00 UTC (rev 125638)
@@ -1185,6 +1185,9 @@
   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
                                              ? "__gcj_personality_sj0"
                                              : "__gcj_personality_v0");
+  /* APPLE LOCAL begin LLVM */
+  default_init_unwind_resume_libfunc ();
+  /* APPLE LOCAL end LLVM */
 
   lang_eh_runtime_type = do_nothing;
 

Modified: apple-local/branches/llvm/gcc/objc/objc-act.c
===================================================================
--- apple-local/branches/llvm/gcc/objc/objc-act.c	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/objc/objc-act.c	2007-04-03 00:13:00 UTC (rev 125638)
@@ -7063,6 +7063,9 @@
 	= init_one_libfunc (USING_SJLJ_EXCEPTIONS
 			    ? "__gnu_objc_personality_sj0"
 			    : "__gnu_objc_personality_v0");
+/* APPLE LOCAL begin LLVM */
+      default_init_unwind_resume_libfunc ();
+/* APPLE LOCAL end LLVM */
       using_eh_for_cleanups ();
       lang_eh_runtime_type = objc_eh_runtime_type;
     }

Modified: apple-local/branches/llvm/gcc/optabs.c
===================================================================
--- apple-local/branches/llvm/gcc/optabs.c	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/optabs.c	2007-04-03 00:13:00 UTC (rev 125638)
@@ -5207,9 +5207,6 @@
   memset_libfunc = init_one_libfunc ("memset");
   setbits_libfunc = init_one_libfunc ("__setbits");
 
-  unwind_resume_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
-					    ? "_Unwind_SjLj_Resume"
-					    : "_Unwind_Resume");
 #ifndef DONT_USE_BUILTIN_SETJMP
   setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
   longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");

Modified: apple-local/branches/llvm/gcc/opts.c
===================================================================
--- apple-local/branches/llvm/gcc/opts.c	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/opts.c	2007-04-03 00:13:00 UTC (rev 125638)
@@ -722,11 +722,10 @@
   target_flags = 0;
   set_target_switch ("");
 
-  /* Unwind tables are always present when a target has ABI-specified unwind
-     tables, so the default should be ON.  */
-#ifdef TARGET_UNWIND_INFO
-  flag_unwind_tables = TARGET_UNWIND_INFO;
-#endif
+/* APPLE LOCAL begin LLVM */
+  /* Some tagets have ABI-specified unwind tables.  */
+  flag_unwind_tables = targetm.unwind_tables_default;
+/* APPLE LOCAL end LLVM */
 
 #ifdef OPTIMIZATION_OPTIONS
   /* Allow default optimizations to be specified on a per-machine basis.  */

Modified: apple-local/branches/llvm/gcc/target-def.h
===================================================================
--- apple-local/branches/llvm/gcc/target-def.h	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/target-def.h	2007-04-03 00:13:00 UTC (rev 125638)
@@ -75,6 +75,12 @@
 #define TARGET_ASM_INTERNAL_LABEL default_internal_label
 #endif
 
+/* APPLE LOCAL begin LLVM */
+#ifndef TARGET_ARM_TTYPE
+#define TARGET_ASM_TTYPE hook_bool_rtx_false
+#endif
+/* APPLE LOCAL end LLVM */
+
 #ifndef TARGET_ASM_ASSEMBLE_VISIBILITY
 #define TARGET_ASM_ASSEMBLE_VISIBILITY default_assemble_visibility
 #endif
@@ -216,6 +222,9 @@
 			TARGET_ASM_EMIT_EXCEPT_TABLE_LABEL,	\
 			TARGET_UNWIND_EMIT,			\
 			TARGET_ASM_INTERNAL_LABEL,		\
+/* APPLE LOCAL begin LLVM */					\
+			TARGET_ASM_TTYPE,			\
+/* APPLE LOCAL end LLVM */					\
 			TARGET_ASM_ASSEMBLE_VISIBILITY,		\
 			TARGET_ASM_FUNCTION_PROLOGUE,		\
 			TARGET_ASM_FUNCTION_END_PROLOGUE,	\
@@ -422,6 +431,10 @@
 #endif
 /* APPLE LOCAL end mainline 2005-10-12 */
 
+/* APPLE LOCAL begin LLVM */
+#define TARGET_ARM_EABI_UNWINDER false
+/* APPLE LOCAL end LLVM */
+
 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_false
 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_false
 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_false
@@ -485,6 +498,11 @@
    }
 /* APPLE LOCAL end mainline 2005-04-14 */
 
+/* APPLE LOCAL begin LLVM */
+#ifndef TARGET_UNWIND_TABLES_DEFAULT
+#define TARGET_UNWIND_TABLES_DEFAULT false
+#endif
+/* APPLE LOCAL end LLVM */
 
 #ifndef TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME
 #define TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME 0
@@ -543,6 +561,12 @@
 #endif
  /* APPLE LOCAL begin mainline 2005-10-12 */
 
+/* APPLE LOCAL begin LLVM */
+#ifndef TARGET_CXX_USE_AEABI_ATEXIT
+#define TARGET_CXX_USE_AEABI_ATEXIT hook_bool_void_false
+#endif
+/* APPLE LOCAL end LLVM */
+
 #define TARGET_CXX				\
   {						\
     TARGET_CXX_GUARD_TYPE,			\
@@ -557,8 +581,11 @@
     TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT,        \
 /* APPLE LOCAL end mainline 4.2 2006-03-01 4311680 */ \
  /* APPLE LOCAL begin mainline 2005-10-12 */ \
-    TARGET_CXX_ADJUST_CLASS_AT_DEFINITION          \
+    TARGET_CXX_ADJUST_CLASS_AT_DEFINITION,          \
  /* APPLE LOCAL end mainline 2005-10-12 */ \
+ /* APPLE LOCAL begin LLVM */ \
+    TARGET_CXX_USE_AEABI_ATEXIT,		\
+ /* APPLE LOCAL end LLVM */ \
   }
 
 /* The whole shebang.  */
@@ -625,6 +652,9 @@
  /* APPLE LOCAL end mainline 2005-10-12 */    \
   TARGET_CALLS,					\
   TARGET_CXX,					\
+/* APPLE LOCAL begin LLVM */			\
+  TARGET_UNWIND_TABLES_DEFAULT,			\
+/* APPLE LOCAL end LLVM */			\
   TARGET_HAVE_NAMED_SECTIONS,			\
   TARGET_HAVE_CTORS_DTORS,			\
   TARGET_HAVE_TLS,				\
@@ -637,6 +667,9 @@
   TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME,	\
   TARGET_HANDLE_PRAGMA_EXTERN_PREFIX,		\
   TARGET_RELAXED_ORDERING,			\
+/* APPLE LOCAL begin LLVM */			\
+  TARGET_ARM_EABI_UNWINDER			\
+/* APPLE LOCAL end LLVM */			\
 }
 
 #include "hooks.h"

Modified: apple-local/branches/llvm/gcc/target.h
===================================================================
--- apple-local/branches/llvm/gcc/target.h	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/target.h	2007-04-03 00:13:00 UTC (rev 125638)
@@ -97,6 +97,11 @@
     /* Output an internal label.  */
     void (* internal_label) (FILE *, const char *, unsigned long);
 
+/* APPLE LOCAL begin LLVM */
+    /* Emit a ttype table reference to a typeinfo object.  */
+    bool (* ttype) (rtx);
+/* APPLE LOCAL end LLVM */
+
     /* Emit an assembler directive to set visibility for the symbol
        associated with the tree decl.  */
     void (* visibility) (tree, int);
@@ -642,8 +647,16 @@
        target modifications).  */  
     void (*adjust_class_at_definition) (tree type);
  /* APPLE LOCAL end mainline 2005-10-12 */
+    /* APPLE LOCAL begin LLVM */
+    bool (*use_aeabi_atexit) (void);
+    /* APPLE LOCAL end LLVM */
   } cxx;
 
+  /* APPLE LOCAL begin LLVM */
+  /* True if unwinding tables should be generated by default.  */
+  bool unwind_tables_default;
+  /* APPLE LOCAL end LLVM */
+
   /* Leave the boolean fields at the end.  */
 
   /* True if arbitrary sections are supported.  */
@@ -691,6 +704,13 @@
      synchronization is explicitly requested.  */
   bool relaxed_ordering;
 
+/* APPLE LOCAL begin LLVM */
+  /* Returns true if we should generate exception tables for use with the
+     ARM EABI.  The effects the encoding of function exception specifications.
+   */
+  bool arm_eabi_unwinder;
+/* APPLE LOCAL end LLVM */
+
   /* Leave the boolean fields at the end.  */
 };
 

Modified: apple-local/branches/llvm/gcc/unwind-c.c
===================================================================
--- apple-local/branches/llvm/gcc/unwind-c.c	2007-04-03 00:10:47 UTC (rev 125637)
+++ apple-local/branches/llvm/gcc/unwind-c.c	2007-04-03 00:13:00 UTC (rev 125638)
@@ -81,6 +81,22 @@
   return p;
 }
 
+/* APPLE LOCAL begin LLVM */
+#ifdef __ARM_EABI_UNWINDER__
+/* ARM EABI personality routines must also unwind the stack.  */
+#define CONTINUE_UNWINDING \
+  do								\
+    {								\
+      if (__gnu_unwind_frame (ue_header, context) != _URC_OK)	\
+	return _URC_FAILURE;					\
+      return _URC_CONTINUE_UNWIND;				\
+    }								\
+  while (0)
+#else
+#define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
+#endif
+/* APPLE LOCAL end LLVM */
+
 #ifdef __USING_SJLJ_EXCEPTIONS__
 #define PERSONALITY_FUNCTION    __gcc_personality_sj0
 #define __builtin_eh_return_data_regno(x) x
@@ -88,7 +104,19 @@
 #define PERSONALITY_FUNCTION    __gcc_personality_v0
 #endif
 
+/* APPLE LOCAL begin LLVM */
+#ifdef __ARM_EABI_UNWINDER__
 _Unwind_Reason_Code
+PERSONALITY_FUNCTION (_Unwind_State, struct _Unwind_Exception *,
+		      struct _Unwind_Context *);
+
+_Unwind_Reason_Code
+PERSONALITY_FUNCTION (_Unwind_State state,
+		      struct _Unwind_Exception * ue_header,
+		      struct _Unwind_Context * context)
+#else
+/* APPLE LOCAL end LLVM */
+_Unwind_Reason_Code
 PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class,
 		      struct _Unwind_Exception *, struct _Unwind_Context *);
 
@@ -98,24 +126,45 @@
 		      _Unwind_Exception_Class exception_class ATTRIBUTE_UNUSED,
 		      struct _Unwind_Exception *ue_header,
 		      struct _Unwind_Context *context)
+/* APPLE LOCAL begin LLVM */
+#endif
+/* APPLE LOCAL end LLVM */
 {
   lsda_header_info info;
   const unsigned char *language_specific_data, *p, *action_record;
   _Unwind_Ptr landing_pad, ip;
 
+/* APPLE LOCAL begin LLVM */
+#ifdef __ARM_EABI_UNWINDER__
+  if (state != _US_UNWIND_FRAME_STARTING)
+    CONTINUE_UNWINDING;
+
+  /* The dwarf unwinder assumes the context structure holds things like the
+     function and LSDA pointers.  The ARM implementation caches these in
+     the exception header (UCB).  To avoid rewriting everything we make the
+     virtual IP register point at the UCB.  */
+  ip = (_Unwind_Ptr) ue_header;
+  _Unwind_SetGR (context, 12, ip);
+#else
+/* APPLE LOCAL end LLVM */
   if (version != 1)
     return _URC_FATAL_PHASE1_ERROR;
 
   /* Currently we only support cleanups for C.  */
   if ((actions & _UA_CLEANUP_PHASE) == 0)
-    return _URC_CONTINUE_UNWIND;
+/* APPLE LOCAL begin LLVM */
+    CONTINUE_UNWINDING;
+#endif
+/* APPLE LOCAL end LLVM */
 
   language_specific_data = (const unsigned char *)
     _Unwind_GetLanguageSpecificData (context);
 
   /* If no LSDA, then there are no handlers or cleanups.  */
   if (! language_specific_data)
-    return _URC_CONTINUE_UNWIND;
+/* APPLE LOCAL begin LLVM */
+    CONTINUE_UNWINDING;
+/* APPLE LOCAL end LLVM */
 
   /* Parse the LSDA header.  */
   p = parse_lsda_header (context, language_specific_data, &info);
@@ -171,20 +220,23 @@
 	  goto found_something;
 	}
     }
-  
 #endif
 
   /* IP is not in table.  No associated cleanups.  */
   /* ??? This is where C++ calls std::terminate to catch throw
      from a destructor.  */
-  return _URC_CONTINUE_UNWIND;
+/* APPLE LOCAL begin LLVM */
+  CONTINUE_UNWINDING;
+/* APPLE LOCAL end LLVM */
 
  found_something:
   if (landing_pad == 0)
     {
       /* IP is present, but has a null landing pad.
 	 No handler to be run.  */
-      return _URC_CONTINUE_UNWIND;
+/* APPLE LOCAL begin LLVM */
+      CONTINUE_UNWINDING;
+/* APPLE LOCAL end LLVM */
     }
 
   _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),





More information about the llvm-commits mailing list