This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Pure function attribute
- To: egcs-patches at egcs dot cygnus dot com
- Subject: Pure function attribute
- From: Jan Hubicka <jhub6202 at ss1000 dot ms dot mff dot cuni dot cz>
- Date: Sun, 22 Aug 1999 16:40:18 +0200 (MET DST)
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