PIPS
points_to.c
Go to the documentation of this file.
1 /*
2 
3  $Id$
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 /* Interface with points-to library */
29 
30 #include <stdio.h>
31 #include <string.h>
32 
33 #include "genC.h"
34 #include "linear.h"
35 
36 #include "misc.h"
37 #include "properties.h"
38 
39 #include "ri.h"
40 #include "effects.h"
41 
42 #include "ri-util.h"
43 #include "prettyprint.h"
44 #include "effects-util.h"
45 
46 #include "text-util.h"
47 
48 #include "effects-simple.h"
49 
50 #include "pips-libs.h"
51 #ifdef HAVE_PIPS_points_to_LIBRARY
52 // for get_points_to_graph_from_statement & expression_to_points_to_sinks
53 #include "points-to.h" // 2 or more functions
54 #else // no HAVE_PIPS_points_to_LIBRARY
55 // typedef set points_to_graph
58 {
59  pips_internal_error("points-to library not available");
60  return NULL;
61 }
62 
66 {
67  pips_internal_error("points-to library not available");
68  return NIL;
69 }
70 
74 {
75  pips_internal_error("points-to library not available");
76  return NIL;
77 }
78 
80  pt_map pt_caller)
81 {
82  pips_internal_error("points-to library not available");
83  return NIL;
84 }
85 #endif // HAVE_PIPS_points_to_LIBRARY
86 
87 #include "transformer.h"
88 
89 /* Special wrapping for the semantics analyses
90  *
91  * FI: check if new cells are allocated to build the returned location
92  * list ll...
93  */
95 {
97  if (!pt_to_list_undefined_p()) {
99  if(statement_undefined_p(curstat)) {
100  // The points-to IN information should be used
101  ;
102  }
103  else
104  ptg = get_points_to_graph_from_statement(curstat);
105  }
106 
108  return ll;
109 }
110 
111 /* Returns a list of cells */
113 {
114  list ll = list_undefined;
115  if(pt_to_list_undefined_p()) {
118  ll = CONS(CELL, c, NIL);
119  }
120  else {
123  ll = expression_to_points_to_sinks(e, ptg);
124  }
125  return ll;
126 }
127 ␌
128 /* If both "se", source entity, and "de", destination entity, are
129  * defined, substitute the values of "se" by the values of "de" in
130  * "backward_p" mode, when translating a callee transformer at a call
131  * site of a caller.
132  *
133  * If the "se" entity cannot be substituted, its value must be
134  * project.
135  */
137 {
138  if(entity_undefined_p(se))
139  ;
140  else if(entity_undefined_p(de))
141  *ppl = CONS(ENTITY, se, *ppl);
142  else if(entity_has_values_p(de)) {
143  // Not in the caller's frame
144  // entity nsv = entity_to_new_value(se);
145  entity nsv = se;
146  entity ndv = entity_to_new_value(de);
147  if(backward_p) { // For transformers
148  tf = transformer_value_substitute(tf, nsv, ndv);
149  }
150  else { // For preconditions
151  tf = transformer_value_substitute(tf, ndv, nsv);
152  }
153  // Careful, se has been substituted in the argument too
156  entity odv = entity_to_old_value(de);
157  if(backward_p) { // For transformers
158  tf = transformer_value_substitute(tf, osv, odv);
159  }
160  else { // For preconditions
161  tf = transformer_value_substitute(tf, odv, osv);
162  }
163  }
164  }
165  else {
166  // FI: could be some debugging stuff
167  pips_user_warning("Stub \"%s\" cannot be substituted.\n",
168  entity_user_name(de));
169  // FI: entity "de" must be projected
170  *ppl = CONS(ENTITY, se, *ppl);
171  }
172  return tf;
173 }
174 ␌
176 {
177  list fl = struct_type_to_fields(lt);
178  FOREACH(ENTITY, f, fl) {
180  if(analyzed_type_p(ft)) {
187 
188  if(!entity_undefined_p(l1)) {
189  if(!entity_undefined_p(l2)) {
190  t = substitute_scalar_stub_in_transformer(t, l1, l2, backward_p, ppl);
191  }
192  }
193  else {
194  // pips_internal_error("Not implemented yet.\n");
195  // Do nothing, this field may simply be not used
196  ;
197  }
198  free_reference(r1);
199  free_reference(r2); // another option would be to remove the last subscript
200  }
201  else if(type_struct_variable_p(ft)) {
202  // This piece of code could be integrate in the previous
203  // alternative to share most of its code
208  if(array_type_p(ft)) {
209  // FI: how do we guess the subscript values? we could try to
210  // infer them from the values used in the transformer or we
211  // can generate all possible subscripts...
212 
213  // FI: a special case, used for debugging only
216  }
217 
218  // GO down recursively
219  t = substitute_struct_stub_in_transformer(t, l1, ft, r1, ft, backward_p, ppl);
220  }
221  }
222  return t;
223 }
224 ␌
225 /* The sources of the relevant points-to */
227 {
228  bool relevant_p = false;
229  cell d = points_to_sink(pt); // callee if backward_p
231  entity de = reference_variable(dr);
232  relevant_p = gen_in_list_p((const void *) de, ll);
233 
234  return relevant_p;
235 }
236 
237 /* Exploit the binding map to substitute calles's stubs by actual
238  * arguments, which may be stubs of the callers,
239  *
240  * backward_p request a substitution from the callees' frame into the
241  * caller's frame, which is useful for transformers. Flag backward_p is
242  * set to false to compute summary preconditions.
243  *
244  * FI: this function is now only used for preconditions. It has been
245  * rewritten for transformers to speed up the process when array
246  * elements are involved. It is better to start from the needs, the
247  * stubs used in the transformer, than from all possible stubs, but it
248  * is much easier for a backward translation. With a forward
249  * translation, regular variables may have to be translated into
250  * stubs.
251  *
252  * FI: A quick improvement would to return when no translation is
253  * needed... but you do not always know it when backward_p is set to
254  * false.
255  */
257 {
259  list ll = backward_p? transformer_to_analyzed_locations(tf)
261  if(ENDP(ll)) {
262  // Return tf as is
263  ;
264  }
265  else if(pt_to_list_undefined_p()) {
266  // Return tf as is
267  }
268  else {
270  bool bottom_p = points_to_graph_bottom(ptg);
271 
272  if(bottom_p) {
273  // FI: should this lead to an empty transformer?
274  pips_internal_error("Not implemented yet.\n");
275  }
276  else {
278  list pl = NIL; // FI: I am not sure we can managed forward and
279  // backward projections with one variable
280  SET_FOREACH(points_to, pt, binding) {
282  if(relevant_translation_pair_p(pt, ll)
284  cell s = points_to_source(pt); // callee if backward_p
285  cell d = points_to_sink(pt); // caller if backward_p
288  // This test should be useless because this is guaranteed by
289  // the approximation, except if binding is corrupted.
291  list srs = reference_indices(sr);
292  list drs = reference_indices(dr);
293  if(ENDP(srs) && ENDP(drs)) {
294  entity se = reference_variable(sr);
295  entity de = reference_variable(dr);
296  //type se_t = entity_basic_concrete_type(se);
297  //type de_t = entity_basic_concrete_type(de);
298  if(entity_has_values_p(de))
299  tf = substitute_scalar_stub_in_transformer(tf, se, de, backward_p, &pl);
300  else {
301  type se_t = entity_basic_concrete_type(se);
302  type de_t = entity_basic_concrete_type(de);
303  if(type_struct_variable_p(se_t)) {
304  tf = substitute_struct_stub_in_transformer(tf, sr, se_t, dr, de_t, backward_p, &pl);
305  }
306  else
307  pl = CONS(ENTITY, se, pl);
308  }
309  }
310  else if(ENDP(srs) && !ENDP(drs)) {
311  entity se = reference_variable(sr);
312  if(analyzed_reference_p(dr)) {
314  tf = substitute_scalar_stub_in_transformer(tf, se, de, backward_p, &pl);
315  }
316  else {
317  pl = CONS(ENTITY, se, pl);
318  }
319  }
320  else if(!ENDP(srs) && ENDP(drs)) {
321  entity de = reference_variable(dr);
322  if(entity_has_values_p(de)) {
324  if(!entity_undefined_p(se))
325  tf = substitute_scalar_stub_in_transformer(tf, se, de, backward_p, &pl);
326  else
327  pips_internal_error("Not implemented yet.\n");
328  }
329  else {
330  type de_t = entity_basic_concrete_type(de);
331  if(type_struct_variable_p(de_t)) {
332  tf = substitute_struct_stub_in_transformer(tf, sr, de_t, dr, de_t, backward_p, &pl);
333  // tf = substitute_struct_stub_reference_in_transformer(tf, sr, de, backward_p, &pl);
334  }
335  else {
336  // Do nothing
337  // entity se = reference_variable(sr);
338  // pl = CONS(ENTITY, se, pl);
339  ;
340  }
341  }
342  }
343  else { // !ENDP(srs) & !ENDP(drs)
344  if(analyzed_reference_p(dr)) {
347  tf = substitute_scalar_stub_in_transformer(tf, se, de, backward_p, &pl);
348  }
349  else {
350  type st = reference_to_type(sr);
352  if(type_struct_variable_p(cst))
353  tf = substitute_struct_stub_in_transformer(tf, sr, cst, dr, cst, backward_p, &pl);
354  else {
355  // No useful information in this binding
356  ;
357  }
358  }
359  }
360  }
361  }
362  }
363  if(!ENDP(pl)) {
364  // Get rid on untranslatable entities
366  }
367  }
368  }
369 
370  gen_free_list(ll);
371 
372  return tf;
373 }
374 ␌
376 {
377  pips_assert("Backward only", backward_p);
379  FOREACH(ENTITY, l, ll) {
381  value val = entity_initial(l);
382  entity v = l;
383  list sl = NIL;
384  if(value_reference_p(val)) {
385  reference r = value_reference(val); // By definition of list ll
386  v = reference_variable(r);
387  sl = reference_indices(r);
388  }
389  list tcrl = reference_to_points_to_translations(v, sl, binding_g);
390  FOREACH(CELL, tcr, tcrl) {
391  reference tr = cell_any_reference(tcr);
393  // FI: The type checking should be useless, but for constant
394  // character strings which appear as a pointer to a char,
395  // i.e. an integer, and is analyzed as such in the callee
396  if(type_equal_p(lt, trt)
397  && generic_atomic_points_to_reference_p(tr, false)) {
399  if(!entity_undefined_p(tl)) {
401  entity ntlv = entity_to_new_value(tl);
402  tf = transformer_value_substitute(tf, nlv, ntlv);
405  entity otlv = entity_to_old_value(tl);
406  tf = transformer_value_substitute(tf, olv, otlv);
407  }
408  }
409  }
410  }
411  gen_free_list(tcrl);
412  }
413  gen_free_list(ll);
414  return tf;
415 }
416 
418 {
419  if(pt_to_list_undefined_p()) {
420  // Return tf as is
421  }
422  else {
424  bool bottom_p = points_to_graph_bottom(ptg);
425 
426  if(bottom_p) {
427  /* This leads to an empty transformer because the statement is
428  * unreachable. Some kind of dereferencement error has occured
429  * earlier in the execution
430  */
431  free_transformer(tf);
432  tf = transformer_empty();
433  }
434  else {
436  pt_map binding_g = make_points_to_graph(false, binding);
437  tf = substitute_stubs_in_transformer_with_translation_binding(tf, binding_g, backward_p);
438  free_points_to_graph(binding_g);
439  }
440  }
441  return tf;
442 }
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
void free_points_to_graph(points_to_graph p)
points_to_graph make_points_to_graph(bool a1, set a2)
void free_transformer(transformer p)
Definition: ri.c:2616
void free_reference(reference p)
Definition: ri.c:2050
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
bool entity_is_argument_p(entity e, cons *args)
Definition: arguments.c:150
transformer transformer_empty()
Allocate an empty transformer.
Definition: basic.c:120
bool generic_atomic_points_to_reference_p(reference r, bool strict_p)
Is it a unique concrete memory location?
Definition: points_to.c:489
bool atomic_points_to_reference_p(reference r)
Definition: points_to.c:519
cell make_anywhere_points_to_cell(type t)
Function storing points to information attached to a statement.
Definition: points_to.c:87
type points_to_reference_to_concrete_type(reference)
Definition: type.c:685
reference cell_any_reference(cell)
API for reference.
Definition: effects.c:77
type points_to_expression_to_concrete_type(expression)
The type returned is stored in a hash-table.
Definition: type.c:617
bool pt_to_list_undefined_p(void)
points_to.c
entity constant_memory_access_path_to_location_entity(reference)
A constant memory access path may not be considered.
Definition: locations.c:329
#define approximation_exact_p(x)
Definition: effects.h:369
#define CELL(x)
CELL.
Definition: effects.h:424
#define approximation_must_p(x)
Definition: effects.h:366
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
#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 list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
#define _UNUSED_
Definition: misc-local.h:232
#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 SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
list reference_to_points_to_translations(entity, list, pt_map)
This function is designed to work properly for the translation of effects at call sites.
#define points_to_approximation(x)
#define points_to_sink(x)
#define points_to_graph_undefined
#define points_to_graph_bottom(x)
#define points_to_source(x)
static hash_table pl
properties are stored in this hash table (string -> property) for fast accesses.
Definition: properties.c:783
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
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
bool array_type_p(type)
Definition: type.c:2942
statement get_current_statement_from_statement_global_stack(void)
Definition: static.c:344
bool type_equal_p(type, type)
Definition: type.c:547
type entity_basic_concrete_type(entity)
retrieves or computes and then returns the basic concrete type of an entity
Definition: type.c:3677
list struct_type_to_fields(type)
Definition: type.c:5798
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
type reference_to_type(reference)
Definition: type.c:2354
bool type_struct_variable_p(type)
Definition: type.c:3867
#define value_reference(x)
Definition: ri.h:3085
#define reference_variable(x)
Definition: ri.h:2326
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define entity_undefined_p(x)
Definition: ri.h:2762
#define transformer_arguments(x)
Definition: ri.h:2871
#define reference_indices(x)
Definition: ri.h:2328
#define value_reference_p(x)
Definition: ri.h:3083
#define statement_undefined_p(x)
Definition: ri.h:2420
#define entity_initial(x)
Definition: ri.h:2796
static transformer substitute_stubs_in_transformer_with_translation_binding(transformer tf, pt_map binding_g, bool backward_p)
Definition: points_to.c:375
points_to_graph get_points_to_graph_from_statement(_UNUSED_ statement st)
Interface with points-to library.
Definition: points_to.c:56
list semantics_expression_to_points_to_sinks(expression e)
Returns a list of cells.
Definition: points_to.c:112
transformer substitute_struct_stub_in_transformer(transformer t, reference l, type lt, reference r, type rt __attribute__((unused)), bool backward_p, list *ppl)
Definition: points_to.c:175
list semantics_expression_to_points_to_sources(expression e)
Special wrapping for the semantics analyses.
Definition: points_to.c:94
list expression_to_points_to_sinks(_UNUSED_ expression e, _UNUSED_ points_to_graph in)
Definition: points_to.c:63
transformer substitute_stubs_in_transformer(transformer tf, call c, statement s, bool backward_p)
Exploit the binding map to substitute calles's stubs by actual arguments, which may be stubs of the c...
Definition: points_to.c:256
set user_call_to_points_to_interprocedural_binding_set(call c, pt_map pt_caller)
Compute the binding relations in a complete interprocedural way: be as accurate as possible.
Definition: points_to.c:79
transformer new_substitute_stubs_in_transformer(transformer tf, call c, statement s, bool backward_p)
Definition: points_to.c:417
transformer substitute_scalar_stub_in_transformer(transformer tf, entity se, entity de, bool backward_p, list *ppl)
If both "se", source entity, and "de", destination entity, are defined, substitute the values of "se"...
Definition: points_to.c:136
list expression_to_points_to_sources(_UNUSED_ expression e, _UNUSED_ points_to_graph in)
Definition: points_to.c:71
static bool relevant_translation_pair_p(points_to pt, list ll)
The sources of the relevant points-to.
Definition: points_to.c:226
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
transformer safe_transformer_projection(transformer t, list args)
t may be undefined, args may contain values unrelated to t
Definition: transformer.c:1187
transformer transformer_value_substitute(transformer t, entity e1, entity e2)
transformer transformer_value_substitute(transformer t, entity e1, entity e2): if e2 does not appear ...
Definition: transformer.c:1993
list transformer_to_analyzed_locations(transformer tf)
The list of location entities that appear in the basis of the transformer predicate.
Definition: transformer.c:2785
list transformer_to_potential_stub_translation(transformer tf, entity m __attribute__((unused)))
Provide a list of variables that might be forward translated into a stub when preconditions are propa...
Definition: transformer.c:2720
bool analyzed_reference_p(reference)
FI: Nelson explains the motivation for can_be_constant_path_p() but I do not understand them.
Definition: value.c:518
entity global_new_value_to_global_old_value(entity)
Definition: value.c:716
entity external_entity_to_new_value(entity)
Definition: value.c:1411
entity entity_to_new_value(entity)
Definition: value.c:859
bool entity_has_values_p(entity)
This function could be made more robust by checking the storage of e.
Definition: value.c:911
entity external_entity_to_old_value(entity)
Definition: value.c:1422
entity entity_to_old_value(entity)
Definition: value.c:869
bool analyzed_type_p(type)
The type t is one of the analyzed types.
Definition: value.c:367