OSDN Git Service

* config/rs6000/rs6000.c (rs6000_va_arg): Replace SPLIT_COMPLEX_ARGS
[pf3gnuchains/gcc-fork.git] / gcc / stmt.c
index e2b36b1..b0cd4fa 100644 (file)
@@ -1,6 +1,6 @@
 /* Expands front end tree to back end RTL for GCC
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -57,11 +57,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "langhooks.h"
 #include "predict.h"
 #include "optabs.h"
-
-/* Assume that case vectors are not pc-relative.  */
-#ifndef CASE_VECTOR_PC_RELATIVE
-#define CASE_VECTOR_PC_RELATIVE 0
-#endif
+#include "target.h"
+#include "regs.h"
 \f
 /* Functions and data structures for expanding case statements.  */
 
@@ -223,8 +220,7 @@ struct nesting GTY(())
             conditional branch points.  */
          rtx last_unconditional_cleanup;
        } GTY ((tag ("BLOCK_NESTING"))) block;
-      /* For switch (C) or case (Pascal) statements,
-        and also for dummies (see `expand_start_case_dummy').  */
+      /* For switch (C) or case (Pascal) statements.  */
       struct nesting_case
        {
          /* The insn after which the case dispatch should finally
@@ -252,8 +248,7 @@ struct nesting GTY(())
 
 /* Allocate and return a new `struct nesting'.  */
 
-#define ALLOC_NESTING() \
- (struct nesting *) ggc_alloc (sizeof (struct nesting))
+#define ALLOC_NESTING() ggc_alloc (sizeof (struct nesting))
 
 /* Pop the nesting stack element by element until we pop off
    the element which is at the top of STACK.
@@ -361,6 +356,7 @@ struct stmt_status GTY(())
      record the expr's type and its RTL value here.  */
   tree x_last_expr_type;
   rtx x_last_expr_value;
+  rtx x_last_expr_alt_rtl;
 
   /* Nonzero if within a ({...}) grouping, in which case we must
      always compute a value for each expr-stmt in case it is the last one.  */
@@ -383,6 +379,7 @@ struct stmt_status GTY(())
 #define current_block_start_count (cfun->stmt->x_block_start_count)
 #define last_expr_type (cfun->stmt->x_last_expr_type)
 #define last_expr_value (cfun->stmt->x_last_expr_value)
+#define last_expr_alt_rtl (cfun->stmt->x_last_expr_alt_rtl)
 #define expr_stmts_for_value (cfun->stmt->x_expr_stmts_for_value)
 #define emit_locus (cfun->stmt->x_emit_locus)
 #define goto_fixup_chain (cfun->stmt->x_goto_fixup_chain)
@@ -391,8 +388,6 @@ struct stmt_status GTY(())
 static int using_eh_for_cleanups_p = 0;
 
 static int n_occurrences (int, const char *);
-static bool parse_input_constraint (const char **, int, int, int, int,
-                                   const char * const *, bool *, bool *);
 static bool decl_conflicts_with_clobbers_p (tree, const HARD_REG_SET);
 static void expand_goto_internal (tree, rtx, rtx);
 static int expand_fixup (tree, rtx, rtx);
@@ -405,6 +400,7 @@ static bool check_unique_operand_names (tree, tree);
 static char *resolve_operand_name_1 (char *, tree, tree);
 static void expand_null_return_1 (rtx);
 static enum br_predictor return_prediction (rtx);
+static rtx shift_return_value (rtx);
 static void expand_value_return (rtx);
 static int tail_recursion_args (tree, tree);
 static void expand_cleanups (tree, int, int);
@@ -434,25 +430,7 @@ using_eh_for_cleanups (void)
 void
 init_stmt_for_function (void)
 {
-  cfun->stmt = ((struct stmt_status *)ggc_alloc (sizeof (struct stmt_status)));
-
-  /* We are not currently within any block, conditional, loop or case.  */
-  block_stack = 0;
-  stack_block_stack = 0;
-  loop_stack = 0;
-  case_stack = 0;
-  cond_stack = 0;
-  nesting_stack = 0;
-  nesting_depth = 0;
-
-  current_block_start_count = 0;
-
-  /* No gotos have been expanded yet.  */
-  goto_fixup_chain = 0;
-
-  /* We are not processing a ({...}) grouping.  */
-  expr_stmts_for_value = 0;
-  clear_last_expr ();
+  cfun->stmt = ggc_alloc_cleared (sizeof (struct stmt_status));
 }
 \f
 /* Record the current file and line.  Called from emit_line_note.  */
@@ -538,10 +516,7 @@ expand_computed_goto (tree exp)
 {
   rtx x = expand_expr (exp, NULL_RTX, VOIDmode, 0);
 
-#ifdef POINTERS_EXTEND_UNSIGNED
-  if (GET_MODE (x) != Pmode)
-    x = convert_memory_address (Pmode, x);
-#endif
+  x = convert_memory_address (Pmode, x);
 
   emit_queue ();
 
@@ -549,9 +524,9 @@ expand_computed_goto (tree exp)
     {
       cfun->computed_goto_common_reg = copy_to_mode_reg (Pmode, x);
       cfun->computed_goto_common_label = gen_label_rtx ();
-      emit_label (cfun->computed_goto_common_label);
 
       do_pending_stack_adjust ();
+      emit_label (cfun->computed_goto_common_label);
       emit_indirect_jump (cfun->computed_goto_common_reg);
 
       current_function_has_computed_jump = 1;
@@ -588,7 +563,7 @@ expand_label (tree label)
 
   if (stack_block_stack != 0)
     {
-      p = (struct label_chain *) ggc_alloc (sizeof (struct label_chain));
+      p = ggc_alloc (sizeof (struct label_chain));
       p->next = stack_block_stack->data.block.label_chain;
       stack_block_stack->data.block.label_chain = p;
       p->label = label;
@@ -669,6 +644,13 @@ expand_goto (tree label)
       else
 #endif
        {
+         emit_insn (gen_rtx_CLOBBER (VOIDmode,
+                                     gen_rtx_MEM (BLKmode,
+                                                  gen_rtx_SCRATCH (VOIDmode))));
+         emit_insn (gen_rtx_CLOBBER (VOIDmode,
+                                     gen_rtx_MEM (BLKmode,
+                                                  hard_frame_pointer_rtx)));
+
          /* Restore frame pointer for containing function.
             This sets the actual hard register used for the frame pointer
             to the location of the function's incoming static chain info.
@@ -851,8 +833,7 @@ expand_fixup (tree tree_label, rtx rtl_label, rtx last_insn)
   if (block != end_block)
     {
       /* Ok, a fixup is needed.  Add a fixup to the list of such.  */
-      struct goto_fixup *fixup
-       = (struct goto_fixup *) ggc_alloc (sizeof (struct goto_fixup));
+      struct goto_fixup *fixup = ggc_alloc (sizeof (struct goto_fixup));
       /* In case an old stack level is restored, make sure that comes
         after any pending stack adjust.  */
       /* ?? If the fixup isn't to come at the present position,
@@ -988,8 +969,8 @@ fixup_gotos (struct nesting *thisblock, rtx stack_level,
              && INSN_UID (first_insn) > INSN_UID (f->before_jump)
              && ! DECL_ERROR_ISSUED (f->target))
            {
-             error_with_decl (f->target,
-                              "label `%s' used before containing binding contour");
+             error ("%Jlabel '%D' used before containing binding contour",
+                    f->target, f->target);
              /* Prevent multiple errors for one label.  */
              DECL_ERROR_ISSUED (f->target) = 1;
            }
@@ -1270,12 +1251,15 @@ parse_output_constraint (const char **constraint_p, int operand_num,
        break;
       }
 
+  if (*is_inout && !*allows_reg)
+    warning ("read-write constraint does not allow a register");
+
   return true;
 }
 
 /* Similar, but for input constraints.  */
 
-static bool
+bool
 parse_input_constraint (const char **constraint_p, int input_num,
                        int ninputs, int noutputs, int ninout,
                        const char * const * constraints,
@@ -1285,6 +1269,7 @@ parse_input_constraint (const char **constraint_p, int input_num,
   const char *orig_constraint = constraint;
   size_t c_len = strlen (constraint);
   size_t j;
+  bool saw_match = false;
 
   /* Assume the constraint doesn't allow the use of either
      a register or memory.  */
@@ -1336,6 +1321,8 @@ parse_input_constraint (const char **constraint_p, int input_num,
          char *end;
          unsigned long match;
 
+         saw_match = true;
+
          match = strtoul (constraint + j, &end, 10);
          if (match >= (unsigned long) noutputs)
            {
@@ -1400,6 +1387,9 @@ parse_input_constraint (const char **constraint_p, int input_num,
        break;
       }
 
+  if (saw_match && !*allows_reg)
+    warning ("matching constraint does not allow a register");
+
   return true;
 }
 
@@ -1422,7 +1412,7 @@ decl_conflicts_with_clobbers_p (tree decl, const HARD_REG_SET clobbered_regs)
 
       for (regno = REGNO (reg);
           regno < (REGNO (reg)
-                   + HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg)));
+                   + hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]);
           regno++)
        if (TEST_HARD_REG_BIT (clobbered_regs, regno))
          {
@@ -1457,7 +1447,7 @@ decl_conflicts_with_clobbers_p (tree decl, const HARD_REG_SET clobbered_regs)
 
 void
 expand_asm_operands (tree string, tree outputs, tree inputs,
-                    tree clobbers, int vol, const char *filename, int line)
+                    tree clobbers, int vol, location_t locus)
 {
   rtvec argvec, constraintvec;
   rtx body;
@@ -1471,13 +1461,13 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
   tree t;
   int i;
   /* Vector of RTX's of evaluated output operands.  */
-  rtx *output_rtx = (rtx *) alloca (noutputs * sizeof (rtx));
-  int *inout_opnum = (int *) alloca (noutputs * sizeof (int));
-  rtx *real_output_rtx = (rtx *) alloca (noutputs * sizeof (rtx));
+  rtx *output_rtx = alloca (noutputs * sizeof (rtx));
+  int *inout_opnum = alloca (noutputs * sizeof (int));
+  rtx *real_output_rtx = alloca (noutputs * sizeof (rtx));
   enum machine_mode *inout_mode
-    = (enum machine_mode *) alloca (noutputs * sizeof (enum machine_mode));
+    = alloca (noutputs * sizeof (enum machine_mode));
   const char **constraints
-    = (const char **) alloca ((noutputs + ninputs) * sizeof (const char *));
+    = alloca ((noutputs + ninputs) * sizeof (const char *));
   int old_generating_concat_p = generating_concat_p;
 
   /* An ASM with no outputs needs to be treated as volatile, for now.  */
@@ -1487,9 +1477,6 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
   if (! check_operand_nalternatives (outputs, inputs))
     return;
 
-  if (! check_unique_operand_names (outputs, inputs))
-    return;
-
   string = resolve_asm_operand_names (string, outputs, inputs);
 
   /* Collect constraints.  */
@@ -1499,13 +1486,11 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
   for (t = inputs; t ; t = TREE_CHAIN (t), i++)
     constraints[i] = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
 
-#ifdef MD_ASM_CLOBBERS
   /* Sometimes we wish to automatically clobber registers across an asm.
      Case in point is when the i386 backend moved from cc0 to a hard reg --
      maintaining source-level compatibility means automatically clobbering
      the flags register.  */
-  MD_ASM_CLOBBERS (clobbers);
-#endif
+  clobbers = targetm.md_asm_clobbers (clobbers);
 
   /* Count the number of meaningful clobbered registers, ignoring what
      we would ignore later.  */
@@ -1678,7 +1663,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
                                : GET_MODE (output_rtx[0])),
                               TREE_STRING_POINTER (string),
                               empty_string, 0, argvec, constraintvec,
-                              filename, line);
+                              locus.file, locus.line);
 
   MEM_VOLATILE_P (body) = vol;
 
@@ -1731,13 +1716,16 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
 
              if (CONSTANT_P (op))
                {
-                 op = force_const_mem (TYPE_MODE (type), op);
-                 op = validize_mem (op);
+                 rtx mem = force_const_mem (TYPE_MODE (type), op);
+                 if (mem)
+                   op = validize_mem (mem);
+                 else
+                   op = force_reg (TYPE_MODE (type), op);
                }
-             else if (GET_CODE (op) == REG
-                      || GET_CODE (op) == SUBREG
-                      || GET_CODE (op) == ADDRESSOF
-                      || GET_CODE (op) == CONCAT)
+             if (GET_CODE (op) == REG
+                 || GET_CODE (op) == SUBREG
+                 || GET_CODE (op) == ADDRESSOF
+                 || GET_CODE (op) == CONCAT)
                {
                  tree qual_type = build_qualified_type (type,
                                                         (TYPE_QUALS (type)
@@ -1825,7 +1813,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
                           (GET_MODE (output_rtx[i]),
                            TREE_STRING_POINTER (string),
                            constraints[i], i, argvec, constraintvec,
-                           filename, line));
+                           locus.file, locus.line));
 
          MEM_VOLATILE_P (SET_SRC (XVECEXP (body, 0, i))) = vol;
        }
@@ -1994,13 +1982,16 @@ resolve_asm_operand_names (tree string, tree outputs, tree inputs)
 {
   char *buffer;
   char *p;
+  const char *c;
   tree t;
 
+  check_unique_operand_names (outputs, inputs);
+
   /* Substitute [<name>] in input constraint strings.  There should be no
      named operands in output constraints.  */
   for (t = inputs; t ; t = TREE_CHAIN (t))
     {
-      const char *c = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
+      c = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
       if (strchr (c, '[') != NULL)
        {
          p = buffer = xstrdup (c);
@@ -2012,31 +2003,48 @@ resolve_asm_operand_names (tree string, tree outputs, tree inputs)
        }
     }
 
-  if (strchr (TREE_STRING_POINTER (string), '[') == NULL)
-    return string;
-
-  /* Assume that we will not need extra space to perform the substitution.
-     This because we get to remove '[' and ']', which means we cannot have
-     a problem until we have more than 999 operands.  */
-
-  p = buffer = xstrdup (TREE_STRING_POINTER (string));
-  while ((p = strchr (p, '%')) != NULL)
+  /* Now check for any needed substitutions in the template.  */
+  c = TREE_STRING_POINTER (string);
+  while ((c = strchr (c, '%')) != NULL)
     {
-      if (p[1] == '[')
-       p += 1;
-      else if (ISALPHA (p[1]) && p[2] == '[')
-       p += 2;
+      if (c[1] == '[')
+       break;
+      else if (ISALPHA (c[1]) && c[2] == '[')
+       break;
       else
        {
-         p += 1;
+         c += 1;
          continue;
        }
-
-      p = resolve_operand_name_1 (p, outputs, inputs);
     }
 
-  string = build_string (strlen (buffer), buffer);
-  free (buffer);
+  if (c)
+    {
+      /* OK, we need to make a copy so we can perform the substitutions.
+        Assume that we will not need extra space--we get to remove '['
+        and ']', which means we cannot have a problem until we have more
+        than 999 operands.  */
+      buffer = xstrdup (TREE_STRING_POINTER (string));
+      p = buffer + (c - TREE_STRING_POINTER (string));
+      
+      while ((p = strchr (p, '%')) != NULL)
+       {
+         if (p[1] == '[')
+           p += 1;
+         else if (ISALPHA (p[1]) && p[2] == '[')
+           p += 2;
+         else
+           {
+             p += 1;
+             continue;
+           }
+
+         p = resolve_operand_name_1 (p, outputs, inputs);
+       }
+
+      string = build_string (strlen (buffer), buffer);
+      free (buffer);
+    }
 
   return string;
 }
@@ -2127,6 +2135,7 @@ expand_expr_stmt_value (tree exp, int want_value, int maybe_last)
 {
   rtx value;
   tree type;
+  rtx alt_rtl = NULL;
 
   if (want_value == -1)
     want_value = expr_stmts_for_value != 0;
@@ -2136,17 +2145,13 @@ expand_expr_stmt_value (tree exp, int want_value, int maybe_last)
      except for last statement in ({...}) where they may be useful.  */
   if (! want_value
       && (expr_stmts_for_value == 0 || ! maybe_last)
-      && exp != error_mark_node)
+      && exp != error_mark_node
+      && warn_unused_value)
     {
-      if (! TREE_SIDE_EFFECTS (exp))
-       {
-         if (warn_unused_value
-             && !(TREE_CODE (exp) == CONVERT_EXPR
-                  && VOID_TYPE_P (TREE_TYPE (exp))))
-           warning ("%Hstatement with no effect", &emit_locus);
-       }
-      else if (warn_unused_value)
+      if (TREE_SIDE_EFFECTS (exp))
        warn_if_unused_value (exp);
+      else if (!VOID_TYPE_P (TREE_TYPE (exp)))
+       warning ("%Hstatement with no effect", &emit_locus);
     }
 
   /* If EXP is of function type and we are expanding statements for
@@ -2157,8 +2162,8 @@ expand_expr_stmt_value (tree exp, int want_value, int maybe_last)
   /* The call to `expand_expr' could cause last_expr_type and
      last_expr_value to get reset.  Therefore, we set last_expr_value
      and last_expr_type *after* calling expand_expr.  */
-  value = expand_expr (exp, want_value ? NULL_RTX : const0_rtx,
-                      VOIDmode, 0);
+  value = expand_expr_real (exp, want_value ? NULL_RTX : const0_rtx,
+                           VOIDmode, 0, &alt_rtl);
   type = TREE_TYPE (exp);
 
   /* If all we do is reference a volatile value in memory,
@@ -2194,6 +2199,7 @@ expand_expr_stmt_value (tree exp, int want_value, int maybe_last)
   if (want_value)
     {
       last_expr_value = value;
+      last_expr_alt_rtl = alt_rtl;
       last_expr_type = type;
     }
 
@@ -2225,7 +2231,6 @@ warn_if_unused_value (tree exp)
     case INIT_EXPR:
     case TARGET_EXPR:
     case CALL_EXPR:
-    case METHOD_CALL_EXPR:
     case RTL_EXPR:
     case TRY_CATCH_EXPR:
     case WITH_CLEANUP_EXPR:
@@ -2314,6 +2319,7 @@ clear_last_expr (void)
 {
   last_expr_type = NULL_TREE;
   last_expr_value = NULL_RTX;
+  last_expr_alt_rtl = NULL_RTX;
 }
 
 /* Begin a statement-expression, i.e., a series of statements which
@@ -2361,6 +2367,7 @@ expand_end_stmt_expr (tree t)
   if (! last_expr_value || ! last_expr_type)
     {
       last_expr_value = const0_rtx;
+      last_expr_alt_rtl = NULL_RTX;
       last_expr_type = void_type_node;
     }
   else if (GET_CODE (last_expr_value) != REG && ! CONSTANT_P (last_expr_value))
@@ -2371,6 +2378,7 @@ expand_end_stmt_expr (tree t)
 
   TREE_TYPE (t) = last_expr_type;
   RTL_EXPR_RTL (t) = last_expr_value;
+  RTL_EXPR_ALT_RTL (t) = last_expr_alt_rtl;
   RTL_EXPR_SEQUENCE (t) = get_insns ();
 
   rtl_expr_chain = tree_cons (NULL_TREE, t, rtl_expr_chain);
@@ -2886,6 +2894,26 @@ expand_null_return (void)
   expand_null_return_1 (last_insn);
 }
 
+/* Generate RTL to return directly from the current function.
+   (That is, we bypass any return value.)  */
+
+void
+expand_naked_return (void)
+{
+  rtx last_insn, end_label;
+
+  last_insn = get_last_insn ();
+  end_label = naked_return_label;
+
+  clear_pending_stack_adjust ();
+  do_pending_stack_adjust ();
+  clear_last_expr ();
+
+  if (end_label == 0)
+    end_label = naked_return_label = gen_label_rtx ();
+  expand_goto_internal (NULL_TREE, end_label, last_insn);
+}
+
 /* Try to guess whether the value of return means error code.  */
 static enum br_predictor
 return_prediction (rtx val)
@@ -2914,6 +2942,34 @@ return_prediction (rtx val)
   return PRED_NO_PREDICTION;
 }
 
+
+/* If the current function returns values in the most significant part
+   of a register, shift return value VAL appropriately.  The mode of
+   the function's return type is known not to be BLKmode.  */
+
+static rtx
+shift_return_value (rtx val)
+{
+  tree type;
+
+  type = TREE_TYPE (DECL_RESULT (current_function_decl));
+  if (targetm.calls.return_in_msb (type))
+    {
+      rtx target;
+      HOST_WIDE_INT shift;
+
+      target = DECL_RTL (DECL_RESULT (current_function_decl));
+      shift = (GET_MODE_BITSIZE (GET_MODE (target))
+              - BITS_PER_UNIT * int_size_in_bytes (type));
+      if (shift > 0)
+       val = expand_binop (GET_MODE (target), ashl_optab,
+                           gen_lowpart (GET_MODE (target), val),
+                           GEN_INT (shift), target, 1, OPTAB_WIDEN);
+    }
+  return val;
+}
+
+
 /* Generate RTL to return from the current function, with value VAL.  */
 
 static void
@@ -2944,16 +3000,17 @@ expand_value_return (rtx val)
   if (return_reg != val)
     {
       tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
-#ifdef PROMOTE_FUNCTION_RETURN
-      int unsignedp = TREE_UNSIGNED (type);
-      enum machine_mode old_mode
-       = DECL_MODE (DECL_RESULT (current_function_decl));
-      enum machine_mode mode
-       = promote_mode (type, old_mode, &unsignedp, 1);
-
-      if (mode != old_mode)
-       val = convert_modes (mode, old_mode, val, unsignedp);
-#endif
+      if (targetm.calls.promote_function_return (TREE_TYPE (current_function_decl)))
+      {
+       int unsignedp = TREE_UNSIGNED (type);
+       enum machine_mode old_mode
+         = DECL_MODE (DECL_RESULT (current_function_decl));
+       enum machine_mode mode
+         = promote_mode (type, old_mode, &unsignedp, 1);
+
+       if (mode != old_mode)
+         val = convert_modes (mode, old_mode, val, unsignedp);
+      }
       if (GET_CODE (return_reg) == PARALLEL)
        emit_group_load (return_reg, val, type, int_size_in_bytes (type));
       else
@@ -3077,13 +3134,13 @@ expand_return (tree retval)
     {
       int i;
       unsigned HOST_WIDE_INT bitpos, xbitpos;
-      unsigned HOST_WIDE_INT big_endian_correction = 0;
+      unsigned HOST_WIDE_INT padding_correction = 0;
       unsigned HOST_WIDE_INT bytes
        = int_size_in_bytes (TREE_TYPE (retval_rhs));
       int n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
       unsigned int bitsize
        = MIN (TYPE_ALIGN (TREE_TYPE (retval_rhs)), BITS_PER_WORD);
-      rtx *result_pseudos = (rtx *) alloca (sizeof (rtx) * n_regs);
+      rtx *result_pseudos = alloca (sizeof (rtx) * n_regs);
       rtx result_reg, src = NULL_RTX, dst = NULL_RTX;
       rtx result_val = expand_expr (retval_rhs, NULL_RTX, VOIDmode, 0);
       enum machine_mode tmpmode, result_reg_mode;
@@ -3094,25 +3151,33 @@ expand_return (tree retval)
          return;
        }
 
-      /* Structures whose size is not a multiple of a word are aligned
-        to the least significant byte (to the right).  On a BYTES_BIG_ENDIAN
-        machine, this means we must skip the empty high order bytes when
-        calculating the bit offset.  */
-      if (BYTES_BIG_ENDIAN
-         && bytes % UNITS_PER_WORD)
-       big_endian_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
-                                                 * BITS_PER_UNIT));
+      /* If the structure doesn't take up a whole number of words, see
+        whether the register value should be padded on the left or on
+        the right.  Set PADDING_CORRECTION to the number of padding
+        bits needed on the left side.
+
+        In most ABIs, the structure will be returned at the least end of
+        the register, which translates to right padding on little-endian
+        targets and left padding on big-endian targets.  The opposite
+        holds if the structure is returned at the most significant
+        end of the register.  */
+      if (bytes % UNITS_PER_WORD != 0
+         && (targetm.calls.return_in_msb (TREE_TYPE (retval_rhs))
+             ? !BYTES_BIG_ENDIAN
+             : BYTES_BIG_ENDIAN))
+       padding_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
+                                              * BITS_PER_UNIT));
 
       /* Copy the structure BITSIZE bits at a time.  */
-      for (bitpos = 0, xbitpos = big_endian_correction;
+      for (bitpos = 0, xbitpos = padding_correction;
           bitpos < bytes * BITS_PER_UNIT;
           bitpos += bitsize, xbitpos += bitsize)
        {
          /* We need a new destination pseudo each time xbitpos is
-            on a word boundary and when xbitpos == big_endian_correction
+            on a word boundary and when xbitpos == padding_correction
             (the first time through).  */
          if (xbitpos % BITS_PER_WORD == 0
-             || xbitpos == big_endian_correction)
+             || xbitpos == padding_correction)
            {
              /* Generate an appropriate register.  */
              dst = gen_reg_rtx (word_mode);
@@ -3139,21 +3204,25 @@ expand_return (tree retval)
                           BITS_PER_WORD);
        }
 
-      /* Find the smallest integer mode large enough to hold the
-        entire structure and use that mode instead of BLKmode
-        on the USE insn for the return register.  */
-      for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-          tmpmode != VOIDmode;
-          tmpmode = GET_MODE_WIDER_MODE (tmpmode))
-       /* Have we found a large enough mode?  */
-       if (GET_MODE_SIZE (tmpmode) >= bytes)
-         break;
+      tmpmode = GET_MODE (result_rtl);
+      if (tmpmode == BLKmode)
+       {
+         /* Find the smallest integer mode large enough to hold the
+            entire structure and use that mode instead of BLKmode
+            on the USE insn for the return register.  */
+         for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+              tmpmode != VOIDmode;
+              tmpmode = GET_MODE_WIDER_MODE (tmpmode))
+           /* Have we found a large enough mode?  */
+           if (GET_MODE_SIZE (tmpmode) >= bytes)
+             break;
 
-      /* No suitable mode found.  */
-      if (tmpmode == VOIDmode)
-       abort ();
+         /* No suitable mode found.  */
+         if (tmpmode == VOIDmode)
+           abort ();
 
-      PUT_MODE (result_rtl, tmpmode);
+         PUT_MODE (result_rtl, tmpmode);
+       }
 
       if (GET_MODE_SIZE (tmpmode) < GET_MODE_SIZE (word_mode))
        result_reg_mode = word_mode;
@@ -3186,7 +3255,7 @@ expand_return (tree retval)
       val = force_not_mem (val);
       emit_queue ();
       /* Return the calculated value, doing cleanups first.  */
-      expand_value_return (val);
+      expand_value_return (shift_return_value (val));
     }
   else
     {
@@ -3258,7 +3327,7 @@ tail_recursion_args (tree actuals, tree formals)
 
   /* Compute all the actuals.  */
 
-  argvec = (rtx *) alloca (i * sizeof (rtx));
+  argvec = alloca (i * sizeof (rtx));
 
   for (a = actuals, i = 0; a; a = TREE_CHAIN (a), i++)
     argvec[i] = expand_expr (TREE_VALUE (a), NULL_RTX, VOIDmode, 0);
@@ -3498,6 +3567,14 @@ expand_nl_handler_label (rtx slot, rtx before_insn)
 static void
 expand_nl_goto_receiver (void)
 {
+    /* Clobber the FP when we get here, so we have to make sure it's
+     marked as used by this function.  */
+  emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
+
+  /* Mark the static chain as clobbered here so life information
+     doesn't get messed up for it.  */
+  emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
+
 #ifdef HAVE_nonlocal_goto
   if (! HAVE_nonlocal_goto)
 #endif
@@ -3546,6 +3623,13 @@ expand_nl_goto_receiver (void)
   if (HAVE_nonlocal_goto_receiver)
     emit_insn (gen_nonlocal_goto_receiver ());
 #endif
+
+  /* @@@ This is a kludge.  Not all machine descriptions define a blockage
+     insn, but we must not allow the code we just generated to be reordered
+     by scheduling.  Specifically, the update of the frame pointer must
+     happen immediately, not later.  So emit an ASM_INPUT to act as blockage
+     insn.  */
+  emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
 }
 
 /* Make handlers for nonlocal gotos taking place in the function calls in
@@ -3639,7 +3723,7 @@ warn_about_unused_variables (tree vars)
          && ! TREE_USED (decl)
          && ! DECL_IN_SYSTEM_HEADER (decl)
          && DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
-       warning_with_decl (decl, "unused variable `%s'");
+       warning ("%Junused variable '%D'", decl, decl);
 }
 
 /* Generate RTL code to terminate a binding contour.
@@ -3699,8 +3783,8 @@ expand_end_bindings (tree vars, int mark_ends, int dont_jump_in)
             that must be an error, because gotos without fixups
             come from outside all saved stack-levels.  */
          if (TREE_ADDRESSABLE (chain->label))
-           error_with_decl (chain->label,
-                            "label `%s' used before containing binding contour");
+           error ("%Jlabel '%D' used before containing binding contour",
+                  chain->label, chain->label);
        }
     }
 
@@ -3717,6 +3801,7 @@ expand_end_bindings (tree vars, int mark_ends, int dont_jump_in)
       /* Don't let cleanups affect ({...}) constructs.  */
       int old_expr_stmts_for_value = expr_stmts_for_value;
       rtx old_last_expr_value = last_expr_value;
+      rtx old_last_expr_alt_rtl = last_expr_alt_rtl;
       tree old_last_expr_type = last_expr_type;
       expr_stmts_for_value = 0;
 
@@ -3733,6 +3818,7 @@ expand_end_bindings (tree vars, int mark_ends, int dont_jump_in)
 
       expr_stmts_for_value = old_expr_stmts_for_value;
       last_expr_value = old_last_expr_value;
+      last_expr_alt_rtl = old_last_expr_alt_rtl;
       last_expr_type = old_last_expr_type;
 
       /* Restore the stack level.  */
@@ -4354,32 +4440,6 @@ expand_start_case (int exit_flag, tree expr, tree type,
 
   start_cleanup_deferral ();
 }
-
-/* Start a "dummy case statement" within which case labels are invalid
-   and are not connected to any larger real case statement.
-   This can be used if you don't want to let a case statement jump
-   into the middle of certain kinds of constructs.  */
-
-void
-expand_start_case_dummy (void)
-{
-  struct nesting *thiscase = ALLOC_NESTING ();
-
-  /* Make an entry on case_stack for the dummy.  */
-
-  thiscase->desc = CASE_NESTING;
-  thiscase->next = case_stack;
-  thiscase->all = nesting_stack;
-  thiscase->depth = ++nesting_depth;
-  thiscase->exit_label = 0;
-  thiscase->data.case_stmt.case_list = 0;
-  thiscase->data.case_stmt.start = 0;
-  thiscase->data.case_stmt.nominal_type = 0;
-  thiscase->data.case_stmt.default_label = 0;
-  case_stack = thiscase;
-  nesting_stack = thiscase;
-  start_cleanup_deferral ();
-}
 \f
 static void
 check_seenlabel (void)
@@ -4593,7 +4653,7 @@ add_case_node (tree low, tree high, tree label, tree *duplicate)
 
   /* Add this label to the chain, and succeed.  */
 
-  r = (struct case_node *) ggc_alloc (sizeof (struct case_node));
+  r = ggc_alloc (sizeof (struct case_node));
   r->low = low;
 
   /* If the bounds are equal, turn this into the one-value case.  */
@@ -5026,8 +5086,7 @@ check_for_full_enumeration_handling (tree type)
       /* We deliberately use calloc here, not cmalloc, so that we can suppress
         this optimization if we don't have enough memory rather than
         aborting, as xmalloc would do.  */
-      && (cases_seen =
-         (unsigned char *) really_call_calloc (bytes_needed, 1)) != NULL)
+      && (cases_seen = really_call_calloc (bytes_needed, 1)) != NULL)
     {
       HOST_WIDE_INT i;
       tree v = TYPE_VALUES (type);
@@ -5247,6 +5306,14 @@ emit_case_bit_tests (tree index_type, tree index_expr, tree minval,
   emit_jump (default_label);
 }
 
+#ifndef HAVE_casesi
+#define HAVE_casesi 0
+#endif
+
+#ifndef HAVE_tablejump
+#define HAVE_tablejump 0
+#endif
+
 /* Terminate a case (Pascal) or switch (C) statement
    in which ORIG_INDEX is the expression to be tested.
    If ORIG_TYPE is not NULL, it is the original ORIG_INDEX
@@ -5427,14 +5494,18 @@ expand_end_case_type (tree orig_index, tree orig_type)
         because we can optimize it.  */
 
       else if (count < case_values_threshold ()
-              || compare_tree_int (range, 10 * count) > 0
+              || compare_tree_int (range,
+                                   (optimize_size ? 3 : 10) * count) > 0
               /* RANGE may be signed, and really large ranges will show up
                  as negative numbers.  */
               || compare_tree_int (range, 0) < 0
 #ifndef ASM_OUTPUT_ADDR_DIFF_ELT
               || flag_pic
 #endif
-              || TREE_CONSTANT (index_expr))
+              || TREE_CONSTANT (index_expr)
+              /* If neither casesi or tablejump is available, we can
+                 only go this way.  */
+              || (!HAVE_casesi && !HAVE_tablejump))
        {
          index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
 
@@ -5541,8 +5612,8 @@ expand_end_case_type (tree orig_index, tree orig_type)
          /* Get table of labels to jump to, in order of case index.  */
 
          ncases = tree_low_cst (range, 0) + 1;
-         labelvec = (rtx *) alloca (ncases * sizeof (rtx));
-         memset ((char *) labelvec, 0, ncases * sizeof (rtx));
+         labelvec = alloca (ncases * sizeof (rtx));
+         memset (labelvec, 0, ncases * sizeof (rtx));
 
          for (n = thiscase->data.case_stmt.case_list; n; n = n->right)
            {