* config/cris/cris.c (cris_target_asm_function_prologue): Do not
authorhp <hp@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 12 Mar 2002 02:17:30 +0000 (02:17 +0000)
committerhp <hp@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 12 Mar 2002 02:17:30 +0000 (02:17 +0000)
emit pic register load if "internal" visibility.
(cris_print_operand): Avoid traditional-warning for 0xffffffff.
(cris_expand_builtin_va_arg): Do all computations on trees.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@50627 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/cris/cris.c

index dd96234..4502a2a 100644 (file)
@@ -1,3 +1,10 @@
+2002-03-12  Hans-Peter Nilsson  <hp@axis.com>
+
+       * config/cris/cris.c (cris_target_asm_function_prologue):  Do not
+       emit pic register load if "internal" visibility.
+       (cris_print_operand): Avoid traditional-warning for 0xffffffff.
+       (cris_expand_builtin_va_arg): Do all computations on trees.
+
 2002-03-11  Richard Henderson  <rth@redhat.com>
 
        * rtlanal.c: Include recog.h.
index 9456874..d1c6f5b 100644 (file)
@@ -857,11 +857,19 @@ cris_target_asm_function_prologue (file, size)
       framesize += size + cfoa_size;
     }
 
-  /* Set up the PIC register.  */
+  /* Set up the PIC register.  Not needed for a function marked with
+     visibility "internal".  */
   if (current_function_uses_pic_offset_table)
-    asm_fprintf (file, "\tmove.d $pc,$%s\n\tsub.d .:GOTOFF,$%s\n",
-                reg_names[PIC_OFFSET_TABLE_REGNUM],
-                reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    {
+      tree vis = lookup_attribute ("visibility", DECL_ATTRIBUTES (cfun->decl));
+
+      if (!vis
+         || strcmp ("internal",
+                    TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (vis)))))
+       asm_fprintf (file, "\tmove.d $pc,$%s\n\tsub.d .:GOTOFF,$%s\n",
+                    reg_names[PIC_OFFSET_TABLE_REGNUM],
+                    reg_names[PIC_OFFSET_TABLE_REGNUM]);
+    }
 
   if (TARGET_PDEBUG)
     fprintf (file,
@@ -1452,7 +1460,8 @@ cris_print_operand (file, x, code)
        }
       else if (HOST_BITS_PER_WIDE_INT > 32 && GET_CODE (operand) == CONST_INT)
        {
-         fprintf (file, "0x%x", (unsigned int)(INTVAL (x) & 0xffffffff));
+         fprintf (file, "0x%x",
+                  INTVAL (x) & ((unsigned int) 0x7fffffff * 2 + 1));
          return;
        }
       /* Otherwise the least significant part equals the normal part,
@@ -2612,32 +2621,69 @@ cris_expand_builtin_va_arg (valist, type)
 {
   tree addr_tree, t;
   rtx addr;
-  enum machine_mode mode = TYPE_MODE (type);
-  int passed_size;
+  tree passed_size = size_zero_node;
+  tree type_size = NULL;
+  tree size3 = size_int (3);
+  tree size4 = size_int (4);
+  tree size8 = size_int (8);
+  tree rounded_size;
 
   /* Get AP.  */
   addr_tree = valist;
 
-  /* Check if the type is passed by value or by reference.  */
-  if (MUST_PASS_IN_STACK (mode, type)
-      || CRIS_FUNCTION_ARG_SIZE (mode, type) > 8)
+  if (type == error_mark_node
+      || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
+      || TREE_OVERFLOW (type_size))
+    /* Presumable an error; the size isn't computable.  A message has
+       supposedly been emitted elsewhere.  */
+    rounded_size = size_zero_node;
+  else
+    rounded_size
+      = fold (build (MULT_EXPR, sizetype,
+                    fold (build (TRUNC_DIV_EXPR, sizetype,
+                                 fold (build (PLUS_EXPR, sizetype,
+                                              type_size, size3)),
+                                 size4)),
+                    size4));
+
+  if (!integer_zerop (rounded_size))
     {
-      tree type_ptr = build_pointer_type (type);
-      addr_tree = build1 (INDIRECT_REF, type_ptr, addr_tree);
-      passed_size = 4;
+      /* Check if the type is passed by value or by reference.  This test must
+        be different than the call-site test and be done at run-time:
+        gcc.c-torture/execute/20020307-2.c.  Hence the tree stuff.
+
+        Values up to 8 bytes are passed by-value, padded to register-size
+        (4 bytes).  Larger values are passed by-reference.  */
+      passed_size
+       = fold (build (COND_EXPR, sizetype,
+                      fold (build (GT_EXPR, sizetype,
+                                   rounded_size,
+                                   size8)),
+                      size4,
+                      rounded_size));
+
+      addr_tree
+       = fold (build (COND_EXPR, TREE_TYPE (addr_tree),
+                     fold (build (GT_EXPR, sizetype,
+                                  rounded_size,
+                                  size8)),
+                     build1 (INDIRECT_REF, build_pointer_type (type),
+                             addr_tree),
+                     addr_tree));
     }
-  else
-    passed_size = (CRIS_FUNCTION_ARG_SIZE (mode, type) > 4) ? 8 : 4;
 
   addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
   addr = copy_to_reg (addr);
 
-  /* Compute new value for AP.  */
-  t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
-            build (PLUS_EXPR, TREE_TYPE (valist), valist,
-                   build_int_2 (passed_size, 0)));
-  TREE_SIDE_EFFECTS (t) = 1;
-  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+  if (!integer_zerop (rounded_size))
+    {
+      /* Compute new value for AP.  */
+      t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
+                build (PLUS_EXPR, TREE_TYPE (valist), valist,
+                       passed_size));
+      TREE_SIDE_EFFECTS (t) = 1;
+      expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+    }
 
   return addr;
 }