PIPS
pointer_values_analyses.c File Reference
#include <stdio.h>
#include <string.h>
#include "genC.h"
#include "linear.h"
#include "ri.h"
#include "ri-util.h"
#include "workspace-util.h"
#include "prettyprint.h"
#include "effects.h"
#include "effects-util.h"
#include "text-util.h"
#include "effects-simple.h"
#include "effects-generic.h"
#include "pipsdbm.h"
#include "misc.h"
#include "pointer_values.h"
+ Include dependency graph for pointer_values_analyses.c:

Go to the source code of this file.

Macros

#define UNDEF   abort
 
#define PV_NB_MAX_ITER_FIX_POINT   3
 

Typedefs

typedef void(* void_function) ()
 
typedef gen_chunk *(* chunks_function) ()
 
typedef list(* list_function) ()
 
typedef bool(* bool_function) ()
 
typedef descriptor(* descriptor_function) ()
 
typedef statement_cell_relations(* statement_cell_relations_function) ()
 
typedef statement_effects(* statement_effects_function) ()
 
typedef cell_relation(* cell_relation_function) ()
 

Functions

statement_cell_relations db_get_simple_pv (const char *module_name)
 I don't know how to deal with these mappings if we have to analyse several modules at the same time when performing an interprocedural analysis. More...
 
void db_put_simple_pv (const char *module_name, statement_cell_relations scr)
 
list db_get_in_simple_pv (const char *module_name)
 
void db_put_in_simple_pv (const char *module_name, list l_pv)
 
list db_get_out_simple_pv (const char *module_name)
 
void db_put_out_simple_pv (const char *module_name, list l_pv)
 
list db_get_initial_simple_pv (const char *module_name)
 
void db_put_initial_simple_pv (const char *module_name, list l_pv)
 
list db_get_program_simple_pv ()
 
void db_put_program_simple_pv (list l_pv)
 
pv_context make_simple_pv_context ()
 
void reset_pv_context (pv_context *p_ctxt)
 
void pv_context_statement_push (statement s, pv_context *ctxt)
 
void pv_context_statement_pop (pv_context *ctxt)
 
statement pv_context_statement_head (pv_context *ctxt)
 
pv_results make_pv_results ()
 
void free_pv_results_paths (pv_results *pv_res)
 
void print_pv_results (pv_results pv_res)
 
list make_anywhere_anywhere_pvs ()
 
static list sequence_to_post_pv (sequence seq, list l_in, pv_context *ctxt)
 
static list statement_to_post_pv (statement stmt, list l_in, pv_context *ctxt)
 
static list declarations_to_post_pv (list l_decl, list l_in, pv_context *ctxt)
 
static list declaration_to_post_pv (entity e, list l_in, pv_context *ctxt)
 
static list instruction_to_post_pv (instruction inst, list l_in, pv_context *ctxt)
 
static list test_to_post_pv (test t, list l_in, pv_context *ctxt)
 
static list loop_to_post_pv (loop l, list l_in, pv_context *ctxt)
 
static list whileloop_to_post_pv (whileloop l, list l_in, pv_context *ctxt)
 
static list forloop_to_post_pv (forloop l, list l_in, pv_context *ctxt)
 
static list unstructured_to_post_pv (unstructured u, list l_in, pv_context *ctxt)
 
static void call_to_post_pv (call c, list l_in, pv_results *pv_res, pv_context *ctxt)
 
void range_to_post_pv (range r, list l_in, pv_results *pv_res, pv_context *ctxt)
 
void expression_to_post_pv (expression exp, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void external_call_to_post_pv (call c, list l_in, pv_results *pv_res, pv_context *ctxt)
 
void single_pointer_assignment_to_post_pv (effect lhs_eff, list l_rhs_eff, list l_rhs_kind, bool declaration_p, list l_in, pv_results *pv_res, pv_context *ctxt)
 
void multiple_pointer_assignment_to_post_pv (effect lhs_base_eff, type lhs_type, list l_rhs_base_eff, list l_rhs_base_kind, bool declaration_p, list l_in, pv_results *pv_res, pv_context *ctxt)
 
void assignment_to_post_pv (expression lhs, bool may_lhs_p, expression rhs, bool declaration_p, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static list module_initial_parameter_pv ()
 
static void generic_module_pointer_values (char *module_name, pv_context *ctxt)
 generic interface to compute the pointer values of a given module More...
 
static void generic_module_initial_pointer_values (char *module_name, pv_context *ctxt)
 
static void generic_program_pointer_values (char *prog_name, pv_context *ctxt)
 
bool simple_pointer_values (const string module_name)
 interface to compute the simple pointer values of a given module More...
 
bool initial_simple_pointer_values (const string module_name)
 
bool program_simple_pointer_values (const string prog_name)
 

Macro Definition Documentation

◆ PV_NB_MAX_ITER_FIX_POINT

#define PV_NB_MAX_ITER_FIX_POINT   3

Definition at line 619 of file pointer_values_analyses.c.

◆ UNDEF

#define UNDEF   abort

Definition at line 151 of file pointer_values_analyses.c.

Typedef Documentation

◆ bool_function

typedef bool(* bool_function) ()

Definition at line 156 of file pointer_values_analyses.c.

◆ cell_relation_function

typedef cell_relation(* cell_relation_function) ()

Definition at line 160 of file pointer_values_analyses.c.

◆ chunks_function

typedef gen_chunk*(* chunks_function) ()

Definition at line 154 of file pointer_values_analyses.c.

◆ descriptor_function

typedef descriptor(* descriptor_function) ()

Definition at line 157 of file pointer_values_analyses.c.

◆ list_function

typedef list(* list_function) ()

Definition at line 155 of file pointer_values_analyses.c.

◆ statement_cell_relations_function

typedef statement_cell_relations(* statement_cell_relations_function) ()

Definition at line 158 of file pointer_values_analyses.c.

◆ statement_effects_function

typedef statement_effects(* statement_effects_function) ()

Definition at line 159 of file pointer_values_analyses.c.

◆ void_function

typedef void(* void_function) ()

Definition at line 153 of file pointer_values_analyses.c.

Function Documentation

◆ assignment_to_post_pv()

void assignment_to_post_pv ( expression  lhs,
bool  may_lhs_p,
expression  rhs,
bool  declaration_p,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)

first convert the rhs and lhs into memory paths, rhs is evaluated first

this is done even if this is a non-pointer assignment, becasue there maybe side effects on alising hidden in sub-expressions, function calls...

we should test here that lhs_pv_res.result_paths has only one element. well is it correct? can a relational operator expression be a lhs ?

l_gen = NIL; l_kill = NIL;

simple case first: lhs is a pointer

hidden pointer assignments

if (type_variable_p(lhs_type)

Parameters
lhshs
may_lhs_pay_lhs_p
rhshs
declaration_peclaration_p
l_in_in
pv_resv_res
ctxttxt

Definition at line 1582 of file pointer_values_analyses.c.

1585 {
1586  list l_in_cur = NIL;
1587  effect lhs_eff = effect_undefined;
1588 
1589  pips_debug(1, "begin with may_lhs_p = %s and declaration_p = %s\n", bool_to_string(may_lhs_p), bool_to_string(declaration_p));
1590  pips_debug_pvs(2, "input pointer values:\n", l_in);
1591  type lhs_type = expression_to_type(lhs);
1592 
1593  /* first convert the rhs and lhs into memory paths, rhs is evaluated first */
1594  /* this is done even if this is a non-pointer assignment, becasue there
1595  maybe side effects on alising hidden in sub-expressions, function calls...
1596  */
1597  pv_results lhs_pv_res = make_pv_results();
1598  pv_results rhs_pv_res = make_pv_results();
1599 
1600  expression_to_post_pv(rhs, l_in, &rhs_pv_res, ctxt);
1601  list l_rhs_eff = rhs_pv_res.result_paths;
1602  list l_rhs_kind = rhs_pv_res.result_paths_interpretations;
1603  l_in_cur = rhs_pv_res.l_out;
1604 
1605  expression_to_post_pv(lhs, l_in_cur, &lhs_pv_res, ctxt);
1606  l_in_cur = lhs_pv_res.l_out;
1607  /* we should test here that lhs_pv_res.result_paths has only one element.
1608  well is it correct? can a relational operator expression be a lhs ?
1609  */
1610  lhs_eff = EFFECT(CAR(lhs_pv_res.result_paths));
1611  if (may_lhs_p) effect_to_may_effect(lhs_eff);
1612  pv_res->result_paths = CONS(EFFECT, copy_effect(lhs_eff), NIL);
1615 
1617  {
1618  pips_debug(2, "non-pointer assignment\n");
1619  /* l_gen = NIL; l_kill = NIL; */
1620  pv_res->l_out = l_in_cur;
1621  }
1622  else
1623  {
1624  if(type_variable_p(lhs_type))
1625  {
1626  if (pointer_type_p(lhs_type)) /* simple case first: lhs is a pointer */
1627  {
1628  single_pointer_assignment_to_post_pv(lhs_eff, l_rhs_eff,
1629  l_rhs_kind,
1630  declaration_p, l_in_cur,
1631  pv_res, ctxt);
1632  }
1633  else /* hidden pointer assignments */
1634  {
1635  multiple_pointer_assignment_to_post_pv(lhs_eff, lhs_type, l_rhs_eff,
1636  l_rhs_kind,
1637  declaration_p, l_in_cur,
1638  pv_res, ctxt);
1639  }
1640  } /* if (type_variable_p(lhs_type) */
1641  else if(type_functional_p(lhs_type))
1642  {
1643  pips_internal_error("not yet implemented");
1644  }
1645  else
1646  pips_internal_error("unexpected_type");
1647  }
1648 
1649 
1650  free_pv_results_paths(&lhs_pv_res);
1651  free_pv_results_paths(&rhs_pv_res);
1652 
1653  pips_debug_pv_results(1, "end with pv_res =\n", *pv_res);
1654  return;
1655 }
cell_interpretation make_cell_interpretation_value_of(void)
Definition: effects.c:237
effect copy_effect(effect p)
EFFECT.
Definition: effects.c:448
void effect_to_may_effect(effect)
#define pips_debug_pvs(level, message, l_pv)
#define effect_undefined
Definition: effects.h:614
#define CELL_INTERPRETATION(x)
CELL_INTERPRETATION.
Definition: effects.h:375
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
#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
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
#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_internal_error
Definition: misc-local.h:149
string bool_to_string(bool)
Definition: string.c:243
#define pips_debug_pv_results(level, message, pv_res)
pv_results make_pv_results()
void expression_to_post_pv(expression exp, list l_in, pv_results *pv_res, pv_context *ctxt)
void free_pv_results_paths(pv_results *pv_res)
void single_pointer_assignment_to_post_pv(effect lhs_eff, list l_rhs_eff, list l_rhs_kind, bool declaration_p, list l_in, pv_results *pv_res, pv_context *ctxt)
void multiple_pointer_assignment_to_post_pv(effect lhs_base_eff, type lhs_type, list l_rhs_base_eff, list l_rhs_base_kind, bool declaration_p, list l_in, pv_results *pv_res, pv_context *ctxt)
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 type_fundamental_basic_p(type)
Definition: type.c:2930
bool basic_concrete_type_leads_to_pointer_p(type)
returns true when the input type successors may be pointers
Definition: type.c:3699
bool pointer_type_p(type)
Check for scalar pointers.
Definition: type.c:2993
#define type_functional_p(x)
Definition: ri.h:2950
#define type_variable_p(x)
Definition: ri.h:2947
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
pv_results is a structure holding the different results of an expression pointer values analysis
list result_paths_interpretations
resulting pointer path of the expression evaluation
list result_paths
resulting pointer_values

References basic_concrete_type_leads_to_pointer_p(), bool_to_string(), CAR, CELL_INTERPRETATION, CONS, copy_effect(), EFFECT, effect_to_may_effect(), effect_undefined, expression_to_post_pv(), expression_to_type(), free_pv_results_paths(), pv_results::l_out, make_cell_interpretation_value_of(), make_pv_results(), multiple_pointer_assignment_to_post_pv(), NIL, pips_debug, pips_debug_pv_results, pips_debug_pvs, pips_internal_error, pointer_type_p(), pv_results::result_paths, pv_results::result_paths_interpretations, single_pointer_assignment_to_post_pv(), type_functional_p, type_fundamental_basic_p(), and type_variable_p.

Referenced by assignment_intrinsic_to_post_pv(), declaration_to_post_pv(), and pointer_values_remove_var().

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

◆ call_to_post_pv()

static void call_to_post_pv ( call  c,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

We should be here only in case of a pointer value rhs, and the value should be 0

use approximation_exact to be consistent with effects, should be approximation_exact

constant strings

not generic here

Definition at line 1141 of file pointer_values_analyses.c.

1142 {
1143  entity func = call_function(c);
1144  value func_init = entity_initial(func);
1145  tag t = value_tag(func_init);
1146  list func_args = call_arguments(c);
1147  type func_type = ultimate_type(entity_type(func));
1148 
1149  pips_debug(1, "begin for %s\n", entity_local_name(func));
1150 
1151  if(type_functional_p(func_type))
1152  {
1153  switch (t)
1154  {
1155  case is_value_code:
1156  external_call_to_post_pv(c, l_in, pv_res, ctxt);
1157  break;
1158 
1159  case is_value_intrinsic:
1160  pips_debug(5, "intrinsic function\n");
1161  intrinsic_to_post_pv(func, func_args, l_in, pv_res, ctxt);
1162  break;
1163 
1164  case is_value_symbolic:
1165  pips_debug(5, "symbolic\n");
1166  pv_res->l_out = l_in;
1167  break;
1168 
1169  case is_value_constant:
1170  pips_debug(5, "constant\n");
1171  pv_res->l_out = l_in;
1172 
1173  constant func_const = value_constant(func_init);
1174  /* We should be here only in case of a pointer value rhs, and the value should be 0 */
1175  if (constant_int_p(func_const) && (constant_int(func_const) == 0))
1176  {
1177  /* use approximation_exact to be consistent with effects,
1178  should be approximation_exact */
1179  pv_res->result_paths = CONS(EFFECT,
1184  NIL);
1187  NIL);
1188  }
1189  else
1190  {
1191  type tt = functional_result(type_functional(func_type));
1192  if (type_variable_p(tt))
1193  {
1194  variable v = type_variable(tt);
1195  basic b = variable_basic(v);
1196  if (basic_string_p(b))/* constant strings */
1197  {
1198  /* not generic here */
1204  pv_res->result_paths = CONS(EFFECT, eff, NIL);
1207  NIL);
1208  }
1209  }
1210  }
1211  pv_res->l_out = l_in;
1212  break;
1213 
1214  case is_value_unknown:
1215  pips_internal_error("unknown function ");
1216  break;
1217 
1218  default:
1219  pips_internal_error("unknown tag %d", t);
1220  break;
1221  }
1222  }
1223  else if(type_variable_p(func_type))
1224  {
1225  pips_internal_error("not yet implemented");
1226  }
1227  else if(type_statement_p(func_type))
1228  {
1229  pips_internal_error("not yet implemented");
1230  }
1231  else
1232  {
1233  pips_internal_error("Unexpected case");
1234  }
1235 
1236  pips_debug_pvs(2, "returning pv_res->l_out:", pv_res->l_out);
1237  pips_debug(1, "end\n");
1238  return;
1239 }
cell make_cell_reference(reference _field_)
Definition: effects.c:293
cell_interpretation make_cell_interpretation_address_of(void)
Definition: effects.c:240
approximation make_approximation_exact(void)
Definition: effects.c:185
effect make_effect(cell a1, action a2, approximation a3, descriptor a4)
Definition: effects.c:484
descriptor make_descriptor_none(void)
Definition: effects.c:442
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
void effect_add_dereferencing_dimension(effect)
cell make_null_pointer_value_cell(void)
action make_action_read_memory(void)
Definition: effects.c:1017
int tag
TAG.
Definition: newgen_types.h:92
void intrinsic_to_post_pv(entity, list, list, pv_results *, pv_context *)
pointer_values_intrinsics.c
static void external_call_to_post_pv(call c, list l_in, pv_results *pv_res, pv_context *ctxt)
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
type ultimate_type(type)
Definition: type.c:3466
#define value_tag(x)
Definition: ri.h:3064
#define functional_result(x)
Definition: ri.h:1444
#define value_constant(x)
Definition: ri.h:3073
#define call_function(x)
Definition: ri.h:709
#define constant_int(x)
Definition: ri.h:850
#define type_functional(x)
Definition: ri.h:2952
#define type_variable(x)
Definition: ri.h:2949
#define type_statement_p(x)
Definition: ri.h:2941
@ is_value_intrinsic
Definition: ri.h:3034
@ is_value_unknown
Definition: ri.h:3035
@ is_value_constant
Definition: ri.h:3033
@ is_value_code
Definition: ri.h:3031
@ is_value_symbolic
Definition: ri.h:3032
#define constant_int_p(x)
Definition: ri.h:848
#define call_arguments(x)
Definition: ri.h:711
#define basic_string_p(x)
Definition: ri.h:629
#define entity_type(x)
Definition: ri.h:2792
#define variable_basic(x)
Definition: ri.h:3120
#define entity_initial(x)
Definition: ri.h:2796

References basic_string_p, call_arguments, call_function, CELL_INTERPRETATION, CONS, constant_int, constant_int_p, EFFECT, effect_add_dereferencing_dimension(), entity_initial, entity_local_name(), entity_type, external_call_to_post_pv(), functional_result, intrinsic_to_post_pv(), is_value_code, is_value_constant, is_value_intrinsic, is_value_symbolic, is_value_unknown, pv_results::l_out, make_action_read_memory(), make_approximation_exact(), make_cell_interpretation_address_of(), make_cell_interpretation_value_of(), make_cell_reference(), make_descriptor_none(), make_effect(), make_null_pointer_value_cell(), make_reference(), NIL, pips_debug, pips_debug_pvs, pips_internal_error, pv_results::result_paths, pv_results::result_paths_interpretations, type_functional, type_functional_p, type_statement_p, type_variable, type_variable_p, ultimate_type(), value_constant, value_tag, and variable_basic.

Referenced by expression_to_post_pv(), and instruction_to_post_pv().

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

◆ db_get_in_simple_pv()

list db_get_in_simple_pv ( const char *  module_name)
Parameters
module_nameodule_name

Definition at line 73 of file pointer_values_analyses.c.

74 {
75  return (list) cell_relations_list((cell_relations) db_get_memory_resource(DBR_IN_SIMPLE_POINTER_VALUES, module_name, true));
76 }
#define cell_relations_list(x)
Definition: effects.h:549
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755

References cell_relations_list, db_get_memory_resource(), and module_name().

Referenced by make_simple_pv_context().

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

◆ db_get_initial_simple_pv()

list db_get_initial_simple_pv ( const char *  module_name)
Parameters
module_nameodule_name

Definition at line 93 of file pointer_values_analyses.c.

94 {
95  return cell_relations_list((cell_relations) db_get_memory_resource(DBR_INITIAL_SIMPLE_POINTER_VALUES, module_name, true));
96 }

References cell_relations_list, db_get_memory_resource(), and module_name().

Referenced by make_simple_pv_context().

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

◆ db_get_out_simple_pv()

list db_get_out_simple_pv ( const char *  module_name)
Parameters
module_nameodule_name

Definition at line 83 of file pointer_values_analyses.c.

84 {
85  return cell_relations_list((cell_relations) db_get_memory_resource(DBR_OUT_SIMPLE_POINTER_VALUES, module_name, true));
86 }

References cell_relations_list, db_get_memory_resource(), and module_name().

Referenced by make_simple_pv_context().

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

◆ db_get_program_simple_pv()

list db_get_program_simple_pv ( void  )

Definition at line 103 of file pointer_values_analyses.c.

104 {
105  return cell_relations_list((cell_relations) db_get_memory_resource(DBR_PROGRAM_SIMPLE_POINTER_VALUES, "", true));
106 }

References cell_relations_list, and db_get_memory_resource().

Referenced by make_simple_pv_context().

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

◆ db_get_simple_pv()

statement_cell_relations db_get_simple_pv ( const char *  module_name)

I don't know how to deal with these mappings if we have to analyse several modules at the same time when performing an interprocedural analysis.

We may need a stack of mappings, or a global mapping for the whole program, and a temporary mapping to store the resources one module at a time

Parameters
module_nameodule_name

Definition at line 63 of file pointer_values_analyses.c.

64 {
65  return (statement_cell_relations) db_get_memory_resource(DBR_SIMPLE_POINTER_VALUES, module_name, true);
66 }

References db_get_memory_resource(), and module_name().

Referenced by make_simple_pv_context().

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

◆ db_put_in_simple_pv()

void db_put_in_simple_pv ( const char *  module_name,
list  l_pv 
)
Parameters
module_nameodule_name
l_pv_pv

Definition at line 78 of file pointer_values_analyses.c.

79 {
80  DB_PUT_MEMORY_RESOURCE(DBR_IN_SIMPLE_POINTER_VALUES, module_name, (char*) make_cell_relations(l_pv));
81 }
cell_relations make_cell_relations(list a)
Definition: effects.c:383
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66

References DB_PUT_MEMORY_RESOURCE, make_cell_relations(), and module_name().

Referenced by make_simple_pv_context().

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

◆ db_put_initial_simple_pv()

void db_put_initial_simple_pv ( const char *  module_name,
list  l_pv 
)
Parameters
module_nameodule_name
l_pv_pv

Definition at line 98 of file pointer_values_analyses.c.

99 {
100  DB_PUT_MEMORY_RESOURCE(DBR_INITIAL_SIMPLE_POINTER_VALUES, module_name, (char*) make_cell_relations(l_pv));
101 }

References DB_PUT_MEMORY_RESOURCE, make_cell_relations(), and module_name().

Referenced by make_simple_pv_context().

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

◆ db_put_out_simple_pv()

void db_put_out_simple_pv ( const char *  module_name,
list  l_pv 
)
Parameters
module_nameodule_name
l_pv_pv

Definition at line 88 of file pointer_values_analyses.c.

89 {
90  DB_PUT_MEMORY_RESOURCE(DBR_OUT_SIMPLE_POINTER_VALUES, module_name, (char*) make_cell_relations(l_pv));
91 }

References DB_PUT_MEMORY_RESOURCE, make_cell_relations(), and module_name().

Referenced by make_simple_pv_context().

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

◆ db_put_program_simple_pv()

void db_put_program_simple_pv ( list  l_pv)
Parameters
l_pv_pv

Definition at line 108 of file pointer_values_analyses.c.

109 {
110  DB_PUT_MEMORY_RESOURCE(DBR_PROGRAM_SIMPLE_POINTER_VALUES, "", (char*) make_cell_relations(l_pv));
111 }

References DB_PUT_MEMORY_RESOURCE, and make_cell_relations().

Referenced by make_simple_pv_context().

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

◆ db_put_simple_pv()

void db_put_simple_pv ( const char *  module_name,
statement_cell_relations  scr 
)
Parameters
module_nameodule_name
scrcr

Definition at line 68 of file pointer_values_analyses.c.

69 {
70  DB_PUT_MEMORY_RESOURCE(DBR_SIMPLE_POINTER_VALUES, module_name, (char*) scr);
71 }

References DB_PUT_MEMORY_RESOURCE, and module_name().

Referenced by make_simple_pv_context().

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

◆ declaration_to_post_pv()

static list declaration_to_post_pv ( entity  e,
list  l_in,
pv_context ctxt 
)
static

turned to true if rhs_exp is built and must be freed

in case of a local static variable, and when not dealing with the initial analysis, we should generate a stub sink

when no initialization is provided for pointer static variables, or aggregate variables which recursively have pointer fields, then all pointers are initialized to NULL previous to program execution.

Definition at line 408 of file pointer_values_analyses.c.

409 {
410  list l_out = NIL;
411  type e_type = entity_basic_concrete_type(e);
412 
413  if (type_variable_p(e_type) && !typedef_entity_p(e)
414  && !type_fundamental_basic_p(e_type)
416  {
417  pips_debug(1, "begin\n");
418  pips_debug(1, "entity %s basic concrete type %s %s\n",
419  entity_name(e), type_to_string(e_type), string_of_type(e_type));
420  expression lhs_exp = entity_to_expression(e);
422  bool free_rhs_exp = false; /* turned to true if rhs_exp is built and
423  must be freed */
424 
425  value v_init = entity_initial(e);
426  bool static_p = (!ctxt->initial_pointer_values_p) && entity_static_variable_p(e);
427 
428  bool ignore = false;
429 
430 
431  /* in case of a local static variable, and when not dealing with the initial analysis,
432  we should generate a stub sink */
433 
434  if (v_init == value_undefined)
435  {
436  pips_debug(2, "undefined inital value\n");
437 
438  if (std_file_entity_p(e))
439  {
440  pips_debug(2, "standard file\n");
442  rhs_exp = make_address_of_expression(tmp_exp);
443  free_expression(tmp_exp);
444  }
445  else if (static_p)
446  /* when no initialization is provided for pointer static variables,
447  or aggregate variables which recursively have pointer fields,
448  then all pointers are initialized to NULL previous to program
449  execution.
450  */
452  else
454  free_rhs_exp = true;
455  }
456  else if (std_file_entity_p(e))
457  {
458  pips_debug(2, "standard file\n");
460  rhs_exp = make_address_of_expression(tmp_exp);
461  free_expression(tmp_exp);
462  free_rhs_exp = true;
463  }
464  else
465  {
466  switch (value_tag(v_init))
467  {
468  case is_value_expression:
469  rhs_exp = value_expression(v_init);
470  break;
471  case is_value_unknown:
472  pips_debug(2, "unknown inital value\n");
473  rhs_exp = expression_undefined;
474  break;
475  case is_value_code:
476  pips_debug(2, "value code\n");
478  {
479  const char * e_user_name = entity_user_name(e);
480  if (same_string_p(e_user_name, "__after_morecore_hook")
481  || same_string_p(e_user_name, "__free_hook")
482  || same_string_p(e_user_name, "__malloc_hook")
483  || same_string_p(e_user_name, "__malloc_initialize_hook")
484  || same_string_p(e_user_name, "__memalign_hook")
485  || same_string_p(e_user_name, "__morecore")
486  || same_string_p(e_user_name, "__realloc_hook"))
487  {
488  pips_debug(2, "standard library internal hook\n");
489  ignore = true;
490  }
491  else
492  {
493  pips_debug(2,"compilation unit, ignoring value for the moment\n");
494  }
495  }
496  else
497  pips_internal_error("unexpected tag\n");
498  break;
499  case is_value_symbolic:
500  pips_debug(2, "value symbolic\n");
501  pips_internal_error("unexpected tag\n");
502  break;
503  case is_value_constant:
504  pips_debug(2, "value constant\n");
505  pips_internal_error("unexpected tag\n");
506  break;
507  case is_value_intrinsic:
508  pips_debug(2, "value intrinsic\n");
509  pips_internal_error("unexpected tag\n");
510  break;
511  default:
512  pips_internal_error("unexpected tag\n");
513  }
514  }
515 
516  if (!ignore)
517  {
518  pv_results pv_res = make_pv_results();
519  assignment_to_post_pv(lhs_exp, static_p, rhs_exp, true, l_in, &pv_res, ctxt);
520  l_out = pv_res.l_out;
521  free_pv_results_paths(&pv_res);
522 
523  free_expression(lhs_exp);
524  if (free_rhs_exp) free_expression(rhs_exp);
525  pips_debug_pvs(2, "returning:", l_out);
526  pips_debug(1, "end\n");
527  }
528  else
529  l_out = l_in;
530  }
531  else
532  l_out = l_in;
533  return (l_out);
534 }
void free_expression(expression p)
Definition: ri.c:853
entity null_pointer_value_entity(void)
entity undefined_pointer_value_entity(void)
pointer_values.c
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#define same_string_p(s1, s2)
void assignment_to_post_pv(expression lhs, bool may_lhs_p, expression rhs, bool declaration_p, list l_in, pv_results *pv_res, pv_context *ctxt)
string string_of_type(const type)
Definition: type.c:56
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
bool std_file_entity_p(entity e)
Definition: entity.c:1232
bool typedef_entity_p(entity e)
Definition: entity.c:1902
entity std_file_entity_to_pointed_file_entity(entity e)
Dummy standard files targets.
Definition: entity.c:1243
expression make_address_of_expression(expression e)
generate a newly allocated expression for &(e)
Definition: expression.c:3956
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
bool compilation_unit_entity_p(entity e)
Check if the given module entity is a compilation unit.
Definition: module.c:87
bool entity_static_variable_p(entity)
return true if the entity is declared with the keyword static
Definition: variable.c:1146
type entity_basic_concrete_type(entity)
retrieves or computes and then returns the basic concrete type of an entity
Definition: type.c:3677
string type_to_string(const type)
type.c
Definition: type.c:51
#define value_undefined
Definition: ri.h:3016
@ is_value_expression
Definition: ri.h:3036
#define expression_undefined
Definition: ri.h:1223
#define entity_name(x)
Definition: ri.h:2790
#define value_expression(x)
Definition: ri.h:3082
bool initial_pointer_values_p
ANALYSIS CONTROL.

References assignment_to_post_pv(), basic_concrete_type_leads_to_pointer_p(), compilation_unit_entity_p(), entity_basic_concrete_type(), entity_initial, entity_name, entity_static_variable_p(), entity_to_expression(), entity_user_name(), expression_undefined, free_expression(), free_pv_results_paths(), get_current_module_entity(), pv_context::initial_pointer_values_p, is_value_code, is_value_constant, is_value_expression, is_value_intrinsic, is_value_symbolic, is_value_unknown, pv_results::l_out, make_address_of_expression(), make_pv_results(), NIL, null_pointer_value_entity(), pips_debug, pips_debug_pvs, pips_internal_error, same_string_p, std_file_entity_p(), std_file_entity_to_pointed_file_entity(), string_of_type(), type_fundamental_basic_p(), type_to_string(), type_variable_p, typedef_entity_p(), undefined_pointer_value_entity(), value_expression, value_tag, and value_undefined.

Referenced by declarations_to_post_pv(), generic_module_initial_pointer_values(), and sequence_to_post_pv().

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

◆ declarations_to_post_pv()

static list declarations_to_post_pv ( list  l_decl,
list  l_in,
pv_context ctxt 
)
static

well, not exactly, we must take kills into account

Definition at line 391 of file pointer_values_analyses.c.

392 {
393  list l_out = l_in;
394  pips_debug(1, "begin\n");
395 
396  FOREACH(ENTITY, e, l_decl)
397  {
398  /* well, not exactly, we must take kills into account */
399  l_out = gen_nconc(l_out, declaration_to_post_pv(e, l_out, ctxt));
400  }
401  pips_debug_pvs(2, "returning: ", l_out);
402  pips_debug(1, "end\n");
403  return (l_out);
404 }
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#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
static list declaration_to_post_pv(entity e, list l_in, pv_context *ctxt)
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755

References declaration_to_post_pv(), ENTITY, FOREACH, gen_nconc(), pips_debug, and pips_debug_pvs.

Referenced by statement_to_post_pv().

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

◆ expression_to_post_pv()

void expression_to_post_pv ( expression  exp,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)

we assume no effects on aliases due to subscripts evaluations for the moment

we assume no effects on aliases due to sizeof argument expression for the moment

aborts if there are calls in subscript expressions

free the spine

we assume no effects on aliases due to subscripts evaluations for the moment

Parameters
expxp
l_in_in
pv_resv_res
ctxttxt

Definition at line 930 of file pointer_values_analyses.c.

931 {
933  {
934  pips_debug(1, "begin for undefined expression, returning undefined pointer_value\n");
935  pv_res->l_out = l_in;
942  }
943  else
944  {
945  pips_debug(1, "begin for expression : %s\n",
947 
948  syntax exp_syntax = expression_syntax(exp);
949 
950  switch(syntax_tag(exp_syntax))
951  {
952  case is_syntax_reference:
953  pips_debug(5, "reference case\n");
954  reference exp_ref = syntax_reference(exp_syntax);
955  if (same_string_p(entity_local_name(reference_variable(exp_ref)), "NULL"))
956  {
963  NIL);
964  }
965  else
966  {
967  // functions that can be pointed by reference_to_effect_func:
968  // reference_to_simple_effect
969  // reference_to_convex_region
970  // reference_to_reference_effect
971  pv_res->result_paths = CONS(EFFECT,
973  (copy_reference(exp_ref),
975  false), NIL);
978  NIL);
979  }
980  /* we assume no effects on aliases due to subscripts evaluations for the moment */
981  pv_res->l_out = l_in;
982  break;
983  case is_syntax_range:
984  pips_internal_error("not yet implemented");
985  break;
986  case is_syntax_call:
987  {
988  call_to_post_pv(syntax_call(exp_syntax), l_in, pv_res, ctxt);
989  break;
990  }
991  case is_syntax_cast:
992  {
994  l_in, pv_res, ctxt);
995  pips_debug(5, "cast case\n");
996  break;
997  }
999  {
1000  /* we assume no effects on aliases due to sizeof argument expression
1001  * for the moment */
1002  pv_res->l_out = l_in;
1003  break;
1004  }
1005  case is_syntax_subscript:
1006  {
1007  pips_debug(5, "subscript case\n");
1008  /* aborts if there are calls in subscript expressions */
1009  list l_eff = NIL;
1011  gen_full_free_list(l_tmp);
1012  FOREACH(EFFECT, eff, l_eff)
1013  {
1014  pv_res->result_paths = CONS(EFFECT, eff, NIL);
1017  NIL);
1018  }
1019  gen_free_list(l_eff); /* free the spine */
1020  /* we assume no effects on aliases due to subscripts evaluations for the moment */
1021  pv_res->l_out = l_in;
1022  break;
1023  }
1024  case is_syntax_application:
1025  pips_internal_error("not yet implemented");
1026  break;
1027  case is_syntax_va_arg:
1028  {
1029  pips_internal_error("not yet implemented");
1030  break;
1031  }
1032  default:
1033  pips_internal_error("unexpected tag %d", syntax_tag(exp_syntax));
1034  break;
1035  }
1036  }
1037 
1038  pips_debug_pv_results(1, "end with pv_results =\n", *pv_res);
1039  pips_debug(1, "end\n");
1040  return;
1041 }
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
list generic_proper_effects_of_complex_address_expression(expression, list *, int)
effect(* reference_to_effect_func)(reference, action, bool)
action make_action_write_memory(void)
To ease the extension of action with action_kind.
Definition: effects.c:1011
cell make_undefined_pointer_value_cell(void)
void gen_full_free_list(list l)
Definition: genClib.c:1023
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
static void call_to_post_pv(call c, list l_in, pv_results *pv_res, pv_context *ctxt)
string expression_to_string(expression e)
Definition: expression.c:77
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#define reference_variable(x)
Definition: ri.h:2326
#define syntax_cast(x)
Definition: ri.h:2739
@ 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 cast_expression(x)
Definition: ri.h:747
#define syntax_call(x)
Definition: ri.h:2736
#define expression_undefined_p(x)
Definition: ri.h:1224
#define expression_syntax(x)
Definition: ri.h:1247
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207

References call_to_post_pv(), cast_expression, CELL_INTERPRETATION, CONS, copy_reference(), EFFECT, entity_local_name(), exp, expression_syntax, expression_to_post_pv(), expression_to_string(), expression_undefined_p, FOREACH, gen_free_list(), gen_full_free_list(), generic_proper_effects_of_complex_address_expression(), is_syntax_application, is_syntax_call, is_syntax_cast, is_syntax_range, is_syntax_reference, is_syntax_sizeofexpression, is_syntax_subscript, is_syntax_va_arg, pv_results::l_out, make_action_read_memory(), make_action_write_memory(), make_approximation_exact(), make_cell_interpretation_value_of(), make_descriptor_none(), make_effect(), make_null_pointer_value_cell(), make_undefined_pointer_value_cell(), NIL, pips_debug, pips_debug_pv_results, pips_internal_error, reference_to_effect_func, reference_variable, pv_results::result_paths, pv_results::result_paths_interpretations, same_string_p, syntax_call, syntax_cast, syntax_reference, and syntax_tag.

Referenced by address_of_to_post_pv(), assignment_to_post_pv(), binary_arithmetic_operator_to_post_pv(), c_return_to_post_pv(), conditional_operator_to_post_pv(), default_intrinsic_to_post_pv(), dereferencing_to_post_pv(), expression_to_post_pv(), external_call_to_post_pv(), field_to_post_pv(), forloop_to_post_pv(), heap_intrinsic_to_post_pv(), instruction_to_post_pv(), logical_operator_to_post_pv(), point_to_to_post_pv(), range_to_post_pv(), safe_intrinsic_to_post_pv(), test_to_post_pv(), unary_arithmetic_operator_to_post_pv(), update_operator_to_post_pv(), and whileloop_to_post_pv().

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

◆ external_call_to_post_pv()

static void external_call_to_post_pv ( call  c,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

the expression that denotes the called function and the arguments are evaluated; then there is a sequence point, and the function is called

Arguments evaluation: we don't use expressions_to_post_pv because we want to accumulate the results paths

Function call: we generate abstract_location targets for all possible effects from arguments. We should also do the same for all global variables in the current compilation unit...

to avoid too long paths until GAPS are handled

only pointers

Return value: test the type of the result path : if it's a pointer type, generate an abstract location target of the pointed type, else it's an empty set/list.

Definition at line 1046 of file pointer_values_analyses.c.

1047 {
1048  entity func = call_function(c);
1049  list func_args = call_arguments(c);
1050  pips_debug(1, "begin for %s\n", entity_local_name(func));
1051 
1052  /* the expression that denotes the called function and the arguments
1053  * are evaluated; then there is a sequence point, and the function is called
1054  */
1055 
1056  /* Arguments evaluation: we don't use expressions_to_post_pv because
1057  * we want to accumulate the results paths
1058  */
1059 
1060  list l_cur = l_in;
1061  pv_results pv_res_exp_eval = make_pv_results();
1062  FOREACH(EXPRESSION, arg, func_args)
1063  {
1064  pv_results pv_res_cur = make_pv_results();
1065  expression_to_post_pv(arg, l_cur, &pv_res_cur, ctxt);
1066  l_cur = pv_res_cur.l_out;
1067  pv_res_exp_eval.result_paths = gen_nconc(pv_res_exp_eval.result_paths, pv_res_cur.result_paths);
1068  pv_res_exp_eval.result_paths_interpretations = gen_nconc(pv_res_exp_eval.result_paths_interpretations,
1069  pv_res_cur.result_paths_interpretations);
1070  }
1071 
1072  /* Function call: we generate abstract_location targets for all
1073  * possible effects from arguments. We should also do the same for
1074  * all global variables in the current compilation unit...
1075  */
1076  list l_ci = pv_res_exp_eval.result_paths_interpretations;
1077  FOREACH(EFFECT, real_arg_eff, pv_res_exp_eval.result_paths)
1078  {
1079  pips_debug_effect(3, "considering effect:\n", real_arg_eff);
1081  bool add_eff = cell_interpretation_address_of_p(ci);
1082  bool to_be_freed = false;
1083  type t = cell_to_type(effect_cell(real_arg_eff), &to_be_freed);
1084 
1085  // generate all possible effects on pointers from the actual parameter
1087  t,
1088  'w',
1089  add_eff,
1090  10, /* to avoid too long paths until GAPS are handled */
1091  true); /* only pointers */
1092  if (to_be_freed) free_type(t);
1093  pips_debug_effects(3, "effects to be killed:\n", lw);
1094 
1095  if (!ENDP(lw))
1096  {
1097  // potentially kill these paths and generate abstract location targets (currently anywhere)
1101  FOREACH(EFFECT, eff, lw)
1102  {
1103  single_pointer_assignment_to_post_pv(eff, l_abstract_eff, l_ci_abstract_eff,
1104  false, l_cur,
1105  pv_res, ctxt);
1106  l_cur = pv_res->l_out;
1107  }
1108 
1109  gen_full_free_list(lw);
1110  }
1111  POP(l_ci);
1112  }
1113  pv_res->l_out = l_cur;
1114 
1115  /* Return value: test the type of the result path : if it's a
1116  * pointer type, generate an abstract location target of the pointed
1117  * type, else it's an empty set/list.
1118  */
1120  if (pointer_type_p(func_res_t))
1121  {
1123  NIL);
1126  NIL);
1127  }
1128  else
1129  {
1130  pv_res->result_paths = NIL;
1132  }
1133  free_type(func_res_t);
1134 
1135  pips_debug_pvs(2, "returning pv_res->l_out:", pv_res->l_out);
1136  pips_debug(1, "end\n");
1137  return;
1138 }
void free_type(type p)
Definition: ri.c:2658
#define pips_debug_effects(level, message, l_eff)
#define pips_debug_effect(level, message, eff)
for debug
void effects_to_may_effects(list)
effect make_anywhere_effect(action)
list generic_effect_generate_all_accessible_paths_effects_with_level(effect, type, tag, bool, int, bool)
type cell_to_type(cell, bool *)
Definition: type.c:513
#define cell_interpretation_address_of_p(x)
Definition: effects.h:418
#define effect_cell(x)
Definition: effects.h:640
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
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 EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217

References call_arguments, call_function, CAR, CELL_INTERPRETATION, cell_interpretation_address_of_p, cell_to_type(), compute_basic_concrete_type(), CONS, EFFECT, effect_cell, effects_to_may_effects(), ENDP, entity_local_name(), entity_type, EXPRESSION, expression_to_post_pv(), FOREACH, free_type(), functional_result, gen_full_free_list(), gen_nconc(), generic_effect_generate_all_accessible_paths_effects_with_level(), pv_results::l_out, make_action_write_memory(), make_anywhere_effect(), make_cell_interpretation_address_of(), make_pv_results(), NIL, pips_debug, pips_debug_effect, pips_debug_effects, pips_debug_pvs, pointer_type_p(), POP, pv_results::result_paths, pv_results::result_paths_interpretations, single_pointer_assignment_to_post_pv(), and type_functional.

Referenced by call_to_post_pv().

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

◆ forloop_to_post_pv()

static list forloop_to_post_pv ( forloop  l,
list  l_in,
pv_context ctxt 
)
static

First, the initialization is always evaluatated

saved in case fix point is not reached

condition is evaluated before each iteration

increment expression is evaluated at the end of each iteration

this iteration may never be executed :

now update input pointer values of inner loop statements

Definition at line 794 of file pointer_values_analyses.c.

795 {
796  list l_out = NIL;
797  list l_in_cur = NIL;
798  pips_debug(1, "begin\n");
799 
801  expression cond = forloop_condition(l);
802  expression incr = forloop_increment(l);
803  statement body = forloop_body(l);
804 
805  /* First, the initialization is always evaluatated */
806  pv_results pv_res_init = make_pv_results();
807  expression_to_post_pv(init, l_in, &pv_res_init, ctxt);
808  l_in_cur = pv_res_init.l_out;
809  l_in = gen_full_copy_list(l_in_cur); /* saved in case fix point is not reached */
810  free_pv_results_paths(&pv_res_init);
811 
812  int i = 1;
813  bool fix_point_reached = false;
814  l_out = l_in_cur;
815  do
816  {
817  pips_debug(3, "fix point iteration number %d.\n", i);
818  list l_iter_in = gen_full_copy_list(l_out);
819  l_in_cur = l_out;
820 
821  /* condition is evaluated before each iteration */
822  pv_results pv_res_cond = make_pv_results();
823  expression_to_post_pv(cond, l_in_cur, &pv_res_cond, ctxt);
824  l_in_cur = pv_res_cond.l_out;
825  free_pv_results_paths(&pv_res_cond);
826 
827  l_in_cur = statement_to_post_pv(body, l_in_cur, ctxt);
828 
829  /* increment expression is evaluated at the end of each iteration */
830  pv_results pv_res_incr = make_pv_results();
831  expression_to_post_pv(incr, l_in_cur, &pv_res_incr, ctxt);
832  l_in_cur = pv_res_incr.l_out;
833  free_pv_results_paths(&pv_res_incr);
834 
835  /* this iteration may never be executed :*/
836  l_out = (*ctxt->pvs_may_union_func)(l_in_cur,
837  gen_full_copy_list(l_iter_in));
838  i++;
839  fix_point_reached = (l_out == l_iter_in)
840  || (*ctxt->pvs_equal_p_func)(l_iter_in, l_out);
841  pips_debug(3, "fix point %s reached\n", fix_point_reached? "":"not");
842  gen_full_free_list(l_iter_in);
843  }
844  while(i<=PV_NB_MAX_ITER_FIX_POINT && !fix_point_reached);
845 
846  if (!fix_point_reached)
847  {
848  pv_results pv_res_failed = make_pv_results();
850  list l_anywhere = CONS(EFFECT, anywhere_eff, NIL);
851  list l_kind = CONS(CELL_INTERPRETATION,
853  single_pointer_assignment_to_post_pv(anywhere_eff, l_anywhere, l_kind,
854  false, l_in,
855  &pv_res_failed, ctxt);
856  l_out = pv_res_failed.l_out;
857  free_pv_results_paths(&pv_res_failed);
858  free_effect(anywhere_eff);
859  gen_free_list(l_anywhere);
860  gen_full_free_list(l_kind);
861 
862  /* now update input pointer values of inner loop statements */
863  l_in_cur = gen_full_copy_list(l_out);
864  pv_results pv_res_cond = make_pv_results();
865  expression_to_post_pv(cond, l_in_cur, &pv_res_cond, ctxt);
866  l_in_cur = pv_res_cond.l_out;
867  free_pv_results_paths(&pv_res_cond);
868 
869  list l_tmp = statement_to_post_pv(body, l_in_cur, ctxt);
870 
871  gen_full_free_list(l_tmp);
872  }
873 
874 
875  pips_debug_pvs(2, "returning:", l_out);
876  pips_debug(1, "end\n");
877  return (l_out);
878 }
void free_effect(effect p)
Definition: effects.c:451
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
#define PV_NB_MAX_ITER_FIX_POINT
static list statement_to_post_pv(statement stmt, list l_in, pv_context *ctxt)
static int init
Maximal value set for Fortran 77.
Definition: entity.c:320
#define forloop_initialization(x)
Definition: ri.h:1366
#define forloop_increment(x)
Definition: ri.h:1370
#define forloop_condition(x)
Definition: ri.h:1368
#define forloop_body(x)
Definition: ri.h:1372
list(* pvs_may_union_func)(list, list)
bool(* pvs_equal_p_func)(list, list)

References CELL_INTERPRETATION, CONS, EFFECT, expression_to_post_pv(), forloop_body, forloop_condition, forloop_increment, forloop_initialization, free_effect(), free_pv_results_paths(), gen_free_list(), gen_full_copy_list(), gen_full_free_list(), init, pv_results::l_out, make_action_write_memory(), make_anywhere_effect(), make_cell_interpretation_address_of(), make_pv_results(), NIL, pips_debug, pips_debug_pvs, PV_NB_MAX_ITER_FIX_POINT, pv_context::pvs_equal_p_func, pv_context::pvs_may_union_func, single_pointer_assignment_to_post_pv(), and statement_to_post_pv().

Referenced by instruction_to_post_pv().

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

◆ free_pv_results_paths()

◆ generic_module_initial_pointer_values()

static void generic_module_initial_pointer_values ( char *  module_name,
pv_context ctxt 
)
static

Definition at line 1835 of file pointer_values_analyses.c.

1836 {
1838  db_get_memory_resource(DBR_CODE, module_name, true));
1840  init_pv();
1841 
1842  debug_on("POINTER_VALUES_DEBUG_LEVEL");
1843  pips_debug(1, "begin\n");
1845 
1846  list l_in = NIL;
1847  list l_cur = l_in;
1848  FOREACH(ENTITY, decl, l_decl)
1849  {
1850  if(variable_static_p(decl))
1851  {
1852  l_cur = declaration_to_post_pv(decl, l_cur, ctxt);
1853  }
1854  }
1855  list l_out = l_cur;
1856 
1857  pips_debug_pvs(1, "Resulting pointer values:\n", l_out);
1858 
1859  (*ctxt->db_put_initial_pv_func)(module_name, l_out);
1860 
1861  pips_debug(1, "end\n");
1862  debug_off();
1865 
1866  reset_pv();
1867 
1868  return;
1869 }
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
#define debug_on(env)
Definition: misc-local.h:157
#define debug_off()
Definition: misc-local.h:160
void init_pv(void)
void reset_pv(void)
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
bool variable_static_p(entity)
true if v appears in a SAVE statement, or in a DATA statement, or is declared static i C.
Definition: variable.c:1579
void(* db_put_initial_pv_func)(const char *, list)
list module_to_all_declarations(entity m)
Definition: module.c:323

References db_get_memory_resource(), pv_context::db_put_initial_pv_func, debug_off, debug_on, declaration_to_post_pv(), ENTITY, FOREACH, get_current_module_entity(), init_pv(), module_name(), module_name_to_entity(), module_to_all_declarations(), NIL, pips_debug, pips_debug_pvs, reset_current_module_entity(), reset_current_module_statement(), reset_pv(), set_current_module_entity(), set_current_module_statement(), and variable_static_p().

Referenced by initial_simple_pointer_values().

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

◆ generic_module_pointer_values()

static void generic_module_pointer_values ( char *  module_name,
pv_context ctxt 
)
static

generic interface to compute the pointer values of a given module

Parameters
module_nameis the name of the module
ctxtgives the functions specific to the kind of pointer values to be computed.

temporary settings : in an interprocedural context we need to keep track of visited modules

Get the code of the module.

Definition at line 1798 of file pointer_values_analyses.c.

1799 {
1800 
1801  /* temporary settings : in an interprocedural context we need to keep track
1802  of visited modules */
1803  /* Get the code of the module. */
1805  db_get_memory_resource(DBR_CODE, module_name, true));
1807  init_pv();
1808 
1809  debug_on("POINTER_VALUES_DEBUG_LEVEL");
1810  pips_debug(1, "begin\n");
1811 
1812  list l_init = module_initial_parameter_pv();
1814  {
1815  l_init = (*ctxt->pvs_must_union_func)(l_init, gen_full_copy_list( (*ctxt->db_get_program_pv_func)() ));
1816  }
1817 
1819 
1820  (*ctxt->db_put_pv_func)(module_name, get_pv());
1821  (*ctxt->db_put_in_pv_func)(module_name, l_init);
1822  (*ctxt->db_put_out_pv_func)(module_name, l_out);
1823 
1824  pips_debug(1, "end\n");
1825  debug_off();
1828 
1829  reset_pv();
1830 
1831  return;
1832 }
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
statement_cell_relations get_pv(void)
static list module_initial_parameter_pv()
bool entity_main_module_p(entity e)
Definition: entity.c:700
list(* pvs_must_union_func)(list, list)
BINARY OPERATORS.
list(* db_get_program_pv_func)()
void(* db_put_out_pv_func)(const char *, list)
void(* db_put_in_pv_func)(const char *, list)
void(* db_put_pv_func)(const char *, statement_cell_relations)

References db_get_memory_resource(), pv_context::db_get_program_pv_func, pv_context::db_put_in_pv_func, pv_context::db_put_out_pv_func, pv_context::db_put_pv_func, debug_off, debug_on, entity_main_module_p(), gen_full_copy_list(), get_current_module_entity(), get_current_module_statement(), get_pv(), init_pv(), module_initial_parameter_pv(), module_name(), module_name_to_entity(), pips_debug, pv_context::pvs_must_union_func, reset_current_module_entity(), reset_current_module_statement(), reset_pv(), set_current_module_entity(), set_current_module_statement(), and statement_to_post_pv().

Referenced by simple_pointer_values().

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

◆ generic_program_pointer_values()

static void generic_program_pointer_values ( char *  prog_name,
pv_context ctxt 
)
static

Unavoidable pitfall: initializations in uncalled modules may be taken into account. It all depends on the "create" command.

Definition at line 1871 of file pointer_values_analyses.c.

1872 {
1874  list l_out = NIL;
1875  pips_assert("main was found", the_main!=entity_undefined);
1876 
1877  debug_on("POINTER_VALUES_DEBUG_LEVEL");
1878  pips_debug(1, "begin\n");
1879  pips_debug(1, "considering program \"%s\" with main \"%s\"\n", prog_name,
1880  module_local_name(the_main));
1881  /* Unavoidable pitfall: initializations in uncalled modules may be
1882  * taken into account. It all depends on the "create" command.
1883  */
1884  gen_array_t modules = db_get_module_list();
1885  int nmodules = gen_array_nitems(modules);
1886  pips_assert("some modules in the program", nmodules>0);
1887 
1888  for(int i=0; i<nmodules; i++)
1889  {
1890  string module_name = gen_array_item(modules, i);
1891  pips_debug(1, "considering module %s\n", module_name);
1892 
1894  list l_cur = (ctxt->db_get_initial_pv_func)(module_name);
1895  pips_debug_pvs(2, "module initial pvs: \n", l_cur);
1897  l_out = gen_nconc(gen_full_copy_list(l_cur), l_out);
1898  }
1899 
1900  set_current_module_entity(the_main);
1901  pips_debug_pvs(2, "storing program pvs: \n", l_out);
1903 
1904  (*ctxt->db_put_program_pv_func)(l_out);
1905  pips_debug(1, "end\n");
1906  debug_off();
1907  return;
1908 }
size_t gen_array_nitems(const gen_array_t a)
Definition: array.c:131
void * gen_array_item(const gen_array_t a, size_t i)
Definition: array.c:143
gen_array_t db_get_module_list(void)
Get an array of all the modules (functions, procedures and compilation units) of a workspace.
Definition: database.c:1266
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
string get_main_entity_name(void)
Return the local name of the main module if it is available, or the local name of any module by defau...
Definition: util.c:63
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
#define entity_undefined
Definition: ri.h:2761
list(* db_get_initial_pv_func)(const char *)
void(* db_put_program_pv_func)(list)

References pv_context::db_get_initial_pv_func, db_get_module_list(), pv_context::db_put_program_pv_func, debug_off, debug_on, entity_undefined, gen_array_item(), gen_array_nitems(), gen_full_copy_list(), gen_nconc(), get_main_entity_name(), module_local_name(), module_name(), module_name_to_entity(), NIL, pips_assert, pips_debug, pips_debug_pvs, reset_current_module_entity(), and set_current_module_entity().

Referenced by program_simple_pointer_values().

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

◆ initial_simple_pointer_values()

bool initial_simple_pointer_values ( const string  module_name)
Parameters
module_nameodule_name

Definition at line 1925 of file pointer_values_analyses.c.

1926 {
1928  ctxt.initial_pointer_values_p = true;
1931  reset_pv_context(&ctxt);
1933  return(true);
1934 }
void generic_effects_reset_all_methods(void)
void set_methods_for_simple_effects(void)
static void generic_module_initial_pointer_values(char *module_name, pv_context *ctxt)
pv_context make_simple_pv_context()
void reset_pv_context(pv_context *p_ctxt)
pv_context is a structure holding the methods to use during pointer values analyses

References generic_effects_reset_all_methods(), generic_module_initial_pointer_values(), pv_context::initial_pointer_values_p, make_simple_pv_context(), module_name(), reset_pv_context(), and set_methods_for_simple_effects().

+ Here is the call graph for this function:

◆ instruction_to_post_pv()

static list instruction_to_post_pv ( instruction  inst,
list  l_in,
pv_context ctxt 
)
static

Definition at line 537 of file pointer_values_analyses.c.

538 {
539  list l_out = NIL;
540  pips_debug(1, "begin\n");
541 
542  switch(instruction_tag(inst))
543  {
545  l_out = sequence_to_post_pv(instruction_sequence(inst), l_in, ctxt);
546  break;
547  case is_instruction_test:
548  l_out = test_to_post_pv(instruction_test(inst), l_in, ctxt);
549  break;
550  case is_instruction_loop:
551  l_out = loop_to_post_pv(instruction_loop(inst), l_in, ctxt);
552  break;
554  l_out = whileloop_to_post_pv(instruction_whileloop(inst), l_in, ctxt);
555  break;
557  l_out = forloop_to_post_pv(instruction_forloop(inst), l_in, ctxt);
558  break;
560  l_out = unstructured_to_post_pv(instruction_unstructured(inst), l_in, ctxt);
561  break;
563  {
564  pv_results pv_res = make_pv_results();
565  expression_to_post_pv(instruction_expression(inst), l_in, &pv_res, ctxt);
566  l_out = pv_res.l_out;
567  free_pv_results_paths(&pv_res);
568  }
569  break;
570  case is_instruction_call:
571  {
572  pv_results pv_res = make_pv_results();
573  call_to_post_pv(instruction_call(inst), l_in, &pv_res, ctxt);
574  l_out = pv_res.l_out;
575  free_pv_results_paths(&pv_res);
576  }
577  break;
578  case is_instruction_goto:
579  pips_internal_error("unexpected goto in pointer values analyses");
580  break;
582  pips_internal_error("unexpected multitest in pointer values analyses");
583  break;
584  default:
585  pips_internal_error("unknown instruction tag");
586  }
587  pips_debug_pvs(2, "returning:", l_out);
588  pips_debug(1, "end\n");
589  return (l_out);
590 }
static list sequence_to_post_pv(sequence seq, list l_in, pv_context *ctxt)
static list loop_to_post_pv(loop l, list l_in, pv_context *ctxt)
static list test_to_post_pv(test t, list l_in, pv_context *ctxt)
static list whileloop_to_post_pv(whileloop l, list l_in, pv_context *ctxt)
static list unstructured_to_post_pv(unstructured u, list l_in, pv_context *ctxt)
static list forloop_to_post_pv(forloop l, list l_in, pv_context *ctxt)
#define instruction_loop(x)
Definition: ri.h:1520
@ is_instruction_goto
Definition: ri.h:1473
@ is_instruction_unstructured
Definition: ri.h:1475
@ is_instruction_whileloop
Definition: ri.h:1472
@ is_instruction_expression
Definition: ri.h:1478
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_multitest
Definition: ri.h:1476
@ is_instruction_call
Definition: ri.h:1474
@ is_instruction_sequence
Definition: ri.h:1469
@ is_instruction_forloop
Definition: ri.h:1477
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define instruction_sequence(x)
Definition: ri.h:1514
#define instruction_forloop(x)
Definition: ri.h:1538
#define instruction_expression(x)
Definition: ri.h:1541
#define instruction_whileloop(x)
Definition: ri.h:1523
#define instruction_call(x)
Definition: ri.h:1529
#define instruction_test(x)
Definition: ri.h:1517
#define instruction_unstructured(x)
Definition: ri.h:1532

References call_to_post_pv(), expression_to_post_pv(), forloop_to_post_pv(), free_pv_results_paths(), instruction_call, instruction_expression, instruction_forloop, instruction_loop, instruction_sequence, instruction_tag, instruction_test, instruction_unstructured, instruction_whileloop, is_instruction_call, is_instruction_expression, is_instruction_forloop, is_instruction_goto, is_instruction_loop, is_instruction_multitest, is_instruction_sequence, is_instruction_test, is_instruction_unstructured, is_instruction_whileloop, pv_results::l_out, loop_to_post_pv(), make_pv_results(), NIL, pips_debug, pips_debug_pvs, pips_internal_error, sequence_to_post_pv(), test_to_post_pv(), unstructured_to_post_pv(), and whileloop_to_post_pv().

Referenced by statement_to_post_pv().

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

◆ loop_to_post_pv()

static list loop_to_post_pv ( loop  l,
list  l_in,
pv_context ctxt 
)
static

first loop range is evaluated

then, the loop body is executed if and only if the upper bound is greater than the lower bound, else the loop body is only possibly executed.

as a first approximation, we perform no test on the loop bounds, and thus assume that the loop body is only possibly executed

this iteration may never be executed :

now update input pointer values of inner loop statements

Definition at line 622 of file pointer_values_analyses.c.

623 {
624  list l_out = NIL;
625  range r = loop_range(l);
626  list l_in_cur = l_in;
627  statement body = loop_body(l);
628  pips_debug(1, "begin\n");
629 
630  /* first loop range is evaluated */
631  pv_results pv_res = make_pv_results();
632  range_to_post_pv(r, l_in_cur, &pv_res, ctxt);
633  free_pv_results_paths(&pv_res);
634  l_in_cur = pv_res.l_out;
635  list l_saved = gen_full_copy_list(l_in_cur);
636 
637  /* then, the loop body is executed if and only if the upper bound
638  is greater than the lower bound, else the loop body is only possibly
639  executed.
640  */
641 
642  /* as a first approximation, we perform no test on the loop bounds,
643  and thus assume that the loop body is only possibly executed
644  */
645  int i = 0;
646  bool fix_point_reached = false;
647  l_out = pv_res.l_out;
648  do
649  {
650  pips_debug(3, "fix point iteration number %d.\n", i+1);
651  list l_iter_in = gen_full_copy_list(l_out);
652  l_out = statement_to_post_pv(body, l_out, ctxt);
653 
654  /* this iteration may never be executed :*/
655  l_out = (*ctxt->pvs_may_union_func)(l_out, gen_full_copy_list(l_iter_in));
656  i++;
657  fix_point_reached = (l_out == l_iter_in)
658  || (*ctxt->pvs_equal_p_func)(l_iter_in, l_out);
659  pips_debug(3, "fix point %s reached\n", fix_point_reached? "":"not");
660  gen_full_free_list(l_iter_in);
661  }
662  while(i<PV_NB_MAX_ITER_FIX_POINT && !fix_point_reached);
663 
664  if (!fix_point_reached)
665  {
666  pv_results pv_res_failed = make_pv_results();
668  list l_anywhere = CONS(EFFECT, anywhere_eff, NIL);
669  list l_kind = CONS(CELL_INTERPRETATION,
671  single_pointer_assignment_to_post_pv(anywhere_eff, l_anywhere, l_kind,
672  false, l_saved,
673  &pv_res_failed, ctxt);
674  l_out = pv_res_failed.l_out;
675  free_pv_results_paths(&pv_res_failed);
676  free_effect(anywhere_eff);
677  gen_free_list(l_anywhere);
678  gen_full_free_list(l_kind);
679 
680  /* now update input pointer values of inner loop statements */
681  l_in_cur = gen_full_copy_list(l_out);
682  list l_tmp = statement_to_post_pv(body, l_in_cur, ctxt);
683  gen_full_free_list(l_tmp);
684  }
685  else
686  gen_full_free_list(l_saved);
687 
688  pips_debug_pvs(1, "end with l_out =\n", l_out);
689  return (l_out);
690 }
void range_to_post_pv(range r, list l_in, pv_results *pv_res, pv_context *ctxt)
#define loop_body(x)
Definition: ri.h:1644
#define loop_range(x)
Definition: ri.h:1642

References CELL_INTERPRETATION, CONS, EFFECT, free_effect(), free_pv_results_paths(), gen_free_list(), gen_full_copy_list(), gen_full_free_list(), pv_results::l_out, loop_body, loop_range, make_action_write_memory(), make_anywhere_effect(), make_cell_interpretation_address_of(), make_pv_results(), NIL, pips_debug, pips_debug_pvs, PV_NB_MAX_ITER_FIX_POINT, pv_context::pvs_equal_p_func, pv_context::pvs_may_union_func, range_to_post_pv(), single_pointer_assignment_to_post_pv(), and statement_to_post_pv().

Referenced by instruction_to_post_pv().

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

◆ make_anywhere_anywhere_pvs()

list make_anywhere_anywhere_pvs ( void  )

Definition at line 237 of file pointer_values_analyses.c.

238 {
241  copy_cell(anywhere_c),
244  return (CONS(CELL_RELATION, pv, NIL));
245 }
cell copy_cell(cell p)
CELL.
Definition: effects.c:246
entity entity_all_locations()
eturn ANY_MODULE:ANYWHERE (the top of the lattice)
cell_relation make_address_of_pointer_value(cell, cell, tag, descriptor)
#define CELL_RELATION(x)
CELL_RELATION.
Definition: effects.h:479
@ is_approximation_may
Definition: effects.h:341

References CELL_RELATION, CONS, copy_cell(), entity_all_locations(), is_approximation_may, make_address_of_pointer_value(), make_cell_reference(), make_descriptor_none(), make_reference(), and NIL.

Referenced by unstructured_to_post_pv().

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

◆ make_pv_results()

◆ make_simple_pv_context()

pv_context make_simple_pv_context ( void  )

Definition at line 119 of file pointer_values_analyses.c.

120 {
121  pv_context ctxt;
122 
123  ctxt.initial_pointer_values_p = false;
124 
135 
146  ctxt.stmt_stack = stack_make(statement_domain, 0, 0);
147  return ctxt;
148 }
void simple_cell_reference_with_address_of_cell_reference_translation(reference, descriptor, reference, descriptor, int, reference *, descriptor *, bool *)
bool simple_cell_preceding_p(cell, descriptor, cell, descriptor, transformer, bool, bool *)
Definition: eval.c:119
void simple_cell_reference_with_value_of_cell_reference_translation(reference, descriptor, reference, descriptor, int, reference *, descriptor *, bool *)
stack stack_make(int, int, int)
allocation
Definition: stack.c:246
list simple_pvs_may_union(list, list)
list simple_pvs_must_union(list, list)
bool simple_pvs_syntactically_equal_p(list, list)
cell_relation simple_pv_composition_with_transformer(cell_relation, transformer)
list make_simple_pv_from_simple_effects(effect, effect, cell_interpretation, list)
pointer_values_operators.c
list db_get_in_simple_pv(const char *module_name)
void db_put_in_simple_pv(const char *module_name, list l_pv)
list db_get_program_simple_pv()
statement_cell_relations db_get_simple_pv(const char *module_name)
I don't know how to deal with these mappings if we have to analyse several modules at the same time w...
void db_put_initial_simple_pv(const char *module_name, list l_pv)
void db_put_program_simple_pv(list l_pv)
void db_put_simple_pv(const char *module_name, statement_cell_relations scr)
void db_put_out_simple_pv(const char *module_name, list l_pv)
list db_get_out_simple_pv(const char *module_name)
list db_get_initial_simple_pv(const char *module_name)
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
void(* cell_reference_with_value_of_cell_reference_translation_func)(reference, descriptor, reference, descriptor, int, reference *, descriptor *, bool *)
TRANSLATION OPERATORS.
bool(* cell_preceding_p_func)(cell, descriptor, cell, descriptor, transformer, bool, bool *)
COMPARISON OPERATORS.
list(* make_pv_from_effects_func)(effect, effect, cell_interpretation, list)
statement_cell_relations (*db_get_gen_pv_func)(char *);
stack stmt_stack
STACKS.
void(* cell_reference_with_address_of_cell_reference_translation_func)(reference, descriptor, reference, descriptor, int, reference *, descriptor *, bool *)
list(* db_get_out_pv_func)(const char *)
list(* db_get_in_pv_func)(const char *)
statement_cell_relations(* db_get_pv_func)(const char *)
set to true for an initial module analysis
cell_relation(* pv_composition_with_transformer_func)(cell_relation, transformer)
UNARY OPERATORS.

References pv_context::cell_preceding_p_func, pv_context::cell_reference_with_address_of_cell_reference_translation_func, pv_context::cell_reference_with_value_of_cell_reference_translation_func, pv_context::db_get_in_pv_func, db_get_in_simple_pv(), pv_context::db_get_initial_pv_func, db_get_initial_simple_pv(), pv_context::db_get_out_pv_func, db_get_out_simple_pv(), pv_context::db_get_program_pv_func, db_get_program_simple_pv(), pv_context::db_get_pv_func, db_get_simple_pv(), pv_context::db_put_in_pv_func, db_put_in_simple_pv(), pv_context::db_put_initial_pv_func, db_put_initial_simple_pv(), pv_context::db_put_out_pv_func, db_put_out_simple_pv(), pv_context::db_put_program_pv_func, db_put_program_simple_pv(), pv_context::db_put_pv_func, db_put_simple_pv(), pv_context::initial_pointer_values_p, pv_context::make_pv_from_effects_func, make_simple_pv_from_simple_effects(), pv_context::pv_composition_with_transformer_func, pv_context::pvs_equal_p_func, pv_context::pvs_may_union_func, pv_context::pvs_must_union_func, simple_cell_preceding_p(), simple_cell_reference_with_address_of_cell_reference_translation(), simple_cell_reference_with_value_of_cell_reference_translation(), simple_pv_composition_with_transformer(), simple_pvs_may_union(), simple_pvs_must_union(), simple_pvs_syntactically_equal_p(), stack_make(), statement_domain, and pv_context::stmt_stack.

Referenced by convex_effect_find_aliased_paths_with_pointer_values(), initial_simple_pointer_values(), print_code_simple_gen_kill_pointer_values(), print_code_simple_pointer_values(), program_simple_pointer_values(), simple_effect_to_constant_path_effects_with_pointer_values(), and simple_pointer_values().

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

◆ module_initial_parameter_pv()

static list module_initial_parameter_pv ( )
static

to avoid too long paths until GAPS are handled

Definition at line 1657 of file pointer_values_analyses.c.

1658 {
1659  list pv_out = NIL;
1661  list l_formals = module_formal_parameters(module);
1662  const char* mod_name = get_current_module_name();
1663  entity pointer_dummy_area = FindOrCreateEntity(mod_name, POINTER_DUMMY_TARGETS_AREA_LOCAL_NAME);
1664  storage pointer_dummy_storage = make_storage_ram(make_ram(module, pointer_dummy_area, UNKNOWN_RAM_OFFSET, NIL));
1665 
1666  FOREACH(ENTITY, formal_ent, l_formals)
1667  {
1668  effect formal_eff = make_reference_simple_effect(make_reference(formal_ent, NIL),
1671  type formal_t = entity_basic_concrete_type(formal_ent);
1672 
1673  // generate all possible effects from the formal parameter
1675  formal_t,
1676  'w',
1677  true,
1678  10, /* to avoid too long paths until GAPS are handled */
1679  false);
1680  const char * formal_name = entity_user_name(formal_ent);
1681  int nb = 1;
1682 
1683  FOREACH(EFFECT, eff, lw)
1684  {
1685  // this should be at least partly be embedded in a representation dependent wrapper
1686  pips_debug_effect(3, "current effect: \n", eff);
1687  bool to_be_freed = false;
1688  type eff_t = cell_to_type(effect_cell(eff), &to_be_freed);
1690  {
1691 
1692  // we generate an address_of pv, the source of which is the effect cell
1693  // and the sink of which is the first element of a new entity, whose type
1694  // is a one dimensional array of the pointed type.
1695 
1696  // first generate the new entity name
1697  entity new_ent = entity_undefined;
1698  string new_name = NULL;
1699  new_name = strdup(concatenate(mod_name, MODULE_SEP_STRING, "_", formal_name,"_", int2a(nb), NULL));
1700  nb ++;
1701 
1702  // then take care of the type and target path indices
1704  type new_type = type_undefined;
1705  list new_dims = NIL; // array dimensions of new type
1706 
1707  // if the effect path contains multiple paths (a[*] or p.end[*].begin for instance)
1708  // then there are several targets;
1709  // the indices of the new_path must have an additional dimension
1710  // and also the new type
1711  bool single_path = true;
1712  list new_inds = NIL; // indices of the target path
1713 
1714  // Not generic
1715  // for simple cells, isn't it sufficient to test the approximation of the effect ?
1717  {
1718  if (unbounded_expression_p(eff_ind_exp))
1719  {
1720  single_path = false;
1721  break;
1722  }
1723  }
1724  if (!single_path)
1725  {
1726  new_inds = CONS(EXPRESSION, make_unbounded_expression(), NIL);
1727  new_dims = CONS(DIMENSION,
1730  NIL),
1731  NIL);
1732  // the approximation will be ok because, as the path is not unique
1733  // the effect approximation is may by construction
1734  }
1735 
1737  {
1738  pips_debug(5, "variable case\n");
1739  variable pointed_type_v = type_variable(pointed_type);
1740  basic new_basic = copy_basic(variable_basic(pointed_type_v));
1741  if (ENDP(variable_dimensions(pointed_type_v)))
1742  {
1743  pips_debug(5, "with 0 dimension\n");
1744  new_dims = gen_nconc(new_dims, CONS(DIMENSION,
1747  new_inds = gen_nconc(new_inds, CONS(EXPRESSION, int_to_expression(0), NIL));
1748  }
1749  else
1750  {
1751  new_dims = gen_full_copy_list(variable_dimensions(pointed_type_v));
1752  pips_debug(5, "with %d dimension\n", (int) gen_length(new_dims));
1753  FOREACH(DIMENSION, dim, new_dims)
1754  {
1755  new_inds = gen_nconc(new_inds, CONS(EXPRESSION, int_to_expression(0), NIL));
1756  }
1757  }
1758  new_type = make_type_variable(make_variable(new_basic, new_dims, NIL));
1759  pips_debug(5, "new_type is: %s (%s)\n", string_of_type(new_type),
1760  type_to_string(new_type));
1761  new_ent = make_entity(new_name,
1762  new_type,
1763  copy_storage(pointer_dummy_storage),
1764  make_value_unknown());
1765  }
1766  else
1767  {
1768  pips_debug(5, "non-variable formal parameter target type -> anywhere\n");
1769  new_ent = entity_all_locations();
1770  gen_full_free_list(new_inds);
1771  new_inds = NIL;
1772  }
1773 
1774  cell new_cell = make_cell_reference(make_reference(new_ent, new_inds));
1775  // then make the new pv
1777  new_cell,
1780  pips_debug_pv(3, "generated pv: \n", new_pv);
1781  // and add it to the return list of pvs
1782  pv_out = CONS(CELL_RELATION, new_pv, pv_out);
1783  }
1784  if (to_be_freed) free_type(eff_t);
1785  }
1786  gen_full_free_list(lw);
1787  }
1788  free_storage(pointer_dummy_storage);
1789  return pv_out;
1790 }
value make_value_unknown(void)
Definition: ri.c:2847
type make_type_variable(variable _field_)
Definition: ri.c:2715
basic copy_basic(basic p)
BASIC.
Definition: ri.c:104
ram make_ram(entity a1, entity a2, intptr_t a3, list a4)
Definition: ri.c:1999
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_storage(storage p)
Definition: ri.c:2231
storage copy_storage(storage p)
STORAGE.
Definition: ri.c:2228
storage make_storage_ram(ram _field_)
Definition: ri.c:2279
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
#define pips_debug_pv(level, message, pv)
#define effect_approximation_tag(eff)
#define make_reference_simple_effect(reference, action, approximation)
const char * get_current_module_name(void)
Get the name of the current module.
Definition: static.c:121
size_t gen_length(const list l)
Definition: list.c:150
#define POINTER_DUMMY_TARGETS_AREA_LOCAL_NAME
Definition: naming-local.h:77
#define MODULE_SEP_STRING
Definition: naming-local.h:30
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
static char * module
Definition: pips.c:74
#define make_entity(n, t, s, i)
#define UNKNOWN_RAM_OFFSET
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
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
bool unbounded_expression_p(expression e)
Definition: expression.c:4329
list module_formal_parameters(entity func)
list module_formal_parameters(entity func) input : an entity representing a function.
Definition: module.c:327
type pointed_type(type)
returns the type pointed by the input type if it is a pointer or an array of pointers
Definition: type.c:3035
#define basic_pointer(x)
Definition: ri.h:637
#define basic_pointer_p(x)
Definition: ri.h:635
#define reference_indices(x)
Definition: ri.h:2328
#define variable_dimensions(x)
Definition: ri.h:3122
#define type_undefined
Definition: ri.h:2883
char * strdup()
char * int2a(int)
util.c
Definition: util.c:42

References basic_pointer, basic_pointer_p, CELL_RELATION, cell_to_type(), concatenate(), CONS, copy_basic(), copy_cell(), copy_storage(), DIMENSION, EFFECT, effect_any_reference, effect_approximation_tag, effect_cell, ENDP, ENTITY, entity_all_locations(), entity_basic_concrete_type(), entity_undefined, entity_user_name(), EXPRESSION, FindOrCreateEntity(), FOREACH, free_storage(), free_type(), gen_full_copy_list(), gen_full_free_list(), gen_length(), gen_nconc(), generic_effect_generate_all_accessible_paths_effects_with_level(), get_current_module_entity(), get_current_module_name(), int2a(), int_to_expression(), make_action_write_memory(), make_address_of_pointer_value(), make_approximation_exact(), make_cell_reference(), make_descriptor_none(), make_dimension(), make_entity, make_ram(), make_reference(), make_reference_simple_effect, make_storage_ram(), make_type_variable(), make_unbounded_expression(), make_value_unknown(), make_variable(), module, module_formal_parameters(), MODULE_SEP_STRING, NIL, pips_debug, pips_debug_effect, pips_debug_pv, pointed_type(), POINTER_DUMMY_TARGETS_AREA_LOCAL_NAME, reference_indices, strdup(), string_of_type(), type_to_string(), type_undefined, type_variable, type_variable_p, unbounded_expression_p(), UNKNOWN_RAM_OFFSET, variable_basic, and variable_dimensions.

Referenced by generic_module_pointer_values().

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

◆ multiple_pointer_assignment_to_post_pv()

void multiple_pointer_assignment_to_post_pv ( effect  lhs_base_eff,
type  lhs_type,
list  l_rhs_base_eff,
list  l_rhs_base_kind,
bool  declaration_p,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)

we could be more precise here on abstract locations

if (!anywhere_lhs_p)

lhs is not a pointer, but it is an array of pointers or an aggregate type with pointers....

In this case, it cannot be an address_of case

First, search for all accessible pointers

to work around the fact that exact effects are must effects

Then for each found pointer, do as if there were an assignment by translating the rhs path accordingly

build the list of corresponding rhs

should be refined

general case at least :-)

This is not generic, I should use a translation algorithm here I guess

first skip dimensions of kill_ref similar to lhs_base_ref

add the remaining dimensions to the copy of rhs_base_eff

while

if (!ENDP(l_lhs))

if (!anywhere_lhs_p)

Parameters
lhs_base_effhs_base_eff
lhs_typehs_type
l_rhs_base_eff_rhs_base_eff
l_rhs_base_kind_rhs_base_kind
declaration_peclaration_p
l_in_in
pv_resv_res
ctxttxt

Definition at line 1444 of file pointer_values_analyses.c.

1448 {
1449  list l_in_cur = l_in;
1450  cell rhs_base_cell = gen_length(l_rhs_base_eff) > 0
1451  ? effect_cell(EFFECT(CAR(l_rhs_base_eff))): cell_undefined;
1452  bool anywhere_lhs_p = false;
1453 
1454  pips_debug(1, "begin\n");
1455 
1456  pips_assert("assigning NULL to several pointers"
1457  " at the same time is forbidden!\n", !(!cell_undefined_p(rhs_base_cell) && null_pointer_value_cell_p(rhs_base_cell)));
1458 
1459  /* we could be more precise here on abstract locations */
1460  if (anywhere_effect_p(lhs_base_eff))
1461  {
1462  pips_assert("we cannot have an anywhere lhs for a declaration\n", !declaration_p);
1463  pips_debug(3, "anywhere lhs\n");
1464  anywhere_lhs_p = true;
1465 
1468 
1469  single_pointer_assignment_to_post_pv(lhs_base_eff, l_rhs_eff, l_rhs_kind, declaration_p, l_in_cur, pv_res, ctxt);
1470 
1471  gen_full_free_list(l_rhs_eff);
1472  gen_full_free_list(l_rhs_kind);
1473  }
1474  else /* if (!anywhere_lhs_p) */
1475  {
1476  /* lhs is not a pointer, but it is an array of pointers or an aggregate type
1477  with pointers.... */
1478  /* In this case, it cannot be an address_of case */
1479 
1480  /* First, search for all accessible pointers */
1482  (lhs_base_eff, lhs_type, is_action_write, false, 0, true);
1483  if(effect_exact_p(lhs_base_eff))
1484  effects_to_must_effects(l_lhs); /* to work around the fact that exact effects are must effects */
1485  pips_debug_effects(2, "l_lhs = ", l_lhs);
1486 
1487  /* Then for each found pointer, do as if there were an assignment by translating
1488  the rhs path accordingly
1489  */
1490  if (!ENDP(l_lhs))
1491  {
1492  list l_lhs_tmp = l_lhs;
1493  while (!anywhere_lhs_p && !ENDP(l_lhs_tmp))
1494  {
1495  /* build the list of corresponding rhs */
1496  effect lhs_eff = EFFECT(CAR(l_lhs_tmp));
1497  reference lhs_ref = effect_any_reference(lhs_eff);
1498  list lhs_dims = reference_indices(lhs_ref);
1499 
1500  reference lhs_base_ref = effect_any_reference(lhs_base_eff);
1501  size_t lhs_base_nb_dim = gen_length(reference_indices(lhs_base_ref));
1502  list l_rhs_eff = NIL;
1503  list l_rhs_kind = NIL;
1504 
1505  bool free_rhs_kind = false;
1506  list l_rhs_base_kind_tmp = l_rhs_base_kind;
1507  FOREACH(EFFECT, rhs_base_eff, l_rhs_base_eff)
1508  {
1509  effect rhs_eff = copy_effect(rhs_base_eff);
1510  cell_interpretation rhs_kind = CELL_INTERPRETATION(CAR(l_rhs_base_kind));
1511 
1512  if (!undefined_pointer_value_cell_p(rhs_base_cell)
1513  && !anywhere_effect_p(rhs_base_eff))
1514  {
1515  reference rhs_ref = effect_any_reference(rhs_eff);
1516  bool to_be_freed = false;
1517  type rhs_type = cell_reference_to_type(rhs_ref, &to_be_freed);
1518 
1519  if (!type_equal_p(lhs_type, rhs_type))
1520  {
1521  pips_debug(5, "not same lhs and rhs types generating anywhere rhs\n");
1522  rhs_eff = make_anywhere_effect(make_action_write_memory()); /* should be refined */
1524  free_rhs_kind = true;
1525  }
1526  else /* general case at least :-) */
1527  {
1528  /* This is not generic, I should use a translation algorithm here I guess */
1529  /* first skip dimensions of kill_ref similar to lhs_base_ref */
1530  list lhs_dims_tmp = lhs_dims;
1531  for(size_t i = 0; i < lhs_base_nb_dim; i++, POP(lhs_dims_tmp));
1532  /* add the remaining dimensions to the copy of rhs_base_eff */
1533  FOREACH(EXPRESSION, dim, lhs_dims_tmp)
1534  {
1535  // functions that can be pointed by effect_add_expression_dimension_func:
1536  // simple_effect_add_expression_dimension
1537  // convex_region_add_expression_dimension
1538  (*effect_add_expression_dimension_func)(rhs_eff, dim);
1539  }
1540  }
1541  if (to_be_freed) free_type(rhs_type);
1542  }
1543  l_rhs_eff = CONS(EFFECT, rhs_eff, l_rhs_eff);
1544  l_rhs_kind = CONS(CELL_INTERPRETATION, rhs_kind, l_rhs_kind);
1545  POP(l_rhs_base_kind_tmp);
1546  }
1547 
1548  single_pointer_assignment_to_post_pv(lhs_eff, l_rhs_eff, l_rhs_kind, declaration_p, l_in_cur, pv_res, ctxt);
1549 
1550  gen_full_free_list(l_rhs_eff);
1551  if (free_rhs_kind) gen_full_free_list(l_rhs_kind); else gen_free_list(l_rhs_kind);
1552 
1553  list l_out = pv_res->l_out;
1554  if (l_out != l_in_cur)
1555  gen_full_free_list(l_in_cur);
1556  l_in_cur = l_out;
1557 
1558  list l_result_paths = pv_res->result_paths;
1559 
1560  if (gen_length(l_result_paths) > 0 && anywhere_effect_p(EFFECT(CAR(l_result_paths))))
1561  anywhere_lhs_p = true;
1562 
1563  POP(l_lhs_tmp);
1564  } /* while */
1565  } /* if (!ENDP(l_lhs)) */
1566  gen_full_free_list(l_lhs);
1567  } /* if (!anywhere_lhs_p) */
1568 
1569  return;
1570 }
void effects_to_must_effects(list)
#define effect_exact_p(eff)
bool undefined_pointer_value_cell_p(cell)
type cell_reference_to_type(reference, bool *)
computes the type of a cell reference representing a memory access path.
Definition: type.c:466
bool anywhere_effect_p(effect)
Is it an anywhere effect? ANYMMODULE:ANYWHERE
Definition: effects.c:346
bool null_pointer_value_cell_p(cell)
#define cell_undefined_p(x)
Definition: effects.h:431
#define cell_undefined
Definition: effects.h:430
@ is_action_write
Definition: effects.h:293
bool type_equal_p(type, type)
Definition: type.c:547

References anywhere_effect_p(), CAR, CELL_INTERPRETATION, cell_reference_to_type(), cell_undefined, cell_undefined_p, CONS, copy_effect(), EFFECT, effect_any_reference, effect_cell, effect_exact_p, effects_to_must_effects(), ENDP, EXPRESSION, FOREACH, free_type(), gen_free_list(), gen_full_free_list(), gen_length(), generic_effect_generate_all_accessible_paths_effects_with_level(), is_action_write, pv_results::l_out, make_action_write_memory(), make_anywhere_effect(), make_cell_interpretation_address_of(), NIL, null_pointer_value_cell_p(), pips_assert, pips_debug, pips_debug_effects, POP, reference_indices, pv_results::result_paths, single_pointer_assignment_to_post_pv(), type_equal_p(), and undefined_pointer_value_cell_p().

Referenced by assignment_to_post_pv().

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

◆ print_pv_results()

void print_pv_results ( pv_results  pv_res)
Parameters
pv_resv_res

Definition at line 211 of file pointer_values_analyses.c.

212 {
213  fprintf(stderr, "l_out =");
214  print_pointer_values(pv_res.l_out);
215  list l_rp = pv_res.result_paths;
216  list l_rpi = pv_res.result_paths_interpretations;
217 
218  if (!ENDP(l_rp))
219  {
220  fprintf(stderr, "result_paths are:\n");
221  for(; !ENDP(l_rp); POP(l_rp), POP(l_rpi))
222  {
223  effect eff = EFFECT(CAR(l_rp));
225  fprintf(stderr, "%s:",
227  ? "value of" : "address of");
228  (*effect_prettyprint_func)(eff);
229  }
230  }
231  else
232  fprintf(stderr, "result_path is undefined\n");
233 }
void print_pointer_values(list)
Definition: prettyprint.c:622
#define cell_interpretation_value_of_p(x)
Definition: effects.h:415
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...

References CAR, CELL_INTERPRETATION, cell_interpretation_value_of_p, EFFECT, ENDP, fprintf(), pv_results::l_out, POP, print_pointer_values(), pv_results::result_paths, and pv_results::result_paths_interpretations.

+ Here is the call graph for this function:

◆ program_simple_pointer_values()

bool program_simple_pointer_values ( const string  prog_name)
Parameters
prog_namerog_name

Definition at line 1936 of file pointer_values_analyses.c.

1937 {
1940  generic_program_pointer_values(prog_name, &ctxt);
1941  reset_pv_context(&ctxt);
1943  return(true);
1944 }
static void generic_program_pointer_values(char *prog_name, pv_context *ctxt)

References generic_effects_reset_all_methods(), generic_program_pointer_values(), make_simple_pv_context(), reset_pv_context(), and set_methods_for_simple_effects().

+ Here is the call graph for this function:

◆ pv_context_statement_head()

statement pv_context_statement_head ( pv_context ctxt)
Parameters
ctxttxt

Definition at line 187 of file pointer_values_analyses.c.

188 {
189  return ((statement) stack_head(ctxt->stmt_stack));
190 }
void * stack_head(const stack)
returns the item on top of stack s
Definition: stack.c:420

References stack_head(), and pv_context::stmt_stack.

Referenced by heap_intrinsic_to_post_pv().

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

◆ pv_context_statement_pop()

void pv_context_statement_pop ( pv_context ctxt)
Parameters
ctxttxt

Definition at line 182 of file pointer_values_analyses.c.

183 {
184  (void) stack_pop( ctxt->stmt_stack);
185 }
void * stack_pop(stack)
POPs one item from stack s.
Definition: stack.c:399

References stack_pop(), and pv_context::stmt_stack.

Referenced by sequence_to_post_pv(), and statement_to_post_pv().

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

◆ pv_context_statement_push()

void pv_context_statement_push ( statement  s,
pv_context ctxt 
)
Parameters
ctxttxt

Definition at line 177 of file pointer_values_analyses.c.

178 {
179  stack_push((void *) s, ctxt->stmt_stack);
180 }
void stack_push(void *, stack)
stack use
Definition: stack.c:373

References stack_push(), and pv_context::stmt_stack.

Referenced by sequence_to_post_pv(), and statement_to_post_pv().

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

◆ range_to_post_pv()

void range_to_post_pv ( range  r,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
Parameters
l_in_in
pv_resv_res
ctxttxt

Definition at line 913 of file pointer_values_analyses.c.

914 {
915  expression el = range_lower(r);
916  expression eu = range_upper(r);
917  expression ei = range_increment(r);
918 
919  pips_debug(1, "begin\n");
920 
921  expression_to_post_pv(el, l_in, pv_res, ctxt);
922  expression_to_post_pv(eu, pv_res->l_out, pv_res, ctxt);
923  expression_to_post_pv(ei, pv_res->l_out, pv_res, ctxt);
924 
925  free_pv_results_paths(pv_res);
926 
927  pips_debug_pvs(1, "end with pv_res->l_out:\n", pv_res->l_out);
928 }
#define range_upper(x)
Definition: ri.h:2290
#define range_increment(x)
Definition: ri.h:2292
#define range_lower(x)
Definition: ri.h:2288

References expression_to_post_pv(), free_pv_results_paths(), pv_results::l_out, pips_debug, pips_debug_pvs, range_increment, range_lower, and range_upper.

Referenced by loop_to_post_pv().

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

◆ reset_pv_context()

void reset_pv_context ( pv_context p_ctxt)

p_ctxt->db_get_gen_pv_func =(statement_cell_relations_function) UNDEF ;

p_ctxt->db_put_gen_pv_func = (void_function) UNDEF;

p_ctxt->db_get_kill_pv_func = (statement_effects_function) UNDEF;

p_ctxt->db_put_kill_pv_func = (void_function) UNDEF;

Parameters
p_ctxt_ctxt

Definition at line 162 of file pointer_values_analyses.c.

163 {
165  p_ctxt->db_put_pv_func = (void_function) UNDEF;
166 /* p_ctxt->db_get_gen_pv_func =(statement_cell_relations_function) UNDEF ; */
167 /* p_ctxt->db_put_gen_pv_func = (void_function) UNDEF; */
168 /* p_ctxt->db_get_kill_pv_func = (statement_effects_function) UNDEF; */
169 /* p_ctxt->db_put_kill_pv_func = (void_function) UNDEF; */
175 }
statement_cell_relations(* statement_cell_relations_function)()
void(* void_function)()
bool(* bool_function)()
list(* list_function)()
#define UNDEF
cell_relation(* cell_relation_function)()

References pv_context::db_get_pv_func, pv_context::db_put_pv_func, pv_context::make_pv_from_effects_func, pv_context::pv_composition_with_transformer_func, pv_context::pvs_equal_p_func, pv_context::pvs_may_union_func, pv_context::pvs_must_union_func, and UNDEF.

Referenced by convex_effect_find_aliased_paths_with_pointer_values(), initial_simple_pointer_values(), print_code_simple_gen_kill_pointer_values(), print_code_simple_pointer_values(), program_simple_pointer_values(), simple_effect_to_constant_path_effects_with_pointer_values(), and simple_pointer_values().

+ Here is the caller graph for this function:

◆ sequence_to_post_pv()

static list sequence_to_post_pv ( sequence  seq,
list  l_in,
pv_context ctxt 
)
static

keep local variables in declaration reverse order

beware don't push static variables and non pointer variables.

don't forget to eliminate local declarations on exit

...

Definition at line 289 of file pointer_values_analyses.c.

290 {
291  list l_cur = l_in;
292  list l_locals = NIL;
293  pips_debug(1, "begin\n");
295  {
296  ifdebug(2){
297 
298  pips_debug(2, "dealing with statement");
300  pips_debug_pvs(2, "l_cur =", l_cur);
301  }
302  /* keep local variables in declaration reverse order */
304  {
306  if(bound_pv_p(stmt))
308  else
311  {
312  type e_type = entity_basic_concrete_type(e);
313  storage e_storage = entity_storage(e);
314  /* beware don't push static variables and non pointer variables. */
315  if (storage_ram_p(e_storage)
316  && ! static_area_p(ram_section(storage_ram(e_storage)))
317  && ! type_fundamental_basic_p(e_type)
319  l_locals = CONS(ENTITY, e, l_locals);
320  l_cur = declaration_to_post_pv(e, l_cur, ctxt);
321  }
322  //store_gen_pv(stmt, make_cell_relations(NIL));
323  //store_kill_pv(stmt, make_effects(NIL));
325  }
326  else
327  l_cur = statement_to_post_pv(stmt, l_cur, ctxt);
328 
329  }
330 
331  /* don't forget to eliminate local declarations on exit */
332  /* ... */
333  if (!ENDP(l_locals))
334  {
335  pips_debug(5, "eliminating local variables\n");
336  expression rhs_exp =
338 
339  FOREACH(ENTITY, e, l_locals)
340  {
341  pips_debug(5, "dealing with %s\n", entity_name(e));
342  pv_results pv_res = make_pv_results();
343  pointer_values_remove_var(e, false, l_cur, &pv_res, ctxt);
344  l_cur= pv_res.l_out;
345  free_pv_results_paths(&pv_res);
346  }
347  free_expression(rhs_exp);
348  }
349 
350  pips_debug_pvs(2, "returning:", l_cur);
351  pips_debug(1, "end\n");
352  return (l_cur);
353 }
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
void pointer_values_remove_var(entity, bool, list, pv_results *, pv_context *)
void update_pv(statement, cell_relations)
void store_pv(statement, cell_relations)
bool bound_pv_p(statement)
void pv_context_statement_pop(pv_context *ctxt)
void pv_context_statement_push(statement s, pv_context *ctxt)
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
bool static_area_p(entity aire)
Definition: area.c:77
#define entity_storage(x)
Definition: ri.h:2794
#define storage_ram_p(x)
Definition: ri.h:2519
#define ram_section(x)
Definition: ri.h:2249
#define sequence_statements(x)
Definition: ri.h:2360
#define statement_declarations(x)
Definition: ri.h:2460
#define storage_ram(x)
Definition: ri.h:2521
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define ifdebug(n)
Definition: sg.c:47
Definition: statement.c:54

References basic_concrete_type_leads_to_pointer_p(), bound_pv_p(), CONS, declaration_statement_p(), declaration_to_post_pv(), ENDP, ENTITY, entity_basic_concrete_type(), entity_name, entity_storage, entity_to_expression(), FOREACH, free_expression(), free_pv_results_paths(), gen_full_copy_list(), ifdebug, pv_results::l_out, make_cell_relations(), make_pv_results(), NIL, pips_debug, pips_debug_pvs, pointer_values_remove_var(), print_statement(), pv_context_statement_pop(), pv_context_statement_push(), ram_section, sequence_statements, STATEMENT, statement_declarations, statement_to_post_pv(), static_area_p(), storage_ram, storage_ram_p, store_pv(), type_fundamental_basic_p(), undefined_pointer_value_entity(), and update_pv().

Referenced by instruction_to_post_pv().

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

◆ simple_pointer_values()

bool simple_pointer_values ( const string  module_name)

interface to compute the simple pointer values of a given module

Parameters
module_nameodule_name

Definition at line 1915 of file pointer_values_analyses.c.

1916 {
1920  reset_pv_context(&ctxt);
1922  return(true);
1923 }
static void generic_module_pointer_values(char *module_name, pv_context *ctxt)
generic interface to compute the pointer values of a given module

References generic_effects_reset_all_methods(), generic_module_pointer_values(), make_simple_pv_context(), module_name(), reset_pv_context(), and set_methods_for_simple_effects().

+ Here is the call graph for this function:

◆ single_pointer_assignment_to_post_pv()

void single_pointer_assignment_to_post_pv ( effect  lhs_eff,
list  l_rhs_eff,
list  l_rhs_kind,
bool  declaration_p,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)

First search for all killed paths

we could be more precise/generic on abstract locations

no aliases for a newly declared entity

if lhs_eff is a may-be-killed, then all aliased effects are also may-be-killed effects

we must find in l_in all pointers p and generate p == rhs for all rhs if p is of a type compatible with rhs, and p == &*anywhere* otherwise. in fact, for the moment we generate p == &*anywhere* in all cases

dealing with first cell

not generic

not generic

generate for all alias p in l_kill p == rhs_eff

except for p==undefined or p==null (should other abstract values/locations be ignored here?)

now take kills into account

and add gen

Parameters
lhs_effhs_eff
l_rhs_eff_rhs_eff
l_rhs_kind_rhs_kind
declaration_peclaration_p
l_in_in
pv_resv_res
ctxttxt

Definition at line 1253 of file pointer_values_analyses.c.

1257 {
1258  list l_out = NIL;
1259  list l_aliased = NIL;
1260  list l_kill = NIL;
1261  list l_gen = NIL;
1262 
1263  pips_debug_effect(1, "begin for lhs_eff =", lhs_eff);
1264  pips_debug(1, "and l_rhs_eff:\n");
1265  ifdebug(1)
1266  {
1267  list l_tmp = l_rhs_kind;
1268  FOREACH(EFFECT, rhs_eff, l_rhs_eff)
1269  {
1271  pips_debug(1, "%s of:\n", cell_interpretation_value_of_p(ci)?"value": "address");
1272  pips_debug_effect(1, "\t", rhs_eff);
1273  POP(l_tmp);
1274  }
1275  }
1276  pips_debug_pvs(1, "and l_in =", l_in);
1277  bool anywhere_lhs_p = false;
1278 
1279  /* First search for all killed paths */
1280  /* we could be more precise/generic on abstract locations */
1281  if (anywhere_effect_p(lhs_eff))
1282  {
1283  pips_assert("we cannot have an anywhere lhs for a declaration\n", !declaration_p);
1284  pips_debug(3, "anywhere lhs\n");
1285  anywhere_lhs_p = true;
1286  l_kill = CONS(EFFECT, copy_effect(lhs_eff), NIL);
1287  l_aliased = l_kill;
1288  }
1289  else
1290  {
1291  if (!declaration_p) /* no aliases for a newly declared entity */
1292  {
1293  l_aliased = effect_find_aliased_paths_with_pointer_values(lhs_eff, l_in, ctxt);
1294  if (!ENDP(l_aliased) && anywhere_effect_p(EFFECT(CAR(l_aliased))))
1295  {
1296  pips_debug(3, "anywhere lhs (from aliases)\n");
1297  anywhere_lhs_p = true;
1298  l_kill = l_aliased;
1299  }
1300  else if (!ENDP(l_aliased) && ((int) gen_length(l_aliased) == 1)
1301  && (null_pointer_value_effect_p(EFFECT(CAR(l_aliased)))))
1302  {
1303  // dereferencing a null pointer is considered as undefined by the standard
1304  // with gcc (without any option) the compiler does not complain, but the execution aborts
1305  // I make the choice here that if the pointer value is exactly NULL, then
1306  // the program abort; hence there is no pointer anymore and the pointer values list is empty.
1307  pips_user_warning("null pointer is dereferenced on lhs(%s)\n",
1308  effect_to_string(lhs_eff));
1309  gen_full_free_list(l_in);
1310  l_in = NIL;
1311  l_kill = NIL;
1312  }
1313  else if (!ENDP(l_aliased) && ((int) gen_length(l_aliased) == 1)
1314  && (undefined_pointer_value_effect_p(EFFECT(CAR(l_aliased)))))
1315  {
1316  // dereferencing a non-initialized pointer is considered as undefined by the standard
1317  // However, with gcc (without any option), the compiler does not complain,
1318  // and the execution is sometimes correct.
1319  // I make the choice here that if the pointer value is (exactly) undefined
1320  // then the program does not necessarily abort;
1321  // as I can keep dereferencements in pointer values (I'm not limited
1322  // to constant paths), I still generate a kill and a gen. BC.
1323  pips_user_warning("undefined pointer is dereferenced on lhs(%s)\n",
1324  effect_to_string(lhs_eff));
1325  l_kill = CONS(EFFECT, copy_effect(lhs_eff), NIL);
1326  }
1327  else
1328  {
1329  /* if lhs_eff is a may-be-killed, then all aliased effects are also
1330  may-be-killed effects */
1331  if (effect_may_p(lhs_eff))
1332  {
1333  pips_debug(3, "may lhs effect, changing all aliased effects to may\n");
1334  effects_to_may_effects(l_aliased);
1335  }
1336  l_kill = CONS(EFFECT, copy_effect(lhs_eff), l_aliased);
1337  }
1338  }
1339  else
1340  {
1341  l_kill = CONS(EFFECT, copy_effect(lhs_eff), NIL);
1342  }
1343  }
1344 
1345  pips_debug_effects(2, "l_kill =", l_kill);
1346 
1347  if (anywhere_lhs_p)
1348  {
1349  free_pv_results_paths(pv_res);
1350  pv_res->result_paths = l_aliased;
1352 
1353  /* we must find in l_in all pointers p and generate p == rhs for all rhs if p is
1354  * of a type compatible with rhs, and p == &*anywhere* otherwise.
1355  * in fact, for the moment we generate p == &*anywhere* in all cases
1356  */
1359  FOREACH(CELL_RELATION, pv_in, l_in)
1360  {
1361  /* dealing with first cell */
1362  /* not generic */
1367 
1368  list l_gen_pv = (* ctxt->make_pv_from_effects_func)
1369  (eff_alias, anywhere_eff, rhs_kind, l_in);
1370  l_gen = (*ctxt->pvs_must_union_func)(l_gen_pv, l_gen);
1371  free_effect(eff_alias);
1372 
1376  {
1377  /* not generic */
1382 
1383  list l_gen_pv = (* ctxt->make_pv_from_effects_func)
1384  (eff_alias, anywhere_eff, rhs_kind, l_in);
1385  l_gen = (*ctxt->pvs_must_union_func)(l_gen_pv, l_gen);
1386  free_effect(eff_alias);
1387  }
1388  }
1389  free_effect(anywhere_eff);
1390  free_cell_interpretation(rhs_kind);
1391  }
1392  else
1393  {
1394  /* generate for all alias p in l_kill p == rhs_eff */
1395  /* except for p==undefined or p==null (should other abstract values/locations be ignored here?) */
1396  FOREACH(EFFECT, eff_alias, l_kill) {
1397  if (!null_pointer_value_effect_p(eff_alias)
1398  && ! undefined_pointer_value_effect_p(eff_alias))
1399  {
1400  list l_rhs_kind_tmp = l_rhs_kind;
1401  FOREACH(EFFECT, rhs_eff, l_rhs_eff)
1402  {
1403  cell_interpretation rhs_kind =
1404  CELL_INTERPRETATION(CAR(l_rhs_kind_tmp));
1405  //bool exact_preceding_p = true;
1406  list l_gen_pv = (* ctxt->make_pv_from_effects_func)
1407  (eff_alias, rhs_eff, rhs_kind, l_in);
1408  l_gen = gen_nconc(l_gen_pv, l_gen);
1409  POP(l_rhs_kind_tmp);
1410  }
1411  }
1412  }
1413  if (declaration_p)
1414  {
1415  gen_full_free_list(l_kill);
1416  l_kill = NIL;
1417  }
1418  pips_debug_pvs(2, "l_gen =", l_gen);
1419  }
1420 
1421  /* now take kills into account */
1422  l_out = kill_pointer_values(l_in, l_kill, ctxt);
1423  pips_debug_pvs(2, "l_out_after kill:", l_out);
1424 
1425  /* and add gen */
1426  l_out = (*ctxt->pvs_must_union_func)(l_out, l_gen);
1427 
1428  pv_res->l_out = l_out;
1429 
1430  return;
1431 }
approximation make_approximation_may(void)
Definition: effects.c:179
void free_cell_interpretation(cell_interpretation p)
Definition: effects.c:194
bool null_pointer_value_effect_p(effect)
bool undefined_pointer_value_effect_p(effect)
string effect_to_string(effect)
#define effect_may_p(eff)
#define cell_relation_second_cell(cr)
#define cell_relation_second_value_of_p(cr)
#define cell_relation_first_cell(cr)
#define pips_user_warning
Definition: misc-local.h:146
list kill_pointer_values(list, list, pv_context *)
eliminate the cells of l_kill from l_in
list effect_find_aliased_paths_with_pointer_values(effect, list, pv_context *)
find all paths equivalent to eff cell in l_pv by performing a transitive closure

References anywhere_effect_p(), CAR, CELL_INTERPRETATION, cell_interpretation_value_of_p, CELL_RELATION, cell_relation_first_cell, cell_relation_second_cell, cell_relation_second_value_of_p, CONS, copy_cell(), copy_effect(), EFFECT, effect_find_aliased_paths_with_pointer_values(), effect_may_p, effect_to_string(), effects_to_may_effects(), ENDP, FOREACH, free_cell_interpretation(), free_effect(), free_pv_results_paths(), gen_full_free_list(), gen_length(), gen_nconc(), ifdebug, kill_pointer_values(), pv_results::l_out, make_action_write_memory(), make_anywhere_effect(), make_approximation_may(), make_cell_interpretation_address_of(), make_descriptor_none(), make_effect(), pv_context::make_pv_from_effects_func, NIL, null_pointer_value_cell_p(), null_pointer_value_effect_p(), pips_assert, pips_debug, pips_debug_effect, pips_debug_effects, pips_debug_pvs, pips_user_warning, POP, pv_context::pvs_must_union_func, pv_results::result_paths, pv_results::result_paths_interpretations, undefined_pointer_value_cell_p(), and undefined_pointer_value_effect_p().

Referenced by assignment_to_post_pv(), external_call_to_post_pv(), forloop_to_post_pv(), free_to_post_pv(), loop_to_post_pv(), multiple_pointer_assignment_to_post_pv(), safe_intrinsic_to_post_pv(), update_operator_to_post_pv(), and whileloop_to_post_pv().

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

◆ statement_to_post_pv()

static list statement_to_post_pv ( statement  stmt,
list  l_in,
pv_context ctxt 
)
static

Definition at line 356 of file pointer_values_analyses.c.

357 {
358  list l_out = NIL;
359  pips_debug(1, "begin\n");
361  pips_debug_pvs(2, "input pvs:", l_in);
362 
363  if(bound_pv_p(stmt))
365  else
367 
369  {
370  list l_decl = statement_declarations(stmt);
371  l_out = declarations_to_post_pv(l_decl, l_in, ctxt);
372  }
373  else
374  {
375  l_out = instruction_to_post_pv(statement_instruction(stmt), l_in, ctxt);
376  }
377 
378  pips_debug_pvs(2, "before composition_with_transformer:", l_out);
380 
381  //store_gen_pv(stmt, make_cell_relations(NIL));
382  //store_kill_pv(stmt, make_effects(NIL));
383  pips_debug_pvs(2, "returning:", l_out);
384  pips_debug(1, "end\n");
386 
387  return (l_out);
388 }
list pvs_composition_with_transformer(list, transformer, pv_context *)
static list instruction_to_post_pv(instruction inst, list l_in, pv_context *ctxt)
static list declarations_to_post_pv(list l_decl, list l_in, pv_context *ctxt)
#define transformer_undefined
Definition: ri.h:2847
#define statement_instruction(x)
Definition: ri.h:2458

References bound_pv_p(), declaration_statement_p(), declarations_to_post_pv(), gen_full_copy_list(), instruction_to_post_pv(), make_cell_relations(), NIL, pips_debug, pips_debug_pvs, pv_context_statement_pop(), pv_context_statement_push(), pvs_composition_with_transformer(), statement_declarations, statement_instruction, store_pv(), transformer_undefined, and update_pv().

Referenced by forloop_to_post_pv(), generic_module_pointer_values(), loop_to_post_pv(), sequence_to_post_pv(), test_to_post_pv(), unstructured_to_post_pv(), and whileloop_to_post_pv().

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

◆ test_to_post_pv()

static list test_to_post_pv ( test  t,
list  l_in,
pv_context ctxt 
)
static

Definition at line 593 of file pointer_values_analyses.c.

594 {
595  list l_out = NIL;
596  pips_debug(1, "begin\n");
597 
598  expression t_cond = test_condition(t);
599  statement t_true = test_true(t);
600  statement t_false = test_false(t);
601 
602  pv_results pv_res = make_pv_results();
603  expression_to_post_pv(t_cond, l_in, &pv_res, ctxt);
604 
605  list l_in_branches = pv_res.l_out;
606 
607  list l_out_true = statement_to_post_pv(t_true, gen_full_copy_list(l_in_branches), ctxt);
608  list l_out_false = statement_to_post_pv(t_false, l_in_branches, ctxt);
609 
610  l_out = (*ctxt->pvs_may_union_func)(l_out_true, l_out_false);
611 
612  free_pv_results_paths(&pv_res);
613 
614  pips_debug_pvs(2, "returning: ", l_out);
615  pips_debug(1, "end\n");
616  return (l_out);
617 }
#define test_false(x)
Definition: ri.h:2837
#define test_true(x)
Definition: ri.h:2835
#define test_condition(x)
Definition: ri.h:2833

References expression_to_post_pv(), free_pv_results_paths(), gen_full_copy_list(), pv_results::l_out, make_pv_results(), NIL, pips_debug, pips_debug_pvs, pv_context::pvs_may_union_func, statement_to_post_pv(), test_condition, test_false, and test_true.

Referenced by instruction_to_post_pv().

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

◆ unstructured_to_post_pv()

static list unstructured_to_post_pv ( unstructured  u,
list  l_in,
pv_context ctxt 
)
static

there is only one statement in u;

Definition at line 882 of file pointer_values_analyses.c.

883 {
884  list l_out = NIL;
885  control entry_ctrl = unstructured_entry( unstr );
886  statement entry_node = control_statement(entry_ctrl);
887 
888  if(control_predecessors(entry_ctrl) == NIL && control_successors(entry_ctrl) == NIL)
889  {
890  /* there is only one statement in u; */
891  pips_debug(6, "unique node\n");
892  l_out = statement_to_post_pv(entry_node, l_in, ctxt);
893  }
894  else
895  {
896  pips_user_warning("Pointer analysis for unstructured part of code not yet fully implemented:\n"
897  "Consider restructuring your code\n");
898  list l_in_anywhere = make_anywhere_anywhere_pvs();
899  list blocs = NIL ;
900  CONTROL_MAP(c, {
901  list l_out = statement_to_post_pv(control_statement(c), gen_full_copy_list(l_in_anywhere), ctxt);
902  gen_full_free_list(l_out);
903  },
904  unstructured_exit( unstr ), blocs) ;
905  gen_free_list(blocs);
906  l_out = make_anywhere_anywhere_pvs();
907  }
908  pips_debug_pvs(2, "returning: ", l_out);
909  pips_debug(1, "end\n");
910  return (l_out);
911 }
#define CONTROL_MAP(ctl, code, c, list)
Macro to walk through all the controls reachable from a given control node of an unstructured.
list make_anywhere_anywhere_pvs()
#define control_predecessors(x)
Definition: ri.h:943
#define control_successors(x)
Definition: ri.h:945
#define unstructured_exit(x)
Definition: ri.h:3006
#define unstructured_entry(x)
Definition: ri.h:3004
#define control_statement(x)
Definition: ri.h:941

References CONTROL_MAP, control_predecessors, control_statement, control_successors, gen_free_list(), gen_full_copy_list(), gen_full_free_list(), make_anywhere_anywhere_pvs(), NIL, pips_debug, pips_debug_pvs, pips_user_warning, statement_to_post_pv(), unstructured_entry, and unstructured_exit.

Referenced by instruction_to_post_pv().

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

◆ whileloop_to_post_pv()

static list whileloop_to_post_pv ( whileloop  l,
list  l_in,
pv_context ctxt 
)
static

in case fix point is not reached

this iteration may never be executed :

now update input pointer values of inner loop statements

Definition at line 693 of file pointer_values_analyses.c.

694 {
695  list l_out = NIL;
696  list l_in_cur = NIL;
697  list l_saved = gen_full_copy_list(l_in); /* in case fix point is not reached */
699  bool before_p = evaluation_before_p(whileloop_evaluation(l));
700  statement body = whileloop_body(l);
701  pips_debug(1, "begin\n");
702 
703  int i = 1;
704  bool fix_point_reached = false;
705  l_out = l_in;
706  do
707  {
708  pips_debug(3, "fix point iteration number %d.\n", i);
709  list l_iter_in = gen_full_copy_list(l_out);
710  l_in_cur = l_out;
711 
712  if(before_p)
713  {
714  pv_results pv_res_cond = make_pv_results();
715  expression_to_post_pv(cond, l_in_cur, &pv_res_cond, ctxt);
716  l_in_cur = pv_res_cond.l_out;
717  free_pv_results_paths(&pv_res_cond);
718  }
719 
720  l_out = statement_to_post_pv(body, l_in_cur, ctxt);
721 
722  if(!before_p)
723  {
724  pv_results pv_res_cond = make_pv_results();
725  expression_to_post_pv(cond, l_out, &pv_res_cond, ctxt);
726  l_out = pv_res_cond.l_out;
727  free_pv_results_paths(&pv_res_cond);
728  }
729 
730  /* this iteration may never be executed :*/
731  if (i!=1 || before_p)
732  l_out = (*ctxt->pvs_may_union_func)(l_out,
733  gen_full_copy_list(l_iter_in));
734  else
735  {
736  l_in = gen_full_copy_list(l_out);
737  }
738 
739  i++;
740  fix_point_reached = (l_out == l_iter_in)
741  || (*ctxt->pvs_equal_p_func)(l_iter_in, l_out);
742  pips_debug(3, "fix point %s reached\n", fix_point_reached? "":"not");
743  gen_full_free_list(l_iter_in);
744  }
745  while(i<=PV_NB_MAX_ITER_FIX_POINT && !fix_point_reached);
746 
747  if (!fix_point_reached)
748  {
749  pv_results pv_res_failed = make_pv_results();
751  list l_anywhere = CONS(EFFECT, anywhere_eff, NIL);
752  list l_kind = CONS(CELL_INTERPRETATION,
754  single_pointer_assignment_to_post_pv(anywhere_eff, l_anywhere, l_kind,
755  false, l_saved,
756  &pv_res_failed, ctxt);
757  l_out = pv_res_failed.l_out;
758  free_pv_results_paths(&pv_res_failed);
759  free_effect(anywhere_eff);
760  gen_free_list(l_anywhere);
761  gen_full_free_list(l_kind);
762 
763  /* now update input pointer values of inner loop statements */
764  l_in_cur = gen_full_copy_list(l_out);
765  if(before_p)
766  {
767  pv_results pv_res_cond = make_pv_results();
768  expression_to_post_pv(cond, l_in_cur, &pv_res_cond, ctxt);
769  l_in_cur = pv_res_cond.l_out;
770  free_pv_results_paths(&pv_res_cond);
771  }
772 
773  list l_tmp = statement_to_post_pv(body, l_in_cur, ctxt);
774 
775  if(!before_p)
776  {
777  pv_results pv_res_cond = make_pv_results();
778  expression_to_post_pv(cond, l_tmp, &pv_res_cond, ctxt);
779  free_pv_results_paths(&pv_res_cond);
780  gen_full_free_list(pv_res_cond.l_out);
781  }
782  else
783  gen_full_free_list(l_tmp);
784  }
785  else
786  gen_full_free_list(l_saved);
787 
788  pips_debug_pvs(2, "returning:", l_out);
789  pips_debug(1, "end\n");
790  return (l_out);
791 }
#define whileloop_evaluation(x)
Definition: ri.h:3166
#define whileloop_body(x)
Definition: ri.h:3162
#define whileloop_condition(x)
Definition: ri.h:3160
#define evaluation_before_p(x)
Definition: ri.h:1159

References CELL_INTERPRETATION, CONS, EFFECT, evaluation_before_p, expression_to_post_pv(), free_effect(), free_pv_results_paths(), gen_free_list(), gen_full_copy_list(), gen_full_free_list(), pv_results::l_out, make_action_write_memory(), make_anywhere_effect(), make_cell_interpretation_address_of(), make_pv_results(), NIL, pips_debug, pips_debug_pvs, PV_NB_MAX_ITER_FIX_POINT, pv_context::pvs_equal_p_func, pv_context::pvs_may_union_func, single_pointer_assignment_to_post_pv(), statement_to_post_pv(), whileloop_body, whileloop_condition, and whileloop_evaluation.

Referenced by instruction_to_post_pv().

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