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]

Re: RFA: handling of mode attribute


2009/9/27 Richard Guenther <richard.guenther@gmail.com>:
> On Sun, Sep 27, 2009 at 12:26 PM, Kai Tietz <ktietz70@googlemail.com> wrote:
>> 2009/9/27 Richard Guenther <richard.guenther@gmail.com>:
>>> On Sun, Sep 27, 2009 at 9:57 AM, Kai Tietz <ktietz70@googlemail.com> wrote:
>>>>
>>>> Hello Joseph,
>>>>
>>>> well the issue described in 32187 is related. I want to use base type
>>>> mode specifiers to have an ability to provide for mingw x64 target
>>>> __int128 type and also for 32-bit mingw targets the types __int8,
>>>> __int16, __int32, and __int64. I spoke here with Ian about this, as we
>>>> would have here also the possibility to extend C/C++ FE keywords, but
>>>> we both came to the opinion that it would be better to be able to
>>>> implement them as pre-defined macros. The patch I attached could be
>>>> used for the __float128 type, too.
>>>>
>>>> As the "mode" attribute can't be changed, I rewrote my patch to use
>>>> attribute "basetype_mode". Major difference between the "mode"
>>>> attribute is, that it always associate to the base type, not to the
>>>> current type declaration.
>>>> Additionally it does not support vector types.
>>>
>>> I'm not really convinced that this will work (nor do I think this is the
>>> best solution).
>>
>> Well, it seems to work as well (as the vector_size attribute works).
>> The best way for sure would be to have ability in C/C++ FE to specify
>> target specific types. But as the signed/unsigned/__complex__ checks
>> aren't designed for this, and builtin-types are based to RID_...
>> constants, it looks for me at the moment as the best way to go.
>> The same mechanism would solve also the issues about float DFmode
>> types, where some issues about the __complex__ extension are present,
>> as typedefs can't get additional base type attributes.
>>
>>> Try to at least conver more cases in your testcase, like for example
>>>
>>> ?const attr_int64 *p
>>>
>>> or
>>>
>>> ?unsigned attr_int64 * const p,
>>
>> Well, I can add const/volatile pointer things here to test-case, if
>> you think it is necessary. But I don't think that here something
>> special will happen, as vector types would have then the same issues
>> AFAICS.
>>
>>> I'd even suggest to run the compile torture with -Dint=__int32
>>>
>>> You only need the modes for types where you do not have a
>>> keyword specifier, right? ?Which means just TImode ints? ?Wouldn't it make
>>> sense to instead add new keywords to C that corresponds to that,
>>> like __long_long_long?
>>
>> Hmm, well. TImode was the initial point, but even to express __int8,
>> __int16, etc via this attribute can make sense here, as for example
>> this prevents checks in gcc related to real 'long long' types.
>
> __int8 should map to char, __int16 to short. ?I don't see the issue here.
> After all if the result should behave as a builtin type it better should be one.
>
> Richard.
>

So I ran c-torture by defining int as 'int __attribute__
((basetype_mode(SI)))'. While running it there were no special failure
by this (beside for those testcases using __attribute__ ((mode(XX)))
on a int type (what was to be expecting).

I extend the testcase to use some cases with const and volatile
keywords for integer using basetype_mode attribute.

Cheers,
Kai
-- 
|  (\_/) This is Bunny. Copy and paste
| (='.'=) Bunny into your signature to help
| (")_(") him gain world domination
Index: gcc/gcc/c-common.c
===================================================================
--- gcc.orig/gcc/c-common.c	2009-09-27 09:25:32.396178000 +0200
+++ gcc/gcc/c-common.c	2009-09-27 09:26:57.668178200 +0200
@@ -499,6 +499,7 @@
 static tree handle_constructor_attribute (tree *, tree, tree, int, bool *);
 static tree handle_destructor_attribute (tree *, tree, tree, int, bool *);
 static tree handle_mode_attribute (tree *, tree, tree, int, bool *);
+static tree handle_basetype_mode_attribute (tree *, tree, tree, int, bool *);
 static tree handle_section_attribute (tree *, tree, tree, int, bool *);
 static tree handle_aligned_attribute (tree *, tree, tree, int, bool *);
 static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
@@ -762,6 +763,8 @@
 			      handle_destructor_attribute },
   { "mode",                   1, 1, false,  true, false,
 			      handle_mode_attribute },
+  { "basetype_mode",	      1, 1, false, true, false,
+			      handle_basetype_mode_attribute },
   { "section",                1, 1, true,  false, false,
 			      handle_section_attribute },
   { "aligned",                0, 1, false, false, false,
@@ -6350,6 +6353,166 @@
   return NULL_TREE;
 }
 
+/* Handle a "basetype_mode" attribute; arguments as in
+   struct attribute_spec.handler.
+   Note: Difference to "mode" attribute is, that it
+   gets always associated to the base type.  */
+
+static tree
+handle_basetype_mode_attribute (tree *node, tree name, tree args,
+				int ARG_UNUSED (flags),
+				bool *no_add_attrs)
+{
+  tree type = *node;
+  tree ident = TREE_VALUE (args);
+
+  while (POINTER_TYPE_P (type)
+         || TREE_CODE (type) == FUNCTION_TYPE
+         || TREE_CODE (type) == METHOD_TYPE
+         || TREE_CODE (type) == ARRAY_TYPE
+         || TREE_CODE (type) == OFFSET_TYPE)
+    type = TREE_TYPE (type);
+
+  *no_add_attrs = true;
+
+  if (TREE_CODE (ident) != IDENTIFIER_NODE)
+    warning (OPT_Wattributes, "%qE attribute ignored", name);
+  else
+    {
+      int j;
+      const char *p = IDENTIFIER_POINTER (ident);
+      int len = strlen (p);
+      enum machine_mode mode = VOIDmode;
+      tree typefm;
+      bool valid_mode;
+
+      if (len > 4 && p[0] == '_' && p[1] == '_'
+          && p[len - 1] == '_' && p[len - 2] == '_')
+        {
+          char *newp = (char *) alloca (len - 1);
+
+          strcpy (newp, &p[2]);
+          newp[len - 4] = '\0';
+          p = newp;
+        }
+
+      /* Change this type to have a type with the specified mode.
+         First check for the special modes.  */
+      if (!strcmp (p, "byte"))
+        mode = byte_mode;
+      else if (!strcmp (p, "word"))
+        mode = word_mode;
+      else if (!strcmp (p, "pointer"))
+        mode = ptr_mode;
+      else if (!strcmp (p, "libgcc_cmp_return"))
+        mode = targetm.libgcc_cmp_return_mode ();
+      else if (!strcmp (p, "libgcc_shift_count"))
+        mode = targetm.libgcc_shift_count_mode ();
+      else if (!strcmp (p, "unwind_word"))
+        mode = targetm.unwind_word_mode ();
+      else
+        for (j = 0; j < NUM_MACHINE_MODES; j++)
+          if (!strcmp (p, GET_MODE_NAME (j)))
+            {
+              mode = (enum machine_mode) j;
+              break;
+            }
+
+      if (mode == VOIDmode)
+        {
+          error ("unknown machine mode %qE", ident);
+          return NULL_TREE;
+        }
+
+      valid_mode = false;
+      switch (GET_MODE_CLASS (mode))
+        {
+        case MODE_INT:
+        case MODE_PARTIAL_INT:
+        case MODE_FLOAT:
+        case MODE_DECIMAL_FLOAT:
+        case MODE_FRACT:
+        case MODE_UFRACT:
+        case MODE_ACCUM:
+        case MODE_UACCUM:
+          valid_mode = targetm.scalar_mode_supported_p (mode);
+          break;
+
+        case MODE_COMPLEX_INT:
+        case MODE_COMPLEX_FLOAT:
+          valid_mode = targetm.scalar_mode_supported_p (GET_MODE_INNER (mode));
+          break;
+
+        default:
+          break;
+        }
+      if (!valid_mode)
+        {
+          error ("unable to emulate %qs", p);
+          return NULL_TREE;
+	}
+      /* For fixed-point modes, we need to test if the signness of type
+         and the machine mode are consistent.  */
+      if (ALL_FIXED_POINT_MODE_P (mode)
+          && TYPE_UNSIGNED (type) != UNSIGNED_FIXED_POINT_MODE_P (mode))
+        {
+          error ("signness of type and machine mode %qs don't match", p);
+          return NULL_TREE;
+        }
+      /* For fixed-point modes, we need to pass saturating info.  */
+      typefm = lang_hooks.types.type_for_mode (mode,
+               ALL_FIXED_POINT_MODE_P (mode) ? TYPE_SATURATING (type)
+                                             : TYPE_UNSIGNED (type));
+
+      if (typefm == NULL_TREE)
+        {
+          error ("no data type for mode %qs", p);
+          return NULL_TREE;
+        }
+      else if (TREE_CODE (type) == ENUMERAL_TYPE)
+        {
+          /* For enumeral types, copy the precision from the integer
+             type returned above.  If not an INTEGER_TYPE, we can't use
+             this mode for this type.  */
+          if (TREE_CODE (typefm) != INTEGER_TYPE)
+            {
+              error ("cannot use mode %qs for enumeral types", p);
+              return NULL_TREE;
+            }
+
+          if (flags & ATTR_FLAG_TYPE_IN_PLACE)
+            {
+              TYPE_PRECISION (type) = TYPE_PRECISION (typefm);
+              typefm = type;
+            }
+          else
+            {
+              /* We cannot build a type variant, as there's code that assumes
+                 that TYPE_MAIN_VARIANT has the same mode.  This includes the
+                 debug generators.  Instead, create a subrange type.  This
+                 results in all of the enumeral values being emitted only once
+                 in the original, and the subtype gets them by reference.  */
+              if (TYPE_UNSIGNED (type))
+                typefm = make_unsigned_type (TYPE_PRECISION (typefm));
+              else
+                typefm = make_signed_type (TYPE_PRECISION (typefm));
+              TREE_TYPE (typefm) = type;
+            }
+        }
+      else if (VECTOR_MODE_P (mode)
+               ? TREE_CODE (type) != TREE_CODE (TREE_TYPE (typefm))
+               : TREE_CODE (type) != TREE_CODE (typefm))
+        {
+          error ("mode %qs applied to inappropriate type", p);
+          return NULL_TREE;
+        }
+
+      *node = lang_hooks.types.reconstruct_complex_type (*node, typefm);
+    }
+
+  return NULL_TREE;
+}
+
 /* Handle a "mode" attribute; arguments as in
    struct attribute_spec.handler.  */
 
Index: gcc/gcc/testsuite/gcc.c-torture/execute/attribute_mode.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/gcc/testsuite/gcc.c-torture/execute/attribute_mode.c	2009-09-27 13:36:34.105486300 +0200
@@ -0,0 +1,52 @@
+__extension__ typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+extern int memcmp (const void *, const void *, size_t);
+
+#define attr_int64 int __attribute__ ((basetype_mode(DI)))
+
+attr_int64
+foo (unsigned attr_int64 b)
+{
+  return ((attr_int64) b);
+}
+
+attr_int64
+foo2 (unsigned attr_int64 * const b)
+{
+  return (attr_int64) (*b);
+}
+
+int
+foo3 (const unsigned attr_int64 a, volatile const attr_int64 * const b)
+{
+  return (*b != a ? 0 : 1);
+}
+
+void
+bar (unsigned attr_int64 b[4])
+{
+  b[1]=0LL; b[0]=1LL; b[2]=2LL; b[3]=5LL;
+}
+
+unsigned int tab1[8] = {
+  1, 0, 0, 0, 2, 0, 5, 0
+};
+
+int
+main ()
+{
+  unsigned attr_int64 a[4];
+  if (sizeof (a) != 32)
+    abort ();
+  if (foo (1ULL) != 1LL)
+    abort ();
+  bar (a);
+  if (memcmp (a, tab1, 32) != 0)
+    abort ();
+  if (foo2 (&a[0]) != 1LL)
+    abort ();
+  if (foo3 (2ULL, &a[2]) == 0)
+    abort ();
+  return 0;
+}
+
Index: gcc/gcc/doc/extend.texi
===================================================================
--- gcc.orig/gcc/doc/extend.texi	2009-09-27 09:25:32.401178000 +0200
+++ gcc/gcc/doc/extend.texi	2009-09-27 09:26:57.713178200 +0200
@@ -4002,6 +4002,23 @@
 @samp{__word__} for the mode of a one-word integer, and @samp{pointer}
 or @samp{__pointer__} for the mode used to represent pointers.
 
+@item basetype_mode (@var{mode})
+@cindex @code{basetype_mode} attribute
+This attribute specifies the base data type for the declaration
+---whichever type corresponds to the mode @var{mode}.  This in effect
+lets you request an integer or floating point type according to its
+width.
+
+You may also specify a mode of @samp{byte} or @samp{__byte__} to
+indicate the mode corresponding to a one-byte integer, @samp{word} or
+@samp{__word__} for the mode of a one-word integer, and @samp{pointer}
+or @samp{__pointer__} for the mode used to represent pointers.
+
+Difference to @code{mode} attribute is, that it always gets associated
+to the base type, and not to the current type with modifiers. Additionally
+aren't vector modes allowed here. For vector modes, see @code{vector_size}
+attribute.
+
 @item packed
 @cindex @code{packed} attribute
 The @code{packed} attribute specifies that a variable or structure field

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