This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

patch: split complex arguments (heads up)


As promised, here is the rest of the patch.

[Port maintainers see below]

PPC Linux and Darwin suffer from the same ABI incompatibility. Geoff is investigating among the Darwin folks as to when/if we can break the ABI. I will be emailing the appropriate Linux lists to verify with them as well. In the meantime, only AIX gets fixed.

David has bootstrapped this on AIX 4.3.3 both on 32 and 64 bits. He has also regtested on 32-bits.

I still need to fix function return values to go in a pair of FPRs. Tomorrow when I'm more awake.

Other port maintainers may be interested in setting this for their targets, since quite a few targets have ABI's specifying complex arguments in separate FPRs (Alpha for sure), not in one munged 64-bit FPR. The patch will break ABI compatibility for complex arguments, so y'all need to investigate.

Ok?

2003-05-23 Aldy Hernandez <aldyh@redhat.com>

* function.c (assign_parms): Split complex arguments.

* doc/tm.texi (SPLIT_COMPLEX_ARGS): Document.

* config/rs6000/rs6000.h (SPLIT_COMPLEX_ARGS): New.

	* expr.h (SPLIT_COMPLEX_ARGS): Define.
	(split_complex_types): Protoize.
	(split_complex_values): Protoize.

	* calls.c (expand_call): Split complex arguments on architectures
	that require it.
	(split_complex_values): New.
	(split_complex_types): New.

Index: function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.427
diff -c -p -r1.427 function.c
*** function.c 11 May 2003 19:21:31 -0000 1.427
--- function.c 29 May 2003 06:52:19 -0000
*************** static void prepare_function_start PARAM
*** 296,301 ****
--- 296,302 ----
static void do_clobber_return_reg PARAMS ((rtx, void *));
static void do_use_return_reg PARAMS ((rtx, void *));
static void instantiate_virtual_regs_lossage PARAMS ((rtx));
+ static tree split_complex_args (tree);

/* Pointer to chain of `struct function' for containing functions. */
static GTY(()) struct function *outer_function_chain;
*************** assign_parms (fndecl)
*** 4346,4352 ****
given as a constant and a tree-expression. */
struct args_size stack_args_size;
tree fntype = TREE_TYPE (fndecl);
! tree fnargs = DECL_ARGUMENTS (fndecl);
/* This is used for the arg pointer when referring to stack args. */
rtx internal_arg_pointer;
/* This is a dummy PARM_DECL that we used for the function result if
--- 4347,4353 ----
given as a constant and a tree-expression. */
struct args_size stack_args_size;
tree fntype = TREE_TYPE (fndecl);
! tree fnargs = DECL_ARGUMENTS (fndecl), orig_fnargs;
/* This is used for the arg pointer when referring to stack args. */
rtx internal_arg_pointer;
/* This is a dummy PARM_DECL that we used for the function result if
*************** assign_parms (fndecl)
*** 4400,4408 ****
--- 4401,4414 ----
fnargs = function_result_decl;
}


+ orig_fnargs = fnargs;
+
max_parm_reg = LAST_VIRTUAL_REGISTER + 1;
parm_reg_stack_loc = (rtx *) ggc_alloc_cleared (max_parm_reg * sizeof (rtx));


+   if (SPLIT_COMPLEX_ARGS)
+     fnargs = split_complex_args (fnargs);
+
  #ifdef REG_PARM_STACK_SPACE
  #ifdef MAYBE_REG_PARM_STACK_SPACE
    reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
*************** assign_parms (fndecl)
*** 5187,5192 ****
--- 5193,5227 ----
  	}
      }

+ if (SPLIT_COMPLEX_ARGS)
+ {
+ parm = orig_fnargs;
+
+ for (; parm; parm = TREE_CHAIN (parm))
+ {
+ tree type = TREE_TYPE (parm);
+
+ if (TREE_CODE (type) == COMPLEX_TYPE)
+ {
+ SET_DECL_RTL (parm,
+ gen_rtx_CONCAT (DECL_MODE (parm),
+ DECL_RTL (fnargs),
+ DECL_RTL (TREE_CHAIN (fnargs))));
+ DECL_INCOMING_RTL (parm)
+ = gen_rtx_CONCAT (DECL_MODE (parm),
+ DECL_INCOMING_RTL (fnargs),
+ DECL_INCOMING_RTL (TREE_CHAIN (fnargs)));
+ fnargs = TREE_CHAIN (fnargs);
+ }
+ else
+ {
+ SET_DECL_RTL (parm, DECL_RTL (fnargs));
+ DECL_INCOMING_RTL (parm) = DECL_INCOMING_RTL (fnargs);
+ }
+ fnargs = TREE_CHAIN (fnargs);
+ }
+ }
+
/* Output all parameter conversion instructions (possibly including calls)
now that all parameters have been copied out of hard registers. */
emit_insn (conversion_insns);
*************** assign_parms (fndecl)
*** 5289,5294 ****
--- 5324,5360 ----
current_function_return_rtx = real_decl_rtl;
}
}
+ }
+
+ static tree
+ split_complex_args (tree args)
+ {
+ tree p;
+
+ args = copy_list (args);
+
+ for (p = args; p; p = TREE_CHAIN (p))
+ {
+ tree complex_type = TREE_TYPE (p);
+
+ if (TREE_CODE (complex_type) == COMPLEX_TYPE)
+ {
+ tree decl;
+ tree subtype = TREE_TYPE (complex_type);
+
+ /* Rewrite the PARM_DECL's type with its component. */
+ /* ?? should probably make a new PARM_DECL?? */
+ TREE_TYPE (p) = subtype;
+ DECL_ARG_TYPE (p) = TREE_TYPE (DECL_ARG_TYPE (p));
+
+ decl = build_decl (PARM_DECL, NULL_TREE, subtype);
+ DECL_ARG_TYPE (decl) = DECL_ARG_TYPE (p);
+ TREE_CHAIN (decl) = TREE_CHAIN (p);
+ TREE_CHAIN (p) = decl;
+ }
+ }
+
+ return args;
}

/* Indicate whether REGNO is an incoming argument to the current function
Index: expr.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.h,v
retrieving revision 1.137
diff -c -p -r1.137 expr.h
*** expr.h 12 May 2003 09:51:11 -0000 1.137
--- expr.h 29 May 2003 06:52:22 -0000
*************** do { \
*** 158,163 ****
--- 158,171 ----
#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) PARM_BOUNDARY
#endif


+ /* Define to nonzero if complex arguments should be split into their
+    corresponding components.  */
+ #ifndef SPLIT_COMPLEX_ARGS
+ #define SPLIT_COMPLEX_ARGS 0
+ #endif
+ tree split_complex_types (tree);
+ tree split_complex_values (tree);
+
  /* Provide a default value for STRICT_ARGUMENT_NAMING.  */
  #ifndef STRICT_ARGUMENT_NAMING
  #define STRICT_ARGUMENT_NAMING 0
Index: calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.273
diff -c -p -r1.273 calls.c
*** calls.c	3 May 2003 14:25:20 -0000	1.273
--- calls.c	29 May 2003 06:52:36 -0000
*************** expand_call (exp, target, ignore)
*** 2072,2077 ****
--- 2072,2078 ----
    rtx tail_call_insns = NULL_RTX;
    /* Data type of the function.  */
    tree funtype;
+   tree type_arg_types;
    /* Declaration of the function being called,
       or 0 if the function is computed (not known by name).  */
    tree fndecl = 0;
*************** expand_call (exp, target, ignore)
*** 2307,2312 ****
--- 2308,2323 ----
      abort ();
    funtype = TREE_TYPE (funtype);

+ /* Munge the tree to split complex arguments into their imaginary
+ and real parts. */
+ if (SPLIT_COMPLEX_ARGS)
+ {
+ type_arg_types = split_complex_types (TYPE_ARG_TYPES (funtype));
+ actparms = split_complex_values (actparms);
+ }
+ else
+ type_arg_types = TYPE_ARG_TYPES (funtype);
+
/* See if this is a call to a function that can return more than once
or a call to longjmp or malloc. */
flags |= special_function_p (fndecl, flags);
*************** expand_call (exp, target, ignore)
*** 2360,2368 ****


    if ((STRICT_ARGUMENT_NAMING
         || ! PRETEND_OUTGOING_VARARGS_NAMED)
!       && TYPE_ARG_TYPES (funtype) != 0)
      n_named_args
!       = (list_length (TYPE_ARG_TYPES (funtype))
  	 /* Don't include the last named arg.  */
  	 - (STRICT_ARGUMENT_NAMING ? 0 : 1)
  	 /* Count the struct value address, if it is passed as a parm.  */
--- 2371,2379 ----

    if ((STRICT_ARGUMENT_NAMING
         || ! PRETEND_OUTGOING_VARARGS_NAMED)
!       && type_arg_types != 0)
      n_named_args
!       = (list_length (type_arg_types)
  	 /* Don't include the last named arg.  */
  	 - (STRICT_ARGUMENT_NAMING ? 0 : 1)
  	 /* Count the struct value address, if it is passed as a parm.  */
*************** expand_call (exp, target, ignore)
*** 3442,3447 ****
--- 3453,3534 ----
      }

    return target;
+ }
+
+ /* Traverse an argument list in VALUES and expand all complex
+    arguments into their components.  */
+ tree
+ split_complex_values (tree values)
+ {
+   tree p;
+
+   values = copy_list (values);
+
+   for (p = values; p; p = TREE_CHAIN (p))
+     {
+       tree complex_value = TREE_VALUE (p);
+       tree complex_type;
+
+       complex_type = TREE_TYPE (complex_value);
+       if (!complex_type)
+ 	continue;
+
+       if (TREE_CODE (complex_type) == COMPLEX_TYPE)
+ 	{
+ 	  tree subtype;
+ 	  tree real, imag, next;
+
+ 	  subtype = TREE_TYPE (complex_type);
+ 	  complex_value = save_expr (complex_value);
+ 	  real = build1 (REALPART_EXPR, subtype, complex_value);
+ 	  imag = build1 (IMAGPART_EXPR, subtype, complex_value);
+
+ 	  TREE_VALUE (p) = real;
+ 	  next = TREE_CHAIN (p);
+ 	  imag = build_tree_list (NULL_TREE, imag);
+ 	  TREE_CHAIN (p) = imag;
+ 	  TREE_CHAIN (imag) = next;
+
+ 	  /* Skip the newly created node.  */
+ 	  p = TREE_CHAIN (p);
+ 	}
+     }
+
+   return values;
+ }
+
+ /* Traverse a list of TYPES and expand all complex types into their
+    components.  */
+ tree
+ split_complex_types (tree types)
+ {
+   tree p;
+
+   types = copy_list (types);
+
+   for (p = types; p; p = TREE_CHAIN (p))
+     {
+       tree complex_type = TREE_VALUE (p);
+
+       if (TREE_CODE (complex_type) == COMPLEX_TYPE)
+ 	{
+ 	  tree next, imag;
+
+ 	  /* Rewrite complex type with component type.  */
+ 	  TREE_VALUE (p) = TREE_TYPE (complex_type);
+ 	  next = TREE_CHAIN (p);
+
+ 	  /* Add another component type for the imaginary part.  */
+ 	  imag = build_tree_list (NULL_TREE, TREE_VALUE (p));
+ 	  TREE_CHAIN (p) = imag;
+ 	  TREE_CHAIN (imag) = next;
+
+ 	  /* Skip the newly created node.  */
+ 	  p = TREE_CHAIN (p);
+ 	}
+     }
+
+   return types;
  }
  
  /* Output a library call to function FUN (a SYMBOL_REF rtx).
Index: doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.222
diff -c -p -r1.222 tm.texi
*** doc/tm.texi	19 May 2003 20:03:42 -0000	1.222
--- doc/tm.texi	29 May 2003 06:53:13 -0000
*************** the structure-value address.  On many ma
*** 3797,3802 ****
--- 3797,3813 ----
  used for this purpose since all function arguments are pushed on the
  stack.

+ @findex SPLIT_COMPLEX_ARGS
+ @item SPLIT_COMPLEX_ARGS
+
+ Define this macro to a nonzero value if complex function arguments
+ should be split into their corresponding components.  By default, GCC
+ will attempt to pack complex arguments into the target's word size.
+ Some ABIs require complex arguments to be split and treated as their
+ individual components.  For example, on AIX64, complex floats should
+ be passed in a pair of floating point registers, even though a complex
+ float would fit in one 64-bit floating point register.
+
  @findex LOAD_ARGS_REVERSED
  @item LOAD_ARGS_REVERSED
  If defined, the order in which arguments are loaded into their
Index: config/rs6000/rs6000.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.274
diff -c -p -r1.274 rs6000.h
*** config/rs6000/rs6000.h	15 May 2003 20:01:10 -0000	1.274
--- config/rs6000/rs6000.h	29 May 2003 06:53:23 -0000
*************** typedef struct rs6000_args
*** 1794,1799 ****
--- 1794,1803 ----
  #define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
    function_arg_boundary (MODE, TYPE)

+ /* Define to nonzero if complex arguments should be split into their
+ corresponding components. */
+ #define SPLIT_COMPLEX_ARGS (DEFAULT_ABI == ABI_AIX)
+
/* Perform any needed actions needed for a function that is receiving a
variable number of arguments.



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]