From: Jason Merrill Date: Fri, 11 Jun 2004 06:08:09 +0000 (-0400) Subject: sparc.c (sparc_gimplify_va_arg): New fn. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5f393b252ee431bad5c22b8a5ed43239d09e5eed;p=gcc.git sparc.c (sparc_gimplify_va_arg): New fn. * config/sparc/sparc.c (sparc_gimplify_va_arg): New fn. (TARGET_GIMPLIFY_VA_ARG_EXPR): Define. From-SVN: r82963 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f9b6182eccd..00d09a0ba1e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2004-06-11 Jason Merrill + + * config/sparc/sparc.c (sparc_gimplify_va_arg): New fn. + (TARGET_GIMPLIFY_VA_ARG_EXPR): Define. + 2004-06-11 Jerry Quinn * typeclass.h: Add GPL plus exception license. Add include diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 0d197271456..5be84c886e0 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -47,6 +47,7 @@ Boston, MA 02111-1307, USA. */ #include "target.h" #include "target-def.h" #include "cfglayout.h" +#include "tree-gimple.h" /* Global variables for machine-dependent things. */ @@ -181,6 +182,7 @@ static bool sparc_promote_prototypes (tree); static rtx sparc_struct_value_rtx (tree, int); static bool sparc_return_in_memory (tree, tree); static bool sparc_strict_argument_naming (CUMULATIVE_ARGS *); +static tree sparc_gimplify_va_arg (tree, tree, tree *, tree *); /* Option handling. */ @@ -289,6 +291,9 @@ enum processor_type sparc_cpu; #undef TARGET_STRICT_ARGUMENT_NAMING #define TARGET_STRICT_ARGUMENT_NAMING sparc_strict_argument_naming +#undef TARGET_GIMPLIFY_VA_ARG_EXPR +#define TARGET_GIMPLIFY_VA_ARG_EXPR sparc_gimplify_va_arg + struct gcc_target targetm = TARGET_INITIALIZER; /* Validate and override various options, and do some machine dependent @@ -6041,6 +6046,96 @@ sparc_va_arg (tree valist, tree type) return addr_rtx; } + +tree +sparc_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) +{ + HOST_WIDE_INT size, rsize, align; + tree addr, incr; + bool indirect; + tree ptrtype = build_pointer_type (type); + + if (function_arg_pass_by_reference (0, TYPE_MODE (type), type, 0)) + { + indirect = true; + size = rsize = UNITS_PER_WORD; + align = 0; + } + else + { + indirect = false; + size = int_size_in_bytes (type); + rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD; + align = 0; + + if (TARGET_ARCH64) + { + /* For SPARC64, objects requiring 16-byte alignment get it. */ + if (TYPE_ALIGN (type) >= 2 * (unsigned) BITS_PER_WORD) + align = 2 * UNITS_PER_WORD; + + /* SPARC-V9 ABI states that structures up to 16 bytes in size + are given whole slots as needed. */ + if (AGGREGATE_TYPE_P (type)) + { + if (size == 0) + size = rsize = UNITS_PER_WORD; + else + size = rsize; + } + } + } + + incr = valist; + if (align) + { + incr = fold (build2 (PLUS_EXPR, ptr_type_node, incr, + ssize_int (align - 1))); + incr = fold (build2 (BIT_AND_EXPR, ptr_type_node, incr, + ssize_int (-align))); + } + + gimplify_expr (&incr, pre_p, post_p, is_gimple_val, fb_rvalue); + addr = incr; + + if (BYTES_BIG_ENDIAN && size < rsize) + addr = fold (build2 (PLUS_EXPR, ptr_type_node, incr, + ssize_int (rsize - size))); + + if (indirect) + { + addr = fold_convert (build_pointer_type (ptrtype), addr); + addr = build_fold_indirect_ref (addr); + } + /* If the address isn't aligned properly for the type, + we may need to copy to a temporary. + FIXME: This is inefficient. Usually we can do this + in registers. */ + else if (align == 0 + && TYPE_ALIGN (type) > BITS_PER_WORD) + { + tree tmp = create_tmp_var (type, "va_arg_tmp"); + tree dest_addr = build_fold_addr_expr (tmp); + + tree copy = build_function_call_expr + (implicit_built_in_decls[BUILT_IN_MEMCPY], + tree_cons (NULL_TREE, dest_addr, + tree_cons (NULL_TREE, addr, + tree_cons (NULL_TREE, size_int (rsize), + NULL_TREE)))); + + gimplify_and_add (copy, pre_p); + addr = dest_addr; + } + else + addr = fold_convert (ptrtype, addr); + + incr = fold (build2 (PLUS_EXPR, ptr_type_node, incr, ssize_int (rsize))); + incr = build2 (MODIFY_EXPR, ptr_type_node, valist, incr); + gimplify_and_add (incr, post_p); + + return build_fold_indirect_ref (addr); +} /* Return the string to output a conditional branch to LABEL, which is the operand number of the label. OP is the conditional expression.