aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/config/cris/cris.c88
2 files changed, 74 insertions, 21 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index dd96234..4502a2a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index 9456874..d1c6f5b 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -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;
}