PIPS
abstract_location.c
Go to the documentation of this file.
1 /*
2 
3  $Id: abstract_location.c 23415 2017-08-14 22:02:20Z irigoin $
4 
5  Copyright 1989-2016 MINES ParisTech
6  Copyright 2009-2010 HPC Project
7 
8  This file is part of PIPS.
9 
10  PIPS is free software: you can redistribute it and/or modify it
11  under the terms of the GNU General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  any later version.
14 
15  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
16  WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  FITNESS FOR A PARTICULAR PURPOSE.
18 
19  See the GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
23 
24 */
25 /* package abstract location. Amira Mensi 2010
26  *
27  * File: abstract_location.c
28  *
29  *
30  * This file contains various useful functions to modelize a heap.
31  *
32  */
33 #ifdef HAVE_CONFIG_H
34  #include "pips_config.h"
35 #endif
36 
37 #include <stdio.h>
38 #include <string.h>
39 #include <stdlib.h>
40 
41 #include "genC.h"
42 #include "linear.h"
43 #include "ri.h"
44 #include "effects.h"
45 #include "points_to_private.h"
46 #include "ri-util.h"
47 #include "prettyprint.h" // for debugging
48 #include "effects-util.h"
49 #include "text.h"
50 #include "text-util.h"
51 #include "misc.h"
52 #include "properties.h"
53 
54 
55 /*
56  Heap Modelization
57 
58  See pipsmake-rc.tex, propertiews ABSTRACT_HEAP_LOCATIONS and
59  ALIASING_ACROSS_TYPES, for documentation.
60 */
61 
62 /* check if an entity b may represent a bucket or a set of buckets in
63  the heap. */
65 {
66  bool bucket_p = entity_all_heap_locations_p(b) ||
68 
69  if(!heap_area_p(b) && !bucket_p) {
70  const char* ln = entity_local_name(b);
71  const char* found = strstr(ln, HEAP_AREA_LOCAL_NAME);
72  bucket_p = found != NULL;
73  }
74 
75  return bucket_p;
76 }
77 
79 {
80  entity e;
81  string s;
82  asprintf(&s, HEAP_AREA_LOCAL_NAME "_l_%d", stmt_number);
83 
85  free(s);
89  //ram r = make_ram(f, a, UNKNOWN_RAM_OFFSET, NIL);
91 
92  /* FI: Beware, the symbol table is updated but this is not
93  reflected in pipsmake.rc */
95  entity_type(e) = copy_type(ct);
99  (void) add_C_variable_to_area(a, e);
100  /* We need to keep track of these pseudo-variables to destroy them
101  before a module is reanalyzed after a code transformation, for
102  instance a constant propagation that changed dependent types
103  into cosntant types. */
105  }
106  else {
107  /* We might be in trouble, unless a piece of code is
108  reanalyzed. Let's assume the type is unchanged */
110  type et = entity_type(e);
111  // FI: too strong if 1-D arrays and pointers can be assimilated
112  //pips_assert("The type is unchanged",
113  // type_equal_p(ct, et));
114  if(!type_equal_p(ct,et)) {
115  // FI: this might be improvable with array_pointer_type_equal_p
116  if(pointer_type_p(ct) && array_type_p(et)) {
117  type pt = type_to_pointed_type(ct);
119  variable etv = type_variable(et);
120  basic eb = variable_basic(etv);
121  int d = (int) gen_length(variable_dimensions(etv));
122  if(d==1 && basic_equal_p(pb, eb))
123  ;
124  else
125  pips_assert("The type is unchanged or compatible", false);
126  }
127  else if(pointer_type_p(et) && array_type_p(ct)) {
128  type pt = type_to_pointed_type(et);
130  variable etv = type_variable(ct);
131  basic eb = variable_basic(etv);
132  int d = (int) gen_length(variable_dimensions(etv));
133  if(d==1 && basic_equal_p(pb, eb))
134  ;
135  else
136  pips_assert("The type is unchanged or compatible", false);
137  }
138  else
139  pips_assert("The type is unchanged or compatible", false);
140  }
141  free_type(ct);
142  }
143  return e;
144 
145 }
146 
148 {
149  bool result = false;
150  const char* ln = entity_local_name(e);
151  string found = strstr(ln, ANYWHERE_LOCATION);
152 
153  pips_debug(9, "input entity: %s\n", ln);
154  pips_debug(9, "found (1) = : %s\n", found);
155 
156  if (found == NULL)
157  {
158  found = strstr(ln, HEAP_AREA_LOCAL_NAME);
159  pips_debug(9, "found (2) = : %s\n", found);
160  if (found!=NULL)
161  {
162  size_t found_n = strspn(found, HEAP_AREA_LOCAL_NAME);
163  ln = &found[found_n];
164  pips_debug(9, "ln : %s\n", ln);
165  found = strstr(ln, "_l_");
166  pips_debug(9, "found (3) = : %s\n", found);
167  result = (found != NULL);
168  }
169  else
170  result = false;
171  }
172  else
173  result = false;
174  pips_debug(9, "result = %d\n", (int) result);
175  return result;
176 }
177 
178 /**
179  @brief generate the type of the allocated area from the malloc argument
180  @param e is the malloc argument expression
181  @return a new type (no sharing)
182 
183  Store dependent types are not generated. It means that whenever the
184  size of the allocated space is store dependent, the returned type
185  is an array of unbounded_dimension.
186  */
188 {
189  type t = type_undefined;
190  syntax s = expression_syntax(e);
193  bool scalar_p = false;;
194 
195  pips_debug(5, "begin for expression:%s\n", expression_to_string(e));
196 
198  {
199  scalar_p = true; // Not necessarily! An array type may be argument
200  sizeof_exp = syntax_sizeofexpression(s);
201  }
202  else if(syntax_cast_p(s)) {
203  cast c = syntax_cast(s);
204  expression ce = cast_expression(c);
205  t = malloc_arg_to_type(ce);
206  return t; // FI: I hate doing this...
207  }
208  else if (syntax_call_p(s))
209  {
210  call c = syntax_call(s);
211  entity func = call_function(c);
212  list func_args = call_arguments(c);
213 
215  {
216  pips_debug(5, "multiply operator found\n");
217  expression arg1 = EXPRESSION(CAR(func_args));
218  expression arg2 = EXPRESSION(CAR(CDR(func_args)));
219 
220  /* which one is the sizeof operator ? try the second one first */
222  {
223  pips_debug(5," second arg is a sizeof expression\n");
224  sizeof_exp = syntax_sizeofexpression(expression_syntax(arg2));
225  n = make_op_exp("-", copy_expression(arg1), int_to_expression(1));
226  }
228  {
229  pips_debug(5," first arg is a sizeof expression\n");
230  sizeof_exp = syntax_sizeofexpression(expression_syntax(arg1));
231  n = make_op_exp("-", copy_expression(arg2), int_to_expression(1));
232  }
233  else
234  {
236  }
237  }
238  else
239  {
241  }
242  }
243  else
245 
247  && !expression_constant_p(n))
248  {
249  // FI: I do not see why we cannot generate dependent types...
250  // We would have to be careful to evaluate the expression in
251  // case its variables are modified. Just as the parser should do.
252  pips_debug(5, "non constant number of elements "
253  "-> generating unbounded dimension\n");
254  free_expression(n);
256  }
257 
258  if (sizeofexpression_undefined_p(sizeof_exp))
259  {
262  CONS(DIMENSION,
264  NIL),
265  NIL));
266  }
267  else if (sizeofexpression_type_p(sizeof_exp))
268  {
269  type t_sizeof_exp = sizeofexpression_type(sizeof_exp);
270  variable t_var_sizeof_exp = type_variable_p(t_sizeof_exp) ?
271  type_variable(t_sizeof_exp) : variable_undefined;
272  pips_assert("type must be variable",
273  !variable_undefined_p(t_var_sizeof_exp));
274 
275  if (scalar_p)
277  (make_variable(copy_basic(variable_basic(t_var_sizeof_exp)),
279  (t_var_sizeof_exp)),
280  NIL));
281  else
283  (make_variable(copy_basic(variable_basic(t_var_sizeof_exp)),
284  CONS(DIMENSION,
287  (t_var_sizeof_exp))),
288  NIL));
289  }
290  else /* sizeofexpression is an expression */
291  {
292  type t_sizeof_exp =
294  variable t_var_sizeof_exp = type_variable_p(t_sizeof_exp) ?
295  type_variable(t_sizeof_exp) : variable_undefined;
296 
297  if (scalar_p)
299  (make_variable(copy_basic(variable_basic( t_var_sizeof_exp)),
301  (t_var_sizeof_exp)),
302  NIL));
303  else
305  (make_variable(copy_basic(variable_basic(t_var_sizeof_exp)),
306  CONS(DIMENSION,
309  (t_var_sizeof_exp))),
310  NIL));
311  free_type(t_sizeof_exp);
312  }
313  pips_debug(5, "end with type %s\n", string_of_type(t));
314  return t;
315 }
316 
317 /**
318  @brief generate an abstract heap location entity
319  @param t is type of the allocated space
320  @param psi is a pointer towards a structure which contains context
321  and/or flow sensitivity information
322  @return an abstract heap location entity
323  */
325 {
327  const char* opt = get_string_property("ABSTRACT_HEAP_LOCATIONS");
328  bool type_sensitive_p = !get_bool_property("ALIASING_ACROSS_TYPES");
329 
330  pips_debug(8, "begin for type %s\n",
331  string_of_type(t));
332  /* in case we want an anywhere abstract heap location : the property
333  ABSTRACT_HEAP_LOCATIONS is set to "unique" and a unique abstract
334  location is used for all heap buckets. */
335  if(strcmp(opt, "unique")==0){
336  if(type_sensitive_p)
338  else
340  }
341 
342  /* in case the property ABSTRACT_HEAP_LOCATIONS is set to
343  "insensitive": an abstract location is used for each function. */
344  else if(strcmp(opt, "insensitive")==0){
345  if(type_sensitive_p)
347  copy_type(t));
348  else
350  }
351 
352  /* in case the property ABSTRACT_HEAP_LOCATIONS is set to
353  "flow-sensitive" or "context-sensitive".
354 
355  No difference here between the two values. The diffferent
356  behavior will show when points-to and effects are translated at
357  call sites
358 
359  At this level, we want to use the statement number or the
360  statement ordering. The statement ordering is safer because two
361  statements or more can be put on the same line. The statement
362  number is more user-friendly.
363 
364  There is no need to distinguish between types since the statement
365  ordering is at least as effective.
366  */
367  else if(strcmp(opt, "flow-sensitive")==0
368  || strcmp(opt, "context-sensitive")==0 )
371  copy_type(t));
372  else
373  pips_user_error("Unrecognized value for property ABSTRACT_HEAP_LOCATION:"
374  " \"%s\"", opt);
375 
376  pips_debug(8, "returning entity %s of type %s\n", entity_name(e),
378 
379  return e;
380 }
381 
382 /**
383  @brief generate an abstract heap location entity
384  @param malloc_exp is the argument expression of the call to malloc
385  @param psi is a pointer towards a structure which contains context
386  and/or flow sensitivity information
387  @return an abstract heap location entity
388  */
391 {
393 
394  pips_debug(8, "begin for expression %s\n", expression_to_string(malloc_exp));
395  type t = malloc_arg_to_type(malloc_exp);
396  //type ct = copy_type(compute_basic_concrete_type(t));
397  //e = malloc_type_to_abstract_location(ct, psi);
399  free_type(t)/*, free_type(ct)*/;
400  pips_debug(8, "returning entity %s of type %s\n", entity_name(e),
402 
403  return e;
404 }
405 
406 /**
407  @brief generate an abstract heap location entity
408  @param n is the first argument expression of the call to calloc
409  @param size is the second argument expression of the call to calloc
410  @param psi is a pointer towards a structure which contains context
411  and/or flow sensitivity information
412  @return an abstract heap location entity
413  */
416 {
417  expression malloc_exp = make_op_exp("*",
418  copy_expression(n),
419  copy_expression(size));
420  entity e = malloc_to_abstract_location(malloc_exp, psi);
421  free_expression(malloc_exp);
422  return(e);
423 }
424 
425 /* to handle malloc statemennts:
426  *
427  * p = (cast t) malloc(sizeof(expression))
428  *
429  * This function return a reference
430  * according to the value of the property ABSTRACT_HEAP_LOCATIONS.
431  */
432 /* the list of callers will be added to ensure the context sensitive
433  property. We should keep in mind that context and sensitive
434  properties are orthogonal and we should modify them in pipsmake.*/
435 reference
437  type __attribute__ ((unused)) var_t,
438  type __attribute__ ((unused)) cast_t,
439  expression sizeof_exp,
440  entity f,
441  statement stmt)
442 {
447  f,
448  NIL);
449  //string opt = get_string_property("ABSTRACT_HEAP_LOCATIONS");
450  //bool type_sensitive_p = !get_bool_property("ALIASING_ACROSS_TYPES");
451 
452  e = malloc_to_abstract_location(sizeof_exp, &si);
453  if(!entity_array_p(e))
454  r = make_reference(e , NIL);
455  else
457  /* /\* in case we want an anywhere abstract heap location : the property */
458 /* ABSTRACT_HEAP_LOCATIONS is set to "unique" and a unique abstract */
459 /* location is used for all heap buckets. *\/ */
460 /* if(strcmp(opt, "unique")==0){ */
461 /* if(type_sensitive_p) { */
462 /* e = entity_all_heap_locations_typed(var_t); */
463 /* r = make_reference(e , NIL); */
464 /* } */
465 /* else { */
466 /* e = entity_all_heap_locations(); */
467 /* r = make_reference(e , NIL); */
468 /* } */
469 /* } */
470 
471 /* /\* in case the property ABSTRACT_HEAP_LOCATIONS is set to */
472 /* "insensitive": an abstract location is used for each function. *\/ */
473 /* else if(strcmp(opt, "insensitive")==0){ */
474 /* if(type_sensitive_p) { */
475 /* e = entity_all_module_heap_locations_typed(get_current_module_entity(), */
476 /* var_t); */
477 /* r = make_reference(e , NIL); */
478 /* } */
479 /* else { */
480 /* e = entity_all_module_heap_locations(f); */
481 /* r = make_reference(e , NIL); */
482 /* } */
483 /* } */
484 
485 /* /\* in case the property ABSTRACT_HEAP_LOCATIONS is set to */
486 /* "flow-sensitive" or "context-sensitive". */
487 
488 /* No difference here between the two values. The diffferent */
489 /* behavior will show when points-to and effects are translated at */
490 /* call sites */
491 
492 /* At this level, we want to use the statement number or the */
493 /* statement ordering. The statement ordering is safer because two */
494 /* statements or more can be put on the same line. The statement */
495 /* number is more user-friendly. */
496 
497 /* There is no need to distinguish between types since the statement */
498 /* ordering is at least as effective. */
499 /* *\/ */
500 /* else if(strcmp(opt, "flow-sensitive")==0 */
501 /* || strcmp(opt, "context-sensitive")==0 ){ */
502 /* e = entity_flow_or_context_sentitive_heap_location(stmt_number, var_t); */
503 /* r = make_reference(e , NIL); */
504 /* } */
505 /* else { */
506 /* pips_user_error("Unrecognized value for property ABSTRACT_HEAP_LOCATION:" */
507 /* " \"%s\"", opt); */
508 /* } */
509 
510 /* pips_debug(8, "Reference to "); */
511 
512  return r;
513 }
514 
515 /*
516  * FLOW AND CONTEXT SENSITIVITY INFORMATION HOOK
517  *
518  * FI->AM: How come the properties are not exploited here?
519  *
520  * FI->AM: do you understand that the data structure "si" is copied back?
521  */
524  list enclosing_flow)
525 {
529  si.enclosing_flow = enclosing_flow;
530  return si;
531 }
532 
float a2sf[2] __attribute__((aligned(16)))
USER generates a user error (i.e., non fatal) by printing the given MSG according to the FMT.
Definition: 3dnow.h:3
static string current_module
Definition: message.c:63
value make_value_unknown(void)
Definition: ri.c:2847
type make_type_variable(variable _field_)
Definition: ri.c:2715
type copy_type(type p)
TYPE.
Definition: ri.c:2655
basic copy_basic(basic p)
BASIC.
Definition: ri.c:104
basic make_basic_int(intptr_t _field_)
Definition: ri.c:158
ram make_ram(entity a1, entity a2, intptr_t a3, list a4)
Definition: ri.c:1999
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
dimension make_dimension(expression a1, expression a2, list a3)
Definition: ri.c:565
variable make_variable(basic a1, list a2, list a3)
Definition: ri.c:2895
void free_expression(expression p)
Definition: ri.c:853
void free_type(type p)
Definition: ri.c:2658
storage make_storage_ram(ram _field_)
Definition: ri.c:2279
reference original_malloc_to_abstract_location(expression lhs __attribute__((unused)), type __attribute__((unused)) var_t, type __attribute__((unused)) cast_t, expression sizeof_exp, entity f, statement stmt)
to handle malloc statemennts:
entity entity_flow_or_context_sentitive_heap_location(int stmt_number, type t)
entity calloc_to_abstract_location(expression n, expression size, sensitivity_information *psi)
generate an abstract heap location entity
sensitivity_information make_sensitivity_information(statement current_stmt, entity current_module, list enclosing_flow)
entity malloc_type_to_abstract_location(type t, sensitivity_information *psi)
generate an abstract heap location entity
type malloc_arg_to_type(expression e)
generate the type of the allocated area from the malloc argument
entity malloc_to_abstract_location(expression malloc_exp, sensitivity_information *psi)
generate an abstract heap location entity
bool entity_flow_or_context_sentitive_heap_location_p(entity e)
bool entity_heap_location_p(entity b)
package abstract location.
entity entity_all_module_heap_locations(entity m)
return m:*HEAP**ANYWHERE
entity entity_all_module_heap_locations_typed(entity m, type t)
bool entity_all_module_heap_locations_p(entity e)
test if an entity is the a heap area
entity entity_all_heap_locations()
return ANY_MODULE:HEAP
entity entity_all_heap_locations_typed(type t)
bool entity_all_heap_locations_p(entity e)
test if an entity is the set of all heap locations
void const char const char const int
static statement current_stmt
#define ANYWHERE_LOCATION
char * get_string_property(const char *)
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
void free(void *)
const char * get_current_module_name(void)
Get the name of the current module.
Definition: static.c:121
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#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
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define asprintf
Definition: misc-local.h:225
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_user_error
Definition: misc-local.h:147
#define HEAP_AREA_LOCAL_NAME
Definition: naming-local.h:71
#define same_string_p(s1, s2)
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
string expression_to_string(expression e)
Definition: expression.c:77
string string_of_type(const type)
Definition: type.c:56
#define DYNAMIC_RAM_OFFSET
FI: I would have assumed that it is used for the stack area, but I must be wrong.....
#define DEFAULT_CHARACTER_TYPE_SIZE
Default type sizes.
#define MULTIPLY_OPERATOR_NAME
@ ABSTRACT_LOCATION
bool heap_area_p(entity aire)
Definition: area.c:86
entity module_to_heap_area(entity f)
Returns the heap area "a" associated to module "f".
Definition: area.c:129
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
entity FindOrCreateEntity(const char *package, const char *local_name)
Problem: A functional global entity may be referenced without parenthesis or CALL keyword in a functi...
Definition: entity.c:1586
bool entity_array_p(entity e)
Is e a variable with an array type?
Definition: entity.c:754
expression make_unbounded_expression()
Definition: expression.c:4339
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
expression make_op_exp(char *op_name, expression exp1, expression exp2)
================================================================
Definition: expression.c:2012
bool unbounded_expression_p(expression e)
Definition: expression.c:4329
bool array_type_p(type)
Definition: type.c:2942
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
void AddEntityToDeclarations(entity, entity)
END_EOLE.
Definition: variable.c:108
int add_C_variable_to_area(entity, entity)
Definition: variable.c:1381
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
bool pointer_type_p(type)
Check for scalar pointers.
Definition: type.c:2993
type compute_basic_concrete_type(type)
computes a new type which is the basic concrete type of the input type (this new type is not stored i...
Definition: type.c:3556
#define reference_undefined
Definition: ri.h:2302
#define call_function(x)
Definition: ri.h:709
#define sizeofexpression_type(x)
Definition: ri.h:2406
#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_variable(x)
Definition: ri.h:2949
#define entity_storage(x)
Definition: ri.h:2794
#define syntax_sizeofexpression_p(x)
Definition: ri.h:2740
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define cast_expression(x)
Definition: ri.h:747
#define type_undefined_p(x)
Definition: ri.h:2884
#define entity_undefined
Definition: ri.h:2761
#define expression_undefined
Definition: ri.h:1223
#define entity_name(x)
Definition: ri.h:2790
#define variable_undefined
Definition: ri.h:3095
#define sizeofexpression_undefined_p(x)
Definition: ri.h:2371
#define syntax_sizeofexpression(x)
Definition: ri.h:2742
#define variable_undefined_p(x)
Definition: ri.h:3096
#define sizeofexpression_type_p(x)
Definition: ri.h:2404
#define syntax_call(x)
Definition: ri.h:2736
#define expression_undefined_p(x)
Definition: ri.h:1224
#define variable_dimensions(x)
Definition: ri.h:3122
#define type_undefined
Definition: ri.h:2883
#define sizeofexpression_undefined
Definition: ri.h:2370
#define call_arguments(x)
Definition: ri.h:711
#define syntax_cast_p(x)
Definition: ri.h:2737
#define entity_kind(x)
Definition: ri.h:2798
#define entity_type(x)
Definition: ri.h:2792
#define statement_number(x)
Definition: ri.h:2452
#define expression_syntax(x)
Definition: ri.h:1247
#define type_variable_p(x)
Definition: ri.h:2947
#define variable_basic(x)
Definition: ri.h:3120
#define entity_initial(x)
Definition: ri.h:2796
int var_t
Type of variables.
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: statement.c:54