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]

Pure function attribute


Hi
Here is patch to add function attribute "pure" to represent, that it have
no side effects.  It use SIDE_EFFECTS field to represent it and my second
patch handle it in calls.c to emit corresponding rtl code.
I've also got rid of build_type_variant on various places in c frontend
to ensure, that pure flag is not lost.

Sat Aug 21 16:18:20 EDT 1999  Jan Hubicka  <hubicka@freesoft.cz>
	* c-common.c (enum attrs): Add A_PURE.
	(init_attribute): Add attribute "pure".
	(decl_attribytes): Call build_qualified_types instead of
	build_type_variant. Handle A_PURE attribute.
	* c-typeck.c (build_function_call): Call build_qualified_type
	instead of buid_type_variant.
	(build_unary_op): Likewise.
	* extend.texi (Function Attributes) Document attribute "pure".
	* tree.h (TYPE_SIDE_EFFECTS): New macro.
	(TYPE_QUAL_PURE): New.
	(TYPE_QUALS): Handle TYPE_QUAL_PURE.
	* tree.c (set_type_quals): Handle TYPE_QUAL_PURE.

*** c-common.c.nopure	Sat Aug 21 12:04:43 1999
--- c-common.c	Sat Aug 21 12:33:54 1999
*************** int skip_evaluation;
*** 144,150 ****
  enum attrs {A_PACKED, A_NOCOMMON, A_COMMON, A_NORETURN, A_CONST, A_T_UNION,
  	    A_NO_CHECK_MEMORY_USAGE, A_NO_INSTRUMENT_FUNCTION,
  	    A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED,
! 	    A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS};
  
  enum format_type { printf_format_type, scanf_format_type,
  		   strftime_format_type };
--- 144,150 ----
  enum attrs {A_PACKED, A_NOCOMMON, A_COMMON, A_NORETURN, A_CONST, A_T_UNION,
  	    A_NO_CHECK_MEMORY_USAGE, A_NO_INSTRUMENT_FUNCTION,
  	    A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED,
! 	    A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS, A_PURE};
  
  enum format_type { printf_format_type, scanf_format_type,
  		   strftime_format_type };
*************** init_attributes ()
*** 484,489 ****
--- 484,490 ----
    add_attribute (A_ALIAS, "alias", 1, 1, 1);
    add_attribute (A_NO_INSTRUMENT_FUNCTION, "no_instrument_function", 0, 0, 1);
    add_attribute (A_NO_CHECK_MEMORY_USAGE, "no_check_memory_usage", 0, 0, 1);
+   add_attribute (A_PURE, "pure", 0, 0, 1);
  }
  
  /* Default implementation of valid_lang_attribute, below.  By default, there
*************** decl_attributes (node, attributes, prefi
*** 614,621 ****
  		   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
  	    TREE_TYPE (decl) = type
  	      = build_pointer_type
! 		(build_type_variant (TREE_TYPE (type),
! 				     TREE_READONLY (TREE_TYPE (type)), 1));
  	  else
  	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
  	  break;
--- 615,623 ----
  		   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
  	    TREE_TYPE (decl) = type
  	      = build_pointer_type
! 		(build_qualified_type (TREE_TYPE (type),
! 				       TYPE_QUAL_VOLATILE 
! 				       | TYPE_QUALS (type)));
  	  else
  	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
  	  break;
*************** decl_attributes (node, attributes, prefi
*** 639,646 ****
  		   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
  	    TREE_TYPE (decl) = type
  	      = build_pointer_type
! 		(build_type_variant (TREE_TYPE (type), 1,
! 				     TREE_THIS_VOLATILE (TREE_TYPE (type))));
  	  else
  	    warning ( "`%s' attribute ignored", IDENTIFIER_POINTER (name));
  	  break;
--- 641,663 ----
  		   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
  	    TREE_TYPE (decl) = type
  	      = build_pointer_type
! 		(build_qualified_type (TREE_TYPE (type),
! 				       TYPE_QUAL_CONST 
! 				       | TYPE_QUALS (type)));
! 	  else
! 	    warning ( "`%s' attribute ignored", IDENTIFIER_POINTER (name));
! 	  break;
! 
! 	case A_PURE:
! 	  if (TREE_CODE (decl) == FUNCTION_DECL)
! 	    TREE_SIDE_EFFECTS (decl) = 0;
! 	  else if (TREE_CODE (type) == POINTER_TYPE
! 		   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
! 	    TREE_TYPE (decl) = type
! 	      = build_pointer_type
! 		(build_qualified_type (TREE_TYPE (type),
! 				       TYPE_QUAL_PURE 
! 				       | TYPE_QUALS (type)));
  	  else
  	    warning ( "`%s' attribute ignored", IDENTIFIER_POINTER (name));
  	  break;
*** c-typeck.c.nopure	Sat Aug 21 12:22:54 1999
--- c-typeck.c	Sat Aug 21 12:34:52 1999
*************** build_function_call (function, params)
*** 1460,1468 ****
        /* Differs from default_conversion by not setting TREE_ADDRESSABLE
  	 (because calling an inline function does not mean the function
  	 needs to be separately compiled).  */
!       fntype = build_type_variant (TREE_TYPE (function),
! 				   TREE_READONLY (function),
! 				   TREE_THIS_VOLATILE (function));
        fundecl = function;
        function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
      }
--- 1460,1467 ----
        /* Differs from default_conversion by not setting TREE_ADDRESSABLE
  	 (because calling an inline function does not mean the function
  	 needs to be separately compiled).  */
!       fntype = build_qualified_type (TREE_TYPE (function), 
! 				     TYPE_QUALS (function));
        fundecl = function;
        function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
      }
*************** build_unary_op (code, xarg, noconvert)
*** 3019,3027 ****
  	  || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
  	{
  	  if (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))
! 	    argtype = c_build_type_variant (argtype,
! 					    TREE_READONLY (arg),
! 					    TREE_THIS_VOLATILE (arg));
  	}
  
        argtype = build_pointer_type (argtype);
--- 3018,3025 ----
  	  || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
  	{
  	  if (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))
! 	    argtype = build_qualified_type (argtype,
! 			    		    TYPE_QUALS (arg));
  	}
  
        argtype = build_pointer_type (argtype);
*************** build_conditional_expr (ifexp, op1, op2)
*** 3469,3477 ****
  
    /* Merge const and volatile flags of the incoming types.  */
    result_type
!     = build_type_variant (result_type,
! 			  TREE_READONLY (op1) || TREE_READONLY (op2),
! 			  TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2));
  
    if (result_type != TREE_TYPE (op1))
      op1 = convert_and_check (result_type, op1);
--- 3467,3473 ----
  
    /* Merge const and volatile flags of the incoming types.  */
    result_type
!     = build_qualified_type (result_type, TYPE_QUALS (op1) | TYPE_QUALS (op2));
  
    if (result_type != TREE_TYPE (op1))
      op1 = convert_and_check (result_type, op1);
Binary files cccp.nopure and cccp differ
*** extend.texi.nopure	Sat Aug 21 12:31:20 1999
--- extend.texi	Sat Aug 21 12:50:46 1999
*************** carefully.
*** 1310,1316 ****
  The keyword @code{__attribute__} allows you to specify special
  attributes when making a declaration.  This keyword is followed by an
  attribute specification inside double parentheses.  Nine attributes,
! @code{noreturn}, @code{const}, @code{format},
  @code{no_instrument_function}, @code{section},
  @code{constructor}, @code{destructor}, @code{unused} and @code{weak} are
  currently defined for functions.  Other attributes, including
--- 1310,1316 ----
  The keyword @code{__attribute__} allows you to specify special
  attributes when making a declaration.  This keyword is followed by an
  attribute specification inside double parentheses.  Nine attributes,
! @code{noreturn}, @code{const}, @code{pure}, @code{format},
  @code{no_instrument_function}, @code{section},
  @code{constructor}, @code{destructor}, @code{unused} and @code{weak} are
  currently defined for functions.  Other attributes, including
*************** specifies that the @samp{const} must be 
*** 1396,1405 ****
  
  @cindex pointer arguments
  Note that a function that has pointer arguments and examines the data
! pointed to must @emph{not} be declared @code{const}.  Likewise, a
! function that calls a non-@code{const} function usually must not be
! @code{const}.  It does not make sense for a @code{const} function to
! return @code{void}.
  
  @item format (@var{archetype}, @var{string-index}, @var{first-to-check})
  @cindex @code{format} function attribute
--- 1396,1428 ----
  
  @cindex pointer arguments
  Note that a function that has pointer arguments and examines the data
! pointed to must @emph{not} be declared @code{const} (use the @code{pure}
! attribute bellow).  Likewise, a function that calls a non-@code{const}
! function usually must not be @code{const}.  It does not make sense for
! a @code{const} function to return @code{void}.
! 
! @cindex @code{pure} function attribute
! @item pure
! This attribute is similar to @code{const} function attribute except the
! function is allowed to read global memory.  Function still have to behave
! deterministically so for example @code{gettimeofday} don't belongs to this
! category.  Compiler still expect:
! @enumerate
! @item Function call can be ignored when return value is dead.
! @item Global memory may be cached in registers across function call.
! @item Two consetuctive calls of function will return same value if global
! memory visible to compiler is not touched. (So function reading volatile
! memory changed by another thread may not be @code{pure})
! @end enumerate
! Much more functions belongs to this category than to the @code{const}
! category and still it provides important hint for the compiler.
! These functions should be declared with the attribute @code{pure}.
! For example,
! 
! @smallexample
! int square (int) __attribute__ ((pure));
! @end smallexample
! 
  
  @item format (@var{archetype}, @var{string-index}, @var{first-to-check})
  @cindex @code{format} function attribute
*** tree.h.nopure	Sat Aug 21 13:37:59 1999
--- tree.h	Sat Aug 21 13:44:42 1999
*************** struct tree_block
*** 835,840 ****
--- 835,843 ----
  /* Means this type is const-qualified.  */
  #define TYPE_READONLY(NODE) ((NODE)->common.readonly_flag)
  
+ /* 0 Means this function type refers to pure function.  */
+ #define TYPE_SIDE_EFFECTS(NODE) ((NODE)->common.side_effects_flag)
+ 
  /* If nonzero, this type is `restrict'-qualified, in the C sense of
     the term.  */
  #define TYPE_RESTRICT(NODE) (TYPE_CHECK (NODE)->type.restrict_flag)
*************** struct tree_block
*** 847,857 ****
  #define TYPE_QUAL_CONST    0x1
  #define TYPE_QUAL_VOLATILE 0x2
  #define TYPE_QUAL_RESTRICT 0x4
  
  /* The set of type qualifiers for this type.  */
! #define TYPE_QUALS(NODE)			\
!   ((TYPE_READONLY(NODE) * TYPE_QUAL_CONST) |	\
!    (TYPE_VOLATILE(NODE) * TYPE_QUAL_VOLATILE) |	\
     (TYPE_RESTRICT(NODE) * TYPE_QUAL_RESTRICT))
  
  /* These flags are available for each language front end to use internally.  */
--- 850,862 ----
  #define TYPE_QUAL_CONST    0x1
  #define TYPE_QUAL_VOLATILE 0x2
  #define TYPE_QUAL_RESTRICT 0x4
+ #define TYPE_QUAL_PURE	   0x8
  
  /* The set of type qualifiers for this type.  */
! #define TYPE_QUALS(NODE)				\
!   ((TYPE_READONLY(NODE) * TYPE_QUAL_CONST) |		\
!    (TYPE_VOLATILE(NODE) * TYPE_QUAL_VOLATILE) |		\
!    ((!TYPE_SIDE_EFFECTS(NODE)) * TYPE_QUAL_PURE) |	\
     (TYPE_RESTRICT(NODE) * TYPE_QUAL_RESTRICT))
  
  /* These flags are available for each language front end to use internally.  */
*** tree.c.nopure	Sat Aug 21 12:13:51 1999
--- tree.c	Sat Aug 21 12:14:02 1999
*************** set_type_quals (type, type_quals)
*** 3617,3622 ****
--- 3617,3623 ----
    TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0;
    TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
    TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
+   TYPE_SIDE_EFFECTS (type) = (type_quals & TYPE_QUAL_PURE) != 0;
  }
  
  /* Given a type node TYPE and a TYPE_QUALIFIER_SET, return a type for


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