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