This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
RE: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
- From: "Iyer, Balaji V" <balaji dot v dot iyer at intel dot com>
- To: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Cc: "aldyh at redhat dot com" <aldyh at redhat dot com>, "Joseph Myers [joseph at codesourcery dot com]" <joseph at codesourcery dot com>
- Date: Fri, 22 Mar 2013 22:03:28 +0000
- Subject: RE: [patch] cilkplus array notation for C (clean, independent patchset, take 1)
- References: <5149D62F dot 9070503 at redhat dot com> <Pine dot LNX dot 4 dot 64 dot 1303211447220 dot 9992 at digraph dot polyomino dot org dot uk>
Attached, please find a patch that should be applied to the head of cilkplus-merge.
This patch is generated by diffing with the following hash: 4f4932be8230284919d197cccb4b10201f82a0b3
This patch also adds documentation about the built-in reduction funtions of array notations that Aldy pointed out in a previous email.
I have not fixed all the issues below (the big one that is left is the bultin function representation that Joseph Pointed out). I have fixed most of the other issues. All the things I have fixed are marked by "FIXED!"
Is this Ok to commit into cilkplus-merge?
Thanks,
Balaji V. Iyer.
> -----Original Message-----
> From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches-
> owner@gcc.gnu.org] On Behalf Of Joseph S. Myers
> Sent: Thursday, March 21, 2013 11:56 AM
> To: Aldy Hernandez
> Cc: Iyer, Balaji V; gcc-patches
> Subject: Re: [patch] cilkplus array notation for C (clean, independent patchset,
> take 1)
>
> On Wed, 20 Mar 2013, Aldy Hernandez wrote:
>
> > Joseph, folks, et al... How does this look?
>
> This review largely deals with coding style (interpreted broadly). I'll review more
> of the substance separately later; reposting with fixes for all the accumulated
> issues is probably a good idea anyway, to avoid the same issues coming up
> repeatedly.
>
> > * c-common.c (c_define_builtins): When cilkplus is enabled, the
> > function array_notation_init_builtins() is called.
>
> Don't use () after a function name when referring to the function.
FIXED!
>
> > diff --git a/gcc/c-family/array-notation-common.c
> > b/gcc/c-family/array-notation-common.c
>
> > +int extract_sec_implicit_index_arg (location_t, tree); bool
> > +is_sec_implicit_index_fn (tree); void array_notation_init_builtins
> > +(void);
FIXED!
>
> Non-static function declarations like this should not be inside a .c file.
> If these functions are used outside this file, there should be an associated
> header that declares them; include it in the .c file. If only used inside the .c file
> that defines them, make them static (and topologically sort static functions
> inside a source file so that forward static declarations are only needed for cases
> of recursion).
>
> > +/* Mark the FNDECL as cold, meaning that the function specified by FNDECL
> is
> > + not run as is. */
>
> The cold attribute means unlikely to be executed rather than "not run as is".
> Maybe "not run as is" is what's relevant here, but I'm not clear why this attribute
> would be useful for built-in functions at all - the documentation suggests it's
> only relevant when a user defines a function themselves, and affects the code
> generated for that function, so wouldn't be relevant at all for built-in functions.
>
> > +void
> > +array_notation_init_builtins (void)
>
> Other built-in functions use various .def files (builtins.def and the files it includes)
> to avoid lots of repetitive code like this - can you integrate this with that
> mechanism? If you do so, then you should be able to avoid (or massively
> simplify) functions like:
>
> > +/* Returns true if the function call specified in FUNC_NAME is
> > + __sec_implicit_index. */
> > +
> > +bool
> > +is_sec_implicit_index_fn (tree func_name)
>
> because code can use the BUILT_IN_* enum values to test whether a particular
> function is in use - which is certainly cleaner than using strcmp against the
> function name.
>
> > +/* Returns the first and only argument for FN, which should be a
> > + sec_implicit_index function. FN's location in the source file is is
> > + indicated by LOCATION. */
> > +
> > +int
> > +extract_sec_implicit_index_arg (location_t location, tree fn) {
> > + tree fn_arg;
> > + HOST_WIDE_INT return_int = 0;
> > + if (!fn)
> > + return -1;
>
> Why the random check for a NULL argument? If a NULL argument is valid
> (meaning that it makes the code cleaner to allow such arguments rather than
> making sure the function isn't called with them), this should be documented in
> the comment above the function; otherwise, if such an argument isn't valid,
> there is no need to check for it.
I always tend to check for a null pointer before I access the fields in the structure. In this case it is unnecessary. In some cases (e.g. find_rank) there is a good chance a null pointer will be passed into the function and we need to check that and reject those.
>
> You declare return_int as HOST_WIDE_INT, but it only receives a value cast to
> int, and is used only to store a value returned as int. Either use int consistently,
> or HOST_WIDE_INT consistently, but I don't see a reason to use both.
FIXED!
>
> > + if (TREE_CODE (fn) == CALL_EXPR)
> > + {
> > + fn_arg = CALL_EXPR_ARG (fn, 0);
> > + if (really_constant_p (fn_arg))
>
> I don't think really_constant_p is what's wanted;
> <http://software.intel.com/sites/default/files/m/4/e/7/3/1/40297-
> Intel_Cilk_plus_lang_spec_2.htm>
> says "The argument shall be an integer constant expression.", and such
> expressions always appear in the C front end as INTEGER_CST. So you can just
> check for INTEGER_CST.
What about C++? This function is shared by both C and C++.
>
> Now a subtlety here is that the function argument will have been folded by this
> point, meaning that cases that aren't integer constant expressions in C standard
> terms will be wrongly allowed (both by the original code and by a version
> checking against INTEGER_CST). In such cases, the way to get things checked
> correctly is to use a keyword rather than a built-in function - as with
> __builtin_choose_expr or __builtin_shuffle, for example. Since this operation
> seems special in ways that built-in functions generally aren't, that seems
> reasonable anyway. So the code parsing this keyword would check that the
> argument is an INTEGER_CST, of integer type (since INTEGER_CSTs can have
> pointer type in GCC), like that for __builtin_choose_expr does. It would then
> quite likely create its own tree code for the operation, rather than using a
> CALL_EXPR at all. (It would need to manage converting to int, given how the
> specification defines things in terms of a prototype for type int - so e.g. a
> constant 1ULL << 32 would act like 0 if int is 32 bits, under the present
> specification.)
>
> The specification doesn't seem very clear on to what extent the __sec_*
> operations must act like functions (what happens if someone puts parentheses
> around the __sec_* name, for example - that wouldn't work with the keyword
> approach). So the specification should be clarified there, but I think saying the
> __sec_* operations are syntactically special, like keywords, is more appropriate
> than requiring other uses to work.
>
> > + return_int = (int) int_cst_value (fn_arg);
> > + else
> > + {
> > + if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (fn))
> > + location = EXPR_LOCATION (fn);
> > + error_at (location, "__sec_implicit_index parameter must be a "
> > + "constant integer expression");
>
> The term is "integer constant expression" not "constant integer expression".
FIXED!
>
> > diff --git a/gcc/c/c-array-notation.c b/gcc/c/c-array-notation.c
>
> > +void replace_array_notations (tree *, bool, vec<tree, va_gc> *,
> > + vec<tree, va_gc> *);
> > +void find_rank (tree, bool, size_t *); void
> > +extract_array_notation_exprs (tree, bool, vec<tree, va_gc> **); tree
> > +fix_conditional_array_notations (tree); struct c_expr
> > +fix_array_notation_expr (location_t, enum tree_code,
> > + struct c_expr);
> > +bool is_builtin_array_notation_fn (tree func_name, an_reduce_type
> > +*type); static tree fix_builtin_array_notation_fn (tree
> > +an_builtin_fn, tree *new_var); bool contains_array_notation_expr
> > +(tree expr); tree expand_array_notation_exprs (tree t);
>
> As before, forward declarations inside .c files should only be for static functions
> with recursive calls to themselves, not for non-static functions or static
> functions not involved in recursion.
FIXED!
>
> > +struct inv_list
> > +{
> > + vec<tree, va_gc> *list_values;
> > + vec<tree, va_gc> *replacement;
> > +};
>
> Comment on this type explaining what it's for.
FIXED!
>
> > +/* Returns the rank of ARRAY through the *RANK. The user can specify
> whether
> > + (s)he wants to step into array_notation-specific builtin functions
> > + (specified by the IGNORE_BUILTIN_FN).
>
> The wording seems awkward; "Set *RANK to the rank of ARRAY, ignoring array-
> notation-specific built-in functions if IGNORE_BUILTIN_FN." would be better.
Yes, I agree with your wording. Thanks! and FIXED!
>
> > +void
> > +find_rank (tree array, bool ignore_builtin_fn, size_t *rank) {
> > + tree ii_tree;
> > + size_t current_rank = 0, ii = 0;
> > + an_reduce_type dummy_type = REDUCE_UNKNOWN;
> > + if (!array)
> > + return;
>
> As before, avoid random checks for NULL parameters unless there is an actual
> reason to allow them and the comments document that they are allowed and
> what the semantics are in that case. In general, explain what ARRAY is - an
> expression?
This check is necessary. Find rank can get a NULL pointer and that must be caught and rejected.
>
> Is *RANK always set by this function? Make clear in the comment above the
> function whether it is, and whether the initial value of *RANK before the
> function is called is of any significance. I note that
>
> > + else if (TREE_CODE (array) == ARRAY_NOTATION_REF)
> > + {
> > + for (ii_tree = array;
> > + ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF;
> > + ii_tree = ARRAY_NOTATION_ARRAY (ii_tree))
> > + current_rank++;
> > + if (*rank == 0)
> > + *rank = current_rank;
>
> does appear to look at the value before the function has set it, implying that the
> original value of *RANK *does* mean something.
FIXED! I looked this way due to an artifact of a previous implementation. It looks a little bit more cleaner now.
>
> > + if (TREE_CODE (array) == CALL_EXPR)
> > + {
> > + tree func_name = CALL_EXPR_FN (array);
> > + if (TREE_CODE (func_name) == ADDR_EXPR)
> > + if (!ignore_builtin_fn)
> > + if (is_builtin_array_notation_fn (func_name, &dummy_type))
> > + /* If it is a builtin function, then we know it returns a
> > + scalar. */
> > + return;
> > + if (TREE_CODE (TREE_OPERAND (array, 0)) == INTEGER_CST)
> > + {
> > + int length = TREE_INT_CST_LOW (TREE_OPERAND (array, 0));
> > + for (ii = 0; ii < (size_t) length; ii++)
>
> TREE_INT_CST_LOW returns unsigned HOST_WIDE_INT. There should be no
> need for converting twice, first to int and then to size_t. And rather than
> depending on implementation default of CALL_EXPR, call_expr_nargs would be
> a better way to calculate the length.
>
> > + find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);
>
> But actually, you're dealing with a CALL_EXPR here. So you should be able to
> use existing iterators over CALL_EXPR arguments (e.g.
> FOR_EACH_CALL_EXPR_ARG) rather than explicitly using the number of
> arguments at all. Doing so, and separately checking CALL_EXPR_FN, and
> CALL_EXPR_STATIC_CHAIN if applicable, seems cleaner than depending on low-
> level details of the sequence of operands to a CALL_EXPR.
FIXED! (I used your suggestion and used FOR_EACH_CALL_EXPR_ARG)
>
> > +/* Extracts all the array notations specified in NODE and stores them in a
> > + dynamic tree array of ARRAY_LIST whose size is stored in *LIST_SIZE. The
> > + user can specify if (s)he wants to ignore the array notations inside the
> > + array-notation specific builtin functions (by setting IGNORE_BUILTIN_FN to
> > + true). */
> > +
> > +void
> > +extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
> > + vec<tree, va_gc> **array_list)
>
> There's no argument LIST_SIZE, so the comment needs updating. Again, the
> wording about "The user" is awkward; the comment should directly define the
> semantics of the function in terms of its argument, without reference to "The
> user".
FIXED! Reworded the comment.
>
> > +{
> > + size_t ii = 0;
> > + an_reduce_type dummy_type = REDUCE_UNKNOWN;
> > +
> > + if (!node)
> > + return;
>
> Again, check for NULL argument without any mention in the comment that such
> arguments are valid; remove unless there is a reason to make them valid.
>
> > + else if (TREE_CODE (node) == TREE_LIST)
>
> What's NODE? My first guess would have been an expression, but if a TREE_LIST
> is possible that's clearly not the answer, so explain in the comment above the
> function what NODE is. (If a TREE_LIST is being used within expressions to store
> something specific to array notation, don't do so - TREE_LIST is deprecated,
> existing uses should be phased out in favour of more specific and less memory-
> hungry datastructures and new uses should not be added.)
FIXED! What is replacing tree-list? I have used tree-list in my later patches and in my Cilk Plus branch.
>
> > + if (TREE_CODE (TREE_OPERAND (node, 0)) == INTEGER_CST)
> > + {
> > + int length = TREE_INT_CST_LOW (TREE_OPERAND (node, 0));
> > +
> > + for (ii = 0; ii < (size_t) length; ii++)
> > + extract_array_notation_exprs
> > + (TREE_OPERAND (node, ii), ignore_builtin_fn, array_list);
>
> Same problems as before with an iterator over CALL_EXPR that should avoid
> depending on low-level details of how CALL_EXPR is implemented, and excess
> integer type conversions.
FIXED!
>
> > +/* Replaces all occurances of array notations in tree ORIG that matches the
> > + ones in LIST with the one in ARRAY_OPERAND. The size of list and
> > + ARRAY_OPERAND is ARRAY_SIZE. For example, ARRAY_OPERAND[x] for
> some index
> > + 'x' will have the equivalent ARRAY_REF for the ARRAY_NOTATION_REF
> specified
> > + in LIST[x]. The user can specify if (s)he wants to ignore the array
> > + notations inside the array-notation specific builtin functions (using the
> > + bool variable IGNORE_BUILTIN_FN). */
>
> Again, avoid "The user".
FIXED!
>
> > +void
> > +replace_array_notations (tree *orig, bool ignore_builtin_fn,
> > + vec<tree, va_gc> *list,
> > + vec<tree, va_gc> *array_operand)
> > +{
> > + size_t ii = 0;
> > + tree node = NULL_TREE, node_replacement = NULL_TREE;
> > + an_reduce_type dummy_type = REDUCE_UNKNOWN;
> > +
> > + if (vec_safe_length (list) == 0 || !*orig)
> > + return;
This ORIG must be checked for NULL because you will step this function even if the node is NULL. This is the spot to check that.
>
> Again, avoid checks for NULL or document that NULL arguments are valid if
> there's a good reason. Generally, document what sort of thing ORIG is.
>
> > + if (TREE_CODE (TREE_OPERAND (*orig, 0)) == INTEGER_CST)
> > + {
> > + int length = TREE_INT_CST_LOW (TREE_OPERAND (*orig, 0));
> > + for (ii = 0; ii < (size_t) length; ii++)
> > + replace_array_notations
> > + (&TREE_OPERAND (*orig, ii), ignore_builtin_fn, list,
> > + array_operand);
>
> Again, better CALL_EXPR iterators.
FIXED!
>
> > +/* This function will find all the scalar expressions in *TP and push it in
> > + DATA struct, typecasted to (void *). If *WALK_SUBTREES is set to 0 then
> > + we have do not go into the *TP's subtrees. */
>
> Rather than "This function will", just "Find ..." (and say "Returns NULL_TREE." or
> something like that - presumably the return type is so it can be passed to
> walk_tree).
>
> > +/* Replaces all the scalar expressions in *NODE. */
> > +
> > +tree
> > +replace_invariant_exprs (tree *node)
>
> Comment needs to explain the semantics of the return value.
FIXED!
>
> > +tree
> > +build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
> > + enum tree_code modifycode, location_t rhs_loc,
> > + tree rhs, tree rhs_origtype)
>
> > + }
> > +
> > +
> > +
> > + for (ii = 0; ii < lhs_rank; ii++)
>
> Excess blank lines in middle of function. Generally there shouldn't be two or
> more consecutive blank lines inside a function (if you want to have different
> sizes of blanks to split up levels of structure in the function, that suggests the
> function is too big and should be split up into separate functions).
FIXED!
>
> > + TREE_TYPE (lhs_var[ii]));
> > +
> > + }
>
> This location for a blank line doesn't make sense.
FIXED!
>
> > + /* The following statements will do the following:
> > + * <if_stmt_label>: (in order from outermost to innermost)
> > + * if (cond_expr) then go to body_label
> > + * else go to exit_label
> > + * <body_label>:
> > + * array expression
> > + *
> > + * (the increment, goto and exit_label goes from innermost to
> > + * outermost).
> > + * ii++ and jj++
> > + * go to if_stmt_label
> > + * <exit_label>:
> > + * <REST OF CODE>
> > + */
>
> Comments should not have an initial "*" on each line.
FIXED!
>
> > +/* Encloses the conditional statement passed in STMT with a loop around it
> > + and replaces the condition in STMT with a ARRAY_REF tree-node to the
> array.
> > + The condition must have a ARRAY_NOTATION_REF tree. */
> > +
> > +static tree
> > +fix_conditional_array_notations_1 (tree stmt)
>
> Comment should explain return value semantics.
FIXED!
>
> > + TREE_TYPE (array_var[ii]));
> > +
> > + }
>
> Another stray blank line. Check the patch generally for stray blank lines
> immediately before a '}', I don't think they ever make sense, but I may have
> missed some.
I think I have caught all of it. I apologize if I missed any.
>
> > + // XDELETEVEC (array_var);
>
> I don't think this sort of commented-out code should be added. If you're
> deliberately not doing something that a reader might expect to be done, have a
> comment explaining *why* you're not doing it, not just commented-out code to
> do it.
FIXED!
>
> > + error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind
> cannot"
> > + " have arrays with dimension greater than 1.");
>
> Diagnostics don't end with ".".
>
> > + default:
> > + gcc_unreachable (); /* You should not reach here. */
>
> No need for comments like this that just repeat the plain semantics of the C
> code. There's nothing else a call to gcc_unreachable could possibly mean; such
> a comment is of no more use than "i++; /* Add 1 to i. */".
FIXED!
>
> > +/* Returns true of FUNC_NAME is a builtin array notation function. The type
> of
> > + function is returned in *TYPE. */
>
> "true if", not "true of".
>
FIXED! Sorry for this stupid mistake.
> > +bool
> > +is_builtin_array_notation_fn (tree func_name, an_reduce_type *type) {
> > + const char *function_name = NULL;
> > +
> > + if (!func_name)
> > + return false;
>
> Another unexplained test for a NULL argument. Again, explain what sort of
> things FUNC_NAME may be. (This is another function that should be using
> BUILT_IN_* enum values rather than strcmp, if you rework how the built-in
> functions are implemented.)
>
> > +/* Returns true of EXPR (and its subtrees) contain
> > +ARRAY_NOTATION_EXPR node. */
>
> "true if", again.
FIXED!
>
> > +/* Replaces array notations in void function call arguments in ARG with loop
> and
> > + tree-node ARRAY_REF and returns that value in a tree node variable called
> > + LOOP. */
>
> LOOP is not an argument to this function, so it doesn't make sense to refer to it
> in the comment. I suspect " in a tree node variable called LOOP" should simply
> be removed.
FIXED!
>
> > + if (TREE_CODE (arg) == CALL_EXPR
> > + && is_builtin_array_notation_fn (CALL_EXPR_FN (arg), &an_type))
> > + {
> > + loop = fix_builtin_array_notation_fn (arg, &new_var);
> > + /* We are ignoring the new var because either the user does not want to
> > + capture it OR he is using sec_reduce_mutating function. */
>
> In general I think "the user" comments should be avoided though this one is a bit
> less awkward than those defining function semantics by reference to "the user".
>
> > +/* Walks through tree node T and find all the call-statments that do not
> return
> > + anything and fix up any array notations they may carry. */
> > +
> > +tree
> > +expand_array_notation_exprs (tree t)
>
> Comment should document return value.
FIXED!
>
> > +{
> > + if (!t || !contains_array_notation_expr (t))
> > + return t;
>
> Another check for NULL without a comment saying NULL is a valid argument.
This function also can receive a null pointer.
>
> > +/* Returns array notation expression for the array base ARRAY of type TYPE,
> > + with start index, length and stride given by START_INDEX, LENGTH and
> STRIDE,
> > + respectively. */
> > +
> > +tree
> > +build_array_notation_ref (location_t loc, tree array, tree start_index,
> > + tree length, tree stride, tree type) {
> > + tree array_ntn_tree = NULL_TREE;
> > + size_t stride_rank = 0, length_rank = 0, start_rank = 0;
> > +
> > + if (!TREE_TYPE (start_index) || !INTEGRAL_TYPE_P (TREE_TYPE
> > + (start_index)))
>
> I'd expect the argument would have to be an expression, so would always have
> a TYPE and the !TREE_TYPE (start_index) check should be unnecessary.
> If it is needed, explain further in the comment at the start of the function.
> Likewise for other checks for NULL types in this function.
FIXED! But Stride could easily be NULL, (e.g. array[0:10]) and in this case we have put one in. So, I have left that check in.
>
> > + {
> > + error_at (loc,
> > + "start-index of array notation triplet is not an integer.");
>
> Diagnostic should not end with ".".
FIXED!
>
> > + error_at (loc, "length of array notation triplet is not an
> > + integer.");
>
> Likewise.
FIXED!
>
> > + error_at (loc, "stride of array notation triplet is not an
> > + integer.");
>
> Likewise.
FIXED!
>
> > + error_at (loc, "rank of an array notation triplet's start-index is not "
> > + "zero.");
>
> Likewise.
FIXED!
>
> > + error_at (loc, "rank of an array notation triplet's length is
> > + not zero.");
>
> Likewise.
FIXED!
>
> > + error_at (loc, "rank of array notation triplet's stride is not
> > + zero.");
>
> Likewise.
FIXED!
>
> That's a coding style review of the first half or so of the patch, more later....
Thanks for reviewing my code!
-Balaji V. Iyer.
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
diff --git a/gcc/c-family/ChangeLog.cilkplus b/gcc/c-family/ChangeLog.cilkplus
index 6591fd1..10db29b 100644
--- a/gcc/c-family/ChangeLog.cilkplus
+++ b/gcc/c-family/ChangeLog.cilkplus
@@ -1,7 +1,11 @@
+2013-03-22 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * c-pretty-print.c (pp_c_expression): Added ARRAY_NOTATION_REF case.
+
2013-03-20 Balaji V. Iyer <balaji.v.iyer@intel.com>
* c-common.c (c_define_builtins): When cilkplus is enabled, the
- function array_notation_init_builtins() is called.
+ function array_notation_init_builtins is called.
(c_common_init_ts): Added ARRAY_NOTATION_REF as typed.
* c-common.def (ARRAY_NOTATION_REF): New tree.
* c-common.h (build_array_notation_expr): New function declaration.
diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c
index 7089c8e..b775225 100644
--- a/gcc/c-family/array-notation-common.c
+++ b/gcc/c-family/array-notation-common.c
@@ -29,19 +29,6 @@ along with GCC; see the file COPYING3. If not see
#include "tree-iterator.h"
#include "diagnostic-core.h"
-int extract_sec_implicit_index_arg (location_t, tree);
-bool is_sec_implicit_index_fn (tree);
-void array_notation_init_builtins (void);
-
-/* Mark the FNDECL as cold, meaning that the function specified by FNDECL is
- not run as is. */
-
-static void
-mark_cold (tree fndecl)
-{
- DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("cold"), NULL_TREE,
- DECL_ATTRIBUTES (fndecl));
-}
/* This function inititializes array notation specific builtin information. */
@@ -54,67 +41,56 @@ array_notation_init_builtins (void)
func_type = build_function_type_list (integer_type_node, ptr_type_node,
NULL_TREE);
new_func = build_fn_decl ("__sec_reduce_add", func_type);
- mark_cold (new_func);
new_func = lang_hooks.decls.pushdecl (new_func);
func_type = build_function_type_list (integer_type_node, ptr_type_node,
NULL_TREE);
new_func = build_fn_decl ("__sec_reduce_mul", func_type);
- mark_cold (new_func);
new_func = lang_hooks.decls.pushdecl (new_func);
func_type = build_function_type_list (integer_type_node, ptr_type_node,
NULL_TREE);
new_func = build_fn_decl ("__sec_reduce_all_zero", func_type);
- mark_cold (new_func);
new_func = lang_hooks.decls.pushdecl (new_func);
func_type = build_function_type_list (integer_type_node, ptr_type_node,
NULL_TREE);
new_func = build_fn_decl ("__sec_reduce_any_zero", func_type);
- mark_cold (new_func);
new_func = lang_hooks.decls.pushdecl (new_func);
func_type = build_function_type_list (integer_type_node, ptr_type_node,
NULL_TREE);
new_func = build_fn_decl ("__sec_reduce_max", func_type);
- mark_cold (new_func);
new_func = lang_hooks.decls.pushdecl (new_func);
func_type = build_function_type_list (integer_type_node, ptr_type_node,
NULL_TREE);
new_func = build_fn_decl ("__sec_reduce_min", func_type);
- mark_cold (new_func);
new_func = lang_hooks.decls.pushdecl (new_func);
func_type = build_function_type_list (integer_type_node, ptr_type_node,
NULL_TREE);
new_func = build_fn_decl ("__sec_reduce_min_ind", func_type);
- mark_cold (new_func);
new_func = lang_hooks.decls.pushdecl (new_func);
func_type = build_function_type_list (integer_type_node, ptr_type_node,
NULL_TREE);
new_func = build_fn_decl ("__sec_reduce_max_ind", func_type);
- mark_cold (new_func);
new_func = lang_hooks.decls.pushdecl (new_func);
func_type = build_function_type_list (integer_type_node, ptr_type_node,
NULL_TREE);
new_func = build_fn_decl ("__sec_reduce_any_nonzero", func_type);
- mark_cold (new_func);
new_func = lang_hooks.decls.pushdecl (new_func);
func_type = build_function_type_list (integer_type_node, ptr_type_node,
NULL_TREE);
new_func = build_fn_decl ("__sec_reduce_all_nonzero", func_type);
- mark_cold (new_func);
new_func = lang_hooks.decls.pushdecl (new_func);
func_type = build_function_type_list (integer_type_node, integer_type_node,
NULL_TREE);
new_func = build_fn_decl ("__sec_implicit_index", func_type);
- mark_cold (new_func);
new_func = lang_hooks.decls.pushdecl (new_func);
func_type = build_function_type_list (integer_type_node, ptr_type_node,
@@ -167,25 +143,23 @@ is_sec_implicit_index_fn (tree func_name)
sec_implicit_index function. FN's location in the source file is is
indicated by LOCATION. */
-int
+HOST_WIDE_INT
extract_sec_implicit_index_arg (location_t location, tree fn)
{
tree fn_arg;
HOST_WIDE_INT return_int = 0;
- if (!fn)
- return -1;
if (TREE_CODE (fn) == CALL_EXPR)
{
fn_arg = CALL_EXPR_ARG (fn, 0);
if (really_constant_p (fn_arg))
- return_int = (int) int_cst_value (fn_arg);
+ return_int = int_cst_value (fn_arg);
else
{
if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (fn))
location = EXPR_LOCATION (fn);
error_at (location, "__sec_implicit_index parameter must be a "
- "constant integer expression");
+ "integer constant expression");
return -1;
}
}
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index edcff2e..e07085d 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -541,7 +541,7 @@ extern tree build_modify_expr (location_t, tree, tree, enum tree_code,
extern tree build_array_notation_expr (location_t, tree, tree, enum tree_code,
location_t, tree, tree);
extern tree build_array_notation_ref (location_t, tree, tree, tree, tree, tree);
-extern void find_rank (tree, bool, size_t *);
+extern bool find_rank (location_t, tree, tree, bool, size_t *);
extern tree build_indirect_ref (location_t, tree, ref_operator);
extern int field_decl_cmp (const void *, const void *);
@@ -1173,5 +1173,10 @@ typedef enum array_notation_reduce_type {
extern int extract_sec_implicit_index_arg (location_t, tree);
extern bool is_sec_implicit_index_fn (tree);
extern void array_notation_init_builtins (void);
+extern struct c_expr fix_array_notation_expr (location_t, enum tree_code,
+ struct c_expr);
+extern bool contains_array_notation_expr (tree);
+extern tree expand_array_notation_exprs (tree);
+extern tree fix_conditional_array_notations (tree);
#endif /* ! GCC_C_COMMON_H */
diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index 30c8e80..b8af90c 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -1479,11 +1479,11 @@ pp_c_postfix_expression (c_pretty_printer *pp, tree e)
case ARRAY_NOTATION_REF:
pp_postfix_expression (pp, ARRAY_NOTATION_ARRAY (e));
pp_c_left_bracket (pp);
- pp_postfix_expression (pp, ARRAY_NOTATION_START (e));
+ pp_expression (pp, ARRAY_NOTATION_START (e));
pp_colon (pp);
- pp_postfix_expression (pp, ARRAY_NOTATION_LENGTH (e));
+ pp_expression (pp, ARRAY_NOTATION_LENGTH (e));
pp_colon (pp);
- pp_postfix_expression (pp, ARRAY_NOTATION_STRIDE (e));
+ pp_expression (pp, ARRAY_NOTATION_STRIDE (e));
pp_c_right_bracket (pp);
break;
@@ -2161,6 +2161,7 @@ pp_c_expression (c_pretty_printer *pp, tree e)
case POSTINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
case ARRAY_REF:
+ case ARRAY_NOTATION_REF:
case CALL_EXPR:
case COMPONENT_REF:
case BIT_FIELD_REF:
diff --git a/gcc/c/c-array-notation.c b/gcc/c/c-array-notation.c
old mode 100644
new mode 100755
index a3e754a..3d36382
--- a/gcc/c/c-array-notation.c
+++ b/gcc/c/c-array-notation.c
@@ -31,19 +31,17 @@
#include "gcc.h"
#include "c-family/c-common.h"
-void replace_array_notations (tree *, bool, vec<tree, va_gc> *,
+static void replace_array_notations (tree *, bool, vec<tree, va_gc> *,
vec<tree, va_gc> *);
-void find_rank (tree, bool, size_t *);
-void extract_array_notation_exprs (tree, bool, vec<tree, va_gc> **);
-tree fix_conditional_array_notations (tree);
-struct c_expr fix_array_notation_expr (location_t, enum tree_code,
- struct c_expr);
-bool is_builtin_array_notation_fn (tree func_name, an_reduce_type *type);
+static void extract_array_notation_exprs (tree, bool, vec<tree, va_gc> **);
+static bool is_builtin_array_notation_fn (tree func_name, an_reduce_type *type);
static tree fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var);
-bool contains_array_notation_expr (tree expr);
-tree expand_array_notation_exprs (tree t);
+/* This structure holds all the scalar values and its appropriate variable
+ replacment. It is mainly used by the function that pulls all the invariant
+ parts that should be executed only once that comes with array notation
+ expressions. */
struct inv_list
{
vec<tree, va_gc> *list_values;
@@ -51,72 +49,80 @@ struct inv_list
};
-/* Returns the rank of ARRAY through the *RANK. The user can specify whether
- (s)he wants to step into array_notation-specific builtin functions
- (specified by the IGNORE_BUILTIN_FN).
+/* Sets *RANK of expression ARRAY, ignoring array notation specific built-in
+ functions if IGNORE_BUILTIN_FN is true. The ORIG_EXPR is printed out if an
+ error occured in the rank calculation. The functions returns false if it
+ encounters an error in rank calculation.
For example, an array notation of A[:][:] or B[0:10][0:5:2] or C[5][:][1:0]
all have a rank of 2. */
-void
-find_rank (tree array, bool ignore_builtin_fn, size_t *rank)
+bool
+find_rank (location_t loc, tree orig_expr, tree array, bool ignore_builtin_fn,
+ size_t *rank)
{
tree ii_tree;
- size_t current_rank = 0, ii = 0;
+ size_t ii = 0, current_rank = 0;
an_reduce_type dummy_type = REDUCE_UNKNOWN;
+
if (!array)
- return;
+ return true;
else if (TREE_CODE (array) == ARRAY_NOTATION_REF)
{
for (ii_tree = array;
ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF;
ii_tree = ARRAY_NOTATION_ARRAY (ii_tree))
current_rank++;
- if (*rank == 0)
- *rank = current_rank;
+ if (*rank == 0)
+ *rank = current_rank;
+ else if (*rank != current_rank)
+ {
+ error_at (loc, "rank mismatch in expression %qE", orig_expr);
+ return false;
+ }
}
else if (TREE_CODE (array) == STATEMENT_LIST)
{
tree_stmt_iterator ii_tsi;
for (ii_tsi = tsi_start (array); !tsi_end_p (ii_tsi);
tsi_next (&ii_tsi))
- find_rank (*tsi_stmt_ptr (ii_tsi), ignore_builtin_fn, rank);
+ if (!find_rank (loc, orig_expr, *tsi_stmt_ptr (ii_tsi),
+ ignore_builtin_fn, rank))
+ return false;
}
else
{
if (TREE_CODE (array) == CALL_EXPR)
{
tree func_name = CALL_EXPR_FN (array);
+ tree arg;
+ call_expr_arg_iterator iter;
if (TREE_CODE (func_name) == ADDR_EXPR)
if (!ignore_builtin_fn)
if (is_builtin_array_notation_fn (func_name, &dummy_type))
- /* If it is a builtin function, then we know it returns a
- scalar. */
- return;
- if (TREE_CODE (TREE_OPERAND (array, 0)) == INTEGER_CST)
- {
- int length = TREE_INT_CST_LOW (TREE_OPERAND (array, 0));
- for (ii = 0; ii < (size_t) length; ii++)
- find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);
- }
- else
- gcc_unreachable ();
+ /* If it is a builtin function, then it returns a scalar. */
+ return true;
+
+ FOR_EACH_CALL_EXPR_ARG (arg, iter, array)
+ if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
+ return false;
}
else
for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (array)); ii++)
- find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);
+ if (!find_rank (loc, orig_expr, TREE_OPERAND (array, ii),
+ ignore_builtin_fn, rank))
+ return false;
}
- return;
+ return true;
}
-/* Extracts all the array notations specified in NODE and stores them in a
- dynamic tree array of ARRAY_LIST whose size is stored in *LIST_SIZE. The
- user can specify if (s)he wants to ignore the array notations inside the
- array-notation specific builtin functions (by setting IGNORE_BUILTIN_FN to
- true). */
+/* Extracts all array notations in NODE ans stores in ARRAY_LIST. If
+ IGNORE_BUILTIN_FN is set, then array notations inside array notation
+ specific builtin functions are ignored. The NODE can be anything from a
+ full function to a single variable. */
-void
+static void
extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
vec<tree, va_gc> **array_list)
{
@@ -148,6 +154,8 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
}
else if (TREE_CODE (node) == CALL_EXPR)
{
+ tree arg;
+ call_expr_arg_iterator iter;
if (is_builtin_array_notation_fn (CALL_EXPR_FN (node), &dummy_type))
{
if (ignore_builtin_fn)
@@ -163,17 +171,9 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
vec_safe_push (*array_list, node);
return;
}
- if (TREE_CODE (TREE_OPERAND (node, 0)) == INTEGER_CST)
- {
- int length = TREE_INT_CST_LOW (TREE_OPERAND (node, 0));
- for (ii = 0; ii < (size_t) length; ii++)
- extract_array_notation_exprs
- (TREE_OPERAND (node, ii), ignore_builtin_fn, array_list);
- }
- else
- gcc_unreachable (); /* We should not get here. */
-
+ FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
+ extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
}
else
for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++)
@@ -183,15 +183,12 @@ extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
}
-/* Replaces all occurances of array notations in tree ORIG that matches the
- ones in LIST with the one in ARRAY_OPERAND. The size of list and
- ARRAY_OPERAND is ARRAY_SIZE. For example, ARRAY_OPERAND[x] for some index
- 'x' will have the equivalent ARRAY_REF for the ARRAY_NOTATION_REF specified
- in LIST[x]. The user can specify if (s)he wants to ignore the array
- notations inside the array-notation specific builtin functions (using the
- bool variable IGNORE_BUILTIN_FN). */
+/* Replaces all the occurances of array notations in *LIST with the appropriate
+ one in ARRAY_OPERAND. If IGNORE_BUILTIN_FN is set, then array notations
+ inside array-notation specific builtin functions are ignored. ORIG can be
+ anything from a collection of statement lists to a single variable. */
-void
+static void
replace_array_notations (tree *orig, bool ignore_builtin_fn,
vec<tree, va_gc> *list,
vec<tree, va_gc> *array_operand)
@@ -200,7 +197,7 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
tree node = NULL_TREE, node_replacement = NULL_TREE;
an_reduce_type dummy_type = REDUCE_UNKNOWN;
- if (vec_safe_length (list) == 0 || !*orig)
+ if (!*orig || vec_safe_length (list) == 0)
return;
if (TREE_CODE (*orig) == ARRAY_NOTATION_REF)
@@ -221,6 +218,8 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
}
else if (TREE_CODE (*orig) == CALL_EXPR)
{
+ tree arg;
+ call_expr_arg_iterator iter;
if (is_builtin_array_notation_fn (CALL_EXPR_FN (*orig), &dummy_type))
{
if (!ignore_builtin_fn)
@@ -244,16 +243,14 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
}
return;
}
- if (TREE_CODE (TREE_OPERAND (*orig, 0)) == INTEGER_CST)
+ ii = 0;
+ FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
{
- int length = TREE_INT_CST_LOW (TREE_OPERAND (*orig, 0));
- for (ii = 0; ii < (size_t) length; ii++)
- replace_array_notations
- (&TREE_OPERAND (*orig, ii), ignore_builtin_fn, list,
- array_operand);
- }
- else
- gcc_unreachable (); /* We should not get here! */
+ replace_array_notations (&arg, ignore_builtin_fn, list,
+ array_operand);
+ CALL_EXPR_ARG (*orig, ii) = arg;
+ ii++;
+ }
}
else
{
@@ -264,9 +261,9 @@ replace_array_notations (tree *orig, bool ignore_builtin_fn,
return;
}
-/* This function will find all the scalar expressions in *TP and push it in
- DATA struct, typecasted to (void *). If *WALK_SUBTREES is set to 0 then
- we have do not go into the *TP's subtrees. */
+/* Find all the scalar expressions in *TP and push it in DATA struct,
+ typecasted to (void *). If *WALK_SUBTREES is set to 0 then do not go into
+ the *TP's subtrees. */
static tree
find_inv_trees (tree *tp, int *walk_subtrees, void *data)
@@ -322,7 +319,9 @@ replace_inv_trees (tree *tp, int *walk_subtrees, void *data)
return NULL_TREE;
}
-/* Replaces all the scalar expressions in *NODE. */
+/* Replaces all the scalar expressions in *NODE. Returns a STATEMENT_LIST that
+ holds the NODE along with variables that holds the results of the invariant
+ expressions. */
tree
replace_invariant_exprs (tree *node)
@@ -391,13 +390,16 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
tree ii_tree = NULL_TREE, new_modify_expr;
vec<tree, va_gc> *lhs_list = NULL, *rhs_list = NULL;
tree new_var = NULL_TREE, builtin_loop = NULL_TREE;
+ tree begin_var, lngth_var, strde_var;
size_t rhs_list_size = 0, lhs_list_size = 0;
/* If either of this is true, an error message must have been send out
already. Not necessary to send out multiple error messages. */
if (lhs == error_mark_node || rhs == error_mark_node)
return error_mark_node;
- find_rank (rhs, false, &rhs_rank);
+
+ if (!find_rank (location, rhs, rhs, false, &rhs_rank))
+ return error_mark_node;
extract_array_notation_exprs (rhs, false, &rhs_list);
rhs_list_size = vec_safe_length (rhs_list);
@@ -434,8 +436,11 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
lhs_rank = 0;
rhs_rank = 0;
- find_rank (lhs, true, &lhs_rank);
- find_rank (rhs, true, &rhs_rank);
+ if (!find_rank (location, lhs, lhs, true, &lhs_rank))
+ return error_mark_node;
+
+ if (!find_rank (location, rhs, rhs, true, &rhs_rank))
+ return error_mark_node;
if (lhs_rank == 0 && rhs_rank == 0)
{
@@ -466,12 +471,22 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
if (lhs_rank == 0 && rhs_rank != 0 && TREE_CODE (rhs) != CALL_EXPR)
{
tree rhs_base = rhs;
- for (ii = 0; ii < (size_t) rhs_rank; ii++)
- rhs_base = ARRAY_NOTATION_ARRAY (rhs);
+ if (TREE_CODE (rhs_base) == ARRAY_NOTATION_REF)
+ {
+ for (ii = 0; ii < (size_t) rhs_rank; ii++)
+ rhs_base = ARRAY_NOTATION_ARRAY (rhs);
- error_at (location, "%qD cannot be scalar when %qD is not", lhs,
- rhs_base);
- return error_mark_node;
+ error_at (location, "%qE cannot be scalar when %qE is not", lhs,
+ rhs_base);
+ return error_mark_node;
+ }
+ else
+ {
+ error_at (location, "%qE cannot be scalar when %qE is not", lhs,
+ rhs_base);
+ return error_mark_node;
+ }
+
}
if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
{
@@ -491,6 +506,72 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
return error_mark_node;
}
+ /* Here we assign the array notation components to variable so that we can
+ satisfy the exec once rule. */
+ for (ii = 0; ii < lhs_list_size; ii++)
+ {
+ tree array_node = (*lhs_list)[ii];
+ tree array_begin = ARRAY_NOTATION_START (array_node);
+ tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+ tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+
+ begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+ integer_type_node);
+ lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+ integer_type_node);
+ strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+ integer_type_node);
+
+ add_stmt (build_modify_expr (location, begin_var, TREE_TYPE (begin_var),
+ NOP_EXPR, location, array_begin,
+ TREE_TYPE (array_begin)));
+ add_stmt (build_modify_expr (location, lngth_var, TREE_TYPE (lngth_var),
+ NOP_EXPR, location, array_lngth,
+ TREE_TYPE (array_lngth)));
+ add_stmt (build_modify_expr (location, strde_var, TREE_TYPE (strde_var),
+ NOP_EXPR, location, array_strde,
+ TREE_TYPE (array_strde)));
+
+ ARRAY_NOTATION_START (array_node) = begin_var;
+ ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+ ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+ }
+
+ for (ii = 0; ii < rhs_list_size; ii++)
+ {
+ tree array_node = (*rhs_list)[ii];
+ if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+ {
+ tree array_begin = ARRAY_NOTATION_START (array_node);
+ tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+ tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+
+ begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+ integer_type_node);
+ lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+ integer_type_node);
+ strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+ integer_type_node);
+
+ add_stmt (build_modify_expr (location, begin_var,
+ TREE_TYPE (begin_var),
+ NOP_EXPR, location, array_begin,
+ TREE_TYPE (array_begin)));
+ add_stmt (build_modify_expr (location, lngth_var,
+ TREE_TYPE (lngth_var),
+ NOP_EXPR, location, array_lngth,
+ TREE_TYPE (array_lngth)));
+ add_stmt (build_modify_expr (location, strde_var,
+ TREE_TYPE (strde_var),
+ NOP_EXPR, location, array_strde,
+ TREE_TYPE (array_strde)));
+
+ ARRAY_NOTATION_START (array_node) = begin_var;
+ ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+ ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+ }
+ }
+
lhs_vector = XNEWVEC (bool *, lhs_list_size);
for (ii = 0; ii < lhs_list_size; ii++)
lhs_vector[ii] = XNEWVEC (bool, lhs_rank);
@@ -678,8 +759,6 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
rhs_vector[ii][jj] = false;
}
-
-
for (ii = 0; ii < lhs_rank; ii++)
{
if (lhs_vector[0][ii])
@@ -691,7 +770,6 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
NOP_EXPR,
location, build_zero_cst (TREE_TYPE (lhs_var[ii])),
TREE_TYPE (lhs_var[ii]));
-
}
}
@@ -965,19 +1043,19 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
}
/* The following statements will do the following:
- * <if_stmt_label>: (in order from outermost to innermost)
- * if (cond_expr) then go to body_label
- * else go to exit_label
- * <body_label>:
- * array expression
- *
- * (the increment, goto and exit_label goes from innermost to
- * outermost).
- * ii++ and jj++
- * go to if_stmt_label
- * <exit_label>:
- * <REST OF CODE>
- */
+ <if_stmt_label>: (in order from outermost to innermost)
+ if (cond_expr) then go to body_label
+ else go to exit_label
+ <body_label>:
+ array expression
+
+ (the increment, goto and exit_label goes from innermost to
+ outermost).
+ ii++ and jj++
+ go to if_stmt_label
+ <exit_label>:
+ <REST OF CODE>
+ */
for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
@@ -1012,7 +1090,9 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
/* Encloses the conditional statement passed in STMT with a loop around it
and replaces the condition in STMT with a ARRAY_REF tree-node to the array.
- The condition must have a ARRAY_NOTATION_REF tree. */
+ The condition must have a ARRAY_NOTATION_REF tree. An expansion of array
+ notation in STMT is returned in a STATEMENT_LIST. */
+
static tree
fix_conditional_array_notations_1 (tree stmt)
@@ -1027,8 +1107,9 @@ fix_conditional_array_notations_1 (tree stmt)
tree *body_label, *body_label_expr, *exit_label, *exit_label_expr;
tree *compare_expr, *if_stmt_label, *expr_incr, *ind_init;
bool **count_down, **array_vector;
+ tree begin_var, lngth_var, strde_var;
location_t location = UNKNOWN_LOCATION;
-
+
if (TREE_CODE (stmt) == COND_EXPR)
cond = COND_EXPR_COND (stmt);
else if (TREE_CODE (stmt) == SWITCH_EXPR)
@@ -1037,7 +1118,11 @@ fix_conditional_array_notations_1 (tree stmt)
/* Otherwise dont even touch the statement. */
return stmt;
- find_rank (cond, false, &rank);
+ location = EXPR_LOCATION (stmt);
+
+ if (!find_rank (location, cond, cond, false, &rank))
+ return error_mark_node;
+
extract_array_notation_exprs (cond, false, &array_list);
loop = push_stmt_list ();
for (ii = 0; ii < vec_safe_length (array_list); ii++)
@@ -1062,7 +1147,9 @@ fix_conditional_array_notations_1 (tree stmt)
}
}
}
- find_rank (cond, true, &rank);
+
+ if (!find_rank (location, cond, cond, true, &rank))
+ return error_mark_node;
if (rank == 0)
{
add_stmt (stmt);
@@ -1076,7 +1163,6 @@ fix_conditional_array_notations_1 (tree stmt)
return stmt;
list_size = vec_safe_length (array_list);
- location = EXPR_LOCATION (stmt);
array_ops = XNEWVEC (tree *, list_size);
for (ii = 0; ii < list_size; ii++)
@@ -1115,6 +1201,42 @@ fix_conditional_array_notations_1 (tree stmt)
array_var = XNEWVEC (tree, rank);
+
+ for (ii = 0; ii < list_size; ii++)
+ {
+ tree array_node = (*array_list)[ii];
+ if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+ {
+ tree array_begin = ARRAY_NOTATION_START (array_node);
+ tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+ tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+
+ begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+ integer_type_node);
+ lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+ integer_type_node);
+ strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+ integer_type_node);
+
+ add_stmt (build_modify_expr (location, begin_var,
+ TREE_TYPE (begin_var),
+ NOP_EXPR, location, array_begin,
+ TREE_TYPE (array_begin)));
+ add_stmt (build_modify_expr (location, lngth_var,
+ TREE_TYPE (lngth_var),
+ NOP_EXPR, location, array_lngth,
+ TREE_TYPE (array_lngth)));
+ add_stmt (build_modify_expr (location, strde_var,
+ TREE_TYPE (strde_var),
+ NOP_EXPR, location, array_strde,
+ TREE_TYPE (array_strde)));
+
+ ARRAY_NOTATION_START (array_node) = begin_var;
+ ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+ ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+ }
+ }
+
for (ii = 0; ii < list_size; ii++)
{
tree array_node = (*array_list)[ii];
@@ -1174,7 +1296,6 @@ fix_conditional_array_notations_1 (tree stmt)
location,
build_int_cst (TREE_TYPE (array_var[ii]), 0),
TREE_TYPE (array_var[ii]));
-
}
for (ii = 0; ii < rank ; ii++)
@@ -1291,7 +1412,6 @@ fix_conditional_array_notations_1 (tree stmt)
XDELETEVEC (if_stmt_label);
XDELETEVEC (expr_incr);
XDELETEVEC (ind_init);
- // XDELETEVEC (array_var);
for (ii = 0; ii < list_size; ii++)
{
@@ -1354,7 +1474,15 @@ fix_array_notation_expr (location_t location, enum tree_code code,
tree *compare_expr, *if_stmt_label, *expr_incr, *ind_init;
bool **count_down, **array_vector;
- find_rank (arg.value, false, &rank);
+ if (!find_rank (location, arg.value, arg.value, false, &rank))
+ {
+ /* If this function returns a NULL, we convert the tree value in the
+ structure to error_mark_node and the parser should take care of the
+ rest. */
+ arg.value = error_mark_node;
+ return arg;
+ }
+
if (rank == 0)
return arg;
@@ -1413,6 +1541,8 @@ fix_array_notation_expr (location_t location, enum tree_code code,
jj++;
}
}
+
+ loop = push_stmt_list ();
for (ii = 0; ii < list_size; ii++)
{
@@ -1451,8 +1581,6 @@ fix_array_notation_expr (location_t location, enum tree_code code,
}
}
- loop = push_stmt_list ();
-
for (ii = 0; ii < rank; ii++)
{
array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
@@ -1531,12 +1659,10 @@ fix_array_notation_expr (location_t location, enum tree_code code,
replace_array_notations (&arg.value, true, array_list, array_operand);
for (ii = 0; ii < rank; ii++)
- {
- expr_incr[ii] =
- build2 (MODIFY_EXPR, void_type_node, array_var[ii],
- build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
- build_int_cst (TREE_TYPE (array_var[ii]), 1)));
- }
+ expr_incr[ii] =
+ build2 (MODIFY_EXPR, void_type_node, array_var[ii],
+ build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
+ build_int_cst (TREE_TYPE (array_var[ii]), 1)));
for (jj = 0; jj < rank; jj++)
{
@@ -1553,7 +1679,6 @@ fix_array_notation_expr (location_t location, enum tree_code code,
array_var[jj], array_length[0][jj]);
}
}
-
for (ii = 0; ii < rank; ii++)
{
@@ -1669,10 +1794,11 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
|| TREE_CODE (func_parm) == EXCESS_PRECISION_EXPR
|| TREE_CODE (func_parm) == NOP_EXPR)
func_parm = TREE_OPERAND (func_parm, 0);
-
- find_rank (an_builtin_fn, true, &rank);
location = EXPR_LOCATION (an_builtin_fn);
+
+ if (!find_rank (location, an_builtin_fn, an_builtin_fn, true, &rank))
+ return error_mark_node;
if (rank == 0)
return an_builtin_fn;
@@ -1680,7 +1806,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
&& (an_type == REDUCE_MAX_INDEX || an_type == REDUCE_MIN_INDEX))
{
error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot"
- " have arrays with dimension greater than 1.");
+ " have arrays with dimension greater than 1");
return error_mark_node;
}
@@ -1712,7 +1838,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
new_var_type = NULL_TREE;
break;
default:
- gcc_unreachable (); /* You should not reach here. */
+ gcc_unreachable ();
}
array_ops = XNEWVEC (tree *, list_size);
@@ -1879,12 +2005,11 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
}
replace_array_notations (&func_parm, true, array_list, array_operand);
for (ii = 0; ii < rank; ii++)
- {
- expr_incr[ii] =
- build2 (MODIFY_EXPR, void_type_node, array_var[ii],
- build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
- build_int_cst (TREE_TYPE (array_var[ii]), 1)));
- }
+ expr_incr[ii] =
+ build2 (MODIFY_EXPR, void_type_node, array_var[ii],
+ build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
+ build_int_cst (TREE_TYPE (array_var[ii]), 1)));
+
for (jj = 0; jj < rank; jj++)
{
@@ -2218,10 +2343,10 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
return loop;
}
-/* Returns true of FUNC_NAME is a builtin array notation function. The type of
+/* Returns true if FUNC_NAME is a builtin array notation function. The type of
function is returned in *TYPE. */
-bool
+static bool
is_builtin_array_notation_fn (tree func_name, an_reduce_type *type)
{
const char *function_name = NULL;
@@ -2310,7 +2435,7 @@ is_builtin_array_notation_fn (tree func_name, an_reduce_type *type)
}
-/* Returns true of EXPR (and its subtrees) contain ARRAY_NOTATION_EXPR node. */
+/* Returns true if EXPR (and its subtrees) contain ARRAY_NOTATION_EXPR node. */
bool
contains_array_notation_expr (tree expr)
@@ -2331,9 +2456,8 @@ contains_array_notation_expr (tree expr)
return true;
}
-/* Replaces array notations in void function call arguments in ARG with loop and
- tree-node ARRAY_REF and returns that value in a tree node variable called
- LOOP. */
+/* Replaces array notations in void function call arguments in ARG and returns
+ a STATEMENT_LIST. */
static tree
fix_array_notation_call_expr (tree arg)
@@ -2347,6 +2471,7 @@ fix_array_notation_call_expr (tree arg)
tree *body_label, *body_label_expr, *exit_label, *exit_label_expr;
tree *compare_expr, *if_stmt_label, *expr_incr, *ind_init;
bool **count_down, **array_vector;
+ tree begin_var, lngth_var, strde_var;
an_reduce_type an_type = REDUCE_UNKNOWN;
location_t location = UNKNOWN_LOCATION;
@@ -2359,12 +2484,13 @@ fix_array_notation_call_expr (tree arg)
return loop;
}
- find_rank (arg, false, &rank);
+ if (!find_rank (location, arg, arg, false, &rank))
+ return error_mark_node;
+
if (rank == 0)
return arg;
extract_array_notation_exprs (arg, true, &array_list);
-
if (vec_safe_length (array_list) == 0)
return arg;
@@ -2407,7 +2533,42 @@ fix_array_notation_call_expr (tree arg)
count_down[ii] = XNEWVEC (bool, rank);
array_var = XNEWVEC (tree, rank);
+
+ loop = push_stmt_list ();
+ for (ii = 0; ii < list_size; ii++)
+ {
+ tree array_node = (*array_list)[ii];
+ if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+ {
+ tree array_begin = ARRAY_NOTATION_START (array_node);
+ tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+ tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+ begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+ integer_type_node);
+ lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+ integer_type_node);
+ strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+ integer_type_node);
+
+ add_stmt (build_modify_expr (location, begin_var,
+ TREE_TYPE (begin_var),
+ NOP_EXPR, location, array_begin,
+ TREE_TYPE (array_begin)));
+ add_stmt (build_modify_expr (location, lngth_var,
+ TREE_TYPE (lngth_var),
+ NOP_EXPR, location, array_lngth,
+ TREE_TYPE (array_lngth)));
+ add_stmt (build_modify_expr (location, strde_var,
+ TREE_TYPE (strde_var),
+ NOP_EXPR, location, array_strde,
+ TREE_TYPE (array_strde)));
+
+ ARRAY_NOTATION_START (array_node) = begin_var;
+ ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+ ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+ }
+ }
for (ii = 0; ii < list_size; ii++)
{
jj = 0;
@@ -2457,8 +2618,6 @@ fix_array_notation_call_expr (tree arg)
}
}
- loop = push_stmt_list ();
-
for (ii = 0; ii < rank; ii++)
{
array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
@@ -2610,7 +2769,9 @@ fix_array_notation_call_expr (tree arg)
/* Walks through tree node T and find all the call-statments that do not return
- anything and fix up any array notations they may carry. */
+ anything and fix up any array notations they may carry. The return value
+ is the same type as T but with all array notations replaced with appropriate
+ STATEMENT_LISTS. */
tree
expand_array_notation_exprs (tree t)
@@ -2665,20 +2826,20 @@ build_array_notation_ref (location_t loc, tree array, tree start_index,
tree array_ntn_tree = NULL_TREE;
size_t stride_rank = 0, length_rank = 0, start_rank = 0;
- if (!TREE_TYPE (start_index) || !INTEGRAL_TYPE_P (TREE_TYPE (start_index)))
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (start_index)))
{
error_at (loc,
- "start-index of array notation triplet is not an integer.");
+ "start-index of array notation triplet is not an integer");
return error_mark_node;
}
- if (!TREE_TYPE (length) || !INTEGRAL_TYPE_P (TREE_TYPE (length)))
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (length)))
{
- error_at (loc, "length of array notation triplet is not an integer.");
+ error_at (loc, "length of array notation triplet is not an integer");
return error_mark_node;
}
- if (stride && (!TREE_TYPE (stride) || !INTEGRAL_TYPE_P (TREE_TYPE (stride))))
+ if (stride && !INTEGRAL_TYPE_P (TREE_TYPE (stride)))
{
- error_at (loc, "stride of array notation triplet is not an integer.");
+ error_at (loc, "stride of array notation triplet is not an integer");
return error_mark_node;
}
if (!stride)
@@ -2690,24 +2851,27 @@ build_array_notation_ref (location_t loc, tree array, tree start_index,
stride = build_int_cst (TREE_TYPE (start_index), 1);
}
- find_rank (start_index, false, &start_rank);
- find_rank (length, false, &length_rank);
- find_rank (stride, false, &stride_rank);
+ if (!find_rank (loc, start_index, start_index, false, &start_rank))
+ return error_mark_node;
+ if (!find_rank (loc, length, length, false, &length_rank))
+ return error_mark_node;
+ if (!find_rank (loc, stride, stride, false, &stride_rank))
+ return error_mark_node;
if (start_rank != 0)
{
error_at (loc, "rank of an array notation triplet's start-index is not "
- "zero.");
+ "zero");
return error_mark_node;
}
if (length_rank != 0)
{
- error_at (loc, "rank of an array notation triplet's length is not zero.");
+ error_at (loc, "rank of an array notation triplet's length is not zero");
return error_mark_node;
}
if (stride_rank != 0)
{
- error_at (loc, "rank of array notation triplet's stride is not zero.");
+ error_at (loc, "rank of array notation triplet's stride is not zero");
return error_mark_node;
}
@@ -2747,4 +2911,3 @@ find_correct_array_notation_type (tree op)
}
return return_type;
}
-
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index ba0a7f9..2ca5a3a 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11052,14 +11052,14 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
if (TREE_CODE (array_type) == POINTER_TYPE)
{
error_at (loc, "start-index and length fields necessary for "
- "using array notations in pointers.");
+ "using array notations in pointers");
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
return error_mark_node;
}
if (TREE_CODE (array_type) == FUNCTION_TYPE)
{
error_at (loc, "array notations cannot be used with function "
- "type.");
+ "type");
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
return error_mark_node;
}
@@ -11074,7 +11074,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
{
error_at (loc, "array notations cannot be used with "
- "function pointer arrays.");
+ "function pointer arrays");
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
NULL);
return error_mark_node;
@@ -11086,7 +11086,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
if (!array_type_domain)
{
error_at (loc, "start-index and length fields necessary for "
- "using array notations in dimensionless arrays.");
+ "using array notations in dimensionless arrays");
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
return error_mark_node;
}
@@ -11098,7 +11098,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
|| !TREE_CONSTANT (TYPE_MAXVAL (array_type_domain)))
{
error_at (loc, "start-index and length fields necessary for "
- "using array notations in variable-length arrays.");
+ "using array notations in variable-length arrays");
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
return error_mark_node;
}
@@ -11120,7 +11120,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
if (TREE_CODE (array_type) == FUNCTION_TYPE)
{
error_at (loc, "array notations cannot be used with function "
- "type.");
+ "type");
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
return error_mark_node;
}
@@ -11138,7 +11138,7 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE)
{
error_at (loc, "array notations cannot be used with "
- "function pointer arrays.");
+ "function pointer arrays");
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
NULL);
return error_mark_node;
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 15dc83d..cb2fe4a 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -2309,7 +2309,8 @@ build_array_ref (location_t loc, tree array, tree index)
if (flag_enable_cilkplus && contains_array_notation_expr (index))
{
size_t rank = 0;
- find_rank (index, true, &rank);
+ if (!find_rank (loc, index, index, true, &rank))
+ return error_mark_node;
if (rank > 1)
{
error_at (loc, "rank of the array's index is greater than 1.");
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 627bf69..3ce9969 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -82,6 +82,8 @@ extensions, accepted by GCC in C90 mode and in C++.
* x86 specific memory model extensions for transactional memory:: x86 memory models.
* Object Size Checking:: Built-in functions for limited buffer overflow
checking.
+* Cilk Plus Builtins:: Built-in functions that are part of Cilk Plus language
+ extension.
* Other Builtins:: Other built-in functions.
* Target Builtins:: Built-in functions specific to particular targets.
* Target Format Checks:: Format checks specific to particular targets.
@@ -8762,6 +8764,31 @@ Similar to @code{__builtin_bswap32}, except the argument and return types
are 64 bit.
@end deftypefn
+@node Cilk Plus Builtins
+@section Cilk Plus C/C++ language extension Built-in Functions.
+
+GCC provides support for the following built-in reduction funtions if Cilk Plus
+is enabled. Cilk Plus can be enabled using the @option{-fcilkplus} flag.
+
+@itemize @bullet
+@item __sec_reduce
+@item __sec_reduce_add
+@item __sec_reduce_all_nonzero
+@item __sec_reduce_all_zero
+@item __sec_reduce_any_nonzero
+@item __sec_reduce_any_zero
+@item __sec_reduce_max
+@item __sec_reduce_min
+@item __sec_reduce_max_ind
+@item __sec_reduce_min_ind
+@item __sec_reduce_mul
+@item __sec_reduce_mutating
+@end itemize
+
+Further details and examples about these built-in functions are described
+in the Cilk Plus language manual which can be found at
+@uref{http://www.cilkplus.org}.
+
@node Target Builtins
@section Built-in Functions Specific to Particular Target Machines
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
index 5fb3680..fd128b1 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/array_test2.c
@@ -26,7 +26,7 @@ int main(int argc, char **argv)
array[ii] = 10;
array2[ii] = 5000000;
}
- array2[0:10:2] = array[0:10:2];
+ array2[0:5:2] = array[0:5:2];
printf("==============================================\n");
for (ii = 0; ii<10; ii++)
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/cilkplus_AN_c_compile.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/cilkplus_AN_c_compile.exp
new file mode 100644
index 0000000..a965997
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/cilkplus_AN_c_compile.exp
@@ -0,0 +1,34 @@
+# Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+
+load_lib gcc-dg.exp
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/errors/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+dg-finish
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp
deleted file mode 100644
index 6d7604b..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/compile/compile.exp
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright (C) 2013 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
-
-
-load_lib gcc-dg.exp
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O0 -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O1 -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O2 -ftree-vectorize -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O3 -fcilkplus" " "
-dg-finish
-
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O0 -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O1 -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O3 -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/errors/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " "
-dg-finish
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/cilkplus_AN_c_errors.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/cilkplus_AN_c_errors.exp
new file mode 100644
index 0000000..a965997
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/cilkplus_AN_c_errors.exp
@@ -0,0 +1,34 @@
+# Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+
+load_lib gcc-dg.exp
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O0 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O1 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O3 -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/errors/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " "
+dg-finish
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c
index 44e7361..4035ed5 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/decl-ptr-colon.c
@@ -1,16 +1,16 @@
int main(void)
{
extern int func(int);
- int array3[:], x, q; /* { dg-error "array notations cannot be used in declaration." } */
- int array3[1:2:x]; /* { dg-error "array notations cannot be used in declaration." } */
- extern char array3[1:func(x)]; /* { dg-error "array notations cannot be used in declaration." } */
+ int array3[:], x, q; /* { dg-error "array notations cannot be used in declaration" } */
+ int array3[1:2:x]; /* { dg-error "array notations cannot be used in declaration" } */
+ extern char array3[1:func(x)]; /* { dg-error "array notations cannot be used in declaration" } */
int *a, ***b;
extern char *c;
int array2[10];
- a[:] = 5; /* { dg-error "start-index and length fields necessary for using array notations in pointers." } */
+ a[:] = 5; /* { dg-error "start-index and length fields necessary for using array notations in pointers" } */
c[1:2] = 3; /* This is OK. */
(array2)[:] = 5; /* This is OK. */
- b[1:2][1:func(x)][:] = 3; /* { dg-error "start-index and length fields necessary for using array notations in pointers." } */
+ b[1:2][1:func(x)][:] = 3; /* { dg-error "start-index and length fields necessary for using array notations in pointers" } */
}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/errors.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/errors.exp
deleted file mode 100644
index 6d7604b..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/errors.exp
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright (C) 2013 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
-
-
-load_lib gcc-dg.exp
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O0 -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O1 -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O2 -ftree-vectorize -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O3 -fcilkplus" " "
-dg-finish
-
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O0 -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O1 -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O3 -fcilkplus" " "
-dg-finish
-
-dg-init
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/errors/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " "
-dg-finish
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
index 272ef41..82008c0 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fn_ptr.c
@@ -3,16 +3,15 @@ typedef int (*foo)(int);
int main(int argc, char **argv)
{
int array[10], array2[10][10];
- // int array[10], array2[10], value, ii = 0;
foo func_array[10];
foo func_array2[10][10];
foo ***func_array_ptr;
- array[:] = func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */
- func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */
- func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */
- array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays." } */
- func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays." } */
+ array[:] = func_array[:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+ func_array[0:5](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+ func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+ array2[0:5][:] = func_array2[0:5][:](10); /* { dg-error "array notations cannot be used with function pointer arrays" } */
+ func_array_ptr[0:5][0:4][0:argc:2](argc); /* { dg-error "array notations cannot be used with function pointer arrays" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c
index ef39b2b..59c2d1e 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/fp_triplet_values.c
@@ -25,18 +25,18 @@ void func (int *x)
int main2 (int argc, char **argv)
{
int array[10], array2[10];
- array2[:] = array[1.5:2]; /* { dg-error "start-index of array notation triplet is not an integer." } */
- array2[:] = array[1:2.32333333333]; /* { dg-error "length of array notation triplet is not an integer." } */
- array2[1:2:1.5] = array[:]; /* { dg-error "stride of array notation triplet is not an integer." } */
- func (&array2[1:2.34:3]); /* { dg-error "length of array notation triplet is not an integer." } */
- array2[1.43:9]++; /* { dg-error "start-index of array notation triplet is not an integer." } */
- array2[1:9.3]++; /* { dg-error "length of array notation triplet is not an integer." } */
- array2[1:9:0.3]++; /* { dg-error "stride of array notation triplet is not an integer." } */
+ array2[:] = array[1.5:2]; /* { dg-error "start-index of array notation triplet is not an integer" } */
+ array2[:] = array[1:2.32333333333]; /* { dg-error "length of array notation triplet is not an integer" } */
+ array2[1:2:1.5] = array[:]; /* { dg-error "stride of array notation triplet is not an integer" } */
+ func (&array2[1:2.34:3]); /* { dg-error "length of array notation triplet is not an integer" } */
+ array2[1.43:9]++; /* { dg-error "start-index of array notation triplet is not an integer" } */
+ array2[1:9.3]++; /* { dg-error "length of array notation triplet is not an integer" } */
+ array2[1:9:0.3]++; /* { dg-error "stride of array notation triplet is not an integer" } */
- ++array2[1:q:3]; /* { dg-error "length of array notation triplet is not an integer." } */
- array2[:] = array[q:1:3]; /* { dg-error "start-index of array notation triplet is not an integer." } */
- array2[:] = array[1:q:3]; /* { dg-error "length of array notation triplet is not an integer." } */
- array2[:] = array[1:3:q]; /* { dg-error "stride of array notation triplet is not an integer." } */
- func (&array2[1:q:3]); /* { dg-error "length of array notation triplet is not an integer." } */
+ ++array2[1:q:3]; /* { dg-error "length of array notation triplet is not an integer" } */
+ array2[:] = array[q:1:3]; /* { dg-error "start-index of array notation triplet is not an integer" } */
+ array2[:] = array[1:q:3]; /* { dg-error "length of array notation triplet is not an integer" } */
+ array2[:] = array[1:3:q]; /* { dg-error "stride of array notation triplet is not an integer" } */
+ func (&array2[1:q:3]); /* { dg-error "length of array notation triplet is not an integer" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch2.c
new file mode 100644
index 0000000..77955a3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/errors/rank_mismatch2.c
@@ -0,0 +1,23 @@
+int function_call (int x)
+{
+ return x;
+}
+
+int main(int argc, char **argv)
+{
+ int array[100], array2[100][100];
+
+ array[:] = array[:] + array2[:][:]; /* { dg-error "rank mismatch in expression" } */
+
+ if (array[:] + array2[:][:]) /* { dg-error "rank mismatch in expression" } */
+ return argc == 5;
+
+ argc += function_call (array[:] + array2[5:10:2][:]); /* { dg-error "rank mismatch in expression" } */
+
+ argc += function_call (function_call (array[:] + array2[5:10:2][:])); /* { dg-error "rank mismatch in expression" } */
+
+ argc += __sec_reduce_add (array[:], array2[:][:]); /* { dg-error "rank mismatch in expression" } */
+
+ argc += __sec_reduce_add (array2[:][:]) + argc; /* This is OK. */
+ return argc;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/cilkplus_AN_c_execute.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/cilkplus_AN_c_execute.exp
new file mode 100644
index 0000000..37d22c5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/cilkplus_AN_c_execute.exp
@@ -0,0 +1,60 @@
+# Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# This file was written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+# Many thanks to the GCC C-torture contributors.
+
+verbose "$tool $libdir" 1
+
+set library_var [get_multilibs]
+dg-init
+set CILK_TORTURE_OPTIONS [list \
+ { -O0 -fcilkplus -std=c99} \
+ { -O1 -fcilkplus -std=c99} \
+ { -O2 -fcilkplus -std=c99} \
+ { -O3 -fcilkplus -fomit-frame-pointer -funroll-loops -std=c99} \
+ { -O3 -fcilkplus -fomit-frame-pointer -funroll-all-loops -finline-functions -std=c99 } \
+ { -O3 -fcilkplus -fomit-frame-pointer -funroll-all-loops -finline-functions -ftree-vectorize -std=c99 } \
+ { -O3 -g -fcilkplus -std=c99} \
+ { -Os -fcilkplus -std=c99} ]
+
+
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# load support procs
+load_lib torture-options.exp
+load_lib c-torture.exp
+
+torture-init
+set-torture-options $CILK_TORTURE_OPTIONS {{}} $CILK_TORTURE_OPTIONS
+
+#
+# main test loop
+#
+
+foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.c]] {
+ # If we're only testing specific files and this isn't one of them, skip it.
+ if ![runtest_file_p $runtests $src] then {
+ continue
+ }
+
+ c-torture-execute $src
+}
+
+torture-finish
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/exec-once2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/exec-once2.c
new file mode 100644
index 0000000..ba70ab8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/exec-once2.c
@@ -0,0 +1,82 @@
+#ifdef HAVE_IO
+#include <stdio.h>
+#endif
+
+
+int func1(int x)
+{
+ /* If x == 2 then it should return 0. */
+ return (x - 2);
+}
+
+int func2(int x)
+{
+ /* If x == 2 then it should return 1000. */
+ return (x * 500);
+}
+
+int func3 (int x)
+{
+ /* If x == 2 then it should return 1. */
+ /* If x == 1 then it should return 0. */
+ return (x-1);
+}
+
+int func4(int x)
+{
+ if (x > 0)
+ return x;
+ else
+ return x--;
+}
+
+
+/* This program makes an assumption that argc == 1. */
+int main (int argc, char **argv)
+{
+
+ int array[2500];
+
+ /* This should set array[0->999] to 5. */
+ array[argc-1:func2(++argc):1] = 5;
+ array[1000:500:1] = 10; /* set all variables in array[1000-->1499] to 10. */
+ array[1500:500:1] = 15; /* set all variables in array[1500-->1999] to 15. */
+ array[2000:500:1] = 20; /* set all variables in array[2000-->2499] to 20. */
+ array[2000:500:1] = 25; /* set all variables in array[2500-->2999] to 25. */
+ array[2000:500:1] = 30; /* set all variables in array[3000-->3499] to 30. */
+
+ argc = func3 (argc); /* This will set argc back to 1. */
+#if HAVE_IO
+ printf("argc = %d\n", argc);
+#endif
+ /* If the parameters inside the function get evaluated only once, then this
+ if statement must work fine, i.e. the triplet values will be 0, 1000, 1.
+
+ Otherwise, the program should crash or give some uneasy value. */
+
+ /* If done correctly, it should boil down to: array[0:1000:1]. */
+ if (array[func3(argc):func2(++argc)] != 5) {
+#ifdef HAVE_IO
+ printf ("Should not be there(1).\n");
+#endif
+ return 1;
+ }
+
+ /* If done correctly, it should boil down to: array[999:500:-1]. */
+ if (func4(array[func2(argc)-1:func2(argc--):func1(argc)]) != 5) {
+#ifdef HAVE_IO
+ printf ("Should not be there(2).\n");
+#endif
+ return 1;
+ }
+
+ /* If done correctly, it should boil down to: array[1000:500:1]. */
+ if (func4 (func4(array[func2(argc++):500: func1(argc--)])) != 5) {
+#ifdef HAVE_IO
+ printf ("Should not be there(3).\n");
+#endif
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp b/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp
deleted file mode 100644
index 37d22c5..0000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/array_notation/execute/execute.exp
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright (C) 2013 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-# This file was written by Balaji V. Iyer <balaji.v.iyer@intel.com>
-# Many thanks to the GCC C-torture contributors.
-
-verbose "$tool $libdir" 1
-
-set library_var [get_multilibs]
-dg-init
-set CILK_TORTURE_OPTIONS [list \
- { -O0 -fcilkplus -std=c99} \
- { -O1 -fcilkplus -std=c99} \
- { -O2 -fcilkplus -std=c99} \
- { -O3 -fcilkplus -fomit-frame-pointer -funroll-loops -std=c99} \
- { -O3 -fcilkplus -fomit-frame-pointer -funroll-all-loops -finline-functions -std=c99 } \
- { -O3 -fcilkplus -fomit-frame-pointer -funroll-all-loops -finline-functions -ftree-vectorize -std=c99 } \
- { -O3 -g -fcilkplus -std=c99} \
- { -Os -fcilkplus -std=c99} ]
-
-
-
-if $tracelevel then {
- strace $tracelevel
-}
-
-# load support procs
-load_lib torture-options.exp
-load_lib c-torture.exp
-
-torture-init
-set-torture-options $CILK_TORTURE_OPTIONS {{}} $CILK_TORTURE_OPTIONS
-
-#
-# main test loop
-#
-
-foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.c]] {
- # If we're only testing specific files and this isn't one of them, skip it.
- if ![runtest_file_p $runtests $src] then {
- continue
- }
-
- c-torture-execute $src
-}
-
-torture-finish