PIPS
array_bound_check_interprocedural.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "genC.h"
#include "linear.h"
#include "ri.h"
#include "effects.h"
#include "ri-util.h"
#include "prettyprint.h"
#include "effects-util.h"
#include "text-util.h"
#include "database.h"
#include "pipsdbm.h"
#include "resources.h"
#include "misc.h"
#include "control.h"
#include "properties.h"
#include "semantics.h"
#include "transformer.h"
#include "conversion.h"
#include "alias_private.h"
#include "instrumentation.h"
#include "transformations.h"
+ Include dependency graph for array_bound_check_interprocedural.c:

Go to the source code of this file.

Data Structures

struct  array_test
 
struct  interprocedural_abc_context_t
 context data structure for interprocedural_abc newgen recursion More...
 

Macros

#define PREFIX   "$IABC"
 This phase checks for out of bound error when passing arrays or array elements as arguments in procedure call. More...
 
#define array_test_undefined   ((array_test) {NIL,NIL})
 

Typedefs

typedef struct array_test array_test
 
typedef struct interprocedural_abc_context_tinterprocedural_abc_context_p
 

Functions

static void initialize_interprocedural_abc_statistics ()
 
static void display_interprocedural_abc_statistics ()
 
static bool array_test_undefined_p (array_test x)
 
static array_test make_array_test (entity e, expression exp)
 
static array_test add_array_test (array_test retour, array_test temp)
 
static expression size_of_dummy_array (entity dummy_array, int i)
 
static expression expression_less_than_in_context (expression e1, expression e2, transformer context)
 
static expression interprocedural_abc_arrays (call c, entity actual_array, entity dummy_array, list l_actual_ref, statement s)
 
static array_test interprocedural_abc_call (call c, statement s)
 
static array_test interprocedural_abc_expression (expression e, statement s)
 
static statement make_interprocedural_abc_tests (array_test at)
 
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)
 
static bool store_mapping (control c, interprocedural_abc_context_p context)
 
static bool push_uns (unstructured u, interprocedural_abc_context_p context)
 
static void pop_uns (unstructured u, interprocedural_abc_context_p context)
 
static void interprocedural_abc_statement (statement module_statement)
 
bool array_bound_check_interprocedural (const char *module_name)
 array_bound_check_interprocedural.c More...
 

Variables

static int number_of_added_tests
 
static int number_of_bound_violations
 
static int total_number_of_added_tests = 0
 
static int total_number_of_bound_violations = 0
 

Macro Definition Documentation

◆ array_test_undefined

#define array_test_undefined   ((array_test) {NIL,NIL})

Definition at line 143 of file array_bound_check_interprocedural.c.

◆ PREFIX

#define PREFIX   "$IABC"

This phase checks for out of bound error when passing arrays or array elements as arguments in procedure call.

It ensures that there is no bound violation in every array access in the callee procedure, with respect to the array declarations in the caller procedure

The association rules for dummy and actual arrays in Fortran standard (ANSI) Section 15.9.3.3 are verified by this checking

  1. If actual argument is an array name : size(dummy_array) <= size(actual_array) (1)
  2. Actual argument is an array element name : size(dummy_array) <= size(actual_array)+1-subscript_value(array element) (2)

Remarks to simplify our checking :

  1. If the first k dimensions of the actual array and the dummy array are the same, we have (1) is equivalent with
    size_from_position(dummy_array,k+1) <= size_from_position(actual_array,k+1)
  2. If the first k dimensions of the actual array and the dummy array are the same, and the first k subscripts of the array element are equal with their correspond lower bounds (column-major order), we have (2) is equivalent with:

size_from_position(dummy_array,k+1) = size_from_position(actual_array,k+1) +1

  • subscript_value_from_position(array_element,k+1).

ATTENTION : FORTRAN standard (15.9.3) says that an association of dummy and actual arguments is valid only if the type of the actual argument is the same as the type of the corresponding dummy argument. But in practice, not much program respect this rule , so we have to multiply the array size by its element size in order to compare 2 arrays for Psysteme_to_expression As we create checks with stop error message who tell us there are bound violations for which array in which call, the following typedef array_test permits us to create a sequence of tests for each statement more easier. The functions interprocedural_abc_call, interprocedural_abc_expression return results of type array_test

Definition at line 96 of file array_bound_check_interprocedural.c.

Typedef Documentation

◆ array_test

typedef struct array_test array_test

◆ interprocedural_abc_context_p

Function Documentation

◆ add_array_test()

static array_test add_array_test ( array_test  retour,
array_test  temp 
)
static

If in temp.exp, there are expressions that exist in retour.exp, we don't have to add those expressions to retour.exp

Definition at line 165 of file array_bound_check_interprocedural.c.

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 }
static bool array_test_undefined_p(array_test x)
#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
#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
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
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207

References array_test::arr, array_test_undefined_p(), CAR, CDR, CONS, ENDP, ENTITY, exp, array_test::exp, EXPRESSION, gen_nconc(), NIL, and same_expression_in_list_p().

Referenced by interprocedural_abc_call().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ array_bound_check_interprocedural()

bool array_bound_check_interprocedural ( const char *  module_name)

array_bound_check_interprocedural.c

s bound checks are added

Parameters
module_nameodule_name

Definition at line 749 of file array_bound_check_interprocedural.c.

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 }
void user_log(const char *format,...)
Definition: message.c:234
bool statement_consistent_p(statement p)
Definition: ri.c:2195
static statement module_statement
Definition: alias_check.c:125
static void display_interprocedural_abc_statistics()
static int total_number_of_bound_violations
static void initialize_interprocedural_abc_statistics()
static void interprocedural_abc_statement(statement module_statement)
static int total_number_of_added_tests
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
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
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
#define debug_on(env)
Definition: misc-local.h:157
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#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
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
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
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
void reset_precondition_map(void)
void set_precondition_map(statement_mapping)
#define ifdebug(n)
Definition: sg.c:47

References db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug(), debug_off, debug_on, display_interprocedural_abc_statistics(), ifdebug, initialize_interprocedural_abc_statistics(), interprocedural_abc_statement(), local_name_to_top_level_entity(), module_name(), module_reorder(), module_statement, pips_assert, reset_current_module_entity(), reset_ordering_to_statement(), reset_precondition_map(), set_current_module_entity(), set_ordering_to_statement(), set_precondition_map(), statement_consistent_p(), total_number_of_added_tests, total_number_of_bound_violations, and user_log().

+ Here is the call graph for this function:

◆ array_test_undefined_p()

static bool array_test_undefined_p ( array_test  x)
static

Definition at line 145 of file array_bound_check_interprocedural.c.

146 {
147  if ((x.arr == NIL) && (x.exp == NIL))
148  return true;
149  return false;
150 }
static char * x
Definition: split_file.c:159

References NIL, and x.

Referenced by add_array_test(), and interprocedural_abc_statement_rwt().

+ Here is the caller graph for this function:

◆ display_interprocedural_abc_statistics()

static void display_interprocedural_abc_statistics ( )
static

Definition at line 124 of file array_bound_check_interprocedural.c.

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 }
static int number_of_added_tests
static int number_of_bound_violations

References number_of_added_tests, number_of_bound_violations, total_number_of_added_tests, total_number_of_bound_violations, and user_log().

Referenced by array_bound_check_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ expression_less_than_in_context()

static expression expression_less_than_in_context ( expression  e1,
expression  e2,
transformer  context 
)
static

his function returns a true expression if (e1 < e2) = TRUE expression undefined if (e1 < e2) = FALSE a test e1 < e2

See if e is true or false if we have already the preconditions ps if ps := ps + e ps = sc_strong_normalize3(ps) if (ps = sc_empty) => not feasible, no bound violation if (ps = sc_rn) => bound violation else => test to put

Trivial test : e1 = 1200, e2 = 1 => e1 < e2 = FALSE

Tets if v_init < 0

False => no bound violation

True => bound violation

False => no bound violation

Constraint form: v +1 <= 0

try fast check

ok, e1<e2 is redundant wrt ps => bound violation

ok, system {ps + {e1<e2}} is infeasible => no bound violation

no result, try slow version

Attention : sc_strong_normalize3 returns SC_UNDEFINED for 103.su2cor

Before using the system, we have to porject variables such as V::init from PIPS

There are V::init variables

Definition at line 224 of file array_bound_check_interprocedural.c.

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 }
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
#define VALUE_ONE
#define value_neg_p(val)
#define value_posz_p(val)
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
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
#define NORMALIZE_EXPRESSION(e)
#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
expression make_true_expression()
Definition: expression.c:1103
#define normalized_linear_p(x)
Definition: ri.h:1779
#define expression_undefined
Definition: ri.h:1223
#define transformer_relation(x)
Definition: ri.h:2873
#define normalized_linear(x)
Definition: ri.h:1781
#define predicate_system(x)
Definition: ri.h:2069
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 ...
Psysteme sc_strong_normalize2(volatile Psysteme ps)
Psysteme sc_strong_normalize2(Psysteme ps)
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
Definition: delay.c:253
bool old_value_entity_p(entity)
Definition: value.c:936
#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

References Ssysteme::base, contrainte_make(), entity_local_name(), expression_undefined, fprint_transformer(), fprintf(), ifdebug, lt_expression, make_true_expression(), NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, old_value_entity_p(), predicate_system, print_expression(), Psysteme_to_expression(), sc_check_inequality_redundancy(), sc_constraint_add(), sc_dup(), sc_empty_p(), sc_fprint(), sc_rn_p(), sc_strong_normalize2(), Svecteur::succ, TCST, transformer_relation, val_of, value_neg_p, VALUE_ONE, value_posz_p, vect_add(), vect_add_elem(), vect_constant_p(), vect_new(), vect_rm(), vect_substract(), VECTEUR_NUL_P, and vecteur_var.

Referenced by interprocedural_abc_arrays().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ initialize_interprocedural_abc_statistics()

static void initialize_interprocedural_abc_statistics ( )
static

Definition at line 118 of file array_bound_check_interprocedural.c.

119 {
122 }

References number_of_added_tests, and number_of_bound_violations.

Referenced by array_bound_check_interprocedural().

+ Here is the caller graph for this function:

◆ interprocedural_abc_arrays()

static expression interprocedural_abc_arrays ( call  c,
entity  actual_array,
entity  dummy_array,
list  l_actual_ref,
statement  s 
)
static

If statement is unreachable => do we need check here ?

Compute the number of same dimensions of the actual array, dummy array and actual array element, based on association information, common variables,
preconditions for more informations)

same_dim < number of dimension of the dummy array

translate the size of dummy array from the current callee to the frame of current module

The size of the dummy array is translated to the caller's frame

As the size of the dummy array is translated, we need only precondition of the call in the current context

Now, compare the element size of actual and dummy arrays

same_dim < number of dimension of the actual array

Actual and formal arguments have different types

Add to Logfile some information:

same_dim == number of dimension of the actual array If the size of the dummy array is greater than 1 => violation For example : actual array A(M,N), dummy array D(M,N,K) or D(M,N,1,K)

Actual and formal arguments have different types

This case is rare, because size of dummy array = constants or formal parameters or commons

else, dummy_array_size == expression_undefined because same_dim == number of dimensions of dummy array, the inequation (1) or (2) is always true (suppose that there is no intraprocedural bound violation)

Definition at line 345 of file array_bound_check_interprocedural.c.

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 }
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....
static expression expression_less_than_in_context(expression e1, expression e2, transformer context)
static expression size_of_dummy_array(entity dummy_array, int i)
#define PREFIX
This phase checks for out of bound error when passing arrays or array elements as arguments in proced...
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
static entity current_callee
if(!(yy_init))
Definition: genread_lex.c:1029
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#define pips_user_warning
Definition: misc-local.h:146
string expression_to_string(expression e)
Definition: expression.c:77
#define binary_intrinsic_expression(name, e1, e2)
#define MULTIPLY_OPERATOR_NAME
const char * entity_module_name(entity e)
See comments about module_name().
Definition: entity.c:1092
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 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
_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 call_function(x)
Definition: ri.h:709
#define type_variable(x)
Definition: ri.h:2949
#define expression_undefined_p(x)
Definition: ri.h:1224
#define entity_type(x)
Definition: ri.h:2792
#define variable_basic(x)
Definition: ri.h:3120
bool statement_weakly_feasible_p(statement)
utils.c
Definition: utils.c:72
transformer load_statement_precondition(statement)
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

References binary_intrinsic_expression, call_function, current_callee, entity_local_name(), entity_module_name(), entity_type, expression_less_than_in_context(), expression_to_string(), expression_undefined, expression_undefined_p, formal_and_actual_parameters_association(), fprintf(), get_current_module_entity(), ifdebug, int_to_expression(), load_statement_precondition(), MULTIPLY_OPERATOR_NAME, pips_user_warning, PREFIX, print_expression(), same_dimension_p(), same_expression_p(), size_of_actual_array(), size_of_dummy_array(), SizeOfElements(), statement_weakly_feasible_p(), transformer_dup(), transformer_identity(), translate_to_module_frame(), type_variable, user_log(), and variable_basic.

Referenced by interprocedural_abc_call().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ interprocedural_abc_call()

static array_test interprocedural_abc_call ( call  c,
statement  s 
)
static

More efficient : same call, same actual array ?

Traverse the argument list => check for argument which is a function call

ATTENTION : we have to compute the callgraph before (make CALLGRAPH_FILE[ALL]) in order to have the initial value of f is recognized by PIPS as value code. If not => core dumped. I should add a user warning here !!!

c is a call to a function or subroutine

find corresponding formal argument in f : f -> value -> code -> declaration -> formal variable -> offset == i ?

We have found the corresponding dummy argument

Formal parameter is an assumed-size array => what to do ?

Actual argument is an assumed-size array => what to do ?

Definition at line 449 of file array_bound_check_interprocedural.c.

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 }
static expression interprocedural_abc_arrays(call c, entity actual_array, entity dummy_array, list l_actual_ref, statement s)
static array_test add_array_test(array_test retour, array_test temp)
#define array_test_undefined
static array_test interprocedural_abc_expression(expression e, statement s)
static array_test make_array_test(entity e, expression exp)
#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
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
bool assumed_size_array_p(entity e)
Definition: entity.c:807
code entity_code(entity e)
Definition: entity.c:1098
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 formal_parameter_p(entity)
Definition: variable.c:1489
#define formal_offset(x)
Definition: ri.h:1408
#define value_code_p(x)
Definition: ri.h:3065
#define reference_variable(x)
Definition: ri.h:2326
#define entity_storage(x)
Definition: ri.h:2794
#define code_declarations(x)
Definition: ri.h:784
#define storage_formal(x)
Definition: ri.h:2524
#define entity_name(x)
Definition: ri.h:2790
#define reference_indices(x)
Definition: ri.h:2328
#define call_arguments(x)
Definition: ri.h:711
#define entity_initial(x)
Definition: ri.h:2796
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References add_array_test(), array_argument_p(), array_test_undefined, assumed_size_array_p(), call_arguments, call_function, code_declarations, ENTITY, entity_code(), entity_initial, entity_local_name(), entity_name, entity_storage, EXPRESSION, expression_reference(), expression_undefined_p, f(), formal_offset, formal_parameter_p(), fprintf(), ifdebug, interprocedural_abc_arrays(), interprocedural_abc_expression(), make_array_test(), MAP, pips_user_warning, reference_indices, reference_variable, storage_formal, and value_code_p.

Referenced by interprocedural_abc_expression(), and interprocedural_abc_statement_rwt().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ interprocedural_abc_expression()

static array_test interprocedural_abc_expression ( expression  e,
statement  s 
)
static

Definition at line 527 of file array_bound_check_interprocedural.c.

528 {
530  if (expression_call_p(e))
532  return retour;
533 }
static array_test interprocedural_abc_call(call c, statement s)
bool expression_call_p(expression e)
Definition: expression.c:415
#define syntax_call(x)
Definition: ri.h:2736
#define expression_syntax(x)
Definition: ri.h:1247

References array_test_undefined, expression_call_p(), expression_syntax, interprocedural_abc_call(), and syntax_call.

Referenced by interprocedural_abc_call(), and interprocedural_abc_statement_rwt().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ interprocedural_abc_insert_before_statement()

static void interprocedural_abc_insert_before_statement ( statement  s,
statement  s1,
interprocedural_abc_context_p  context 
)
static

If s is in an unstructured instruction, we must pay attention when inserting s1 before s.

take the control that has s as its statement

take the unstructured correspond to the control c

for a consistent unstructured, a test must have 2 successors, so if s1 is a test, we transform it into sequence in order to avoid this constraint.
Then we create a new control for it, with the predecessors are those of c and the only one successor is c. The new predecessors of c are only the new control

if c is the entry node of the correspond unstructured u, the newc will become the new entry node of u

Definition at line 585 of file array_bound_check_interprocedural.c.

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 }
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
statement instruction_to_statement(instruction)
Build a statement from a give instruction.
Definition: statement.c:597
#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
bool statement_test_p(statement)
Definition: statement.c:343
void insert_statement(statement, statement, bool)
This is the normal entry point.
Definition: statement.c:2570
void * stack_head(const stack)
returns the item on top of stack s
Definition: stack.c:420
int stack_size(const stack)
observers
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
#define unstructured_control
After the modification in Newgen: unstructured = entry:control x exit:control we have create a macro ...
#define CONTROL_(x)
Definition: ri.h:913
#define control_predecessors(x)
Definition: ri.h:943
struct _newgen_struct_unstructured_ * unstructured
Definition: ri.h:447
#define CONTROL(x)
CONTROL.
Definition: ri.h:910
@ is_instruction_sequence
Definition: ri.h:1469
#define control_successors(x)
Definition: ri.h:945
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
s1
Definition: set.c:247

References apply_persistant_statement_to_control(), bound_persistant_statement_to_control_p(), CAR, CONS, CONTROL, CONTROL_, control_predecessors, control_successors, fprintf(), ifdebug, insert_statement(), instruction_to_statement(), is_instruction_sequence, make_control(), make_instruction(), make_sequence(), MAP, MAPL, NIL, print_statement(), s1, stack_head(), stack_size(), STATEMENT, statement_test_p(), and unstructured_control.

Referenced by interprocedural_abc_statement_rwt().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ interprocedural_abc_statement()

static void interprocedural_abc_statement ( statement  module_statement)
static

Definition at line 733 of file array_bound_check_interprocedural.c.

734 {
738 
743  NULL);
744 
746  stack_free(&context.uns);
747 }
persistant_statement_to_control make_persistant_statement_to_control(void)
Definition: ri.c:1594
void free_persistant_statement_to_control(persistant_statement_to_control p)
Definition: ri.c:1561
static bool push_uns(unstructured u, interprocedural_abc_context_p context)
static void interprocedural_abc_statement_rwt(statement s, interprocedural_abc_context_p context)
static void pop_uns(unstructured u, interprocedural_abc_context_p context)
static bool store_mapping(control c, interprocedural_abc_context_p context)
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
void stack_free(stack *)
type, bucket_size, policy
Definition: stack.c:292
stack stack_make(int, int, int)
allocation
Definition: stack.c:246
#define unstructured_domain
newgen_type_domain_defined
Definition: ri.h:442
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define control_domain
newgen_controlmap_domain_defined
Definition: ri.h:98
context data structure for interprocedural_abc newgen recursion

References control_domain, free_persistant_statement_to_control(), gen_context_multi_recurse(), gen_null(), gen_true(), interprocedural_abc_statement_rwt(), make_persistant_statement_to_control(), module_statement, pop_uns(), push_uns(), stack_free(), stack_make(), statement_domain, store_mapping(), and unstructured_domain.

Referenced by array_bound_check_interprocedural().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ interprocedural_abc_statement_rwt()

static void interprocedural_abc_statement_rwt ( statement  s,
interprocedural_abc_context_p  context 
)
static

because we use gen_recurse with statement domain, we don't have to check unstructured instruction here

Definition at line 649 of file array_bound_check_interprocedural.c.

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 }
static statement make_interprocedural_abc_tests(array_test at)
static void interprocedural_abc_insert_before_statement(statement s, statement s1, interprocedural_abc_context_p context)
bool stop_statement_p(statement)
Test if a statement is a Fortran STOP.
Definition: statement.c:263
#define pips_internal_error
Definition: misc-local.h:149
int tag
TAG.
Definition: newgen_types.h:92
@ 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_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define test_condition(x)
Definition: ri.h:2833
#define instruction_whileloop(x)
Definition: ri.h:1523
#define statement_instruction(x)
Definition: ri.h:2458
#define instruction_call(x)
Definition: ri.h:1529
#define instruction_test(x)
Definition: ri.h:1517
#define whileloop_condition(x)
Definition: ri.h:3160

References array_test_undefined_p(), instruction_call, instruction_tag, instruction_test, instruction_whileloop, interprocedural_abc_call(), interprocedural_abc_expression(), interprocedural_abc_insert_before_statement(), is_instruction_call, is_instruction_loop, is_instruction_sequence, is_instruction_test, is_instruction_unstructured, is_instruction_whileloop, make_interprocedural_abc_tests(), pips_internal_error, statement_instruction, stop_statement_p(), test_condition, user_log(), and whileloop_condition.

Referenced by interprocedural_abc_statement().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ make_array_test()

static array_test make_array_test ( entity  e,
expression  exp 
)
static

Definition at line 153 of file array_bound_check_interprocedural.c.

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 }

References array_test::arr, array_test_undefined, CONS, ENTITY, exp, array_test::exp, EXPRESSION, expression_undefined_p, gen_nconc(), and NIL.

Referenced by interprocedural_abc_call().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ make_interprocedural_abc_tests()

static statement make_interprocedural_abc_tests ( array_test  at)
static

There is a bound violation, we can return a stop statement immediately, but for debugging purpose, it is better to display all bound violations

Definition at line 535 of file array_bound_check_interprocedural.c.

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 }
statement copy_statement(statement p)
STATEMENT.
Definition: ri.c:2186
test make_test(expression a1, statement a2, statement a3)
Definition: ri.c:2607
string print_variables(expression e)
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 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
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define test_to_statement(t)
bool true_expression_p(expression e)
Definition: expression.c:1113
#define statement_undefined_p(x)
Definition: ri.h:2420
#define statement_undefined
Definition: ri.h:2419
char * strdup()

References array_test::arr, CAR, CDR, concatenate(), copy_statement(), ENDP, ENTITY, entity_name, array_test::exp, EXPRESSION, expression_to_string(), fprintf(), get_bool_property(), ifdebug, insert_statement(), make_block_statement(), make_print_statement(), make_stop_statement(), make_test(), NIL, number_of_added_tests, number_of_bound_violations, print_statement(), print_variables(), statement_undefined, statement_undefined_p, strdup(), test_to_statement, and true_expression_p().

Referenced by interprocedural_abc_statement_rwt().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pop_uns()

static void pop_uns ( unstructured  u,
interprocedural_abc_context_p  context 
)
static

Definition at line 727 of file array_bound_check_interprocedural.c.

728 {
729  pips_assert("true", u==u && context==context);
730  stack_pop(context->uns);
731 }
void * stack_pop(stack)
POPs one item from stack s.
Definition: stack.c:399

References pips_assert, and stack_pop().

Referenced by interprocedural_abc_statement().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ push_uns()

static bool push_uns ( unstructured  u,
interprocedural_abc_context_p  context 
)
static

Definition at line 721 of file array_bound_check_interprocedural.c.

722 {
723  stack_push((char *) u, context->uns);
724  return true;
725 }
void stack_push(void *, stack)
stack use
Definition: stack.c:373

References stack_push().

Referenced by interprocedural_abc_statement().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ size_of_dummy_array()

static expression size_of_dummy_array ( entity  dummy_array,
int  i 
)
static

Definition at line 191 of file array_bound_check_interprocedural.c.

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 }
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
size_t gen_length(const list l)
Definition: list.c:150
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
#define MINUS_OPERATOR_NAME
#define PLUS_OPERATOR_NAME
int expression_to_int(expression exp)
================================================================
Definition: expression.c:2205
dimension find_ith_dimension(list, int)
This function returns the ith dimension of a list of dimensions.
Definition: type.c:5621
#define dimension_lower(x)
Definition: ri.h:980
#define dimension_upper(x)
Definition: ri.h:982
#define variable_dimensions(x)
Definition: ri.h:3122

References binary_intrinsic_expression, copy_expression(), dimension_lower, dimension_upper, entity_type, expression_constant_p(), expression_to_int(), expression_undefined, expression_undefined_p, find_ith_dimension(), fprintf(), gen_length(), ifdebug, int_to_expression(), MINUS_OPERATOR_NAME, MULTIPLY_OPERATOR_NAME, PLUS_OPERATOR_NAME, print_expression(), type_variable, and variable_dimensions.

Referenced by interprocedural_abc_arrays().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ store_mapping()

static bool store_mapping ( control  c,
interprocedural_abc_context_p  context 
)
static

Definition at line 714 of file array_bound_check_interprocedural.c.

715 {
717  control_statement(c), c);
718  return true;
719 }
void extend_persistant_statement_to_control(persistant_statement_to_control f, statement k, control v)
Definition: ri.c:1603
#define control_statement(x)
Definition: ri.h:941

References control_statement, and extend_persistant_statement_to_control().

Referenced by interprocedural_abc_statement().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ number_of_added_tests

◆ number_of_bound_violations

◆ total_number_of_added_tests

int total_number_of_added_tests = 0
static

◆ total_number_of_bound_violations

int total_number_of_bound_violations = 0
static