Import pre-release gcc-5.0 to new vendor branch
[dragonfly.git] / contrib / gcc-5.0 / gcc / c-family / array-notation-common.c
1 /* This file is part of the Intel(R) Cilk(TM) Plus support
2    This file contains the builtin functions for Array
3    notations.
4    Copyright (C) 2013-2015 Free Software Foundation, Inc.
5    Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
6                   Intel Corporation
7
8 This file is part of GCC.
9
10 GCC is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3, or (at your option)
13 any later version.
14
15 GCC is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3.  If not see
22 <http://www.gnu.org/licenses/>.  */
23
24 #include "config.h"
25 #include "system.h" 
26 #include "coretypes.h"
27 #include "hash-set.h"
28 #include "machmode.h"
29 #include "vec.h"
30 #include "double-int.h"
31 #include "input.h"
32 #include "alias.h"
33 #include "symtab.h"
34 #include "options.h"
35 #include "wide-int.h"
36 #include "inchash.h"
37 #include "tree.h"
38 #include "langhooks.h" 
39 #include "tree-iterator.h"
40 #include "c-family/c-common.h"
41 #include "diagnostic-core.h"
42
43 /* Returns true if the function call in FNDECL is  __sec_implicit_index.  */
44
45 bool
46 is_sec_implicit_index_fn (tree fndecl)
47 {
48   if (!fndecl)
49     return false;
50
51   if (TREE_CODE (fndecl) == ADDR_EXPR)
52     fndecl = TREE_OPERAND (fndecl, 0);
53
54   return
55     (TREE_CODE (fndecl) == FUNCTION_DECL
56      && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
57      && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CILKPLUS_SEC_IMPLICIT_INDEX);
58 }
59
60 /* Returns the first and only argument for FN, which should be a
61    sec_implicit_index function.  FN's location in the source file is as 
62    indicated by LOCATION.  The argument to FN must be a constant integer
63    expression, otherwise returns -1.  */
64
65 HOST_WIDE_INT
66 extract_sec_implicit_index_arg (location_t location, tree fn)
67 {
68   tree fn_arg;
69   HOST_WIDE_INT return_int = 0;
70
71   if (TREE_CODE (fn) == CALL_EXPR)
72     {
73       fn_arg = CALL_EXPR_ARG (fn, 0);
74       if (TREE_CODE (fn_arg) == INTEGER_CST)
75         return_int = int_cst_value (fn_arg);
76       else
77         {
78           /* If the location is unknown, and if fn has a location, then use that
79              information so that the user has a better idea where the error
80              could be.  */
81           if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (fn))
82             location = EXPR_LOCATION (fn);
83           error_at (location, "__sec_implicit_index parameter must be an " 
84                     "integer constant expression");
85           return -1;
86         }
87     }
88   return return_int;
89 }
90
91 /* Returns true if there is a length mismatch among exprssions that are at the
92    same dimension and one the same side of the equal sign.  The Array notation
93    lengths (LIST->LENGTH) is passed in as a 2D vector of trees.  */
94
95 bool
96 length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
97 {
98   size_t ii, jj;
99   tree length = NULL_TREE;
100   
101   size_t x = list.length ();
102   size_t y = list[0].length ();
103   
104   for (jj = 0; jj < y; jj++)
105     {
106       length = NULL_TREE;
107       for (ii = 0; ii < x; ii++)
108         {
109           if (!length)
110             length = list[ii][jj].length;
111           else if (TREE_CODE (length) == INTEGER_CST)
112             {
113               /* If length is a INTEGER, and list[ii][jj] is an integer then
114                  check if they are equal.  If they are not equal then return
115                  true.  */
116               if (TREE_CODE (list[ii][jj].length) == INTEGER_CST
117                   && !tree_int_cst_equal (list[ii][jj].length, length))
118                 { 
119                   error_at (loc, "length mismatch in expression"); 
120                   return true;
121                 }
122             }
123           else
124             /* We set the length node as the current node just in case it turns
125                out to be an integer.  */
126             length = list[ii][jj].length;
127         }
128     }
129   return false;
130 }
131
132 /* Given an FNDECL of type FUNCTION_DECL or ADDR_EXPR, return the corresponding
133    BUILT_IN_CILKPLUS_SEC_REDUCE_* being called.  If none, return
134    BUILT_IN_NONE.  */
135
136 enum built_in_function
137 is_cilkplus_reduce_builtin (tree fndecl)
138 {
139   if (!fndecl)
140     return BUILT_IN_NONE;
141   if (TREE_CODE (fndecl) == ADDR_EXPR)
142     fndecl = TREE_OPERAND (fndecl, 0);
143
144   if (TREE_CODE (fndecl) == FUNCTION_DECL
145       && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
146     switch (DECL_FUNCTION_CODE (fndecl))
147       {
148       case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
149       case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
150       case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
151       case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
152       case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
153       case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
154       case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
155       case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
156       case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
157       case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
158       case BUILT_IN_CILKPLUS_SEC_REDUCE:
159       case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
160         return DECL_FUNCTION_CODE (fndecl);
161       default:
162         break;
163       }
164
165   return BUILT_IN_NONE;
166 }
167
168 /* This function will recurse into EXPR finding any
169    ARRAY_NOTATION_EXPRs and calculate the overall rank of EXPR,
170    storing it in *RANK. LOC is the location of the original expression.
171
172    ORIG_EXPR is the original expression used to display if any rank
173    mismatch errors are found.
174
175    Upon entry, *RANK must be either 0, or the rank of a parent
176    expression that must have the same rank as the one being
177    calculated.  It is illegal to have multiple array notation with different
178    rank in the same expression (see examples below for clarification).
179
180    If there were any rank mismatches while calculating the rank, an
181    error will be issued, and FALSE will be returned.  Otherwise, TRUE
182    is returned.  
183
184    If IGNORE_BUILTIN_FN is TRUE, ignore array notation specific
185    built-in functions (__sec_reduce_*, etc).
186
187    Here are some examples of array notations and their rank:
188
189    Expression                       RANK
190    5                                0
191    X (a variable)                   0
192    *Y (a pointer)                   0
193    A[5]                             0
194    B[5][10]                         0
195    A[:]                             1 
196    B[0:10]                          1
197    C[0:10:2]                        1
198    D[5][0:10:2]                     1 (since D[5] is considered "scalar")
199    D[5][:][10]                      1 
200    E[:] + 5                         1 
201    F[:][:][:] + 5 + X               3
202    F[:][:][:] + E[:] + 5 + X        RANKMISMATCH-ERROR since rank (E[:]) = 1 and
203                                     rank (F[:][:][:]) = 3.  They must be equal 
204                                     or have a rank of zero.
205    F[:][5][10] + E[:] * 5 + *Y      1
206
207    int func (int);
208    func (A[:])                      1
209    func (B[:][:][:][:])             4 
210    
211    int func2 (int, int)
212    func2 (A[:], B[:][:][:][:])      RANKMISMATCH-ERROR -- Since Rank (A[:]) = 1 
213                                     and Rank (B[:][:][:][:]) = 4
214
215    A[:] + func (B[:][:][:][:])      RANKMISMATCH-ERROR
216    func2 (A[:], B[:]) + func (A)    1 
217
218  */
219
220 bool
221 find_rank (location_t loc, tree orig_expr, tree expr, bool ignore_builtin_fn,
222            size_t *rank)
223 {
224   tree ii_tree;
225   size_t ii = 0, current_rank = 0;
226
227   if (TREE_CODE (expr) == ARRAY_NOTATION_REF)
228     {
229       ii_tree = expr;
230       while (ii_tree)
231         {
232           if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
233             {
234               current_rank++;
235               ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
236             }
237           else if (handled_component_p (ii_tree)
238                    || TREE_CODE (ii_tree) == INDIRECT_REF)
239             ii_tree = TREE_OPERAND (ii_tree, 0);
240           else if (TREE_CODE (ii_tree) == PARM_DECL
241                    || TREE_CODE (ii_tree) == VAR_DECL)
242             break;
243           else
244             gcc_unreachable ();
245         }
246       if (*rank == 0)
247         /* In this case, all the expressions this function has encountered thus
248            far have been scalars or expressions with zero rank.  Please see
249            header comment for examples of such expression.  */
250         *rank = current_rank;
251       else if (*rank != current_rank)
252         {
253           /* In this case, find rank is being recursed through a set of 
254              expression of the form A <OPERATION> B, where A and B both have
255              array notations in them and the rank of A is not equal to rank of
256              B.  
257              A simple example of such case is the following: X[:] + Y[:][:] */ 
258           *rank = current_rank;
259           return false;
260         }
261     }
262   else if (TREE_CODE (expr) == STATEMENT_LIST)
263     {
264       tree_stmt_iterator ii_tsi;
265       for (ii_tsi = tsi_start (expr); !tsi_end_p (ii_tsi);
266            tsi_next (&ii_tsi))
267         if (!find_rank (loc, orig_expr, *tsi_stmt_ptr (ii_tsi),
268                         ignore_builtin_fn, rank))
269           return false;
270     }
271   else
272     {
273       if (TREE_CODE (expr) == CALL_EXPR)
274         {
275           tree func_name = CALL_EXPR_FN (expr);
276           tree prev_arg = NULL_TREE, arg;
277           call_expr_arg_iterator iter;
278           size_t prev_rank = 0;
279           if (TREE_CODE (func_name) == ADDR_EXPR)
280             if (!ignore_builtin_fn)
281               if (is_cilkplus_reduce_builtin (func_name))
282                 /* If it is a built-in function, then we know it returns a 
283                    scalar.  */
284                 return true;
285           if (!find_rank (loc, orig_expr, func_name, ignore_builtin_fn, rank))
286             return false;
287           FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
288             {
289               if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
290                 {
291                   if (prev_arg && EXPR_HAS_LOCATION (prev_arg)
292                       && prev_rank != *rank)
293                     error_at (EXPR_LOCATION (prev_arg),
294                               "rank mismatch between %qE and %qE", prev_arg,
295                               arg);
296                   else if (prev_arg && prev_rank != *rank)
297                     /* Here the original expression is printed as a "heads-up"
298                        to the programmer.  This is because since there is no 
299                        location information for the offending argument, the 
300                        error could be in some internally generated code that is
301                        not visible for the programmer.  Thus, the correct fix
302                        may lie in the original expression.  */
303                     error_at (loc, "rank mismatch in expression %qE",
304                               orig_expr);
305                   return false;
306                 }
307               prev_arg = arg;
308               prev_rank = *rank;
309             }   
310         }
311       else
312         {
313           tree prev_arg = NULL_TREE;
314           for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (expr)); ii++)
315             {
316               if (TREE_OPERAND (expr, ii)
317                   && !find_rank (loc, orig_expr, TREE_OPERAND (expr, ii),
318                                  ignore_builtin_fn, rank))
319                 {
320                   if (prev_arg && EXPR_HAS_LOCATION (prev_arg))
321                     error_at (EXPR_LOCATION (prev_arg),
322                               "rank mismatch between %qE and %qE", prev_arg,
323                               TREE_OPERAND (expr, ii));
324                   return false;
325                 }
326               prev_arg = TREE_OPERAND (expr, ii);
327             }
328         }
329     }
330   return true;
331 }
332
333 /* Extracts all array notations in NODE and stores them in ARRAY_LIST.  If 
334    IGNORE_BUILTIN_FN is set, then array notations inside array notation
335    specific built-in functions are ignored.  The NODE can be constants,
336    VAR_DECL, PARM_DECLS, STATEMENT_LISTS or full expressions.   */
337
338 void
339 extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
340                               vec<tree, va_gc> **array_list)
341 {
342   size_t ii = 0;  
343
344   if (!node)
345     return;
346   if (TREE_CODE (node) == ARRAY_NOTATION_REF)
347     {
348       vec_safe_push (*array_list, node);
349       return;
350     }
351   if (TREE_CODE (node) == DECL_EXPR)
352     {
353       tree x = DECL_EXPR_DECL (node);
354       if (DECL_INITIAL (x))
355         extract_array_notation_exprs (DECL_INITIAL (x),
356                                       ignore_builtin_fn,
357                                       array_list);
358     }
359   else if (TREE_CODE (node) == STATEMENT_LIST)
360     {
361       tree_stmt_iterator ii_tsi;
362       for (ii_tsi = tsi_start (node); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
363         extract_array_notation_exprs (*tsi_stmt_ptr (ii_tsi),
364                                       ignore_builtin_fn, array_list);
365     }
366   else if (TREE_CODE (node) == CALL_EXPR)
367     {
368       tree arg;
369       call_expr_arg_iterator iter;
370       if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (node)))
371         {
372           if (ignore_builtin_fn)
373             return;
374           else
375             {
376               vec_safe_push (*array_list, node);
377               return;
378             }
379         }
380       if (is_sec_implicit_index_fn (CALL_EXPR_FN (node)))
381         {
382           vec_safe_push (*array_list, node);
383           return;
384         }
385       /* This will extract array notations in function pointers.  */
386       extract_array_notation_exprs (CALL_EXPR_FN (node), ignore_builtin_fn,
387                                     array_list);
388       FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
389         extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
390     } 
391   else 
392     for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++) 
393       if (TREE_OPERAND (node, ii))
394         extract_array_notation_exprs (TREE_OPERAND (node, ii),
395                                       ignore_builtin_fn, array_list);
396   return;
397 }
398
399 /* LIST contains all the array notations found in *ORIG and ARRAY_OPERAND
400    contains the expanded ARRAY_REF.  E.g., if LIST[<some_index>] contains
401    an array_notation expression, then ARRAY_OPERAND[<some_index>] contains its
402    expansion.  If *ORIG matches LIST[<some_index>] then *ORIG is set to
403    ARRAY_OPERAND[<some_index>].  This function recursively steps through
404    all the sub-trees of *ORIG, if it is larger than a single
405    ARRAY_NOTATION_REF.  */
406
407 void
408 replace_array_notations (tree *orig, bool ignore_builtin_fn,
409                          vec<tree, va_gc> *list,
410                          vec<tree, va_gc> *array_operand)
411 {
412   size_t ii = 0;
413   extern tree build_c_cast (location_t, tree, tree);
414   tree node = NULL_TREE, node_replacement = NULL_TREE;
415   
416   if (vec_safe_length (list) == 0)
417     return;
418
419   if (TREE_CODE (*orig) == ARRAY_NOTATION_REF)
420     {
421       for (ii = 0; vec_safe_iterate (list, ii, &node); ii++) 
422         if (*orig == node)
423           {
424             node_replacement = (*array_operand)[ii];
425             *orig = node_replacement;
426           }
427     }
428   else if (TREE_CODE (*orig) == STATEMENT_LIST)
429     {
430       tree_stmt_iterator ii_tsi;
431       for (ii_tsi = tsi_start (*orig); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
432         replace_array_notations (tsi_stmt_ptr (ii_tsi), ignore_builtin_fn, list,
433                                  array_operand);
434     }
435   else if (TREE_CODE (*orig) == CALL_EXPR)
436     {
437       tree arg;
438       call_expr_arg_iterator iter;
439       if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (*orig)))
440         {
441           if (!ignore_builtin_fn)
442             {
443               for (ii = 0; vec_safe_iterate (list, ii, &node); ii++) 
444                 if (*orig == node)
445                   {
446                     node_replacement = (*array_operand)[ii];
447                     *orig = node_replacement;
448                   }
449             }
450           return;
451         }
452       if (is_sec_implicit_index_fn (CALL_EXPR_FN (*orig)))
453         {
454           for (ii = 0; vec_safe_iterate (list, ii, &node); ii++)
455             if (*orig == node)
456               {
457                 node_replacement = (*array_operand)[ii];
458                 *orig = build_c_cast (EXPR_LOCATION (*orig),
459                                       TREE_TYPE (*orig), node_replacement);
460               }
461           return;
462         }
463       /* Fixes array notations in array notations in function pointers.  */
464       replace_array_notations (&CALL_EXPR_FN (*orig), ignore_builtin_fn, list,
465                                array_operand);
466       ii = 0;
467       FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
468         {
469           replace_array_notations (&arg, ignore_builtin_fn, list,
470                                    array_operand);
471           CALL_EXPR_ARG (*orig, ii) = arg;
472           ii++;
473         }     
474     }
475   else
476     {
477       for (ii = 0; ii < (size_t) TREE_CODE_LENGTH (TREE_CODE (*orig)); ii++) 
478         if (TREE_OPERAND (*orig, ii))
479           replace_array_notations (&TREE_OPERAND (*orig, ii), ignore_builtin_fn,
480                                    list, array_operand);
481     }
482   return;
483 }
484
485 /* Callback for walk_tree.  Find all the scalar expressions in *TP and push 
486    them in DATA struct, typecasted to (void *).  If *WALK_SUBTREES is set to 0 
487    then do not go into the *TP's subtrees.  Since this function steps through 
488    all the subtrees, *TP and TP can be NULL_TREE and NULL, respectively.  The 
489    function returns NULL_TREE unconditionally.  */
490
491 tree
492 find_inv_trees (tree *tp, int *walk_subtrees, void *data)
493 {
494   struct inv_list *i_list = (struct inv_list *) data;
495   unsigned int ii = 0;
496
497   if (!tp || !*tp)
498     return NULL_TREE;
499   if (TREE_CONSTANT (*tp))
500     return NULL_TREE; /* No need to save constant to a variable.  */
501   if (TREE_CODE (*tp) != COMPOUND_EXPR && !contains_array_notation_expr (*tp))
502     {
503       vec_safe_push (i_list->list_values, *tp);
504       *walk_subtrees = 0;
505     }
506   else if (TREE_CODE (*tp) == ARRAY_NOTATION_REF
507            || TREE_CODE (*tp) == ARRAY_REF
508            || TREE_CODE (*tp) == CALL_EXPR)
509     /* No need to step through the internals of array notation.  */
510     *walk_subtrees = 0;
511   else
512     {
513       *walk_subtrees = 1;
514
515       /* This function is used by C and C++ front-ends.  In C++, additional
516          tree codes such as TARGET_EXPR must be eliminated.  These codes are
517          passed into additional_tcodes and are walked through and checked.  */
518       for (ii = 0; ii < vec_safe_length (i_list->additional_tcodes); ii++)
519         if (TREE_CODE (*tp) == (*(i_list->additional_tcodes))[ii])
520           *walk_subtrees = 0;
521     }
522   return NULL_TREE;
523 }
524
525 /* Callback for walk_tree.  Replace all the scalar expressions in *TP with the 
526    appropriate replacement stored in the struct *DATA (typecasted to void*).  
527    The subtrees are not touched if *WALK_SUBTREES is set to zero.  */
528
529 tree
530 replace_inv_trees (tree *tp, int *walk_subtrees, void *data)
531 {
532   size_t ii = 0;
533   tree t, r;
534   struct inv_list *i_list = (struct inv_list *) data;
535
536   if (vec_safe_length (i_list->list_values))
537     {
538       for (ii = 0; vec_safe_iterate (i_list->list_values, ii, &t); ii++)
539         if (simple_cst_equal (*tp, t) == 1)
540           {
541             vec_safe_iterate (i_list->replacement, ii, &r);
542             gcc_assert (r != NULL_TREE);
543             *tp = r;
544             *walk_subtrees = 0;
545           }
546     }
547   else
548     *walk_subtrees = 0;
549   return NULL_TREE;
550 }
551
552 /* Returns true if EXPR or any of its subtrees contain ARRAY_NOTATION_EXPR 
553    node.  */
554
555 bool
556 contains_array_notation_expr (tree expr)
557 {
558   vec<tree, va_gc> *array_list = NULL;
559
560   if (!expr)
561     return false;
562   if (TREE_CODE (expr) == FUNCTION_DECL)
563     if (is_cilkplus_reduce_builtin (expr))
564       return true;
565   
566   extract_array_notation_exprs (expr, false, &array_list);
567   if (vec_safe_length (array_list) == 0)
568     return false;
569   else
570     return true;
571 }
572
573 /* This function will check if OP is a CALL_EXPR that is a built-in array 
574    notation function.  If so, then we will return its type to be the type of
575    the array notation inside.  */
576
577 tree
578 find_correct_array_notation_type (tree op)
579 {
580   tree fn_arg, return_type = NULL_TREE;
581
582   if (op)
583     {
584       return_type = TREE_TYPE (op); /* This is the default case.  */
585       if (TREE_CODE (op) == CALL_EXPR) 
586         if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (op))) 
587           { 
588             fn_arg = CALL_EXPR_ARG (op, 0); 
589             if (fn_arg) 
590               return_type = TREE_TYPE (fn_arg); 
591           }
592     } 
593   return return_type;
594 }
595
596 /* Extracts all the array notation triplet information from LIST and stores
597    them in the following fields of the 2-D array NODE(size x rank):
598    START, LENGTH and STRIDE, holding the starting index, length, and stride,
599    respectively.  In addition, it also sets two bool fields, IS_VECTOR and
600    COUNT_DOWN, in NODE indicating whether a certain value at a certain field
601    is a vector and if the array is accessed from high to low.  */
602
603 void
604 cilkplus_extract_an_triplets (vec<tree, va_gc> *list, size_t size, size_t rank,
605                               vec<vec<struct cilkplus_an_parts> > *node)
606 {
607   vec<vec<tree> > array_exprs = vNULL;
608
609   node->safe_grow_cleared (size);
610   array_exprs.safe_grow_cleared (size);
611
612   if (rank > 0)
613     for (size_t ii = 0; ii < size; ii++)
614       {
615         (*node)[ii].safe_grow_cleared (rank);
616         array_exprs[ii].safe_grow_cleared (rank);
617       }
618   for (size_t ii = 0; ii < size; ii++)
619     {
620       size_t jj = 0;
621       tree ii_tree = (*list)[ii];
622       while (ii_tree)
623         {
624           if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
625             {
626               array_exprs[ii][jj] = ii_tree;
627               jj++;
628               ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
629             }
630           else if (TREE_CODE (ii_tree) == ARRAY_REF)
631             ii_tree = TREE_OPERAND (ii_tree, 0);
632           else
633             break;
634         }
635     }
636     for (size_t ii = 0; ii < size; ii++)
637       if (TREE_CODE ((*list)[ii]) == ARRAY_NOTATION_REF)
638         for (size_t jj = 0; jj < rank; jj++)
639           {
640             tree ii_tree = array_exprs[ii][jj];
641             (*node)[ii][jj].is_vector = true;
642             (*node)[ii][jj].value = ARRAY_NOTATION_ARRAY (ii_tree);
643             (*node)[ii][jj].start = ARRAY_NOTATION_START (ii_tree);
644             (*node)[ii][jj].length =
645               fold_build1 (CONVERT_EXPR, integer_type_node,
646                            ARRAY_NOTATION_LENGTH (ii_tree));
647             (*node)[ii][jj].stride =
648               fold_build1 (CONVERT_EXPR, integer_type_node,
649                            ARRAY_NOTATION_STRIDE (ii_tree));
650           }
651 }
652
653 /* Replaces all the __sec_implicit_arg functions in LIST with the induction
654    variable stored in VAR at the appropriate location pointed by the
655    __sec_implicit_arg's first parameter.  Emits an error if the parameter is
656    not between 0 and RANK.  */
657
658 vec <tree, va_gc> *
659 fix_sec_implicit_args (location_t loc, vec <tree, va_gc> *list,
660                        vec<an_loop_parts> an_loop_info, size_t rank,
661                        tree orig_stmt)
662 {
663   vec <tree, va_gc> *array_operand = NULL;
664   for (size_t ii = 0; ii < vec_safe_length (list); ii++)
665     if (TREE_CODE ((*list)[ii]) == CALL_EXPR
666         && is_sec_implicit_index_fn (CALL_EXPR_FN ((*list)[ii])))
667       {
668         int idx = extract_sec_implicit_index_arg (loc, (*list)[ii]);
669         if (idx < 0)
670           /* In this case, the returning function would have emitted an
671              error thus it is not necessary to do so again.  */
672           return NULL;
673         else if (idx < (int) rank)
674           vec_safe_push (array_operand, an_loop_info[idx].var);
675         else
676           {
677             error_at (loc, "__sec_implicit_index argument %d must be "
678                       "less than the rank of %qE", idx, orig_stmt);
679             return NULL;
680           }
681       }
682     else
683       /* Save the existing value into the array operand.  */
684       vec_safe_push (array_operand, (*list)[ii]);
685   return array_operand;
686 }