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]

Fix i386 local and fastcall functions handling


Hi,
this patch brings into sync 3 places where amount of register arguments is
computed and fixes bugs in local functions returning structures and some cases
of fastcall problems.

Regtested/bootstrapped i386.
OK?
Honza
Wed Aug 13 21:00:51 CEST 2003  Jan Hubicka  <jh@suse.cz>
	* i386.c (ix86_fntype_regparm): Rename from ...
	(ix86_function_regparm): ... this one; add fastcall and local
	functions.
	(ix86_function_ok_for_sibcall): Update.
	(ix86_return_pops_args): Likewise.
	(init_cumulative_args): Likewise.
	(x86_can_output_mi_thunk): Likewise.
	(function_arg): Fix formating.
	(x86_this_parameter): Fix fastcall.
	(x86_output_mi_thunk): Likewise.
diff -Nrc3p gcc.old/config/i386/i386.c gcc/config/i386/i386.c
*** gcc.old/config/i386/i386.c	Mon Aug  4 22:43:01 2003
--- gcc/config/i386/i386.c	Wed Aug 13 20:36:30 2003
*************** static unsigned int ix86_select_alt_pic_
*** 866,872 ****
  static int ix86_save_reg (unsigned int, int);
  static void ix86_compute_frame_layout (struct ix86_frame *);
  static int ix86_comp_type_attributes (tree, tree);
! static int ix86_fntype_regparm (tree);
  const struct attribute_spec ix86_attribute_table[];
  static bool ix86_function_ok_for_sibcall (tree, tree);
  static tree ix86_handle_cdecl_attribute (tree *, tree, tree, int, bool *);
--- 866,872 ----
  static int ix86_save_reg (unsigned int, int);
  static void ix86_compute_frame_layout (struct ix86_frame *);
  static int ix86_comp_type_attributes (tree, tree);
! static int ix86_function_regparm (tree, tree);
  const struct attribute_spec ix86_attribute_table[];
  static bool ix86_function_ok_for_sibcall (tree, tree);
  static tree ix86_handle_cdecl_attribute (tree *, tree, tree, int, bool *);
*************** ix86_function_ok_for_sibcall (tree decl,
*** 1532,1550 ****
       such registers are not used for passing parameters.  */
    if (!decl && !TARGET_64BIT)
      {
!       int regparm = ix86_regparm;
!       tree attr, type;
  
        /* We're looking at the CALL_EXPR, we need the type of the function.  */
        type = TREE_OPERAND (exp, 0);		/* pointer expression */
        type = TREE_TYPE (type);			/* pointer type */
        type = TREE_TYPE (type);			/* function type */
  
!       attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
!       if (attr)
!         regparm = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
! 
!       if (regparm >= 3)
  	{
  	  /* ??? Need to count the actual number of registers to be used,
  	     not the possible number of registers.  Fix later.  */
--- 1532,1545 ----
       such registers are not used for passing parameters.  */
    if (!decl && !TARGET_64BIT)
      {
!       tree type;
  
        /* We're looking at the CALL_EXPR, we need the type of the function.  */
        type = TREE_OPERAND (exp, 0);		/* pointer expression */
        type = TREE_TYPE (type);			/* pointer type */
        type = TREE_TYPE (type);			/* function type */
  
!       if (ix86_function_regparm (type, NULL) >= 3)
  	{
  	  /* ??? Need to count the actual number of registers to be used,
  	     not the possible number of registers.  Fix later.  */
*************** ix86_handle_regparm_attribute (tree *nod
*** 1637,1645 ****
  	}
  
        if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (*node)))
!     {
!       error ("fastcall and regparm attributes are not compatible");
!     }
      }
  
    return NULL_TREE;
--- 1632,1640 ----
  	}
  
        if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (*node)))
! 	{
! 	  error ("fastcall and regparm attributes are not compatible");
! 	}
      }
  
    return NULL_TREE;
*************** ix86_comp_type_attributes (tree type1, t
*** 1670,1687 ****
    return 1;
  }
  
! /* Return the regparm value for a fuctio with the indicated TYPE.  */
  
  static int
! ix86_fntype_regparm (tree type)
  {
    tree attr;
  
!   attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
!   if (attr)
!     return TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
!   else
!     return ix86_regparm;
  }
  
  /* Value is the number of bytes of arguments automatically
--- 1665,1713 ----
    return 1;
  }
  
! /* Return the regparm value for a fuctio with the indicated TYPE and DECL.
!    DECL may be NULL when calling function indirectly
!    or considerling a libcall.  */
  
  static int
! ix86_function_regparm (tree type, tree decl)
  {
    tree attr;
+   int regparm = ix86_regparm;
+   bool user_convention = false;
  
!   if (!TARGET_64BIT)
!     {
!       attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
!       if (attr)
! 	{
! 	  regparm = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
! 	  user_convention = true;
! 	}
! 
!       if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
! 	{
! 	  regparm = 2;
! 	  user_convention = true;
! 	}
! 
!       /* Use register calling convention for local functions when possible.  */
!       if (!TARGET_64BIT && !user_convention && decl
! 	  && flag_unit_at_a_time)
! 	{
! 	  struct cgraph_local_info *i = cgraph_local_info (decl);
! 	  if (i && i->local)
! 	    {
! 	      /* We can't use regparm(3) for nested functions as these use
! 		 static chain pointer in third argument.  */
! 	      if (DECL_CONTEXT (decl) && !DECL_NO_STATIC_CHAIN (decl))
! 		regparm = 2;
! 	      else
! 		regparm = 3;
! 	    }
! 	}
!     }
!   return regparm;
  }
  
  /* Value is the number of bytes of arguments automatically
*************** ix86_return_pops_args (tree fundecl, tre
*** 1725,1731 ****
    if (aggregate_value_p (TREE_TYPE (funtype))
        && !TARGET_64BIT)
      {
!       int nregs = ix86_fntype_regparm (funtype);
  
        if (!nregs)
  	return GET_MODE_SIZE (Pmode);
--- 1751,1757 ----
    if (aggregate_value_p (TREE_TYPE (funtype))
        && !TARGET_64BIT)
      {
!       int nregs = ix86_function_regparm (funtype, fundecl);
  
        if (!nregs)
  	return GET_MODE_SIZE (Pmode);
*************** init_cumulative_args (CUMULATIVE_ARGS *c
*** 1767,1773 ****
  {
    static CUMULATIVE_ARGS zero_cum;
    tree param, next_param;
-   bool user_convention = false;
  
    if (TARGET_DEBUG_ARG)
      {
--- 1793,1798 ----
*************** init_cumulative_args (CUMULATIVE_ARGS *c
*** 1786,1803 ****
    *cum = zero_cum;
  
    /* Set up the number of registers to use for passing arguments.  */
!   cum->nregs = ix86_regparm;
    cum->sse_nregs = SSE_REGPARM_MAX;
-   if (fntype && !TARGET_64BIT)
-     {
-       tree attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (fntype));
- 
-       if (attr)
- 	{
- 	  cum->nregs = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
- 	  user_convention = true;
- 	}
-     }
    cum->maybe_vaarg = false;
  
    /* Use ecx and edx registers if function has fastcall attribute */
--- 1811,1821 ----
    *cum = zero_cum;
  
    /* Set up the number of registers to use for passing arguments.  */
!   if (fntype)
!     cum->nregs = ix86_function_regparm (fntype, fndecl);
!   else
!     cum->nregs = ix86_regparm;
    cum->sse_nregs = SSE_REGPARM_MAX;
    cum->maybe_vaarg = false;
  
    /* Use ecx and edx registers if function has fastcall attribute */
*************** init_cumulative_args (CUMULATIVE_ARGS *c
*** 1807,1829 ****
  	{
  	  cum->nregs = 2;
  	  cum->fastcall = 1;
- 	  user_convention = true;
- 	}
-     }
- 
-   /* Use register calling convention for local functions when possible.  */
-   if (!TARGET_64BIT && !user_convention && fndecl
-       && flag_unit_at_a_time)
-     {
-       struct cgraph_local_info *i = cgraph_local_info (fndecl);
-       if (i && i->local)
- 	{
- 	  /* We can't use regparm(3) for nested functions as these use
- 	     static chain pointer in third argument.  */
- 	  if (DECL_CONTEXT (fndecl) && !DECL_NO_STATIC_CHAIN (fndecl))
- 	    cum->nregs = 2;
- 	  else
- 	    cum->nregs = 3;
  	}
      }
  
--- 1825,1830 ----
*************** function_arg (CUMULATIVE_ARGS *cum,	/* c
*** 2501,2507 ****
  
  	        /* ECX not EAX is the first allocated register.  */
  	        if (regno == 0)
! 		      regno = 2;
  	      }
  	    ret = gen_rtx_REG (mode, regno);
  	  }
--- 2502,2508 ----
  
  	        /* ECX not EAX is the first allocated register.  */
  	        if (regno == 0)
! 		  regno = 2;
  	      }
  	    ret = gen_rtx_REG (mode, regno);
  	  }
*************** x86_this_parameter (tree function)
*** 15069,15075 ****
        return gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
      }
  
!   if (ix86_fntype_regparm (type) > 0)
      {
        tree parm;
  
--- 15070,15076 ----
        return gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
      }
  
!   if (ix86_function_regparm (type, function) > 0)
      {
        tree parm;
  
*************** x86_this_parameter (tree function)
*** 15079,15087 ****
        for (; parm; parm = TREE_CHAIN (parm))
  	if (TREE_VALUE (parm) == void_type_node)
  	  break;
!       /* If not, the this parameter is in %eax.  */
        if (parm)
! 	return gen_rtx_REG (SImode, 0);
      }
  
    if (aggregate_value_p (TREE_TYPE (type)))
--- 15080,15093 ----
        for (; parm; parm = TREE_CHAIN (parm))
  	if (TREE_VALUE (parm) == void_type_node)
  	  break;
!       /* If not, the this parameter is in the first argument.  */
        if (parm)
! 	{
! 	  int regno = 0;
! 	  if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
! 	    regno = 2;
! 	  return gen_rtx_REG (SImode, 0);
! 	}
      }
  
    if (aggregate_value_p (TREE_TYPE (type)))
*************** x86_can_output_mi_thunk (tree thunk ATTR
*** 15102,15108 ****
      return true;
  
    /* For 32-bit, everything's fine if we have one free register.  */
!   if (ix86_fntype_regparm (TREE_TYPE (function)) < 3)
      return true;
  
    /* Need a free register for vcall_offset.  */
--- 15108,15114 ----
      return true;
  
    /* For 32-bit, everything's fine if we have one free register.  */
!   if (ix86_function_regparm (TREE_TYPE (function), function) < 3)
      return true;
  
    /* Need a free register for vcall_offset.  */
*************** x86_output_mi_thunk (FILE *file ATTRIBUT
*** 15173,15179 ****
        if (TARGET_64BIT)
  	tmp = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 2 /* R10 */);
        else
! 	tmp = gen_rtx_REG (SImode, 2 /* ECX */);
  
        xops[0] = gen_rtx_MEM (Pmode, this_reg);
        xops[1] = tmp;
--- 15179,15191 ----
        if (TARGET_64BIT)
  	tmp = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 2 /* R10 */);
        else
! 	{
! 	  int tmp_regno = 2 /* ECX */;
! 	  if (lookup_attribute ("fastcall",
! 	      TYPE_ATTRIBUTES (TREE_TYPE (function))))
! 	    tmp_regno = 0 /* EAX */;
! 	  tmp = gen_rtx_REG (SImode, tmp_regno);
! 	}
  
        xops[0] = gen_rtx_MEM (Pmode, this_reg);
        xops[1] = tmp;


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