re PR target/9601 (-mrtd switch/stdcall attribute raises warnings for __buitltin...
authorKai Tietz <ktietz@redhat.com>
Mon, 11 Apr 2011 17:44:04 +0000 (19:44 +0200)
committerKai Tietz <ktietz@gcc.gnu.org>
Mon, 11 Apr 2011 17:44:04 +0000 (19:44 +0200)
2011-04-11  Kai Tietz  <ktietz@redhat.com>

PR target/9601
PR target/11772
* config/i386/i386-protos.h (ix86_get_callcvt): New prototype.
* config/i386/i386.c (ix86_handle_cconv_attribute): Adjust
comment.
(ix86_is_msabi_thiscall): Removed.
(ix86_is_type_thiscall): Likewise.
(ix86_get_callcvt): New function.
(ix86_comp_type_attributes): Simplify check.
(ix86_function_regparm): Use ix86_get_callcvt for calling
convention attribute checks.
(ix86_return_pops_args): Likewise.
(ix86_static_chain): Likewise.
(x86_this_parameter): Likewise.
(x86_output_mi_thunk): Likewise.
(ix86_function_type_abi): Optimize check for types without attributes.
* config/i386/i386.h (IX86_CALLCVT_CDECL, IX86_CALLCVT_STDCALL,
IX86_CALLCVT_FASTCALL, IX86_CALLCVT_THISCALL, IX86_CALLCVT_REGPARM,
IX86_CALLCVT_SSEREGPARM): New macros to represent calling convention
by flag-values.
(IX86_BASE_CALLCVT): Helper macro.
* config/i386/netware.c (i386_nlm_maybe_mangle_decl_assembler_name):
Use ix86_get_callcvt for calling convention attribute checks and avoid
symbol-decoration for stdcall in TARGET_RTD case.
* config/i386/winnt.c (i386_pe_maybe_mangle_decl_assembler_name):
Likewise.
(gen_stdcall_or_fastcall_suffix): Adjust ident and use DECL_ORIGIN
for declaration.

From-SVN: r172268

gcc/ChangeLog
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/i386/netware.c
gcc/config/i386/winnt.c

index 80e8c3bf025ca1a300f61de8e5b127245ac9b0ff..36ca4804b1274b2ef42e2dab72b49fd97e7ddc78 100644 (file)
@@ -1,3 +1,34 @@
+2011-04-11  Kai Tietz  <ktietz@redhat.com>
+
+       PR target/9601
+       PR target/11772
+       * config/i386/i386-protos.h (ix86_get_callcvt): New prototype.
+       * config/i386/i386.c (ix86_handle_cconv_attribute): Adjust
+       comment.
+       (ix86_is_msabi_thiscall): Removed.
+       (ix86_is_type_thiscall): Likewise.
+       (ix86_get_callcvt): New function.
+       (ix86_comp_type_attributes): Simplify check.
+       (ix86_function_regparm): Use ix86_get_callcvt for calling
+       convention attribute checks.
+       (ix86_return_pops_args): Likewise.
+       (ix86_static_chain): Likewise.
+       (x86_this_parameter): Likewise.
+       (x86_output_mi_thunk): Likewise.
+       (ix86_function_type_abi): Optimize check for types without attributes.
+       * config/i386/i386.h (IX86_CALLCVT_CDECL, IX86_CALLCVT_STDCALL,
+       IX86_CALLCVT_FASTCALL, IX86_CALLCVT_THISCALL, IX86_CALLCVT_REGPARM,
+       IX86_CALLCVT_SSEREGPARM): New macros to represent calling convention
+       by flag-values.
+       (IX86_BASE_CALLCVT): Helper macro.
+       * config/i386/netware.c (i386_nlm_maybe_mangle_decl_assembler_name):
+       Use ix86_get_callcvt for calling convention attribute checks and avoid
+       symbol-decoration for stdcall in TARGET_RTD case.
+       * config/i386/winnt.c (i386_pe_maybe_mangle_decl_assembler_name):
+       Likewise.
+       (gen_stdcall_or_fastcall_suffix): Adjust ident and use DECL_ORIGIN
+       for declaration.
+
 2011-04-11  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/sse.md (VI_128): New mode iterator.
index 4f90b502167a580b094f806612fc38d05f2d1a56..4b34e411808a960feab0103ea0459875a98c72af 100644 (file)
@@ -191,6 +191,8 @@ extern tree ix86_handle_shared_attribute (tree *, tree, tree, int, bool *);
 extern tree ix86_handle_selectany_attribute (tree *, tree, tree, int, bool *);
 extern int x86_field_alignment (tree, int);
 extern tree ix86_valid_target_attribute_tree (tree);
+extern unsigned int ix86_get_callcvt (const_tree);
+
 #endif
 
 extern rtx ix86_tls_get_addr (void);
index cd47ba75f942738fb967419aa966bf86d4a2bfd6..62187021e8aeb967db2d7228cea9e45d19acd370 100644 (file)
@@ -5312,7 +5312,7 @@ ix86_handle_cconv_attribute (tree *node, tree name,
       return NULL_TREE;
     }
 
-  /* Can combine regparm with all attributes but fastcall.  */
+  /* Can combine regparm with all attributes but fastcall, and thiscall.  */
   if (is_attribute_p ("regparm", name))
     {
       tree cst;
@@ -5436,38 +5436,54 @@ ix86_handle_cconv_attribute (tree *node, tree name,
   return NULL_TREE;
 }
 
-/* This function checks if the method-function has default __thiscall
-   calling-convention for 32-bit msabi.
-   It returns true if TYPE is of kind METHOD_TYPE, no stdarg function,
-   and the MS_ABI 32-bit is used.  Otherwise it returns false.  */
+/* This function determines from TYPE the calling-convention.  */
 
-static bool
-ix86_is_msabi_thiscall (const_tree type)
+unsigned int
+ix86_get_callcvt (const_tree type)
 {
-  if (TARGET_64BIT || ix86_function_type_abi (type) != MS_ABI
-      || TREE_CODE (type) != METHOD_TYPE || stdarg_p (type))
-    return false;
-  /* Check for different calling-conventions.  */
-  if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (type))
-      || lookup_attribute ("stdcall", TYPE_ATTRIBUTES (type))
-      || lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type))
-      || lookup_attribute ("regparm", TYPE_ATTRIBUTES (type))
-      || lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type)))
-    return false;
-  return true;
-}
+  unsigned int ret = 0;
+  bool is_stdarg;
+  tree attrs;
 
-/* This function checks if the thiscall attribute is set for the TYPE,
-   or if it is an method-type with default thiscall convention.
-   It returns true if function match, otherwise false is returned.  */
+  if (TARGET_64BIT)
+    return IX86_CALLCVT_CDECL;
 
-static bool
-ix86_is_type_thiscall (const_tree type)
-{
-  if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type))
-      || ix86_is_msabi_thiscall (type))
-    return true;
-  return false;
+  attrs = TYPE_ATTRIBUTES (type);
+  if (attrs != NULL_TREE)
+    {
+      if (lookup_attribute ("cdecl", attrs))
+       ret |= IX86_CALLCVT_CDECL;
+      else if (lookup_attribute ("stdcall", attrs))
+       ret |= IX86_CALLCVT_STDCALL;
+      else if (lookup_attribute ("fastcall", attrs))
+       ret |= IX86_CALLCVT_FASTCALL;
+      else if (lookup_attribute ("thiscall", attrs))
+       ret |= IX86_CALLCVT_THISCALL;
+
+      /* Regparam isn't allowed for thiscall and fastcall.  */
+      if ((ret & (IX86_CALLCVT_THISCALL | IX86_CALLCVT_FASTCALL)) == 0)
+       {
+         if (lookup_attribute ("regparm", attrs))
+           ret |= IX86_CALLCVT_REGPARM;
+         if (lookup_attribute ("sseregparm", attrs))
+           ret |= IX86_CALLCVT_SSEREGPARM;
+       }
+
+      if (IX86_BASE_CALLCVT(ret) != 0)
+       return ret;
+    }
+
+  is_stdarg = stdarg_p (type);
+  if (TARGET_RTD && !is_stdarg)
+    return IX86_CALLCVT_STDCALL | ret;
+
+  if (ret != 0
+      || is_stdarg
+      || TREE_CODE (type) != METHOD_TYPE
+      || ix86_function_type_abi (type) != MS_ABI)
+    return IX86_CALLCVT_CDECL | ret;
+
+  return IX86_CALLCVT_THISCALL;
 }
 
 /* Return 0 if the attributes for two types are incompatible, 1 if they
@@ -5477,43 +5493,18 @@ ix86_is_type_thiscall (const_tree type)
 static int
 ix86_comp_type_attributes (const_tree type1, const_tree type2)
 {
-  /* Check for mismatch of non-default calling convention.  */
-  bool is_thiscall = ix86_is_msabi_thiscall (type1);
-  const char *const rtdstr = TARGET_RTD ? (is_thiscall ? "thiscall" : "cdecl") : "stdcall";
+  unsigned int ccvt1, ccvt2;
 
   if (TREE_CODE (type1) != FUNCTION_TYPE
       && TREE_CODE (type1) != METHOD_TYPE)
     return 1;
 
-  /* Check for mismatched fastcall/regparm types.  */
-  if ((!lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type1))
-       != !lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type2)))
-      || (ix86_function_regparm (type1, NULL)
-         != ix86_function_regparm (type2, NULL)))
-    return 0;
-
-  /* Check for mismatched sseregparm types.  */
-  if (!lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type1))
-      != !lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type2)))
+  ccvt1 = ix86_get_callcvt (type1);
+  ccvt2 = ix86_get_callcvt (type2);
+  if (ccvt1 != ccvt2)
     return 0;
-
-  /* Check for mismatched thiscall types.  */
-  if (is_thiscall && !TARGET_RTD)
-    {
-      if (!lookup_attribute ("cdecl", TYPE_ATTRIBUTES (type1))
-         != !lookup_attribute ("cdecl", TYPE_ATTRIBUTES (type2)))
-       return 0;
-    }
-  else if (!is_thiscall || TARGET_RTD)
-    {
-      if (!lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type1))
-         != !lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type2)))
-       return 0;
-    }
-
-  /* Check for mismatched return types (cdecl vs stdcall).  */
-  if (!lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type1))
-      != !lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type2)))
+  if (ix86_function_regparm (type1, NULL)
+      != ix86_function_regparm (type2, NULL))
     return 0;
 
   return 1;
@@ -5528,23 +5519,26 @@ ix86_function_regparm (const_tree type, const_tree decl)
 {
   tree attr;
   int regparm;
+  unsigned int ccvt;
 
   if (TARGET_64BIT)
     return (ix86_function_type_abi (type) == SYSV_ABI
            ? X86_64_REGPARM_MAX : X86_64_MS_REGPARM_MAX);
-
+  ccvt = ix86_get_callcvt (type);
   regparm = ix86_regparm;
-  attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
-  if (attr)
+
+  if ((ccvt & IX86_CALLCVT_REGPARM) != 0)
     {
-      regparm = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
-      return regparm;
+      attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
+      if (attr)
+       {
+         regparm = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
+         return regparm;
+       }
     }
-
-  if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
+  else if ((ccvt & IX86_CALLCVT_FASTCALL) != 0)
     return 2;
-
-  if (ix86_is_type_thiscall (type))
+  else if ((ccvt & IX86_CALLCVT_THISCALL) != 0)
     return 1;
 
   /* Use register calling convention for local functions when possible.  */
@@ -5695,27 +5689,18 @@ ix86_keep_aggregate_return_pointer (tree fntype)
 static int
 ix86_return_pops_args (tree fundecl, tree funtype, int size)
 {
-  int rtd;
+  unsigned int ccvt;
 
   /* None of the 64-bit ABIs pop arguments.  */
   if (TARGET_64BIT)
     return 0;
 
-  rtd = TARGET_RTD && (!fundecl || TREE_CODE (fundecl) != IDENTIFIER_NODE);
+  ccvt = ix86_get_callcvt (funtype);
 
-  /* Cdecl functions override -mrtd, and never pop the stack.  */
-  if (! lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype)))
-    {
-      /* Stdcall and fastcall functions will pop the stack if not
-         variable args.  */
-      if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype))
-         || lookup_attribute ("fastcall", TYPE_ATTRIBUTES (funtype))
-          || ix86_is_type_thiscall (funtype))
-       rtd = 1;
-
-      if (rtd && ! stdarg_p (funtype))
-       return size;
-    }
+  if ((ccvt & (IX86_CALLCVT_STDCALL | IX86_CALLCVT_FASTCALL
+              | IX86_CALLCVT_THISCALL)) != 0
+      && ! stdarg_p (funtype))
+    return size;
 
   /* Lose any fake structure return argument if it is passed on the stack.  */
   if (aggregate_value_p (TREE_TYPE (funtype), fundecl)
@@ -5818,7 +5803,7 @@ ix86_reg_parm_stack_space (const_tree fndecl)
 enum calling_abi
 ix86_function_type_abi (const_tree fntype)
 {
-  if (fntype != NULL)
+  if (fntype != NULL_TREE && TYPE_ATTRIBUTES (fntype) != NULL_TREE)
     {
       enum calling_abi abi = ix86_abi;
       if (abi == SYSV_ABI)
@@ -6048,12 +6033,13 @@ init_cumulative_args (CUMULATIVE_ARGS *cum,  /* Argument info to initialize */
         else look for regparm information.  */
       if (fntype)
        {
-         if (ix86_is_type_thiscall (fntype))
+         unsigned int ccvt = ix86_get_callcvt (fntype);
+         if ((ccvt & IX86_CALLCVT_THISCALL) != 0)
            {
              cum->nregs = 1;
              cum->fastcall = 1; /* Same first register as in fastcall.  */
            }
-         else if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype)))
+         else if ((ccvt & IX86_CALLCVT_FASTCALL) != 0)
            {
              cum->nregs = 2;
              cum->fastcall = 1;
@@ -9839,13 +9825,13 @@ find_drap_reg (void)
 
       /* Reuse static chain register if it isn't used for parameter
          passing.  */
-      if (ix86_function_regparm (TREE_TYPE (decl), decl) <= 2
-         && !lookup_attribute ("fastcall",
-                               TYPE_ATTRIBUTES (TREE_TYPE (decl)))
-         && !ix86_is_type_thiscall (TREE_TYPE (decl)))
-       return CX_REG;
-      else
-       return DI_REG;
+      if (ix86_function_regparm (TREE_TYPE (decl), decl) <= 2)
+       {
+         unsigned int ccvt = ix86_get_callcvt (TREE_TYPE (decl));
+         if ((ccvt & (IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL)) == 0)
+           return CX_REG;
+       }
+      return DI_REG;
     }
 }
 
@@ -23283,20 +23269,19 @@ ix86_static_chain (const_tree fndecl, bool incoming_p)
   else
     {
       tree fntype;
+      unsigned int ccvt;
+
       /* By default in 32-bit mode we use ECX to pass the static chain.  */
       regno = CX_REG;
 
       fntype = TREE_TYPE (fndecl);
-      if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype)))
+      ccvt = ix86_get_callcvt (fntype);
+      if ((ccvt & (IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL)) != 0)
        {
          /* Fastcall functions use ecx/edx for arguments, which leaves
-            us with EAX for the static chain.  */
-         regno = AX_REG;
-       }
-      else if (ix86_is_type_thiscall (fntype))
-       {
-         /* Thiscall functions use ecx for arguments, which leaves
-            us with EAX for the static chain.  */
+            us with EAX for the static chain.
+            Thiscall functions use ecx for arguments, which also
+            leaves us with EAX for the static chain.  */
          regno = AX_REG;
        }
       else if (ix86_function_regparm (fntype, fndecl) == 3)
@@ -29847,10 +29832,11 @@ x86_this_parameter (tree function)
   if (nregs > 0 && !stdarg_p (type))
     {
       int regno;
+      unsigned int ccvt = ix86_get_callcvt (type);
 
-      if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
+      if ((ccvt & IX86_CALLCVT_FASTCALL) != 0)
        regno = aggr ? DX_REG : CX_REG;
-      else if (ix86_is_type_thiscall (type))
+      else if ((ccvt & IX86_CALLCVT_THISCALL) != 0)
         {
          regno = CX_REG;
          if (aggr)
@@ -29967,9 +29953,8 @@ x86_output_mi_thunk (FILE *file,
       else
        {
          int tmp_regno = CX_REG;
-         if (lookup_attribute ("fastcall",
-                               TYPE_ATTRIBUTES (TREE_TYPE (function)))
-             || ix86_is_type_thiscall (TREE_TYPE (function)))
+         unsigned int ccvt = ix86_get_callcvt (TREE_TYPE (function));
+         if ((ccvt & (IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL)) != 0)
            tmp_regno = AX_REG;
          tmp = gen_rtx_REG (SImode, tmp_regno);
        }
index c7f3bd4dc6d47f809b9b6efa7caacd7711a7948b..511429a727a4cfe7f46f20f7095136c43990b3d8 100644 (file)
@@ -2368,6 +2368,18 @@ extern void debug_dispatch_window (int);
        ((VALUE) = GET_MODE_BITSIZE (MODE), TARGET_BMI)
 
 
+/* Flags returned by ix86_get_callcvt ().  */
+#define IX86_CALLCVT_CDECL     0x1
+#define IX86_CALLCVT_STDCALL   0x2
+#define IX86_CALLCVT_FASTCALL  0x4
+#define IX86_CALLCVT_THISCALL  0x8
+#define IX86_CALLCVT_REGPARM   0x10
+#define IX86_CALLCVT_SSEREGPARM        0x20
+
+#define IX86_BASE_CALLCVT(FLAGS) \
+       ((FLAGS) & (IX86_CALLCVT_CDECL | IX86_CALLCVT_STDCALL \
+                   | IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL))
+
 /*
 Local variables:
 version-control: t
index 2232dbf6e51170285dd9ca19194a736b0ae59cbf..80f26f88aecddfa6e16bd734154d7344ca6ac0f3 100644 (file)
@@ -148,12 +148,20 @@ i386_nlm_maybe_mangle_decl_assembler_name (tree decl, tree id)
 {
   tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));
   tree new_id;
+  unsigned int ccvt = ix86_get_callcvt (TREE_TYPE (decl));
 
-  if (lookup_attribute ("stdcall", type_attributes))
-    new_id = gen_stdcall_or_fastcall_decoration (decl, id, '_');
-  else if (lookup_attribute ("fastcall", type_attributes))
+  if ((ccvt & IX86_CALLCVT_STDCALL) != 0)
+    {
+      if (TARGET_RTD)
+       /* If we are using -mrtd emit undecorated symbol and let linker
+          do the proper resolving.  */
+       return NULL_TREE;
+      new_id = gen_stdcall_or_fastcall_decoration (decl, id, '_');
+    }
+  else if ((ccvt & IX86_CALLCVT_FASTCALL) != 0)
     new_id = gen_stdcall_or_fastcall_decoration (decl, id, FASTCALL_PREFIX);
-  else if ((new_id = lookup_attribute ("regparm", type_attributes)))
+  else if ((cvt & IX86_CALLCVT_REGPARM) != 0
+          && (new_id = lookup_attribute ("regparm", type_attributes)))
     new_id = gen_regparm_prefix (decl, id,
                  TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (new_id))));
   else
index 169832fd36a954f0076b1357e5af6cc26f7bb85c..8e7043f1fe524d98e8ab43b3c3c6d3676ef72d07 100644 (file)
@@ -170,7 +170,7 @@ gen_stdcall_or_fastcall_suffix (tree decl, tree id, bool fastcall)
   HOST_WIDE_INT total = 0;
   const char *old_str = IDENTIFIER_POINTER (id != NULL_TREE ? id : DECL_NAME (decl));
   char *new_str, *p;
-  tree type = TREE_TYPE (decl);
+  tree type = TREE_TYPE (DECL_ORIGIN (decl));
   tree arg;
   function_args_iterator args_iter;
 
@@ -202,7 +202,8 @@ gen_stdcall_or_fastcall_suffix (tree decl, tree id, bool fastcall)
                       / parm_boundary_bytes * parm_boundary_bytes);
          total += parm_size;
        }
-      }
+    }
+
   /* Assume max of 8 base 10 digits in the suffix.  */
   p = new_str = XALLOCAVEC (char, 1 + strlen (old_str) + 1 + 8 + 1);
   if (fastcall)
@@ -222,10 +223,16 @@ i386_pe_maybe_mangle_decl_assembler_name (tree decl, tree id)
 
   if (TREE_CODE (decl) == FUNCTION_DECL)
     { 
-      tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));
-      if (lookup_attribute ("stdcall", type_attributes))
-       new_id = gen_stdcall_or_fastcall_suffix (decl, id, false);
-      else if (lookup_attribute ("fastcall", type_attributes))
+      unsigned int ccvt = ix86_get_callcvt (TREE_TYPE (decl));
+      if ((ccvt & IX86_CALLCVT_STDCALL) != 0)
+        {
+         if (TARGET_RTD)
+           /* If we are using -mrtd emit undecorated symbol and let linker
+              do the proper resolving.  */
+           return NULL_TREE;
+         new_id = gen_stdcall_or_fastcall_suffix (decl, id, false);
+       }
+      else if ((ccvt & IX86_CALLCVT_FASTCALL) != 0)
        new_id = gen_stdcall_or_fastcall_suffix (decl, id, true);
     }