PIPS
alias_check.c
Go to the documentation of this file.
1 /*
2 
3  $Id: alias_check.c 23495 2018-10-24 09:19:47Z 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  * ALIAS VERIFICATION
30  *
31  *
32  In Fortran 77, parameters are passed by address in such a way that,
33  as long as the actual argument is associated with a named storage
34  location, the called subprogram can change the value of the actual
35  argument by assigning a value to the corresponding formal parameter.
36  So new aliases can be created between formal parameters if the same
37  actual argument is passed to two or more formal parameters, or
38  between formal parameters and global parameters if an actual
39  argument is an object in common storage which is also visible in the
40  called subprogram or other subprograms in the call chain below it.
41 
42  Restrictions on association of entities in Fortran 77 (Section 15.9.3.6
43  ANSI83) say that neither aliased formal parameters nor the variable
44  in the common block may become defined during execution of the called
45  subprogram or the others subprograms in the call chain.
46 
47  This phase verifies statically if the program violates the standard
48  restriction on alias or not by using information from the alias
49  propagation phase. If these informations are not known at compile-time,
50  we instrument the code with tests that check the violation dynamically
51  during execution of program.
52 
53  For each alias_association of a formal variable F, check for 2 cases:
54 
55  Case 1: there is other formal variable F' that has a same section by an
56  included call path => test(F,F')
57 
58  Case 2:
59  2.1 there is a common variable W in current module that has same section
60  with F => test(F,W)
61  2.2 there is a common variable V in some callee (direct and indirect) of the
62  current module that has same section with F => test(F,V)
63 
64  Test(A,B):
65  1. No intersection between A and B => OK
66  2. Intersection
67  2.1 no write on one variable => OK
68  2.2 write on one varibale => violation
69  2.3 Undecidable
70  3. Undecidable
71 
72  In case of undecidable, we try to repeat Test(A,B) in one higher call site
73  in the call path. And if we return to undecidable cases, we use dynamic checks
74 
75 *******************************************************************/
76 
77 /* TO AMELIORATE :
78  for the moment, we only use trivial_expression_p to compare offsets + array sizes
79  CAN TAKE MORE INFORMATION from array declarations, A(l:u) => u>l
80  not precondtitions (corrupted)*/
81 
82 #include <stdio.h>
83 #include <stdlib.h>
84 #include <string.h>
85 #include "genC.h"
86 #include "linear.h"
87 #include "ri.h"
88 #include "effects.h"
89 #include "ri-util.h"
90 #include "prettyprint.h" // for debugging
91 #include "effects-util.h"
92 #include "alias_private.h"
93 #include "database.h"
94 #include "pipsdbm.h"
95 #include "resources.h"
96 #include "misc.h"
97 #include "properties.h"
98 #include "effects-generic.h"
99 #include "instrumentation.h"
100 #include "text-util.h" /* for words_to_string*/
101 
102 #define PREFIX1 "$ALIAS_CHECK"
103 #define PREFIX2 "$ALIAS_CHECK_END"
104 #define ALIAS_FLAG "ALIAS_FLAG"
105 #define ALIAS_FUNCTION "DYNAMIC_ALIAS_CHECK"
106 
107 typedef struct
108 {
116  bool insert;
119 
122 static const char* caller_name;
127 static int current_ordering = 0;
128 static FILE * out;
131 /* This list tells us if two variables have been checked dynamically or not*/
133 static int unique_flag_number = 0; // a counter for alias flags
134 static int number_of_tests = 0;
135 static int number_of_calls = 0;
137 
138 
140 {
142  {
143  /* If e is a relational expression*/
145  expression e1 = EXPRESSION(CAR(args));
146  expression e2 = EXPRESSION(CAR(CDR(args)));
148  {
152  {
154  Pvecteur v1 = normalized_linear(n1);
155  Pvecteur v2 = normalized_linear(n2);
156  Pvecteur v = vect_substract(v1,v2);
157  expression new_exp;
158  vect_normalize(v);
159  new_exp = Pvecteur_to_expression(v);
161  }
162  }
163  }
164  return e;
165 }
166 
168 {
169  user_log("\n Number of flags : %d", unique_flag_number);
170  user_log("\n Number of tests : %d", number_of_tests);
171  user_log("\n Number of calls : %d", number_of_calls);
172  user_log("\n Number of processed modules: %d\n",number_of_processed_modules);
173 }
174 
176 {
178  list l_formals = NIL;
179  list l_commons = NIL;
180  /* search for formal parameters in the declaration list */
181  MAP(ENTITY, e,
182  {
183  if (formal_parameter_p(e))
184  l_formals = gen_nconc(l_formals,CONS(ENTITY,e,NIL));
185  },
186  l_decls);
187  MAP(ENTITY, e,
188  {
189  if (variable_in_common_p(e))
191  },
192  l_decls);
193 
194  MAP(ENTITY,e1,
195  {
196  MAP(ENTITY,e2,
197  {
198  dynamic_check dc = make_dynamic_check(e1,e2,false);
200  },l_formals);
201  MAP(ENTITY,e2,
202  {
203  dynamic_check dc = make_dynamic_check(e1,e2,false);
205  },l_commons);
206  },l_formals);
207 }
208 
209 static bool dynamic_checked_p(entity e1, entity e2)
210 {
211  MAP(DYNAMIC_CHECK,dc,
212  {
213  if ((dynamic_check_first(dc)==e1)&&(dynamic_check_second(dc)==e2))
214  return dynamic_check_checked(dc);
215  }, l_dynamic_check);
216  return false;
217 }
218 
219 static void set_dynamic_checked(entity e1, entity e2)
220 {
221  MAP(DYNAMIC_CHECK,dc,
222  {
223  if ((dynamic_check_first(dc)==e1)&&(dynamic_check_second(dc)==e2))
224  dynamic_check_checked(dc) = true;
225  }, l_dynamic_check);
226 }
227 
228 static bool same_call_site_p(call_site cs1, call_site cs2)
229 {
230  entity f1 = call_site_function(cs1);
232  int o1 = call_site_ordering(cs1);
233  int o2 = call_site_ordering(cs2);
234  return (same_entity_p(f1,f2) && (o1==o2));
235 }
236 
237 /****************************************************************************
238 
239  This function returns true if one list is included in other :
240  l1=conc(l2,l) or l2=conc(l1,l)
241 
242 *****************************************************************************/
243 
244 // FC: function also in ricedg/impact_check.c
245 
247 {
248  while (!ENDP(l1) && !ENDP(l2))
249  {
250  call_site cs1 = CALL_SITE(CAR(l1));
251  call_site cs2 = CALL_SITE(CAR(l2));
252  if (!same_call_site_p(cs1,cs2)) return false;
253  l1 = CDR(l1);
254  l2 = CDR(l2);
255  }
256  return true;
257 }
258 
259 /****************************************************************************
260 
261  This function returns true if l1 = conc(cs,l2)
262 
263 *****************************************************************************/
264 
265 static bool tail_call_path_p(call_site cs, list l1, list l2)
266 {
267  if (gen_length(l1) == gen_length(l2)+1)
268  {
269  call_site cs1 = CALL_SITE(CAR(l1));
270  return (same_call_site_p(cs,cs1) && included_call_chain_p(l2,CDR(l1)));
271  }
272  return false;
273 }
274 
275 /* This function prints the call path , including names of caller functions
276  and orderings of call sites in their corresponding functions */
277 static string print_call_path(list path)
278 {
279  list pc = NIL;
280  MAP(CALL_SITE,casi,
281  {
282  entity casifunc = call_site_function(casi);
283  int casiord = call_site_ordering(casi);
284  pc = CHAIN_SWORD(pc,"(");
285  pc = CHAIN_SWORD(pc,module_local_name(casifunc));
286  pc = CHAIN_SWORD(pc,":(");
287  pc = CHAIN_SWORD(pc,int2a(ORDERING_NUMBER(casiord)));
288  pc = CHAIN_SWORD(pc,",");
289  pc = CHAIN_SWORD(pc,int2a(ORDERING_STATEMENT(casiord)));
290  pc = CHAIN_SWORD(pc,")) ");
291  },path);
292  return words_to_string(pc);
293 }
294 
295 /*****************************************************************************
296 
297  This function prints an alias_association
298 
299 *****************************************************************************/
300 
302 {
307  int l = alias_association_lower_offset(aa);
308  int u = alias_association_upper_offset(aa);
309  fprintf(stderr,"\n Alias association :");
310  fprintf(stderr,"\n Formal variable %s with",entity_name(e));
311  fprintf(stderr, "\n section :%s", entity_name(sec));
312  fprintf(stderr, "\n offset :");
314  fprintf(stderr, "lower offset :%d, upper offset: %d \n",l,u);
315  fprintf(stderr, "call path :%s \n", print_call_path(path));
316 }
317 
318 /*****************************************************************************
319 
320  This function prints the list of alias_association
321 
322 *****************************************************************************/
323 
325 {
326  MAP(ALIAS_ASSOCIATION, aa,{
328  },l);
329 }
330 
331 /*****************************************************************************
332 
333  This function returns the size of an array minus 1, multiplied by array element
334  (D1*D2*...*Dn-1)* element_size
335 
336 *****************************************************************************/
337 
339 {
341  if (!assumed_size_array_p(ent) && !pointer_type_array_p(ent))
342  {
343  variable var = type_variable(entity_type(ent));
344  list l_dims = variable_dimensions(var);
345  int num_dim = gen_length(l_dims),j;
348  for (j=1; j<= num_dim; j++)
349  {
350  dimension dim_j = find_ith_dimension(l_dims,j);
351  expression lower_j = dimension_lower(dim_j);
352  expression upper_j = dimension_upper(dim_j);
353  expression size_j;
354  if (expression_constant_p(lower_j) && (expression_to_int(lower_j)==1))
355  size_j = copy_expression(upper_j);
356  else
357  {
358  size_j = binary_intrinsic_expression(MINUS_OPERATOR_NAME,upper_j,lower_j);
361  }
363  exp = copy_expression(size_j);
364  else
366  copy_expression(exp),size_j);
367  }
370  ifdebug(2)
371  {
372  fprintf(stderr, "\n Stride of array size : \n");
374  }
375  }
376  /* else return expression_undefined with assumed-size or pointer-type array*/
377  return exp;
378 }
379 
380 /*****************************************************************************
381 
382  This function inserts flags and condition (if exists) before current
383  statement in module : IF (cond && F1 && F2) STOP "Alias violation"
384 
385 *****************************************************************************/
386 
388  statement s, entity e1, entity e2,list path)
389 {
390  expression cond;
391  statement smt;
392  int order = statement_ordering(s);
393  string message = strdup(concatenate("\'Alias violation in module ",
394  module_local_name(current_mod),": write on ",
395  entity_local_name(e1),", aliased with ",
396  entity_local_name(e2)," by call path ",
397  print_call_path(path),"\'", NULL));
398  const char* mod_name = module_local_name(current_mod);
399  string user_file = db_get_memory_resource(DBR_USER_FILE,mod_name,true);
400  string base_name = pips_basename(user_file, NULL);
402  if (true_expression_p(condition))
403  cond = copy_expression(flags);
404  else
405  cond = and_expression(condition,flags);
406  if (get_bool_property("PROGRAM_VERIFICATION_WITH_PRINT_MESSAGE"))
409  else
412  fprintf(out,"%s\t%s\t%s\t(%d,%d)\n",PREFIX1,file_name,module_local_name(current_mod),
413  ORDERING_NUMBER(order),ORDERING_STATEMENT(order));
414  fprint_statement(out, smt);
415  fprintf(out,"%s\n",PREFIX2);
416  number_of_tests++;
417  free(file_name), file_name = NULL;
418  free(message), message = NULL;
419 }
420 
421 /*****************************************************************************
422 
423  This function inserts a flag before each call site in call path :
424  ALIAS_FLAG(i) = .TRUE.
425 
426 *****************************************************************************/
427 
429 {
430  while (!ENDP(path))
431  {
432  call_site cs = CALL_SITE(CAR(path));
433  expression e_flag = EXPRESSION(CAR(flags));
434  entity caller = call_site_function(cs);
435  int order = call_site_ordering(cs);
437  const char* call_name = module_local_name(caller);
438  string user_file = db_get_memory_resource(DBR_USER_FILE,call_name,true);
439  string base_name = pips_basename(user_file, NULL);
441  fprintf(out,"%s\t%s\t%s\t(%d,%d)\n",PREFIX1,file_name,module_local_name(caller),
442  ORDERING_NUMBER(order),ORDERING_STATEMENT(order));
443  fprint_statement(out,s_flag);
444  fprintf(out, "%s\n",PREFIX2);
445  path = CDR(path);
446  flags = CDR(flags);
447  free(file_name), file_name = NULL;
448  }
449 }
450 
451 /*****************************************************************************
452 
453  This function inserts flags and condition (if exists) before current
454  call site : IF (cond) ALIAS_FLAG(i) =.TRUE.
455 
456 *****************************************************************************/
457 
458 static void insert_test_before_caller(expression condition, expression e_flag)
459 {
461  string user_file = db_get_memory_resource(DBR_USER_FILE,caller_name,true);
462  string base_name = pips_basename(user_file, NULL);
464  if (true_expression_p(condition))
465  {
466  fprintf(out,"%s\t%s\t%s\t(%d,%d)\n",PREFIX1,file_name,module_local_name(current_caller),
468  fprint_statement(out,s_flag);
469  fprintf(out,"%s\n",PREFIX2);
470  }
471  else
472  {
473  statement smt = test_to_statement(make_test(condition, s_flag,
475  fprintf(out,"%s\t%s\t%s\t(%d,%d)\n",PREFIX1,file_name,module_local_name(current_caller),
477  fprint_statement(out,smt);
478  fprintf(out,"%s\n",PREFIX2);
479  number_of_tests++;
480  }
481  free(file_name), file_name = NULL;
482 }
483 
485 {
486  int i;
487  list retour = NIL;
488  for (i=1;i<=(int)gen_length(path);i++)
489  {
492  ifdebug(2)
493  {
494  fprintf(stderr, "\n New flag expression: \n");
495  print_expression(e_flag);
496  }
497  if (retour==NIL)
498  retour = CONS(EXPRESSION,e_flag,NIL);
499  else
500  retour = gen_nconc(retour, CONS(EXPRESSION,e_flag,NIL));
501  }
502  return retour;
503 }
504 
505 /* This function returns true if c is an user-defined function/subroutine*/
507 {
508  entity fun = call_function(c);
509  return entity_module_p(fun);
510 }
511 
512 static bool written = false;
514 /* This function returns true if the variable is written directly in the current module,
515  not by its callees (do not take into account the effects on X,Y of statement like
516  CALL FOO(X,Y))*/
517 
519 {
520  if (statement_call_p(s))
521  {
523  {
525  MAP(EFFECT, eff,
526  {
527  action a = effect_action(eff);
528  if (action_write_p(a))
529  {
531  entity e = reference_variable(r);
533  {
534  ifdebug(3)
535  {
536  fprintf(stderr,"\n Write on entity %s :\n",entity_name(e));
537  fprintf(stderr,"\n Current entity %s :\n",entity_name(current_entity));
538  }
539  written = true;
540  //gen_recurse_stop(NULL);
541  return false;
542  }
543  }
544  },
545  l_rw);
546  return false;
547  }
548  return false;
549  }
550  return true;
551 }
552 
554 {
555  written = false;
556  current_entity = ent;
560  return written;
561 }
562 
564  entity e2, expression size,
565  statement s)
566 {
567  string message = strdup(concatenate("\'Alias violation in module ",
568  module_local_name(current_mod),": write on ",
569  entity_local_name(e1),", aliased with ",
570  entity_local_name(e2),"\'", NULL));
571  list l = CONS(EXPRESSION,size,NIL);
572  statement smt;
573  int order = statement_ordering(s);
574  const char* mod_name = module_local_name(current_mod);
575  string user_file = db_get_memory_resource(DBR_USER_FILE,mod_name,true);
576  string base_name = pips_basename(user_file, NULL);
579  l = CONS(EXPRESSION,subval,l);
583  fprintf(out,"%s\t%s\t%s\t(%d,%d)\n",PREFIX1,file_name,module_local_name(current_mod),
584  ORDERING_NUMBER(order),ORDERING_STATEMENT(order));
585  fprint_statement(out, smt);
586  fprintf(out,"%s\n",PREFIX2);
587  number_of_calls++;
588  free(file_name), file_name = NULL;
589 }
590 
591 /*****************************************************************************
592 
593  This function generates a CALL ALIAS_CHECK(e1,ref1,e2,size2) before each write on
594  a may be aliased variable e1. checkalias() is a C function that takes the addresses of
595  e1 and e2, writing reference ref1 and offset size2 as input, returns if there is
596  alias violation on this writing or not.
597 
598  This type of dynamic checking is expensive, because we do not use information from
599  static analysese => use it only when we can do nothing else.
600 
601 *****************************************************************************/
602 
604 {
605  list l_rw = NIL;
606  if (statement_call_p(s))
607  l_rw = load_proper_rw_effects_list(s);
608  else
610 
611  MAP(EFFECT, eff,
612  {
613  action a = effect_action(eff);
614  if (action_write_p(a))
615  {
617  entity e = reference_variable(r);
618  if (same_entity_p(e,context->first_entity))
619  {
621  if (approximation_exact_p(rw))
622  {
623  list l_inds = reference_indices(r);
624  expression subval = subscript_value_stride(context->first_entity,l_inds);
625  expression size;
626  if (array_entity_p(context->second_entity))
627  size = array_size_stride(context->second_entity);
628  else
629  size = int_to_expression(0);
630  if (!expression_undefined_p(size)) // not assumed-size array
631  insert_check_alias_before_statement(context->first_entity,subval,
632  context->second_entity,size,s);
633  else
634  /* Assumed-size or pointer-type array, the size of dummy array can not be
635  derived from the size of actual argument as we have no corresponding call chain*/
636  pips_user_warning("\nAssumed-size or pointer-type array \n");
637  return false;
638  }
639  return true;
640  }
641  }
642  },
643  l_rw);
644  return false; /* The variable is not in the list of write effects => OK*/
645 }
646 
647 /*****************************************************************************
648 
649  This function checks if an aliased scalar variable is written or not.
650  If yes, insert test before statement
651 
652 *****************************************************************************/
653 
656 {
657  list l_rw = NIL;
658  if (statement_call_p(s))
659  l_rw = load_proper_rw_effects_list(s);
660  else
662  MAP(EFFECT, eff,
663  {
664  action a = effect_action(eff);
665  if (action_write_p(a))
666  {
668  entity e = reference_variable(r);
669  if (same_entity_p(e,context->first_entity))
670  {
672  if (approximation_exact_p(rw))
673  {
674  insert_test_before_statement(context->flags,context->condition,s,
675  context->first_entity,context->second_entity,
676  context->path);
677  context->insert = true;
678  return false;
679  }
680  return true;
681  }
682  }
683  },
684  l_rw);
685  return false; /* The variable is not in the list of write effects => OK*/
686 }
687 
688 /*****************************************************************************
689 
690  This function checks if an array element which is aliased with a scalar variable
691  is written or not. Test : ref2 == off1 ? where ref2 = off2 + subval_stride2
692  If yes, insert test before statement
693 
694 *****************************************************************************/
695 
698 {
699  list l_rw = NIL;
700  if (statement_call_p(s))
701  l_rw = load_proper_rw_effects_list(s);
702  else
704 
705  MAP(EFFECT, eff,
706  {
707  action a = effect_action(eff);
708  if (action_write_p(a))
709  {
711  entity e = reference_variable(r);
712  if (same_entity_p(e,context->first_entity))
713  {
715  if (approximation_exact_p(rw))
716  {
717  list l_inds = reference_indices(r);
718  /* Attention : <may be written> V(*,*) => what kind of indices ???*/
719  expression subval2 = subscript_value_stride(context->first_entity,l_inds);
720  expression diff;
721  int k;
722  if (same_expression_p(context->offset1,context->offset2))
723  diff = eq_expression(int_to_expression(0),subval2);
724  else
725  {
726  expression ref2;
727  if (expression_equal_integer_p(context->offset2,0))
728  ref2 = copy_expression(subval2);
729  else
730  ref2 = binary_intrinsic_expression(PLUS_OPERATOR_NAME,context->offset2,subval2);
731  diff = eq_expression(context->offset1,ref2);
732  }
733  clean_all_normalized(diff);
734  k = trivial_expression_p(diff);
735  switch(k){
736  case -1:
737  /* off1 == ref2 is false => Okay, no write on aliased variable */
738  return false;
739  default:
740  {
741  /* k = 0 or 1*/
742  if (k==0)
744  context->first_entity,context->second_entity,
745  context->path);
746  else
748  context->first_entity,context->second_entity,
749  context->path);
750 
751  context->insert = true;
752  return false;
753  }
754  }
755  }
756  return true;
757  }
758  }
759  },
760  l_rw);
761  return false; /* The variable is not in the list of write effects => OK*/
762 }
763 
764 /*****************************************************************************
765 
766  This function checks if an array variable has written element which is aliased
767  with other array variable's element or not.
768  Test : off2 <= ref1 <= off2+size_stride2 ? where ref1 = off1+subval_stride1
769  If yes, insert test before statement
770 
771 *****************************************************************************/
772 
774 {
775  list l_rw = NIL;
776  if (statement_call_p(s))
777  l_rw = load_proper_rw_effects_list(s);
778  else
780 
781  MAP(EFFECT, eff,
782  {
783  action a = effect_action(eff);
784  if (action_write_p(a))
785  {
787  entity e = reference_variable(r);
788  if (same_entity_p(e,context->first_entity))
789  {
791  if (approximation_exact_p(rw))
792  {
793  list l_inds = reference_indices(r);
794  /* Attention : <may be written> V(*,*) => what kind of indices ???*/
795  expression subval1 = subscript_value_stride(context->first_entity,l_inds);
796  expression diff1;
797  int k1;
798  expression ref1;
799  if (expression_equal_integer_p(context->offset1,0))
800  ref1 = copy_expression(subval1);
801  else
803  context->offset1,subval1);
804  if (same_expression_p(context->offset1,context->offset2))
805  diff1 = ge_expression(subval1,int_to_expression(0));
806  else
807  diff1 = ge_expression(ref1,context->offset2);
808  clean_all_normalized(diff1);
809  k1 = trivial_expression_p(diff1);
810  switch(k1){
811  case -1:
812  /* off2 <= ref1 is false => Okay, no write on aliased variable */
813  return false;
814  default:
815  {
816  expression size2 = array_size_stride(context->second_entity);
817  // test of assumed-size array is carried out before
818  expression diff2;
819  int k2;
820  if (same_expression_p(context->offset1,context->offset2))
821  diff2 = le_expression(subval1,size2);
822  else
823  {
824  expression sum2;
825  if (expression_equal_integer_p(context->offset2,0))
826  sum2 = copy_expression(size2);
827  else
829  context->offset2,size2);
830  diff2 = le_expression(ref1,sum2);
831  }
832  clean_all_normalized(diff2);
833  k2 = trivial_expression_p(diff2);
834  switch(k2){
835  case -1:
836  /* ref1 <= off2+size_stride2 is false => Okay, no write on aliased variable */
837  return false;
838  default:
839  {
840  /* k1 = 0 or 1, k2 = 0 or 1*/
841  if (k1+k2==0) // k1=k2=0
845  s,context->first_entity,context->second_entity,
846  context->path);
847  else
848  {
849  if (k1+k2==2) // k1=k2=1
851  context->first_entity,context->second_entity,
852  context->path);
853  else
854  {
855  if (k1==0) // k1=0, k2=1
858  context->first_entity,context->second_entity,
859  context->path);
860  else // k2=0, k1=1
863  context->first_entity,context->second_entity,
864  context->path);
865  }
866  }
867  context->insert = true;
868  return false;
869  }
870  }
871  return false;
872  }
873  }
874  }
875  return true;
876  }
877  }
878  },
879  l_rw);
880  return false; /* The variable is not in the list of write effects => OK*/
881 }
882 
883 /*****************************************************************************
884 
885  This function checks if there is alias violation between two scalar variables or not.
886 
887  IF off1 != off2 => no alias, OK
888  ELSE, off1 == off2 => alias,
889  IF e1 or e2 is written => alias violation
890  => insert test before every statement where e1 and e2 must be written
891 
892 *****************************************************************************/
893 
895  expression off2,list path)
896 {
897  expression diff = eq_expression(off1,off2);
898  int k;
899  clean_all_normalized(diff);
900  k = trivial_expression_p(diff);
901  /* Should we use also formal and actual binding / precondition ??? */
902  ifdebug(2)
903  fprintf(stderr,"\n Check in module, 2 scalar variables \n");
904  switch(k){
905  case -1:
906  /* off1 != off2 => Okay, no alias between these 2 variables */
907  return;
908  default:
909  {
910  /* insert flags before each call site in call path*/
911  list l_flags = make_list_of_flags(path);
913  context.insert = false;
914  context.path = path;
915  context.flags = expression_list_to_conjonction(l_flags);
916  if (k==1)
917  context.condition = make_true_expression();
918  else
919  context.condition = simplify_relational_expression(diff);
920  context.first_entity = e1;
921  context.second_entity = e2;
924  context.first_entity = e2;
925  context.second_entity = e1;
928  if (context.insert)
930  context.first_entity = entity_undefined;
931  context.second_entity = entity_undefined;
932  context.offset1 = expression_undefined;
933  context.offset2 = expression_undefined;
934  context.condition = expression_undefined;
936  context.path = NIL;
937  }
938  }
939 }
940 
941 /*****************************************************************************
942 
943  This function checks if there is alias violation between a scalar variable e1
944  and an array variable e2 or not.
945 
946  IF off1 < off2 OR off1 > off2+size_stride2 => no alias, OK
947  ELSE : off2 <= off1 <= off2+size_stride2
948  - IF e1 is written => alias violation
949  - IF e2 is written (ref2 == subval_stride2+off2) :
950  - IF ref2 != off1 => no alias violation
951  - IF ref2 == off1 => alias violation
952 
953 *****************************************************************************/
954 
956  expression off1,expression off2,list path)
957 {
958  expression diff1 = le_expression(off2,off1);
959  int k1;
960  clean_all_normalized(diff1);
961  k1 = trivial_expression_p(diff1);
962  ifdebug(2)
963  fprintf(stderr,"\n Check in module, scalar and array variables \n");
964  switch(k1){
965  case -1:
966  /* off2 <= off1 is false => Okay, no alias between these 2 variables */
967  return;
968  default:
969  {
970  expression size2 = array_size_stride(e2);
971  if (!expression_undefined_p(size2)) // not assumed-size array
972  {
973  expression diff2;
974  int k2;
975  if (same_expression_p(off1,off2))
976  diff2 = le_expression(int_to_expression(0),size2);
977  else
978  {
979  expression sum2;
980  if (expression_equal_integer_p(off2,0))
981  sum2 = copy_expression(size2);
982  else
984  diff2 = le_expression(off1,sum2);
985  }
986  clean_all_normalized(diff2);
987  k2 = trivial_expression_p(diff2);
988  switch(k2){
989  case -1:
990  /* off1 <= off2+size_stride2 is false => Okay, no alias between these 2 variables */
991  return;
992  default:
993  {
994  /* k1 = 0 or 1, k2 = 0 or 1
995  insert flags before each call site in call path*/
996  list l_flags = make_list_of_flags(path);
998  context.insert = false;
999  context.path = path;
1000  context.flags = expression_list_to_conjonction(l_flags);
1001  if (k1+k2==0) // k1=k2=0
1004  else
1005  {
1006  if (k1+k2==2) // k1=k2=1
1007  context.condition = make_true_expression();
1008  else
1009  {
1010  if (k1==0) // k1=0, k2=1
1011  context.condition = simplify_relational_expression(diff1);
1012  else // k2=0, k1=1
1013  context.condition = simplify_relational_expression(diff2);
1014  }
1015  }
1016  context.first_entity = e1;
1017  context.second_entity = e2;
1020  context.offset1 = off1;
1021  context.offset2 = off2;
1022  context.first_entity = e2;
1023  context.second_entity = e1;
1026  if (context.insert)
1028  context.first_entity = entity_undefined;
1029  context.second_entity = entity_undefined;
1030  context.offset1 = expression_undefined;
1031  context.offset2 = expression_undefined;
1032  context.condition = expression_undefined;
1033  context.flags = expression_undefined;
1034  context.path = NIL;
1035  }
1036  }
1037  }
1038  else
1039  /* Assumed-size or pointer-type array, the size of dummy array can be
1040  derived from the size of actual argument, as we have the corresponding call chain*/
1041  pips_user_warning("\nAssumed-size or pointer-type array \n");
1042  }
1043  }
1044 }
1045 
1046 /*****************************************************************************
1047 
1048  These functions check if there is alias violation between two array variables or not.
1049 
1050  IF (off2+size_stride2<off1) OR (off2>off1+size_stride1) => OK, no alias
1051 
1052  ELSE
1053  IF e1 is written (ref1)
1054  IF (ref1 < off2) OR (ref1 > off2+size_stride2) => no alias violation
1055  ELSE (off2 <= ref1 <= off2+size_stride2) => alias violation
1056  IF e2 is written (ref2) : symetrical with e1
1057  IF (ref2 < off1) OR (ref2 > off1+size_stride1) => no alias violation
1058  ELSE (off1 <= ref2 <= off1+size_stride1) => alias violation
1059 
1060 *****************************************************************************/
1061 
1063  expression off2,list path)
1064 {
1065  expression size2 = array_size_stride(e2);
1066  if (!expression_undefined_p(size2)) // not assumed-size array
1067  {
1068  expression sum2,diff1;
1069  int k1;
1070  if (expression_equal_integer_p(off2,0))
1071  sum2 = copy_expression(size2);
1072  else
1074  diff1 = gt_expression(off1,sum2);
1075  clean_all_normalized(diff1);
1076  k1 = trivial_expression_p(diff1);
1077  ifdebug(2)
1078  fprintf(stderr,"\n Check in module, 2 array variables \n");
1079  switch(k1){
1080  case 1:
1081  {
1082  ifdebug(3)
1083  fprintf(stderr,"\n off1> off2+size_stride2 is true => Okay, no alias between these 2 variables \n");
1084  /* off1> off2+size_stride2 is true => Okay, no alias between these 2 variables */
1085  return;
1086  }
1087  default:
1088  {
1089  expression size1 = array_size_stride(e1);
1090  if (!expression_undefined_p(size1)) // not assumed-size array
1091  {
1092  expression sum1,diff2;
1093  int k2;
1094  if (expression_equal_integer_p(off1,0))
1095  sum1 = copy_expression(size1);
1096  else
1098  diff2 = gt_expression(off2,sum1);
1099  clean_all_normalized(diff2);
1100  k2 = trivial_expression_p(diff2);
1101  switch(k2){
1102  case 1:
1103  {
1104  ifdebug(3)
1105  fprintf(stderr,"\n off2 > off1+size_stride1 is true => Okay, no alias between these 2 variables \n");
1106  /* off2 > off1+size_stride1 is true => Okay, no alias between these 2 variables */
1107  return;
1108  }
1109  default:
1110  {
1111  /* insert flags before each call site in call path*/
1112  list l_flags = make_list_of_flags(path);
1114  context.insert = false;
1115  context.path = path;
1116  context.flags = expression_list_to_conjonction(l_flags);
1117  context.first_entity = e1;
1118  context.second_entity = e2;
1119  context.offset1 = off1;
1120  context.offset2 = off2;
1123  context.first_entity = e2;
1124  context.second_entity = e1;
1125  context.offset1 = off2;
1126  context.offset2 = off1;
1129  if (context.insert)
1131  context.first_entity = entity_undefined;
1132  context.second_entity = entity_undefined;
1133  context.offset1 = expression_undefined;
1134  context.offset2 = expression_undefined;
1135  context.condition = expression_undefined;
1136  context.flags = expression_undefined;
1137  context.path = NIL;
1138  }
1139  }
1140  }
1141  else
1142  /* Assumed-size or pointer-type array, the size of dummy array can be
1143  derived from the size of actual argument, as we have the corresponding call chain*/
1144  pips_user_warning("\nAssumed-size or pointer-type array \n");
1145  }
1146  }
1147  }
1148  else
1149  /* Assumed-size or pointer-type array, the size of dummy array can be
1150  derived from the size of actual argument, as we have the corresponding call chain*/
1151  pips_user_warning("\nAssumed-size or pointer-type array \n");
1152 }
1153 
1154 /*****************************************************************************
1155 
1156  This function checks if there is an alias violation in written reference r
1157  of entity 1, which may be aliased with entity 2
1158 
1159 *****************************************************************************/
1160 
1162  expression off1,expression off2,list path)
1163 {
1164  /* There are 3 cases:
1165  - Case 1: e1 and e2 are scalar variables
1166  - Case 2: e1 is a scalar variable, e2 is an array variable or vice-versa
1167  - Case 3: e1 and e2 are array variables */
1168 
1169  if (entity_scalar_p(e1) && entity_scalar_p(e2))
1171 
1172  if (entity_scalar_p(e1) && !entity_scalar_p(e2))
1174 
1175  if (!entity_scalar_p(e1) && entity_scalar_p(e2))
1177 
1178  if (!entity_scalar_p(e1) && !entity_scalar_p(e2))
1180 }
1181 
1182 
1183 /*****************************************************************************
1184 
1185  This function checks if an aliased scalar variable is written or not.
1186  If yes, insert test before direct call
1187 
1188 *****************************************************************************/
1189 
1191 {
1192  list l_rw = NIL;
1193  if (statement_call_p(s))
1194  l_rw = load_proper_rw_effects_list(s);
1195  else
1197  MAP(EFFECT, eff,
1198  {
1199  action a = effect_action(eff);
1200  if (action_write_p(a))
1201  {
1203  entity e = reference_variable(r);
1204  if (same_entity_p(e,context->first_entity))
1205  {
1207  if (approximation_exact_p(rw))
1208  {
1210  context->first_entity,context->second_entity,
1211  context->path);
1212  context->insert = true;
1213  return false;
1214  }
1215  return true;
1216  }
1217  }
1218  },
1219  l_rw);
1220  return false; /* The variable is not in the list of write effects => OK*/
1221 }
1222 
1223 /*****************************************************************************
1224 
1225  This function checks if an array element which is aliased with a scalar variable
1226  is written or not. Test : ref2 == off1 ? where ref2 = off2+subval_stride2
1227  If yes, insert test before direct call
1228 
1229 *****************************************************************************/
1230 
1232 {
1233  list l_rw = NIL;
1234  if (statement_call_p(s))
1235  l_rw = load_proper_rw_effects_list(s);
1236  else
1238 
1239  MAP(EFFECT, eff,
1240  {
1241  action a = effect_action(eff);
1242  if (action_write_p(a))
1243  {
1245  entity e = reference_variable(r);
1246  if (same_entity_p(e,context->first_entity))
1247  {
1249  if (approximation_exact_p(rw))
1250  {
1251  list l_inds = reference_indices(r);
1252  /* Attention : <may be written> V(*,*) => what kind of indices ???*/
1253  expression subval2 = subscript_value_stride(context->first_entity,l_inds);
1254  /* Translate subval2 to the frame of caller, in order to compare with offsets*/
1256  if (!expression_undefined_p(new_subval2))
1257  {
1258  expression diff;
1259  int k;
1260  if (same_expression_p(context->offset1,context->offset2))
1261  diff = eq_expression(int_to_expression(0),new_subval2);
1262  else
1263  {
1264  expression ref2;
1265  if (expression_equal_integer_p(context->offset2,0))
1266  ref2 = copy_expression(new_subval2);
1267  else
1268  ref2 = binary_intrinsic_expression(PLUS_OPERATOR_NAME,context->offset2,new_subval2);
1269  diff = eq_expression(context->offset1,ref2);
1270  }
1271  clean_all_normalized(diff);
1272  k = trivial_expression_p(diff);
1273  switch(k){
1274  case -1:
1275  /* off1 == ref2 is false => Okay, no write on aliased variable */
1276  return false;
1277  default:
1278  {
1279  /* k = 0 or 1*/
1282  ifdebug(2)
1283  {
1284  fprintf(stderr, "\n New flag expression: \n");
1285  print_expression(e_flag);
1286  }
1287  if (true_expression_p(context->flags))
1289  context->first_entity,context->second_entity,
1290  context->path);
1291  else
1294  context->first_entity,context->second_entity,
1295  context->path);
1296  if (k==0)
1298  else
1300  context->insert = true;
1301  return false;
1302  }
1303  }
1304  }
1305  else
1306  {
1307  /* We can not translate subval to the frame of caller => use dynamic check*/
1308  insert_check_alias_before_statement(context->first_entity,subval2,
1309  context->second_entity,int_to_expression(0),s);
1310  return false;
1311  //user_log("\n Warning : Can not translate writing reference to frame of caller \n");
1312  }
1313  }
1314  return true;
1315  }
1316  }
1317  },
1318  l_rw);
1319  return false; /* The variable is not in the list of write effects => OK*/
1320 }
1321 
1322 /*****************************************************************************
1323 
1324  This function checks if an array variable has written element which is aliased
1325  with other array variable's element or not.
1326  Test : off2 <= ref1 <= off2+size_stride2 ? where ref1 = off1+subval_stride1
1327  If yes, insert test before statement
1328 
1329 *****************************************************************************/
1330 
1332 {
1333  list l_rw = NIL;
1334  if (statement_call_p(s))
1335  l_rw = load_proper_rw_effects_list(s);
1336  else
1338  MAP(EFFECT, eff,
1339  {
1340  action a = effect_action(eff);
1341  if (action_write_p(a))
1342  {
1344  entity e = reference_variable(r);
1345  if (same_entity_p(e,context->first_entity))
1346  {
1348  if (approximation_exact_p(rw))
1349  {
1350 
1351  /*TREATED ? CASE READ *,ARRAY */
1352 
1353  list l_inds = reference_indices(r);
1354  /* Attention : <may be written> V(*,*) => what kind of indices ???*/
1355  expression subval1 = subscript_value_stride(context->first_entity,l_inds);
1356  /* Translate subval1 to the frame of caller, in order to compare with offsets*/
1358  subval1,current_call);
1359  if (!expression_undefined_p(new_subval1))
1360  {
1362  int k1;
1364  if (same_expression_p(context->offset1,context->offset2))
1365  diff1 = ge_expression(new_subval1,int_to_expression(0));
1366  else
1367  {
1368  if (expression_equal_integer_p(context->offset1,0))
1369  ref1 = copy_expression(new_subval1);
1370  else
1371  ref1 = binary_intrinsic_expression(PLUS_OPERATOR_NAME,context->offset1,new_subval1);
1372  diff1 = ge_expression(ref1,context->offset2);
1373  }
1374  clean_all_normalized(diff1);
1375  k1 = trivial_expression_p(diff1);
1376  switch(k1){
1377  case -1:
1378  /* off2 <= ref1 is false => Okay, no write on aliased variable */
1379  break;
1380  default:
1381  {
1382  expression size2 = array_size_stride(context->second_entity);
1383  /* Test of assumed-size array has been carried out before
1384  Translate size2 to the frame of caller, in order to compare with offsets*/
1386  if (!expression_undefined_p(size2))
1387  {
1388  expression diff2;
1389  int k2;
1390  if (same_expression_p(context->offset1,context->offset2))
1391  diff2 = le_expression(new_subval1,size2);
1392  else
1393  {
1394  expression sum2;
1395  if (expression_equal_integer_p(context->offset2,0))
1396  sum2 = copy_expression(size2);
1397  else
1399  diff2 = le_expression(ref1,sum2);
1400  }
1401  clean_all_normalized(diff2);
1402  k2 = trivial_expression_p(diff2);
1403  switch(k2){
1404  case -1:
1405  /* ref1 <= off2+size_stride2 is false => Okay, no write on aliased variable */
1406  break;
1407  default:
1408  {
1409  /* k1 = 0 or 1, k2 = 0 or 1*/
1412  ifdebug(2)
1413  {
1414  fprintf(stderr, "\n New flag expression: \n");
1415  print_expression(e_flag);
1416  }
1417  if (true_expression_p(context->flags))
1419  context->first_entity,context->second_entity,
1420  context->path);
1421  else
1424  context->first_entity,context->second_entity,
1425  context->path);
1426  if (k1+k2==0) // k1=k2=0
1428  simplify_relational_expression(diff2)),e_flag);
1429  else
1430  {
1431  if (k1+k2==2) // k1=k2=1
1433  else
1434  {
1435  if (k1==0) // k1=0, k2=1
1437  else // k2=0, k1=1
1439  }
1440  }
1441  context->insert = true;
1442  break;
1443  }
1444  }
1445  }
1446  else
1447  /* We can not translate size2 to the frame of caller => create new common variable*/
1448  pips_user_warning("\nCan not translate size of array to frame of caller \n");
1449  break;
1450  }
1451  }
1452  }
1453  else
1454  {
1455  /* We can not translate subval1 to the frame of caller => use dynamic check*/
1456  expression size2 = array_size_stride(context->second_entity);
1457  insert_check_alias_before_statement(context->first_entity,subval1,
1458  context->second_entity,size2,s);
1459  }
1460  return false;
1461  }
1462  return true;
1463  }
1464  }
1465  },
1466  l_rw);
1467  return false; /* The variable is not in the list of write effects => OK*/
1468 }
1469 
1470 /*****************************************************************************
1471 
1472  This function checks if there is alias violation between two scalar variables or not.
1473 
1474  IF off1 != off2 => no alias, OK
1475  ELSE, off1 == off2 => alias,
1476  IF e1 or e2 is written => alias violation
1477  => insert test before every statement where e1 and e2 must be written
1478 
1479 *****************************************************************************/
1480 
1482  expression off2,list path)
1483 {
1484  expression diff = eq_expression(off1,off2);
1485  int k;
1486  clean_all_normalized(diff);
1487  k = trivial_expression_p(diff);
1488  /* Should we use also formal and actual binding / precondition ??? */
1489  ifdebug(2)
1490  fprintf(stderr,"\n Check in caller, 2 scalar variables \n");
1491  switch(k){
1492  case -1:
1493  /* off1 != off2 => Okay, no alias between these 2 variables */
1494  return;
1495  default:
1496  {
1497  /* insert flags before each call site in call path and for the
1498  current caller, we add the condition */
1499  list l_flags = make_list_of_flags(path);
1501  context.insert = false;
1502  context.path = path;
1503  context.flags = expression_list_to_conjonction(l_flags);
1504  context.first_entity = e1;
1505  context.second_entity = e2;
1508  context.first_entity = e2;
1509  context.second_entity = e1;
1512  if (context.insert)
1513  {
1514  expression e_flag = EXPRESSION(CAR(l_flags));
1516  if (k==1)
1518  else
1520  }
1521  context.first_entity = entity_undefined;
1522  context.second_entity = entity_undefined;
1523  context.offset1 = expression_undefined;
1524  context.offset2 = expression_undefined;
1525  context.condition = expression_undefined;
1526  context.flags = expression_undefined;
1527  context.path = NIL;
1528  }
1529  }
1530 }
1531 
1532 /*****************************************************************************
1533 
1534  This function checks if there is alias violation between a scalar variable e1
1535  and an array variable e2 or not.
1536 
1537  IF off1 < off2 OR off1 > off2+size_stride2 => no alias, OK
1538  ELSE : off2 <= off1 <= off2+size_stride2
1539  - IF e1 is written => alias violation
1540  - IF e2 is written (ref2 == subval_stride2+off2) :
1541  - IF ref2 != off1 => no alias violation
1542  - IF ref2 == off1 => alias violation
1543 
1544 *****************************************************************************/
1545 
1547  expression off1, expression off2,list path)
1548 {
1549  expression diff1 = le_expression(off2,off1);
1550  int k1;
1551  clean_all_normalized(diff1);
1552  k1 = trivial_expression_p(diff1);
1553  ifdebug(2)
1554  fprintf(stderr,"\n Check in caller, scalar and array variables \n");
1555  switch(k1){
1556  case -1:
1557  /* off2 <= off1 is false => Okay, no alias between these 2 variables */
1558  return;
1559  default:
1560  {
1561  expression size2 = array_size_stride(e2);
1562  if (!expression_undefined_p(size2))
1563  {
1564  /* Translate size2 to the frame of caller, in order to compare with offsets*/
1566  if (!expression_undefined_p(size2))
1567  {
1568  expression diff2;
1569  int k2;
1570  if (same_expression_p(off1,off2))
1571  diff2 = le_expression(int_to_expression(0),size2);
1572  else
1573  {
1574  expression sum2;
1575  if (expression_equal_integer_p(off2,0))
1576  sum2 = copy_expression(size2);
1577  else
1579  diff2 = le_expression(off1,sum2);
1580  }
1581  clean_all_normalized(diff2);
1582  k2 = trivial_expression_p(diff2);
1583  switch(k2){
1584  case -1:
1585  /* off1 <= off2+size_stride2 is false => Okay, no alias between these 2 variables */
1586  return;
1587  default:
1588  {
1589  /* k1 = 0 or 1, k2 = 0 or 1
1590  insert flag before each call site in call path and for the current caller,
1591  we add the condition */
1592  list l_flags = make_list_of_flags(path);
1594  context.insert = false;
1595  context.path = path;
1596  context.flags = expression_list_to_conjonction(l_flags);
1597  context.first_entity = e1;
1598  context.second_entity = e2;
1601 
1602  /* Attention: there are differences between scalar and array variables
1603  when adding test/flag before current statement and current caller.
1604  For array variable, we must take into account the ref (reference),
1605  it must be sure if this reference is written or not. So new flag
1606  is inserted to guarantee if the reference is written. */
1607 
1608  if (ENDP(CDR(l_flags)))
1609  context.flags = make_true_expression();
1610  else
1611  context.flags = expression_list_to_conjonction(CDR(l_flags));
1612  context.offset1 = off1;
1613  context.offset2 = off2;
1614  context.first_entity = e2;
1615  context.second_entity = e1;
1618 
1619  if (context.insert)
1620  {
1622  if (variable_is_written_p(e1))
1623  {
1624  expression e_flag = EXPRESSION(CAR(l_flags));
1625  if (k1+k2==0) // k1=k2=0
1627  simplify_relational_expression(diff2)),e_flag);
1628  else
1629  {
1630  if (k1+k2==2) // k1=k2=1
1632  else
1633  {
1634  if (k1==0) // k1=0, k2=1
1636  else // k2=0, k1=1
1638  }
1639  }
1640  }
1641  }
1642  context.first_entity = entity_undefined;
1643  context.second_entity = entity_undefined;
1644  context.offset1 = expression_undefined;
1645  context.offset2 = expression_undefined;
1646  context.condition = expression_undefined;
1647  context.flags = expression_undefined;
1648  context.path = NIL;
1649  }
1650  }
1651  }
1652  else
1653  pips_user_warning("\nCan not translate size of array to frame of caller");
1654  }
1655  else
1656  /* Assumed-size or pointer-type array, the size of dummy array can be
1657  derived from the size of actual argument, as we have the corresponding call chain*/
1658  pips_user_warning("\nAssumed-size or pointer-type array \n");
1659  }
1660  }
1661 }
1662 
1663 /*****************************************************************************
1664 
1665  These functions check if there is alias violation between two array variables or not.
1666 
1667  IF (off2+size_stride2<off1) OR (off2>off1+size_stride1) => OK, no alias
1668  ELSE
1669  IF e1 is written (ref1)
1670  IF (ref1 < off2) OR (ref1 > off2+size_stride2) => no alias violation
1671  ELSE (off2 <= ref1 <= off2+size_stride2) => alias violation
1672  IF e2 is written (ref2) : symetrical with e1
1673  IF (ref2 < off1) OR (ref2 > off1+size_stride1) => no alias violation
1674  ELSE (off1 <= ref2 <= off1+size_stride1) => alias violation
1675 
1676 *****************************************************************************/
1677 
1679  expression off1, expression off2,list path)
1680 {
1681  expression size2 = array_size_stride(e2);
1682  if (!expression_undefined_p(size2))
1683  {
1684  /* Translate size2 to the frame of caller, in order to compare with offsets*/
1686  if (!expression_undefined_p(size2))
1687  {
1688  expression sum2,diff1;
1689  int k1;
1690  if (expression_equal_integer_p(off2,0))
1691  sum2 = copy_expression(size2);
1692  else
1694  diff1 = gt_expression(off1,sum2);
1695  clean_all_normalized(diff1);
1696  k1 = trivial_expression_p(diff1);
1697  ifdebug(2)
1698  fprintf(stderr,"\n Check in caller, 2 array variables \n");
1699  switch(k1){
1700  case 1:
1701  /* off1>off2+size_stride2 is true => Okay, no alias between these 2 variables */
1702  return;
1703  default:
1704  {
1705  expression size1 = array_size_stride(e1);
1706  if (!expression_undefined_p(size1))
1707  {
1708  /* Translate size1 to the frame of caller, in order to compare with offsets*/
1710  if (!expression_undefined_p(size1))
1711  {
1712  expression sum1,diff2;
1713  int k2;
1714  if (expression_equal_integer_p(off1,0))
1715  sum1 = copy_expression(size1);
1716  else
1718  diff2 = gt_expression(off2,sum1);
1719  clean_all_normalized(diff2);
1720  k2 = trivial_expression_p(diff2);
1721  switch(k2){
1722  case 1:
1723  /* off2 > off1+size_stride1 is true => Okay, no alias between these 2 variables */
1724  return;
1725  default:
1726  {
1727  /* insert flag before each call site in call path */
1728  list l_flags = NIL;
1730  context.insert = false;
1731  context.path = path;
1732  if (ENDP(CDR(path)))
1733  context.flags = make_true_expression();
1734  else
1735  {
1736  l_flags = make_list_of_flags(CDR(path));
1737  context.flags = expression_list_to_conjonction(l_flags);
1738  }
1739  context.first_entity = e1;
1740  context.second_entity = e2;
1741  context.offset1 = off1;
1742  context.offset2 = off2;
1745  context.first_entity = e2;
1746  context.second_entity = e1;
1747  context.offset1 = off2;
1748  context.offset2 = off1;
1751 
1752  if (context.insert)
1754  context.first_entity = entity_undefined;
1755  context.second_entity = entity_undefined;
1756  context.offset1 = expression_undefined;
1757  context.offset2 = expression_undefined;
1758  context.condition = expression_undefined;
1759  context.flags = expression_undefined;
1760  context.path = NIL;
1761  }
1762  }
1763  }
1764  else
1765  pips_user_warning("\nCan not translate size of array to frame of caller");
1766  }
1767  else
1768  /* Assumed-size or pointer-type array, the size of dummy array can be
1769  derived from the size of actual argument, as we have the corresponding call chain*/
1770  pips_user_warning("\nAssumed-size or pointer-type array \n");
1771  }
1772  }
1773  }
1774  else
1775  pips_user_warning("\nCan not translate size of array to frame of caller");
1776  }
1777  else
1778  /* Assumed-size or pointer-type array, the size of dummy array can be
1779  derived from the size of actual argument, as we have the corresponding call chain*/
1780  pips_user_warning("\nAssumed-size or pointer-type array \n");
1781 }
1782 
1783 
1784 /*****************************************************************************
1785 
1786 
1787 *****************************************************************************/
1789  expression off2,list path)
1790 {
1791  if (entity_scalar_p(e1) && entity_scalar_p(e2))
1793 
1794  if (entity_scalar_p(e1) && !entity_scalar_p(e2))
1796 
1797  if (!entity_scalar_p(e1) && entity_scalar_p(e2))
1799 
1800  if (!entity_scalar_p(e1) && !entity_scalar_p(e2))
1802 }
1803 
1804 
1805 /*****************************************************************************
1806 
1807  This function computes the offset of a storage ram variable :
1808  offset = initial_offset + subscript_value_stride
1809 
1810 *****************************************************************************/
1811 
1813 {
1814  ram r = storage_ram(s);
1815  int initial_off = ram_offset(r);
1816  expression exp = int_to_expression(initial_off);
1817  if (!expression_equal_integer_p(subval,0))
1818  {
1819  if (initial_off == 0)
1820  exp = copy_expression(subval);
1821  else
1823  int_to_expression(initial_off),
1824  copy_expression(subval));
1825  }
1826  return exp;
1827 }
1828 
1829 /****************************************************************************
1830 
1831  This function computes the offset of a formal storage variable :
1832  offset = initial_offset + subscript_value_stride
1833 
1834  initial_offset is from alias_association with path' = path - {cs}
1835 
1836 *****************************************************************************/
1837 
1839  expression subval,list path)
1840 {
1841  list l_caller_aliases = alias_associations_list((alias_associations)
1842  db_get_memory_resource(DBR_ALIAS_ASSOCIATIONS,caller_name,true));
1844  MAP(ALIAS_ASSOCIATION, aa,
1845  {
1846  entity caller_var = alias_association_variable(aa);
1847  list caller_path = alias_association_call_chain(aa);
1848  if (same_entity_p(caller_var,actual_var) && tail_call_path_p(cs,caller_path,path))
1849  {
1850  expression initial_off = alias_association_offset(aa);
1851  if (!expression_undefined_p(initial_off))
1852  {
1853  if (expression_equal_integer_p(subval,0))
1854  exp = copy_expression(initial_off);
1855  else
1857  copy_expression(initial_off),
1858  copy_expression(subval));
1859  }
1860  return exp;
1861  }
1862  },
1863  l_caller_aliases);
1864  return exp;
1865 }
1866 
1867 
1868 /*****************************************************************************
1869 
1870  If e is a formal parameter, find its rank in the formal parameter list of
1871  current module in order to find out the corresponding actual argument and
1872  then its offset
1873  If e is a common variable in the current module, offset of e is constant
1874 
1875 *****************************************************************************/
1876 
1878 {
1879  ram ra ;
1880  if (formal_parameter_p(e))
1881  {
1883  int rank = formal_offset(f);
1884  list l_args = call_arguments(current_call);
1885  expression actual_arg = find_ith_argument(l_args,rank);
1886  reference actual_ref = expression_reference(actual_arg);
1887  entity actual_var = reference_variable(actual_ref);
1888  list l_actual_inds = reference_indices(actual_ref);
1889  /* compute the subscript value, return expression_undefined if
1890  if the actual argument is a scalar variable or array name*/
1891  expression subval = subscript_value_stride(actual_var,l_actual_inds);
1892  storage s = entity_storage(actual_var);
1893  ifdebug(3)
1894  fprintf(stderr, " \n Current actual argument %s",entity_name(actual_var));
1895  if (storage_ram_p(s))
1896  /* The actual argument has a ram storage */
1897  return storage_ram_offset(s,subval);
1898  if (storage_formal_p(s))
1899  /* The actual argument is a formal parameter of the current caller,
1900  we must take the alias_associations of the caller */
1901  return storage_formal_offset(cs,actual_var,subval,path);
1902  }
1903  // common variable
1904  ra = storage_ram(entity_storage(e));
1905  return int_to_expression(ram_offset(ra));
1906 }
1907 
1909 {
1911  {
1912  current_statement = s;
1913  return false;
1914  }
1915  return true;
1916 }
1917 
1919  expression off2, list path)
1920 {
1922  {
1923  /* e1 or e2 is written => check for alias violation*/
1924  if (!expression_undefined_p(off1) && !expression_undefined_p(off2))
1925  alias_check_in_module(e1,e2,off1,off2,path);
1926  else
1927  {
1928  /* As we do not have exact offsets of variables, we have to go to the
1929  caller's frame to check for alias violations. The direct caller is
1930  CAR(call_path) because of the following concatenation in alias_propagation:
1931  path = CONS(CALL_SITE,cs,gen_full_copy_list(alias_association_call_chain(aa)));
1932 
1933  To find a call site from its ordering, we have to do a gen_recurse
1934  in the caller module. */
1935 
1936  call_site cs = CALL_SITE(CAR(path));
1937  statement caller_statement;
1941  caller_statement = (statement)db_get_memory_resource(DBR_CODE,caller_name,true);
1943 
1944  gen_recurse(caller_statement,statement_domain,
1946 
1948  {
1949  expression new_off1, new_off2;
1951  new_off1 = offset_in_caller(e1,cs,path);
1952  new_off2 = offset_in_caller(e2,cs,path);
1953  if (!expression_undefined_p(new_off1) && !expression_undefined_p(new_off2))
1954  alias_check_in_caller(e1,e2,new_off1,new_off2,path);
1955  else
1956  {
1957  /* Try with special cases : CALL FOO(R(TR(K)),R(TR(K))) ???????
1958  Does this case exist when we create special section + offset
1959  for same actual arguments ??? */
1960  /* use dynamic alias check*/
1962  context.first_entity = e1;
1963  context.second_entity = e2;
1966  context.first_entity = e2;
1967  context.second_entity = e1;
1970  context.first_entity = entity_undefined;
1971  context.second_entity = entity_undefined;
1972  set_dynamic_checked(e1,e2);
1973  }
1975  }
1976  else
1977  pips_user_warning("Problem with statement ordering *\n");
1979  current_ordering = 0;
1981  }
1982  }
1983 }
1984 
1985 /*****************************************************************************
1986  Take pair of variables (formal and formal or formal and common) that
1987  may be aliased (in same section, included call path), then check if they
1988  are really aliased or not.
1989  If no , OK.
1990  If yes, gen_recurse on statements that write these variables => check for
1991  alias violations
1992 *****************************************************************************/
1993 
1995 {
1996  /* File instrument.out is used to store alias checks and flags*/
1997  string dir_name = db_get_current_workspace_directory();
1998  string instrument_file = strdup(concatenate(dir_name, "/instrument.out", NULL));
1999  free(dir_name), dir_name = NULL;
2000  out = safe_fopen(instrument_file, "a");
2003  /* We do not add the line "INCLUDE alias_flags.h" into code_decls_text because of
2004  repeated bug for module with ENTRY.
2005  09/11/2001 : do not add INCLUDE any more, because there are modules that do not
2006  need this INCLUDE => use script: if a module is modified => add INCLUDE line
2007  fprintf(out, "AC: %s (%d,%d)\n",module_local_name(current_mod),0,1);
2008  fprintf(out," INCLUDE 'alias_flags.h'\n");
2009  fprintf(out, "ACEND \n");*/
2010  debug_on("ALIAS_CHECK_DEBUG_LEVEL");
2011  ifdebug(1)
2012  fprintf(stderr, " \n Begin alias_check for %s \n", module_name);
2014  db_get_memory_resource(DBR_ALIAS_ASSOCIATIONS,module_name,true));
2015  /* if the list of alias associations of module is NIL, do nothing*/
2016  if (l_module_aliases != NIL)
2017  {
2018  /* Compute the list of direct and indirect callees of current module */
2019  // list l_callees = compute_all_callees(current_mod);
2020  string alias_flag_name = strdup(concatenate(TOP_LEVEL_MODULE_NAME,
2022  string alias_function_name = strdup(concatenate(TOP_LEVEL_MODULE_NAME,
2024  alias_flag = gen_find_tabulated(alias_flag_name,entity_domain);
2026  alias_flag = make_entity(alias_flag_name,
2030  alias_function = gen_find_tabulated(alias_function_name,entity_domain);
2034  ifdebug(2)
2035  {
2036  fprintf(stderr, " \n The list of alias associations for module %s is:\n", module_name);
2038  }
2041  /* Get the proper and cumulated effects of the module, we have to take both kinds of
2042  effects because of their difference for an elementary statement:
2043  V(I) = I => cumulated effect : <may be written> V(*)
2044  => proper effect : <must be written> V(I)
2045  If a cumulated effect for elementary statements = proper effect => we need only
2046  cumulated effect */
2048  db_get_memory_resource(DBR_CUMULATED_EFFECTS,module_name,true));
2050  db_get_memory_resource(DBR_PROPER_EFFECTS,module_name,true));
2052  while (!ENDP(l_module_aliases))
2053  {
2056  entity sec1 = alias_association_section(aa1);
2057  list path1 = alias_association_call_chain(aa1);
2059  int l1 = alias_association_lower_offset(aa1);
2060  int u1 = alias_association_upper_offset(aa1);
2062 
2063  /* Looking for another formal variable in the list of alias
2064  associations that has same section and included call path.
2065  If this variable is checked dynamically with e1 => no need
2066  to continue */
2067 
2068  MAP(ALIAS_ASSOCIATION, aa2,
2069  {
2071  entity sec2 = alias_association_section(aa2);
2072  list path2 = alias_association_call_chain(aa2);
2073  if (!same_entity_p(e1,e2) && same_entity_p(sec1,sec2) &&
2074  !dynamic_checked_p(e1,e2)&& included_call_chain_p(path1,path2))
2075  {
2076  int l2 = alias_association_lower_offset(aa2);
2077  int u2 = alias_association_upper_offset(aa2);
2078  /*
2079  Special cases : no alias u1 < l2, u2 <l1, u1< o1, u2 < o1,
2080  o2 + s2 < l1, o1 + s1 < l2
2081  So easiest case: If u1,l2 are defined (different to -1) and u1<l2,
2082  there is no alias violation
2083  The same for: u2,l1 are defined (different to -1) and u2<l1*/
2084  if (((u1==-1)||(u1>=l2))&&((u2==-1)||(u2>=l1)))
2085  {
2087  ifdebug(2)
2088  fprintf(stderr, "\nFound two may be aliased formal parameters: %s, %s. Let's check !\n",
2089  entity_name(e1),entity_name(e2));
2090  if (gen_length(path1) < gen_length(path2))
2091  alias_check_two_variables(e1,e2,off1,off2,path2);
2092  else
2093  alias_check_two_variables(e1,e2,off1,off2,path1);
2094  }
2095  }
2096  },
2097  l_module_aliases);
2098 
2099  /* Looking for common variables in module or callee of modules
2100  to check for alias violation ...*/
2101 
2102  /* For this moment, only for common variable of module
2103  ========> add for chain of callees
2104 
2105  Check for write on common variables in callee, keep call path also
2106  => to insert test*/
2107 
2108  MAP(ENTITY, e2,
2109  {
2110  if (variable_in_common_p(e2))
2111  {
2112  ram ra = storage_ram(entity_storage(e2));
2113  entity sec2 = ram_section(ra);
2114  if (!dynamic_checked_p(e1,e2) && same_entity_p(sec1,sec2))
2115  {
2116  /* formal parameter has a same section with other common variable*/
2117  int l2 = ram_offset(ra);
2118  int u2 = l2;
2119  if (array_entity_p(e2))
2120  {
2121  int tmp;
2122  if (SizeOfArray(e2,&tmp))
2124  else
2125  user_log("Varying size of common variable");
2126  }
2127  /* If u1 is defined (different to -1) and u1<l2, there is no alias violation
2128  The same for: l1 is defined (different to -1) and u2<l1*/
2129  if (((u1==-1)||(u1>=l2))&&(u2>=l1))
2130  {
2131  expression off2 = int_to_expression(l2);
2132  /* The common variable always have a good offset off2 */
2133  ifdebug(2)
2134  fprintf(stderr,"\n Found may be aliased formal and common variable :%s, %s. Let's check ! \n",
2135  entity_name(e1), entity_name(e2));
2136  alias_check_two_variables(e1,e2,off1,off2,path1);
2137  }
2138  }
2139  }
2140  },
2142  }
2143  l_dynamic_check = NIL;
2150  // free(alias_flag_name), alias_flag_name = NULL;
2151  // free(alias_function_name), alias_function_name = NULL;
2152  }
2153  else
2154  user_log("\n No alias for this module \n");
2155 
2156  safe_fclose(out,instrument_file);
2157  free(instrument_file), instrument_file= NULL;
2159  pips_debug(1, "end\n");
2160  debug_off();
2163  return true;
2164 }
2165 
2166 
2167 
2168 
2169 
2170 
2171 
2172 
2173 
void user_log(const char *format,...)
Definition: message.c:234
dynamic_check make_dynamic_check(entity a1, entity a2, bool a3)
call make_call(entity a1, list a2)
Definition: ri.c:269
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
language copy_language(language p)
LANGUAGE.
Definition: ri.c:1202
test make_test(expression a1, statement a2, statement a3)
Definition: ri.c:2607
variable make_variable(basic a1, list a2, list a3)
Definition: ri.c:2895
basic make_basic_logical(intptr_t _field_)
Definition: ri.c:164
type make_type(enum type_utype tag, void *val)
Definition: ri.c:2706
static void insert_test_before_statement(expression flags, expression condition, statement s, entity e1, entity e2, list path)
Definition: alias_check.c:387
static void alias_check_in_caller(entity e1, entity e2, expression off1, expression off2, list path)
Definition: alias_check.c:1788
expression simplify_relational_expression(expression e)
alias_check.c
Definition: alias_check.c:139
static FILE * out
Definition: alias_check.c:128
static void alias_check_scalar_and_array_variables_in_caller(entity e1, entity e2, expression off1, expression off2, list path)
Definition: alias_check.c:1546
static int current_ordering
Definition: alias_check.c:127
bool alias_check(char *module_name)
Definition: alias_check.c:1994
static void initialize_dynamic_check_list()
Definition: alias_check.c:175
static void alias_check_two_array_variables_in_caller(entity e1, entity e2, expression off1, expression off2, list path)
Definition: alias_check.c:1678
static expression offset_in_caller(entity e, call_site cs, list path)
Definition: alias_check.c:1877
static bool same_call_site_p(call_site cs1, call_site cs2)
Definition: alias_check.c:228
static void display_alias_check_statistics()
Definition: alias_check.c:167
static string print_call_path(list path)
This function prints the call path , including names of caller functions and orderings of call sites ...
Definition: alias_check.c:277
static int number_of_tests
Definition: alias_check.c:134
static bool dynamic_checked_p(entity e1, entity e2)
Definition: alias_check.c:209
static bool alias_check_array_variable_in_module_flt(statement s, alias_context_p context)
Definition: alias_check.c:773
static void insert_flag_before_call_site(list flags, list path)
Definition: alias_check.c:428
static void alias_check_two_array_variables_in_module(entity e1, entity e2, expression off1, expression off2, list path)
Definition: alias_check.c:1062
static bool dynamic_alias_check_flt(statement s, alias_context_p context)
Definition: alias_check.c:603
bool included_call_chain_p(list l1, list l2)
Definition: alias_check.c:246
static entity alias_flag
Definition: alias_check.c:129
static void alias_check_in_module(entity e1, entity e2, expression off1, expression off2, list path)
Definition: alias_check.c:1161
#define ALIAS_FLAG
Definition: alias_check.c:104
static entity alias_function
Definition: alias_check.c:130
#define PREFIX1
TO AMELIORATE : for the moment, we only use trivial_expression_p to compare offsets + array sizes CAN...
Definition: alias_check.c:102
static bool search_statement_by_ordering_flt(statement s)
Definition: alias_check.c:1908
static expression array_size_stride(entity ent)
Definition: alias_check.c:338
static void alias_check_two_scalar_variables_in_module(entity e1, entity e2, expression off1, expression off2, list path)
Definition: alias_check.c:894
static entity current_entity
Definition: alias_check.c:513
static void set_dynamic_checked(entity e1, entity e2)
Definition: alias_check.c:219
static bool alias_check_array_variable_in_caller_flt(statement s, alias_context_p context)
Definition: alias_check.c:1331
static entity current_caller
Definition: alias_check.c:121
static bool variable_is_written_p(entity ent)
Definition: alias_check.c:553
static bool tail_call_path_p(call_site cs, list l1, list l2)
Definition: alias_check.c:265
bool functional_call_p(call c)
This function returns true if c is an user-defined function/subroutine.
Definition: alias_check.c:506
struct alias_context_t * alias_context_p
static expression storage_formal_offset(call_site cs, entity actual_var, expression subval, list path)
Definition: alias_check.c:1838
static void insert_check_alias_before_statement(entity e1, expression subval, entity e2, expression size, statement s)
Definition: alias_check.c:563
static int unique_flag_number
Definition: alias_check.c:133
static int number_of_processed_modules
Definition: alias_check.c:136
static expression storage_ram_offset(storage s, expression subval)
Definition: alias_check.c:1812
static statement module_statement
Definition: alias_check.c:125
#define PREFIX2
Definition: alias_check.c:103
#define ALIAS_FUNCTION
Definition: alias_check.c:105
static int number_of_calls
Definition: alias_check.c:135
static void alias_check_two_variables(entity e1, entity e2, expression off1, expression off2, list path)
Definition: alias_check.c:1918
static void insert_test_before_caller(expression condition, expression e_flag)
Definition: alias_check.c:458
static call current_call
Definition: alias_check.c:123
static list l_module_aliases
Definition: alias_check.c:124
static statement current_statement
Definition: alias_check.c:126
static bool alias_check_array_and_scalar_variable_in_caller_flt(statement s, alias_context_p context)
Definition: alias_check.c:1231
void print_list_of_alias_associations(list l)
Definition: alias_check.c:324
static bool alias_check_scalar_variable_in_caller_flt(statement s, alias_context_p context)
Definition: alias_check.c:1190
static void alias_check_scalar_and_array_variables_in_module(entity e1, entity e2, expression off1, expression off2, list path)
Definition: alias_check.c:955
static void alias_check_two_scalar_variables_in_caller(entity e1, entity e2, expression off1, expression off2, list path)
Definition: alias_check.c:1481
static list make_list_of_flags(list path)
Definition: alias_check.c:484
void print_alias_association(alias_association aa)
Definition: alias_check.c:301
static bool alias_check_array_and_scalar_variable_in_module_flt(statement s, alias_context_p context)
Definition: alias_check.c:696
static list l_dynamic_check
This list tells us if two variables have been checked dynamically or not.
Definition: alias_check.c:132
static entity current_mod
Definition: alias_check.c:120
static const char * caller_name
Definition: alias_check.c:122
static bool variable_is_written_by_statement_flt(statement s)
This function returns true if the variable is written directly in the current module,...
Definition: alias_check.c:518
static bool alias_check_scalar_variable_in_module_flt(statement s, alias_context_p context)
Definition: alias_check.c:654
static bool written
Definition: alias_check.c:512
#define dynamic_check_second(x)
#define alias_associations_list(x)
Definition: alias_private.h:86
#define alias_association_lower_offset(x)
#define CALL_SITE(x)
CALL_SITE.
#define call_site_function(x)
#define alias_association_upper_offset(x)
#define alias_association_section(x)
#define alias_association_variable(x)
#define ALIAS_ASSOCIATION(x)
ALIAS_ASSOCIATION.
Definition: alias_private.h:90
#define dynamic_check_checked(x)
#define alias_association_call_chain(x)
#define dynamic_check_first(x)
#define alias_association_offset(x)
#define DYNAMIC_CHECK(x)
DYNAMIC_CHECK.
#define call_site_ordering(x)
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....
void const char const char const int
static list l_commons
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
expression MakeCharacterConstantExpression(string s)
END_EOLE.
Definition: constant.c:573
list load_proper_rw_effects_list(statement)
void reset_proper_rw_effects(void)
void set_proper_rw_effects(statement_effects)
void set_cumulated_rw_effects(statement_effects)
list load_cumulated_rw_effects_list(statement)
void reset_cumulated_rw_effects(void)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
#define approximation_exact_p(x)
Definition: effects.h:369
#define effect_action(x)
Definition: effects.h:642
#define action_write_p(x)
Definition: effects.h:314
#define effect_approximation(x)
Definition: effects.h:644
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
FILE * safe_fopen(const char *filename, const char *what)
Definition: file.c:67
int safe_fclose(FILE *stream, const char *filename)
Definition: file.c:77
char * pips_basename(char *fullpath, char *suffix)
Definition: file.c:822
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
static FILE * user_file
These functions implements the writing of objects.
Definition: genClib.c:1485
void free(void *)
statement make_block_statement(list)
Make a block statement from a list of statement.
Definition: statement.c:616
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
void gen_null2(__attribute__((unused)) void *u1, __attribute__((unused)) void *u2)
idem with 2 args, to please overpeaky compiler checks
Definition: genClib.c:2758
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
#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 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
call statement_call(statement)
Get the call of a statement.
Definition: statement.c:1406
bool statement_call_p(statement)
Definition: statement.c:364
statement make_assign_statement(expression, expression)
Definition: statement.c:583
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 expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
string db_get_directory_name_for_module(const char *name)
returns the allocated and mkdir'ed directory for module name
Definition: lowlevel.c:150
#define debug_on(env)
Definition: misc-local.h:157
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_user_warning
Definition: misc-local.h:146
#define debug_off()
Definition: misc-local.h:160
static entity rank
#define TOP_LEVEL_MODULE_NAME
Module containing the global variables in Fortran and C.
Definition: naming-local.h:101
#define MODULE_SEP_STRING
Definition: naming-local.h:30
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
void * gen_find_tabulated(const char *, int)
Definition: tabulated.c:218
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
int f2(int off1, int off2, int w, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:1
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
#define WORKSPACE_SRC_SPACE
Definition: pipsdbm-local.h:32
string db_get_current_workspace_directory(void)
Definition: workspace.c:96
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
void fprint_statement(FILE *, statement)
Print statement "s" on file descriptor "fd".
Definition: statement.c:68
#define MINUS_OPERATOR_NAME
#define PLUS_OPERATOR_NAME
#define ORDERING_NUMBER(o)
#define ORDERING_STATEMENT(o)
#define NORMALIZE_EXPRESSION(e)
#define gt_expression(e1, e2)
#define make_entity(n, t, s, i)
#define test_to_statement(t)
#define and_expression(e1, e2)
#define binary_intrinsic_expression(name, e1, e2)
#define call_to_statement(c)
#define ge_expression(e1, e2)
#define le_expression(e1, e2)
#define eq_expression(e1, e2)
#define module_language(e)
implemented as a macro to allow lhs
#define MULTIPLY_OPERATOR_NAME
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
bool array_entity_p(entity e)
Definition: entity.c:793
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
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
bool pointer_type_array_p(entity e)
Definition: entity.c:826
code entity_code(entity e)
Definition: entity.c:1098
entity make_empty_subroutine(const char *name, language l)
Definition: entity.c:268
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
bool entity_module_p(entity e)
Definition: entity.c:683
expression reference_to_expression(reference r)
Definition: expression.c:196
expression Pvecteur_to_expression(Pvecteur vect)
AP, sep 25th 95 : some usefull functions moved from static_controlize/utils.c.
Definition: expression.c:1825
void clean_all_normalized(expression e)
Definition: expression.c:4102
int expression_to_int(expression exp)
================================================================
Definition: expression.c:2205
int trivial_expression_p(expression e)
This function returns:
Definition: expression.c:679
bool true_expression_p(expression e)
Definition: expression.c:1113
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
expression expression_list_to_conjonction(list l)
Definition: expression.c:1937
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
expression find_ith_argument(list args, int n)
Definition: expression.c:1147
expression subscript_value_stride(entity arr, list l_inds)
Definition: expression.c:4127
bool expression_equal_integer_p(expression exp, int i)
================================================================
Definition: expression.c:1977
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
bool relational_expression_p(expression e)
Definition: expression.c:587
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 SizeOfArray(entity, int *)
This function computes the total size of a variable in bytes, ie.
Definition: size.c:87
bool entity_scalar_p(entity)
The concrete type of e is a scalar type.
Definition: variable.c:1113
bool variable_in_common_p(entity)
true if v is in a common.
Definition: variable.c:1570
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_undefined
Definition: ri.h:3016
#define storage_formal_p(x)
Definition: ri.h:2522
#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 ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define statement_ordering(x)
Definition: ri.h:2454
#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 code_declarations(x)
Definition: ri.h:784
#define storage_ram_p(x)
Definition: ri.h:2519
#define ram_section(x)
Definition: ri.h:2249
#define storage_formal(x)
Definition: ri.h:2524
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define entity_undefined_p(x)
Definition: ri.h:2762
#define entity_undefined
Definition: ri.h:2761
#define expression_undefined
Definition: ri.h:1223
#define entity_name(x)
Definition: ri.h:2790
#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 expression_undefined_p(x)
Definition: ri.h:1224
#define variable_dimensions(x)
Definition: ri.h:3122
#define storage_ram(x)
Definition: ri.h:2521
#define call_arguments(x)
Definition: ri.h:711
#define statement_undefined_p(x)
Definition: ri.h:2420
@ is_type_variable
Definition: ri.h:2900
#define entity_type(x)
Definition: ri.h:2792
#define call_undefined
Definition: ri.h:685
#define normalized_linear(x)
Definition: ri.h:1781
#define expression_syntax(x)
Definition: ri.h:1247
#define entity_domain
newgen_syntax_domain_defined
Definition: ri.h:410
#define variable_basic(x)
Definition: ri.h:3120
#define statement_undefined
Definition: ri.h:2419
#define ram_offset(x)
Definition: ri.h:2251
#define storage_undefined
Definition: ri.h:2476
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
#define ifdebug(n)
Definition: sg.c:47
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
expression offset2
Definition: alias_check.c:112
entity first_entity
Definition: alias_check.c:109
expression offset1
Definition: alias_check.c:111
expression condition
Definition: alias_check.c:113
entity second_entity
Definition: alias_check.c:110
expression flags
Definition: alias_check.c:114
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: delay.c:253
#define CHAIN_SWORD(l, s)
string words_to_string(cons *lw)
Definition: print.c:211
char * int2a(int)
util.c
Definition: util.c:42
static int k2
static int k1
static string file_name
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207
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_normalize(Pvecteur v)
void vect_normalize(Pvecteur v): division de tous les coefficients de v par leur pgcd; "normalisation...
Definition: unaires.c:59