OSDN Git Service

Fix linux kernel miscompilation.
[pf3gnuchains/gcc-fork.git] / gcc / config / ia64 / ia64.c
index f4b45d3..871c52d 100644 (file)
@@ -276,6 +276,7 @@ static tree ia64_handle_model_attribute (tree *, tree, tree, int, bool *);
 static void ia64_encode_section_info (tree, rtx, int);
 static rtx ia64_struct_value_rtx (tree, int);
 static tree ia64_gimplify_va_arg (tree, tree, tree *, tree *);
+static bool ia64_scalar_mode_supported_p (enum machine_mode mode);
 
 \f
 /* Table of valid machine attributes.  */
@@ -416,6 +417,9 @@ static const struct attribute_spec ia64_attribute_table[] =
 #undef TARGET_UNWIND_EMIT
 #define TARGET_UNWIND_EMIT process_for_unwind_directive
 
+#undef TARGET_SCALAR_MODE_SUPPORTED_P
+#define TARGET_SCALAR_MODE_SUPPORTED_P ia64_scalar_mode_supported_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 typedef enum
@@ -669,10 +673,7 @@ static rtx
 gen_thread_pointer (void)
 {
   if (!thread_pointer_rtx)
-    {
-      thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
-      RTX_UNCHANGING_P (thread_pointer_rtx) = 1;
-    }
+    thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
   return thread_pointer_rtx;
 }
 
@@ -689,13 +690,11 @@ ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
 
       tga_op1 = gen_reg_rtx (Pmode);
       emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
-      tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
-      RTX_UNCHANGING_P (tga_op1) = 1;
+      tga_op1 = gen_const_mem (Pmode, tga_op1);
 
       tga_op2 = gen_reg_rtx (Pmode);
       emit_insn (gen_load_ltoff_dtprel (tga_op2, op1));
-      tga_op2 = gen_rtx_MEM (Pmode, tga_op2);
-      RTX_UNCHANGING_P (tga_op2) = 1;
+      tga_op2 = gen_const_mem (Pmode, tga_op2);
 
       tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
                                         LCT_CONST, Pmode, 2, tga_op1,
@@ -718,8 +717,7 @@ ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
 
       tga_op1 = gen_reg_rtx (Pmode);
       emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
-      tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
-      RTX_UNCHANGING_P (tga_op1) = 1;
+      tga_op1 = gen_const_mem (Pmode, tga_op1);
 
       tga_op2 = const0_rtx;
 
@@ -749,8 +747,7 @@ ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
     case TLS_MODEL_INITIAL_EXEC:
       tmp = gen_reg_rtx (Pmode);
       emit_insn (gen_load_ltoff_tprel (tmp, op1));
-      tmp = gen_rtx_MEM (Pmode, tmp);
-      RTX_UNCHANGING_P (tmp) = 1;
+      tmp = gen_const_mem (Pmode, tmp);
       tmp = force_reg (Pmode, tmp);
 
       if (!register_operand (op0, Pmode))
@@ -3176,17 +3173,7 @@ ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
          else if (gr_size > UNITS_PER_WORD)
            int_regs += gr_size / UNITS_PER_WORD;
        }
-
-      /* If we ended up using just one location, just return that one loc, but
-        change the mode back to the argument mode.  However, we can't do this
-        when hfa_mode is XFmode and mode is TImode.  In that case, we would
-        return a TImode reference to an FP reg, but FP regs can't hold TImode.
-        We need the PARALLEL to make this work.  This can happen for a union
-        containing a single __float80 member.  */
-      if (i == 1 && ! (hfa_mode == XFmode && mode == TImode))
-       return gen_rtx_REG (mode, REGNO (XEXP (loc[0], 0)));
-      else
-       return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
+      return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
     }
 
   /* Integral and aggregates go in general registers.  If we have run out of
@@ -3380,6 +3367,12 @@ ia64_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
 static bool
 ia64_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
 {
+  /* We can't perform a sibcall if the current function has the syscall_linkage
+     attribute.  */
+  if (lookup_attribute ("syscall_linkage",
+                       TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
+    return false;
+
   /* We must always return with our current GP.  This means we can
      only sibcall to functions defined in the current module.  */
   return decl && (*targetm.binds_local_p) (decl);
@@ -3396,7 +3389,7 @@ ia64_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
     {
       tree ptrtype = build_pointer_type (type);
       tree addr = std_gimplify_va_arg_expr (valist, ptrtype, pre_p, post_p);
-      return build_fold_indirect_ref (addr);
+      return build_va_arg_indirect_ref (addr);
     }
 
   /* Aggregate arguments with alignment larger than 8 bytes start at
@@ -3407,9 +3400,9 @@ ia64_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
       ? int_size_in_bytes (type) > 8 : TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
     {
       tree t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
-                     build_int_cst (NULL_TREE, 2 * UNITS_PER_WORD - 1, 0));
+                     build_int_cst (NULL_TREE, 2 * UNITS_PER_WORD - 1));
       t = build (BIT_AND_EXPR, TREE_TYPE (t), t,
-                build_int_cst (NULL_TREE, -2 * UNITS_PER_WORD, -1));
+                build_int_cst (NULL_TREE, -2 * UNITS_PER_WORD));
       t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
       gimplify_and_add (t, pre_p);
     }
@@ -3484,11 +3477,7 @@ ia64_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
                                      GEN_INT (offset));
          offset += hfa_size;
        }
-
-      if (i == 1)
-       return XEXP (loc[0], 0);
-      else
-       return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
+      return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
     }
   else if (FLOAT_TYPE_P (valtype) && mode != TFmode && mode != TCmode)
     return gen_rtx_REG (mode, FR_ARG_FIRST);
@@ -8499,4 +8488,29 @@ ia64_struct_value_rtx (tree fntype,
   return gen_rtx_REG (Pmode, GR_REG (8));
 }
 
+static bool
+ia64_scalar_mode_supported_p (enum machine_mode mode)
+{
+  switch (mode)
+    {
+    case QImode:
+    case HImode:
+    case SImode:
+    case DImode:
+    case TImode:
+      return true;
+
+    case SFmode:
+    case DFmode:
+    case XFmode:
+      return true;
+
+    case TFmode:
+      return TARGET_HPUX;
+
+    default:
+      return false;
+    }
+}
+
 #include "gt-ia64.h"