PIPS
pointer_values_intrinsics.c File Reference
#include <stdio.h>
#include <string.h>
#include "genC.h"
#include "linear.h"
#include "ri.h"
#include "ri-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 "misc.h"
#include "pointer_values.h"
+ Include dependency graph for pointer_values_intrinsics.c:

Go to the source code of this file.

Data Structures

struct  IntrinsicDescriptor
 The following data structure describes an intrinsic function: its name and its arity and its type, a function to type it (?) and a function to obtain its name if it is different from the entity user name, e.g. More...
 

Typedefs

typedef struct IntrinsicDescriptor IntrinsicToPostPVDescriptor
 the following data structure describes an intrinsic function: its name and the function to apply on a call to this intrinsic to get the post pointer values of the call More...
 

Functions

static void assignment_intrinsic_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void binary_arithmetic_operator_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void unary_arithmetic_operator_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void update_operator_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void logical_operator_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void conditional_operator_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void dereferencing_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void field_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void point_to_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void address_of_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void c_io_function_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void unix_io_function_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void string_function_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void va_list_function_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void heap_intrinsic_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void c_return_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void safe_intrinsic_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void intrinsic_to_identical_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void unknown_intrinsic_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void default_intrinsic_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void assignment_intrinsic_to_post_pv (entity __attribute__((unused)) func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void unary_arithmetic_operator_to_post_pv (entity __attribute__((unused)) func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void logical_operator_to_post_pv (entity __attribute__((unused)) func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void conditional_operator_to_post_pv (entity __attribute__((unused)) func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void dereferencing_to_post_pv (entity __attribute__((unused)) func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void field_to_post_pv (entity __attribute__((unused)) func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void point_to_to_post_pv (entity __attribute__((unused)) func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void address_of_to_post_pv (entity __attribute__((unused)) func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void free_to_post_pv (list l_free_eff, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void c_return_to_post_pv (entity __attribute__((unused)) func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void safe_intrinsic_to_post_pv (entity __attribute__((unused)) func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
static void intrinsic_to_identical_post_pv (entity __attribute__((unused)) func, list __attribute__((unused)) func_args, list l_in, pv_results *pv_res, pv_context __attribute__((unused)) *ctxt)
 
static void unknown_intrinsic_to_post_pv (entity __attribute__((unused)) func, list __attribute__((unused)) func_args, list __attribute__((unused)) l_in, pv_results __attribute__((unused)) *pv_res, pv_context __attribute__((unused)) *ctxt)
 
static void default_intrinsic_to_post_pv (entity __attribute__((unused)) func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 
void intrinsic_to_post_pv (entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
 pointer_values_intrinsics.c More...
 

Variables

static IntrinsicToPostPVDescriptor IntrinsicToPostPVDescriptorTable []
 

Typedef Documentation

◆ IntrinsicToPostPVDescriptor

the following data structure describes an intrinsic function: its name and the function to apply on a call to this intrinsic to get the post pointer values of the call

These intrinsics are arranged in the order of the standard ISO/IEC 9899:TC2. MB

Function Documentation

◆ address_of_to_post_pv() [1/2]

static void address_of_to_post_pv ( entity __attribute__((unused))  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

Definition at line 1485 of file pointer_values_intrinsics.c.

1487 {
1488  expression_to_post_pv(EXPRESSION(CAR(func_args)), l_in, pv_res, ctxt);
1490  {
1492  }
1493 }
#define cell_interpretation_tag(x)
Definition: effects.h:414
@ is_cell_interpretation_address_of
Definition: effects.h:397
#define CELL_INTERPRETATION(x)
CELL_INTERPRETATION.
Definition: effects.h:375
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
#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
void expression_to_post_pv(expression, list, pv_results *, pv_context *)
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
list result_paths_interpretations
resulting pointer path of the expression evaluation

References CAR, CELL_INTERPRETATION, cell_interpretation_tag, EXPRESSION, expression_to_post_pv(), FOREACH, is_cell_interpretation_address_of, and pv_results::result_paths_interpretations.

+ Here is the call graph for this function:

◆ address_of_to_post_pv() [2/2]

static void address_of_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

◆ assignment_intrinsic_to_post_pv() [1/2]

static void assignment_intrinsic_to_post_pv ( entity __attribute__((unused))  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

Definition at line 1100 of file pointer_values_intrinsics.c.

1104 {
1105  expression lhs = EXPRESSION(CAR(func_args));
1106  expression rhs = EXPRESSION(CAR(CDR(func_args)));
1107  assignment_to_post_pv(lhs, false, rhs, false, l_in, pv_res, ctxt);
1108 }
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
void assignment_to_post_pv(expression, bool, expression, bool, list, pv_results *, pv_context *)

References assignment_to_post_pv(), CAR, CDR, and EXPRESSION.

+ Here is the call graph for this function:

◆ assignment_intrinsic_to_post_pv() [2/2]

static void assignment_intrinsic_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

◆ binary_arithmetic_operator_to_post_pv()

static void binary_arithmetic_operator_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

From ISO/IEC 9899:TC3 :

  • For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to an object type and the other shall have integer type.
  • For substraction, one of the following shall hold :
    • both operands have arithmetic types
    • both operands are pointers to qualified or unqualified versions of compatible object types; (in this case, both pointers shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements) (as a consequence the result is not of a pointer type)
    • the left operand is a pointer to an object type and the right operand has integer type

pointer arithmetic, the pointer is in the first expression

build new effects

Definition at line 1110 of file pointer_values_intrinsics.c.

1113 {
1114  list l_in_cur;
1115 
1116  pips_debug(1, "begin\n");
1117 
1118  pv_results pv_res1 = make_pv_results();
1119  expression arg1 = EXPRESSION(CAR(func_args));
1120  expression_to_post_pv(arg1, l_in, &pv_res1, ctxt);
1121 
1122  l_in_cur = pv_res1.l_out;
1123  if (l_in != l_in_cur) gen_full_free_list(l_in);
1124 
1125  pv_results pv_res2 = make_pv_results();
1126  expression arg2 = EXPRESSION(CAR(CDR(func_args)));
1127  expression_to_post_pv(arg2, l_in_cur, &pv_res2, ctxt);
1128  if (pv_res2.l_out != l_in_cur) gen_full_free_list(l_in_cur);
1129 
1130 
1131  type t1 = expression_to_type(arg1);
1132  bool pointer_t1 = pointer_type_p(t1);
1133  bool array_t1 = array_type_p(t1);
1134  pips_debug(5, "type t1 is: %s (%s)\n", string_of_type(t1),
1135  type_to_string(t1));
1136 
1137  type t2 = expression_to_type(arg2);
1138  bool pointer_t2 = pointer_type_p(t2);
1139  bool array_t2 = array_type_p(t2);
1140  pips_debug(5, "type t2 is: %s (%s)\n", string_of_type(t2),
1141  type_to_string(t2));
1142 
1143  int nb_dims = 0;
1144 
1145  const char* func_name = entity_local_name(func);
1146 
1147  /* From ISO/IEC 9899:TC3 :
1148 
1149  - For addition, either both operands shall have arithmetic type,
1150  or one operand shall be a pointer to an object type and the other
1151  shall have integer type.
1152 
1153  - For substraction, one of the following shall hold :
1154 
1155  - both operands have arithmetic types
1156  - both operands are pointers to qualified or unqualified versions of
1157  compatible object types;
1158  (in this case, both pointers shall point to elements of the same array object,
1159  or one past the last element of the array object; the result is the difference
1160  of the subscripts of the two array elements)
1161  (as a consequence the result is not of a pointer type)
1162  - the left operand is a pointer to an object type and the right operand has
1163  integer type
1164  */
1165  list l_eff1 = pv_res1.result_paths;
1166  list l_eff2 = pv_res2.result_paths;
1167 
1168  bool pointer_arithmetic = false;
1169  list l_eff_pointer = NIL;
1170  expression other_arg = expression_undefined;
1171 
1172  if ((pointer_t1 || array_t1) && !(pointer_t2 || array_t2))
1173  /* pointer arithmetic, the pointer is in the first expression */
1174  {
1175  pointer_arithmetic = true;
1176  l_eff_pointer = l_eff1;
1177  other_arg = arg2;
1178  nb_dims = pointer_t1 ? 1 : gen_length(variable_dimensions(type_variable(t1)));
1179  }
1180  else if ((pointer_t2 || array_t2) && !(pointer_t1 || array_t1))
1181  {
1182  pointer_arithmetic = true;
1183  l_eff_pointer = l_eff2;
1184  other_arg = arg1;
1185  nb_dims = pointer_t2 ? 1 : gen_length(variable_dimensions(type_variable(t2)));
1186  }
1187  free_type(t1);
1188  free_type(t2);
1189 
1190  if (pointer_arithmetic)
1191  {
1192  free_pv_results_paths(pv_res);
1193  if (!anywhere_effect_p(EFFECT(CAR(l_eff_pointer))))
1194  {
1195  /* build new effects */
1196  list l_new_eff = NIL;
1197  list l_new_eff_kind = NIL;
1198 
1199  if (nb_dims == 1)
1200  {
1201 
1202  pips_debug(3, "one dimension case\n");
1203  expression new_arg = copy_expression(other_arg);
1204 
1205  if (same_string_p(func_name, MINUS_C_OPERATOR_NAME))
1206  {
1207  entity unary_minus_ent =
1210  entity_domain);
1211  new_arg = MakeUnaryCall(unary_minus_ent, new_arg);
1212  }
1213 
1214  FOREACH(EFFECT, eff, l_eff_pointer)
1215  {
1216  effect new_eff = copy_effect(eff);
1217  reference new_ref = effect_any_reference(new_eff);
1218  list l_inds = reference_indices(new_ref);
1219  if (ENDP(l_inds))
1220  {
1221  // functions that can be pointed by effect_add_expression_dimension_func:
1222  // simple_effect_add_expression_dimension
1223  // convex_region_add_expression_dimension
1224  (*effect_add_expression_dimension_func)(new_eff, new_arg);
1225  }
1226  else
1227  {
1228  expression last_exp = EXPRESSION(CAR(gen_last(l_inds)));
1231  entity_domain);
1232  new_arg = MakeBinaryCall(binary_plus_ent, copy_expression(last_exp), new_arg);
1233  // functions that can be pointed by effect_change_ith_dimension_expression_func:
1234  // simple_effect_change_ith_dimension_expression
1235  // convex_region_change_ith_dimension_expression
1236  (*effect_change_ith_dimension_expression_func)(new_eff, new_arg, (int) gen_length(l_inds));
1237  }
1238  l_new_eff = CONS(EFFECT, new_eff, l_new_eff);
1239  l_new_eff_kind = CONS(CELL_INTERPRETATION,
1241  }
1242  free_expression(new_arg);
1243 
1244  }
1245  else
1246  {
1247  pips_debug(3, "several dimensions (%d) case\n", nb_dims);
1248 
1249  // we could do more work to be more precise
1251  FOREACH(EFFECT, eff, l_eff_pointer)
1252  {
1253  effect new_eff = copy_effect(eff);
1254 
1255  for(int i = 1; i <= nb_dims; i++) {
1256  // functions that can be pointed by effect_add_expression_dimension_func:
1257  // simple_effect_add_expression_dimension
1258  // convex_region_add_expression_dimension
1259  (*effect_add_expression_dimension_func)(new_eff, copy_expression(new_ind));
1260  }
1261  l_new_eff = CONS(EFFECT, new_eff, l_new_eff);
1262  l_new_eff_kind = CONS(CELL_INTERPRETATION,
1264  }
1265  free_expression(new_ind);
1266  }
1267  gen_nreverse(l_new_eff);
1268  gen_nreverse(l_new_eff_kind);
1269  pv_res->result_paths = l_new_eff;
1270  pv_res->result_paths_interpretations = l_new_eff_kind;
1271  }
1272  }
1273  pv_res->l_out = pv_res2.l_out;
1274  free_pv_results_paths(&pv_res1);
1275  free_pv_results_paths(&pv_res2);
1276  pips_debug_pv_results(1, "end with pv_res =\n", *pv_res);
1277 }
cell_interpretation make_cell_interpretation_address_of(void)
Definition: effects.c:240
effect copy_effect(effect p)
EFFECT.
Definition: effects.c:448
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
void free_expression(expression p)
Definition: ri.c:853
void free_type(type p)
Definition: ri.c:2658
void const char const char const int
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
bool anywhere_effect_p(effect)
Is it an anywhere effect? ANYMMODULE:ANYWHERE
Definition: effects.c:346
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
string make_entity_fullname(const char *module_name, const char *local_name)
END_EOLE.
Definition: entity_names.c:230
void gen_full_free_list(list l)
Definition: genClib.c:1023
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define TOP_LEVEL_MODULE_NAME
Module containing the global variables in Fortran and C.
Definition: naming-local.h:101
#define same_string_p(s1, s2)
void * gen_find_tabulated(const char *, int)
Definition: tabulated.c:218
#define pips_debug_pv_results(level, message, pv_res)
pv_results make_pv_results(void)
void free_pv_results_paths(pv_results *)
string string_of_type(const type)
Definition: type.c:56
#define UNARY_MINUS_OPERATOR_NAME
#define MINUS_C_OPERATOR_NAME
#define PLUS_C_OPERATOR_NAME
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
expression make_unbounded_expression()
Definition: expression.c:4339
expression MakeBinaryCall(entity f, expression eg, expression ed)
Creates a call expression to a function with 2 arguments.
Definition: expression.c:354
expression MakeUnaryCall(entity f, expression a)
Creates a call expression to a function with one argument.
Definition: expression.c:342
bool array_type_p(type)
Definition: type.c:2942
type expression_to_type(expression)
For an array declared as int a[10][20], the type returned for a[i] is int [20].
Definition: type.c:2486
bool pointer_type_p(type)
Check for scalar pointers.
Definition: type.c:2993
string type_to_string(const type)
type.c
Definition: type.c:51
#define type_variable(x)
Definition: ri.h:2949
#define expression_undefined
Definition: ri.h:1223
#define reference_indices(x)
Definition: ri.h:2328
#define variable_dimensions(x)
Definition: ri.h:3122
#define entity_domain
newgen_syntax_domain_defined
Definition: ri.h:410
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
resulting pointer_values

References anywhere_effect_p(), array_type_p(), CAR, CDR, CELL_INTERPRETATION, CONS, copy_effect(), copy_expression(), EFFECT, effect_any_reference, ENDP, entity_domain, entity_local_name(), EXPRESSION, expression_to_post_pv(), expression_to_type(), expression_undefined, FOREACH, free_expression(), free_pv_results_paths(), free_type(), gen_find_tabulated(), gen_full_free_list(), gen_last(), gen_length(), gen_nreverse(), int, pv_results::l_out, make_cell_interpretation_address_of(), make_entity_fullname(), make_pv_results(), make_unbounded_expression(), MakeBinaryCall(), MakeUnaryCall(), MINUS_C_OPERATOR_NAME, NIL, pips_debug, pips_debug_pv_results, PLUS_C_OPERATOR_NAME, pointer_type_p(), reference_indices, pv_results::result_paths, pv_results::result_paths_interpretations, same_string_p, string_of_type(), TOP_LEVEL_MODULE_NAME, type_to_string(), type_variable, UNARY_MINUS_OPERATOR_NAME, and variable_dimensions.

+ Here is the call graph for this function:

◆ c_io_function_to_post_pv()

static void c_io_function_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

first argument is a FILE*

last argument is a FILE*

we assume that there is no effects on aliasing due to FILE* argument if any

Definition at line 1495 of file pointer_values_intrinsics.c.

1497 {
1498  const char* func_name = entity_local_name(func);
1499  list general_args = NIL;
1500  bool free_general_args = false;
1501  list l_in_cur = l_in;
1502 
1503  /* first argument is a FILE* */
1504  if (same_string_p(func_name,FCLOSE_FUNCTION_NAME)
1505  || same_string_p(func_name,FPRINTF_FUNCTION_NAME)
1506  || same_string_p(func_name,FSCANF_FUNCTION_NAME)
1508  || same_string_p(func_name,VFSCANF_FUNCTION_NAME)
1510  || same_string_p(func_name,FGETC_FUNCTION_NAME)
1511  || same_string_p(func_name,GETC_FUNCTION_NAME)
1513  || same_string_p(func_name,FGETPOS_FUNCTION_NAME)
1514  || same_string_p(func_name,FSEEK_FUNCTION_NAME)
1515  || same_string_p(func_name,FSETPOS_FUNCTION_NAME)
1516  || same_string_p(func_name,FTELL_FUNCTION_NAME)
1519  || same_string_p(func_name,FEOF_FUNCTION_NAME)
1520  || same_string_p(func_name,FERROR_FUNCTION_NAME))
1521  {
1522  general_args = CDR(func_args);
1523  }
1524  /* last argument is a FILE* */
1525  else if (same_string_p(func_name,FGETS_FUNCTION_NAME)
1526  || same_string_p(func_name,FPUTC_FUNCTION_NAME)
1527  || same_string_p(func_name,FPUTS_FUNCTION_NAME)
1528  || same_string_p(func_name,PUTC_FUNCTION_NAME)
1530  || same_string_p(func_name,UNGETC_FUNCTION_NAME)
1531  || same_string_p(func_name,FREAD_FUNCTION_NAME)
1532  || same_string_p(func_name,FWRITE_FUNCTION_NAME))
1533  {
1534  for(; !ENDP(CDR(func_args)); POP(func_args))
1535  {
1536  general_args = CONS(EXPRESSION, EXPRESSION(CAR(func_args)), general_args);
1537  }
1538  free_general_args = true;
1539  }
1540 
1541  /* we assume that there is no effects on aliasing due to FILE* argument if any */
1542 
1543  safe_intrinsic_to_post_pv(func, general_args, l_in_cur, pv_res, ctxt);
1544 
1545  if (free_general_args)
1546  gen_free_list(general_args);
1547 }
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
static void safe_intrinsic_to_post_pv(entity func, list func_args, list l_in, pv_results *pv_res, pv_context *ctxt)
#define FREAD_FUNCTION_NAME
#define VFPRINTF_FUNCTION_NAME
#define FGETC_FUNCTION_NAME
#define FWRITE_FUNCTION_NAME
#define ISOC99_VFSCANF_FUNCTION_NAME
#define FGETPOS_FUNCTION_NAME
#define C_REWIND_FUNCTION_NAME
#define GETC_FUNCTION_NAME
#define CLEARERR_FUNCTION_NAME
#define PUTC_FUNCTION_NAME
#define FSEEK_FUNCTION_NAME
#define _IO_GETC_FUNCTION_NAME
#define VFSCANF_FUNCTION_NAME
#define FPRINTF_FUNCTION_NAME
#define UNGETC_FUNCTION_NAME
#define _IO_PUTC_FUNCTION_NAME
#define FGETS_FUNCTION_NAME
#define FEOF_FUNCTION_NAME
#define FTELL_FUNCTION_NAME
#define FPUTC_FUNCTION_NAME
#define FERROR_FUNCTION_NAME
#define FSCANF_FUNCTION_NAME
#define FPUTS_FUNCTION_NAME
#define FCLOSE_FUNCTION_NAME
#define FSETPOS_FUNCTION_NAME

References _IO_GETC_FUNCTION_NAME, _IO_PUTC_FUNCTION_NAME, C_REWIND_FUNCTION_NAME, CAR, CDR, CLEARERR_FUNCTION_NAME, CONS, ENDP, entity_local_name(), EXPRESSION, FCLOSE_FUNCTION_NAME, FEOF_FUNCTION_NAME, FERROR_FUNCTION_NAME, FGETC_FUNCTION_NAME, FGETPOS_FUNCTION_NAME, FGETS_FUNCTION_NAME, FPRINTF_FUNCTION_NAME, FPUTC_FUNCTION_NAME, FPUTS_FUNCTION_NAME, FREAD_FUNCTION_NAME, FSCANF_FUNCTION_NAME, FSEEK_FUNCTION_NAME, FSETPOS_FUNCTION_NAME, FTELL_FUNCTION_NAME, FWRITE_FUNCTION_NAME, gen_free_list(), GETC_FUNCTION_NAME, ISOC99_VFSCANF_FUNCTION_NAME, NIL, POP, PUTC_FUNCTION_NAME, safe_intrinsic_to_post_pv(), same_string_p, UNGETC_FUNCTION_NAME, VFPRINTF_FUNCTION_NAME, and VFSCANF_FUNCTION_NAME.

+ Here is the call graph for this function:

◆ c_return_to_post_pv() [1/2]

static void c_return_to_post_pv ( entity __attribute__((unused))  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

but we have to evaluate the impact of the argument evaluation on pointer values eliminate local variables, retrieve the value of the returned pointer if any...

Definition at line 1853 of file pointer_values_intrinsics.c.

1855 {
1856  /* but we have to evaluate the impact
1857  of the argument evaluation on pointer values
1858  eliminate local variables, retrieve the value of the returned pointer if any...
1859  */
1860  if (!ENDP(func_args))
1861  expression_to_post_pv(EXPRESSION(CAR(func_args)), l_in, pv_res, ctxt);
1862 }

References CAR, ENDP, EXPRESSION, and expression_to_post_pv().

+ Here is the call graph for this function:

◆ c_return_to_post_pv() [2/2]

static void c_return_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

◆ conditional_operator_to_post_pv() [1/2]

static void conditional_operator_to_post_pv ( entity __attribute__((unused))  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

well, it should be a union, but there may not be such stupid things as (..)? a:a; I cannot use the effects test union operator because I must also merge interpretations

Definition at line 1382 of file pointer_values_intrinsics.c.

1385 {
1386  pips_debug(1, "begin for conditional operator\n");
1387 
1388  expression t_cond = EXPRESSION(CAR(func_args));
1389  POP(func_args);
1390  expression t_true = EXPRESSION(CAR(func_args));
1391  POP(func_args);
1392  expression t_false = EXPRESSION(CAR(func_args));
1393 
1394  pv_results pv_res_cond = make_pv_results();
1395  expression_to_post_pv(t_cond, l_in, &pv_res_cond, ctxt);
1396 
1397  list l_in_branches = pv_res_cond.l_out;
1398 
1399  pv_results pv_res_true = make_pv_results();
1400  list l_in_true = gen_full_copy_list(l_in_branches);
1401  expression_to_post_pv(t_true, l_in_true, &pv_res_true, ctxt);
1402  if (pv_res_true.l_out != l_in_true) gen_full_free_list(l_in_true);
1403 
1404  pv_results pv_res_false = make_pv_results();
1405  list l_in_false = gen_full_copy_list(l_in_branches);
1406  expression_to_post_pv(t_false, l_in_false, &pv_res_false, ctxt);
1407  if (pv_res_false.l_out != l_in_false) gen_full_free_list(l_in_false);
1408 
1409 
1410  pv_res->l_out = (*ctxt->pvs_may_union_func)(pv_res_true.l_out,
1411  gen_full_copy_list(pv_res_false.l_out));
1412 
1413  /* well, it should be a union, but there may not be such stupid things as (..)? a:a;
1414  I cannot use the effects test union operator because I must also merge
1415  interpretations */
1416  pv_res->result_paths = gen_nconc(pv_res_true.result_paths, pv_res_false.result_paths);
1420  pv_res_false.result_paths_interpretations);
1421 
1422  pips_debug_pv_results(1, "end with pv_results =\n", *pv_res);
1423  pips_debug(1, "end\n");
1424 
1425 }
void effects_to_may_effects(list)
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
list(* pvs_may_union_func)(list, list)

References CAR, effects_to_may_effects(), EXPRESSION, expression_to_post_pv(), gen_full_copy_list(), gen_full_free_list(), gen_nconc(), pv_results::l_out, make_pv_results(), pips_debug, pips_debug_pv_results, POP, pv_context::pvs_may_union_func, pv_results::result_paths, and pv_results::result_paths_interpretations.

+ Here is the call graph for this function:

◆ conditional_operator_to_post_pv() [2/2]

static void conditional_operator_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

◆ default_intrinsic_to_post_pv() [1/2]

static void default_intrinsic_to_post_pv ( entity __attribute__((unused))  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

free the result paths of the previous expression evaluation

Definition at line 1954 of file pointer_values_intrinsics.c.

1957 {
1958  list l_in_cur = l_in;
1959  FOREACH(EXPRESSION, arg, func_args)
1960  {
1961  /* free the result paths of the previous expression evaluation */
1962  free_pv_results_paths(pv_res);
1963  expression_to_post_pv(arg, l_in_cur, pv_res, ctxt);
1964  l_in_cur = pv_res->l_out;
1965  }
1966 }

References EXPRESSION, expression_to_post_pv(), FOREACH, free_pv_results_paths(), and pv_results::l_out.

+ Here is the call graph for this function:

◆ default_intrinsic_to_post_pv() [2/2]

static void default_intrinsic_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

◆ dereferencing_to_post_pv() [1/2]

static void dereferencing_to_post_pv ( entity __attribute__((unused))  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

Definition at line 1429 of file pointer_values_intrinsics.c.

1431 {
1432  expression_to_post_pv(EXPRESSION(CAR(func_args)), l_in, pv_res, ctxt);
1433  list l_eff_ci = pv_res->result_paths_interpretations;
1434  FOREACH(EFFECT, eff, pv_res->result_paths)
1435  {
1439  else
1441  POP(l_eff_ci);
1442  }
1443 }
void effect_add_dereferencing_dimension(effect)
@ is_cell_interpretation_value_of
Definition: effects.h:396
#define cell_interpretation_value_of_p(x)
Definition: effects.h:415

References CAR, CELL_INTERPRETATION, cell_interpretation_tag, cell_interpretation_value_of_p, EFFECT, effect_add_dereferencing_dimension(), EXPRESSION, expression_to_post_pv(), FOREACH, is_cell_interpretation_value_of, POP, pv_results::result_paths, and pv_results::result_paths_interpretations.

+ Here is the call graph for this function:

◆ dereferencing_to_post_pv() [2/2]

static void dereferencing_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

◆ field_to_post_pv() [1/2]

static void field_to_post_pv ( entity __attribute__((unused))  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

Definition at line 1445 of file pointer_values_intrinsics.c.

1447 {
1448  expression e2 = EXPRESSION(CAR(CDR(func_args)));
1449  syntax s2 = expression_syntax(e2);
1450  reference r2 = syntax_reference(s2);
1451  entity f = reference_variable(r2);
1452 
1453  pips_assert("e2 is a reference", syntax_reference_p(s2));
1454  pips_debug(4, "It's a field operator\n");
1455 
1456  expression_to_post_pv(EXPRESSION(CAR(func_args)), l_in, pv_res, ctxt);
1457  FOREACH(EFFECT, eff, pv_res->result_paths)
1458  {
1460  }
1461 }
void effect_add_field_dimension(effect, entity)
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
#define syntax_reference_p(x)
Definition: ri.h:2728
#define syntax_reference(x)
Definition: ri.h:2730
#define reference_variable(x)
Definition: ri.h:2326
#define expression_syntax(x)
Definition: ri.h:1247

References CAR, CDR, EFFECT, effect_add_field_dimension(), EXPRESSION, expression_syntax, expression_to_post_pv(), f(), FOREACH, pips_assert, pips_debug, reference_variable, pv_results::result_paths, syntax_reference, and syntax_reference_p.

+ Here is the call graph for this function:

◆ field_to_post_pv() [2/2]

static void field_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

◆ free_to_post_pv()

static void free_to_post_pv ( list  l_free_eff,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

for each freed pointer, find it's targets

try to find the heap location

try to find the heap target in remants

try first to find another target

try to find the heap location

assign an undefined_value to freed pointer

no flow or context sensitive variable found

FOREACH

Definition at line 1568 of file pointer_values_intrinsics.c.

1570 {
1571  pips_debug_effects(5, "begin with input effects :\n", l_free_eff);
1572 
1573  FOREACH(EFFECT, eff, l_free_eff)
1574  {
1575  /* for each freed pointer, find it's targets */
1576 
1577  list l_remnants = NIL;
1578  cell_relation exact_eff_pv = cell_relation_undefined;
1579  list l_values = NIL;
1580 
1581  pips_debug_effect(4, "begin, looking for an exact target for eff:\n",
1582  eff);
1583 
1584  l_values = effect_find_equivalent_pointer_values(eff, l_in,
1585  &exact_eff_pv,
1586  &l_remnants);
1587  pips_debug_pvs(3, "l_values:\n", l_values);
1588  pips_debug_pvs(3, "l_remnants:\n", l_remnants);
1589  pips_debug_pv(3, "exact_eff_pv:\n", exact_eff_pv);
1590 
1591  list l_heap_eff = NIL;
1592 
1593  if (exact_eff_pv != cell_relation_undefined)
1594  {
1595  cell heap_c = cell_undefined;
1596  /* try to find the heap location */
1597  cell c1 = cell_relation_first_cell(exact_eff_pv);
1599 
1600  cell c2 = cell_relation_second_cell(exact_eff_pv);
1602 
1604  heap_c = c1;
1606  heap_c = c2;
1607  if (!cell_undefined_p(heap_c))
1608  l_heap_eff =
1609  CONS(EFFECT,
1610  make_effect(copy_cell(heap_c),
1614  NIL);
1615  else
1616  {
1617  /* try to find the heap target in remants */
1618  cell other_c = cell_undefined;
1619  if (same_entity_p(effect_entity(eff), e1))
1620  other_c = c2;
1621  else other_c = c1;
1622  list l_tmp =
1623  CONS(EFFECT,
1624  make_effect(copy_cell(other_c),
1628  NIL);
1629  free_to_post_pv(l_tmp, l_remnants, pv_res, ctxt);
1630  pv_res->l_out = CONS(CELL_RELATION,
1631  copy_cell_relation(exact_eff_pv),
1632  pv_res->l_out);
1633  gen_free_list(l_tmp);
1634  return;
1635  }
1636  }
1637  else
1638  {
1639  /* try first to find another target */
1640  FOREACH(CELL_RELATION, pv_tmp, l_values) {
1641  cell heap_c = cell_undefined;
1642  /* try to find the heap location */
1643  cell c1 = cell_relation_first_cell(pv_tmp);
1645 
1646  cell c2 = cell_relation_second_cell(pv_tmp);
1648 
1650  heap_c = c1;
1652  heap_c = c2;
1653  if (!cell_undefined_p(heap_c))
1654  l_heap_eff =
1655  CONS(EFFECT,
1656  make_effect(copy_cell(heap_c),
1658  cell_relation_exact_p(pv_tmp)
1660  (effect_approximation(eff))
1663  NIL);
1664 
1665  }
1666  }
1667 
1668  if (!ENDP(l_heap_eff))
1669  {
1670  /* assign an undefined_value to freed pointer */
1671  list l_rhs =
1672  CONS(EFFECT,
1677  NIL);
1678  list l_kind = CONS(CELL_INTERPRETATION,
1680  NIL);
1681  single_pointer_assignment_to_post_pv(eff, l_rhs, l_kind,
1682  false, l_in, pv_res, ctxt);
1683  gen_full_free_list(l_rhs);
1684  gen_full_free_list(l_kind);
1685  free_pv_results_paths(pv_res);
1686  if (l_in != pv_res->l_out)
1687  {
1688  gen_full_free_list(l_in);
1689  l_in = pv_res->l_out;
1690  }
1691  pips_debug_pvs(5, "l_in after assigning "
1692  "undefined value to freed pointer:\n",
1693  l_in);
1694 
1695  FOREACH(EFFECT, heap_eff, l_heap_eff)
1696  {
1697  entity heap_e =
1699  pips_debug(5, "heap entity found (%s)\n", entity_name(heap_e));
1700 
1702  effect_may_p(eff)
1703  || effect_may_p(heap_eff),
1704  l_in,
1705  pv_res, ctxt);
1706  l_in= pv_res->l_out;
1707  }
1708  }
1709  else /* no flow or context sensitive variable found */
1710  {
1711  list l_rhs =
1712  CONS(EFFECT,
1717  NIL);
1718  list l_kind = CONS(CELL_INTERPRETATION,
1720  NIL);
1721  single_pointer_assignment_to_post_pv(eff, l_rhs, l_kind,
1722  false, l_in, pv_res, ctxt);
1723  gen_full_free_list(l_rhs);
1724  gen_full_free_list(l_kind);
1725  free_pv_results_paths(pv_res);
1726  if (l_in != pv_res->l_out)
1727  {
1728  gen_full_free_list(l_in);
1729  l_in = pv_res->l_out;
1730  }
1731  pips_debug_pvs(5, "l_in after assigning "
1732  "undefined value to freed pointer:\n",
1733  l_in);
1734  }
1735 
1736  } /* FOREACH */
1737  pips_debug_pvs(5, "end with pv_res->l_out:", pv_res->l_out);
1738 }
cell_interpretation make_cell_interpretation_value_of(void)
Definition: effects.c:237
approximation make_approximation_exact(void)
Definition: effects.c:185
approximation copy_approximation(approximation p)
APPROXIMATION.
Definition: effects.c:132
approximation make_approximation_may(void)
Definition: effects.c:179
effect make_effect(cell a1, action a2, approximation a3, descriptor a4)
Definition: effects.c:484
cell_relation copy_cell_relation(cell_relation p)
CELL_RELATION.
Definition: effects.c:305
descriptor make_descriptor_none(void)
Definition: effects.c:442
cell copy_cell(cell p)
CELL.
Definition: effects.c:246
bool entity_flow_or_context_sentitive_heap_location_p(entity e)
#define pips_debug_effects(level, message, l_eff)
#define pips_debug_effect(level, message, eff)
for debug
#define effect_may_p(eff)
#define pips_debug_pv(level, message, pv)
#define cell_relation_second_cell(cr)
#define pips_debug_pvs(level, message, l_pv)
#define cell_relation_exact_p(cr)
#define cell_relation_first_cell(cr)
entity effect_entity(effect)
cproto-generated files
Definition: effects.c:52
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)
#define cell_reference(x)
Definition: effects.h:469
#define CELL_RELATION(x)
CELL_RELATION.
Definition: effects.h:479
#define cell_undefined_p(x)
Definition: effects.h:431
#define cell_undefined
Definition: effects.h:430
#define cell_relation_undefined
Definition: effects.h:485
#define effect_approximation(x)
Definition: effects.h:644
void pointer_values_remove_var(entity, bool, list, pv_results *, pv_context *)
void single_pointer_assignment_to_post_pv(effect, list, list, bool, list, pv_results *, pv_context *)
list effect_find_equivalent_pointer_values(effect, list, cell_relation *, list *)
find pointer_values in l_in which give (possible or exact) paths equivalent to eff.
static void free_to_post_pv(list l_free_eff, list l_in, pv_results *pv_res, pv_context *ctxt)
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
#define entity_name(x)
Definition: ri.h:2790

References CELL_INTERPRETATION, cell_reference, CELL_RELATION, cell_relation_exact_p, cell_relation_first_cell, cell_relation_second_cell, cell_relation_undefined, cell_undefined, cell_undefined_p, CONS, copy_approximation(), copy_cell(), copy_cell_relation(), EFFECT, effect_any_reference, effect_approximation, effect_entity(), effect_find_equivalent_pointer_values(), effect_may_p, ENDP, entity_flow_or_context_sentitive_heap_location_p(), entity_name, FOREACH, free_pv_results_paths(), gen_free_list(), gen_full_free_list(), pv_results::l_out, make_action_write_memory(), make_approximation_exact(), make_approximation_may(), make_cell_interpretation_value_of(), make_descriptor_none(), make_effect(), make_undefined_pointer_value_cell(), NIL, pips_debug, pips_debug_effect, pips_debug_effects, pips_debug_pv, pips_debug_pvs, pointer_values_remove_var(), reference_variable, same_entity_p(), and single_pointer_assignment_to_post_pv().

Referenced by heap_intrinsic_to_post_pv().

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

◆ heap_intrinsic_to_post_pv()

static void heap_intrinsic_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

free the previously allocated path if need be

Then retrieve the allocated path if any

first, impact of argument evaluation on pointer values

Definition at line 1740 of file pointer_values_intrinsics.c.

1742 {
1743  const char* func_name = entity_local_name(func);
1744  expression malloc_arg = expression_undefined;
1745  bool free_malloc_arg = false;
1746  list l_in_cur = l_in;
1747 
1748 
1749  /* free the previously allocated path if need be */
1750  if (same_string_p(func_name, FREE_FUNCTION_NAME)
1751  || same_string_p(func_name, REALLOC_FUNCTION_NAME))
1752  {
1753  expression free_ptr_exp = EXPRESSION(CAR(func_args));
1754 
1755  pv_results pv_res_arg = make_pv_results();
1756  expression_to_post_pv(free_ptr_exp, l_in_cur, &pv_res_arg, ctxt);
1757  if (pv_res_arg.l_out != l_in_cur)
1758  {
1759  gen_full_free_list(l_in_cur);
1760  l_in_cur = pv_res_arg.l_out;
1761  }
1762  free_to_post_pv(pv_res_arg.result_paths, l_in_cur, pv_res, ctxt);
1763  l_in_cur = pv_res->l_out;
1764  }
1765 
1766  /* Then retrieve the allocated path if any */
1767  if(same_string_p(func_name, MALLOC_FUNCTION_NAME))
1768  {
1769  malloc_arg = EXPRESSION(CAR(func_args));
1770  }
1771  else if(same_string_p(func_name, CALLOC_FUNCTION_NAME))
1772  {
1773  malloc_arg =
1774  make_op_exp("*",
1775  copy_expression(EXPRESSION(CAR(func_args))),
1776  copy_expression(EXPRESSION(CAR(CDR(func_args)))));
1777  free_malloc_arg = true;
1778  }
1779  else if (same_string_p(func_name, REALLOC_FUNCTION_NAME))
1780  {
1781  malloc_arg = EXPRESSION(CAR(CDR(func_args)));
1782  }
1783  else if (same_string_p(func_name, STRDUP_FUNCTION_NAME))
1784  {
1785  malloc_arg = MakeBinaryCall(
1787  int_to_expression(1),
1788  MakeUnaryCall(
1790  copy_expression(EXPRESSION(CAR(func_args)))
1791  )
1792  );
1793  free_malloc_arg = true;
1794  }
1795 
1796  if (!expression_undefined_p(malloc_arg))
1797  {
1798 
1799  /* first, impact of argument evaluation on pointer values */
1800  pv_results pv_res_arg = make_pv_results();
1801  expression_to_post_pv(malloc_arg, l_in_cur, &pv_res_arg, ctxt);
1802  free_pv_results_paths(&pv_res_arg);
1803  if (pv_res_arg.l_out != l_in_cur)
1804  {
1805  gen_full_free_list(l_in_cur);
1806  l_in_cur = pv_res_arg.l_out;
1807  }
1808 
1812  NIL);
1813  entity e = malloc_to_abstract_location(malloc_arg, &si);
1814 
1819 
1820  if (!entity_all_heap_locations_p(e) &&
1822  {
1823  if (!entity_scalar_p(e))
1824  effect_add_dereferencing_dimension(eff); // well, in fact, it's a [0] array dimension!
1825  }
1826  else
1827  effect_to_may_effect(eff);
1828  pv_res->result_paths = CONS(EFFECT, eff, NIL);
1832  NIL);
1833  if (free_malloc_arg)
1834  free_expression(malloc_arg);
1835  }
1836 
1837  pv_res->l_out = l_in_cur;
1838 }
cell make_cell_reference(reference _field_)
Definition: effects.c:293
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
sensitivity_information make_sensitivity_information(statement current_stmt, entity current_module, list enclosing_flow)
entity malloc_to_abstract_location(expression malloc_exp, sensitivity_information *psi)
generate an abstract heap location entity
bool entity_all_module_heap_locations_p(entity e)
test if an entity is the a heap area
bool entity_all_heap_locations_p(entity e)
test if an entity is the set of all heap locations
void effect_to_may_effect(effect)
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
statement pv_context_statement_head(pv_context *)
#define REALLOC_FUNCTION_NAME
#define STRLEN_FUNCTION_NAME
#define MALLOC_FUNCTION_NAME
#define PLUS_OPERATOR_NAME
#define CALLOC_FUNCTION_NAME
#define STRDUP_FUNCTION_NAME
#define FREE_FUNCTION_NAME
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
expression make_op_exp(char *op_name, expression exp1, expression exp2)
================================================================
Definition: expression.c:2012
bool entity_scalar_p(entity)
The concrete type of e is a scalar type.
Definition: variable.c:1113
#define expression_undefined_p(x)
Definition: ri.h:1224

References CALLOC_FUNCTION_NAME, CAR, CDR, CELL_INTERPRETATION, CONS, copy_expression(), EFFECT, effect_add_dereferencing_dimension(), effect_to_may_effect(), entity_all_heap_locations_p(), entity_all_module_heap_locations_p(), entity_intrinsic(), entity_local_name(), entity_scalar_p(), EXPRESSION, expression_to_post_pv(), expression_undefined, expression_undefined_p, free_expression(), FREE_FUNCTION_NAME, free_pv_results_paths(), free_to_post_pv(), gen_full_free_list(), get_current_module_entity(), int_to_expression(), pv_results::l_out, make_action_write_memory(), make_approximation_exact(), make_cell_interpretation_address_of(), make_cell_reference(), make_descriptor_none(), make_effect(), make_op_exp(), make_pv_results(), make_reference(), make_sensitivity_information(), MakeBinaryCall(), MakeUnaryCall(), MALLOC_FUNCTION_NAME, malloc_to_abstract_location(), NIL, PLUS_OPERATOR_NAME, pv_context_statement_head(), REALLOC_FUNCTION_NAME, pv_results::result_paths, pv_results::result_paths_interpretations, same_string_p, STRDUP_FUNCTION_NAME, and STRLEN_FUNCTION_NAME.

+ Here is the call graph for this function:

◆ intrinsic_to_identical_post_pv() [1/2]

static void intrinsic_to_identical_post_pv ( entity __attribute__((unused))  func,
list __attribute__((unused))  func_args,
list  l_in,
pv_results pv_res,
pv_context __attribute__((unused)) *  ctxt 
)
static

Definition at line 1938 of file pointer_values_intrinsics.c.

1941 {
1942  pv_res->l_out = l_in;
1943 }

References pv_results::l_out.

◆ intrinsic_to_identical_post_pv() [2/2]

static void intrinsic_to_identical_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

◆ intrinsic_to_post_pv()

void intrinsic_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)

pointer_values_intrinsics.c

Parameters
funcunc
func_argsunc_args
l_in_in
pv_resv_res
ctxttxt

Definition at line 1969 of file pointer_values_intrinsics.c.

1971 {
1972  const char* func_name = entity_local_name(func);
1973  pips_debug(1, "begin for %s\n", func_name);
1974 
1976 
1977  while (pid->name != NULL)
1978  {
1979  if (strcmp(pid->name, func_name) == 0)
1980  {
1981  (*(pid->to_post_pv_function))(func, func_args, l_in, pv_res, ctxt);
1982  pips_debug_pv_results(2, "resulting pv_res:", *pv_res);
1983  pips_debug(1, "end\n");
1984  return;
1985  }
1986  pid += 1;
1987  }
1988 
1989  pips_internal_error("unknown intrinsic %s", func_name);
1990  pips_debug(1, "end\n");
1991  return;
1992 }
#define pips_internal_error
Definition: misc-local.h:149
static IntrinsicToPostPVDescriptor IntrinsicToPostPVDescriptorTable[]
The following data structure describes an intrinsic function: its name and its arity and its type,...

References entity_local_name(), IntrinsicToPostPVDescriptorTable, IntrinsicDescriptor::name, pips_debug, pips_debug_pv_results, pips_internal_error, and IntrinsicDescriptor::to_post_pv_function.

Referenced by call_to_post_pv().

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

◆ logical_operator_to_post_pv() [1/2]

static void logical_operator_to_post_pv ( entity __attribute__((unused))  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

If it is a pure logical operator (&& or ||), there is a sequence point just after the evaluation of the first operand so we must evaluate the second operand in the memory store resulting from the evaluation of the first operand. If it's a relational operator, the evaluation order is not important, so let's do the same !

first operand

second operand

the resulting path of a relational expression is not a pointer value

Definition at line 1353 of file pointer_values_intrinsics.c.

1356 {
1357  expression e1 = EXPRESSION(CAR(func_args));
1358  expression e2 = EXPRESSION(CAR(CDR(func_args)));
1359  pv_results pv_res1 = make_pv_results();
1360 
1361  /* If it is a pure logical operator (&& or ||), there is a
1362  sequence point just after the evaluation of the first operand
1363  so we must evaluate the second operand in the memory store
1364  resulting from the evaluation of the first operand.
1365  If it's a relational operator, the evaluation order is not important,
1366  so let's do the same !
1367  */
1368  /* first operand */
1369  expression_to_post_pv(e1, l_in, &pv_res1, ctxt);
1370  list l_in_cur = pv_res1.l_out;
1371  if (l_in != l_in_cur) gen_full_free_list(l_in);
1372  free_pv_results_paths(&pv_res1);
1373 
1374  /* second operand */
1375  expression_to_post_pv(e2, l_in_cur, pv_res, ctxt);
1376  free_pv_results_paths(pv_res);
1377  /* the resulting path of a relational expression is not a pointer value */
1378  pv_res->result_paths = NIL;
1380 }

References CAR, CDR, EXPRESSION, expression_to_post_pv(), free_pv_results_paths(), gen_full_free_list(), pv_results::l_out, make_pv_results(), NIL, pv_results::result_paths, and pv_results::result_paths_interpretations.

+ Here is the call graph for this function:

◆ logical_operator_to_post_pv() [2/2]

static void logical_operator_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

◆ point_to_to_post_pv() [1/2]

static void point_to_to_post_pv ( entity __attribute__((unused))  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

We add a dereferencing

we add the field dimension

Definition at line 1463 of file pointer_values_intrinsics.c.

1465 {
1466  expression e2 = EXPRESSION(CAR(CDR(func_args)));
1467  syntax s2 = expression_syntax(e2);
1468  entity f;
1469 
1470  pips_assert("e2 is a reference", syntax_reference_p(s2));
1472 
1473  pips_debug(4, "It's a point to operator\n");
1474  expression_to_post_pv(EXPRESSION(CAR(func_args)), l_in, pv_res, ctxt);
1475 
1476  FOREACH(EFFECT, eff, pv_res->result_paths)
1477  {
1478  /* We add a dereferencing */
1480  /* we add the field dimension */
1482  }
1483 }

References CAR, CDR, EFFECT, effect_add_dereferencing_dimension(), effect_add_field_dimension(), EXPRESSION, expression_syntax, expression_to_post_pv(), f(), FOREACH, pips_assert, pips_debug, reference_variable, pv_results::result_paths, syntax_reference, and syntax_reference_p.

+ Here is the call graph for this function:

◆ point_to_to_post_pv() [2/2]

static void point_to_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

◆ safe_intrinsic_to_post_pv() [1/2]

static void safe_intrinsic_to_post_pv ( entity __attribute__((unused))  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

first assume that all pointers reachable from arguments are written and set to anywhere

this should be quickly refined

well this is not safe in case of arguments with external function calls I should use the result paths of pv_res_arg, but there is a lot of work done in c_actual_argument_to_may_ summary_effect about arrays, and I'm not sure expression_to_post_pv does the same job

assume all pointers now point to anywhere

then retrieve the return value type to set pv_res->result_paths

if it is a pointer type, set it to anywhere for the moment specific work should be done for each intrinsic

Definition at line 1864 of file pointer_values_intrinsics.c.

1867 {
1868  /* first assume that all pointers reachable from arguments are written and set to
1869  anywhere */
1870  /* this should be quickly refined */
1872  NIL);
1873  list l_rhs_kind = CONS(CELL_INTERPRETATION,
1875 
1876  pips_debug(1, "begin\n");
1877 
1878  if (!ENDP(func_args))
1879  {
1880  list lw = NIL;
1881  list l_in_cur = l_in;
1882  FOREACH(EXPRESSION, arg, func_args)
1883  {
1884  pv_results pv_res_arg = make_pv_results();
1885  expression_to_post_pv(arg, l_in_cur, &pv_res_arg, ctxt);
1886  free_pv_results_paths(&pv_res_arg);
1887  if (pv_res_arg.l_out != l_in_cur)
1888  {
1889  //gen_full_free_list(l_in_cur);
1890  l_in_cur = pv_res_arg.l_out;
1891  }
1892  /* well this is not safe in case of arguments with external function calls
1893  I should use the result paths of pv_res_arg, but there is a lot of work
1894  done in c_actual_argument_to_may_ summary_effect about arrays, and I'm not
1895  sure expression_to_post_pv does the same job
1896  */
1898  }
1899 
1900  pips_debug_effects(3, "effects to be killed: \n", lw);
1901 
1902  /* assume all pointers now point to anywhere */
1903 
1904  FOREACH(EFFECT, eff, lw)
1905  {
1906  bool to_be_freed = false;
1907  type t = cell_to_type(effect_cell(eff), &to_be_freed);
1908  if (pointer_type_p(t))
1909  {
1911  l_anywhere_eff, l_rhs_kind,
1912  false, l_in_cur,
1913  pv_res, ctxt);
1914  if (pv_res->l_out != l_in_cur)
1915  {
1916  gen_full_free_list(l_in_cur);
1917  l_in_cur = pv_res->l_out;
1918  }
1919  free_pv_results_paths(pv_res);
1920  }
1921  if (to_be_freed) free_type(t);
1922  }
1923  pv_res->l_out = l_in_cur;
1924  }
1925  else
1926  pv_res->l_out = l_in;
1927  /* then retrieve the return value type to set pv_res->result_paths */
1928  /* if it is a pointer type, set it to anywhere for the moment
1929  specific work should be done for each intrinsic
1930  */
1931  pv_res->result_paths = l_anywhere_eff;
1932  pv_res->result_paths_interpretations = l_rhs_kind;
1933 
1934  pips_debug_pv_results(1, "ending with pv_res:", *pv_res);
1935 
1936 }
effect make_anywhere_effect(action)
list c_actual_argument_to_may_summary_effects(expression, tag)
type cell_to_type(cell, bool *)
Definition: type.c:513
#define effect_cell(x)
Definition: effects.h:640

References c_actual_argument_to_may_summary_effects(), CELL_INTERPRETATION, cell_to_type(), CONS, EFFECT, effect_cell, ENDP, EXPRESSION, expression_to_post_pv(), FOREACH, free_pv_results_paths(), free_type(), gen_full_free_list(), gen_nconc(), pv_results::l_out, make_action_write_memory(), make_anywhere_effect(), make_cell_interpretation_address_of(), make_pv_results(), NIL, pips_debug, pips_debug_effects, pips_debug_pv_results, pointer_type_p(), pv_results::result_paths, pv_results::result_paths_interpretations, and single_pointer_assignment_to_post_pv().

+ Here is the call graph for this function:

◆ safe_intrinsic_to_post_pv() [2/2]

static void safe_intrinsic_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

◆ string_function_to_post_pv()

static void string_function_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

Definition at line 1555 of file pointer_values_intrinsics.c.

1557 {
1558  safe_intrinsic_to_post_pv(func, func_args, l_in, pv_res, ctxt);
1559 }

References safe_intrinsic_to_post_pv().

+ Here is the call graph for this function:

◆ unary_arithmetic_operator_to_post_pv() [1/2]

static void unary_arithmetic_operator_to_post_pv ( entity __attribute__((unused))  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

Definition at line 1279 of file pointer_values_intrinsics.c.

1283 {
1284  expression arg = EXPRESSION(CAR(func_args));
1285  expression_to_post_pv(arg, l_in, pv_res, ctxt);
1286  ifdebug(1)
1287  {
1288  type t = expression_to_type(arg);
1289  pips_assert("unary arithmetic operators should not have pointer arguments",
1290  !pointer_type_p(t));
1291  free_type(t);
1292  }
1293 }
#define ifdebug(n)
Definition: sg.c:47

References CAR, EXPRESSION, expression_to_post_pv(), expression_to_type(), free_type(), ifdebug, pips_assert, and pointer_type_p().

+ Here is the call graph for this function:

◆ unary_arithmetic_operator_to_post_pv() [2/2]

static void unary_arithmetic_operator_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

◆ unix_io_function_to_post_pv()

static void unix_io_function_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

Definition at line 1549 of file pointer_values_intrinsics.c.

1551 {
1552  safe_intrinsic_to_post_pv(func, func_args, l_in, pv_res, ctxt);
1553 }

References safe_intrinsic_to_post_pv().

+ Here is the call graph for this function:

◆ unknown_intrinsic_to_post_pv() [1/2]

static void unknown_intrinsic_to_post_pv ( entity __attribute__((unused))  func,
list __attribute__((unused))  func_args,
list __attribute__((unused))  l_in,
pv_results __attribute__((unused)) *  pv_res,
pv_context __attribute__((unused)) *  ctxt 
)
static

Definition at line 1945 of file pointer_values_intrinsics.c.

1950 {
1951  pips_internal_error("not a C intrinsic");
1952 }

References pips_internal_error.

◆ unknown_intrinsic_to_post_pv() [2/2]

static void unknown_intrinsic_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

◆ update_operator_to_post_pv()

static void update_operator_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

build rhs

_lhs_kind = CONS(CELL_INTERPRETATION, make_cell_interpretation_address_of(), NIL);

Definition at line 1295 of file pointer_values_intrinsics.c.

1297 {
1298  pips_debug(1, "begin for update operator\n");
1299 
1300  expression arg = EXPRESSION(CAR(func_args));
1301  expression_to_post_pv(arg, l_in, pv_res, ctxt);
1302  list l_in_cur = pv_res->l_out;
1303  if (l_in != l_in_cur) gen_full_free_list(l_in);
1304 
1305  type t = expression_to_type(arg);
1306  if (pointer_type_p(t))
1307  {
1308  list l_lhs_eff = pv_res->result_paths;
1309  //list l_lhs_kind = pv_res->result_paths_interpretations;
1310  const char* func_name = entity_local_name(func);
1311 
1312  pips_assert("update operators admit a single path\n",
1313  gen_length(l_lhs_eff) == (size_t) 1);
1314 
1315  effect lhs_eff = EFFECT(CAR(l_lhs_eff));
1316  effect rhs_eff = copy_effect(lhs_eff);
1318  NIL);
1319 
1320  if (!anywhere_effect_p(lhs_eff))
1321  {
1322  /* build rhs */
1323  expression new_dim = expression_undefined;
1324 
1327  {
1328  new_dim = int_to_expression(1);
1329  }
1330  else if (same_string_p(func_name, POST_DECREMENT_OPERATOR_NAME)
1332  {
1333  new_dim = int_to_expression(-1);
1334  }
1335  else
1336  //pips_internal_error("unexpected update operator on pointers");
1337  new_dim = make_unbounded_expression();
1338 
1339  // functions that can be pointed by effect_add_expression_dimension_func:
1340  // simple_effect_add_expression_dimension
1341  // convex_region_add_expression_dimension
1342  (*effect_add_expression_dimension_func)(rhs_eff, new_dim);
1343  /*l_lhs_kind = CONS(CELL_INTERPRETATION, make_cell_interpretation_address_of(),
1344  NIL);*/
1345  }
1346  list l_rhs_eff = CONS(EFFECT, rhs_eff, NIL);
1347  single_pointer_assignment_to_post_pv(lhs_eff, l_rhs_eff, l_rhs_kind, false,
1348  l_in_cur, pv_res, ctxt);
1349  }
1350  pips_debug_pv_results(1, "end with pv_res:\n", *pv_res);
1351 }
#define POST_DECREMENT_OPERATOR_NAME
Definition: ri-util-local.h:98
#define PRE_DECREMENT_OPERATOR_NAME
#define PRE_INCREMENT_OPERATOR_NAME
Definition: ri-util-local.h:99
#define POST_INCREMENT_OPERATOR_NAME
Definition: ri-util-local.h:97

References anywhere_effect_p(), CAR, CELL_INTERPRETATION, CONS, copy_effect(), EFFECT, entity_local_name(), EXPRESSION, expression_to_post_pv(), expression_to_type(), expression_undefined, gen_full_free_list(), gen_length(), int_to_expression(), pv_results::l_out, make_cell_interpretation_address_of(), make_unbounded_expression(), NIL, pips_assert, pips_debug, pips_debug_pv_results, pointer_type_p(), POST_DECREMENT_OPERATOR_NAME, POST_INCREMENT_OPERATOR_NAME, PRE_DECREMENT_OPERATOR_NAME, PRE_INCREMENT_OPERATOR_NAME, pv_results::result_paths, same_string_p, and single_pointer_assignment_to_post_pv().

+ Here is the call graph for this function:

◆ va_list_function_to_post_pv()

static void va_list_function_to_post_pv ( entity  func,
list  func_args,
list  l_in,
pv_results pv_res,
pv_context ctxt 
)
static

Definition at line 1561 of file pointer_values_intrinsics.c.

1563 {
1564  safe_intrinsic_to_post_pv(func, func_args, l_in, pv_res, ctxt);
1565 }

References safe_intrinsic_to_post_pv().

+ Here is the call graph for this function:

Variable Documentation

◆ IntrinsicToPostPVDescriptorTable

IntrinsicToPostPVDescriptor IntrinsicToPostPVDescriptorTable[]
static

Definition at line 92 of file pointer_values_intrinsics.c.

Referenced by intrinsic_to_post_pv().