PIPS
expression.c
Go to the documentation of this file.
1 /*
2 
3  $Id: expression.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  * Functions for the expressions
29  *
30  * Yi-Qing YANG, Lei ZHOU, Francois IRIGOIN, Fabien COELHO
31  *
32  * 12, Sep, 1991
33  *
34  * Alexis PLATONOFF, Sep. 25, 1995 : I have added some usefull functions from
35  * static_controlize/utils.c
36  */
37 
38 #include <stdio.h>
39 #include <string.h>
40 #include <ctype.h>
41 
42 #include "linear.h"
43 #include "genC.h"
44 #include "misc.h"
45 #include "ri.h"
46 
47 #include "ri-util.h"
48 #include "properties.h"
49 
50 /**************************************************** FORTRAN STRING COMPARE */
51 
52 /* quite lazy...
53  */
54 static string actual_fortran_string_to_compare(string fs, int * plength)
55 {
56  string s = fs;
57  int len;
58 
59  /* skip TOP-LEVEL header */
60  if (strncmp(s, TOP_LEVEL_MODULE_NAME, strlen(TOP_LEVEL_MODULE_NAME))==0)
61  s += strlen(TOP_LEVEL_MODULE_NAME);
62 
63  /* skip : header */
64  if (strncmp(s, MODULE_SEP_STRING, strlen(MODULE_SEP_STRING))==0)
65  s += strlen(MODULE_SEP_STRING);
66 
67  len = strlen(s);
68 
69  /* skip surrounding quotes */
70  if (len>=2 &&
71  ((s[0]=='\'' && s[len-1]=='\'') || (s[0]=='"' && s[len-1]=='"')))
72  {
73  s++;
74  len -= 2;
75  }
76 
77  /* skip trailing *spaces* (are these blanks?) if any. */
78  while (len>0 && s[len-1]==' ')
79  len--;
80 
81  *plength = len;
82  return s;
83 }
84 
85 /* compare pips fortran string constants from the fortran point of view.
86  *
87  * as of 3.1 and 6.3.5 of the Fortran 77 standard, the character order
88  * is not fully specified. It states:
89  * - A < B < C ... < Z
90  * - 0 < 1 < 2 ... < 9
91  * - blank < 0
92  * - blank < A
93  * - 9 < A *OR* Z < 0
94  * since these rules are ascii compatible, we'll take ascii.
95  * in practice, this may be implementation dependent?
96  *
97  * @param fs1 constant fortran string (entity name is fine)
98  * @param fs2 constant fortran string (entity name is fine)
99  * @return -n 0 +n depending on < == >, n first differing char.
100  */
101 int fortran_string_compare(string fs1, string fs2)
102 {
103  int l1, l2, i, c = 0;
104  string s1, s2;
105 
106  /* skip headers, trailers... */
108  s2 = actual_fortran_string_to_compare(fs2, &l2);
109 
110  /* collating sequence comparison. */
111  for (i=0; c==0 && i<l1 && i<l2; i++)
112  {
113  if (s1[i] < s2[i]) c = -i-1;
114  if (s1[i] > s2[i]) c = i+1;
115  }
116 
117  /* equal string header case. */
118  if (c==0 && l1!=l2)
119  c = (l1<l2)? -l1-1: l2+1;
120 
121  return c;
122 }
123 
124 /********************************************************************* BASIC */
125 
126 /* a BASIC tag is returned for the expression
127  * this is a preliminary version. should be improved.
128  * was in HPFC.
129  */
131 {
132  tag result = basic_tag(expression_basic(e));
133 
134  if (result==is_basic_overloaded)
135  {
136  syntax s = expression_syntax(e);
137 
138  /* must be a call
139  */
140  assert(syntax_call_p(s));
141 
143  result = is_basic_logical;
144  else
145  {
146  /* else some clever analysis could be done
147  */
148  pips_user_warning("an overloaded is turned into an int...\n");
149  result = is_basic_int;
150  }
151  }
152 
153  return result;
154 }
155 
157 {
158  pips_internal_error("not implemented");
159  return ex;
160 }
161 
162 /* if v is a constant, returns a constant call.
163  * if v is a variable, returns a reference to v.
164  */
166 {
167  if(entity_symbolic_p(e))
168  return call_to_expression(make_call(e, NIL));
169  else if (entity_constant_p(e))
170  return call_to_expression(make_call(e, NIL));
171  else /* should be a scalar variable! */
173 }
174 
175 
177 {
179  if( entity_constant_p(e) )
180  {
182  }
183  else
184  {
185  reference r = make_reference(e, inds);
186  s = make_syntax_reference(r);
187  }
188  return syntax_to_expression(s);
189 }
190 
191 /*
192  * remarks: why is the default to normalized_complex~?
193  * should be undefined, OR normalized if possible.
194  * I put normalize_reference... FC 27/09/93 and june 94
195  */
197 {
198  expression e;
200 
202 
203  return e;
204 }
205 
206 
207 /*
208  * Get a reference from an expression. The expression has to contain
209  * directly a syntax containing directly the reference.
210  * NL : what the difference with expression_reference?
211  */
213 {
214  syntax s = expression_syntax(e);
215  message_assert("reference", syntax_reference_p(s));
216  return syntax_reference(s);
217 }
218 ␌
219 /* Add a last subscript expression s to a reference r
220  *
221  * The validity of the input reference is not checked.
222  * The validity of the output reference is not checked either.
223  */
225 {
227  CONS(EXPRESSION, s, NIL));
228  return r;
229 }
230 
231 /* Add a set of zero subscripts to a reference "r" by side effect.
232  *
233  * Used when array names or partial array references have to to
234  * converted to the first array element.
235  */
237 {
238  pips_assert("type is of kind variable", type_variable_p(t));
239  variable v = type_variable(t);
240  //list rsl = reference_indices(r);
241 
242  // FI: this assert makes sense within the ri-util framework but is
243  // too strong for the kind of references used in effects-util
244  // pips_assert("scalar type", ENDP(reference_indices(r)));
245 
246  list dl = variable_dimensions(v);
247  //
248  //pips_assert("Reference r is correct", gen_length(dl)>=gen_length(rsl));
249  //
250  //FOREACH(EXPRESSION, rs, rsl)
251  // POP(dl);
252  list sl = NIL; // subscript list
253  FOREACH(DIMENSION, d, dl) {
255  // reference_indices(r) = CONS(EXPRESSION, s, reference_indices(r));
256  sl = CONS(EXPRESSION, s, sl);
257  }
259 }
260 
262 {
264 }
265 
266 /* No check on reference r. This may generate an illegal reference if not called properly */
268 {
271  CONS(EXPRESSION, z, NIL));
272 }
273 
274 /* Reference r to an array maybe partial, as is possible in C: with
275  declaration "int a[10][10]", references "a", "a[i]" and "a[i][j]"
276  are all legal. The subscript list of reference r is completed with
277  0 subscript to reference an array element. */
279 {
280  list rsl = reference_indices(r);
281  entity e = reference_variable(r);
283  pips_assert("t is a type of kind variable", type_variable_p(t));
284  variable v = type_variable(t);
285  list dl = variable_dimensions(v);
286 
287  if(gen_length(dl)>gen_length(rsl)) {
288  FOREACH(EXPRESSION, rs, rsl)
289  POP(dl);
290  list sl = NIL; // subscript list
291  FOREACH(DIMENSION, d, dl) {
292  // expression s = zero_p? int_to_expression(0) : make_unbounded_expression();
294  sl = CONS(EXPRESSION, s, sl);
295  }
297  }
298 }
299 
301 {
303 }
304 ␌
305 /* Build an expression that call a function or procedure.
306 
307  @param c is the call
308  */
310 {
313 }
314 
315 
316 /* Build an expression that call an function entity with an argument list.
317 
318  @param e is the function entity to call
319  @param l is the list of argument expressions given to the function to call
320  */
322 {
323  return call_to_expression(make_call(e, l));
324 }
325 
326 
327 /* Creates a call expression to a function with zero arguments.
328 
329  @param f is the function entity to call
330  */
332 {
333  return make_call_expression(f, NIL);
334 }
335 
336 
337 /* Creates a call expression to a function with one argument.
338 
339  @param f is the function entity to call
340  @param a is the argument expression given to the function to call
341  */
343 {
344  return make_call_expression(f, CONS(EXPRESSION, a, NIL));
345 }
346 
347 
348 /* Creates a call expression to a function with 2 arguments.
349 
350  @param f is the function entity to call
351  @param eg is the first argument expression given to the function to call
352  @param ed is the second argument expression given to the function to call
353  */
356  CONS(EXPRESSION, ed, NIL)));
357 }
358 
359 
360 /* Creates a call expression to a function with 3 arguments.
361 
362  @param f is the function entity to call
363  @param e1 is the first argument expression given to the function to call
364  @param e2 is the second argument expression given to the function to call
365  @param e3 is the second argument expression given to the function to call
366  */
368  expression e1,
369  expression e2,
370  expression e3) {
371  return make_call_expression(f,
372  CONS(EXPRESSION, e1,
373  CONS(EXPRESSION, e2,
374  CONS(EXPRESSION, e3,
375  NIL))));
376 }
377 
378 
379 /* Make an assign expression, since in C the assignment is a side effect
380  operator.
381 
382  Useful in for-loops.
383 
384  @param lhs must be a reference
385  @param rhs is the expression to assign
386 
387  @return the expression "lhs = rhs"
388 */
391  expression rhs) {
392  /* RK: this assert should be relaxed to deal with *p and so on.
393  pips_assert("Need a reference as lhs", expression_reference_p(lhs)); */
395 }
396 
398 {
399  subscript i = make_subscript(a, sl);
402  return e;
403 }
404 
405 /* predicates and short cut accessors on expressions */
406 
408  if(expression_call_p(e)) {
409  call c = expression_call(e);
411  }
412  return false;
413 }
414 
416 {
417  return(syntax_call_p(expression_syntax(e)));
418 }
419 
421 {
422  bool address_p = false;
423  syntax s = expression_syntax(e);
424  if(syntax_call_p(s)) {
425  call c = syntax_call(s);
426  entity f = call_function(c);
428  address_p = true;
429  }
430  return address_p;
431 }
432 #if false
434 {
435  if (expression_call_p(e))
436  {
437  call c = expression_call(e);
439  }
440  else
441  return false;
442 }
443 #endif
444 
446 {
447  return(syntax_call(expression_syntax(e)));
448 }
449 
451 {
452  return(syntax_cast_p(expression_syntax(e)));
453 }
454 
456 {
457  return(syntax_cast(expression_syntax(e)));
458 }
459 
461 {
463 }
464 
466 {
468 }
469 /* Duplicate
470 bool expression_subscript_p(expression e)
471 {
472  return(syntax_subscript_p(expression_syntax(e)));
473 }
474 
475 subscript expression_subscript(expression e)
476 {
477  return(syntax_subscript(expression_syntax(e)));
478 }
479 */
481 {
483 }
484 
486 {
488 }
489 
490 /* The expression is of kind "s.a", where "s" is a struct and a "a" field. */
492 {
493  return expression_call_p(e)
495 }
496 
497 /* The expression is of kind "a", where "a" is a field of some struct "s". */
499 {
500  return expression_reference_p(e)
502 }
503 /* we get the type of the expression by calling expression_to_type()
504  * which allocates a new one. Then we call ultimate_type() to have
505  * the final type. Finally we test if it's a pointer by using pointer_type_p().*/
507  type et = expression_to_type(e);
508  type t = ultimate_type(et);
509  return pointer_type_p(t);
510 
511 }
512 
514 {
515  if (expression_reference_p(e))
516  {
519  if (array_entity_p(ent)) return true;
520  }
521  return false;
522 }
523 
524 
525 
526 /* Test if an expression is a reference.
527  */
530 }
531 
533 {
534  /* Assume e is a reference expression:
535  expression_reference_p(e)==true */
537 }
538 
539 /* Test if an expression is a reference to a given variable entity.
540  */
542 {
543  bool is_e_reference_to_v = false;
544 
545  if(expression_reference_p(e)) {
547 
548  is_e_reference_to_v = (reference_variable(r)==v);
549  }
550  return is_e_reference_to_v;
551 }
552 
553 ␌
554 /* This function returns true, if there exists a same expression in the list
555  * false, otherwise
556 */
558 {
559  MAP(EXPRESSION, f, if (same_expression_p(e,f)) return true, le);
560  return false;
561 }
562 
563 /* This function returns true, if there exists an expression equal in the list
564  * false, otherwise
565 */
567 {
568  MAP(EXPRESSION, f, if (expression_equal_p(e,f)) return true, le);
569  return false;
570 }
571 
572 /* C xor is missing */
574 {
575  /* Logical operators are : .NOT.,.AND.,.OR.,.EQV.,.NEQV.*/
576  if (expression_call_p(e))
577  {
579  if (ENTITY_AND_P(op) || ENTITY_OR_P(op) || ENTITY_NOT_P(op) ||
581  return true;
582  return false;
583  }
584  return false;
585 }
586 
588 {
589  /* A relational expression is a call whose function is either one of the following :
590  * .LT.,.LE.,.EQ.,.NE.,.GT.,.GE. */
591  if (expression_call_p(e))
592  {
595  return true;
596  return false;
597  }
598  return false;
599 }
600 
602 {
603  basic b = basic_of_expression(e);
604  bool integer_p = basic_int_p(b);
605 
606  free_basic(b);
607  return integer_p;
608 }
609 
611 {
612  /* A logical expression is either one of the following:
613  * - a logical constant
614  * - the symbolic name of a logical constant
615  * - a logical variable name
616  * - a logical array element name
617  * - a logical function reference
618  * - a relational expression (.LT.,.LE.,.EQ.,.NE.,.GT.,.GE.)
619  * - is formed by combining together one or more of the above
620  * entities using parentheses and the logical operators
621  * .NOT.,.AND.,.OR.,.EQV.,.NEQV. */
622 
623  /* NN: In fact, I didn't use the PIPS function : basic_of_expression because of 2 reasons :
624  * - the function basic_of_intrinsic use the macro : ENTITY_LOGICAL_OPERATOR_P
625  * which is not like the Fortran Standard definition (the above comments)
626  * - the case where an expression is a range is not considered here for a
627  * logical expression */
628 
629  syntax s = expression_syntax(e);
630  basic b;
631  entity func;
632 
633  pips_debug(2, "\n");
634 
635  switch(syntax_tag(s)) {
636  case is_syntax_reference:
637  {
639  if (basic_logical_p(b))
640  return true;
641  return false;
642  }
643  case is_syntax_call:
644  {
649  return true;
652  if (basic_logical_p(b)) return true;
653 
654  /* The case of symbolic name of a logical constant is not treated here */
655 
656  return false;
657  }
658  case is_syntax_range:
659  return false;
660  default: pips_internal_error("Bad syntax tag");
661  return false;
662  }
663 
664  debug(2, "logical expression", " ends\n");
665 }
666 
667 
668 /* This function returns:
669  *
670  * 1, if e is a relational expression that is always true
671  *
672  * -1, if e is a relational expression that is always false
673  *
674  * 0, otherwise.
675  *
676  * It should be called trivial_condition_p().
677  */
678 
680 {
682  {
683  /* If e is a relational expression*/
685  expression e1 = EXPRESSION(CAR(args));
686  expression e2 = EXPRESSION(CAR(CDR(args)));
687  normalized n1,n2;
688  entity op;
689  if (expression_undefined_p(e1) ||expression_undefined_p(e2) ) return 0;
690  n1 = NORMALIZE_EXPRESSION(e1);
691  n2 = NORMALIZE_EXPRESSION(e2);
693 
694  // FI: no cycle between the ri-util and prettyprint libraries
695  /* ifdebug(3) { */
696  /* fprintf(stderr, "Normalizes of expression:"); */
697  /* print_expression(e); */
698  /* print_normalized(n1); */
699  /* print_normalized(n2); */
700  /* } */
701 
703  {
704  Pvecteur v1 = normalized_linear(n1);
705  Pvecteur v2 = normalized_linear(n2);
706  Pvecteur v = vect_substract(v1,v2);
707 
708  /* The test if an expression is trivial (always true or false) or not
709  * depends on the operator of the expression :
710  * (op= {<=,<,>=,>,==,!=}) so we have to treat each different case */
711 
712  if (vect_constant_p(v))
713  {
714  if (ENTITY_NON_EQUAL_P(op))
715  {
716  /* Expression : v != 0 */
717  if (VECTEUR_NUL_P(v)) return -1;
718  if (value_zero_p(val_of(v))) return -1;
719  if (value_notzero_p(val_of(v))) return 1;
720  }
721  if (ENTITY_EQUAL_P(op))
722  {
723  /* Expression : v == 0 */
724  if (VECTEUR_NUL_P(v)) return 1;
725  if (value_zero_p(val_of(v))) return 1;
726  if (value_notzero_p(val_of(v))) return -1;
727  }
729  {
730  /* Expression : v >= 0 */
731  if (VECTEUR_NUL_P(v)) return 1;
732  if (value_posz_p(val_of(v))) return 1;
733  if (value_neg_p(val_of(v))) return -1;
734  }
735  if (ENTITY_LESS_OR_EQUAL_P(op))
736  {
737  /* Expression : v <= 0 */
738  if (VECTEUR_NUL_P(v)) return 1;
739  if (value_negz_p(val_of(v))) return 1;
740  if (value_pos_p(val_of(v))) return -1;
741  }
742  if (ENTITY_LESS_THAN_P(op))
743  {
744  /* Expression : v < 0 */
745  if (VECTEUR_NUL_P(v)) return -1;
746  if (value_neg_p(val_of(v))) return 1;
747  if (value_posz_p(val_of(v))) return -1;
748  }
749  if (ENTITY_GREATER_THAN_P(op))
750  {
751  /* Expression : v > 0 */
752  if (VECTEUR_NUL_P(v)) return -1;
753  if (value_pos_p(val_of(v))) return 1;
754  if (value_negz_p(val_of(v))) return -1;
755  }
756  }
757  return 0;
758  }
759  return 0;
760  }
761  return 0;
762 }
763 
764 
765 /* Test if an expression is a verbose reduction of the form :
766  "i = i op v" or "i = v op i"
767 
768  @param e is the expression to analyse
769 
770  @param filter is a function that take an expression and return true iff
771  expression is of the form "op(a,b,c...)". The filter may not be specific
772  to binary operators, even if this function only deal with binary
773  patterns. Use for example add_expression_p() to detect "i = i + v" or "i
774  = v + i".
775 
776  @return the v expression if e is of the requested form or
777  expression_undefined if not
778  */
781  bool filter(expression)) {
782  if (assignment_expression_p(incr)) {
783  /* The expression is an assignment, it is a good start. */
784  list assign_params = call_arguments(syntax_call(expression_syntax(incr)));
785  expression lhs = EXPRESSION(CAR(assign_params));
786 
787  /* Only deal with simple references right now: */
788  if (expression_reference_p(lhs)) {
789  expression rhs = EXPRESSION(CAR(CDR(assign_params)));
790  if (filter(rhs)) {
791  /* Operation found. */
793  /* Only deal with binary operators */
794  if (gen_length(op_params) == 2) {
795  expression arg1 = EXPRESSION(CAR(op_params));
796  expression arg2 = EXPRESSION(CAR(CDR(op_params)));
797  if (expression_reference_p(arg1)
799  expression_reference(arg1)))
800  /* If arg1 is the same reference as lhs,
801  we are in the "i = i op v" case: */
802  return arg2;
803  else if (expression_reference_p(arg2)
805  expression_reference(arg2)))
806  /* If arg2 is the same reference as lhs,
807  we are in the "i = v op i" case: */
808  return arg1;
809  }
810  }
811  }
812  }
813  return expression_undefined;
814 }
815 
816 
818 expression e ;
819 {
820  if (expression_call_p(e)) {
822  entity e = call_function(c);
823 
824  return(strcmp(entity_local_name(e), IMPLIED_DO_NAME) == 0);
825  }
826 
827  return(false);
828 }
829 
831 {
832  bool result = false;
833 
834  if (expression_call_p(e)) {
836  entity f = call_function(c);
837 
838  result = ENTITY_COMMA_P(f);
839  }
840 
841  return result;
842 }
843 
845 expression e ;
846 {
847  if (expression_call_p(e)) {
849  entity e = call_function(c);
850 
851  return(strcmp(entity_local_name(e), LIST_DIRECTED_FORMAT_NAME) == 0);
852  }
853 
854  return(false);
855 }
856 
857 /* More extensive than next function */
859 {
860  value v = EvalExpression(e);
861  bool ice_p = false;
862 
863  if(value_constant_p(v)) {
864  constant c = value_constant(v);
865 
866  ice_p = constant_int_p(c);
867  }
868  free_value(v);
869  return ice_p;
870 }
871 
872 // same as previous but also returns the integer constant in the integer
873 // pointed by parameter result if the expression is an integer constant
875 {
876  value v = EvalExpression(e);
877  bool ice_p = false;
878 
879  if(value_constant_p(v)) {
880  constant c = value_constant(v);
881 
882  ice_p = constant_int_p(c);
883  if (ice_p) *result = constant_int(c);
884  }
885  free_value(v);
886  return ice_p;
887 }
888 
889 
890 /* positive integer constant expression: call to a positive constant
891  or to a sum of positive integer constant expressions (much too
892  restrictive, but enough for the source codes submitted to PIPS up
893  to now).
894 
895  Likely to fail and need further extension if subtraction and
896  multiplication are used as probably allowed by C standard.
897 
898  NormalizeExpression() could be used instead, as it is in fact to compute
899  the value of the expression.
900 
901  Use previous function instead of this one, and -1 will be a constant...
902 */
904 expression e;
905 {
906  syntax s = expression_syntax(e);
907  bool ice = false;
908 
909  if(syntax_call_p(s)) {
910  call c = syntax_call(s);
911  entity cst = call_function(c);
912  list args = call_arguments(c);
913  int i;
914 
915  if(integer_constant_p(cst, &i)) {
916  ice = true;
917  }
918  else if(integer_symbolic_constant_p(cst, &i)) {
919  ice = true;
920  }
921  else if(ENTITY_PLUS_P(cst)||ENTITY_PLUS_C_P(cst)) {
922  expression e1 = EXPRESSION(CAR(args));
923  expression e2 = EXPRESSION(CAR(CDR(args)));
924 
926  }
927  }
928 
929  return ice;
930 }
931 
933 {
935  syntax s = expression_syntax(e);
936 
937  if(syntax_call_p(s)) {
938  call c = syntax_call(s);
939  entity um = call_function(c);
940 
943  entity_domain)) {
944  expression e2 = binary_call_lhs(c);
945 
947  }
948  }
949  return false;
950  }
951  else {
952  return true;
953  }
954 }
955 
956 /* The expression may be complicated but all its leaves are constants or
957  parameters. It evaluates to a signed integer constant. I am too lazy to
958  fully implement it as I should and I only take care of affine
959  expressions (Francois). */
961 expression e;
962 {
964  bool constant_p = false;
965 
966  if(normalized_linear_p(ne)) {
967  Pvecteur ve = normalized_linear(ne);
968  /* No vecteur_constant_p() in linear library? */
970  || (term_cst(ve) && VECTEUR_UNDEFINED_P(vecteur_succ(ve)));
971  }
972 
973  return constant_p;
974 }
975 
976 
977 /* Test if an expression is an assignment operation.
978  */
981 }
982 
983 
984 /* Test if an expression is an addition.
985  */
989  ;
990 }
994  ;
995 }
996 
997 
998 /* Test if an expression is an substraction.
999  */
1003 }
1004 
1005 
1007 expression e;
1008 {
1010 }
1011 
1013 expression e;
1014 {
1016 }
1017 
1019 expression e;
1020 {
1022 }
1023 
1025 expression e;
1026 {
1028 }
1029 
1031 expression e;
1032 {
1034 }
1035 
1037 expression e;
1038 {
1040 }
1041 
1043 expression e;
1044 {
1046 }
1047 
1049 expression e;
1050 {
1052 }
1053 
1055 expression e;
1056 {
1059 }
1060 
1062 expression e;
1063 {
1066 }
1067 
1069 expression e;
1070 {
1071  syntax s = expression_syntax(e);
1072  bool user_function_call_p = false;
1073 
1074  if(syntax_call_p(s)) {
1075  call c = syntax_call(s);
1076  entity f = call_function(c);
1077  value v = entity_initial(f);
1079  }
1080  else {
1081  user_function_call_p = false;
1082  }
1083 
1084  return user_function_call_p;
1085 }
1086 
1087 bool operator_expression_p(e, op_name)
1088 expression e;
1089 string op_name;
1090 {
1091  syntax s = expression_syntax(e);
1092 
1093  if(syntax_call_p(s)) {
1094  call c = syntax_call(s);
1095  entity op = call_function(c);
1096 
1097  return strcmp(op_name, entity_local_name(op)) == 0;
1098  }
1099  else
1100  return false;
1101 }
1102 
1104 {
1106 }
1107 
1109 {
1111 }
1112 
1114 {
1116 }
1117 
1119 {
1121 }
1122 
1123 /* bool unbounded_dimension_p(dim)
1124  * input : a dimension of an array entity.
1125  * output : true if the last dimension is unbounded (*),
1126  * false otherwise.
1127  * modifies : nothing
1128  * comment :
1129  */
1131 dimension dim;
1132 {
1133  syntax dim_synt = expression_syntax(dimension_upper(dim));
1134  bool res = false;
1135 
1136  if (syntax_call_p(dim_synt)) {
1137  const char* dim_nom = entity_local_name(call_function(syntax_call(dim_synt)));
1138 
1140  res = true;
1141  }
1142 
1143  return(res);
1144 }
1145 
1146 ␌
1148 {
1149  int i;
1150  pips_assert("find_ith_argument", n > 0);
1151 
1152  for(i=1; i<n && !ENDP(args); i++, POP(args))
1153  ;
1154  if(i==n && !ENDP(args))
1155  return EXPRESSION(CAR(args));
1156  else
1157  return expression_undefined;
1158 }
1159 
1160 /* find_ith_expression() is obsolet; use find_ith_argument() instead */
1162 {
1163  /* the first element is one */
1164  /* two local variables, useless but for debugging */
1165  list cle;
1166  int i;
1167 
1168  pips_assert("find_ith_expression", r > 0);
1169 
1170  for(i=r, cle=le ; i>1 && !ENDP(cle); i--, POP(cle))
1171  ;
1172 
1173  if(ENDP(cle))
1174  pips_internal_error("not enough elements in expresion list");
1175 
1176  return EXPRESSION(CAR(cle));
1177 }
1178 
1179 
1180 /* transform an int into an expression and generate the corresponding
1181  entity if necessary; it is not clear if strdup() is always/sometimes
1182  necessary and if a memory leak occurs; wait till syntax/expression.c
1183  is merged with ri-util/expression.c
1184 
1185  Negative constants do not seem to be included in PIPS internal
1186  representation.
1187  */
1189 {
1190  bool negative_p = i<0;
1191  /* special hook for VALUE_MIN:
1192  the problem is that VALUE_MIN cannot be represented in the IR because
1193  -VALUE_MIN does not fit into and _int, so we replace it by VALUE_MIN -1,
1194  which is still big ... */
1195  if(negative_p)
1196  while(i==-i) { // ie while we have an integer overflow
1197  ++i;
1198  }
1199  // it is unclear whether to call abs/labs/llabs...
1200  entity e = int_to_entity(negative_p? -i: i);
1202  if(negative_p)
1204  return exp;
1205 }
1206 
1207 /* Make a zero expression.
1208  *
1209  * It is useful compared to int_to_expression(0) because it is much
1210  * easier to search in source text.
1211  */
1213 {
1214  return int_to_expression(0);
1215 }
1216 
1218 {
1219  bool zero_p = false;
1220  if(expression_call_p(e)) {
1221  call c = expression_call(e);
1222  entity f = call_function(c);
1223  if(f==int_to_entity(0))
1224  zero_p = true;
1225  }
1226  return zero_p;
1227 }
1228 
1230 {
1231  entity e = float_to_entity(c);
1232  return call_to_expression(make_call(e,NIL));
1233 }
1235 {
1237 }
1239 {
1240  return MakeNullaryCall
1242  is_basic_logical));
1243 }
1244 
1245 /* added interface for linear stuff.
1246  * it is not ok if Value is not an int, but if Value is changed
1247  * sometime, I guess code that use this function will not need
1248  * any change.
1249  * FC.
1250  */
1252 {
1253  return(int_to_expression(VALUE_TO_INT(v)));
1254 }
1255 ␌
1256 /* conversion of an expression into a list of references; references are
1257  appended to list lr as they are encountered; array references are
1258  added before their index expressions are scanned;
1259 
1260  references to functions and constants (which are encoded as null-ary
1261  functions) are not recorded
1262 */
1264 {
1265  syntax s = expression_syntax(e);
1266  lr = syntax_to_reference_list(s, lr);
1267  return lr;
1268 }
1269 
1271 {
1272  switch(syntax_tag(s)) {
1273  case is_syntax_reference:
1274  lr = gen_nconc(lr, CONS(REFERENCE, syntax_reference(s), NIL));
1275  MAPL(ce, {
1276  expression e = EXPRESSION(CAR(ce));
1277  lr = expression_to_reference_list(e, lr);
1278  },
1280  break;
1281  case is_syntax_range:
1285  lr);
1286  break;
1287  case is_syntax_call:
1288  MAPL(ce, {
1289  expression e = EXPRESSION(CAR(ce));
1290  lr = expression_to_reference_list(e, lr);
1291  },
1293  break;
1294  case is_syntax_cast: {
1295  cast c = syntax_cast(s);
1296  expression e = cast_expression(c);
1297  lr = expression_to_reference_list(e, lr);
1298  break;
1299  }
1304  lr = expression_to_reference_list(e, lr);
1305  }
1306  break;
1307  }
1308  case is_syntax_subscript: {
1309  subscript sub = syntax_subscript(s);
1310  expression e = subscript_array(sub);
1311  list il = subscript_indices(sub);
1312  lr = expression_to_reference_list(e, lr);
1313  FOREACH(EXPRESSION, i,il) {
1314  lr = expression_to_reference_list(i, lr);
1315  }
1316  break;
1317  }
1318  case is_syntax_application: {
1321  list al = application_arguments(app);
1322  lr = expression_to_reference_list(f, lr);
1323  FOREACH(EXPRESSION, a,al) {
1324  lr = expression_to_reference_list(a, lr);
1325  }
1326  break;
1327  }
1328  case is_syntax_va_arg: {
1329  list two = syntax_va_arg(s);
1330  FOREACH(SIZEOFEXPRESSION, soe, two) {
1333  lr = expression_to_reference_list(e, lr);
1334  }
1335  }
1336  break;
1337  }
1338  default:
1339  pips_internal_error("illegal tag %d",
1340  syntax_tag(s));
1341 
1342  }
1343  return lr;
1344 }
1345 
1346 /* Syntactic equality e1==e2 */
1348 {
1349  syntax s1, s2;
1350 
1351  /* Add expression_undefined tests to avoid segmentation fault */
1352 
1354  return true;
1356  return false;
1357 
1358  /* let's assume that every expression has a correct syntax component */
1359  s1 = expression_syntax(e1);
1360  s2 = expression_syntax(e2);
1361 
1362  return syntax_equal_p(s1, s2);
1363 }
1364 
1365 /* e1==e2 or -e1==e2 or e1==-e2 syntactically */
1367 {
1368  bool equal_or_opposite_p = false;
1369  if(expression_equal_p(e1,e2)) {
1370  equal_or_opposite_p = true;
1371  }
1373  call c1 = expression_call(e1);
1375  equal_or_opposite_p = expression_equal_p(e11, e2);
1376  }
1378  call c2 = expression_call(e2);
1380  equal_or_opposite_p = expression_equal_p(e1, e22);
1381  }
1382  return equal_or_opposite_p;
1383 }
1384 
1385 /* e1+e2==0, i.e. -e1==e2 or e1==-e2 syntactically */
1387 {
1388  bool opposite_p = false;
1389 
1390  if(unary_minus_expression_p(e1)) {
1391  call c1 = expression_call(e1);
1393  opposite_p = expression_equal_p(e11, e2);
1394  }
1395  else if(unary_minus_expression_p(e2)) {
1396  call c2 = expression_call(e2);
1398  opposite_p = expression_equal_p(e1, e22);
1399  }
1400  return opposite_p;
1401 }
1402 
1403 // FI: renamed because of gcc
1404 //bool expressions_equal_p(list l1, list l2)
1406 {
1407  bool equal_p = true;
1408  list cl1 = l1, cl2 = l2;
1409  while(!ENDP(cl1) && !ENDP(cl2)) {
1410  expression e1 = EXPRESSION(CAR(cl1));
1411  expression e2 = EXPRESSION(CAR(cl2));
1412  if(!expression_equal_p(e1, e2)) {
1413  equal_p = false;
1414  break;
1415  }
1416  POP(cl1), POP(cl2);
1417  }
1418  if(equal_p)
1419  equal_p = ENDP(cl1) && ENDP(cl2);
1420  return equal_p;
1421 }
1422 
1423 /* this is slightly different from expression_equal_p, as it will return true for
1424  * a+b vs b+a
1425  */
1427 {
1428 
1429  /* lazy normalization.
1430  */
1433 
1434  normalized n1, n2;
1435  n1 = expression_normalized(e1);
1436  n2 = expression_normalized(e2);
1437 
1438 
1439 
1442  else
1443  return expression_equal_p(e1, e2);
1444 }
1445 
1447 {
1452  return false;
1453 }
1454 
1455 bool cast_equal_p(cast c1, cast c2)
1456 {
1457  return
1458  type_equal_p(cast_type(c1), cast_type(c2)) &&
1460 }
1461 
1463 {
1464  tag t1 = syntax_tag(s1);
1465  tag t2 = syntax_tag(s2);
1466 
1467  if(t1!=t2)
1468  return false;
1469 
1470  switch(t1) {
1471  case is_syntax_reference:
1473  case is_syntax_range:
1474  return range_equal_p(syntax_range(s1), syntax_range(s2));
1475  case is_syntax_call:
1476  return call_equal_p(syntax_call(s1), syntax_call(s2));
1477  case is_syntax_cast:
1478  return cast_equal_p(syntax_cast(s1), syntax_cast(s2));
1481  case is_syntax_subscript:
1483  case is_syntax_application:
1484  case is_syntax_va_arg:
1485  pips_internal_error("Not implemented for syntax tag %d\n", t1);
1486  default:
1487  return false;
1488  break;
1489  }
1490 
1491  pips_internal_error("illegal. syntax tag %d", t1);
1492  return false;
1493 }
1494 
1498 }
1499 
1501 {
1502  entity v1 = reference_variable(r1);
1503  entity v2 = reference_variable(r2);
1504 
1505  list dims1 = reference_indices(r1);
1506  list dims2 = reference_indices(r2);
1507 
1508  if(v1 != v2) {
1509  if(entity_field_p(v1) && entity_field_p(v2)) {
1510  // FI: because of separate compilation, the same field is
1511  // represented by different entities
1512  return same_field_entity_p(v1, v2);
1513  }
1514  else
1515  return false;
1516  }
1517 
1518  return gen_equals(dims1,dims2,(gen_eq_func_t)expression_equal_p);
1519 }
1520 
1521 
1523 {
1524  return expression_equal_p(range_lower(r1), range_lower(r2))
1527 }
1528 
1529 bool call_equal_p(call c1, call c2)
1530 {
1531  entity f1 = call_function(c1);
1532  entity f2 = call_function(c2);
1533  list args1 = call_arguments(c1);
1534  list args2 = call_arguments(c2);
1535 
1536  if(f1 != f2)
1537  return false;
1538 
1539  return gen_equals(args1,args2,(gen_eq_func_t)expression_equal_p);
1540 
1541  return true;
1542 }
1543 ␌
1544 
1546 {
1547  pips_assert("is constant", integer_constant_expression_p(e));
1549 }
1550 
1552 {
1553  /* could be coded by geting directly the value of the constant entity... */
1554  /* also available as integer_constant_p() which has *two* arguments */
1555 
1557  int val = 0;
1558 
1559  pips_assert("is signed constant", signed_integer_constant_expression_p(e));
1560 
1561  n = NORMALIZE_EXPRESSION(e);
1562  if(normalized_linear_p(n)) {
1564 
1565  if(vect_constant_p(v)) {
1566  Value x = vect_coeff(TCST, v);
1567  val = VALUE_TO_INT(x);
1568  }
1569  else
1570  pips_internal_error("non constant expression");
1571  }
1572  else
1573  pips_internal_error("non affine expression");
1574 
1575  return val;
1576 }
1577 
1578 
1580 {
1581  expression new_exp = expression_undefined;
1582  if (lang == is_language_c)
1583  {
1585  copy_expression(e1),
1586  copy_expression(e2));
1588  comp_exp,
1589  e2,
1590  e1);
1591  }
1592  else
1593  {
1595  e1,e2);
1596  }
1597  return new_exp;
1598 }
1599 
1601 {
1602  expression new_exp = expression_undefined;
1603  if (lang == is_language_c)
1604  {
1606  copy_expression(e1),
1607  copy_expression(e2));
1609  comp_exp,
1610  e1,
1611  e2);
1612  }
1613  else
1614  {
1616  e1,e2);
1617  }
1618  return new_exp;
1619 }
1620 
1621 
1622 
1623 
1624 /* Some functions to generate expressions from vectors and constraint
1625  systems. */
1626 
1627 
1628 /* expression make_factor_expression(int coeff, entity vari)
1629  * make the expression "coeff*vari" where vari is an entity.
1630  */
1632 {
1633  expression e1, e2, e3;
1634 
1635  e1 = int_to_expression(coeff);
1636  if (vari==NULL)
1637  return(e1); /* a constant only */
1638  else {
1639  e2 = entity_to_expression(vari);
1640  if (coeff == 1) return(e2);
1641  else {
1643  return (e3);
1644  }
1645  }
1646 }
1647 
1648 /* make expression for vector (Pvecteur)
1649  */
1651 {
1652  /* sort: to insure a deterministic generation of the expression.
1653  * note: the initial system is *NOT* touched.
1654  * ??? Sometimes the vectors are shared, so you cant modify them
1655  * that easily. Many cores in Hpfc (deducables), Wp65, and so.
1656  * ok, I'm responsible for some of them:-)
1657  *
1658  * (c) FC 24/11/94
1659  * SG: added support for generation of C operator when needed
1660  */
1661  Pvecteur
1662  v_sorted = vect_sort(pv, compare_Pvecteur),
1663  v = v_sorted;
1664  expression factor1, factor2;
1665  entity op_add, op_sub,
1666  c_op_add, c_op_sub;
1667  int coef;
1668 
1673 
1674  if (VECTEUR_NUL_P(v))
1675  return int_to_expression(0);
1676 
1677  coef = VALUE_TO_INT(vecteur_val(v));
1678 
1679  entity var = (entity) vecteur_var(v);
1680  bool next_op_is_c = var !=TCST && entity_pointer_p(var);
1681  if (coef==-1) /* let us avoid -1*var, we prefer -var */
1682  {
1684  factor1 = make_factor_expression(1, (entity) vecteur_var(v));
1685  factor1 = call_to_expression
1686  (make_call(op_ums, CONS(EXPRESSION, factor1, NIL)));
1687  }
1688  else
1689  factor1 = make_factor_expression(coef, (entity) vecteur_var(v));
1690 
1691  for (v=v->succ; v!=NULL; v=v->succ)
1692  {
1693  var = (entity) vecteur_var(v);
1694  coef = VALUE_TO_INT(vecteur_val(v));
1695  pips_assert("some coefficient", coef!=0);
1696  factor2 = make_factor_expression(ABS(coef), var);
1697  /* choose among C or fortran operator depending on the entity type
1698  * this limits the use of +C and -C to pointer arithmetic
1699  */
1700  entity op =
1701  ( next_op_is_c ) ?
1702  ( coef> 0 ? c_op_add : c_op_sub ) :
1703  ( coef> 0 ? op_add : op_sub ) ;
1704  factor1 = MakeBinaryCall(op,factor1,factor2);
1705  next_op_is_c = var !=TCST && entity_pointer_p(var);
1706  }
1707 
1708  vect_rm(v_sorted);
1709 
1710  return factor1;
1711 }
1712 
1713 /* generates var = linear expression from the Pvecteur.
1714 
1715  var is removed if necessary.
1716 
1717  ??? should manage an (positive remainder) integer divide ? Have a look
1718  to make_constraint_expression instead?
1719  */
1721  Pvecteur v)
1722 {
1723  statement result;
1724  Pvecteur vcopy;
1725  Value coef;
1726 
1727  coef = vect_coeff((Variable) var, v);
1729 
1730  vcopy = vect_dup(v);
1731 
1732  if (value_notzero_p(coef)) vect_erase_var(&vcopy, (Variable) var);
1733  if (value_one_p(coef)) vect_chg_sgn(vcopy);
1734 
1736  make_vecteur_expression(vcopy));
1737  vect_rm(vcopy);
1738 
1739  return result;
1740 }
1741 
1742 
1743 /* Make an expression from a constraint v for a given index.
1744 
1745  For example: for a constraint of index I : aI + linear_expr(J,K,TCST) <=0
1746  @return the new expression for I that is -expr_linear(J,K,TCST)/a
1747  */
1749 {
1750  Pvecteur pv;
1751  expression ex1, ex2, ex;
1752  entity div;
1753  Value coeff;
1754 
1755  /*search the couple (var,val) where var is equal to index and extract it */
1756  pv = vect_dup(v);
1757  coeff = vect_coeff(index, pv);
1758  vect_erase_var(&pv, index);
1759 
1760  if (VECTEUR_NUL_P(pv))
1761  /* If the vector wihout the index is the vector null, we have simply
1762  index = 0: */
1763  return int_to_expression(0);
1764 
1765  /* If the coefficient for the index is positive, inverse all the
1766  vector since the index goes at the other side of "=": */
1767  if (value_pos_p(coeff))
1768  vect_chg_sgn(pv);
1769  else {
1770  /* If coeff is negative, correct the future division rounding (by
1771  -coeff) by adding (coeff - 1) to the vector first: */
1772  value_absolute(coeff);
1773  vect_add_elem(&pv, TCST, value_minus(coeff, VALUE_ONE));
1774  }
1775 
1776  if(vect_size(pv) == 1 && vecteur_var(pv) == TCST) {
1777  /* If the vector is simply coeff.index=c, directly generate and
1778  return c/coeff: */
1779  vecteur_val(pv) = value_pdiv(vecteur_val(pv), coeff);
1780  return make_vecteur_expression(pv);
1781  }
1782 
1783  /* Generate an expression from the linear vector: */
1784  ex1 = make_vecteur_expression(pv);
1785 
1786  if (value_gt(coeff, VALUE_ONE)) {
1787  /* If coeff > 1, divide all the expression by coeff: */
1788  /* FI->YY: before generating a division, you should test if it could
1789  not be performed statically; you have to check if ex1 is not a
1790  constant expression, which is fairly easy since you still have
1791  its linear form, pv */
1792  /* build expressions for the lower and upper bounds */
1793  if( c_language_module_p(get_current_module_entity()) && !get_bool_property("PRETTYPRINT_DIV_INTRINSICS"))
1795  else // Fortran case and C intrinsics requested
1796  div = gen_find_tabulated("TOP-LEVEL:/",entity_domain);
1797  pips_assert("Division operator not found", div != entity_undefined);
1798 
1799  ex2 = int_to_expression(VALUE_TO_INT(coeff));
1801  make_call(div,
1802  CONS(EXPRESSION,ex1,
1803  CONS(EXPRESSION,
1804  ex2,NIL)))),
1806  return(ex);
1807  }
1808  else
1809  return(ex1);
1810 }
1811 
1812 
1813 /* A wrapper around make_constraint_expression() for compatibility.
1814  */
1816  /* Simply call the function on the vector in the constrain system: */
1817  return make_constraint_expression(pc->vecteur, index);
1818 }
1819 
1820 
1821 /* AP, sep 25th 95 : some usefull functions moved from
1822  static_controlize/utils.c */
1823 
1824 /* rather use make_vecteur_expression which was already there */
1826 {
1827  return make_vecteur_expression(vect);
1828 }
1829 
1830 
1831 /* Short cut, meaningful only if expression_reference_p(e) holds. */
1833 {
1834  pips_assert("e is a reference\n",expression_reference_p(e));
1836 }
1837 
1840 }
1841 
1842 
1844 {
1845  pips_assert("is a subscript\n",expression_subscript_p(e));
1847 }
1849 {
1850  return syntax_range_p(expression_syntax(e));
1851 }
1852 
1854 {
1855  pips_assert("is a range", expression_range_p(e));
1856  return syntax_range(expression_syntax(e));
1857 }
1858 ␌
1859 /* predicates on references */
1860 
1862 {
1863  /* two possible meanings:
1864  * - the referenced variable is declared as an array
1865  * - the reference is to an array element
1866  *
1867  * This makes a difference in procedure calls and IO statements
1868  *
1869  * The second interpretation is chosen.
1870  */
1871 
1872  return reference_indices(r) != NIL;
1873 }
1874 
1875 /* If true is returned, the two references cannot conflict unless array
1876  * bound declarations are violated. If false is returned, the two references
1877  * may conflict.
1878  *
1879  * true is returned if the two references are array references and if
1880  * the two references entities are equal and if at least one dimension
1881  * can be used to desambiguate the two references using constant subscript
1882  * expressions. This test is store independent and certainly does not
1883  * replace a dependence test. It may beused to compute ude-def chains.
1884  *
1885  * If needed, an extra effort could be made for aliased arrays.
1886  */
1887 
1889 {
1890  bool do_not_conflict = false;
1891  entity v1 = reference_variable(r1);
1892  entity v2 = reference_variable(r2);
1893 
1894  if(v1==v2) {
1895  list s1 = reference_indices(r1);
1896  list s2 = reference_indices(r2);
1897  if(!ENDP(s1) && gen_length(s1)==gen_length(s2)) {
1898  list cs1, cs2;
1899  for(cs1=s1, cs2=s2; !ENDP(cs1) && !do_not_conflict; POP(cs1), POP(cs2)) {
1900  expression sub1 = EXPRESSION(CAR(cs1));
1901  expression sub2 = EXPRESSION(CAR(cs2));
1902  if(expression_constant_p(sub1) && expression_constant_p(sub2)) {
1903  /* FI: OK, it would be better to use their normalized forms */
1904  do_not_conflict = (expression_to_int(sub1)!=expression_to_int(sub2));
1905  }
1906  }
1907  }
1908  }
1909 
1910  return do_not_conflict;
1911 }
1912 
1913 /*
1914  * Utils from hpfc on 15 May 94, FC
1915  *
1916  */
1918 {
1919  int
1920  len = gen_length(l);
1921  expression
1922  result = expression_undefined;
1923 
1924  pips_assert("list_to_binary_operator_call", len!=0);
1925 
1926  result = EXPRESSION(CAR(l));
1927 
1928  MAPL(ce,
1929  {
1930  result = MakeBinaryCall(op, EXPRESSION(CAR(ce)), result);
1931  },
1932  CDR(l));
1933 
1934  return(result);
1935 }
1936 
1938 {
1939  int len = gen_length(l);
1941  return(len==0?
1942  MakeNullaryCall(entity_intrinsic(".TRUE.")):
1944 }
1945 
1946 /* bool expression_intrinsic_operation_p(expression exp): Returns true
1947  * if "exp" is an expression with a call to an intrinsic operation.
1948  */
1950 {
1951  entity e;
1952  syntax syn = expression_syntax(exp);
1953 
1954  if (syntax_tag(syn) != is_syntax_call)
1955  return (false);
1956 
1957  e = call_function(syntax_call(syn));
1958 
1960 }
1961 
1962 /* bool call_constant_p(call c): Returns true if "c" is a call to a constant,
1963  * that is, a constant number or a symbolic constant.
1964  */
1966 {
1968  return( (value_tag(cv) == is_value_constant) ||
1969  (value_tag(cv) == is_value_symbolic) );
1970 }
1971 
1972 
1973 /*=================================================================*/
1974 /* bool expression_equal_integer_p(expression exp, int i): returns true if
1975  * "exp" is a constant value equal to "i".
1976  */
1978 {
1979  pips_debug(7, "doing\n");
1981  return(expression_to_int(exp) == i);
1982  return(false);
1983 }
1984 
1985 /*=================================================================*/
1986 /* expression make_op_exp(char *op_name, expression exp1 exp2):
1987  * Returns an expression containing the operation "op_name" between "exp1" and
1988  * "exp2".
1989  * "op_name" must be one of the four classic operations : +, -, * or /.
1990  *
1991  * If both expressions are integer constant values and the operation
1992  * result is an integer then the returned expression contained the
1993  * calculated result.
1994  *
1995  * Else, we treat five special cases :
1996  * _ exp1 and exp2 are integer linear and op_name is + or -.
1997  * This case is resolved by make_lin_op_exp().
1998  * _ exp1 = 0
1999  * _ exp1 = 1
2000  * _ exp2 = 0
2001  * _ exp2 = 1
2002  *
2003  * Else, we create a new expression with a binary call.
2004  *
2005  * Note: The function MakeBinaryCall() comes from Pips/.../syntax/expression.c
2006  * The function int_to_expression() comes from ri-util.
2007  *
2008  * Warning: using the same semantic as MakeBinaryCall,
2009  * make_op_exp owns the pointer exp1 and exp2 after the call,
2010  * beware of not sharing them !
2011  */
2012 expression make_op_exp(char *op_name, expression exp1, expression exp2)
2013 {
2014  expression result_exp = expression_undefined;
2015  entity op_ent, unary_minus_ent;
2016 
2017  debug( 7, "make_op_exp", "doing\n");
2019  op_name), entity_domain);
2020  unary_minus_ent =
2023  entity_domain);
2024 
2025  // FI: to avoid cycle between the ri and prettyprint libraries
2026  /* pips_debug(5, "begin OP EXP : %s %s %s\n", */
2027  /* words_to_string(words_expression(exp1, NIL)), */
2028  /* op_name, */
2029  /* words_to_string(words_expression(exp2, NIL))); */
2030 
2031  if( ! ENTITY_FIVE_OPERATION_P(op_ent) )
2032  user_error("make_op_exp", "operation must be : +, -, *, MOD, or /");
2033 
2034  intptr_t val1, val2;
2035  if( expression_integer_value(exp1,&val1) && expression_integer_value(exp2,&val2) )
2036  {
2037 
2038  debug(6, "make_op_exp", "Constant expressions\n");
2039 
2040  if (ENTITY_PLUS_P(op_ent))
2041  result_exp = int_to_expression(val1 + val2);
2042  else if(ENTITY_MINUS_P(op_ent))
2043  result_exp = int_to_expression(val1 - val2);
2044  else if(ENTITY_MULTIPLY_P(op_ent))
2045  result_exp = int_to_expression(val1 * val2);
2046  else if(ENTITY_MODULO_P(op_ent))
2047  result_exp = int_to_expression(val1 % val2);
2048  else /* ENTITY_DIVIDE_P(op_ent) */
2049  /* we compute here as FORTRAN would do */
2050  result_exp = int_to_expression((int) (val1 / val2));
2051  free_expression(exp1);
2052  free_expression(exp2);
2053  }
2054  else
2055  {
2056  /* We need to know the integer linearity of both expressions. */
2057  normalized nor1 = NORMALIZE_EXPRESSION(exp1);
2058  normalized nor2 = NORMALIZE_EXPRESSION(exp2);
2059 
2060  /* dividing by one or minus one is similar to multiplying */
2061  _int val;
2062  if(( ENTITY_DIVIDE_P(op_ent) || ENTITY_MULTIPLY_P(op_ent))
2063  && expression_integer_value(exp2,&val)
2064  && ( val == -1) ) {
2065  free_expression(exp2);
2067  }
2068 
2069  if((normalized_linear_p(nor1) && normalized_linear_p(nor2) ) &&
2070  (ENTITY_PLUS_P(op_ent) || ENTITY_MINUS_P(op_ent) ) )
2071  {
2072  pips_debug(6, "Linear operation\n");
2073 
2074  result_exp = make_lin_op_exp(op_ent, copy_expression(exp1), copy_expression(exp2));
2075  }
2076  else if(expression_equal_integer_p(exp1, 0))
2077  {
2078  if (ENTITY_PLUS_P(op_ent)) {
2079  result_exp = exp2;
2080  free_expression(exp1);
2081  }
2082  else if(ENTITY_MINUS_P(op_ent)) {
2083  result_exp = MakeUnaryCall(unary_minus_ent, exp2);
2084  free_expression(exp1);
2085  }
2086  else /* ENTITY_MULTIPLY_P(op_ent) || ENTITY_DIVIDE_P(op_ent) */ {
2087  result_exp = int_to_expression(0);
2088  free_expression(exp1);free_expression(exp2);
2089  }
2090  }
2091  else if(expression_equal_integer_p(exp1, 1))
2092  {
2093  if(ENTITY_MULTIPLY_P(op_ent)) {
2094  result_exp = exp2;
2095  free_expression(exp1);
2096  }
2097  }
2098  else if(expression_equal_integer_p(exp2, 0))
2099  {
2100  free_expression(exp2);
2101  if (ENTITY_PLUS_P(op_ent) || ENTITY_MINUS_P(op_ent))
2102  result_exp = exp1;
2103  else if (ENTITY_MULTIPLY_P(op_ent)) {
2104  result_exp = int_to_expression(0);
2105  free_expression(exp1);
2106  }
2107  else /* ENTITY_DIVIDE_P(op_ent) */
2108  user_error("make_op_exp", "division by zero");
2109  }
2110  else if(expression_equal_integer_p(exp2, 1))
2111  {
2112  if(ENTITY_MULTIPLY_P(op_ent) || ENTITY_DIVIDE_P(op_ent)) {
2113  result_exp = exp1;
2114  free_expression(exp2);
2115  }
2116  }
2117  }
2118 
2119  if(result_exp == expression_undefined)
2120  result_exp = MakeBinaryCall(op_ent, exp1, exp2);
2121 
2122  // FI: to avoid cycle between the ri and prettyprint libraries
2123  /* pips_debug(5, "end OP EXP : %s\n", */
2124  /* words_to_string(words_expression(result_exp, NIL))); */
2125 
2126  return (result_exp);
2127 }
2128 
2129 /// @return a new expression that adds the an expression with an integer
2130 /// @param e, the expression to add
2131 /// @param n, the integer to add
2134 }
2135 
2136 /*=================================================================*/
2137 /* expression make_lin_op_exp(entity op_ent, expression exp1 exp2): returns
2138  * the expression resulting of the linear operation (ie. + or -) "op_ent"
2139  * between two integer linear expressions "exp1" and "exp2".
2140  *
2141  * This function uses the linear library for manipulating Pvecteurs.
2142  * exp1 and exp2 are freed
2143  *
2144  * Pvecteur_to_expression() is a function that rebuilds an expression
2145  * from a Pvecteur.
2146  */
2148 {
2149  Pvecteur V1, V2, newV = VECTEUR_NUL;
2150 
2151  debug( 7, "make_lin_op_exp", "doing\n");
2154  pips_internal_error( "expressions MUST be linear and normalized");
2155 
2158 
2159  if (ENTITY_PLUS_P(op_ent))
2160  newV = vect_add(V1, V2);
2161  else if (ENTITY_MINUS_P(op_ent))
2162  newV = vect_substract(V1, V2);
2163  else
2164  pips_internal_error("operation must be : + or -");
2165  free_expression(exp1);
2166  free_expression(exp2);
2167 
2168  return(Pvecteur_to_expression(newV));
2169 }
2170 
2171 
2172 /*=================================================================*/
2173 /* int expression_to_int(expression exp): returns the integer value of
2174  * "exp" when "exp" is programming language constant or a Fortran
2175  * symbolic constant.
2176  *
2177  * Note: "exp" is supposed to contain an integer value which means that the
2178  * function expression_constant_p() has returned true with "exp" as
2179  * argument.
2180  *
2181  * This implies that if "exp" is not a "value_constant", it must be
2182  * a "value_intrinsic". In that case it is an unary minus operation
2183  * upon an expression for which the function expression_constant_p()
2184  * returns true (see its comment).
2185  *
2186  * SG: improvement: the integer value of a
2187  * extended_integer_constant_expression_p is computed too, for
2188  * instance 0+5 or 6+3.
2189  *
2190  * FI: I am not sure it is an improvement, at best it is an extension;
2191  * it looks more like a change of semantics (see above comments and
2192  * expression_constant_p()); other functions exist to evaluate a
2193  * constant expression... The extension should be useless as this
2194  * function should not be called unless guarded by a test with
2195  * expression_constant_p()... The same is true for the extension
2196  * related to symbolic constants.
2197  *
2198  * For an extended static expression evaluation, see
2199  * EvalExpression(). See also extended_expression_constant_p() for
2200  * more comments about what is called a "constant" expression.
2201  *
2202  * For a cleaner implementation of this function, as it was originally
2203  * intended, see below expression_to_float().
2204  */
2206 {
2207  int rv = 0;
2208  pips_debug(7, "doing\n");
2209 
2210  /* use the normalize field first: this is Serge Guelton's improvement... */
2211  /* Not good for user source code preservation... */
2214  if(normalized_linear_p(n)) {
2215  Pvecteur pv = normalized_linear(n);
2216  if(vect_constant_p(pv))
2217  return (int)vect_coeff(TCST, pv);
2218  }
2219 
2220  /* This is the initial code */
2221  if(expression_constant_p(exp)) {
2223  if(syntax_call_p(s)) { // A nullary call is assumed
2224  call c = syntax_call(s);
2225  switch(value_tag(entity_initial(call_function(c)))) {
2226  case is_value_constant: {
2228  break;
2229  }
2230  case is_value_intrinsic: {
2231  entity op = call_function(c);
2232  if(ENTITY_UNARY_MINUS_P(op))
2233  rv = 0 - expression_to_int(binary_call_lhs(c));
2234  else if(ENTITY_UNARY_PLUS_P(op))
2236  else
2237  pips_internal_error("Unexpected intrinsic \"%s\"\n",
2238  entity_local_name(op));
2239  break;
2240  }
2241  default:
2242  /* pips_internal_error("expression %s is not an integer constant.\n", */
2243  /* expression_to_string(exp)); */
2244  pips_internal_error("expression is not an integer constant.\n");
2245  }
2246  }
2247  else if(false && syntax_sizeofexpression(s)) {
2249  // FI: do we want to guard this evaluation with EVAL_SIZEOF?
2250  // This should be part of eval.c
2251  value v = EvalSizeofexpression(soe);
2252  if(value_constant_p(v)) { // Should always be true... but for dependent types
2253  rv = constant_int(value_constant(v));
2254  }
2255  else {
2256  /* Could be improved checking dependent and not dependent types...*/
2257  // FI: to avoid cycles between librairies ri-util and prettyprint
2258  /* pips_internal_error("expression %s is not an integer constant\n", */
2259  /* expression_to_string(exp)); */
2260  pips_internal_error("expression is not an integer constant.\n");
2261  }
2262  free_value(v);
2263  }
2264  }
2265  /* This is another useless extension */
2266  else if(expression_call_p(exp)) {
2267  /* Is it an integer "parameter" in Fortran, that is symbolic constants?
2268  *
2269  * Should this be generalized to C const qualified variables?
2270  *
2271  * I have doubt about this piece of code since the call is
2272  * supposedly guarded by expression_constant_p()
2273  */
2275  value v = entity_initial(p);
2276 
2279  }
2280  else {
2281  // FI: to avoid cycles between librairies ri-util and prettyprint
2282  /* pips_internal_error("expression %s is not an integer constant\n", */
2283  /* expression_to_string(exp)); */
2284  pips_internal_error("expression is not an integer constant\n");
2285  }
2286  }
2287  else {
2288  // FI: to avoid cycles between librairies ri-util and prettyprint
2289  /* pips_internal_error("expression %s is not an integer constant" */
2290  /* " in the sense of expression_constant_p()\n", */
2291  /* expression_to_string(exp)); */
2292  pips_internal_error("expression is not an integer constant"
2293  " in the sense of expression_constant_p()\n");
2294  }
2295 
2296  return(rv);
2297 }
2298 
2299 
2300 
2301 /* Same as above for floating point constants
2302  *
2303  * Its calls must be guarded by expression_constant_p()
2304  */
2306 {
2307  float rv = 0;
2308 
2309  pips_debug( 7, "doing\n");
2310  if(expression_constant_p(exp)) {
2312  switch(value_tag(entity_initial(call_function(c)))) {
2313  case is_value_constant: {
2314  rv = atof(entity_user_name(call_function(c)));
2315  break;
2316  }
2317  case is_value_intrinsic: {
2318  entity op = call_function(c);
2319  if(ENTITY_UNARY_MINUS_P(op))
2320  rv = 0 - expression_to_float(binary_call_lhs(c));
2321  else if(ENTITY_UNARY_PLUS_P(op))
2323  else
2324  pips_internal_error("Unexpected intrinsic \"%s\"\n",
2325  entity_local_name(op));
2326  break;
2327  }
2328  default:
2329  pips_internal_error("expression is not a constant"
2330  " according to expression_constant_p()");
2331  }
2332  }
2333  else
2334  pips_internal_error("expression is not a constant"
2335  " according to expression_constant_p()");
2336  return(rv);
2337 }
2338 
2339 /* This function returns a "constant" object if the expression is a
2340  * constant such as 10, -11 or 2.345 or "foo".
2341  *
2342  * Expressions such as "5+0" or "sizeof(int)" or "m", with m defined
2343  * as "const int m = 2;" or "M" with M defined as PARAMETER do not
2344  * qualify. However their value is constant, i.e. store independent,
2345  * and can be evaluated using EvalExpression().
2346  */
2348 {
2350  if(syntax_call_p(s))
2351  {
2354  switch(value_tag(v))
2355  {
2356  case is_value_constant:
2357  return value_constant(v);
2358  case is_value_intrinsic: {
2359  entity op = call_function(c);
2362  }
2363  default:
2364  ;
2365  }
2366  }
2367  else if(false && syntax_sizeofexpression_p(s)) {
2369  /* FI: difficult to make a decision here. We may have a constant
2370  expression that cannot be evaluated as a constant statically by
2371  PIPS. What is the semantics of expression_constant_p()? */
2372  if(sizeofexpression_type_p(soe) /* && get_bool_property("EVAL_SIZEOF")*/ ) {
2373  /* Too bad we need a function located in eval.c ... */
2374  value v = EvalSizeofexpression(soe);
2375  if(value_constant_p(v)) { // Should always be true...
2376  constant c = value_constant(v);
2378  free_value(v);
2379  return c;
2380  }
2381  }
2382  }
2383  else if(false && syntax_reference_p(s)) {
2384  /* Might be a reference to a scalar constant. */
2385  reference r = syntax_reference(s);
2386  entity v = reference_variable(r);
2387  if(const_variable_p(v)) {
2388  value val = entity_initial(v);
2389  if(value_constant_p(val)) {
2391  return c;
2392  }
2393  }
2394  }
2395  return constant_undefined;
2396 }
2397 
2399  bool constant_p = false;
2401  call c = expression_call(exp);
2402  entity operator = call_function(c);
2404  }
2405  return constant_p;
2406 }
2407 
2408 /* returns a newly allocated string! */
2410  pips_assert("is a string constant", expression_string_constant_p(exp));
2411  call c = expression_call(exp);
2412  entity operator = call_function(c);
2413  const char * eun = entity_user_name(operator);
2414  return strndup(eun+1,strlen(eun)-2);
2415 }
2416 
2418 expression e;
2419 {
2420  syntax s = expression_syntax(e);
2422 
2423  if ((n!=normalized_undefined) && (normalized_linear_p(n)))
2424  {
2425  Pvecteur v = normalized_linear(n);
2426  int s = vect_size(v);
2427 
2428  if (s==0) return(true);
2429  if (s>1) return(false);
2430  return((s==1) && value_notzero_p(vect_coeff(TCST,v)));
2431  }
2432  else
2433  if (syntax_call_p(s))
2434  {
2435  call c = syntax_call(s);
2437 
2438  /* I hope a short evaluation is made by the compiler */
2439  return((value_constant_p(v)) && (constant_int_p(value_constant(v))));
2440  }
2441 
2442  return(false);
2443 }
2444 /*=================================================================*/
2445 /* bool expression_constant_p(expression exp)
2446  * Returns true if "exp" is an (integer) constant value.
2447  *
2448  * Note : A negativePositive constant can be represented with a call to the unary
2449  * minus/plus intrinsic function upon a positive value.
2450  *
2451  * See below extended_expression_constant_p() for a more general function.
2452  */
2454 {
2456 }
2457 
2458 /* Returns true if the value of the expression does not depend
2459  syntactically on the current store. Returns false when this has not
2460  been proved. */
2462 {
2464  bool constant_p = false;
2465 
2466  switch(syntax_tag(s)) {
2467  case is_syntax_reference: {
2468  /* The only constant references in PIPS internal representation
2469  are references to functions and to declared constants. */
2470  reference r = syntax_reference(s);
2471  entity v = reference_variable(r);
2472  type t = ultimate_type(entity_type(v));
2473 
2475  break;
2476  }
2477  case is_syntax_range: {
2478  range r = syntax_range(s);
2479  expression lb = range_lower(r);
2480  expression ub = range_upper(r);
2481  expression inc = range_increment(r);
2482 
2486  break;
2487  }
2488  case is_syntax_call: {
2489  call c = syntax_call(s);
2490  entity f = call_function(c);
2491  value v = entity_initial(f);
2492  switch(value_tag(v)) {
2493  case is_value_constant:
2494  constant_p = true;
2495  break;
2496  case is_value_intrinsic: {
2497  /* Check that all arguments are constant */
2498  list args = call_arguments(c);
2499  constant_p = true;
2500  FOREACH(EXPRESSION, sub_exp, args) {
2502  }
2503  break;
2504  }
2505  case is_value_symbolic:
2506  /* Certainly true for Fortran. Quid for C? */
2507  constant_p = true;
2508  break;
2509  case is_value_expression: {
2510  /* does not make much sense... for a function! */
2511  expression sub_exp = value_expression(v);
2513  break;
2514  }
2515  case is_value_unknown:
2516  case is_value_code:
2517  default:
2518  /* Let's be conservative */
2519  constant_p = false;
2520  }
2521  break;
2522  }
2523  case is_syntax_cast: {
2524  /* There might be another case of constant expressions: all that
2525  are casted to void... Usage? */
2526  cast c = syntax_cast(s);
2527  expression sub_exp = cast_expression(c);
2529  break;
2530  }
2532  /* This should be a constant, except for dependent types. */
2534  type t = type_undefined;
2535  if(sizeofexpression_type_p(soe))
2536  t = copy_type(sizeofexpression_type(soe));
2537  else {
2539  t = expression_to_type(se);
2540  }
2541  // constant_p = !dependent_type_p(t);
2543  free_type(t);
2544  break;
2545  }
2546  case is_syntax_subscript:
2547  break;
2548  case is_syntax_application:
2549  break;
2550  case is_syntax_va_arg:
2551  break;
2552  default:
2553  pips_internal_error("Unexpected syntax tag %d", syntax_tag(s));
2554  }
2555  return constant_p;
2556 }
2557 
2558 /* Not all expressions can be used as right-hand side (rhs) in C
2559  assignments.
2560 
2561  PIPS expressions used to encode initializations such as
2562 
2563  "{ 1, 2, 3}"
2564 
2565  in
2566 
2567  "int k[] = { 1, 2, 3 };" cannot be used as rhs.
2568 
2569  There are probably many more cases, especially with
2570  Fortran-specific expressions, e.g. IO expressions. But we do not
2571  have a way to know if an intrinsic is a Fortran or a C or a shared
2572  intrinsic. The information is not carried by PIPS internal
2573  representation and hence not initialized in bootstrap.
2574 
2575  Note: this test is too restrictive as the condition depends on the
2576  type of the lhs. A struct can be assigned a brace expression. So a
2577  type argument should be passed to make such decisions.
2578 
2579  "s = { 1, 2, 3};" is ok if s is a struct with three integer
2580  compatible fields.
2581  */
2583 {
2584  bool is_rhs_p = false;
2585 
2586  is_rhs_p = !brace_expression_p(exp);
2587 
2588  return is_rhs_p;
2589 }
2590 
2592 {
2593  bool one_p = false;
2594 
2598 
2599  if(value_constant_p(v)) {
2600  constant c = value_constant(v);
2601  one_p = constant_int_p(c) && (constant_int(c)==1);
2602  }
2603  }
2604  return one_p;
2605 }
2606 
2607 /**
2608  returns true if the expression is equal to zero or NULL (even if
2609  there is a cast before such as in (void *) 0).
2610 */
2612 {
2613  bool null_p = false;
2614  if (expression_cast_p(exp))
2616  else if (expression_reference_p(exp))
2617  {
2619  }
2620  else
2621  {
2623  null_p = (expression_to_int(exp) == 0);
2624  }
2625  return null_p;
2626 }
2627 
2628 
2629 /************************************************************* DAVINCI GRAPH */
2630 
2631 #define ALREADY_SEEN(node) (hash_defined_p(seen, (char*)node))
2632 #define SEEN(node) (hash_put(seen, (char*) node, (char*) 1))
2633 
2634 #define DV_CIRCLE ",a(\"_GO\",\"circle\")"
2635 #define DV_YELLOW ",a(\"COLOR\",\"yellow\")"
2636 
2638  FILE * out, expression e, hash_table seen)
2639 {
2640  syntax s;
2641  const char* name, *shape, *color;
2642  list sons = NIL;
2643  bool first = true, something = true;
2644 
2645  if (ALREADY_SEEN(e)) return false;
2646  SEEN(e);
2647 
2648  s = expression_syntax(e);
2649  switch (syntax_tag(s))
2650  {
2651  case is_syntax_call:
2652  {
2653  call c = syntax_call(s);
2654  name = entity_local_name(call_function(c));
2655  sons = call_arguments(c);
2656  shape = "";
2657  color = "";
2658  break;
2659  }
2660  case is_syntax_range:
2661  name = "::";
2662  shape = "";
2663  color = "";
2664  break;
2665  case is_syntax_cast: // ???
2666  name = "";
2667  shape = "";
2668  color = "";
2669  pips_user_warning("skipping cast\n");
2670  break;
2671  case is_syntax_reference:
2673  shape = DV_CIRCLE;
2674  color = DV_YELLOW;
2675  break;
2676  default:
2677  name = "";
2678  shape = "";
2679  color = "";
2680  pips_internal_error("unexpected syntax tag (%d)", syntax_tag(s));
2681  }
2682 
2683  /* daVinci node prolog. */
2684  fprintf(out, "l(\"%zx\",n(\"\",[a(\"OBJECT\",\"%s\")%s%s],[",
2685  (_uint) e, name, color, shape);
2686 
2687  MAP(EXPRESSION, son,
2688  {
2689  if (!first) fprintf(out, ",\n");
2690  else { fprintf(out, "\n"); first=false; }
2691  fprintf(out, " l(\"%zx->%zx\",e(\"\",[],r(\"%zx\")))",
2692  (_uint) e, (_uint) son, (_uint) son);
2693  },
2694  sons);
2695 
2696  /* node epilog */
2697  fprintf(out, "]))\n");
2698 
2699  MAP(EXPRESSION, son,
2700  {
2701  if (something) fprintf(out, ",");
2702  something = davinci_dump_expression_rc(out, son, seen);
2703  }, sons);
2704 
2705  return true;
2706 }
2707 
2708 /* dump expression e in file out as a davinci graph.
2709  */
2711 {
2713  fprintf(out, "[\n");
2715  fprintf(out, "]\n\n");
2717 }
2718 
2719 static FILE * out_flt = NULL;
2720 static bool expr_flt(expression e)
2721 {
2723  return false;
2724 }
2725 
2726 /* dump all expressions in s to out.
2727  */
2729 {
2730  out_flt = out;
2732  out_flt = NULL;
2733 }
2734 ␌
2735 
2736 typedef struct ctx_substitute {
2738  entity new;
2740 
2742  entity old = ctx->old;
2743  entity new = ctx->new;
2744 
2745  if (same_entity_p(reference_variable(r), old)) {
2746  reference_variable(r) = new;
2747  }
2748 }
2749 
2751  entity old = ctx->old;
2752  entity new = ctx->new;
2753 
2754  if (same_entity_p(call_function(c),old)) {
2755  call_function(c) = new;
2756  }
2757 }
2758 
2759 /**
2760  * (This function isn't use for the moment)
2761  * This function replaces all the occurrences of an old entity in the
2762  * expression exp by the new entity. It returns the expression modified.
2763  * It replaces only entity when it's an variable.
2764  * So a recurse can be made on reference to replace the entity.
2765  * (to not consider only variable entity have to make a special case for call, call_function)
2766  * Modify the entry expression e by side effect
2767  * \param old entity to replace
2768  * \param new entity that will replace old
2769  * \param e expression in will the entity old will be replaced
2770  * \return e expression modified by side effect
2771  */
2773 {
2774  ctx_substitute_t ctx;
2775  ctx.old = old;
2776  ctx.new = new;
2777 
2779  return e;
2780 }
2781 
2782 /* This function replaces all the occurences of an old entity in the
2783  * expression exp by the new entity. It returns the expression modified.
2784  * I think we can write this function by using gen_context_multi_recurse ... * To do .... NN
2785  * gen_context_multi_recurse done in r22231
2786  * Modify the entry expression e by side effect
2787  * \param old entity to replace
2788  * \param new entity that will replace old
2789  * \param e expression in will the entity old will be replaced
2790  * \return e expression modified by side effect
2791  */
2793 {
2794  ctx_substitute_t ctx;
2795  ctx.old = old;
2796  ctx.new = new;
2797 
2799  e, &ctx,
2802  NULL);
2803  return e;
2804 }
2805 ␌
2806 /* Replace C operators "+C" and "-C" which can handle pointers by
2807  arithmetic operators "+" and "-" when it is safe to do so, i.e. when no
2808  pointer arithmetic is involved.
2809 
2810  FI: Also, it might be useful to normalize the expression in order
2811  not to leave an undefined field in it. But this is a recursive
2812  function and probably not the right place to cope with this.
2813  */
2815 {
2816  syntax s = expression_syntax(e);
2817  bool can_be_substituted_p = false;
2818 
2819  pips_debug(9, "Begin\n");
2820 
2821  switch(syntax_tag(s)) {
2822  case is_syntax_reference:
2823  {
2825  type rt = entity_type(re);
2826 
2827  if(type_undefined_p(rt)) {
2828  /* FI: see C_syntax/block_scope12.c. The source code line
2829  number where the problem occurs cannot be given because we
2830  are not in the c_syntax library. */
2831  pips_user_warning("Variable \"%s\" is probably used before it is defined\n",
2832  entity_user_name(re));
2833  can_be_substituted_p = false;
2834  }
2835  else {
2836  basic bt = basic_undefined;
2837 
2838  if(type_variable_p(rt)) { /* FI: What if not? core dump? */
2839  /* The variable type can hide a functional type via a
2840  typedef */
2841  type urt = ultimate_type(rt);
2842  if(type_variable_p(urt)) {
2843  bt = variable_basic(type_variable(urt));
2844 
2845  can_be_substituted_p =
2846  basic_int_p(bt)
2847  || basic_float_p(bt)
2848  || basic_overloaded_p(bt) /* Might be wrong, but necessary */
2849  || basic_complex_p(bt) /* Should not occur in old C code */
2850  || basic_logical_p(bt); /* Should not occur in old C code */
2851 
2852  pips_debug(9, "Variable %s is an arithmetic variable: %s\n",
2853  entity_local_name(re), bool_to_string(can_be_substituted_p));
2854  }
2855  }
2856  }
2857  break; /* FI: The index expressions should be simplified too... */
2858  }
2859  case is_syntax_call:
2860  {
2861  call c = syntax_call(s);
2862 
2863  if(expression_constant_p(e)) {
2864  /* What is the type of the constant? */
2865  entity cste = call_function(c);
2867 
2868  can_be_substituted_p =
2869  basic_int_p(rb)
2870  || basic_float_p(rb)
2871  || basic_complex_p(rb); /* Should not occur in C, before C99 */
2872  }
2873  else if(gen_length(call_arguments(c))==2) {
2874  /* Check "+C" and "-C" */
2875  expression e1 = binary_call_lhs(c);
2876  expression e2 = binary_call_rhs(c);
2877  bool can_be_substituted_p1 = simplify_C_expression(e1);
2878  bool can_be_substituted_p2 = simplify_C_expression(e2);
2879  can_be_substituted_p = can_be_substituted_p1 && can_be_substituted_p2;
2880  if(can_be_substituted_p) {
2881  entity op = call_function(c);
2882  if(ENTITY_PLUS_C_P(op)) {
2884  }
2885  else if(ENTITY_MINUS_C_P(op)) {
2887  }
2888  }
2889  }
2890  else {
2891  /* Try to simplify the arguments, do not hope much from the result
2892  type because of overloading. */
2893  type ft = call_to_functional_type(c, true);
2895  entity f = call_function(c);
2896 
2897  //pips_assert("The function type is functional", type_functional_p(entity_type(f)));
2898 
2899  FOREACH(EXPRESSION, se, call_arguments(c)) {
2900  (void) simplify_C_expression(se);
2901  }
2902 
2904  can_be_substituted_p = false;
2905  }
2906  else if(type_variable_p(rt)) {
2908 
2909  if(basic_overloaded_p(rb)) {
2910  /* a void expression such as (void) 0 results in an
2911  * undefined basic. And so may do a condition c? (void *)
2912  * 0 : (void *) 0.
2913  */
2914  rb = basic_of_expression(e);
2915  }
2916  else
2917  rb = copy_basic(rb);
2918 
2919  if(!basic_undefined_p(rb)) {
2920  /* FI: I guess, typedef equivalent to those could also be declared substituable */
2921  can_be_substituted_p =
2922  basic_int_p(rb)
2923  || basic_float_p(rb)
2924  || basic_complex_p(rb); /* Should not occur in C */
2925  free_basic(rb);
2926  }
2927  else {
2928  /* e must be a void expression, i.e. an expression returning no value */
2929  can_be_substituted_p = false;
2930  }
2931  }
2932  else {
2933  can_be_substituted_p = false;
2934  }
2935  }
2936  break;
2937  }
2938  case is_syntax_range:
2939  {
2940  range r = syntax_range(s);
2941  expression le = range_lower(r);
2942  expression ue = range_upper(r);
2943  expression ince = range_increment(r);
2944  (void) simplify_C_expression(le);
2945  (void) simplify_C_expression(ue);
2946  (void) simplify_C_expression(ince);
2947  can_be_substituted_p = false;
2948  break;
2949  }
2950  case is_syntax_cast:
2952  case is_syntax_subscript:
2953  case is_syntax_application:
2954  case is_syntax_va_arg:
2955  can_be_substituted_p = false;
2956  break;
2957  default: pips_internal_error("Bad syntax tag");
2958  can_be_substituted_p = false; /* for gcc */
2959  }
2960 
2961  pips_debug(9, "End: %s\n", bool_to_string(can_be_substituted_p));
2962  return can_be_substituted_p;
2963 }
2964 
2965 /* Replace a C expression used as FOR bound by a Fortran DO bound
2966  expression, taking into account the C comparison operator used.
2967 */
2968 expression convert_bound_expression(expression e, bool upper_p, bool non_strict_p)
2969 {
2971 
2972  if(non_strict_p) {
2973  b = copy_expression(e);
2974  }
2975  else {
2976  /* */
2977  intptr_t ib = 0;
2978  intptr_t nb = 0;
2979 
2980  /* Fi this test is too strong to preserve source code */
2981  if(false && expression_integer_value(e, &ib)) {
2982  /* The offset might not be plus or minus one, unless we know the
2983  index is an integer? Does it depend on the step value? More
2984  thought needed than available tonight (FI) */
2985  nb = upper_p? ib-1 : ib+1;
2986  b = int_to_expression(nb);
2987  }
2988  else if(expression_constant_p(e)) {
2989  /* The offset might not be plus or minus one, unless we know the
2990  index is an integer? Does it depend on the step value? More
2991  thought needed than available tonight (FI) */
2992  ib = expression_to_int(e);
2993  nb = upper_p? ib-1 : ib+1;
2994  b = int_to_expression(nb);
2995  }
2996  else if(NORMALIZE_EXPRESSION(e), expression_linear_p(e)) {
2997  /* May modify the source code a bit more than necessary, but
2998  avoids stupid expressions such as 64-1-1 */
3000  Pvecteur v = normalized_linear(n);
3001  /* This could be generalized to any affine expression. See for
3002  instance loop_bound02.c. But the source code is likely to be
3003  disturbed if the bound expression is regenerated from v after
3004  adding or subtracting 1 from its constant term. */
3005  if(vect_constant_p(v) || VECTEUR_NUL_P(v)) {
3006  Value c = vect_coeff(TCST, v);
3007  ib = (int) c;
3008  nb = upper_p? ib-1 : ib+1;
3009  b = int_to_expression(nb);
3010  }
3011  }
3012  if(expression_undefined_p(b)) {
3015 
3016  b = MakeBinaryCall(op, copy_expression(e), offset);
3017  }
3018  }
3019  return b;
3020 }
3021 ␌
3023 {
3024  list sel = reference_indices(r);
3025  bool constant_p = true;
3026 
3027  FOREACH(EXPRESSION, se, sel) {
3029  && !field_expression_p(se) ) { // for points-to references
3030  constant_p = false;
3031  break;
3032  }
3033  }
3034  return constant_p;
3035 }
3036 
3037 /* Return by side effect a reference whose memory locations includes
3038  the memory locations of r in case the subcript expressions are
3039  changed by a store change.
3040 
3041  Constant subscript expressions are preserved.
3042 
3043  Store varying subscript expressions are replaced by unbounded expressions.
3044  */
3046 {
3047  list sel = reference_indices(r);
3048  list sec = list_undefined;
3049 
3050  for(sec = sel; !ENDP(sec); POP(sec)) {
3051  expression se = EXPRESSION(CAR(sec));
3052 
3054  free_expression(se);
3056  }
3057  }
3058 
3059  return r;
3060 }
3061 
3062 /* indices can be constant or unbounded: they are store independent.
3063  *
3064  * See next function, reference_with_unbounded_subscript_p()
3065  */
3067 {
3068  list sel = reference_indices(r);
3069  bool unbounded_p = true;
3070 
3071  FOREACH(EXPRESSION, se, sel) {
3073  && !unbounded_expression_p(se)) {
3074  unbounded_p = false;
3075  break;
3076  }
3077  }
3078  return unbounded_p;
3079 }
3080 
3081 /* See if the reference uses the unbounded function '*'
3082  *
3083  * See previous function, reference_with_unbounded_indices_p()
3084  */
3086 {
3087  list sel = reference_indices(r);
3088  bool unbounded_p = false;
3089 
3090  FOREACH(EXPRESSION, se, sel) {
3091  if(unbounded_expression_p(se)) {
3092  unbounded_p = true;
3093  break;
3094  }
3095  }
3096  return unbounded_p;
3097 }
3098 ␌
3099 /* Does this reference define the same set of memory locations
3100  * regardless of the current (environment and) memory state?
3101  *
3102  * This function copes with standard references, extended to pointer
3103  * references such as p[i], not with general points-to references,
3104  * which are extended to cope with structs and implicit
3105  * dereferencing. Points-to references are/should be handled in
3106  * effects-util, not in ri-util.
3107  */
3109 {
3110  bool independent_p = true;
3111  //list ind = reference_indices(r);
3112  entity v = reference_variable(r);
3113  type t = ultimate_type(entity_type(v));
3114 
3115  if(pointer_type_p(t)) {
3116  independent_p = false;
3117  }
3118  else {
3119  independent_p = reference_with_constant_indices_p(r);
3120  }
3121 
3122  return independent_p;
3123 }
3124 ␌
3125 
3126 /* just returns the entity of an expression, or entity_undefined
3127  *
3128  * The entity returned is either the function called or the variable
3129  * referenced
3130  *
3131  * SG: moved here from hpfc
3132  * Warning: This function certainly needs to be reviewed,
3133  * maybe just testing the size of arguments (call), or the
3134  * size of index (reference) may be sufficient as a first step.
3135  * If their sizes are != 0, it may not return what we expect
3136  * (for instance "-3" will return UNARY_MINUS_OPERATOR_NAME "--").
3137  * But expression_to_entity is called by many functions and I worry
3138  * about the side effects on them.
3139  */
3141 {
3142  syntax s = expression_syntax(e);
3143 
3144  switch (syntax_tag(s))
3145  {
3146  case is_syntax_call:
3147  return call_function(syntax_call(s));
3148  case is_syntax_reference:
3150  case is_syntax_range:
3151  case is_syntax_cast:
3153  case is_syntax_subscript:
3154  case is_syntax_application:
3155  case is_syntax_va_arg:
3156  default:
3157  return entity_undefined;
3158  }
3159 }
3160 /* map expression_to_entity on expressions */
3162 {
3163  list entities = NIL;
3164  FOREACH(EXPRESSION,exp,expressions)
3166  return gen_nreverse(entities);
3167 }
3168 
3169 
3170 /**
3171  * @brief perform the real similarity comparaison between two expressions
3172  * @a target is matched against @a pattern, and expression <> argument is stored in @a symbols
3173  *
3174  * @param target cheked expression
3175  * @param pattern pattern expression
3176  * @param symbols map storing entity <> expression tuple
3177  *
3178  * @return true if similar
3179  */
3181 {
3182  bool similar=true;
3183  syntax starget = expression_syntax(target),
3184  spattern = expression_syntax(pattern);
3185 
3186  /* cast handler */
3187  if( syntax_cast_p( spattern ) )
3188  {
3189  pips_user_warning("cast ignored\n");
3190  return _expression_similar_p(target, cast_expression(syntax_cast(spattern)),symbols);
3191  }
3192  if( syntax_cast_p( starget ) )
3193  {
3194  pips_user_warning("cast ignored\n");
3195  return _expression_similar_p(cast_expression(syntax_cast(starget)), pattern,symbols);
3196  }
3197 
3198  switch(syntax_tag(spattern) )
3199  {
3200  /* we memorize reference from target and pattern in the symbol table
3201  * similar to \1 in sed
3202  */
3203  case is_syntax_reference:
3204  {
3205  reference r = syntax_reference(spattern);
3206  /* scalar reference always matches.
3207  * SG: in fact, you have to check for type compatibility too ...
3208  * Allows to match malloc(a) with more complex expressions like malloc(1 +
3209  * strlen("...")).
3210  * Interferes incorrectly with commutativity. */
3212  similar = false;
3213  else {
3214  basic bpattern = basic_of_expression(pattern),
3215  btarget = basic_of_expression(target);
3216  basic bmax = basic_maximum(bpattern,btarget);
3217  if(basic_overloaded_p(bmax) || basic_equal_p(bmax,bpattern)) {
3218  hash_put(symbols,entity_name(reference_variable(r)), target);
3219  }
3220  else
3221  similar = false;
3222  free_basic(bmax);
3223  free_basic(bpattern);
3224  free_basic(btarget);
3225  }
3226  } break;
3227  /* recursively compare each arguments if call do not differ */
3228  case is_syntax_call:
3229  if( syntax_call_p(starget) &&
3231  {
3232  call cpattern = syntax_call(spattern);
3233  call ctarget = syntax_call(starget);
3234  if(commutative_call_p(cpattern))
3235  {
3236  pips_assert("pips commutative call have only two arguments\n",gen_length(call_arguments(cpattern))==2);
3237  expression lhs_pattern = binary_call_lhs(cpattern),
3238  rhs_pattern = binary_call_rhs(cpattern),
3239  lhs_target = binary_call_lhs(ctarget),
3240  rhs_target = binary_call_rhs(ctarget);
3241  similar = (_expression_similar_p(lhs_target,lhs_pattern,symbols) && _expression_similar_p(rhs_target,rhs_pattern,symbols))
3242  ||
3243  (_expression_similar_p(lhs_target,rhs_pattern,symbols) && _expression_similar_p(rhs_target,lhs_pattern,symbols))
3244  ;
3245 
3246  }
3247  else
3248  {
3249  list iter = call_arguments(cpattern);
3250  FOREACH(EXPRESSION, etarget, call_arguments(ctarget) )
3251  {
3252  if( ENDP(iter) ) { similar = false; break; }/* could occur with va args */
3253  expression epattern = EXPRESSION(CAR(iter));
3254  similar&= _expression_similar_p(etarget,epattern,symbols);
3255  POP(iter);
3256  if(!similar)
3257  break;
3258  }
3259  }
3260  }
3261  else
3262  {
3263  similar =false;
3264  }
3265  break;
3266  /* SG: will this be usefull ?*/
3267  case is_syntax_range:
3268  similar = syntax_range_p(starget) &&
3269  _expression_similar_p(range_lower(syntax_range(starget)),range_lower(syntax_range(spattern)),symbols) &&
3270  _expression_similar_p(range_upper(syntax_range(starget)),range_upper(syntax_range(spattern)),symbols) &&
3272  break;
3273 
3274  /* SG:not supported yet */
3275  case is_syntax_cast:
3276  pips_user_warning("cast ignored\n");
3277  similar = _expression_similar_p(cast_expression(syntax_cast(starget)),pattern,symbols);
3278  break;
3279 
3281  if( syntax_sizeofexpression_p(starget) )
3282  {
3283  sizeofexpression seo_target = syntax_sizeofexpression(starget);
3284  sizeofexpression seo_pattern = syntax_sizeofexpression(spattern);
3285  if( sizeofexpression_type(seo_pattern) )
3286  similar = sizeofexpression_type_p(seo_target) &&
3287  type_equal_p( sizeofexpression_type(seo_target), sizeofexpression_type(seo_pattern) );
3288  else
3289  similar = _expression_similar_p(sizeofexpression_expression(seo_target),
3290  sizeofexpression_expression(seo_pattern),
3291  symbols );
3292  }
3293  else
3294  {
3295  similar =false;
3296  }
3297  break;
3298 
3299  case is_syntax_subscript:
3300  if( syntax_subscript_p(starget) )
3301  {
3302  subscript sub_target = syntax_subscript(starget),
3303  sub_pattern = syntax_subscript(spattern);
3304  similar&= _expression_similar_p( subscript_array(sub_target), subscript_array(sub_pattern),symbols );
3305 
3306  list iter = subscript_indices(sub_pattern);
3307  FOREACH(EXPRESSION, etarget, subscript_indices(sub_target) )
3308  {
3309  if( ENDP(iter) ) { similar = false; break; }/* could occur with va args */
3310  expression epattern = EXPRESSION(CAR(iter));
3311  similar&= _expression_similar_p(etarget,epattern,symbols);
3312  POP(iter);
3313  }
3314  }
3315  else
3316  similar =false;
3317  break;
3318  case is_syntax_application:
3319  pips_user_warning("application similarity not implemented yet\n");
3320  similar=false;
3321  break;
3322  case is_syntax_va_arg:
3323  pips_user_warning("va_arg similarity not implemented yet\n");
3324  similar=false;
3325  break;
3326  };
3327  return similar;
3328 }
3329 /**
3330  * @brief similar to expression_similar_p but the hash_map
3331  * containing the crossref value is retured for further use
3332  *
3333  * @param target expression to compare
3334  * @param pattern expression serving as pattern
3335  * @param symbol_table pointer to unallocated hash_map, in the end it will contain a set of pair (original syntax reference name, substituted syntax element). Must be freed, but only if expressions are similar
3336  *
3337  * @return true if expressions are similar
3338  */
3340 {
3342  bool similar = _expression_similar_p(target,pattern,*symbol_table);
3343  if( !similar) hash_table_free(*symbol_table);
3344  return similar;
3345 }
3346 
3347 /**
3348  * @brief compare if two expressions are similar
3349  * that is can we exchange target and pattern by substituing
3350  * variables
3351  * examples:
3352  * 1+2 ~ a+b
3353  * a+b !~ a+2
3354  * 1+b ~ 1+c
3355  * @param target expression that sould match with pattern
3356  * @param pattern the pattern to match
3357  *
3358  * @return true if expressions are similar
3359  */
3361 {
3363  bool similar = _expression_similar_p(target,pattern,symbol_table);
3365  return similar;
3366 }
3367 
3368 list /* of expression */
3369 make_list_of_constant(int val, /* the constant value */
3370  int number) /* the length of the created list */
3371 {
3372  list l=NIL;
3373 
3374  pips_assert("valid number", number>=0);
3375  for(; number; number--)
3376  l = CONS(EXPRESSION, int_to_expression(val), l);
3377 
3378  return l;
3379 }
3380 ␌
3381 /**
3382  * Return bool indicating if expression e is a brace expression
3383  */
3385 {
3386  if (expression_call_p(e))
3387  {
3390  return true;
3391  }
3392  return false;
3393 }
3394 
3395 /* helper for brace_expression_to_statements */
3397  int new_index = 0;
3398  list out = NIL;
3400  // FI: we need to know the type of arr[curr_indices] to determine
3401  // if it is a struct or an array
3402 
3403  // A reference r is built temporarily to call reference_to_type()
3404  reference r = make_reference(arr, curr_indices);
3405  // FI: I have no idea if t should be freed; no documentation for
3406  // reference_to_type()
3407  type t = reference_to_type(r);
3408  reference_indices(r) = NIL;
3409  free_reference(r);
3410 
3412  if(array_type_p(t)) {
3413  ee = int_to_expression(new_index);
3414  }
3415  else if(type_struct_variable_p(t)) {
3416  list fl = struct_type_to_fields(t);
3417  entity f = ENTITY(gen_nth(new_index, fl));
3418  ee = entity_to_expression(f);
3419  // The field will appear as an index, not as a field selector
3420  }
3421  else
3422  pips_internal_error("Unexpected type.\n");
3423 
3424  list ind = gen_append(gen_full_copy_list(curr_indices),
3425  make_expression_list(ee));
3426  if(brace_expression_p(arg)) {
3427  list out_bis = do_brace_expression_to_statements(arr, arg,ind);
3428  gen_full_free_list(ind);
3429  out = gen_append(out, out_bis);
3430  }
3431  else {
3432  reference r = make_reference(arr,NIL);
3434  // FI: the expression should be normalized and field subscripts
3435  // replaced by field accesses, with the field operator...
3436  FOREACH(expression, ie, ind) {
3437  if(expression_reference_p(ie)) {
3439  if(entity_field_p(i)) {
3440  // FI: this is not going to work for structs of arrays...
3441  // expression ne = make_op_exp(FIELD_OPERATOR_NAME, e, ie);
3442  // expression ne = make_op_exp(FIELD_OPERATOR_NAME, e, ie);
3444  expression ne = MakeBinaryCall(op, e, ie);
3445  e = ne;
3446  }
3447  else
3448  pips_internal_error("Unexpected entity.\n");
3449  }
3450  else {
3451  // list ind is memory leaked...
3452  if(expression_reference_p(e)) {
3454  CONS(expression, ie, NIL));
3455  }
3456  else {
3457  subscript s = make_subscript(e, CONS(expression, ie, NIL));
3458  syntax ss = make_syntax_subscript(s);
3460  //entity op = CreateIntrinsic(SUBSCRIPT_OPERATOR_NAME);
3461  //expression ne = MakeBinaryCall(op, e, ie);
3462  //e = ne;
3463  }
3464  }
3465  }
3466  gen_free_list(ind);
3469  )
3470  );
3471  }
3472  ++new_index;
3473  }
3474  return out;
3475 }
3476 
3477 /* converts a brace expression used to initialize an array (not a struct yet)
3478  * into a statement sequence
3479  */
3481  pips_assert("is a brace expression\n",brace_expression_p(e));
3482  //SG: needs work to support structures
3483  // pips_assert("is an array\n",array_entity_p(arr));
3484  list curr_index = NIL;
3485  list out = do_brace_expression_to_statements(arr,e,curr_index);
3486  return out;
3487 }
3488 
3489 /* helper for brace_expression_to_updated_type
3490  *
3491  * Side-effect on dl, the dimension list of e's type
3492  */
3494  expression e,
3495  list dl)
3496 {
3497  dimension d = DIMENSION(CAR(dl));
3498  expression u = dimension_upper(d);
3499  if(unbounded_expression_p(u)) {
3501  int nu = (int) gen_length(al) -1 ;
3502  expression nue = int_to_expression(nu);
3503  dimension_upper(d) = nue;
3504  free_expression(u);
3505  if(!ENDP(CDR(dl))) {
3506  // This is probably useless because only the first dimension can
3507  // be undefined
3508  expression se = EXPRESSION(CAR(al));
3510  }
3511  }
3512 }
3513 
3514 /* use a brace expression to update the type of array "arr" if the
3515  dimensions are implicit
3516  */
3518  pips_assert("is a brace expression\n",brace_expression_p(e));
3519  //SG: needs work to support structures
3520  //pips_assert("is an array\n",array_entity_p(arr));
3521  // type t = entity_basic_concrete_type(arr);
3522  type t = entity_type(arr);
3523  variable v = type_variable(t);
3524  list dl = variable_dimensions(v);
3526 }
3527 ␌
3528 /* This function returns true if Reference r is scalar
3529 */
3531 {
3532  entity v = reference_variable(r);
3533  assert(!reference_undefined_p(r) && r!=NULL && v!=NULL);
3534  return (reference_indices(r) == NIL && entity_scalar_p(v));
3535 }
3536 
3537 /**
3538  @brief take a list of expression and apply a binary operator between all
3539  of them and return it as an expression
3540  @return the operations as an expression
3541  @param l_exprs, the list of expressions to compute with the operator
3542  @param op, the binary operator to apply
3543  **/
3546  if ((l_exprs != NIL) && (op != entity_undefined)){
3547  list l_src = l_exprs;
3548  result = EXPRESSION (CAR (l_src));
3549  POP(l_src);
3550  FOREACH (EXPRESSION, ex, l_src) {
3551  list args = gen_expression_cons (result, NIL);
3552  args = gen_expression_cons (ex, args);
3553  call c = make_call (op, args);
3554  result = call_to_expression (c);
3555  }
3556  }
3557  return result;
3558 }
3559 
3560 /**
3561  * frees expression syntax of @p e
3562  * and replace it by the new syntax @p s
3563  */
3565 {
3568  expression_syntax(e)=s;
3569 }
3570 /* replace expression @p caller by expression @p field , where @p field is contained by @p caller */
3572 {
3573  syntax s = expression_syntax(field) ;
3575  free_syntax(expression_syntax(caller));
3576  expression_syntax(caller)=s;
3578 }
3579 
3580 /* generates an expression from a syntax */
3582  return make_expression(
3583  s,
3585  );
3586 }
3587 
3588 /* converts a monome to an expression */
3590 {
3591  if (MONOME_UNDEFINED_P(pm))
3592  return expression_undefined;
3593  else {
3594  expression coeff;
3595  float x= monome_coeff(pm);
3596  if(x == (int)x)
3597  coeff = (x==1.f)? expression_undefined:int_to_expression((int)x);
3598  else
3599  coeff = float_to_expression(x);
3601  for(Pvecteur v = monome_term(pm);!VECTEUR_NUL_P(v);v=vecteur_succ(v)) {
3602  Value exp = vecteur_val(v);
3603  Variable var = vecteur_var(v);
3604  expression tmp ;
3605  if(exp==0||var==TCST) tmp = int_to_expression(1);
3606  else {
3607  Value val = exp>0 ? exp: -exp;
3608  tmp = entity_to_expression((entity)var);
3609  while(--val)
3611  if(exp<0)
3613  }
3615  }
3616  return expression_undefined_p(coeff)?term:
3618  }
3619 }
3620 
3621 /* converts a polynomial to expression */
3623 {
3625 
3626  if (POLYNOME_UNDEFINED_P(pp))
3628  else if (POLYNOME_NUL_P(pp))
3629  r = int_to_expression(0);
3630  else {
3631  while (!POLYNOME_NUL_P(pp)) {
3633  if(expression_undefined_p(r)) r=s;
3634  else
3636  pp = polynome_succ(pp);
3637  }
3638  }
3639  return r;
3640 }
3641 /*============================================================================*/
3642 /* Ppolynome expression_to_polynome(expression exp): translates "exp" into a
3643  * polynome. This transformation is feasible if "exp" contains only scalars and
3644  * the four classical operations (+, -, *, /).
3645  *
3646  * The translation is done straightforwardly and recursively.
3647  *
3648  * it returns a POLYNOME_UNDEFINED if the conversion failed
3649  */
3651 {
3652  Ppolynome pp_new=POLYNOME_UNDEFINED; /* This the resulting polynome */
3654 
3655  switch(syntax_tag(sy))
3656  {
3657  case is_syntax_reference:
3658  {
3659  reference r = syntax_reference(sy);
3660  entity en = reference_variable(r);
3661 
3663  pp_new = make_polynome(1.0, (Variable) en, (Value) 1);
3664  break;
3665  }
3666  case is_syntax_call:
3667  {
3668  /* Two cases : _ a constant
3669  * _ a "real" call, ie an intrinsic or external function
3670  */
3671  if (expression_constant_p(exp)) {
3672  float etof = expression_to_float(exp);
3673  pp_new = make_polynome( etof,
3675  /* We should have a real null polynome : 0*TCST^1 AL, AC 04 11 93
3676  *else {
3677  * Pmonome pm = (Pmonome) malloc(sizeof(Smonome));
3678  * monome_coeff(pm) = 0;
3679  * monome_term(pm) = vect_new(TCST, 1);
3680  * pp_new = monome_to_new_polynome(pm);
3681  *}
3682  */
3683  }
3684  else
3685  {
3686  int cl;
3687  expression arg1, arg2 = expression_undefined;
3688  entity op_ent = call_function(syntax_call(sy));
3689 
3690  /* The call must be one of the four classical operations:
3691  * +, - (unary or binary), *, /
3692  */
3693  if(ENTITY_FIVE_OPERATION_P(op_ent))
3694  {
3695  /* This call has one (unary minus) or two (binary plus, minus,
3696  * multiply or divide) arguments, no less and no more.
3697  */
3699  if( (cl != 2) && (cl != 1) )
3700  pips_internal_error("%s call with %d argument(s)",
3701  entity_local_name(op_ent), cl);
3702 
3703  arg1 = EXPRESSION(CAR(call_arguments(syntax_call(sy))));
3704  if(cl == 2)
3705  arg2 = EXPRESSION(CAR(CDR(call_arguments(syntax_call(sy)))));
3706 
3707  if (ENTITY_PLUS_P(op_ent)||ENTITY_PLUS_C_P(op_ent)) /* arg1 + arg2 */
3708  {
3709  pp_new = expression_to_polynome(arg1);
3710  if(!POLYNOME_UNDEFINED_P(pp_new))
3711  polynome_add(&pp_new, expression_to_polynome(arg2));
3712  }
3713  else if(ENTITY_MINUS_P(op_ent)||ENTITY_MINUS_C_P(op_ent)) /* -arg2 + arg1 */
3714  {
3715  pp_new = expression_to_polynome(arg2);
3716  if(!POLYNOME_UNDEFINED_P(pp_new)) {
3717  polynome_negate(&pp_new);
3718  Ppolynome parg1 = expression_to_polynome(arg1);
3719  if(!POLYNOME_UNDEFINED_P(parg1))
3720  polynome_add(&pp_new, parg1);
3721  else {
3722  polynome_rm(&pp_new);
3723  pp_new=POLYNOME_UNDEFINED;
3724  }
3725  }
3726  }
3727  else if(ENTITY_MULTIPLY_P(op_ent)) /* arg1 * arg2 */ {
3728  Ppolynome p1 = expression_to_polynome(arg1);
3729  if(!POLYNOME_UNDEFINED_P(p1)) {
3730  Ppolynome p2 = expression_to_polynome(arg2);
3731  if(!POLYNOME_UNDEFINED_P(p2)) {
3732  pp_new = polynome_mult(p1,p2);
3733  }
3734  }
3735  }
3736  else if(ENTITY_DIVIDE_P(op_ent)) /* arg1 / arg2 */ {
3737  Ppolynome p1 = expression_to_polynome(arg1);
3738  if(!POLYNOME_UNDEFINED_P(p1)) {
3739  Ppolynome p2 = expression_to_polynome(arg2);
3740  if(!POLYNOME_UNDEFINED_P(p2)) {
3741  pp_new = polynome_div(p1,p2);
3742  }
3743  }
3744  }
3745  else /* (ENTITY_UNARY_MINUS_P(op_ent)) : -arg1 */
3746  {
3747  pp_new = expression_to_polynome(arg1);
3748  if(!POLYNOME_UNDEFINED_P(pp_new)) {
3749  polynome_negate(&pp_new);
3750  }
3751  }
3752  }
3753  }
3754 
3755  break;
3756  }
3757  default :
3758  {
3759  pp_new=POLYNOME_UNDEFINED;
3760  }
3761  }
3762  return(pp_new);
3763 }
3764 
3765 /* use polynomials to simplify an expression
3766  * in some cases this operation can change the basic of the expression.
3767  * E.g. n/4 -> .25 * n
3768  * In that case we just undo the simplification
3769  */
3771  expression exp = *pexp;
3772  bool result =false;
3773  if(!expression_undefined_p(exp)) {
3774  basic oldb = basic_of_expression(exp);
3776  if((result=!POLYNOME_UNDEFINED_P(pu))) {
3778  basic nbasic = basic_of_expression(pue);
3779  if(basic_equal_p(oldb,nbasic)) {
3781  *pexp=pue;
3782  }
3783  else {
3784  free_expression(pue);
3785  }
3786  free_basic(nbasic);
3787  polynome_rm(&pu);
3788  }
3789  free_basic(oldb);
3790  }
3791  return result;
3792 }
3793 
3795  for(list iter = call_arguments(c);!ENDP(iter);POP(iter)) {
3796  expression *pexp = (expression*)REFCAR(iter);
3797  simplify_expression(pexp);
3798  }
3799 }
3800 
3801 void simplify_expressions(void *obj) {
3803 }
3804 
3805 /* computes the offset of a C reference with its origin
3806  */
3808 {
3809  if(ENDP(reference_indices(ref))) return int_to_expression(0);
3810  else {
3811  expression address_computation = copy_expression(EXPRESSION(CAR(reference_indices(ref))));
3812 
3813  /* iterate on the dimensions & indices to create the index expression */
3816  POP(indices);
3817  if(!ENDP(dims)) POP(dims); // the first dimension is unused
3818  FOREACH(DIMENSION,dim,dims)
3819  {
3822  make_op_exp(
3826  ),
3827  int_to_expression(1));
3828 
3829  if( !ENDP(indices) ) { /* there may be more dimensions than indices */
3830  expression index_expression = EXPRESSION(CAR(indices));
3831  address_computation = make_op_exp(
3833  copy_expression(index_expression),
3834  make_op_exp(
3836  dimension_size,address_computation
3837  )
3838  );
3839  POP(indices);
3840  }
3841  else {
3842  address_computation = make_op_exp(
3844  dimension_size,address_computation
3845  );
3846  }
3847  }
3848 
3849  /* there may be more indices than dimensions */
3851  {
3852  address_computation = make_op_exp(
3854  address_computation,copy_expression(e)
3855  );
3856  }
3857  return address_computation ;
3858  }
3859 }
3860 ␌
3861 /* Use side effects to move the content of e2, s2 and n2, into e1; s1
3862  and n1 are freed, as well as e2. This is useful if you need to
3863  keep the handle on e1. e1 is returned, although it is redundant. */
3865 {
3866  syntax s1 = expression_syntax(e1);
3868  syntax s2 = expression_syntax(e2);
3870 
3871  expression_syntax(e1) = s2;
3872  expression_normalized(e1) = n2;
3875  free_syntax(s1);
3876  free_normalized(n1);
3877  free_expression(e2);
3878 
3879  return e1;
3880 }
3881 /* @return true if expression @p e is a min or a max */
3883 {
3884  if(expression_call_p(e))
3885  {
3887  return ENTITY_MIN_P(op) || ENTITY_MAX_P(op);
3888  }
3889  return false;
3890 }
3891 
3892 /******************* EXPRESSIONS **********************
3893  * moved there from c_syntax by SG
3894  */
3895 
3897 {
3898 
3901  return exp; /* exp = sizeof(e)*/
3902 }
3903 
3905 {
3908  return exp; /* exp = sizeof(t) */
3909 }
3910 
3912 {
3913  syntax s = make_syntax_cast(make_cast(t,e));
3915  return exp; /* exp = (t) e */
3916 }
3917 
3919 {
3920  if (ENDP(l))
3921  return expression_undefined;
3922  if (gen_length(l)==1)
3923  return EXPRESSION(CAR(l));
3925 }
3926 
3928 {
3930 }
3931 
3932 /* generate a newly allocated expression for *(e)
3933  */
3935 {
3936  if (expression_call_p(e))
3937  {
3938  call c = expression_call(e);
3939  if (ENTITY_ADDRESS_OF_P(call_function(c))) // e is "&x"
3940  {
3941  pips_assert("one arg to address operator (&)",
3942  gen_length(call_arguments(c))==1);
3943 
3944  // result is simply "x"
3946  }
3947  }
3948 
3949  // result is "*e"
3951  copy_expression(e));
3952 }
3953 
3954 /* generate a newly allocated expression for &(e)
3955  */
3957 {
3958  if (expression_call_p(e))
3959  {
3960  call c = expression_call(e);
3961  if (ENTITY_DEREFERENCING_P(call_function(c))) // e is "*x"
3962  {
3963  pips_assert("one arg to address operator (&)",
3964  gen_length(call_arguments(c))==1);
3965 
3966  // result is simply "x"
3968  }
3969  }
3970 
3971  // result is "*e"
3973  copy_expression(e));
3974 }
3975 
3976 
3977 
3978 /* make a full copy of the subscript expression list, preserve
3979  constant subscripts, replace non-constant subscript by the star
3980  subscript expression. */
3982 {
3983  list nsl = NIL;
3984 
3985  FOREACH(EXPRESSION, s, sl){
3987  value v = EvalExpression(s);
3989  int i = constant_int(value_constant(v));
3990  ni = int_to_expression(i);
3991  }
3992  else {
3994  }
3995  nsl = CONS(EXPRESSION, ni, nsl);
3996  }
3997  nsl = gen_nreverse(nsl);
3998  return nsl;
3999 }
4000 
4001 
4002 /* Assume p is a pointer. Compute expression "*(p+i)" from reference
4003  r = "p[i]". */
4005 {
4006  entity p = reference_variable(r);
4008  list rsl = reference_indices(r);
4009  int p_d = variable_dimension_number(type_variable(t)); // pointer dimension
4010  int r_d = (int) gen_length(rsl); // reference dimension
4011 
4012  pips_assert("The reference dimension is strictly greater than "
4013  "the array of pointers dimension", r_d>p_d);
4014 
4015  /* rsl is fully copied into two sub-lists: the effective array
4016  indices and then the pointer indices. */
4017  list esl = NIL;
4018  list psl = NIL;
4019  list crsl = rsl;
4020  int i;
4021  for(i = 0; i<r_d; i++) {
4022  expression se = EXPRESSION(CAR(crsl));
4023  i<p_d? (esl = CONS(EXPRESSION, copy_expression(se), esl))
4024  : (psl = CONS(EXPRESSION, copy_expression(se), psl));
4025  POP(crsl);
4026  }
4027  esl = gen_nreverse(esl), psl = gen_nreverse(psl);
4028 
4029  pips_assert("The pointer index list is not empty", !ENDP(psl));
4030 
4031  /* We build a proper reference to an element of p */
4032  reference nr = make_reference(p, esl);
4034 
4035  /* We build the equivalent pointer arithmetic expression */
4036  expression pae = nre;
4037  // FI: would be better to compute the two operators before entering the loop
4038  // entity plus = ;
4039  // entity indirection = ;
4040  FOREACH(EXPRESSION, pse, psl) {
4043  }
4044 
4045  return pae;
4046 }
4047 
4048 /* Reuse expression e to build expression *(e) without cheking the
4049  * legality of the construct.
4050  */
4052 {
4054 }
4055 
4057 {
4058  bool initialization_p = false;
4059  syntax s = expression_syntax(e);
4060  if(syntax_call_p(s)) {
4061  call c = syntax_call(s);
4062  entity f = call_function(c);
4064  initialization_p = true;
4065  }
4066  return initialization_p;
4067 }
4068 
4069 /* Returns a list of expressions hidden by the brace function.
4070  *
4071  * First cut: FI not too sure about recursive calls to the brace function.
4072  */
4074 {
4075  pips_assert("rhs is a C initialization expression",
4077  syntax s = expression_syntax(e);
4078  call c = syntax_call(s);
4079  list el = call_arguments(c);
4080  return el;
4081 }
4082 
4083 /* Free a list of expressions. */
4085 {
4086  FOREACH(EXPRESSION,e, el)
4087  free_expression(e);
4088 }
4089 
4090 // moved from instrumentation
4091 /* hack: clean all normalize fields...
4092  */
4093 static void expr_rwt(expression e)
4094 {
4096  {
4099  }
4100 }
4101 
4103 {
4105 }
4106 
4107 
4108 /*****************************************************************************
4109  This function computes the subscript value of an array element
4110  minus 1, multiplied by the size of array element.
4111 
4112  [subscript_value(array_element)-1]*array_element_size
4113 
4114  DIMENSION A(l1:u1,...,ln:un)
4115  subscript_value(A(s1,s2,...,sn)) =
4116  1+(s1-l1)+(s2-l2)*(u1-l1+1)+...+ (sn-ln)*(u1-l1+1)*...*(u(n-1) -l(n-1)+1)
4117 
4118  Input : the entity A
4119  the indice list (s1,s2,..sn)
4120  Output : [subscript_value(A(s1,..sn))-1]*array_element_size
4121 
4122  If l_inds = NIL => return int_to_expression(0)
4123  If si = li for all i => return int_to_expression(0)
4124 
4125 *****************************************************************************/
4126 
4128 {
4129  expression retour = int_to_expression(0);
4130  if (!ENDP(l_inds))
4131  {
4132  variable var = type_variable(entity_type(arr));
4134  list l_dims = variable_dimensions(var);
4135  int num_dim = gen_length(l_inds),i;
4138  for (i=1; i<= num_dim; i++)
4139  {
4140  dimension dim_i = find_ith_dimension(l_dims,i);
4141  expression lower_i = dimension_lower(dim_i);
4142  expression sub_i = find_ith_argument(l_inds,i);
4143  expression upper_i = dimension_upper(dim_i);
4144  expression size_i;
4145  if ( expression_constant_p(lower_i) && (expression_to_int(lower_i)==1))
4146  size_i = copy_expression(upper_i);
4147  else
4148  {
4149  size_i = binary_intrinsic_expression(
4150  MINUS_OPERATOR_NAME, upper_i, lower_i);
4151  size_i = binary_intrinsic_expression(
4153  }
4154  if (!same_expression_p(sub_i,lower_i))
4155  {
4156  expression sub_low_i =
4158  expression elem_i;
4159  if (expression_undefined_p(prod))
4160  elem_i = copy_expression(sub_low_i);
4161  else
4163  sub_low_i,prod);
4164  if (expression_equal_integer_p(retour,0))
4165  retour = copy_expression(elem_i);
4166  else
4168  retour, elem_i);
4169  }
4170  if (expression_undefined_p(prod))
4171  prod = copy_expression(size_i);
4172  else
4174  prod,size_i);
4175  }
4176  if (!expression_equal_integer_p(retour,0))
4177  retour = binary_intrinsic_expression(
4178  MULTIPLY_OPERATOR_NAME, copy_expression(retour), e_size);
4179  }
4180  // FI: to avoid cycles between librairies ri-util and prettyprint
4181  /* ifdebug(4) */
4182  /* { */
4183  /* pips_debug(4,"\nStride of subscript value:"); */
4184  /* print_expression(retour); */
4185  /* } */
4186  return retour;
4187 }
4188 
4189 
4190 /*****************************************************************************
4191 
4192  This function returns the size of an array, from position i+1, minus the
4193  subscript value of array reference from position i+1:
4194  (D(i+1)*...*Dn - (1+ s(i+1)-l(i+1) + (s(i+2)-l(i+2))*d(i+1)+...-1))
4195 
4196 *****************************************************************************/
4198  entity actual_array, list l_actual_ref, int i)
4199 {
4201  variable actual_var = type_variable(entity_type(actual_array));
4202  list l_actual_dims = variable_dimensions(actual_var);
4203  int num_dim = gen_length(l_actual_dims), j;
4204  for (j=i+1; j<= num_dim; j++)
4205  {
4206  dimension dim_j = find_ith_dimension(l_actual_dims,j);
4207  expression lower_j = dimension_lower(dim_j);
4208  expression upper_j = dimension_upper(dim_j);
4209  expression size_j;
4210  if (expression_constant_p(lower_j) && (expression_to_int(lower_j)==1))
4211  size_j = copy_expression(upper_j);
4212  else
4213  {
4214  size_j = binary_intrinsic_expression(MINUS_OPERATOR_NAME,upper_j,lower_j);
4216  copy_expression(size_j),int_to_expression(1));
4217  }
4218  if (expression_undefined_p(e))
4219  e = copy_expression(size_j);
4220  else
4222  }
4223  // FI: to avoid cycles between librairies ri-util and prettyprint
4224  /* ifdebug(3) */
4225  /* { */
4226  /* fprintf(stderr, "\n Size of actual array without subscript value \n"); */
4227  /* print_expression(e); */
4228  /* } */
4229  if (l_actual_ref!=NIL)
4230  {
4231  // the actual argument is an array element name,
4232  // we have to compute the subscript value also
4234  ifdebug(3)
4235  fprintf(stderr, "\n actual argument is an array element name:");
4236  for (j=i+1; j<= num_dim; j++)
4237  {
4238  dimension dim_j = find_ith_dimension(l_actual_dims,j);
4239  expression lower_j = dimension_lower(dim_j);
4240  expression sub_j = find_ith_argument(l_actual_ref,j);
4241  expression upper_j = dimension_upper(dim_j);
4242  expression size_j,sub_low_j,elem_j;
4243  if ( expression_constant_p(lower_j) && (expression_to_int(lower_j)==1))
4244  size_j = copy_expression(upper_j);
4245  else
4246  {
4247  size_j = binary_intrinsic_expression(
4248  MINUS_OPERATOR_NAME, upper_j, lower_j);
4249  size_j = binary_intrinsic_expression(
4251  }
4252  // CAUTION : heuristic
4253  // We can distinguish or not the special case: lower_bound = subscript,
4254  // 1. If not, we do not lose information such as in SPEC95/applu.f :
4255  // real u(5,33,33,33)
4256  // call exact(i,j,1,u(1,i,j,1))
4257  // => size = 5.33.33.33 -((i-1)5 +(j-1)5.33 +(k-1)5.33.33),
4258  // not 5.33.33.33 -((i-1)5 +(j-1)5.33) (as k=1)
4259  // subroutine exact(i,j,k,u000ijk)
4260  // We will have more combinations, but more chance to translate
4261  // the size of actual array to the callee's frame
4262  // 2. If yes, there are so much combinations =>
4263  // it takes long time to compute, such as in SPEC95/turb3d.f
4264  // CONCLUSION : for time efficiency, we distinguish this case
4265  if (!same_expression_p(sub_j,lower_j))
4266  {
4268  sub_j,lower_j);
4269  if (expression_undefined_p(prod))
4270  elem_j = copy_expression(sub_low_j);
4271  else
4273  sub_low_j,prod);
4275  sum = copy_expression(elem_j);
4276  else
4278  sum, elem_j);
4279  }
4280  if (expression_undefined_p(prod))
4281  prod = copy_expression(size_j);
4282  else
4284  prod,size_j);
4285  // FI: to avoid cycles between librairies ri-util and prettyprint
4286  /* ifdebug(4) */
4287  /* { */
4288  /* fprintf(stderr, "\n j = %d \n",j); */
4289  /* fprintf(stderr, "\n prod : \n"); */
4290  /* print_expression(prod); */
4291  /* fprintf(stderr, "\n sum =: \n"); */
4292  /* print_expression(sum); */
4293  /* } */
4294  }
4296  {
4298  copy_expression(e),sum);
4299  // FI: to avoid cycles between librairies ri-util and prettyprint
4300  /* ifdebug(2) */
4301  /* { */
4302  /* fprintf(stderr, "\n Size of actual array - subscript value : \n"); */
4303  /* print_expression(e); */
4304  /* } */
4305  }
4306  }
4307  // FI: to avoid cycles between librairies ri-util and prettyprint
4308  /* ifdebug(2) */
4309  /* { */
4310  /* fprintf(stderr, "\n Size of actual array:\n"); */
4311  /* print_expression(e); */
4312  /* } */
4313  return e;
4314 }
4315 
4317 {
4319  make_reference(ent, args)),
4321 }
4322 
4324 {
4325  const char* n = entity_local_name(f);
4327 }
4328 
4330 {
4331  syntax s = expression_syntax(e);
4332  if (syntax_call_p(s)) {
4334  return unbounded_entity_p(f);
4335  }
4336  return false;
4337 }
4338 
4340 {
4342 }
4343 
4344 /* FI: this piece of code must have been duplicated somewhere else in
4345  an effect library */
4347 {
4348  list sl = NIL;
4349  int i;
4350 
4351  for(i=0; i<d; i++) {
4353  }
4354 
4355  return sl;
4356 }
4357 
4358 /**
4359  * Test if a call is a user call
4360  */
4362  entity f = call_function(c);
4363  value v = entity_initial(f);
4364  return value_code_p(v);
4365 }
4366 ␌
4367 /* Normalization of subscript in expressions.
4368  *
4369  * The C parser generates no more than one index in each subscript construct:
4370  *
4371  * subscript = array:expression x indices:expression* ;
4372  * syntax = reference + range + call + cast + sizeofexpression
4373  * + subscript + application + va_arg:sizeofexpression* ;
4374  * expression = syntax x normalized ;
4375  *
4376  * If the array expression points to a multidimensional array, the
4377  * indices list should be as long as possible, compatible with the
4378  * array dimension.
4379  *
4380  * e (expression)
4381  * |
4382  * es (syntax)
4383  * |
4384  * esub (subscript)
4385  * / \
4386  * / \
4387  * a il -> -> (indices list)
4388  * | \
4389  * as \
4390  * | \
4391  * asub \
4392  * / \ \
4393  * / \ \
4394  * sa sil -> -> ->
4395  *
4396  * The recursive normalization function works bottom up and, when
4397  * facing the pattern above, concatenate the il index list (or a
4398  * sublist) to the sil list. If the il list becomes empty, e is
4399  * connected directly to as and the pieces of data structure es, esub
4400  * and a are removed.
4401  *
4402  * gen_recurse() is used to apply the transformation on the way up in
4403  * expression trees. In the C parser, the transformation is applied to
4404  * a module statement and to the initialization expressions present in
4405  * the declarations.
4406  */
4408 {
4409  syntax es = expression_syntax(e);
4410  if(syntax_subscript_p(es)) {
4411  subscript esub = syntax_subscript(es);
4412  expression a = subscript_array(esub);
4413  syntax as = expression_syntax(a);
4414  if(syntax_subscript_p(as)) {
4415  subscript asub = syntax_subscript(as);
4416  // FI: bad, imported from effects-util :-( We could use
4417  // expression_to_type and then convert it into a concrete type
4418  //extern type points_to_expression_to_concrete_type(expression);
4419  // type t = points_to_expression_to_concrete_type(a);
4421  // This might be wrong: a is likely to be a pointer to a sub-array
4422  // or a pointer to a scalar for 1D array.
4423  if(pointer_type_p(t) || array_type_p(t)) { // FI: should always be true for a subscript?
4424  int nm = 0;
4425  if(pointer_type_p(t)) {
4426  type et = type_to_pointed_type(t);
4427  nm = (int) array_type_dimension(et) + 1;
4428  }
4429  else
4430  nm = (int) array_type_dimension(t);
4431  //list sil = subscript_indices(asub);
4432  // int nsi = (int) gen_length(sil);
4433  // FI: the efficient way would be to cut of the il list into two
4434  // parts and to use only one call to gen_nconc()
4435  list il = subscript_indices(esub);
4436  for(int i=0;i<nm && !ENDP(il); i++) {
4437  list ni = il; // new index/subscript
4438  POP(il);
4439  CDR(ni) = NIL;
4440  subscript_indices(asub) =
4441  gen_nconc(subscript_indices(asub), ni);
4442  }
4443  if(ENDP(il)) {
4444  // The top subscript can be removed
4445  expression_syntax(e) = as;
4447  subscript_indices(esub) = NIL;
4448  free_syntax(es);
4449  }
4450  else if(il!=subscript_indices(esub)) {
4451  // Update the new index list with the remaining indices
4452  subscript_indices(esub) = il;
4453  }
4454  else {
4455  // No restructuring
4456  ;
4457  }
4458  }
4459  free_type(t);
4460  }
4461  }
4462 }
4463 
4464 /* To be used for initialization expressions */
4466 {
4468 }
4469 
4470 /* To be used for module statements */
4472 {
4474 }
static hash_table seen
static function to store whether a module has been seen during the recursive generation of the daVinc...
Definition: graph.c:85
void free_normalized(normalized p)
Definition: ri.c:1407
list gen_expression_cons(expression p, list l)
Definition: ri.c:866
cast make_cast(type a1, expression a2)
Definition: ri.c:311
call make_call(entity a1, list a2)
Definition: ri.c:269
sizeofexpression make_sizeofexpression_expression(expression _field_)
Definition: ri.c:2180
syntax make_syntax_call(call _field_)
Definition: ri.c:2500
expression make_expression(syntax a1, normalized a2)
Definition: ri.c:886
subscript make_subscript(expression a1, list a2)
Definition: ri.c:2327
syntax make_syntax_sizeofexpression(sizeofexpression _field_)
Definition: ri.c:2506
type copy_type(type p)
TYPE.
Definition: ri.c:2655
void free_reference(reference p)
Definition: ri.c:2050
basic copy_basic(basic p)
BASIC.
Definition: ri.c:104
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
sizeofexpression make_sizeofexpression_type(type _field_)
Definition: ri.c:2177
void free_expression(expression p)
Definition: ri.c:853
syntax make_syntax_cast(cast _field_)
Definition: ri.c:2503
void free_type(type p)
Definition: ri.c:2658
void free_syntax(syntax p)
Definition: ri.c:2445
syntax make_syntax(enum syntax_utype tag, void *val)
Definition: ri.c:2491
void free_basic(basic p)
Definition: ri.c:107
constant copy_constant(constant p)
CONSTANT.
Definition: ri.c:359
syntax make_syntax_subscript(subscript _field_)
Definition: ri.c:2509
void free_value(value p)
Definition: ri.c:2787
syntax make_syntax_reference(reference _field_)
Definition: ri.c:2494
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
static FILE * out
Definition: alias_check.c:128
#define value_pos_p(val)
#define value_minus(v1, v2)
#define value_absolute(ref)
#define value_gt(v1, v2)
#define VALUE_TO_INT(val)
#define value_pdiv(v1, v2)
#define value_le(v1, v2)
#define value_notzero_p(val)
void const char const char const int
#define value_one_p(val)
#define value_negz_p(val)
#define value_zero_p(val)
int Value
#define ABS(x)
was: #define value_mult(v,w) value_direct_multiply(v,w) #define value_product(v,w) value_direct_produ...
#define VALUE_ONE
#define value_abs(val)
#define value_neg_p(val)
#define value_posz_p(val)
bool constant_string_entity_p(entity e)
Definition: constant.c:356
bool integer_constant_p(entity ent, int *int_p)
Returns the double value associated to a PIPS constant.
Definition: constant.c:542
entity float_to_entity(float c)
Definition: constant.c:430
entity MakeConstant(string name, tag bt)
Make a Fortran constant.
Definition: constant.c:351
expression MakeComplexConstantExpression(expression r, expression i)
Definition: constant.c:397
bool integer_symbolic_constant_p(entity ent, int *int_p)
(*int_p) gets integer constant if any
Definition: constant.c:556
entity int_to_entity(_int c)
Definition: constant.c:453
int compare_Pvecteur(Pvecteur *pv1, Pvecteur *pv2)
comparison function for Pvecteur in pips, to be used by qsort.
Definition: constraint.c:50
bool vect_constant_p(Pvecteur)
bool vect_constant_p(Pvecteur v): v contains only a constant term, may be zero
Definition: predicats.c:211
static Value offset
Definition: translation.c:283
string make_entity_fullname(const char *module_name, const char *local_name)
END_EOLE.
Definition: entity_names.c:230
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
void gen_full_free_list(list l)
Definition: genClib.c:1023
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
bool gen_true2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2785
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#define REFCAR(pc)
Get the adress of the first element of a list.
Definition: newgen_list.h:119
#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
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define MAPL(_map_list_cp, _code, _l)
Apply some code on the addresses of all the elements of a list.
Definition: newgen_list.h:203
list gen_append(list l1, const list l2)
Definition: list.c:471
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
#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
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
bool gen_equals(const list l0, const list l1, gen_eq_func_t equals)
compares two lists using the functor given in parameters returns true if for all n,...
Definition: list.c:192
statement make_assign_statement(expression, expression)
Definition: statement.c:583
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
void hash_put(hash_table htp, const void *key, const void *val)
This functions stores a couple (key,val) in the hash table pointed to by htp.
Definition: hash.c:364
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
static list indices
Definition: icm.c:204
static void term(Pproblem XX, int s, Value k, int x)
Definition: isolve.c:315
bool vect_equal(Pvecteur v1, Pvecteur v2)
bool vect_equal(Pvecteur v1, Pvecteur v2): test a egalite de deux vecteurs
Definition: reductions.c:278
int vect_size(Pvecteur v)
package vecteur - reductions
Definition: reductions.c:47
#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 pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define user_error(fn,...)
Definition: misc-local.h:265
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
#define LIST_DIRECTED_FORMAT_NAME
Definition: naming-local.h:97
#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
#define assert(ex)
Definition: newgen_assert.h:41
#define message_assert(msg, ex)
Definition: newgen_assert.h:47
string bool_to_string(bool)
Definition: string.c:243
@ hash_string
Definition: newgen_hash.h:32
@ hash_pointer
Definition: newgen_hash.h:32
#define HASH_DEFAULT_SIZE
Definition: newgen_hash.h:26
#define same_string_p(s1, s2)
void * gen_find_tabulated(const char *, int)
Definition: tabulated.c:218
int tag
TAG.
Definition: newgen_types.h:92
intptr_t _int
_INT
Definition: newgen_types.h:53
uintptr_t _uint
Definition: newgen_types.h:54
bool(* gen_eq_func_t)(const void *, const void *)
Definition: newgen_types.h:115
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
normalized normalize_reference(reference r)
Definition: normalize.c:592
void unnormalize_expression(void *st)
void unnormalize_expression(expression exp): puts all the normalized field of expressions in "st" to ...
Definition: normalize.c:452
Ppolynome make_polynome(float coeff, Variable var, Value expo)
Ppolynome make_polynome(float coeff, Variable var, Value expo) PRIVATE allocates space for,...
Definition: pnome-alloc.c:100
void polynome_rm(Ppolynome *ppp)
void polynome_rm(Ppolynome* ppp) frees space occupied by polynomial *ppp returns *ppp pointing to POL...
Definition: pnome-alloc.c:170
Ppolynome polynome_div(Ppolynome pp1, Ppolynome pp2)
Ppolynome polynome_div(Ppolynome pp1, Ppolynome pp2) returns p = pp1 / pp2.
Definition: pnome-bin.c:381
Ppolynome polynome_mult(Ppolynome pp1, Ppolynome pp2)
Ppolynome polynome_mult(Ppolynome pp1, Ppolynome pp2) returns pp1 * pp2.
Definition: pnome-bin.c:287
void polynome_add(Ppolynome *ppp, Ppolynome pp2)
void polynome_add(Ppolynome* ppp, Ppolynome pp2) (*ppp) = (*ppp) + pp2.
Definition: pnome-bin.c:171
void polynome_negate(Ppolynome *ppp)
void polynome_negate(Ppolynome *ppp); changes sign of polynomial *ppp.
Definition: pnome-unaires.c:45
#define POLYNOME_UNDEFINED
#define POLYNOME_UNDEFINED_P(pp)
#define monome_term(pm)
#define MONOME_UNDEFINED_P(pm)
#define polynome_monome(pp)
#define monome_coeff(pm)
Macros definitions.
#define POLYNOME_NUL_P(pp)
#define polynome_succ(pp)
bool symbol_table(const char *)
To replace c_symbol_table() and fortran_symbol_table() because the information about the language is ...
Definition: symbol_table.c:673
static bool constant_p(entity e)
This function return a bool indicating if related entity e represents a constant.
#define UNBOUNDED_DIMENSION_NAME
Definition: ri-util-local.h:74
#define make_expression_list(stats...)
#define ENTITY_OR_P(e)
#define MAX_OPERATOR_NAME
#define POWER_OPERATOR_NAME
#define CABS_OPERATOR_NAME
#define ENTITY_DIVIDE_P(e)
#define ENTITY_RELATIONAL_OPERATOR_P(e)
#define ABS_OPERATOR_NAME
#define ENTITY_AND_P(e)
#define ENTITY_NON_EQUAL_P(e)
#define binary_call_rhs(c)
#define ENTITY_EQUAL_P(e)
#define ENTITY_FIVE_OPERATION_P(e)
#define MINUS_OPERATOR_NAME
#define ENTITY_MINUS_P(e)
#define ENTITY_COMMA_P(e)
#define ENTITY_UNARY_MINUS_P(e)
#define IABS_OPERATOR_NAME
#define ENTITY_DEREFERENCING_P(e)
#define COMMA_OPERATOR_NAME
#define PLUS_OPERATOR_NAME
#define ENTITY_PLUS_P(e)
#define ENTITY_LESS_THAN_P(e)
#define ENTITY_MULTIPLY_P(e)
#define NORMALIZE_EXPRESSION(e)
#define MAX0_OPERATOR_NAME
#define DEREFERENCING_OPERATOR_NAME
Definition: ri-util-local.h:93
#define MIN0_OPERATOR_NAME
#define entity_symbolic_p(e)
#define FIELD_OPERATOR_NAME
Definition: ri-util-local.h:91
#define ENTITY_BRACE_INTRINSIC_P(e)
C initialization expression.
#define ENTITY_CONDITIONAL_P(e)
#define expression_scalar_p(e)
#define unary_intrinsic_expression(name, e)
Building quickly bool expressions, FC.
#define IMPLIED_DO_NAME
Definition: ri-util-local.h:75
#define CONDITIONAL_OPERATOR_NAME
#define FALSE_OPERATOR_NAME
#define ENTITY_NOT_P(e)
#define binary_intrinsic_expression(name, e1, e2)
#define AND_OPERATOR_NAME
FI: intrinsics are defined at a third place after bootstrap and effects! I guess the name should be d...
#define ENTITY_PLUS_C_P(e)
#define ENTITY_MAX_P(e)
#define ENTITY_GREATER_THAN_P(e)
#define ADDRESS_OF_OPERATOR_NAME
#define ENTITY_FIELD_P(e)
C data structure and pointer management.
#define ENTITY_UNARY_PLUS_P(e)
#define ENTITY_MINUS_C_P(e)
#define DIVIDE_OPERATOR_NAME
#define ENTITY_NON_EQUIV_P(e)
#define DABS_OPERATOR_NAME
#define UNARY_MINUS_OPERATOR_NAME
#define binary_call_lhs(c)
#define BRACE_INTRINSIC
Definition: ri-util-local.h:85
#define C_LESS_THAN_OPERATOR_NAME
#define ENTITY_MIN_P(e)
#define TRUE_OPERATOR_NAME
#define ENTITY_ADDRESS_OF_P(e)
#define ENTITY_LESS_OR_EQUAL_P(e)
#define make_statement_list(stats...)
easy list constructor
#define MINUS_C_OPERATOR_NAME
#define MULTIPLY_OPERATOR_NAME
#define entity_constant_p(e)
#define ENTITY_GREATER_OR_EQUAL_P(e)
#define ASSIGN_OPERATOR_NAME
Definition: ri-util-local.h:95
#define MODULO_OPERATOR_NAME
#define PIPS_C_DIV_OPERATOR_NAME
#define ENTITY_MODULO_P(e)
#define PLUS_C_OPERATOR_NAME
#define MIN_OPERATOR_NAME
#define ENTITY_EQUIV_P(e)
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
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 commutative_call_p(call c)
Test if we are allowed to commute operations.
Definition: entity.c:2661
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
bool entity_field_p(entity e)
e is the field of a structure
Definition: entity.c:857
entity CreateIntrinsic(string name)
this function does not create an intrinsic function because they must all be created beforehand by th...
Definition: entity.c:1311
bool entity_pointer_p(entity e)
Definition: entity.c:745
bool same_field_entity_p(const entity f1, const entity f2)
Definition: entity.c:1019
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
bool expression_linear_p(expression e)
returns if e is already normalized and linear.
Definition: eval.c:951
value EvalExpression(expression e)
Evaluate statically an expression.
Definition: eval.c:108
value EvalSizeofexpression(sizeofexpression soe)
Definition: eval.c:210
bool expression_integer_value(expression e, intptr_t *pval)
Definition: eval.c:792
bool false_expression_p(expression e)
Definition: expression.c:1118
bool expression_one_p(expression exp)
Definition: expression.c:2591
expression add_integer_to_expression(expression exp, int val)
Definition: expression.c:2132
bool user_function_call_p(expression e)
Definition: expression.c:1068
subscript expression_subscript(expression e)
Definition: expression.c:1843
bool expression_address_of_p(expression e)
Definition: expression.c:420
static list do_brace_expression_to_statements(entity arr, expression e, list curr_indices)
helper for brace_expression_to_statements
Definition: expression.c:3396
expression make_vecteur_expression(Pvecteur pv)
make expression for vector (Pvecteur)
Definition: expression.c:1650
bool reference_with_unbounded_indices_p(reference r)
indices can be constant or unbounded: they are store independent.
Definition: expression.c:3066
bool expression_is_C_rhs_p(expression exp)
Not all expressions can be used as right-hand side (rhs) in C assignments.
Definition: expression.c:2582
bool call_equal_p(call c1, call c2)
Definition: expression.c:1529
bool iabs_expression_p(expression e)
Definition: expression.c:1036
list struct_initialization_expression_to_expressions(expression e)
Returns a list of expressions hidden by the brace function.
Definition: expression.c:4073
expression reference_to_expression(reference r)
Definition: expression.c:196
expression MakeSizeofType(type t)
Definition: expression.c:3904
range expression_range(expression e)
Definition: expression.c:1853
bool unbounded_entity_p(entity f)
Definition: expression.c:4323
bool expression_sizeofexpression_p(expression e)
Definition: expression.c:460
void reference_complete_with_zero_subscripts(reference r)
Reference r to an array maybe partial, as is possible in C: with declaration "int a[10][10]",...
Definition: expression.c:278
expression make_entity_expression(entity e, cons *inds)
Definition: expression.c:176
list syntax_to_reference_list(syntax s, list lr)
Definition: expression.c:1270
bool expression_opposite_p(expression e1, expression e2)
e1+e2==0, i.e.
Definition: expression.c:1386
void brace_expression_to_updated_type(entity arr, expression e)
use a brace expression to update the type of array "arr" if the dimensions are implicit
Definition: expression.c:3517
bool expression_integer_constant_p(expression e)
Definition: expression.c:2417
expression make_address_of_expression(expression e)
generate a newly allocated expression for &(e)
Definition: expression.c:3956
bool expression_minmax_p(expression e)
Definition: expression.c:3882
expression expression_verbose_reduction_p_and_return_increment(expression incr, bool filter(expression))
Test if an expression is a verbose reduction of the form : "i = i op v" or "i = v op i".
Definition: expression.c:780
struct ctx_substitute ctx_substitute_t
application expression_application(expression e)
Definition: expression.c:485
bool simplify_expression(expression *pexp)
use polynomials to simplify an expression in some cases this operation can change the basic of the ex...
Definition: expression.c:3770
expression Pvecteur_to_expression(Pvecteur vect)
AP, sep 25th 95 : some usefull functions moved from static_controlize/utils.c.
Definition: expression.c:1825
bool expression_similar_get_context_p(expression target, expression pattern, hash_table *symbol_table)
similar to expression_similar_p but the hash_map containing the crossref value is retured for further...
Definition: expression.c:3339
expression make_constraint_expression(Pvecteur v, Variable index)
Make an expression from a constraint v for a given index.
Definition: expression.c:1748
bool min0_expression_p(expression e)
Definition: expression.c:1054
void clean_all_normalized(expression e)
Definition: expression.c:4102
expression MakeBraceExpression(list l)
Definition: expression.c:3927
bool expression_field_p(expression e)
The expression is of kind "s.a", where "s" is a struct and a "a" field.
Definition: expression.c:491
bool logical_operator_expression_p(expression e)
C xor is missing.
Definition: expression.c:573
bool substraction_expression_p(expression e)
Test if an expression is an substraction.
Definition: expression.c:1000
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
void davinci_dump_expression(FILE *out, expression e)
dump expression e in file out as a davinci graph.
Definition: expression.c:2710
bool expression_list_directed_p(e)
Definition: expression.c:844
expression make_lin_op_exp(entity op_ent, expression exp1, expression exp2)
================================================================
Definition: expression.c:2147
void normalize_subscript_expression(expression e)
Normalization of subscript in expressions.
Definition: expression.c:4407
list make_unbounded_subscripts(int d)
FI: this piece of code must have been duplicated somewhere else in an effect library.
Definition: expression.c:4346
bool extended_integer_constant_expression_p(expression e)
More extensive than next function.
Definition: expression.c:858
reference expression_to_reference(expression e)
Definition: expression.c:212
bool zero_expression_p(expression e)
Definition: expression.c:1217
bool expression_constant_p(expression exp)
================================================================
Definition: expression.c:2453
expression expressions_to_operation(const list l_exprs, entity op)
take a list of expression and apply a binary operator between all of them and return it as an express...
Definition: expression.c:3544
bool expression_call_p(expression e)
Definition: expression.c:415
expression substitute_entity_variable_in_expression(entity old, entity new, expression e)
(This function isn't use for the moment) This function replaces all the occurrences of an old entity ...
Definition: expression.c:2772
void reference_add_zero_subscripts(reference r, type t)
Definition: expression.c:261
list expressions_to_entities(list expressions)
map expression_to_entity on expressions
Definition: expression.c:3161
int expression_to_int(expression exp)
================================================================
Definition: expression.c:2205
expression make_unbounded_expression()
Definition: expression.c:4339
int trivial_expression_p(expression e)
This function returns:
Definition: expression.c:679
bool true_expression_p(expression e)
Definition: expression.c:1113
expression MakeCommaExpression(list l)
Definition: expression.c:3918
bool call_constant_p(call c)
bool call_constant_p(call c): Returns true if "c" is a call to a constant, that is,...
Definition: expression.c:1965
expression monome_to_expression(Pmonome pm)
converts a monome to an expression
Definition: expression.c:3589
bool reference_with_unbounded_subscript_p(reference r)
See if the reference uses the unbounded function '*'.
Definition: expression.c:3085
bool expression_cast_p(expression e)
Definition: expression.c:450
expression float_to_expression(float c)
Definition: expression.c:1229
expression make_min_expression(expression e1, expression e2, enum language_utype lang)
Definition: expression.c:1600
expression make_call_expression(entity e, list l)
Build an expression that call an function entity with an argument list.
Definition: expression.c:321
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
bool expression_subscript_p(expression e)
Definition: expression.c:1838
static void substitute_variable_in_reference(reference r, ctx_substitute_t *ctx)
Definition: expression.c:2741
constant expression_constant(expression exp)
This function returns a "constant" object if the expression is a constant such as 10,...
Definition: expression.c:2347
static void expr_rwt(expression e)
hack: clean all normalize fields...
Definition: expression.c:4093
expression make_factor_expression(int coeff, entity vari)
Some functions to generate expressions from vectors and constraint systems.
Definition: expression.c:1631
bool max0_expression_p(expression e)
Definition: expression.c:1061
bool expression_equal_or_opposite_p(expression e1, expression e2)
e1==e2 or -e1==e2 or e1==-e2 syntactically
Definition: expression.c:1366
statement Pvecteur_to_assign_statement(entity var, Pvecteur v)
generates var = linear expression from the Pvecteur.
Definition: expression.c:1720
bool expression_string_constant_p(expression exp)
Definition: expression.c:2398
bool expression_null_p(expression exp)
returns true if the expression is equal to zero or NULL (even if there is a cast before such as in (v...
Definition: expression.c:2611
bool field_expression_p(expression e)
The expression is of kind "a", where "a" is a field of some struct "s".
Definition: expression.c:498
bool extended_integer_constant_expression_p_to_int(expression e, int *result)
Definition: expression.c:874
void local_assign_expression(expression caller, expression field)
replace expression caller by expression field , where field is contained by caller
Definition: expression.c:3571
#define ALREADY_SEEN(node)
Definition: expression.c:2631
bool syntax_equal_p(syntax s1, syntax s2)
Definition: expression.c:1462
expression expression_list_to_binary_operator_call(list l, entity op)
Definition: expression.c:1917
static void do_simplify_expressions(call c)
Definition: expression.c:3794
expression MakeBinaryCall(entity f, expression eg, expression ed)
Creates a call expression to a function with 2 arguments.
Definition: expression.c:354
bool expression_brace_p(expression e)
predicates and short cut accessors on expressions
Definition: expression.c:407
bool subscript_equal_p(subscript s1, subscript s2)
Definition: expression.c:1495
expression replace_expression_content(expression e1, expression e2)
Use side effects to move the content of e2, s2 and n2, into e1; s1 and n1 are freed,...
Definition: expression.c:3864
expression make_zero_expression(void)
Make a zero expression.
Definition: expression.c:1212
expression size_of_actual_array(entity actual_array, list l_actual_ref, int i)
Definition: expression.c:4197
bool expression_equal_p(expression e1, expression e2)
Syntactic equality e1==e2.
Definition: expression.c:1347
void reference_add_zero_subscript(reference r)
No check on reference r.
Definition: expression.c:267
call expression_call(expression e)
Definition: expression.c:445
expression expression_list_to_conjonction(list l)
Definition: expression.c:1937
void update_expression_syntax(expression e, syntax s)
frees expression syntax of e and replace it by the new syntax s
Definition: expression.c:3564
reference add_subscript_to_reference(reference r, expression s)
Add a last subscript expression s to a reference r.
Definition: expression.c:224
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
cast expression_cast(expression e)
Definition: expression.c:455
void expression_normalize_subscripts(expression e)
To be used for initialization expressions.
Definition: expression.c:4465
bool expression_pointer_p(expression e)
we get the type of the expression by calling expression_to_type() which allocates a new one.
Definition: expression.c:506
expression MakeSizeofExpression(expression e)
Definition: expression.c:3896
bool brace_expression_p(expression e)
Return bool indicating if expression e is a brace expression.
Definition: expression.c:3384
expression make_op_exp(char *op_name, expression exp1, expression exp2)
================================================================
Definition: expression.c:2012
bool logical_expression_p(expression e)
Definition: expression.c:610
bool dabs_expression_p(expression e)
Definition: expression.c:1042
int fortran_string_compare(string fs1, string fs2)
compare pips fortran string constants from the fortran point of view.
Definition: expression.c:101
static FILE * out_flt
Definition: expression.c:2719
expression make_subscript_expression(expression a, list sl)
Definition: expression.c:397
expression expression_to_dereferencing_expression(expression e)
Reuse expression e to build expression *(e) without cheking the legality of the construct.
Definition: expression.c:4051
expression substitute_entity_in_expression(entity old, entity new, expression e)
This function replaces all the occurences of an old entity in the expression exp by the new entity.
Definition: expression.c:2792
expression find_ith_argument(list args, int n)
Definition: expression.c:1147
bool add_expression_p(expression e)
Test if an expression is an addition.
Definition: expression.c:986
bool references_do_not_conflict_p(reference r1, reference r2)
If true is returned, the two references cannot conflict unless array bound declarations are violated.
Definition: expression.c:1888
bool user_call_p(call c)
Test if a call is a user call.
Definition: expression.c:4361
bool integer_expression_p(expression e)
Definition: expression.c:601
expression MakeNullaryCall(entity f)
Creates a call expression to a function with zero arguments.
Definition: expression.c:331
expression Value_to_expression(Value v)
added interface for linear stuff.
Definition: expression.c:1251
bool reference_equal_p(reference r1, reference r2)
Definition: expression.c:1500
bool unbounded_dimension_p(dimension dim)
bool unbounded_dimension_p(dim) input : a dimension of an array entity.
Definition: expression.c:1130
bool assignment_expression_p(expression e)
Test if an expression is an assignment operation.
Definition: expression.c:979
bool cabs_expression_p(expression e)
Definition: expression.c:1048
expression find_ith_expression(list le, int r)
find_ith_expression() is obsolet; use find_ith_argument() instead
Definition: expression.c:1161
bool expression_equal_in_list_p(expression e, list le)
This function returns true, if there exists an expression equal in the list false,...
Definition: expression.c:566
bool integer_constant_expression_p(expression e)
positive integer constant expression: call to a positive constant or to a sum of positive integer con...
Definition: expression.c:903
bool comma_expression_p(expression e)
Definition: expression.c:830
bool signed_integer_constant_expression_p(expression e)
Definition: expression.c:932
bool modulo_expression_p(expression e)
Definition: expression.c:1006
expression convert_bound_expression(expression e, bool upper_p, bool non_strict_p)
Replace a C expression used as FOR bound by a Fortran DO bound expression, taking into account the C ...
Definition: expression.c:2968
bool array_argument_p(expression e)
Definition: expression.c:513
expression MakeCastExpression(type t, expression e)
Definition: expression.c:3911
expression make_contrainte_expression(Pcontrainte pc, Variable index)
A wrapper around make_constraint_expression() for compatibility.
Definition: expression.c:1815
expression make_false_expression()
Definition: expression.c:1108
void reference_add_unbounded_subscripts(reference r, type t)
Definition: expression.c:300
bool expression_application_p(expression e)
Duplicate bool expression_subscript_p(expression e) { return(syntax_subscript_p(expression_syntax(e))...
Definition: expression.c:480
bool unary_minus_expression_p(expression e)
Definition: expression.c:1030
static bool _expression_similar_p(expression target, expression pattern, hash_table symbols)
perform the real similarity comparaison between two expressions target is matched against pattern,...
Definition: expression.c:3180
bool sizeofexpression_equal_p(sizeofexpression s0, sizeofexpression s1)
Definition: expression.c:1446
bool expression_intrinsic_operation_p(expression exp)
bool expression_intrinsic_operation_p(expression exp): Returns true if "exp" is an expression with a ...
Definition: expression.c:1949
list make_list_of_constant(int val, int number)
of expression
Definition: expression.c:3369
expression subscript_value_stride(entity arr, list l_inds)
Definition: expression.c:4127
expression MakeUnaryCall(entity f, expression a)
Creates a call expression to a function with one argument.
Definition: expression.c:342
void statement_normalize_subscripts(statement s)
To be used for module statements.
Definition: expression.c:4471
sizeofexpression expression_sizeofexpression(expression e)
Definition: expression.c:465
bool array_reference_p(reference r)
predicates on references
Definition: expression.c:1861
expression make_ref_expr(entity ent, list args)
Definition: expression.c:4316
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
bool cast_equal_p(cast c1, cast c2)
Definition: expression.c:1455
bool expression_equal_integer_p(expression exp, int i)
================================================================
Definition: expression.c:1977
Ppolynome expression_to_polynome(expression exp)
===========================================================================
Definition: expression.c:3650
bool store_independent_reference_p(reference r)
Does this reference define the same set of memory locations regardless of the current (environment an...
Definition: expression.c:3108
static string actual_fortran_string_to_compare(string fs, int *plength)
quite lazy...
Definition: expression.c:54
expression make_max_expression(expression e1, expression e2, enum language_utype lang)
Definition: expression.c:1579
bool unbounded_expression_p(expression e)
Definition: expression.c:4329
bool simplify_C_expression(expression e)
Replace C operators "+C" and "-C" which can handle pointers by arithmetic operators "+" and "-" when ...
Definition: expression.c:2814
expression expression_mult(expression ex)
Definition: expression.c:156
expression make_assign_expression(expression lhs, expression rhs)
Make an assign expression, since in C the assignment is a side effect operator.
Definition: expression.c:390
bool reference_with_constant_indices_p(reference r)
Definition: expression.c:3022
void free_expressions(list el)
Free a list of expressions.
Definition: expression.c:4084
void generic_reference_add_fixed_subscripts(reference r, type t, bool zero_p)
Add a set of zero subscripts to a reference "r" by side effect.
Definition: expression.c:236
void simplify_expressions(void *obj)
Definition: expression.c:3801
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
static bool expr_flt(expression e)
Definition: expression.c:2720
bool expression_with_constant_signed_integer_value_p(expression e)
The expression may be complicated but all its leaves are constants or parameters.
Definition: expression.c:960
bool C_initialization_expression_p(expression e)
Definition: expression.c:4056
expression reference_offset(reference ref)
computes the offset of a C reference with its origin
Definition: expression.c:3807
entity expression_variable(expression e)
Definition: expression.c:532
expression complex_to_expression(float re, float im)
Definition: expression.c:1234
bool range_equal_p(range r1, range r2)
Definition: expression.c:1522
bool relational_expression_p(expression e)
Definition: expression.c:587
expression MakeTernaryCall(entity f, expression e1, expression e2, expression e3)
Creates a call expression to a function with 3 arguments.
Definition: expression.c:367
bool power_expression_p(expression e)
Definition: expression.c:1018
#define DV_YELLOW
Definition: expression.c:2635
float expression_to_float(expression exp)
Same as above for floating point constants.
Definition: expression.c:2305
reference reference_with_store_independent_indices(reference r)
Return by side effect a reference whose memory locations includes the memory locations of r in case t...
Definition: expression.c:3045
bool expression_range_p(expression e)
Definition: expression.c:1848
static void do_brace_expression_to_updated_type(entity arr, expression e, list dl)
helper for brace_expression_to_updated_type
Definition: expression.c:3493
entity expression_to_entity(expression e)
just returns the entity of an expression, or entity_undefined
Definition: expression.c:3140
bool divide_expression_p(expression e)
Definition: expression.c:1012
expression dereference_expression(expression e)
generate a newly allocated expression for *(e)
Definition: expression.c:3934
#define DV_CIRCLE
Definition: expression.c:2634
bool sub_expression_p(expression e)
Definition: expression.c:991
#define SEEN(node)
Definition: expression.c:2632
bool expression_implied_do_p(e)
Definition: expression.c:817
expression pointer_reference_to_expression(reference r)
Assume p is a pointer.
Definition: expression.c:4004
bool reference_scalar_p(reference r)
This function returns true if Reference r is scalar.
Definition: expression.c:3530
list expression_to_reference_list(expression e, list lr)
conversion of an expression into a list of references; references are appended to list lr as they are...
Definition: expression.c:1263
void davinci_dump_all_expressions(FILE *out, statement s)
dump all expressions in s to out.
Definition: expression.c:2728
bool extended_expression_constant_p(expression exp)
Returns true if the value of the expression does not depend syntactically on the current store.
Definition: expression.c:2461
list subscript_expressions_to_constant_subscript_expressions(list sl)
make a full copy of the subscript expression list, preserve constant subscripts, replace non-constant...
Definition: expression.c:3981
bool abs_expression_p(expression e)
Definition: expression.c:1024
expression bool_to_expression(bool b)
Definition: expression.c:1238
expression syntax_to_expression(syntax s)
generates an expression from a syntax
Definition: expression.c:3581
expression polynome_to_expression(Ppolynome pp)
converts a polynomial to expression
Definition: expression.c:3622
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
bool is_expression_reference_to_entity_p(expression e, entity v)
Test if an expression is a reference to a given variable entity.
Definition: expression.c:541
tag suggest_basic_for_expression(expression e)
a BASIC tag is returned for the expression this is a preliminary version.
Definition: expression.c:130
bool expression_similar_p(expression target, expression pattern)
compare if two expressions are similar that is can we exchange target and pattern by substituing vari...
Definition: expression.c:3360
expression make_true_expression()
Definition: expression.c:1103
int signed_integer_constant_expression_value(expression e)
Definition: expression.c:1551
char * expression_string_constant(expression exp)
returns a newly allocated string!
Definition: expression.c:2409
int integer_constant_expression_value(expression e)
Definition: expression.c:1545
static bool davinci_dump_expression_rc(FILE *out, expression e, hash_table seen)
Definition: expression.c:2637
expression call_to_expression(call c)
Build an expression that call a function or procedure.
Definition: expression.c:309
list brace_expression_to_statements(entity arr, expression e)
converts a brace expression used to initialize an array (not a struct yet) into a statement sequence
Definition: expression.c:3480
static void substitute_entity_in_call(call c, ctx_substitute_t *ctx)
Definition: expression.c:2750
bool expression_lists_equal_p(list l1, list l2)
Definition: expression.c:1405
bool operator_expression_p(expression e, string op_name)
Definition: expression.c:1087
bool c_language_module_p(entity m)
Definition: module.c:447
bool const_variable_p(entity)
Definition: variable.c:1687
basic basic_of_expression(expression)
basic basic_of_expression(expression exp): Makes a basic of the same basic as the expression "exp".
Definition: type.c:1383
type ultimate_type(type)
Definition: type.c:3466
bool array_type_p(type)
Definition: type.c:2942
dimension find_ith_dimension(list, int)
This function returns the ith dimension of a list of dimensions.
Definition: type.c:5621
bool variable_length_array_type_p(type)
Is this equivalent to dependent_type_p()?
Definition: type.c:2972
type expression_to_type(expression)
For an array declared as int a[10][20], the type returned for a[i] is int [20].
Definition: type.c:2486
bool entity_scalar_p(entity)
The concrete type of e is a scalar type.
Definition: variable.c:1113
int dimension_size(dimension)
this function computes the size of a dimension.
Definition: size.c:491
type expression_to_concrete_type(expression)
A new type is allocated.
Definition: type.c:3751
type call_to_functional_type(call, bool)
The function called can have a functional type, or a typedef type or a pointer type to a functional t...
Definition: type.c:3824
int variable_dimension_number(variable)
Definition: type.c:5632
bool type_equal_p(type, type)
Definition: type.c:547
bool basic_equal_p(basic, basic)
Definition: type.c:927
type type_to_pointed_type(type)
returns t if t is not a pointer type, and the pointed type if t is a pointer type.
Definition: type.c:5265
type entity_basic_concrete_type(entity)
retrieves or computes and then returns the basic concrete type of an entity
Definition: type.c:3677
bool pointer_type_p(type)
Check for scalar pointers.
Definition: type.c:2993
unsigned int array_type_dimension(type)
Definition: type.c:2947
list struct_type_to_fields(type)
Definition: type.c:5798
_int SizeOfElements(basic)
This function returns the length in bytes of the Fortran or C type represented by a basic,...
Definition: size.c:297
type reference_to_type(reference)
Definition: type.c:2354
bool type_struct_variable_p(type)
Definition: type.c:3867
basic expression_basic(expression)
Definition: type.c:1115
basic basic_maximum(basic, basic)
Definition: type.c:1816
#define type_functional_p(x)
Definition: ri.h:2950
#define value_tag(x)
Definition: ri.h:3064
@ is_basic_overloaded
Definition: ri.h:574
@ is_basic_int
Definition: ri.h:571
@ is_basic_logical
Definition: ri.h:573
#define value_code_p(x)
Definition: ri.h:3065
#define normalized_undefined
Definition: ri.h:1745
#define syntax_reference_p(x)
Definition: ri.h:2728
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define functional_result(x)
Definition: ri.h:1444
#define REFERENCE(x)
REFERENCE.
Definition: ri.h:2296
#define basic_complex_p(x)
Definition: ri.h:626
#define value_constant(x)
Definition: ri.h:3073
#define basic_int_p(x)
Definition: ri.h:614
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#define normalized_complex_p(x)
Definition: ri.h:1782
#define normalized_linear_p(x)
Definition: ri.h:1779
#define call_function(x)
Definition: ri.h:709
#define EXPRESSION_(x)
Definition: ri.h:1220
#define reference_variable(x)
Definition: ri.h:2326
#define SIZEOFEXPRESSION(x)
SIZEOFEXPRESSION.
Definition: ri.h:2364
#define sizeofexpression_type(x)
Definition: ri.h:2406
#define range_upper(x)
Definition: ri.h:2290
#define reference_undefined_p(x)
Definition: ri.h:2303
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define symbolic_constant(x)
Definition: ri.h:2599
#define constant_int(x)
Definition: ri.h:850
#define syntax_call_p(x)
Definition: ri.h:2734
#define sizeofexpression_expression(x)
Definition: ri.h:2409
#define syntax_cast(x)
Definition: ri.h:2739
#define type_functional(x)
Definition: ri.h:2952
#define syntax_application(x)
Definition: ri.h:2748
#define dimension_lower(x)
Definition: ri.h:980
#define syntax_va_arg(x)
Definition: ri.h:2751
#define basic_tag(x)
Definition: ri.h:613
#define type_variable(x)
Definition: ri.h:2949
@ is_value_intrinsic
Definition: ri.h:3034
@ is_value_unknown
Definition: ri.h:3035
@ is_value_expression
Definition: ri.h:3036
@ is_value_constant
Definition: ri.h:3033
@ is_value_code
Definition: ri.h:3031
@ is_value_symbolic
Definition: ri.h:3032
#define syntax_sizeofexpression_p(x)
Definition: ri.h:2740
#define syntax_range(x)
Definition: ri.h:2733
@ is_syntax_range
Definition: ri.h:2692
@ is_syntax_application
Definition: ri.h:2697
@ is_syntax_cast
Definition: ri.h:2694
@ is_syntax_call
Definition: ri.h:2693
@ is_syntax_va_arg
Definition: ri.h:2698
@ is_syntax_reference
Definition: ri.h:2691
@ is_syntax_sizeofexpression
Definition: ri.h:2695
@ is_syntax_subscript
Definition: ri.h:2696
#define range_increment(x)
Definition: ri.h:2292
#define value_constant_p(x)
Definition: ri.h:3071
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define basic_overloaded_p(x)
Definition: ri.h:623
#define value_symbolic(x)
Definition: ri.h:3070
#define basic_undefined_p(x)
Definition: ri.h:557
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define cast_expression(x)
Definition: ri.h:747
#define application_arguments(x)
Definition: ri.h:510
#define subscript_indices(x)
Definition: ri.h:2563
#define type_undefined_p(x)
Definition: ri.h:2884
#define basic_undefined
Definition: ri.h:556
#define reference_domain
newgen_range_domain_defined
Definition: ri.h:338
#define entity_undefined
Definition: ri.h:2761
#define constant_int_p(x)
Definition: ri.h:848
#define expression_undefined
Definition: ri.h:1223
#define value_symbolic_p(x)
Definition: ri.h:3068
#define entity_name(x)
Definition: ri.h:2790
#define expression_normalized(x)
Definition: ri.h:1249
#define dimension_upper(x)
Definition: ri.h:982
#define reference_indices(x)
Definition: ri.h:2328
#define syntax_sizeofexpression(x)
Definition: ri.h:2742
#define sizeofexpression_expression_p(x)
Definition: ri.h:2407
#define sizeofexpression_type_p(x)
Definition: ri.h:2404
#define syntax_call(x)
Definition: ri.h:2736
#define cast_type(x)
Definition: ri.h:745
#define constant_undefined_p(x)
Definition: ri.h:803
#define syntax_application_p(x)
Definition: ri.h:2746
#define expression_undefined_p(x)
Definition: ri.h:1224
#define subscript_array(x)
Definition: ri.h:2561
#define application_function(x)
Definition: ri.h:508
#define range_lower(x)
Definition: ri.h:2288
#define variable_dimensions(x)
Definition: ri.h:3122
#define syntax_undefined
Definition: ri.h:2676
#define type_undefined
Definition: ri.h:2883
#define syntax_subscript(x)
Definition: ri.h:2745
#define call_arguments(x)
Definition: ri.h:711
#define syntax_cast_p(x)
Definition: ri.h:2737
#define syntax_range_p(x)
Definition: ri.h:2731
#define normalized_undefined_p(x)
Definition: ri.h:1746
#define entity_type(x)
Definition: ri.h:2792
#define normalized_linear(x)
Definition: ri.h:1781
#define expression_syntax(x)
Definition: ri.h:1247
#define type_variable_p(x)
Definition: ri.h:2947
#define value_expression(x)
Definition: ri.h:3082
language_utype
Definition: ri.h:1565
@ is_language_c
Definition: ri.h:1567
#define entity_domain
newgen_syntax_domain_defined
Definition: ri.h:410
#define constant_undefined
Definition: ri.h:802
#define variable_basic(x)
Definition: ri.h:3120
#define basic_logical_p(x)
Definition: ri.h:620
#define basic_float_p(x)
Definition: ri.h:617
#define entity_initial(x)
Definition: ri.h:2796
#define syntax_subscript_p(x)
Definition: ri.h:2743
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
void vect_chg_sgn(Pvecteur v)
void vect_chg_sgn(Pvecteur v): multiplie v par -1
Definition: scalaires.c:151
s1
Definition: set.c:247
#define ifdebug(n)
Definition: sg.c:47
static char * x
Definition: split_file.c:159
#define intptr_t
Definition: stdint.in.h:294
t_real sum(int n1, int n2, int n3, t_real u[n1][n2][n3])
Definition: stencil.c:57
char * strndup(char const *s, size_t n)
A replacement function, for systems that lack strndup.
Definition: strndup.c:26
Pvecteur vecteur
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define vecteur_val(v)
#define vecteur_var(v)
#define val_of(varval)
#define VECTEUR_NUL
DEFINITION DU VECTEUR NUL.
struct Svecteur * Pvecteur
#define vecteur_succ(v)
#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
#define term_cst(varval)
#define VECTEUR_UNDEFINED_P(v)
Pvecteur vect_dup(Pvecteur v_in)
Pvecteur vect_dup(Pvecteur v_in): duplication du vecteur v_in; allocation de et copie dans v_out;.
Definition: alloc.c:51
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_erase_var(Pvecteur *ppv, Variable v)
void vect_erase_var(Pvecteur * ppv, Variable v): projection du vecteur *ppv selon la direction v (i....
Definition: unaires.c:106
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
Value vect_coeff(Variable var, Pvecteur vect)
Variable vect_coeff(Variable var, Pvecteur vect): coefficient de coordonnee var du vecteur vect —> So...
Definition: unaires.c:228
Pvecteur vect_sort(Pvecteur v, int *compare)
Pvecteur vect_sort(v, compare) Pvecteur v; int (*compare)();.
Definition: unaires.c:335