PIPS
array_bound_check_interprocedural.c
Go to the documentation of this file.
1 /*
2 
3  $Id: array_bound_check_interprocedural.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 /****************************************************************** *
28  *
29  * INTERPROCEDURAL ARRAY BOUND CHECKING
30  *
31  *
32 *******************************************************************/
33 /* This phase checks for out of bound error when passing arrays or array
34  elements as arguments in procedure call. It ensures that there is no bound
35  violation in every array access in the callee procedure, with respect to
36  the array declarations in the caller procedure
37 
38  The association rules for dummy and actual arrays in Fortran standard (ANSI)
39  Section 15.9.3.3 are verified by this checking
40 
41  * 1. If actual argument is an array name :
42  size(dummy_array) <= size(actual_array) (1)
43  * 2. Actual argument is an array element name :
44  * size(dummy_array) <= size(actual_array)+1-subscript_value(array element) (2)
45 
46  * Remarks to simplify our checking :
47  * 1. If the first k dimensions of the actual array and the dummy array are the same,
48  * we have (1) is equivalent with
49  * size_from_position(dummy_array,k+1) <= size_from_position(actual_array,k+1)
50  *
51  * 2. If the first k dimensions of the actual array and the dummy array are the same,
52  * and the first k subscripts of the array element are equal with their
53  * correspond lower bounds (column-major order), we have (2) is equivalent with:
54  *
55  * size_from_position(dummy_array,k+1) = size_from_position(actual_array,k+1) +1
56  * - subscript_value_from_position(array_element,k+1).
57 
58  ATTENTION : FORTRAN standard (15.9.3) says that an association of dummy and actual
59  arguments is valid only if the type of the actual argument is the same as the type
60  of the corresponding dummy argument. But in practice, not much program respect this
61  rule , so we have to multiply the array size by its element size in order to compare
62  2 arrays*/
63 
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include <string.h>
67 #include "genC.h"
68 #include "linear.h"
69 #include "ri.h"
70 #include "effects.h"
71 #include "ri-util.h"
72 #include "prettyprint.h"
73 #include "effects-util.h"
74 #include "text-util.h"
75 #include "database.h"
76 #include "pipsdbm.h"
77 #include "resources.h"
78 #include "misc.h"
79 #include "control.h"
80 #include "properties.h"
81 #include "semantics.h"
82 #include "transformer.h"
83 #include "conversion.h" /* for Psysteme_to_expression*/
84 #include "alias_private.h"
85 #include "instrumentation.h"
86 #include "transformations.h"
87 
88 /* As we create checks with stop error message who tell us there are
89  * bound violations for which array in which call, the following
90  * typedef array_test permits us to create a sequence of tests
91  * for each statement more easier.
92  * The functions interprocedural_abc_call,
93  * interprocedural_abc_expression return results of type
94  * array_test */
95 
96 #define PREFIX "$IABC"
97 
98 typedef struct array_test
99 {
103 
104 /* context data structure for interprocedural_abc newgen recursion */
105 typedef struct
106 {
109 }
112 
117 
119 {
122 }
123 
125 {
126  if (number_of_added_tests > 0)
127  user_log("* There %s %d array bound check%s added *\n",
128  number_of_added_tests > 1 ? "are" : "is",
130  number_of_added_tests > 1 ? "s" : "");
131 
133  user_log("* There %s %d bound violation%s *\n",
134  number_of_bound_violations > 1 ? "are" : "is",
136  number_of_bound_violations > 1 ? "s" : "");
141 }
142 
143 #define array_test_undefined ((array_test) {NIL,NIL})
144 
146 {
147  if ((x.arr == NIL) && (x.exp == NIL))
148  return true;
149  return false;
150 }
151 
152 static array_test
154 {
157  {
158  retour.arr = gen_nconc( CONS(ENTITY,e,NIL),NIL);
159  retour.exp = gen_nconc( CONS(EXPRESSION,exp,NIL),NIL);
160  }
161  return retour;
162 }
163 
164 static array_test
166 {
167  if (!array_test_undefined_p(temp))
168  {
169  if (array_test_undefined_p(retour))
170  return temp;
171  /* If in temp.exp, there are expressions that exist
172  * in retour.exp, we don't have
173  * to add those expressions to retour.exp */
174  while (!ENDP(temp.exp))
175  {
176  expression exp = EXPRESSION(CAR(temp.exp));
177  if (!same_expression_in_list_p(exp,retour.exp))
178  {
179  retour.arr = gen_nconc(CONS(ENTITY,ENTITY(CAR(temp.arr)),NIL),
180  retour.arr);
181  retour.exp = gen_nconc(CONS(EXPRESSION,exp,NIL),retour.exp);
182  }
183  temp.arr = CDR(temp.arr);
184  temp.exp = CDR(temp.exp);
185  }
186  }
187  return retour;
188 }
189 
190 
191 static expression size_of_dummy_array(entity dummy_array,int i)
192 {
193  variable dummy_var = type_variable(entity_type(dummy_array));
194  list l_dummy_dims = variable_dimensions(dummy_var);
195  int num_dim = gen_length(l_dummy_dims),j;
197  for (j=i+1; j<= num_dim; j++)
198  {
199  dimension dim_j = find_ith_dimension(l_dummy_dims,j);
200  expression lower_j = dimension_lower(dim_j);
201  expression upper_j = dimension_upper(dim_j);
202  expression size_j;
203  if (expression_constant_p(lower_j) && (expression_to_int(lower_j)==1))
204  size_j = copy_expression(upper_j);
205  else
206  {
207  size_j = binary_intrinsic_expression(MINUS_OPERATOR_NAME,upper_j,lower_j);
210  }
211  if (expression_undefined_p(e))
212  e = copy_expression(size_j);
213  else
215  }
216  ifdebug(2)
217  {
218  fprintf(stderr, "\n Size of dummy array: \n");
219  print_expression(e);
220  }
221  return e;
222 }
223 
226 {
227  /*This function returns a true expression if (e1 < e2) = TRUE
228  expression undefined if (e1 < e2) = FALSE
229  a test e1 < e2*/
232  ifdebug(3)
233  {
234  fprintf(stderr, "\n First expression e1: ");
235  print_expression(e1);
236  fprintf(stderr, "\n Second expression e2: ");
237  print_expression(e2);
238  fprintf(stderr, " \n e1 less e2 wrt to the precondition : ");
240  }
242  {
243  /* See if e is true or false if we have already the preconditions ps
244  * if ps := ps + e
245  * ps = sc_strong_normalize3(ps)
246  * if (ps = sc_empty) => not feasible, no bound violation
247  * if (ps = sc_rn) => bound violation
248  * else => test to put
249  */
250  Pvecteur v1 = normalized_linear(n1);
251  Pvecteur v2 = normalized_linear(n2);
252  Pvecteur v_init = vect_substract(v1,v2);
253  /* Trivial test : e1 = 1200, e2 = 1 => e1 < e2 = FALSE*/
254  if (vect_constant_p(v_init))
255  {
256  /* Tets if v_init < 0 */
257  if (VECTEUR_NUL_P(v_init)) return expression_undefined;; /* False => no bound violation*/
258  if (value_neg_p(val_of(v_init))) return make_true_expression();/* True => bound violation*/
259  if (value_posz_p(val_of(v_init))) return expression_undefined;/* False => no bound violation*/
260  }
261  else
262  {
263  /* Constraint form: v +1 <= 0*/
264  Pvecteur v_one = vect_new(TCST,1);
265  Pvecteur v = vect_add(v_init,v_one);
267  switch (sc_check_inequality_redundancy(contrainte_make(v), ps)) /* try fast check */
268  {
269  case 1: /* ok, e1<e2 is redundant wrt ps => bound violation*/
270  return make_true_expression();
271  case 2: /* ok, system {ps + {e1<e2}} is infeasible => no bound violation*/
272  return expression_undefined;
273  case 0: /* no result, try slow version */
274  {
275  Psysteme sc = sc_dup(ps);
276  Pvecteur pv_var = NULL;
277  Pbase b;
278  ifdebug(3)
279  {
280  fprintf(stderr, " \n System before add inequality: ");
281  sc_fprint(stderr,sc,(char * (*)(Variable)) entity_local_name);
282  }
283  sc_constraint_add(sc, contrainte_make(v), false);
284  ifdebug(3)
285  {
286  fprintf(stderr, " \n System after add inequality: ");
287  sc_fprint(stderr,sc,(char * (*)(Variable)) entity_local_name);
288  }
289  sc = sc_strong_normalize2(sc);
290  /* Attention : sc_strong_normalize3 returns SC_UNDEFINED for 103.su2cor*/
291  ifdebug(3)
292  {
293  fprintf(stderr, " \n System after strong normalize 2: ");
294  sc_fprint(stderr,sc,(char * (*)(Variable)) entity_local_name);
295  }
296  if (SC_UNDEFINED_P(sc) || sc_empty_p(sc))
297  return expression_undefined;
298  if (sc_rn_p(sc))
299  return make_true_expression();
300  /* Before using the system, we have to porject variables such as V#init from PIPS*/
301  b = sc->base;
302  for(; !VECTEUR_NUL_P(b);b = b->succ)
303  {
304  entity e = (entity) vecteur_var(b);
305  if (old_value_entity_p(e))
306  vect_add_elem(&pv_var, (Variable) e, VALUE_ONE);
307  }
308  if (pv_var!=NULL)
309  {
310  /* There are V#init variables */
311  ifdebug(3)
312  {
313  fprintf(stderr, " \n System before #init variables projection: ");
314  sc_fprint(stderr,sc,(char * (*)(Variable)) entity_local_name);
315  }
316  sc = sc_system_projection_along_variables(sc, pv_var);
317  ifdebug(3)
318  {
319  fprintf(stderr, " \n System after #init variables projection: ");
320  sc_fprint(stderr,sc,(char * (*)(Variable)) entity_local_name);
321  }
322  vect_rm(pv_var);
323  if (!SC_UNDEFINED_P(sc))
324  {
325  // the projection is exact
326  if (sc_rn_p(sc))
327  // the system is trivial true, there are bounds violation
328  return make_true_expression();
329  if (sc_empty_p(sc))
330  // system is infeasible, no bound violations
331  return expression_undefined;
332  return Psysteme_to_expression(sc);
333  }
334  // else : the projection is not exact => return the e1.LT.e2
335  }
336  else
337  return Psysteme_to_expression(sc);
338  }
339  }
340  }
341  }
342  return lt_expression(e1,e2);
343 }
344 
346  entity dummy_array,
347  list l_actual_ref, statement s)
348 {
350  expression dummy_array_size;
351  int same_dim = 0;
356  else
357  /* If statement is unreachable => do we need check here ?*/
359  /* Compute the number of same dimensions of the actual array, dummy array
360  and actual array element, based on association information, common variables,
361  preconditions for more informations) */
362  while (same_dimension_p(actual_array,dummy_array,l_actual_ref,same_dim+1,context))
363  same_dim ++;
364  ifdebug(2)
365  fprintf(stderr, "\n Number of same dimensions : %d \n",same_dim);
366  dummy_array_size = size_of_dummy_array(dummy_array,same_dim);
367  if (!expression_undefined_p(dummy_array_size))
368  {
369  /* same_dim < number of dimension of the dummy array*/
371  ifdebug(2)
372  {
373  fprintf(stderr, "\n Dummy array size before translation:\n");
374  print_expression(dummy_array_size);
375  }
376  /* translate the size of dummy array from the current callee to the
377  frame of current module */
379  dummy_array_size,c);
380  ifdebug(2)
381  {
382  fprintf(stderr, "\n Dummy array size after translation: \n");
383  print_expression(dummy_array_size);
384  }
385  if (!expression_undefined_p(dummy_array_size))
386  {
387  /* The size of the dummy array is translated to the caller's frame*/
388  expression actual_array_size = size_of_actual_array(actual_array,l_actual_ref,same_dim);
389  /* As the size of the dummy array is translated, we need only precondition of the call
390  in the current context*/
391  /* Now, compare the element size of actual and dummy arrays*/
392  basic b_dummy = variable_basic(type_variable(entity_type(dummy_array)));
393  basic b_actual = variable_basic(type_variable(entity_type(actual_array)));
394  int i_dummy = SizeOfElements(b_dummy);
395  int i_actual = SizeOfElements(b_actual);
396  if (!expression_undefined_p(actual_array_size))
397  {
398  /* same_dim < number of dimension of the actual array*/
399  if (i_dummy != i_actual)
400  {
401  /* Actual and formal arguments have different types*/
402  actual_array_size = binary_intrinsic_expression(MULTIPLY_OPERATOR_NAME,actual_array_size,
403  int_to_expression(i_actual));
404  dummy_array_size = binary_intrinsic_expression(MULTIPLY_OPERATOR_NAME,dummy_array_size,
405  int_to_expression(i_dummy));
406  }
407  if (!same_expression_p(dummy_array_size,actual_array_size))
408  retour = expression_less_than_in_context(actual_array_size,dummy_array_size,prec);
409  /* Add to Logfile some information:*/
410  if (!expression_undefined_p(retour))
411  user_log("%s\t%s\t%s\t%s\t%s\t%s\t%s\n",PREFIX,
412  entity_module_name(actual_array),
413  entity_local_name(actual_array),
414  expression_to_string(actual_array_size),
415  entity_module_name(dummy_array),
416  entity_local_name(dummy_array),
417  expression_to_string(dummy_array_size));
418  }
419  else
420  {
421  /* same_dim == number of dimension of the actual array
422  * If the size of the dummy array is greater than 1 => violation
423  * For example : actual array A(M,N), dummy array D(M,N,K) or D(M,N,1,K) */
424  if (i_dummy != i_actual)
425  {
426  /* Actual and formal arguments have different types*/
427  dummy_array_size = binary_intrinsic_expression(MULTIPLY_OPERATOR_NAME,dummy_array_size,
428  int_to_expression(i_dummy));
429  retour = expression_less_than_in_context(int_to_expression(i_actual),dummy_array_size,prec);
430  }
431  else
432  retour = expression_less_than_in_context(int_to_expression(1),dummy_array_size,prec);
433  }
434  }
435  else
436  pips_user_warning("Cannot translate the size of dummy array %s into module %s's frame\n",
438  /* This case is rare, because size of dummy array = constants or formal parameters or commons*/
439  }
440  /* else, dummy_array_size == expression_undefined because same_dim == number of
441  dimensions of dummy array, the inequation (1) or (2) is always true (suppose
442  that there is no intraprocedural bound violation) */
443  return retour;
444 }
445 
448 
450 {
451  /* More efficient : same call, same actual array ? */
453  entity f = call_function(c);
454  list l_args = call_arguments(c);
455  /* Traverse the argument list => check for argument which is a function call*/
456  MAP(EXPRESSION,e,
457  {
459  retour = add_array_test(retour,temp);
460  },
461  l_args);
462  /* ATTENTION : we have to compute the callgraph before (make CALLGRAPH_FILE[%ALL])
463  in order to have the initial value of f is recognized by PIPS as value code.
464  If not => core dumped. I should add a user warning here !!!*/
466  {
467  /* c is a call to a function or subroutine */
468  int i =1;
469  ifdebug(2)
470  {
471  fprintf(stderr, "\n Call to a function/subroutine:");
472  fprintf(stderr, "%s ", entity_name(f));
473  }
474  MAP(EXPRESSION,e,
475  {
476  if (array_argument_p(e))
477  {
479  entity actual_array = reference_variable(r);
480  if (!assumed_size_array_p(actual_array))
481  {
482  /* find corresponding formal argument in f :
483  f -> value -> code -> declaration -> formal variable
484  -> offset == i ?*/
485  list l_actual_ref = reference_indices(r);
486  list l_decls = code_declarations(entity_code(f));
487  MAP(ENTITY, dummy_array,
488  {
489  if (formal_parameter_p(dummy_array))
490  {
491  formal fo = storage_formal(entity_storage(dummy_array));
492  if (formal_offset(fo) == i)
493  {
494  /* We have found the corresponding dummy argument*/
495  if (!assumed_size_array_p(dummy_array))
496  {
497  expression check = interprocedural_abc_arrays(c,actual_array,
498  dummy_array,l_actual_ref,s);
499  if (!expression_undefined_p(check))
500  {
501  array_test tmp = make_array_test(actual_array,check);
502  retour = add_array_test(retour,tmp);
503  }
504  }
505  else
506  /* Formal parameter is an assumed-size array => what to do ?*/
507  pips_user_warning("Formal parameter %s is an assumed-size array\n",
508  entity_local_name(dummy_array));
509  break;
510  }
511  }
512  },
513  l_decls);
514  }
515  else
516  /* Actual argument is an assumed-size array => what to do ?*/
517  pips_user_warning("Actual argument %s is an assumed-size array\n",
518  entity_local_name(actual_array));
519  }
520  i++;
521  },
522  l_args);
523  }
524  return retour;
525 }
526 
528 {
530  if (expression_call_p(e))
532  return retour;
533 }
534 
536 {
537  list la = at.arr,le = at.exp;
539  while (!ENDP(la))
540  {
541  entity a = ENTITY(CAR(la));
542  expression e = EXPRESSION(CAR(le));
543  string stop_message = strdup(concatenate("\"Bound violation: array ",
544  entity_name(a),"\"", NULL));
545  string print_message = strdup(concatenate("\'BV array ",entity_name(a)," with ",
547  "\'",print_variables(e), NULL));
549  if (true_expression_p(e))
550  {
551  /* There is a bound violation, we can return a stop statement immediately,
552  but for debugging purpose, it is better to display all bound violations */
554  if (get_bool_property("PROGRAM_VERIFICATION_WITH_PRINT_MESSAGE"))
555  smt = make_print_statement(print_message);
556  else
557  smt = make_stop_statement(stop_message);
558  }
559  else
560  {
562  if (get_bool_property("PROGRAM_VERIFICATION_WITH_PRINT_MESSAGE"))
563  smt = test_to_statement(make_test(e, make_print_statement(print_message),
565  else
566  smt = test_to_statement(make_test(e, make_stop_statement(stop_message),
568  }
569  if (statement_undefined_p(retour))
570  retour = copy_statement(smt);
571  else
572  // always structured case
573  insert_statement(retour,copy_statement(smt),false);
574  la = CDR(la);
575  le = CDR(le);
576  }
577  ifdebug(3)
578  {
579  fprintf(stderr, " Returned statement:");
580  print_statement(retour);
581  }
582  return retour;
583 }
584 
587 {
588  /* If s is in an unstructured instruction, we must pay attention
589  when inserting s1 before s. */
591  {
592  /* take the control that has s as its statement */
594  if (stack_size(context->uns)>0)
595  {
596  /* take the unstructured correspond to the control c */
598  control newc;
599  ifdebug(2)
600  {
601  fprintf(stderr, "Unstructured case: \n");
602  print_statement(s);
603  }
604  /* for a consistent unstructured, a test must have 2 successors,
605  so if s1 is a test, we transform it into sequence in order
606  to avoid this constraint.
607  Then we create a new control for it, with the predecessors
608  are those of c and the only one successor is c.
609  The new predecessors of c are only the new control*/
610  if (statement_test_p(s1))
611  {
612  list seq = CONS(STATEMENT,s1,NIL);
614  make_sequence(seq)));
615  ifdebug(2)
616  {
617  fprintf(stderr, "Unstructured case, insert a test:\n");
619  print_statement(s2);
620  }
621  newc = make_control(s2, control_predecessors(c), CONS(CONTROL, c, NIL));
622  }
623  else
625  // replace c by newc as successor of each predecessor of c
626  MAP(CONTROL, co,
627  {
628  MAPL(lc,
629  {
630  if (CONTROL(CAR(lc))==c) CONTROL_(CAR(lc)) = newc;
631  }, control_successors(co));
632  },control_predecessors(c));
634  /* if c is the entry node of the correspond unstructured u,
635  the newc will become the new entry node of u */
636  if (unstructured_control(u)==c)
637  unstructured_control(u) = newc;
638  }
639  else
640  // there is no unstructured (?)
641  insert_statement(s,s1,true);
642  }
643  else
644  // structured case
645  insert_statement(s,s1,true);
646 }
647 
648 
650 {
652  tag t = instruction_tag(i);
653  switch(t)
654  {
655  case is_instruction_call:
656  {
657  call c = instruction_call(i);
658  array_test retour = interprocedural_abc_call(c,s);
659  if (!array_test_undefined_p(retour))
660  {
662  if (stop_statement_p(seq))
663  user_log("Bound violation !!!!\n");
664  // insert the STOP or the new sequence of tests before the current statement
666  }
667  break;
668  }
670  {
672  // check for function call in the while loop condition
675  if (!array_test_undefined_p(retour))
676  {
678  if (stop_statement_p(seq))
679  user_log("Bound violation !!!!\n");
680  // insert the STOP or the new sequence of tests before the current statement
682  }
683  break;
684  }
685  case is_instruction_test:
686  {
687  test it = instruction_test(i);
688  // check for function call in the test condition
689  expression e = test_condition(it);
691  if (!array_test_undefined_p(retour))
692  {
694  if (stop_statement_p(seq))
695  user_log("Bound violation !!!!\n");
696  // insert the STOP statement or the new sequence of tests before the current statement
698  }
699  break;
700  }
702  case is_instruction_loop:
703  // There is not function call in loop's range
705  /* because we use gen_recurse with statement domain,
706  * we don't have to check unstructured instruction here*/
707  break;
708  default:
709  pips_internal_error("Unexpected instruction tag %d ", t );
710  break;
711  }
712 }
713 
715 {
717  control_statement(c), c);
718  return true;
719 }
720 
722 {
723  stack_push((char *) u, context->uns);
724  return true;
725 }
726 
728 {
729  pips_assert("true", u==u && context==context);
730  stack_pop(context->uns);
731 }
732 
734 {
738 
743  NULL);
744 
746  stack_free(&context.uns);
747 }
748 
750 {
755  db_get_memory_resource(DBR_PRECONDITIONS,module_name,true));
757  debug_on("ARRAY_BOUND_CHECK_INTERPROCEDURAL_DEBUG_LEVEL");
758  ifdebug(1)
759  {
760  debug(1, "Interprocedural array bound check","Begin for %s\n", module_name);
761  pips_assert("Statement is consistent ...", statement_consistent_p(module_statement));
762  }
766  user_log("* The total number of added tests is %d *\n",
768  user_log("* The total number of bound violation is %d *\n",
770  module_reorder(module_statement); /*as bound checks are added*/
771  ifdebug(1)
772  {
773  pips_assert("Statement is consistent ...", statement_consistent_p(module_statement));
774  debug(1, "Interprocedural array bound check","End for %s\n", module_name);
775  }
776  debug_off();
781  return true;
782 }
783 
784 
785 
786 
787 
788 
void user_log(const char *format,...)
Definition: message.c:234
persistant_statement_to_control make_persistant_statement_to_control(void)
Definition: ri.c:1594
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
statement copy_statement(statement p)
STATEMENT.
Definition: ri.c:2186
bool statement_consistent_p(statement p)
Definition: ri.c:2195
test make_test(expression a1, statement a2, statement a3)
Definition: ri.c:2607
control apply_persistant_statement_to_control(persistant_statement_to_control f, statement k)
Definition: ri.c:1597
instruction make_instruction(enum instruction_utype tag, void *val)
Definition: ri.c:1166
bool bound_persistant_statement_to_control_p(persistant_statement_to_control f, statement k)
Definition: ri.c:1609
sequence make_sequence(list a)
Definition: ri.c:2125
control make_control(statement a1, list a2, list a3)
Definition: ri.c:523
void extend_persistant_statement_to_control(persistant_statement_to_control f, statement k, control v)
Definition: ri.c:1603
void free_persistant_statement_to_control(persistant_statement_to_control p)
Definition: ri.c:1561
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
static statement module_statement
Definition: alias_check.c:125
expression translate_to_module_frame(entity mod1, entity mod2, expression e1, call c)
This function translates an expression e1 from the frame of module 1 to the frame of module 2 1....
#define VALUE_ONE
#define value_neg_p(val)
#define value_posz_p(val)
string print_variables(expression e)
static statement make_interprocedural_abc_tests(array_test at)
static bool push_uns(unstructured u, interprocedural_abc_context_p context)
static expression interprocedural_abc_arrays(call c, entity actual_array, entity dummy_array, list l_actual_ref, statement s)
static void display_interprocedural_abc_statistics()
static array_test interprocedural_abc_call(call c, statement s)
static expression expression_less_than_in_context(expression e1, expression e2, transformer context)
static array_test add_array_test(array_test retour, array_test temp)
static int number_of_added_tests
struct array_test array_test
static int total_number_of_bound_violations
static void initialize_interprocedural_abc_statistics()
static void interprocedural_abc_insert_before_statement(statement s, statement s1, interprocedural_abc_context_p context)
static void interprocedural_abc_statement_rwt(statement s, interprocedural_abc_context_p context)
bool array_bound_check_interprocedural(const char *module_name)
array_bound_check_interprocedural.c
#define array_test_undefined
static bool array_test_undefined_p(array_test x)
static int number_of_bound_violations
static array_test interprocedural_abc_expression(expression e, statement s)
static void interprocedural_abc_statement(statement module_statement)
static array_test make_array_test(entity e, expression exp)
static expression size_of_dummy_array(entity dummy_array, int i)
struct interprocedural_abc_context_t * interprocedural_abc_context_p
static void pop_uns(unstructured u, interprocedural_abc_context_p context)
static bool store_mapping(control c, interprocedural_abc_context_p context)
#define PREFIX
This phase checks for out of bound error when passing arrays or array elements as arguments in proced...
static int total_number_of_added_tests
transformer transformer_dup(transformer t_in)
transformer package - basic routines
Definition: basic.c:49
transformer transformer_identity()
Allocate an identity transformer.
Definition: basic.c:110
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
Pcontrainte contrainte_make(Pvecteur pv)
Pcontrainte contrainte_make(Pvecteur pv): allocation et initialisation d'une contrainte avec un vecte...
Definition: alloc.c:73
bool vect_constant_p(Pvecteur)
bool vect_constant_p(Pvecteur v): v contains only a constant term, may be zero
Definition: predicats.c:211
expression Psysteme_to_expression(Psysteme)
system_to_code.c
static entity current_callee
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
statement make_block_statement(list)
Make a block statement from a list of statement.
Definition: statement.c:616
statement instruction_to_statement(instruction)
Build a statement from a give instruction.
Definition: statement.c:597
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define MAPL(_map_list_cp, _code, _l)
Apply some code on the addresses of all the elements of a list.
Definition: newgen_list.h:203
#define MAP(_map_CASTER, _map_item, _map_code, _map_list)
Apply/map an instruction block on all the elements of a list (old fashioned)
Definition: newgen_list.h:226
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
bool statement_test_p(statement)
Definition: statement.c:343
statement make_print_statement(string)
Make a Fortran print statement.
Definition: statement.c:835
statement make_stop_statement(string)
This function returns a Fortran stop statement with an error message.
Definition: statement.c:908
bool stop_statement_p(statement)
Test if a statement is a Fortran STOP.
Definition: statement.c:263
void insert_statement(statement, statement, bool)
This is the normal entry point.
Definition: statement.c:2570
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
#define debug_on(env)
Definition: misc-local.h:157
#define pips_user_warning
Definition: misc-local.h:146
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define debug_off()
Definition: misc-local.h:160
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
void * stack_head(const stack)
returns the item on top of stack s
Definition: stack.c:420
int stack_size(const stack)
observers
void stack_push(void *, stack)
stack use
Definition: stack.c:373
void stack_free(stack *)
type, bucket_size, policy
Definition: stack.c:292
stack stack_make(int, int, int)
allocation
Definition: stack.c:246
void * stack_pop(stack)
POPs one item from stack s.
Definition: stack.c:399
int tag
TAG.
Definition: newgen_types.h:92
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
hash_table set_ordering_to_statement(statement s)
To be used instead of initialize_ordering_to_statement() to make sure that the hash table ots is in s...
Definition: ordering.c:172
void reset_ordering_to_statement(void)
Reset the mapping from ordering to statement.
Definition: ordering.c:185
transformer fprint_transformer(FILE *fd, transformer tf, get_variable_name_t value_name)
Definition: io.c:69
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
string expression_to_string(expression e)
Definition: expression.c:77
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define MINUS_OPERATOR_NAME
#define PLUS_OPERATOR_NAME
#define NORMALIZE_EXPRESSION(e)
#define test_to_statement(t)
#define unstructured_control
After the modification in Newgen: unstructured = entry:control x exit:control we have create a macro ...
#define binary_intrinsic_expression(name, e1, e2)
#define MULTIPLY_OPERATOR_NAME
#define lt_expression(e1, e2)
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
bool assumed_size_array_p(entity e)
Definition: entity.c:807
entity local_name_to_top_level_entity(const char *n)
This function try to find a top-level entity from a local name.
Definition: entity.c:1450
code entity_code(entity e)
Definition: entity.c:1098
const char * entity_module_name(entity e)
See comments about module_name().
Definition: entity.c:1092
bool same_expression_in_list_p(expression e, list le)
This function returns true, if there exists a same expression in the list false, otherwise.
Definition: expression.c:557
bool expression_call_p(expression e)
Definition: expression.c:415
int expression_to_int(expression exp)
================================================================
Definition: expression.c:2205
bool true_expression_p(expression e)
Definition: expression.c:1113
expression size_of_actual_array(entity actual_array, list l_actual_ref, int i)
Definition: expression.c:4197
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
bool array_argument_p(expression e)
Definition: expression.c:513
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
bool same_expression_p(expression e1, expression e2)
this is slightly different from expression_equal_p, as it will return true for a+b vs b+a
Definition: expression.c:1426
expression make_true_expression()
Definition: expression.c:1103
dimension find_ith_dimension(list, int)
This function returns the ith dimension of a list of dimensions.
Definition: type.c:5621
bool formal_parameter_p(entity)
Definition: variable.c:1489
_int SizeOfElements(basic)
This function returns the length in bytes of the Fortran or C type represented by a basic,...
Definition: size.c:297
#define formal_offset(x)
Definition: ri.h:1408
#define value_code_p(x)
Definition: ri.h:3065
#define unstructured_domain
newgen_type_domain_defined
Definition: ri.h:442
#define CONTROL_(x)
Definition: ri.h:913
#define normalized_linear_p(x)
Definition: ri.h:1779
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define control_predecessors(x)
Definition: ri.h:943
struct _newgen_struct_unstructured_ * unstructured
Definition: ri.h:447
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define dimension_lower(x)
Definition: ri.h:980
#define type_variable(x)
Definition: ri.h:2949
#define entity_storage(x)
Definition: ri.h:2794
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define control_domain
newgen_controlmap_domain_defined
Definition: ri.h:98
#define code_declarations(x)
Definition: ri.h:784
#define CONTROL(x)
CONTROL.
Definition: ri.h:910
#define storage_formal(x)
Definition: ri.h:2524
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define expression_undefined
Definition: ri.h:1223
@ is_instruction_unstructured
Definition: ri.h:1475
@ is_instruction_whileloop
Definition: ri.h:1472
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_call
Definition: ri.h:1474
@ is_instruction_sequence
Definition: ri.h:1469
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define entity_name(x)
Definition: ri.h:2790
#define transformer_relation(x)
Definition: ri.h:2873
#define dimension_upper(x)
Definition: ri.h:982
#define reference_indices(x)
Definition: ri.h:2328
#define syntax_call(x)
Definition: ri.h:2736
#define control_successors(x)
Definition: ri.h:945
#define expression_undefined_p(x)
Definition: ri.h:1224
#define test_condition(x)
Definition: ri.h:2833
#define instruction_whileloop(x)
Definition: ri.h:1523
#define variable_dimensions(x)
Definition: ri.h:3122
#define statement_instruction(x)
Definition: ri.h:2458
#define instruction_call(x)
Definition: ri.h:1529
#define call_arguments(x)
Definition: ri.h:711
#define control_statement(x)
Definition: ri.h:941
#define instruction_test(x)
Definition: ri.h:1517
#define statement_undefined_p(x)
Definition: ri.h:2420
#define whileloop_condition(x)
Definition: ri.h:3160
#define entity_type(x)
Definition: ri.h:2792
#define normalized_linear(x)
Definition: ri.h:1781
#define expression_syntax(x)
Definition: ri.h:1247
#define predicate_system(x)
Definition: ri.h:2069
#define variable_basic(x)
Definition: ri.h:3120
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
bool sc_rn_p(Psysteme sc)
bool sc_rn_p(Psysteme sc): check if the set associated to sc is the whole space, rn
Definition: sc_alloc.c:369
bool sc_empty_p(Psysteme sc)
bool sc_empty_p(Psysteme sc): check if the set associated to sc is the constant sc_empty or not.
Definition: sc_alloc.c:350
Psysteme sc_dup(Psysteme ps)
Psysteme sc_dup(Psysteme ps): should becomes a link.
Definition: sc_alloc.c:176
int sc_check_inequality_redundancy(Pcontrainte ineq, Psysteme ps)
int sc_check_inequality_redundancy(Pcontrainte ineq, Psysteme ps) Check if an inequality ineq,...
Psysteme sc_constraint_add(Psysteme sc, Pcontrainte c, bool equality)
Definition: sc_insert_eq.c:115
void sc_fprint(FILE *fp, Psysteme ps, get_variable_name_t nom_var)
void sc_fprint(FILE * f, Psysteme ps, char * (*nom_var)()): cette fonction imprime dans le fichier po...
Definition: sc_io.c:220
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
Psysteme sc_strong_normalize2(volatile Psysteme ps)
Psysteme sc_strong_normalize2(Psysteme ps)
bool statement_weakly_feasible_p(statement)
utils.c
Definition: utils.c:72
transformer load_statement_precondition(statement)
void reset_precondition_map(void)
void set_precondition_map(statement_mapping)
s1
Definition: set.c:247
#define ifdebug(n)
Definition: sg.c:47
static char * x
Definition: split_file.c:159
Pbase base
Definition: sc-local.h:75
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
struct Svecteur * succ
Definition: vecteur-local.h:92
the stack head
Definition: stack.c:62
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: delay.c:253
context data structure for interprocedural_abc newgen recursion
transformer formal_and_actual_parameters_association(call c, transformer pre)
formal_and_actual_parameters_association(call c, transformer pre): Add equalities between actual and ...
Definition: transformer.c:2542
bool same_dimension_p(entity actual_array, entity dummy_array, list l_actual_ref, size_t i, transformer context)
This function returns true if the actual array and the dummy array have the same dimension number i,...
Definition: transformer.c:2665
bool old_value_entity_p(entity)
Definition: value.c:936
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define vecteur_var(v)
#define val_of(varval)
char *(* get_variable_name_t)(Variable)
Definition: vecteur-local.h:62
#define VECTEUR_NUL_P(v)
void * Variable
arithmetique is a requirement for vecteur, but I do not want to inforce it in all pips files....
Definition: vecteur-local.h:60
Pvecteur vect_new(Variable var, Value coeff)
Pvecteur vect_new(Variable var,Value coeff): allocation d'un vecteur colineaire au vecteur de base va...
Definition: alloc.c:110
void vect_rm(Pvecteur v)
void vect_rm(Pvecteur v): desallocation des couples de v;
Definition: alloc.c:78
Pvecteur vect_add(Pvecteur v1, Pvecteur v2)
package vecteur - operations binaires
Definition: binaires.c:53
Pvecteur vect_substract(Pvecteur v1, Pvecteur v2)
Pvecteur vect_substract(Pvecteur v1, Pvecteur v2): allocation d'un vecteur v dont la valeur est la di...
Definition: binaires.c:75
void vect_add_elem(Pvecteur *pvect, Variable var, Value val)
void vect_add_elem(Pvecteur * pvect, Variable var, Value val): addition d'un vecteur colineaire au ve...
Definition: unaires.c:72