(root)/
gcc-13.2.0/
gcc/
attr-fnspec.h
       1  /* Handling of fnspec attribute specifiers
       2     Copyright (C) 2008-2023 Free Software Foundation, Inc.
       3     Contributed by Richard Guenther  <rguenther@suse.de>
       4  
       5     This file is part of GCC.
       6  
       7     GCC is free software; you can redistribute it and/or modify
       8     under the terms of the GNU General Public License as published by
       9     the Free Software Foundation; either version 3 of the License, or
      10     (at your option) any later version.
      11  
      12     GCC is distributed in the hope that it will be useful,
      13     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15     GNU General Public License for more details.
      16  
      17     You should have received a copy of the GNU General Public License
      18     along with GCC; see the file COPYING3.  If not see
      19     <http://www.gnu.org/licenses/>.  */
      20  
      21  /* Parse string of attribute "fn spec".  This is an internal attribute
      22     describing side effects of a function as follows:
      23  
      24     character 0  specifies properties of return values as follows:
      25       '1'...'4'  specifies number of argument function returns (as in memset)
      26       'm'	specifies that returned value is noalias (as in malloc)
      27       '.'	specifies that nothing is known.
      28     character 1  specifies additional function properties
      29       ' '        specifies that nothing is known
      30       'p' or 'P' specifies that function is pure except for described side
      31  		effects.
      32       'c' or 'C' specifies that function is const except for described side
      33  		effects.
      34     The uppercase letter in addition specifies that function clobbers errno.
      35  
      36     character 2+2i specifies properties of argument number i as follows:
      37       'x' or 'X' specifies that parameter is unused.
      38       'r' or 'R' specifies that the memory pointed to by the parameter is only
      39  		read and does not escape
      40       'o' or 'O' specifies that the memory pointed to by the parameter is only
      41  		written and does not escape
      42       'w' or 'W' specifies that the memory pointed to by the parameter does not
      43  		escape
      44       '1'....'9' specifies that the memory pointed to by the parameter is
      45  		copied to memory pointed to by different parameter
      46  		(as in memcpy).
      47       '.'	specifies that nothing is known.
      48     The uppercase letter in addition specifies that the memory pointed to
      49     by the parameter is not dereferenced.  For 'r' only read applies
      50     transitively to pointers read from the pointed-to memory.
      51  
      52     character 3+2i specifies additional properties of argument number i
      53     as follows:
      54       ' '        nothing is known
      55       't'	the size of value written/read corresponds to the size of
      56  		of the pointed-to type of the argument type
      57       '1'...'9'  specifies the size of value written/read is bound by the
      58  		specified argument
      59   */
      60  
      61  #ifndef ATTR_FNSPEC_H
      62  #define ATTR_FNSPEC_H
      63  
      64  class attr_fnspec
      65  {
      66  private:
      67    /* fn spec attribute string.  */
      68    const char *str;
      69    /* length of the fn spec string.  */
      70    const unsigned len;
      71    /* Number of characters specifying return value.  */
      72    const unsigned int return_desc_size = 2;
      73    /* Number of characters specifying size.  */
      74    const unsigned int arg_desc_size = 2;
      75  
      76    /* Return start of specifier of arg i.  */
      77    unsigned int arg_idx (int i)
      78    {
      79      return return_desc_size + arg_desc_size * i;
      80    }
      81  
      82  public:
      83    attr_fnspec (const char *str, unsigned len)
      84    : str (str), len (len)
      85    {
      86      if (flag_checking)
      87        verify ();
      88    }
      89    attr_fnspec (const char *str)
      90    : str (str), len (strlen (str))
      91    {
      92      if (flag_checking)
      93        verify ();
      94    }
      95    attr_fnspec (const_tree identifier)
      96    : str (TREE_STRING_POINTER (identifier)),
      97      len (TREE_STRING_LENGTH (identifier))
      98    {
      99      if (flag_checking)
     100        verify ();
     101    }
     102    attr_fnspec ()
     103    : str (NULL), len (0)
     104    {
     105    }
     106  
     107    /* Return true if fn spec is known.  */
     108    bool
     109    known_p ()
     110    {
     111      return len;
     112    }
     113  
     114    /* Return true if arg I is specified.  */
     115    bool
     116    arg_specified_p (unsigned int i)
     117    {
     118      return len >= arg_idx (i + 1);
     119    }
     120  
     121    /* True if the argument is not dereferenced recursively, thus only
     122       directly reachable memory is read or written.  */
     123    bool
     124    arg_direct_p (unsigned int i)
     125    {
     126      unsigned int idx = arg_idx (i);
     127      gcc_checking_assert (arg_specified_p (i));
     128      return str[idx] == 'R' || str[idx] == 'O'
     129  	   || str[idx] == 'W' || (str[idx] >= '1' && str[idx] <= '9');
     130    }
     131  
     132    /* True if argument is used.  */
     133    bool
     134    arg_used_p (unsigned int i)
     135    {
     136      unsigned int idx = arg_idx (i);
     137      gcc_checking_assert (arg_specified_p (i));
     138      return str[idx] != 'x' && str[idx] != 'X';
     139    }
     140  
     141    /* True if memory reached by the argument is readonly (not clobbered).  */
     142    bool
     143    arg_readonly_p (unsigned int i)
     144    {
     145      unsigned int idx = arg_idx (i);
     146      gcc_checking_assert (arg_specified_p (i));
     147      return str[idx] == 'r' || str[idx] == 'R' || (str[idx] >= '1' && str[idx] <= '9');
     148    }
     149  
     150    /* True if memory reached by the argument is read (directly or indirectly)  */
     151    bool
     152    arg_maybe_read_p (unsigned int i)
     153    {
     154      unsigned int idx = arg_idx (i);
     155      gcc_checking_assert (arg_specified_p (i));
     156      return str[idx] != 'o' && str[idx] != 'O'
     157  	   && str[idx] != 'x' && str[idx] != 'X';
     158    }
     159  
     160    /* True if memory reached by the argument is written.
     161       (directly or indirectly)  */
     162    bool
     163    arg_maybe_written_p (unsigned int i)
     164    {
     165      unsigned int idx = arg_idx (i);
     166      gcc_checking_assert (arg_specified_p (i));
     167      return str[idx] != 'r' && str[idx] != 'R'
     168  	   && (str[idx] < '1' || str[idx] > '9')
     169  	   && str[idx] != 'x' && str[idx] != 'X';
     170    }
     171  
     172    /* Return true if load of memory pointed to by argument I is bound
     173       by another argument.  In this case set ARG.  */
     174    bool
     175    arg_max_access_size_given_by_arg_p (unsigned int i, unsigned int *arg)
     176    {
     177      unsigned int idx = arg_idx (i);
     178      gcc_checking_assert (arg_specified_p (i));
     179      if (str[idx + 1] >= '1' && str[idx + 1] <= '9')
     180        {
     181  	*arg = str[idx + 1] - '1';
     182  	return true;
     183        }
     184      else
     185        return false;
     186    }
     187  
     188    /* Return true if the pointed-to type of the argument correspond to the
     189       size of the memory acccess.  */
     190    bool
     191    arg_access_size_given_by_type_p (unsigned int i)
     192    {
     193      unsigned int idx = arg_idx (i);
     194      gcc_checking_assert (arg_specified_p (i));
     195      return str[idx + 1] == 't';
     196    }
     197  
     198    /* Return true if memory pointer to by argument is copied to a memory
     199       pointed to by a different argument (as in memcpy).
     200       In this case set ARG.  */
     201    bool
     202    arg_copied_to_arg_p (unsigned int i, unsigned int *arg)
     203    {
     204      unsigned int idx = arg_idx (i);
     205      gcc_checking_assert (arg_specified_p (i));
     206      if (str[idx] < '1' || str[idx] > '9')
     207        return false;
     208      *arg = str[idx] - '1';
     209      return true;
     210    }
     211  
     212  
     213    /* True if the argument does not escape.  */
     214    bool
     215    arg_noescape_p (unsigned int i)
     216    {
     217      unsigned int idx = arg_idx (i);
     218      gcc_checking_assert (arg_specified_p (i));
     219      return str[idx] == 'w' || str[idx] == 'W'
     220  	   || str[idx] == 'r' || str[idx] == 'R'
     221  	   || str[idx] == 'o' || str[idx] == 'O';
     222    }
     223  
     224    /* Return true if function returns value of its parameter.  If ARG_NO is
     225       non-NULL return initialize it to the argument returned.  */
     226    bool
     227    returns_arg (unsigned int *arg_no)
     228    {
     229      if (str[0] >= '1' && str[0] <= '4')
     230        {
     231  	if (arg_no)
     232  	  *arg_no = str[0] - '1';
     233  	return true;
     234        }
     235      return false;
     236    }
     237  
     238    /* Nonzero if the return value does not alias with anything.  Functions
     239       with the malloc attribute have this set on their return value.  */
     240    bool
     241    returns_noalias_p ()
     242    {
     243      return str[0] == 'm';
     244    }
     245  
     246    /* Return true if all memory read by the function is specified by fnspec.  */
     247    bool
     248    global_memory_read_p ()
     249    {
     250      return str[1] != 'c' && str[1] != 'C';
     251    }
     252  
     253    /* Return true if all memory written by the function
     254       is specified by fnspec.  */
     255    bool
     256    global_memory_written_p ()
     257    {
     258      return str[1] != 'c' && str[1] != 'C' && str[1] != 'p' && str[1] != 'P';
     259    }
     260  
     261    bool
     262    errno_maybe_written_p ()
     263    {
     264      return str[1] == 'C' || str[1] == 'P';
     265    }
     266  
     267    /* Return EAF flags for arg I.  */
     268    int
     269    arg_eaf_flags (unsigned int i)
     270    {
     271      int flags = 0;
     272  
     273      if (!arg_specified_p (i))
     274        ;
     275      else if (!arg_used_p (i))
     276        flags = EAF_UNUSED;
     277      else
     278        {
     279  	if (arg_direct_p (i))
     280  	  flags |= EAF_NO_INDIRECT_READ | EAF_NO_INDIRECT_ESCAPE
     281  		   | EAF_NOT_RETURNED_INDIRECTLY | EAF_NO_INDIRECT_CLOBBER;
     282  	if (arg_noescape_p (i))
     283  	  flags |= EAF_NO_DIRECT_ESCAPE | EAF_NO_INDIRECT_ESCAPE;
     284  	if (arg_readonly_p (i))
     285  	  flags |= EAF_NO_DIRECT_CLOBBER | EAF_NO_INDIRECT_CLOBBER;
     286        }
     287      return flags;
     288    }
     289  
     290    /* Check validity of the string.  */
     291    void verify ();
     292  
     293    /* Return the fnspec string.  */
     294    const char *
     295    get_str ()
     296    {
     297      return str;
     298    }
     299  };
     300  
     301  extern attr_fnspec gimple_call_fnspec (const gcall *stmt);
     302  extern attr_fnspec builtin_fnspec (tree);
     303  
     304  #endif /* ATTR_FNSPEC_H  */