PIPS
semantics.h File Reference

Go to the source code of this file.

Data Structures

struct  path
 

Macros

#define SEMANTICS_OPTIONS   "?Otcfieod-D:"
 Warning! Do not modify this file that is automatically generated! More...
 
#define SEQUENTIAL_TRANSFORMER_SUFFIX   ".tran"
 
#define USER_TRANSFORMER_SUFFIX   ".utran"
 
#define SEQUENTIAL_PRECONDITION_SUFFIX   ".prec"
 
#define USER_PRECONDITION_SUFFIX   ".uprec"
 
#define SEQUENTIAL_TOTAL_PRECONDITION_SUFFIX   ".tprec"
 
#define USER_TOTAL_PRECONDITION_SUFFIX   ".utprec"
 
#define semantics_user_warning   semantics_user_warning_func2
 

Functions

int call_site_count (entity)
 cproto-generated files More...
 
int caller_count (entity)
 
int dynamic_call_count (entity)
 
void semantics_user_warning_func (const char *, const char *,...)
 
void semantics_user_warning_func2 (const char *,...)
 
transformer apply_array_effect_to_transformer (transformer, effect, bool)
 ri_to_transformers.c More...
 
transformer effects_to_transformer (list)
 list of effects More...
 
transformer filter_transformer (transformer, list)
 Previous version of effects_to_transformer() transformer effects_to_transformer(list e) { list args = NIL; Pbase b = VECTEUR_NUL; Psysteme s = sc_new();. More...
 
transformer dimensions_to_transformer (entity, transformer)
 Assumes that entity_has_values_p(v) holds. More...
 
transformer declaration_to_transformer (entity, transformer)
 Note: initializations of static variables are not used as transformers but to initialize the program precondition. More...
 
transformer declarations_to_transformer (list, transformer)
 For C declarations. More...
 
list effects_to_arguments (list)
 list of effects More...
 
transformer intrinsic_to_transformer (entity, list, transformer, list)
 effects of intrinsic call More...
 
transformer call_to_transformer (call, transformer, list)
 Use to be static, but may be called from expressions in C. More...
 
transformer user_function_call_to_transformer (entity, expression, transformer)
 a function call is a call to a non void function in C and to a FUNCTION in Fortran More...
 
transformer generic_transformer_intra_to_inter (transformer, list, bool)
 transformer translation from the module intraprocedural transformer to the module interprocedural transformer. More...
 
transformer transformer_intra_to_inter (transformer, list)
 
unsigned int number_of_usable_functional_parameters (list)
 Number of formal parameters in pl before a vararg is reached. More...
 
transformer transformer_formal_parameter_projection (entity, transformer)
 
transformer array_elements_substitution_in_transformer (transformer, entity, type, expression, transformer, list, bool)
 
transformer new_array_element_backward_substitution_in_transformer (transformer, entity, reference, reference)
 Substitute formal location entity l by a location entity corresponding to ar, if it is possible. More...
 
transformer new_array_elements_backward_substitution_in_transformer (transformer, entity, type, expression, transformer, list)
 
transformer new_array_elements_forward_substitution_in_transformer (transformer, entity, type, expression, transformer, list)
 
transformer new_array_elements_substitution_in_transformer (transformer, entity, type, expression, transformer, list, bool)
 
transformer generic_substitute_formal_array_elements_in_transformer (transformer, entity, list, transformer, list, bool)
 
transformer substitute_formal_array_elements_in_transformer (transformer, entity, list, transformer, list)
 
transformer substitute_formal_array_elements_in_precondition (transformer, entity, list, transformer, list)
 
transformer any_user_call_site_to_transformer (entity, list, transformer, list)
 
transformer c_user_call_to_transformer (entity, list, transformer, list)
 
transformer fortran_user_call_to_transformer (entity, list, list)
 Effects are necessary to clean up the transformer t_caller. More...
 
transformer user_call_to_transformer (entity, list, transformer, list)
 
transformer c_return_to_transformer (entity, list, list, transformer)
 
transformer assigned_expression_to_transformer (entity, expression, transformer)
 transformer assigned_expression_to_transformer(entity e, expression expr, list ef): returns a transformer abstracting the effect of assignment "e = expr" when possible, transformer_undefined otherwise. More...
 
transformer safe_assigned_expression_to_transformer (entity, expression, transformer)
 Always returns a fully defined transformer. More...
 
transformer integer_assign_to_transformer (expression, expression, transformer, list)
 This function never returns an undefined transformer. More...
 
transformer any_scalar_assign_to_transformer_without_effect (entity, expression, transformer)
 assign to the scalar variable v the expression rhs (a scalar variable has a basic type; it cannot be an array, a struct or a union; it can be an enum) WARNING : this function can return transformer_undefined More...
 
transformer any_scalar_assign_to_transformer (entity, expression, list, transformer)
 precondition More...
 
transformer transformer_apply_field_assignments_or_equalities (transformer, reference, reference, type, bool)
 For all analyzable fields f, apply the assignment "le.f = re.f;" to transformer t. More...
 
transformer transformer_apply_field_assignments (transformer, reference, reference, type)
 
transformer transformer_apply_field_equalities (transformer, reference, reference, type)
 
transformer transformer_apply_unknown_field_assignments (transformer, reference, type)
 
transformer transformer_apply_unknown_field_equalities (transformer, reference, type)
 
transformer struct_reference_assignment_to_transformer (reference, type, expression, transformer, list)
 
transformer struct_reference_equality_to_transformer (reference, type, expression, transformer, list)
 
transformer struct_variable_assignment_to_transformer (entity, type, expression, transformer, list)
 
transformer struct_variable_equality_to_transformer (entity, type, expression, transformer, list)
 
transformer any_assign_to_transformer (list, list, transformer)
 precondition More...
 
transformer any_update_to_transformer (entity, list, list, transformer)
 precondition More...
 
transformer any_basic_update_to_transformer (entity, list, list, transformer)
 precondition More...
 
transformer complete_statement_transformer (transformer, transformer, statement)
 Returns the effective transformer ct for a given statement s. More...
 
transformer complete_non_identity_statement_transformer (transformer, transformer, statement)
 FI: only implemented for while loops. More...
 
transformer generic_complete_statement_transformer (transformer, transformer, statement, bool)
 Loops, do, for, while or repeat, have transformers linked to their body preconditions so as to compute those. More...
 
transformer statement_to_transformer (statement, transformer)
 stmt precondition More...
 
transformer get_module_precondition (entity)
 interprocedural.c More...
 
void add_module_call_site_precondition (entity, transformer)
 
list module_to_formal_analyzable_parameters (entity)
 returns a module's parameter's list More...
 
bool same_analyzable_type_scalar_entity_list_p (list)
 
transformer add_formal_to_actual_bindings (call, transformer, entity)
 add_formal_to_actual_bindings(call c, transformer pre, entity caller): More...
 
transformer new_add_formal_to_actual_bindings (call, transformer, entity)
 Take side effects into account: More...
 
transformer precondition_intra_to_inter (entity, transformer, list)
 
void translate_global_values (entity, transformer)
 
void translate_global_value (entity, transformer, entity)
 Try to convert an value on a non-local variable into an value on a local variable using a guessed name (instead of a location identity: M and N declared as COMMON/FOO/M and COMMON/FOO/N are not identified as a unique variable/location). More...
 
void expressions_to_summary_precondition (transformer, list)
 
void expression_to_summary_precondition (transformer, expression)
 
void call_to_summary_precondition (transformer, call)
 
text call_site_to_module_precondition_text (entity, entity, statement, call)
 This function does everything needed. More...
 
void reset_call_site_number (void)
 
int get_call_site_number (void)
 
void update_summary_precondition_in_declaration (expression, transformer)
 This function is called to deal with call sites located in initialization expressions carried by declarations. More...
 
transformer update_precondition_with_call_site_preconditions (transformer, entity, entity)
 Update precondition t for callee with preconditions of call sites to callee in caller. More...
 
transformer value_passing_summary_transformer (entity, transformer)
 With value passing, writes on formal parameters are not effective interprocedurally unless an array is passed as parameter. More...
 
list get_module_global_arguments (void)
 ri_to_preconditions.c More...
 
void set_module_global_arguments (list)
 
list effects_to_entity_list (list)
 returns an allocated list of entities that appear in lef. More...
 
transformer data_to_precondition (entity)
 restricted to variables with effects. More...
 
transformer all_data_to_precondition (entity)
 any variable is included. More...
 
void precondition_add_reference_information (transformer, statement)
 
void transformer_add_reference_information (transformer, statement)
 
void precondition_add_type_information (transformer)
 
transformer statement_to_postcondition (transformer, statement)
 end of the non recursive section More...
 
transformer propagate_preconditions_in_declarations (list, transformer, void(*)(expression, transformer))
 This function is mostly copied from declarations_to_transformer(). More...
 
transformer tf_equivalence_equalities_add (transformer)
 mappings.c More...
 
void add_equivalenced_values (entity, entity, bool)
 
void add_intraprocedural_value_entities (entity)
 Use to be static, but may be called from ri_to_transformer. More...
 
void add_or_kill_equivalenced_variables (entity, bool)
 Look for variables equivalenced with e. More...
 
void add_implicit_interprocedural_write_effects (entity, list)
 It is assumed that al is an abstract location that is written and which may conflict with effects in effect list el. More...
 
void module_to_value_mappings (entity)
 void module_to_value_mappings(entity m): build hash tables between variables and values (old, new and intermediate), and between values and names for module m, as well as equivalence equalities More...
 
bool value_mappings_compatible_vector_p (Pvecteur)
 transform a vector based on variable entities into a vector based on new value entities when possible; does nothing most of the time; does a little in the presence of equivalenced variables More...
 
list variables_to_values (list)
 
list variable_to_values (entity)
 
list dynamic_variables_to_values (list)
 Build the list of values to be projected when the declaration list list_mod is no longer valid because a block is closed/left. More...
 
list variables_to_old_values (list)
 
void variables_to_new_values (Pvecteur)
 replace variables by new values which is necessary for equivalenced variables More...
 
void upwards_vect_rename (Pvecteur, transformer)
 Renaming of variables in v according to transformations occuring later. More...
 
bool transformer_map_undefined_p (void)
 dbm_interface.c More...
 
void set_transformer_map (statement_mapping)
 
statement_mapping get_transformer_map (void)
 
void reset_transformer_map (void)
 
void free_transformer_map (void)
 
void make_transformer_map (void)
 
transformer load_statement_transformer (statement)
 
void delete_statement_transformer (statement)
 
bool statement_transformer_undefined_p (statement)
 
void store_statement_transformer (statement, transformer)
 
void update_statement_transformer (statement, transformer)
 
bool precondition_map_undefined_p (void)
 
void set_precondition_map (statement_mapping)
 
statement_mapping get_precondition_map (void)
 
void reset_precondition_map (void)
 
void free_precondition_map (void)
 
void make_precondition_map (void)
 
transformer load_statement_precondition (statement)
 
void delete_statement_precondition (statement)
 
bool statement_precondition_undefined_p (statement)
 
void store_statement_precondition (statement, transformer)
 
void update_statement_precondition (statement, transformer)
 
bool total_precondition_map_undefined_p (void)
 
void set_total_precondition_map (statement_mapping)
 
statement_mapping get_total_precondition_map (void)
 
void reset_total_precondition_map (void)
 
void free_total_precondition_map (void)
 
void make_total_precondition_map (void)
 
transformer load_statement_total_precondition (statement)
 
void delete_statement_total_precondition (statement)
 
bool statement_total_precondition_undefined_p (statement)
 
void store_statement_total_precondition (statement, transformer)
 
void update_statement_total_precondition (statement, transformer)
 
transformer load_completed_statement_transformer (statement)
 three mappings used throughout semantics analysis: More...
 
void add_declaration_list_information (transformer, list, bool)
 
bool transformers_intra_fast (char *)
 Functions to make transformers. More...
 
bool transformers_intra_full (char *)
 
bool transformers_inter_fast (char *)
 
bool transformers_inter_full (char *)
 
bool transformers_inter_full_with_points_to (char *)
 
bool refine_transformers (char *)
 
bool refine_transformers_with_points_to (char *)
 
bool summary_transformer (char *)
 
bool preconditions_intra (char *)
 
bool preconditions_intra_fast (char *)
 
bool preconditions_inter_fast (char *)
 
bool preconditions_inter_full (char *)
 
bool preconditions_inter_full_with_points_to (char *)
 
bool total_preconditions_intra (char *)
 
bool total_preconditions_inter (char *)
 
bool old_summary_precondition (char *)
 
bool intraprocedural_summary_precondition (char *)
 
bool interprocedural_summary_precondition (char *)
 
bool use_points_to_p (void)
 
bool interprocedural_summary_precondition_with_points_to (char *)
 
bool summary_precondition (char *)
 
bool summary_total_postcondition (char *)
 
bool summary_total_precondition (char *)
 
void set_warning_counters (void)
 
bool test_warning_counters (void)
 
bool generic_module_name_to_transformers (const char *, bool)
 bool generic_module_name_to_transformers(char * module_name, bool in_context): compute a transformer for each statement of a module with a given name; compute also the global transformer for the module More...
 
bool module_name_to_transformers_in_context (const char *)
 
bool module_name_to_transformers (const char *)
 
bool module_name_to_preconditions (const char *)
 resource module_name_to_preconditions(char * module_name): compute a transformer for each statement of a module with a given name; compute also the global transformer for the module More...
 
bool module_name_to_total_preconditions (const char *)
 
transformer load_summary_transformer (entity)
 
void update_summary_precondition (entity, transformer)
 void update_summary_precondition(e, t): t is supposed to be a precondition related to one of e's call sites and translated into e's basis; More...
 
transformer load_summary_precondition (entity)
 summary_preconditions are expressed in any possible frame, in fact the frame of the last procedure that used/produced it More...
 
transformer load_summary_total_postcondition (entity)
 summary_preconditions are expressed in any possible frame, in fact the frame of the last procedure that used/produced it More...
 
list load_summary_effects (entity)
 FI->FI, FI->BC: these two functions should be moved into effects-util or effects-simple. More...
 
list load_body_effects (entity)
 
list load_module_intraprocedural_effects (entity)
 
void cumulated_effects_map_print (void)
 ca n'a rien a` faire ici, et en plus, il serait plus inte'ressant d'avoir une fonction void statement_map_print(statement_mapping htp) More...
 
bool semantic_map_undefined_p (void)
 prettyprint.c More...
 
void set_semantic_map (statement_mapping)
 
statement_mapping get_semantic_map (void)
 
void reset_semantic_map (void)
 
void free_semantic_map (void)
 
void make_semantic_map (void)
 
transformer load_statement_semantic (statement)
 
void delete_statement_semantic (statement)
 
bool statement_semantic_undefined_p (statement)
 
void store_statement_semantic (statement, transformer)
 
void update_statement_semantic (statement, transformer)
 
void set_prettyprint_transformer (void)
 
bool print_code_transformers (const char *)
 
bool print_code_as_a_graph_transformers (const string)
 
bool print_code_preconditions (const char *)
 
bool print_code_as_a_graph_preconditions (const string)
 
bool print_code_total_preconditions (const char *)
 
bool print_code_as_a_graph_total_preconditions (const string)
 
bool print_source_transformers (const char *)
 
bool print_source_preconditions (const char *)
 
bool print_source_total_preconditions (const char *)
 
text get_text_transformers (const string)
 
text get_text_preconditions (const string)
 
text get_text_total_preconditions (const string)
 
text semantic_to_text (entity, int, statement)
 this function name is VERY misleading - it should be changed, sometime FI More...
 
text text_transformer (transformer)
 text text_transformer(transformer tran) input : a transformer representing a transformer or a precondition output : a text containing commentaries representing the transformer modifies : nothing. More...
 
text text_for_a_transformer (transformer, bool)
 call this one from outside. More...
 
text string_predicate_to_commentary (string, string)
 text string_predicate_to_commentary(string str_pred, string comment_prefix) input : a string, part of which represents a predicate. More...
 
text words_predicate_to_commentary (list, string)
 text words_predicate_to_commentary(list w_pred, string comment_prefix) input : a list of strings, one of them representing a predicate. More...
 
sentence make_pred_commentary_sentence (string, string)
 sentence make_pred_commentary_sentence(string str_pred, string comment_prefix) input : a substring formatted to be a commentary output : a sentence, containing the commentary form of this string, beginning with the comment_prefix. More...
 
bool print_call_graph_with_transformers (const string)
 
bool print_call_graph_with_preconditions (const string)
 
bool print_call_graph_with_total_preconditions (const string)
 
bool print_icfg_with_preconditions (const string)
 
bool print_icfg_with_transformers (const string)
 
bool print_icfg_with_loops_preconditions (const string)
 
bool print_icfg_with_loops_transformers (const string)
 
bool print_icfg_with_control_preconditions (const string)
 
bool print_icfg_with_control_transformers (const string)
 
bool print_icfg_with_total_preconditions (const string)
 
bool print_icfg_with_loops_total_preconditions (const string)
 
bool print_icfg_with_control_total_preconditions (const string)
 
bool postcondition_map_undefined_p (void)
 postcondition.c More...
 
void set_postcondition_map (statement_mapping)
 
statement_mapping get_postcondition_map (void)
 
void reset_postcondition_map (void)
 
void free_postcondition_map (void)
 
void make_postcondition_map (void)
 
transformer load_statement_postcondition (statement)
 
void delete_statement_postcondition (statement)
 
bool statement_postcondition_undefined_p (statement)
 
void store_statement_postcondition (statement, transformer)
 
void update_statement_postcondition (statement, transformer)
 
statement_mapping compute_postcondition (statement, statement_mapping, statement_mapping)
 statement_mapping compute_postcondition(stat, post_map, pre_map) statement stat; statement_mapping post_map, pre_map; More...
 
bool statement_weakly_feasible_p (statement)
 utils.c More...
 
bool statement_feasible_p (statement)
 Return true if statement s is reachable according to its precondition. More...
 
bool statement_strongly_feasible_p (statement)
 Return true if statement s is reachable according to its precondition. More...
 
bool empty_range_wrt_precondition_p (range, transformer)
 A range cannot be tested exactly wrt a precondition You can try to prove that it is empty or you can try to prove that it is not empty. More...
 
bool non_empty_range_wrt_precondition_p (range, transformer)
 
bool check_range_wrt_precondition (range, transformer, bool)
 FI: this function is outdated because it does not compute the transformers for the range expressions, because it does not take side effects into account and ... More...
 
bool condition_true_wrt_precondition_p (expression, transformer)
 A condition cannot be tested exactly wrt a precondition You can try to prove that it is always true (because it is never false) or you can try to prove that it is always false (because it is never true). More...
 
bool condition_false_wrt_precondition_p (expression, transformer)
 
bool check_condition_wrt_precondition (expression, transformer, bool)
 
void expression_and_precondition_to_integer_interval (expression, transformer, int *, int *)
 Evaluate expression e in context p, assuming that e is an integer expression. More...
 
void integer_expression_and_precondition_to_integer_interval (expression, transformer, int *, int *)
 Could be used for bool expressions too? Extended to any kind of expression? More...
 
void integer_value_and_precondition_to_integer_interval (entity, transformer, int *, int *)
 Should be used by previous function, integer_expression_and_precondition_to_integer_interval() More...
 
bool initial_precondition (string)
 initial.c More...
 
bool program_precondition (const string)
 Compute the union of all initial preconditions. More...
 
bool program_postcondition (const string)
 The program correctness postcondition cannot be infered. More...
 
bool print_initial_precondition (const string)
 
bool print_program_precondition (const string)
 
void print_control_postcondition_map (control_mapping)
 unstructured.c More...
 
transformer load_cycle_fix_point (control, hash_table)
 
void update_temporary_precondition (void *, transformer, hash_table)
 
void update_statement_temporary_precondition (statement, transformer, statement_mapping)
 
void print_statement_temporary_precondition (statement_mapping)
 
void update_cycle_temporary_precondition (control, transformer, control_mapping)
 
transformer load_cycle_temporary_precondition (control, control_mapping, hash_table, hash_table)
 
transformer load_statement_temporary_precondition (statement, statement_mapping)
 
transformer dag_or_cycle_to_flow_sensitive_postconditions_or_transformers (list, unstructured, hash_table, hash_table, control_mapping, transformer, transformer, hash_table, bool, bool)
 Should ndu be a dag or a cycle? More...
 
transformer dag_to_flow_sensitive_postconditions_or_transformers (list, unstructured, hash_table, hash_table, control_mapping, transformer, transformer, hash_table, bool)
 Compute transformers or preconditions. More...
 
transformer cycle_to_flow_sensitive_postconditions_or_transformers (list, unstructured, hash_table, hash_table, control_mapping, transformer, transformer, hash_table, bool)
 Compute transformers or preconditions. More...
 
transformer unstructured_to_flow_sensitive_postconditions_or_transformers (transformer, transformer, unstructured, bool)
 compute either the postconditions in an unstructured or the transformer of this unstructured. More...
 
transformer unstructured_to_flow_sensitive_postconditions (transformer, transformer, unstructured)
 compute pre- and post-conditions in an unstructured from the entry precondition pre and return the exit postcondition. More...
 
transformer unstructured_to_postcondition (transformer, unstructured, transformer)
 
transformer unstructured_to_flow_insensitive_transformer (unstructured)
 This simple fix-point over-approximates the CFG by a fully connected graph. More...
 
transformer unstructured_to_transformer (unstructured, transformer, list)
 effects of u More...
 
transformer unstructured_to_flow_sensitive_total_preconditions (transformer, transformer, unstructured)
 
transformer generic_reference_to_transformer (entity, reference, transformer, bool)
 expression.c More...
 
transformer any_basic_update_operation_to_transformer (entity, entity, entity)
 See also any_basic_update_to_transformer(), which should be based on this function. More...
 
transformer any_assign_operation_to_transformer (entity, list, transformer, bool)
 
transformer safe_any_assign_operation_to_transformer (entity, list, transformer, bool)
 
transformer transformer_add_condition_information (transformer, expression, transformer, bool)
 
transformer precondition_add_condition_information (transformer, expression, transformer, bool)
 context might be derivable from pre as transformer_range(pre) but this is sometimes very computationally intensive, e.g. More...
 
transformer transformer_add_domain_condition (transformer, expression, transformer, bool)
 
transformer transformer_add_range_condition (transformer, expression, transformer, bool)
 
transformer simple_affine_to_transformer (entity, Pvecteur, bool)
 INTEGER EXPRESSIONS. More...
 
transformer affine_to_transformer (entity, Pvecteur, bool)
 
transformer affine_increment_to_transformer (entity, Pvecteur)
 
transformer modulo_by_a_constant_to_transformer (entity, transformer, entity, int)
 Analyze v2 % k, with v2 constrainted by tf, assuming tf is a precondition. More...
 
transformer assign_operation_to_transformer (entity, expression, expression, transformer)
 Returns an undefined transformer in case of failure. More...
 
transformer points_to_unary_operation_to_transformer (entity, entity, expression, transformer, bool, bool)
 This function is redundant with generic_unary_operation_to_transformer() except for its use of parameter is_pointer. More...
 
transformer expression_effects_to_transformer (expression)
 
transformer integer_expression_to_transformer (entity, expression, transformer, bool)
 Do check wrt to value mappings... More...
 
transformer safe_integer_expression_to_transformer (entity, expression, transformer, bool)
 Always return a defined transformer, using effects in case a more precise analysis fails. More...
 
transformer transformer_logical_inequalities_add (transformer, entity)
 PROCESSING OF LOGICAL EXPRESSIONS. More...
 
transformer logical_intrinsic_to_transformer (entity, call, transformer, bool)
 
transformer logical_expression_to_transformer (entity, expression, transformer, bool)
 Could be used to compute preconditions too. More...
 
transformer string_expression_to_transformer (entity, expression)
 
transformer float_expression_to_transformer (entity, expression, transformer, bool)
 
transformer pointer_expression_to_transformer (entity, expression, transformer, bool)
 
transformer transformer_add_any_relation_information (transformer, entity, expression, expression, transformer, bool, bool)
 compute transformer or precondition More...
 
transformer any_expression_side_effects_to_transformer (expression, transformer, bool)
 
transformer any_expressions_side_effects_to_transformer (list, transformer, bool)
 same as any_expression_side_effects_to_transformer() but for a list of expressions More...
 
transformer safe_any_expression_side_effects_to_transformer (expression, transformer, bool)
 Same as any_expression_side_effects_to_transformer() but effects are used to always generate a transformer. More...
 
transformer any_expression_to_transformer (entity, expression, transformer, bool)
 A set of functions to compute the transformer associated to an expression evaluated in a given context. More...
 
transformer safe_any_expression_to_transformer (entity, expression, transformer, bool)
 Always return a usable transformer. More...
 
transformer expression_to_transformer (expression, transformer, list)
 Just to capture side effects as the returned value is ignored. More...
 
transformer safe_expression_to_transformer (expression, transformer)
 
transformer condition_to_transformer (expression, transformer, bool)
 To capture side effects and to add C twist for numerical conditions. More...
 
transformer conditional_to_transformer (expression, expression, expression, transformer, list)
 FI: not too smart to start with the special case with no value returned, just side-effects... More...
 
transformer any_conditional_to_transformer (entity, list, transformer)
 Take care of the returned value. More...
 
transformer logical_not_to_transformer (entity, list, transformer)
 returns the transformer associated to a C logical not, !, applied to an integer argument, when meaningful, and transformer_undefined otherwise. More...
 
transformer bitwise_xor_to_transformer (entity, list, transformer)
 returns the transformer associated to a C bitwise xor, ^, applied to two integer argument, when meaningful, and transformer_undefined otherwise. More...
 
transformer expressions_to_transformer (list, transformer)
 Compute the transformer associated to a list of expressions such as "i=0, j = 1;". More...
 
transformer any_expressions_to_transformer (entity, list, transformer)
 Compute the transformer associated to a list of expressions such as "i=0, j = 1;". More...
 
bool precondition_minmax_of_value (entity, transformer, intptr_t *, intptr_t *)
 compute integer bounds pmax, pmin of value val under preconditions tr require value mappings set ! More...
 
bool precondition_minmax_of_expression (expression, transformer, intptr_t *, intptr_t *)
 compute integer bounds pmax, pmin of expression exp under preconditions tr require value mappings set ! More...
 
void simplify_minmax_expression (expression, transformer)
 tries hard to simplify expression e if it is a min or a max operator, by evaluating it under preconditions tr. More...
 
bool false_condition_wrt_precondition_p (expression, transformer)
 
bool true_condition_wrt_precondition_p (expression, transformer)
 
bool eval_condition_wrt_precondition_p (expression, transformer, bool)
 
transformer transformer_add_integer_relation_information (transformer, entity, expression, expression, bool, bool)
 It is supposed to be obsolete but is still called. More...
 
int simplify_boolean_expression_with_precondition (expression, transformer)
 Simplification of bool expressions with precondition. More...
 
bool semantics_usable_points_to_reference_p (reference, expression, int)
 See if references rlhs is usable and process null, undefined and anywhere locations defined by rlhs. More...
 
transformer lhs_expression_to_transformer (entity, expression, transformer)
 This function deals with e1.e2 and e1->e2, not with simple references such as x or a[i]. More...
 
transformer any_loop_to_k_transformer (transformer, transformer, transformer, statement, list, transformer, int)
 loop.c More...
 
transformer any_loop_to_transformer (transformer, transformer, transformer, statement, list, transformer)
 
transformer forloop_to_transformer (forloop, transformer, list)
 effects of forloop fl More...
 
list forloop_to_transformer_list (forloop, transformer, list)
 
transformer new_whileloop_to_transformer (whileloop, transformer, list)
 effects of whileloop wl More...
 
transformer new_whileloop_to_k_transformer (whileloop, transformer, list, int)
 
transformer repeatloop_to_transformer (whileloop, transformer, list)
 effects of whileloop wl More...
 
transformer add_loop_skip_condition (transformer, loop, transformer)
 tf and pre are a unique data structure when preconditions are computed More...
 
transformer add_index_range_conditions (transformer, entity, range, transformer)
 
transformer add_loop_index_exit_value (transformer, loop, transformer)
 The exit value is known if. More...
 
bool simple_dead_loop_p (expression, expression)
 
transformer precondition_filter_old_values (transformer)
 
transformer transformer_add_loop_index_initialization (transformer, loop, transformer)
 The loop initialization is performed before tf. More...
 
transformer transformer_add_loop_index_incrementation (transformer, loop, transformer)
 
transformer loop_bound_evaluation_to_transformer (loop, transformer)
 Side effects in loop bounds and increment are taken into account. More...
 
transformer loop_initialization_to_transformer (loop, transformer)
 Note: It used to be implemented by computing the effect list of the lower bound expression and and new allocated effect for the loop index definition. More...
 
transformer loop_to_transformer (loop, transformer, list)
 The transformer associated to a DO loop does not include the exit condition because it is used to compute the precondition for any loop iteration. More...
 
list loop_to_transformer_list (loop, transformer, list)
 
transformer loop_to_initialization_transformer (loop, transformer)
 Transformer expression the loop initialization. More...
 
transformer loop_to_enter_transformer (loop, transformer)
 Transformer expressiong the conditions between the index and the loop bounds according to the sign of the increment. More...
 
transformer loop_to_continue_transformer (loop, transformer)
 
transformer new_loop_to_transformer (loop, transformer, list)
 loop_to_transformer() was developed first but is not as powerful as the new algorithm used for all kinds of loops. More...
 
list complete_any_loop_transformer_list (transformer, transformer, transformer, transformer, transformer, transformer)
 FI: used to be complete_any_loop_transformer() with a direct reduction by convex hull. More...
 
transformer complete_any_loop_transformer (transformer, transformer, transformer, transformer, transformer, transformer, transformer, transformer)
 
transformer complete_forloop_transformer (transformer, transformer, forloop)
 
list complete_forloop_transformer_list (transformer, transformer, forloop)
 
list new_complete_whileloop_transformer_list (transformer, transformer, whileloop, bool)
 
transformer new_complete_whileloop_transformer (transformer, transformer, whileloop, bool)
 entered_p is used to for the execution of at least one iteration More...
 
list complete_repeatloop_transformer_list (transformer, transformer, whileloop)
 
transformer complete_repeatloop_transformer (transformer, transformer, whileloop)
 
transformer complete_loop_transformer (transformer, transformer, loop)
 The transformer computed and stored for a loop is useful to compute the loop body precondition, but it is not useful to analyze a higher level construct, which need the loop transformer with the exit condition. More...
 
list complete_loop_transformer_list (transformer, transformer, loop)
 
transformer complete_whileloop_transformer (transformer, transformer, whileloop)
 FI: I'm not sure this function is useful. More...
 
list complete_whileloop_transformer_list (transformer, transformer, whileloop)
 
transformer old_complete_whileloop_transformer (transformer, transformer, whileloop)
 
transformer standard_whileloop_to_transformer (whileloop, transformer, list)
 This function computes the effect of K loop iteration, with K positive. More...
 
transformer whileloop_to_transformer (whileloop, transformer, list)
 effects of whileloop l More...
 
transformer whileloop_to_k_transformer (whileloop, transformer, list, int)
 
transformer any_loop_to_postcondition (statement, transformer, transformer, transformer, transformer, transformer, transformer, transformer, transformer, transformer)
 
transformer forloop_to_postcondition (transformer, forloop, transformer)
 
transformer repeatloop_to_postcondition (transformer, whileloop, transformer)
 
transformer loop_to_postcondition (transformer, loop, transformer)
 
transformer loop_to_total_precondition (transformer, loop, transformer, transformer)
 
transformer whileloop_to_postcondition (transformer, whileloop, transformer)
 
transformer whileloop_to_total_precondition (transformer, whileloop, transformer, transformer)
 
transformer statement_to_total_precondition (transformer, statement)
 ri_to_total_preconditions.c More...
 
list declaration_to_transformer_list (entity, transformer)
 ri_to_transformer_lists.c More...
 
list declarations_to_transformer_list (list, transformer)
 For C declarations. More...
 
list intrinsic_to_transformer_list (entity, list, transformer, list)
 because of the conditional and the comma C intrinsics at least More...
 
list assigned_expression_to_transformer_list (entity, expression, transformer)
 transformer assigned_expression_to_transformer(entity e, expression expr, list ef): returns a transformer abstracting the effect of assignment "e = expr" when possible, transformer_undefined otherwise. More...
 
list safe_assigned_expression_to_transformer_list (entity, expression, transformer)
 Always returns a fully defined transformer. More...
 
list integer_assign_to_transformer_list (expression, expression, transformer, list)
 This function never returns an undefined transformer. More...
 
list any_scalar_assign_to_transformer_list (entity, expression, list, transformer)
 precondition More...
 
list any_assign_to_transformer_list (list, list, transformer)
 precondition More...
 
list any_update_to_transformer_list (entity, list, list, transformer)
 precondition More...
 
list any_basic_update_to_transformer_list (entity, list, list, transformer)
 precondition More...
 
list statement_to_transformer_list (statement, transformer)
 A transformer is already available for statement s, but it is going to be refined into a list of transformers to isolate at least the identity transformer from effective transformers. More...
 
void path_initialize (statement, statement, statement, path *, path *)
 path_transformer.c More...
 
transformer path_transformer_on (statement, path, path, int)
 
transformer compute_path_transformer (statement, path, path)
 
bool path_transformer (const string)
 
void transformer_add_type_information (transformer)
 type.c More...
 
void transformer_add_variable_type_information (transformer, entity)
 
list semantics_expression_to_points_to_sources (expression)
 points_to.c More...
 
list semantics_expression_to_points_to_sinks (expression)
 Returns a list of cells. More...
 
transformer substitute_scalar_stub_in_transformer (transformer, entity, entity, bool, list *)
 If both "se", source entity, and "de", destination entity, are defined, substitute the values of "se" by the values of "de" in "backward_p" mode, when translating a callee transformer at a call site of a caller. More...
 
transformer substitute_struct_stub_in_transformer (transformer, reference, type, reference, type, bool, list *)
 
transformer substitute_stubs_in_transformer (transformer, call, statement, bool)
 Exploit the binding map to substitute calles's stubs by actual arguments, which may be stubs of the callers,. More...
 
transformer new_substitute_stubs_in_transformer (transformer, call, statement, bool)
 

Variables

bool refine_transformers_p
 Transformer recomputation cannot be of real use unless an interprocedural analysis is performed. More...
 

Macro Definition Documentation

◆ SEMANTICS_OPTIONS

#define SEMANTICS_OPTIONS   "?Otcfieod-D:"

Warning! Do not modify this file that is automatically generated!

Modify src/Libs/semantics/semantics-local.h instead, to add your own modifications. header file built by cproto semantics-local.h include file for semantic analysis

Definition at line 34 of file semantics.h.

◆ semantics_user_warning

#define semantics_user_warning   semantics_user_warning_func2

Definition at line 54 of file semantics.h.

◆ SEQUENTIAL_PRECONDITION_SUFFIX

#define SEQUENTIAL_PRECONDITION_SUFFIX   ".prec"

Definition at line 38 of file semantics.h.

◆ SEQUENTIAL_TOTAL_PRECONDITION_SUFFIX

#define SEQUENTIAL_TOTAL_PRECONDITION_SUFFIX   ".tprec"

Definition at line 40 of file semantics.h.

◆ SEQUENTIAL_TRANSFORMER_SUFFIX

#define SEQUENTIAL_TRANSFORMER_SUFFIX   ".tran"

Definition at line 36 of file semantics.h.

◆ USER_PRECONDITION_SUFFIX

#define USER_PRECONDITION_SUFFIX   ".uprec"

Definition at line 39 of file semantics.h.

◆ USER_TOTAL_PRECONDITION_SUFFIX

#define USER_TOTAL_PRECONDITION_SUFFIX   ".utprec"

Definition at line 41 of file semantics.h.

◆ USER_TRANSFORMER_SUFFIX

#define USER_TRANSFORMER_SUFFIX   ".utran"

Definition at line 37 of file semantics.h.

Function Documentation

◆ add_declaration_list_information()

void add_declaration_list_information ( transformer  pre,
list  dl,
bool  precondition_p 
)
Parameters
prere
dll
precondition_precondition_p

Definition at line 179 of file dbm_interface.c.

182 {
185  language l = code_language(c);
186 
187  FOREACH(ENTITY, v, dl) {
188  type t = entity_type(v);
189 
190  if(type_variable_p(t)) {
191  variable tv = type_variable(t);
192 
196 
198  Pvecteur vl = normalized_linear(nl);
199  Pvecteur vu = normalized_linear(nu);
200 
203  Pvecteur cv = vect_substract(vl, vu);
204 
205  if(language_c_p(l))
207 
208  if(!precondition_p) {
209  upwards_vect_rename(cv, pre);
210  }
211 
212  if(!vect_constant_p(cv) || vect_coeff(TCST, cv) > 0) {
214  }
215  }
216  }
217  }
218 
219  }
220  }
221 }
#define VALUE_MONE
transformer transformer_inequality_add(transformer tf, Pvecteur i)
Definition: basic.c:375
bool vect_constant_p(Pvecteur)
bool vect_constant_p(Pvecteur v): v contains only a constant term, may be zero
Definition: predicats.c:211
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
#define NORMALIZE_EXPRESSION(e)
#define normalized_linear_p(x)
Definition: ri.h:1779
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define dimension_lower(x)
Definition: ri.h:980
#define type_variable(x)
Definition: ri.h:2949
#define language_c_p(x)
Definition: ri.h:1594
#define dimension_upper(x)
Definition: ri.h:982
#define value_code(x)
Definition: ri.h:3067
#define variable_dimensions(x)
Definition: ri.h:3122
#define entity_type(x)
Definition: ri.h:2792
#define code_language(x)
Definition: ri.h:792
#define normalized_linear(x)
Definition: ri.h:1781
#define type_variable_p(x)
Definition: ri.h:2947
#define entity_initial(x)
Definition: ri.h:2796
bool value_mappings_compatible_vector_p(Pvecteur iv)
transform a vector based on variable entities into a vector based on new value entities when possible...
Definition: mappings.c:924
void upwards_vect_rename(Pvecteur v, transformer post)
Renaming of variables in v according to transformations occuring later.
Definition: mappings.c:1062
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
Pvecteur vect_substract(Pvecteur v1, Pvecteur v2)
Pvecteur vect_substract(Pvecteur v1, Pvecteur v2): allocation d'un vecteur v dont la valeur est la di...
Definition: binaires.c:75
void vect_add_elem(Pvecteur *pvect, Variable var, Value val)
void vect_add_elem(Pvecteur * pvect, Variable var, Value val): addition d'un vecteur colineaire au ve...
Definition: unaires.c:72
Value vect_coeff(Variable var, Pvecteur vect)
Variable vect_coeff(Variable var, Pvecteur vect): coefficient de coordonnee var du vecteur vect —> So...
Definition: unaires.c:228

References code_language, DIMENSION, dimension_lower, dimension_upper, ENTITY, entity_initial, entity_type, FOREACH, get_current_module_entity(), language_c_p, NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, TCST, transformer_inequality_add(), type_variable, type_variable_p, upwards_vect_rename(), value_code, value_mappings_compatible_vector_p(), VALUE_MONE, variable_dimensions, vect_add_elem(), vect_coeff(), vect_constant_p(), and vect_substract().

Referenced by add_declaration_information().

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

◆ add_equivalenced_values()

void add_equivalenced_values ( entity  e,
entity  eq,
bool  readonly 
)

e and eq are assumed to be different scalar variables of the same analyzed type

eq will be seen as e, as far as values are concerned, but for printing

new equalities e::new == eq::new and e::old == eq::old have to be added to the preconditions just before they are stored; since eq should never be written no eq::old should appear; thus the first equation is enough

By definition, all variables are conflicting with themselves but this is assumed filtered out above.

add the equivalence equations

Parameters
eqq
readonlyeadonly

Definition at line 107 of file mappings.c.

108 {
109  /* e and eq are assumed to be different scalar variables of the same
110  analyzed type */
111  /* eq will be seen as e, as far as values are concerned,
112  but for printing */
113  /* new equalities e#new == eq#new and e#old == eq#old
114  have to be added to the preconditions just before they
115  are stored; since eq should never be written no eq#old
116  should appear; thus the first equation is enough */
117 
118  /* By definition, all variables are conflicting
119  with themselves but this is assumed filtered out above. */
120 
121  pips_assert("e is not eq", e!=eq);
122 
123  add_synonym_values(e, eq, readonly);
124  /* add the equivalence equations */
126 
127 }
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
Pcontrainte eq
element du vecteur colonne du systeme donne par l'analyse
Definition: sc_gram.c:108
static void add_equivalence_equality(entity e, entity eq)
Definition: mappings.c:93
void add_synonym_values(entity, entity, bool)
Definition: value.c:1578

References add_equivalence_equality(), add_synonym_values(), eq, and pips_assert.

Referenced by add_or_kill_equivalenced_variables().

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

◆ add_formal_to_actual_bindings()

transformer add_formal_to_actual_bindings ( call  c,
transformer  pre,
entity  caller 
)

add_formal_to_actual_bindings(call c, transformer pre, entity caller):

pre := pre U {f = expr } i i for all i such that formal f_i is an analyzable scalar variable and as far as expression expr_i is analyzable and of the same type

let's start a long, long, long MAPL, so long that MAPL is a pain

type checking. You already know that fp is a scalar variable

Do not care about side effects on expressions: this is used to map a caller precondition towards a callee summary precondition.

tmp must be used instead of fp_new because fp_new does not exist in the caller frame

Likely memory leak for the initial pre

ignore assocation

Parameters
prere
calleraller

Definition at line 283 of file interprocedural.c.

284 {
285  entity f = call_function(c);
286  list pc = call_arguments(c);
288  cons * ce;
289 
290  pips_debug(6, "begin for call to %s from %s, pre=%p\n",
291  module_local_name(f), module_local_name(caller), pre);
292  ifdebug(6) dump_transformer(pre);
293 
294  pips_assert("f is a module",
295  entity_module_p(f));
296  pips_assert("The precondition pre is defined",
297  pre != transformer_undefined);
298 
299  /* let's start a long, long, long MAPL, so long that MAPL is a pain */
300  for( ce = formals; !ENDP(ce); POP(ce)) {
301  entity fp = ENTITY(CAR(ce));
303  expression expr = find_ith_argument(pc, r);
304 
305  if(expr == expression_undefined)
306  pips_user_error("not enough args in call to %s from %s for formal parameter %s of rank %d\n",
308  module_local_name(caller),
309  entity_local_name(fp), r);
310  else {
311  /* type checking. You already know that fp is a scalar variable */
312  type tfp = entity_type(fp);
313  basic bfp = variable_basic(type_variable(tfp));
314  basic bexpr = basic_of_expression(expr);
315 
316  if(!same_basic_p(bfp, bexpr)) {
317  pips_user_warning("Type incompatibility (%s/%s) for formal parameter \"%s\""
318  " (rank %d)\nin call to \"%s\" from \"%s\"\n",
319  basic_to_string(bfp), basic_to_string(bexpr),
320  entity_local_name(fp), r,
322  }
323 
324  if(basic_tag(bfp)==basic_tag(bexpr)) {
325  /* Do not care about side effects on expressions: this is used to map
326  a caller precondition towards a callee summary precondition. */
329  /* tmp must be used instead of fp_new because fp_new does not
330  exist in the caller frame */
331  transformer t_expr = any_expression_to_transformer(tmp, expr,
333  false);
334 
335  t_expr = transformer_safe_value_substitute(t_expr, tmp, fp_new);
336  /* Likely memory leak for the initial pre */
337  pre = transformer_safe_image_intersection(pre, t_expr);
338  free_transformer(t_expr);
339  }
340  else {
341  /* ignore assocation */
342  pips_debug(6, "Full type incompatibility (%s/%s) for formal parameter %s (rank %d)"
343  " in call to %s from %s\n"
344  "Association ignored",
345  basic_to_string(bfp), basic_to_string(bexpr),
347  module_local_name(caller));
348  }
349  }
350  }
351 
352  free_arguments(formals);
353 
354  ifdebug(6) {
355  pips_debug(6, "new pre=%p\n", pre);
356  dump_transformer(pre);
357  pips_debug(6, "end for call to %s from %s\n", module_local_name(f),
358  module_local_name(caller));
359  }
360 
361  return pre;
362 }
void free_transformer(transformer p)
Definition: ri.c:2616
void free_arguments(cons *args)
Definition: arguments.c:218
#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
#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_user_warning
Definition: misc-local.h:146
#define pips_user_error
Definition: misc-local.h:147
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
static char * module
Definition: pips.c:74
#define dump_transformer(t)
Definition: print.c:355
string basic_to_string(basic)
Definition: type.c:87
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
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
bool entity_module_p(entity e)
Definition: entity.c:683
expression find_ith_argument(list args, int n)
Definition: expression.c:1147
basic basic_of_expression(expression)
basic basic_of_expression(expression exp): Makes a basic of the same basic as the expression "exp".
Definition: type.c:1383
bool same_basic_p(basic, basic)
check if two basics are similar.
Definition: type.c:969
#define formal_offset(x)
Definition: ri.h:1408
#define transformer_undefined
Definition: ri.h:2847
#define call_function(x)
Definition: ri.h:709
#define basic_tag(x)
Definition: ri.h:613
#define entity_storage(x)
Definition: ri.h:2794
#define storage_formal(x)
Definition: ri.h:2524
#define expression_undefined
Definition: ri.h:1223
#define call_arguments(x)
Definition: ri.h:711
#define variable_basic(x)
Definition: ri.h:3120
transformer any_expression_to_transformer(entity v, expression expr, transformer pre, bool is_internal)
A set of functions to compute the transformer associated to an expression evaluated in a given contex...
Definition: expression.c:4993
list module_to_formal_analyzable_parameters(entity f)
returns a module's parameter's list
#define ifdebug(n)
Definition: sg.c:47
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
transformer transformer_safe_image_intersection(transformer t1, transformer t2)
Allocate a new transformer.
Definition: transformer.c:647
transformer transformer_safe_value_substitute(transformer t, entity e1, entity e2)
Definition: transformer.c:2048
entity make_local_temporary_value_entity(type)
Definition: value.c:605
entity external_entity_to_new_value(entity)
Definition: value.c:1411

References any_expression_to_transformer(), basic_of_expression(), basic_tag, basic_to_string(), call_arguments, call_function, CAR, dump_transformer, ENDP, ENTITY, entity_local_name(), entity_module_p(), entity_storage, entity_type, expression_undefined, external_entity_to_new_value(), f(), find_ith_argument(), formal_offset, free_arguments(), free_transformer(), ifdebug, make_local_temporary_value_entity(), module_local_name(), module_to_formal_analyzable_parameters(), pips_assert, pips_debug, pips_user_error, pips_user_warning, POP, same_basic_p(), storage_formal, transformer_safe_image_intersection(), transformer_safe_value_substitute(), transformer_undefined, type_variable, and variable_basic.

Referenced by call_site_to_module_precondition_text(), and call_to_summary_precondition().

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

◆ add_implicit_interprocedural_write_effects()

void add_implicit_interprocedural_write_effects ( entity  al,
list  el 
)

It is assumed that al is an abstract location that is written and which may conflict with effects in effect list el.

If there is a conflict, than the variable associated to this effect is written.

It should be generalized to non-interprocedural cases.

Parameters
all
ell

Definition at line 382 of file mappings.c.

383 {
384  type alt = entity_type(al);
385 
386  if(type_unknown_p(alt)
387  || type_area_p(alt) // FI: Let's agree about typing issues!
388  || get_bool_property("ALIASING_ACROSS_TYPES")
389  || overloaded_type_p(alt)) {
390  FOREACH(EFFECT, ef, el) {
392  entity v = reference_variable(r);
393 
395  && entities_may_conflict_p(al, v)
398  }
399  }
400  }
401  else {
402  FOREACH(EFFECT, ef, el) {
404  entity v = reference_variable(r);
405  type vt = ultimate_type(entity_type(v));
406 
408  && entities_may_conflict_p(al, v)
409  && type_equal_p(alt, vt)) {
411  pips_internal_error("Effects cannot be related to dummy parameters.");
413  }
414  }
415  }
416 }
bool entity_abstract_location_p(entity al)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
bool entities_may_conflict_p(entity e1, entity e2)
Check if two entities may conflict.
Definition: conflicts.c:984
#define pips_internal_error
Definition: misc-local.h:149
bool dummy_parameter_entity_p(entity p)
is p a dummy parameter?
Definition: entity.c:1941
type ultimate_type(type)
Definition: type.c:3466
bool type_equal_p(type, type)
Definition: type.c:547
bool overloaded_type_p(type)
Returns true if t is a variable type with a basic overloaded.
Definition: type.c:2666
#define type_unknown_p(x)
Definition: ri.h:2956
#define reference_variable(x)
Definition: ri.h:2326
#define type_area_p(x)
Definition: ri.h:2944
static void add_interprocedural_value_entities(entity e)
????
Definition: mappings.c:133
bool analyzable_scalar_entity_p(entity)
The entity type is one of the analyzed types.
Definition: value.c:471

References add_interprocedural_value_entities(), analyzable_scalar_entity_p(), dummy_parameter_entity_p(), EFFECT, effect_any_reference, entities_may_conflict_p(), entity_abstract_location_p(), entity_type, FOREACH, get_bool_property(), overloaded_type_p(), pips_internal_error, reference_variable, type_area_p, type_equal_p(), type_unknown_p, and ultimate_type().

Referenced by module_to_value_mappings().

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

◆ add_index_range_conditions()

transformer add_index_range_conditions ( transformer  pre,
entity  i,
range  r,
transformer  tfb 
)

if tfb is not undefined, then it is a loop; loop bounds can be kept as preconditions for the loop body if the loop increment is numerically known and if they are linear and if they are loop body invariant, i.e. indices are accepted

is the loop increment numerically known? Is its sign known?

incr == 0 is used below as a give-up condition

When lost, try to exploit type information thanks to unsigned variables

find the real upper and lower bounds

try to add the lower bound

try to add the upper bound

Parameters
prere
tfbfb

Definition at line 711 of file loop.c.

715 {
716  /* if tfb is not undefined, then it is a loop;
717  loop bounds can be kept as preconditions for the loop body
718  if the loop increment is numerically known and if they
719  are linear and if they are loop body invariant, i.e.
720  indices are accepted */
721 
722  expression lb = range_lower(r);
723  expression ub = range_upper(r);
724  expression e_incr = range_increment(r);
725  int incr = 0;
726  int incr_lb = 0;
727  int incr_ub = 0;
728 
729  pips_debug(8, "begin\n");
730 
731  if(entity_has_values_p(i)) {
732 
733  /* is the loop increment numerically known? Is its sign known? */
734  expression_and_precondition_to_integer_interval(e_incr, pre, &incr_lb, &incr_ub);
735 
736  if(incr_lb==incr_ub) {
737  if(incr_lb==0) {
738  pips_user_error("Illegal null increment\n");
739  }
740  else
741  incr = incr_lb;
742  }
743  else if(incr_lb>=1) {
744  incr = 1;
745  }
746  else if(incr_ub<=-1) {
747  incr = -1;
748  }
749  else {
750  /* incr == 0 is used below as a give-up condition */
751  incr = 0;
752  }
753 
754  /* When lost, try to exploit type information thanks to unsigned variables */
755  if(incr==0) {
756  if(positive_expression_p(e_incr))
757  incr = 1;
758  else if(negative_expression_p(e_incr))
759  incr = -1;
760  }
761 
762  /* find the real upper and lower bounds */
763  if(incr<0) {
764  ub = range_lower(r);
765  lb = range_upper(r);
766  }
767 
768  if(incr!=0) {
769  if(simple_dead_loop_p(lb, ub)) {
770  transformer new_pre = transformer_empty();
771 
772  free_transformer(pre);
773  pre = new_pre;
774  }
775  else {
776  /* try to add the lower bound */
777  add_index_bound_conditions(pre, i, lb, IS_LOWER_BOUND, tfb);
778 
779  /* try to add the upper bound */
780  add_index_bound_conditions(pre, i, ub, IS_UPPER_BOUND, tfb);
781  }
782  }
783 
784  }
785 
786  pips_debug(8, "end\n");
787  return pre;
788 }
transformer transformer_empty()
Allocate an empty transformer.
Definition: basic.c:120
bool positive_expression_p(expression e)
Use constants and type information to decide if the value of sigma(e) is always positive,...
Definition: eval.c:826
bool negative_expression_p(expression e)
Use constants and type information to decide if the value of sigma(e) is always negative,...
Definition: eval.c:896
#define range_upper(x)
Definition: ri.h:2290
#define range_increment(x)
Definition: ri.h:2292
#define range_lower(x)
Definition: ri.h:2288
#define IS_LOWER_BOUND
Definition: loop.c:491
#define IS_UPPER_BOUND
Definition: loop.c:492
bool simple_dead_loop_p(expression lower, expression upper)
Definition: loop.c:1028
static transformer add_index_bound_conditions(transformer pre, entity index, expression bound, int lower_or_upper, transformer tfb)
Side effect on pre.
Definition: loop.c:624
void expression_and_precondition_to_integer_interval(expression, transformer, int *, int *)
Evaluate expression e in context p, assuming that e is an integer expression.
Definition: utils.c:325
bool entity_has_values_p(entity)
This function could be made more robust by checking the storage of e.
Definition: value.c:911

References add_index_bound_conditions(), entity_has_values_p(), expression_and_precondition_to_integer_interval(), free_transformer(), IS_LOWER_BOUND, IS_UPPER_BOUND, negative_expression_p(), pips_debug, pips_user_error, positive_expression_p(), range_increment, range_lower, range_upper, simple_dead_loop_p(), and transformer_empty().

Referenced by add_good_loop_conditions(), comp_regions_of_implied_do(), and loop_to_transformer().

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

◆ add_intraprocedural_value_entities()

void add_intraprocedural_value_entities ( entity  e)

Use to be static, but may be called from ri_to_transformer.

void add_intraprocedural_value_entities(entity e)

Definition at line 181 of file mappings.c.

182 {
184 
185  pips_debug(8, "for %s\n", entity_name(e));
186  if(!entity_has_values_p(e) && type_variable_p(ut) ) {
188  }
189 }
type entity_basic_concrete_type(entity)
retrieves or computes and then returns the basic concrete type of an entity
Definition: type.c:3677
#define entity_name(x)
Definition: ri.h:2790
static void add_intraprocedural_value_entities_unconditionally(entity e)
Definition: mappings.c:169

References add_intraprocedural_value_entities_unconditionally(), entity_basic_concrete_type(), entity_has_values_p(), entity_name, pips_debug, and type_variable_p.

Referenced by add_inter_or_intraprocedural_field_entities(), add_reference_values(), and module_to_value_mappings().

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

◆ add_loop_index_exit_value()

transformer add_loop_index_exit_value ( transformer  post,
loop  l,
transformer  pre 
)

The exit value is known if.

  • the loop index is an analyzed integer scalar variable real index are standard-compliant, integer index can be equivalenced to a real variable,...
  • the increment is affine (non-necessary assumption made: it is affine if the increment sign is known)
  • the increment sign is known
  • the body and loop initialization execution does not modify the value of the upper bound
  • the upper bound is affine (?)

Affine increments can be handled when their signs only are known.

For instance, for increment==k: i >= ub i-k <= ub-1

Note the simplification when k==1.

But, first of all, the value of the loop index in post must be incremented. This changes its relationship with induction variables.

Most tests here are redundant because this function is only called if it has been proved that the loop was executed which implies that the upper and lower bounds are affine, that the increment is affine and that the increment sign is known.

Always returns a newly allocated value precondition on loop entrance

This part should be useless because post really is a loop postcondition. There should be no need for an index incrementation or anything. It is used to recover some of the fix-point failures:-(

In fact, it may be useful. The loop transformer and its invariant are computed without knowledge about the number of iteration, which may be zero. By adding one execution of the loop body and the index incrementation, we change b* into b+ which should add effective information.

Do not apply an extra iteration!

post = transformer_apply(t_body, post);

v_i - v_incr == v_ub, regardless of the sign

v_i - v_incr <= v_ub < v_i or: v_i - v_incr - v_ub <= 0, v_ub - v_i + 1 <= 0

v_i - v_incr >= v_ub > v_i

or:

  • v_i + v_incr + v_ub <= 0, - v_ub + v_i + 1 <= 0

should never happen!

Parameters
postost
lpostcondition of the last iteration
preloop to process

Definition at line 878 of file loop.c.

882 {
883  entity i = loop_index(l);
885  normalized n_incr = NORMALIZE_EXPRESSION(e_incr);
886  expression e_ub = range_upper(loop_range(l));
887  normalized n_ub = NORMALIZE_EXPRESSION(e_ub);
890  list li = CONS(ENTITY, i, NIL);
891  int ub_inc = 0;
892  int lb_inc = 0;
893 
894  ifdebug(8) {
895  pips_debug(8, "begin with post:\n");
896  (void) print_transformer(post);
897  }
898 
899  if(!entity_has_values_p(i)) {
900  ifdebug(8) {
901  pips_debug(8, "give up because %s has no values:\n",
902  entity_local_name(i));
903  pips_debug(8, "end with post:\n");
904  (void) print_transformer(post);
905  }
906  return transformer_dup(post);
907  }
908 
909  expression_and_precondition_to_integer_interval(e_incr, pre, &lb_inc, &ub_inc);
910 
911  /* This part should be useless because post really is a loop postcondition.
912  * There should be no need for an index incrementation or anything.
913  * It is used to recover some of the fix-point failures:-(
914  *
915  * In fact, it may be useful. The loop transformer and its invariant are
916  * computed without knowledge about the number of iteration, which may be
917  * zero. By adding one execution of the loop body and the index incrementation,
918  * we change b* into b+ which should add effective information.
919  */
920  if(normalized_linear_p(n_incr)) {
921  Pvecteur v_incr = (Pvecteur) normalized_linear(n_incr);
923  entity i_new = entity_to_new_value(i);
924  entity i_rep = value_to_variable(i_new);
925  t_incr = affine_increment_to_transformer(i_rep, v_incr);
926  }
927  else {
928  t_incr = transformer_undefined;
929  }
930  }
931  else {
932  t_incr = transformer_undefined;
933  }
934  if(t_incr==transformer_undefined)
935  t_incr = args_to_transformer(li);
936  /* Do not apply an extra iteration! */
937  /* post = transformer_apply(t_body, post); */
938  post = transformer_apply(t_incr, post);
939  transformer_free(t_incr);
940 
941  ifdebug(8) {
942  pips_debug(8, "post after index incrementation:\n");
943  (void) print_transformer(post);
944  }
945 
946  if(normalized_linear_p(n_ub)
948  if(lb_inc >= 1 || ub_inc <= -1) {
949  Pvecteur v_ub = (Pvecteur) normalized_linear(n_ub);
950  Pvecteur v_incr = (Pvecteur) normalized_linear(n_incr);
951 
954  entity i_new = entity_to_new_value(i);
955  entity i_rep = value_to_variable(i_new);
956  Pvecteur v_i = vect_new((Variable) i_rep, (Value) 1);
959 
960  pips_assert("The increment is an affine function", normalized_linear_p(n_incr));
961  if(lb_inc==ub_inc && ABS(lb_inc)==1) {
962  /* v_i - v_incr == v_ub, regardless of the sign */
963  c1 = vect_substract(v_i, v_incr);
964  c1 = vect_cl(c1, (Value) -1, v_ub);
965  transformer_equality_add(post, c1);
966  }
967  else {
968  if(lb_inc>=1) {
969  /* v_i - v_incr <= v_ub < v_i
970  * or:
971  * v_i - v_incr - v_ub <= 0, v_ub - v_i + 1 <= 0
972  */
973  c1 = vect_substract(v_i, v_incr);
974  c2 = vect_substract(v_ub, v_i);
975 
976  c1 = vect_cl(c1, (Value) -1, v_ub);
977  vect_add_elem(&c2, (Variable) TCST, (Value) 1);
978  }
979  else if(ub_inc<=-1) {
980  /* v_i - v_incr >= v_ub > v_i
981  *
982  * or:
983  * - v_i + v_incr + v_ub <= 0, - v_ub + v_i + 1 <= 0
984  */
985  c1 = vect_substract(v_incr, v_i);
986  c2 = vect_substract(v_i, v_ub);
987 
988  c1 = vect_cl(c1, (Value) 1, v_ub);
989  vect_add_elem(&c2, (Variable) TCST, (Value) 1);
990  }
991  else {
992  /* should never happen! */
993  pips_assert("add_loop_index_exit_value", false);
994  }
995  transformer_inequality_add(post, c1);
996  transformer_inequality_add(post, c2);
997  }
998 
999  ifdebug(8) {
1000  pips_debug(8, "post with exit conditions:\n");
1001  (void) print_transformer(post);
1002  }
1003  }
1004  else {
1005  pips_debug(8,
1006  "post is unchanged because the increment or the upper bound"
1007  " reference unanalyzed variables\n");
1008  }
1009  }
1010  else {
1011  pips_debug(8,
1012  "post is unchanged because the increment sign is unknown\n");
1013  }
1014  }
1015  else {
1016  pips_debug(8,
1017  "post is unchanged because the upper bound is not affine\n");
1018  }
1019 
1020  ifdebug(8) {
1021  pips_debug(8, "end: post:\n");
1022  (void) print_transformer(post);
1023  }
1024 
1025  return post;
1026 }
int Value
#define ABS(x)
was: #define value_mult(v,w) value_direct_multiply(v,w) #define value_product(v,w) value_direct_produ...
transformer transformer_dup(transformer t_in)
transformer package - basic routines
Definition: basic.c:49
void transformer_free(transformer t)
Definition: basic.c:68
transformer transformer_equality_add(transformer tf, Pvecteur i)
Definition: basic.c:383
#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 print_transformer(t)
Definition: print.c:357
#define loop_body(x)
Definition: ri.h:1644
#define loop_range(x)
Definition: ri.h:1642
#define loop_index(x)
Definition: ri.h:1640
transformer affine_increment_to_transformer(entity e, Pvecteur a)
Definition: expression.c:1269
transformer load_statement_transformer(statement)
bool transformer_affect_linear_p(transformer tf, Pvecteur l)
bool transformer_affect_linear_p(transformer tf, Pvecteur l): returns TRUE if there is a state s such...
Definition: transformer.c:1850
transformer args_to_transformer(list le)
Generates a transformer abstracting a totally unknown modification of the values associated to variab...
Definition: transformer.c:1907
transformer transformer_apply(transformer tf, transformer pre)
transformer transformer_apply(transformer tf, transformer pre): apply transformer tf on precondition ...
Definition: transformer.c:1559
entity entity_to_new_value(entity)
Definition: value.c:859
entity value_to_variable(entity)
Get the primitive variable associated to any value involved in a transformer.
Definition: value.c:1624
#define VECTEUR_UNDEFINED
struct Svecteur * Pvecteur
void * Variable
arithmetique is a requirement for vecteur, but I do not want to inforce it in all pips files....
Definition: vecteur-local.h:60
Pvecteur vect_new(Variable var, Value coeff)
Pvecteur vect_new(Variable var,Value coeff): allocation d'un vecteur colineaire au vecteur de base va...
Definition: alloc.c:110
Pvecteur vect_cl(Pvecteur v, Value lambda, Pvecteur u)
Definition: binaires.c:181

References ABS, affine_increment_to_transformer(), args_to_transformer(), CONS, ENTITY, entity_has_values_p(), entity_local_name(), entity_to_new_value(), expression_and_precondition_to_integer_interval(), ifdebug, load_statement_transformer(), loop_body, loop_index, loop_range, NIL, NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, pips_assert, pips_debug, print_transformer, range_increment, range_upper, TCST, transformer_affect_linear_p(), transformer_apply(), transformer_dup(), transformer_equality_add(), transformer_free(), transformer_inequality_add(), transformer_undefined, value_mappings_compatible_vector_p(), value_to_variable(), vect_add_elem(), vect_cl(), vect_new(), vect_substract(), and VECTEUR_UNDEFINED.

Referenced by complete_loop_transformer(), complete_loop_transformer_list(), loop_to_postcondition(), and loop_to_total_precondition().

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

◆ add_loop_skip_condition()

transformer add_loop_skip_condition ( transformer  tf,
loop  l,
transformer  pre 
)

tf and pre are a unique data structure when preconditions are computed

It is assumed that loop l is not entered

EXPRESSION_TO_TRANSFORMER() should be used

is the loop increment numerically known? Is its sign known?

incr == 0 is used below as a give-up condition

find the real upper and lower bounds

exchange bounds

ub < lb, i.e. ub + lb + 1 <= 0

Parameters
tff
prere

Definition at line 495 of file loop.c.

496 {
497  /* It is assumed that loop l is not entered */
498  range r = loop_range(l);
499  expression e_lb = range_lower(r);
500  expression e_ub = range_upper(r);
501  expression e_incr = range_increment(r);
502  normalized n_lb = NORMALIZE_EXPRESSION(e_lb);
503  normalized n_ub = NORMALIZE_EXPRESSION(e_ub);
504  int incr = 0;
505  int incr_lb = 0;
506  int incr_ub = 0;
507 
508  /* EXPRESSION_TO_TRANSFORMER() should be used */
509 
510  pips_debug(8,"begin with transformer tf=%p\n", tf);
511  ifdebug(8) {
512  (void) print_transformer(tf);
513  pips_debug(8,"and precondition pre=%p\n", pre);
514  (void) print_transformer(pre);
515  }
516 
517  /* is the loop increment numerically known? Is its sign known? */
518  expression_and_precondition_to_integer_interval(e_incr, pre, &incr_lb, &incr_ub);
519 
520  if(incr_lb==incr_ub) {
521  if(incr_lb==0) {
522  user_error("add_loop_skip_condition", "Illegal null loop increment\n");
523  }
524  else
525  incr = incr_lb;
526  }
527  else if(incr_lb>=1) {
528  incr = 1;
529  }
530  else if(incr_ub<=-1) {
531  incr = -1;
532  }
533  else
534  incr = 0;
535 
536  /* incr == 0 is used below as a give-up condition */
537 
538  /* find the real upper and lower bounds */
539  if(incr<0) {
540  /* exchange bounds */
541  n_lb = NORMALIZE_EXPRESSION(e_ub);
542  n_ub = NORMALIZE_EXPRESSION(e_lb);
543  }
544 
545  if(incr!=0 && normalized_linear_p(n_lb) && normalized_linear_p(n_ub)) {
546  /* ub < lb, i.e. ub + lb + 1 <= 0 */
547  Pvecteur v_ub = (Pvecteur) normalized_linear(n_ub);
548  Pvecteur v_lb = (Pvecteur) normalized_linear(n_lb);
549 
552  Pvecteur v = vect_substract(v_ub, v_lb);
553 
554  vect_add_elem(&v, TCST, (Value) 1);
555  tf = transformer_inequality_add(tf, v);
556 
557  ifdebug(8) {
558  debug(8,"add_loop_skip_condition","Skip condition:\n");
559  vect_fprint(stderr, v, (char * (*)(Variable)) external_value_name);
560  }
561  }
562  else {
563  pips_debug(8,"Non-analyzed variable in loop bound(s)\n");
564  }
565  }
566  else {
567  pips_debug(8,"increment sign unknown or non-affine bound\n");
568  }
569 
570  ifdebug(8) {
571  pips_debug(8,"end with new tf=%p\n", tf);
572  (void) print_transformer(tf);
573  }
574 
575  return tf;
576 }
void vect_fprint(FILE *f, Pvecteur v, get_variable_name_t variable_name)
void vect_fprint(FILE * f, Pvecteur v, char * (*variable_name)()): impression d'un vecteur creux v su...
Definition: io.c:124
#define user_error(fn,...)
Definition: misc-local.h:265
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
const char * external_value_name(entity)
Definition: value.c:753

References debug(), expression_and_precondition_to_integer_interval(), external_value_name(), ifdebug, loop_range, NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, pips_debug, print_transformer, range_increment, range_lower, range_upper, TCST, transformer_inequality_add(), user_error, value_mappings_compatible_vector_p(), vect_add_elem(), vect_fprint(), and vect_substract().

Referenced by complete_loop_transformer(), complete_loop_transformer_list(), loop_to_postcondition(), and loop_to_total_precondition().

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

◆ add_module_call_site_precondition()

void add_module_call_site_precondition ( entity  m,
transformer  p 
)

module precondition

cons * ef = code_effects(value_code(entity_initial(m)));

p might not be printable; it may (should!) contain formal parameters of module m

keep only the interprocedural part of p that can be easily used by m; this is non optimal because symbolic constants will be lost; this is due to value mappings; new and old values should be added to the mapping using the module precondition

convert global variables in the summary precondition in the local frame as defined by value mappings (FI, 1 February 1994)

p is returned in the callee's frame; there is no need for a translation; the caller's frame should always contain the callee's frame by definition of effects;unfortunately, I do not remember why I added this translation; it was linked to a problem encountered with transformer and "invisible" variables, i.e. global variables which are indirectly changed by a procedure which does not see them; such variables receive an arbitrary existing global name; they may receive different names in different context, because there is no canonical name; each time, summary_precondition and summary_transformer are used, they must be converted in a unique frame, which can only be the frame of the current module.

FI, 9 February 1994

the former precondition represents the entire space : the new precondition must also represent the entire space BC, november 1994.

the former precondition is undefined. The new precondition is defined by the current call site precondition BC, november 1994.

Definition at line 123 of file interprocedural.c.

126 {
127  /* module precondition */
128  transformer mp;
129  transformer new_mp;
130  /* cons * ef = code_effects(value_code(entity_initial(m))); */
131  list ef = load_summary_effects(m);
132 
133  pips_assert("add_module_call_site_precondition",entity_module_p(m));
134  pips_assert("add_module_call_site_precondition",
135  p != transformer_undefined);
136 
137  ifdebug(8) {
138  pips_debug(8,"begin\n");
139  pips_debug(8,"for module %s\n",
140  module_local_name(m));
141  pips_debug(8,"call site precondition %p:\n", p);
142  /* p might not be printable; it may (should!) contain formal parameters
143  of module m */
144  dump_transformer(p);
145  }
146 
147  /* keep only the interprocedural part of p that can be easily used
148  by m; this is non optimal because symbolic constants will be
149  lost; this is due to value mappings; new and old values should be
150  added to the mapping using the module precondition*/
151  p = precondition_intra_to_inter(m, p, ef);
152 
153  pips_debug(8, "filtered call site precondition:\n");
155 
156  mp = get_module_precondition(m);
157 
158  ifdebug(8) {
159  if (!transformer_undefined_p(mp)) {
160  pips_debug(8, "old module precondition:\n");
161  dump_transformer(mp);
162  }
163  else
164  pips_debug(8, "old module precondition undefined\n");
165  }
166 
168 
169  pips_debug(8, "new module precondition in current frame:\n");
171 
172  if (!transformer_undefined_p(mp)) {
173 
174  /* convert global variables in the summary precondition in the
175  * local frame as defined by value mappings (FI, 1 February
176  * 1994) */
177 
178  /* p is returned in the callee's frame; there is no need for a
179  * translation; the caller's frame should always contain the
180  * callee's frame by definition of effects;unfortunately, I do not
181  * remember *why* I added this translation; it was linked to a
182  * problem encountered with transformer and "invisible" variables,
183  * i.e. global variables which are indirectly changed by a
184  * procedure which does not see them; such variables receive an
185  * arbitrary existing global name; they may receive different
186  * names in different context, because there is no canonical name;
187  * each time, summary_precondition and summary_transformer are
188  * used, they must be converted in a unique frame, which can only
189  * be the frame of the current module.
190  *
191  * FI, 9 February 1994
192  */
194 
195  pips_debug(8, "old module precondition in current frame:\n");
196  ifdebug(8) dump_transformer(mp);
197 
199  /* the former precondition represents the entire space :
200  * the new precondition must also represent the entire space
201  * BC, november 1994.
202  */
203  transformer_free(p);
204  new_mp = mp;
205  }
206  else
207  new_mp = transformer_convex_hull(mp, p);
208 
209  }
210  else {
211  /* the former precondition is undefined. The new precondition
212  * is defined by the current call site precondition
213  * BC, november 1994.
214  */
215  new_mp = p;
216  }
217 
218  pips_debug(8, "new module precondition in current frame:\n");
219  ifdebug(8) dump_transformer(new_mp);
220 
221  DB_PUT_MEMORY_RESOURCE(DBR_SUMMARY_PRECONDITION,
223  (char*) new_mp );
224 
225  pips_debug(8, "end\n");
226 }
bool transformer_identity_p(transformer t)
Check that t is an identity function.
Definition: basic.c:154
list load_summary_effects(entity e)
FI->FI, FI->BC: these two functions should be moved into effects-util or effects-simple.
if(!(yy_init))
Definition: genread_lex.c:1029
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
char end
Definition: gtk_status.c:82
#define transformer_undefined_p(x)
Definition: ri.h:2848
char * strdup()
transformer precondition_intra_to_inter(entity callee, transformer pre, list le)
transformer get_module_precondition(entity m)
package semantics
void translate_global_values(entity m, transformer tf)
transformer transformer_convex_hull(transformer t1, transformer t2)
transformer transformer_convex_hull(t1, t2): compute convex hull for t1 and t2; t1 and t2 are slightl...
Definition: convex_hull.c:216

References DB_PUT_MEMORY_RESOURCE, dump_transformer, entity_module_p(), get_current_module_entity(), get_module_precondition(), ifdebug, load_summary_effects(), module_local_name(), pips_assert, pips_debug, precondition_intra_to_inter(), strdup(), transformer_convex_hull(), transformer_free(), transformer_identity_p(), transformer_undefined, transformer_undefined_p, and translate_global_values().

Referenced by call_to_summary_precondition().

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

◆ add_or_kill_equivalenced_variables()

void add_or_kill_equivalenced_variables ( entity  e,
bool  readonly 
)

Look for variables equivalenced with e.

e already has values associated although it may not be a canonical representative of its equivalence class...

Forget dynamic aliasing between formal parameters.

Handle intraprocedural aliasing only.

Do not handle interprocedural aliasing: this does not seem to be the right place because too many synonyms, not visible from the current procedure, are introduced (global_shared = area_layout(type_area(t));

potential canonical representative for all variables equivalenced with e

Is e intraprocedurally equivalenced/aliased with an array or a non-analyzable variable which would make e and all its aliased variables unanalyzable?

Since the equivalence is reflexive, no need to process e==eq again.

Since the equivalence is symetrical, eq may have been processed already.

this approximate test by Pierre Jouvelot should be replaced by an exact test but it does not really matter; an exact test could only be useful in presence of arrays; and in presence of arrays we do nothing here

if it's not, go ahead: it exists at least one eq such that e and eq are different, are scalars and have the same analyzable type. All eq conflicting with e meets these conditions.

Declare values for the canonical representative re

Give values to re which should have none and remove values of e. Assume that e and re are local variables.

If it is intra-procedurally equivalenced, set the synonyms as read-only variables

if eq is an integer scalar variable it does not only have a destructive effect

Variable e is equivalenced with an array or a non-integer variable and cannot be analyzed; it must be removed from the hash tables.

semantics analysis should be performed on this kind of variable but it has probably been eliminated earlier; no equivalence possible anyway!

to be dealt with later if we assume non-standard dynamic aliasing between formal parameters

Parameters
readonlyeadonly

Definition at line 204 of file mappings.c.

205 {
206  storage s = entity_storage(e);
207  entity re = e; /* potential canonical representative for all variables equivalenced with e */
208 
209  pips_debug(8, "Begin for %s %s\n", entity_name(e),
210  readonly? "readonly" : "read/write");
211 
212  pips_assert("e has values", entity_has_values_p(e));
213 
214  if(storage_ram_p(s)) {
215  list local_shared = ram_shared(storage_ram(s));
216  bool array_equivalenced = false;
217  entity sec = ram_section(storage_ram(s));
218  type t = entity_type(sec);
219  list ce = list_undefined;
220 
221  pips_assert("t is an area", type_area_p(t));
222 
223  /* Is e intraprocedurally equivalenced/aliased with an array or a
224  * non-analyzable variable which would make e and all its aliased
225  * variables unanalyzable? */
226  for(ce=local_shared; !ENDP(ce); POP(ce)) {
227  entity eq = ENTITY(CAR(ce));
228 
229  /* Since the equivalence is reflexive, no need to process e==eq again. */
230  if(e==eq) continue;
231  /* Since the equivalence is symetrical, eq may have been processed
232  already. */
233  if(entity_has_values_p(eq)) continue;
234 
235  /* this approximate test by Pierre Jouvelot should be
236  replaced by an exact test but it does not really matter;
237  an exact test could only be useful in presence of arrays;
238  and in presence of arrays we do nothing here */
240  pips_user_warning("Values for variable %s are not analyzed because "
241  "%s is aliased with scalar variable %s with non "
242  "analyzed type %s or with array variable\n",
245  array_equivalenced = true;
246  break;
247  }
248 
251  pips_user_warning("Values for variable %s of type %s are not analyzed because "
252  "%s is aliased with scalar variable %s with different "
253  "type %s\n",
257  array_equivalenced = true;
258  break;
259  }
260  }
261  if(entities_may_conflict_p(e, eq) && strcmp(entity_name(eq), entity_name(re))<0) {
262  re = eq;
263  }
264  }
265 
266  /* if it's not, go ahead: it exists at least one eq such that e and eq
267  are different, are scalars and have the same analyzable type. All
268  eq conflicting with e meets these conditions. */
269  if(!array_equivalenced) {
270 
271  /* Declare values for the canonical representative re */
272  if(e!=re) {
273  pips_debug(8, "Canonical representative is %s\n", entity_local_name(re));
274  /* Give values to re which should have none and remove values of
275  e. Assume that e and re are local variables. */
276  pips_assert("re has no values", !entity_has_values_p(re));
277  remove_entity_values(e, readonly);
278  add_new_value(re);
279  if(!readonly) {
280  add_old_value(re);
282  }
283  }
284 
285  /* If it is intra-procedurally equivalenced, set the synonyms as
286  * read-only variables
287  */
288  for(ce=local_shared; !ENDP(ce); POP(ce)) {
289  entity eq = ENTITY(CAR(ce));
290 
291  if(re==eq) continue;
292  if(entities_may_conflict_p(re, eq)) {
293  /* if eq is an integer scalar variable it does not
294  only have a destructive effect */
295  add_equivalenced_values(re, eq, readonly);
296  }
297  }
298  }
299  else {
300  /* Variable e is equivalenced with an array or a non-integer
301  * variable and cannot be analyzed; it must be removed from
302  * the hash tables.
303  */
304  remove_entity_values(e, readonly);
305  }
306  }
307  else if(storage_return_p(s)) {
308  /* semantics analysis should be performed on this kind of variable
309  but it has probably been eliminated earlier; no equivalence
310  possible anyway! */
311  // FI: the warning message is not useful. See formal parameters
312  // pips_user_warning("storage return\n");
313  ;
314  }
315  else if(storage_formal_p(s))
316  /* to be dealt with later if we assume non-standard dynamic
317  aliasing between formal parameters */
318  ;
319  else
320  pips_internal_error("unproper storage = %d (%s), for entity %s", storage_tag(s), storage_to_string(s), entity_name(e));
321 
322  pips_debug(8, "End for %s\n", entity_name(e));
323 }
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
string storage_to_string(storage s)
Definition: entity.c:2030
string type_to_string(const type)
type.c
Definition: type.c:51
#define storage_formal_p(x)
Definition: ri.h:2522
#define storage_tag(x)
Definition: ri.h:2515
#define storage_ram_p(x)
Definition: ri.h:2519
#define ram_section(x)
Definition: ri.h:2249
#define storage_ram(x)
Definition: ri.h:2521
#define ram_shared(x)
Definition: ri.h:2253
#define storage_return_p(x)
Definition: ri.h:2516
void add_equivalenced_values(entity e, entity eq, bool readonly)
Definition: mappings.c:107
void add_new_value(entity)
Definition: value.c:1386
void remove_entity_values(entity, bool)
Definition: value.c:1545
void add_intermediate_value(entity)
Definition: value.c:1476
void add_old_value(entity)
Definition: value.c:1440

References add_equivalenced_values(), add_intermediate_value(), add_new_value(), add_old_value(), analyzable_scalar_entity_p(), CAR, ENDP, entities_may_conflict_p(), ENTITY, entity_has_values_p(), entity_local_name(), entity_name, entity_storage, entity_type, eq, list_undefined, pips_assert, pips_debug, pips_internal_error, pips_user_warning, POP, ram_section, ram_shared, remove_entity_values(), storage_formal_p, storage_ram, storage_ram_p, storage_return_p, storage_tag, storage_to_string(), type_area_p, type_equal_p(), and type_to_string().

Referenced by add_interprocedural_new_value_entity(), add_interprocedural_value_entities(), and add_intraprocedural_value_entities_unconditionally().

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

◆ affine_increment_to_transformer()

transformer affine_increment_to_transformer ( entity  e,
Pvecteur  a 
)

Definition at line 1269 of file expression.c.

1270 {
1272 
1273  tf = affine_to_transformer(e, a, false);
1274 
1275  return tf;
1276 }
transformer affine_to_transformer(entity e, Pvecteur a, bool assignment)
Definition: expression.c:1212

References affine_to_transformer(), and transformer_undefined.

Referenced by add_loop_index_exit_value().

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

◆ affine_to_transformer()

transformer affine_to_transformer ( entity  e,
Pvecteur  a,
bool  assignment 
)

must be duplicated right now because it will be renamed and checked at the same time by value_mappings_compatible_vector_p()

Parameters
assignmentssignment

Definition at line 1212 of file expression.c.

1213 {
1215  Pvecteur ve = vect_new((Variable) e, VALUE_ONE);
1216  entity e_new = entity_to_new_value(e);
1217  entity e_old = entity_to_old_value(e);
1218  cons * tf_args = CONS(ENTITY, e_new, NIL);
1219  /* must be duplicated right now because it will be
1220  renamed and checked at the same time by
1221  value_mappings_compatible_vector_p() */
1222  Pvecteur vexpr = vect_dup(a);
1223  Pcontrainte c;
1225 
1226  pips_debug(8, "begin\n");
1227 
1228  ifdebug(9) {
1229  pips_debug(9, "\nLinearized expression:\n");
1230  vect_dump(vexpr);
1231  }
1232 
1233  if(!assignment) {
1234  vect_add_elem(&vexpr, (Variable) e, (Value) 1);
1235 
1236  ifdebug(8) {
1237  pips_debug(8, "\nLinearized expression for incrementation:\n");
1238  vect_dump(vexpr);
1239  }
1240  }
1241 
1244  ve = vect_variable_rename(ve,
1245  (Variable) e,
1246  (Variable) e_new);
1247  (void) vect_variable_rename(vexpr,
1248  (Variable) e_new,
1249  (Variable) e_old);
1250  eq = vect_substract(ve, vexpr);
1251  vect_rm(ve);
1252  vect_rm(vexpr);
1253  c = contrainte_make(eq);
1254  tf = make_transformer(tf_args,
1256  }
1257  else {
1258  vect_rm(eq);
1259  vect_rm(ve);
1260  vect_rm(vexpr);
1261  tf = transformer_undefined;
1262  }
1263 
1264  pips_debug(8, "end\n");
1265 
1266  return tf;
1267 }
transformer make_transformer(list a1, predicate a2)
Definition: ri.c:2649
predicate make_predicate(Psysteme a1)
Definition: ri.c:1820
#define VALUE_ONE
Pvecteur vect_variable_rename(Pvecteur v, Variable v_old, Variable v_new)
Pvecteur vect_variable_rename(Pvecteur v, Variable v_old, Variable v_new): rename the potential coord...
Definition: base.c:366
#define CONTRAINTE_UNDEFINED
Pcontrainte contrainte_make(Pvecteur pv)
Pcontrainte contrainte_make(Pvecteur pv): allocation et initialisation d'une contrainte avec un vecte...
Definition: alloc.c:73
void vect_dump(Pvecteur v)
void vect_dump(Pvecteur v): print sparse vector v on stderr.
Definition: io.c:304
Psysteme sc_make(Pcontrainte leg, Pcontrainte lineg)
Psysteme sc_make(Pcontrainte leg, Pcontrainte lineg): allocation et initialisation d'un systeme d'equ...
Definition: sc.c:78
entity entity_to_old_value(entity)
Definition: value.c:869
#define VECTEUR_NUL
DEFINITION DU VECTEUR NUL.
Pvecteur vect_dup(Pvecteur v_in)
Pvecteur vect_dup(Pvecteur v_in): duplication du vecteur v_in; allocation de et copie dans v_out;.
Definition: alloc.c:51
void vect_rm(Pvecteur v)
void vect_rm(Pvecteur v): desallocation des couples de v;
Definition: alloc.c:78

References CONS, contrainte_make(), CONTRAINTE_UNDEFINED, ENTITY, entity_to_new_value(), entity_to_old_value(), eq, ifdebug, make_predicate(), make_transformer(), NIL, pips_debug, sc_make(), transformer_undefined, value_mappings_compatible_vector_p(), VALUE_ONE, vect_add_elem(), vect_dump(), vect_dup(), vect_new(), vect_rm(), vect_substract(), vect_variable_rename(), and VECTEUR_NUL.

Referenced by affine_increment_to_transformer().

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

◆ all_data_to_precondition()

transformer all_data_to_precondition ( entity  m)

any variable is included.

FI: it would be nice, if only for debugging, to pass a more restricted list...

This assumes the all variables declared in a statement is also declared at the module level.

Definition at line 536 of file ri_to_preconditions.c.

537 {
538  /* FI: it would be nice, if only for debugging, to pass a more
539  restricted list...
540 
541  This assumes the all variables declared in a statement is also
542  declared at the module level. */
543  // transformer pre =
544  // data_to_prec_for_variables(m, code_declarations(entity_code(m)));
547 
548  gen_free_list(dl);
549 
550  return pre;
551 }
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
static transformer data_to_prec_for_variables(entity m, list le)
list module_to_all_declarations(entity m)
Definition: module.c:323

References data_to_prec_for_variables(), gen_free_list(), and module_to_all_declarations().

Referenced by initial_precondition().

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

◆ any_assign_operation_to_transformer()

transformer any_assign_operation_to_transformer ( entity  ,
list  ,
transformer  ,
bool   
)

◆ any_assign_to_transformer()

transformer any_assign_to_transformer ( list  args,
list  ef,
transformer  pre 
)

precondition

The lhs must be a scalar reference to perform an interesting analysis in Fortran. In C, the condition can be relaxed to take into account side effects in sub-expressions.

f ou NIL ??

if some condition was not met and transformer derivation failed

Parameters
argsrgs
eff
prere

Definition at line 3177 of file ri_to_transformers.c.

3180 {
3182  expression lhs = EXPRESSION(CAR(args));
3183  expression rhs = EXPRESSION(CAR(CDR(args)));
3184  // Take care of side effects in lhs
3185  // FI: do you want to take care of the write effect as well ?
3186 
3187  // The false read implied here does not matter because only write
3188  // effects are taken into account
3190  // FI: the rhs should be evaluated first according to the C standard
3191  transformer npre = transformer_apply(lhst, pre);
3192  // How about the side effects in rhs? It might be done below?
3193  // transformer trhs = safe_expression_to_transformer(rhs, npre);
3194  // transformer nnpre = transformer_apply(lhsr, npre);
3195  // Side-effects transformer setf
3196  // transformer seft = transformer_combine(rhst, lhst);
3197  // free_transformer(lhst); // rhst is propagated as seft
3198  // free_transformer(npre);
3199 
3200  pips_assert("2 args to assign", CDR(CDR(args))==NIL);
3201 
3202  syntax slhs = expression_syntax(lhs);
3203  /* The lhs must be a scalar reference to perform an interesting
3204  analysis in Fortran. In C, the condition can be relaxed to take
3205  into account side effects in sub-expressions. */
3206  if(syntax_reference_p(slhs)) {
3207  reference rlhs = syntax_reference(slhs);
3208  // FI: it is assumed that lhst is identity in case lhs is a reference
3209  // that leads to a defined transformer
3210  // Range of the new precondition: nprer
3211  // transformer nprer = transformer_range(npre);
3212  tf = assign_rhs_to_reflhs_to_transformer(rlhs, rhs, pre, ef);
3213  //free_transformer(nprer);
3214  }
3215  // case constant path in lhs (dereferencing, struct, array)
3216  else if (syntax_call_p(slhs) || syntax_subscript_p(slhs)) {
3219  int n = (int) gen_length(l);
3220  // FI: I wonder what happens with side effects in the rhs and
3221  // with pointer dereferencing in the rhs
3222  FOREACH(CELL, cp, l) {
3224 
3225  // example of case which is normally filter *p when p formal
3226  // parameter, or dynamic allocation of p
3228  && analyzed_reference_p(rlhs)) {
3229  ifdebug(7) {
3230  pips_debug(7, "source reference : %s\n", reference_to_string(rlhs));
3231  }
3232 
3233  transformer rt = assign_rhs_to_reflhs_to_transformer(rlhs, rhs, npre, ef/*ef ou NIL ?? */);
3234  // NL : It must have be a better way to do that but I don't know how
3235  if (transformer_undefined_p(tf))
3236  tf = rt;
3237  else {
3238  if(transformer_undefined_p(rt)) {
3239  // FI: absorbing element
3240 
3241  // FI: this is not going to work in general, because
3242  // undefined is used to perform or not the convex hull
3243  tf = transformer_undefined;
3244  }
3245  else {
3246  tf = transformer_convex_hull(tf, rt);
3247  free_transformer(rt);
3248  }
3249  }
3250  }
3251  else if(anywhere_reference_p(rlhs)) {
3252  /*
3253  list nefl = CONS(EFFECT, anywhere_effect(make_action_write_memory()), NIL);
3254  tf = effects_to_transformer(nefl);
3255  gen_full_free_list(nefl);
3256  */
3257  tf = transformer_undefined;
3258  }
3259  else if(reference_typed_anywhere_locations_p(rlhs)) {
3260  /*
3261  type t = points_to_reference_to_concrete_type(rlhs);
3262  cell c = make_anywhere_points_to_cell(t);
3263  effect nef = make_effect(c, make_action_write_memory(),
3264  make_approximation_may(), make_descriptor_none());
3265  list nefl = CONS(EFFECT, nef, NIL);
3266  tf = effects_to_transformer(nefl);
3267  gen_full_free_list(nefl);
3268  */
3269  tf = transformer_undefined;
3270  }
3271  }
3272  }
3273  }
3274  else {
3275  // if nothing else retrieve lhs and rhs transformers
3276  transformer rhst = safe_expression_to_transformer(rhs, npre);
3277  // transformer nnpre = transformer_apply(lhsr, npre);
3278  // Side-effects transformer setf
3279  tf = transformer_combine(rhst, lhst);
3280  // free_transformer(lhst); // rhst is propagated as seft, done below
3281  // free_transformer(npre); // done below
3282  tf = apply_additional_effects_to_transformer(tf, ef, true, rhs);
3283  }
3284 
3285  free_transformer(npre);
3286 
3287  /* if some condition was not met and transformer derivation failed */
3288  // This should be dead code now
3289  if(tf==transformer_undefined) {
3290  transformer tf1 = lhst;
3292  tf = transformer_combine (tf1, tf2);
3293  free_transformer(tf2); // tf1 is exported in tf
3294  // FI: previous solution, only based on effects, was much safer
3295  // and simpler ! But kills tf1 and tf2 by definition... tf =
3296  // apply_effects_to_transformer(tf, ef, true, rhs); FI: the all
3297  // assignment should be passed as expression to provide
3298  // information about the effects origin: make_binary_call(=, lhs,
3299  // rhs); lhs is more likely than rhs to explain the effects
3300  tf = apply_additional_effects_to_transformer(tf, ef, true, lhs);
3301  }
3302  else {
3303  free_transformer(lhst);
3304  }
3305 
3306  pips_debug(6,"return tf=%p\n", tf);
3307  ifdebug(6) (void) print_transformer(tf);
3308  pips_debug(6,"end\n");
3309  return tf;
3310 }
bool reference_typed_anywhere_locations_p(reference r)
test if a reference is the bottom of the lattice
void const char const char const int
reference cell_any_reference(cell)
API for reference.
Definition: effects.c:77
bool anywhere_reference_p(reference)
Definition: effects.c:378
bool pt_to_list_undefined_p(void)
points_to.c
#define CELL(x)
CELL.
Definition: effects.h:424
size_t gen_length(const list l)
Definition: list.c:150
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
string reference_to_string(reference r)
Definition: expression.c:87
#define syntax_reference_p(x)
Definition: ri.h:2728
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_call_p(x)
Definition: ri.h:2734
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define expression_syntax(x)
Definition: ri.h:1247
#define syntax_subscript_p(x)
Definition: ri.h:2743
static transformer assign_rhs_to_reflhs_to_transformer(reference rlhs, expression rhs, transformer pre, list ef)
static transformer apply_additional_effects_to_transformer(transformer tf, list el, bool apply_p, expression rhs)
Pvecteur cp
pointeur sur l'egalite ou l'inegalite courante
Definition: sc_read.c:87
bool semantics_usable_points_to_reference_p(reference rlhs, expression lhs, int n)
See if references rlhs is usable and process null, undefined and anywhere locations defined by rlhs.
Definition: expression.c:6194
transformer safe_expression_to_transformer(expression exp, transformer pre)
Definition: expression.c:5307
list semantics_expression_to_points_to_sources(expression e)
Special wrapping for the semantics analyses.
Definition: points_to.c:94
transformer transformer_combine(volatile transformer t1, transformer t2)
transformer transformer_combine(transformer t1, transformer t2): compute the composition of transform...
Definition: transformer.c:238
bool analyzed_reference_p(reference)
FI: Nelson explains the motivation for can_be_constant_path_p() but I do not understand them.
Definition: value.c:518
bool constant_path_analyzed_p(void)
Definition: value.c:330

References analyzed_reference_p(), anywhere_reference_p(), apply_additional_effects_to_transformer(), assign_rhs_to_reflhs_to_transformer(), CAR, CDR, CELL, cell_any_reference(), constant_path_analyzed_p(), cp, EXPRESSION, expression_syntax, expression_undefined, FOREACH, free_transformer(), gen_length(), ifdebug, int, NIL, pips_assert, pips_debug, print_transformer, pt_to_list_undefined_p(), reference_to_string(), reference_typed_anywhere_locations_p(), safe_expression_to_transformer(), semantics_expression_to_points_to_sources(), semantics_usable_points_to_reference_p(), syntax_call_p, syntax_reference, syntax_reference_p, syntax_subscript_p, transformer_apply(), transformer_combine(), transformer_convex_hull(), transformer_undefined, and transformer_undefined_p.

Referenced by intrinsic_to_transformer(), and intrinsic_to_transformer_list().

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

◆ any_assign_to_transformer_list()

list any_assign_to_transformer_list ( list  args,
list  ef,
transformer  pre 
)

precondition

The lhs must be a scalar reference to perform an interesting analysis

if some condition was not met and transformer derivation failed

Parameters
argsrgs
eff
prere

Definition at line 777 of file ri_to_transformer_lists.c.

780 {
781  list tl = NIL;
783  expression lhs = EXPRESSION(CAR(args));
784  expression rhs = EXPRESSION(CAR(CDR(args)));
785  syntax slhs = expression_syntax(lhs);
786 
787  pips_internal_error("Not implemented yet.");
788 
789  pips_assert("2 args to assign", CDR(CDR(args))==NIL);
790 
791  /* The lhs must be a scalar reference to perform an interesting analysis */
792  if(syntax_reference_p(slhs)) {
793  reference rlhs = syntax_reference(slhs);
794  if(ENDP(reference_indices(rlhs))) {
795  entity v = reference_variable(rlhs);
796  tf = any_scalar_assign_to_transformer(v, rhs, ef, pre);
797  }
798  }
799 
800  /* if some condition was not met and transformer derivation failed */
801  if(tf==transformer_undefined)
802  tf = effects_to_transformer(ef);
803 
804  pips_debug(6,"return tl=%p\n", tl);
805  ifdebug(6) (void) print_transformers(tl);
806  pips_debug(8,"end\n");
807  return tl;
808 }
list print_transformers(list tl)
Definition: io.c:62
#define reference_indices(x)
Definition: ri.h:2328
transformer effects_to_transformer(list e)
list of effects
transformer any_scalar_assign_to_transformer(entity v, expression rhs, list ef, transformer pre)
precondition

References any_scalar_assign_to_transformer(), CAR, CDR, effects_to_transformer(), ENDP, EXPRESSION, expression_syntax, ifdebug, NIL, pips_assert, pips_debug, pips_internal_error, print_transformers(), reference_indices, reference_variable, syntax_reference, syntax_reference_p, and transformer_undefined.

+ Here is the call graph for this function:

◆ any_basic_update_operation_to_transformer()

transformer any_basic_update_operation_to_transformer ( entity  tmp,
entity  v,
entity  op 
)

See also any_basic_update_to_transformer(), which should be based on this function.

FI: why

Parameters
tmpmp
opp

Definition at line 317 of file expression.c.

318 {
324  list args = list_undefined;
325 
327  inc = int_to_expression(1);
328  else
329  inc = int_to_expression(-1);
330 
331  n_rhs = MakeBinaryCall(plus, inc, entity_to_expression(v));
332 
333  /* FI: why*/
334  args = CONS(EXPRESSION, ve, CONS(EXPRESSION, n_rhs, NIL));
336  args,
338  false);
341  else
342  tf = transformer_add_equality(tf, v, tmp);
343  gen_full_free_list(args);
344 
345  pips_debug(6,"return tf=%p\n", tf);
346  ifdebug(6) (void) dump_transformer(tf);
347  pips_debug(8,"end\n");
348  return tf;
349 }
transformer transformer_add_equality(transformer tf, entity v1, entity v2)
Add an equality between two values (two variables?)
Definition: basic.c:436
void gen_full_free_list(list l)
Definition: genClib.c:1023
#define ENTITY_POST_DECREMENT_P(e)
#define ENTITY_POST_INCREMENT_P(e)
#define ENTITY_PRE_INCREMENT_P(e)
#define PLUS_C_OPERATOR_NAME
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
expression MakeBinaryCall(entity f, expression eg, expression ed)
Creates a call expression to a function with 2 arguments.
Definition: expression.c:354
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
transformer any_assign_operation_to_transformer(entity tmp, list args, transformer pre, bool is_internal __attribute__((unused)))
Similar to any_assign_to_transformer(), which is a simpler case.
Definition: expression.c:499

References any_assign_operation_to_transformer(), CONS, dump_transformer, entity_intrinsic(), ENTITY_POST_DECREMENT_P, ENTITY_POST_INCREMENT_P, ENTITY_PRE_INCREMENT_P, entity_to_expression(), entity_to_old_value(), EXPRESSION, expression_undefined, gen_full_free_list(), ifdebug, int_to_expression(), list_undefined, MakeBinaryCall(), NIL, pips_debug, PLUS_C_OPERATOR_NAME, transformer_add_equality(), and transformer_undefined.

Referenced by generic_unary_operation_to_transformer(), and pointer_unary_operation_to_transformer().

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

◆ any_basic_update_to_transformer()

transformer any_basic_update_to_transformer ( entity  op,
list  args,
list  ef,
transformer  pre 
)

precondition

The lhs must be a scalar reference to perform an interesting analysis No more, lhs can also be dereferencing

f ou NIL ??

if some condition was not met and transformer derivation failed

Parameters
opp
argsrgs
eff
prere

Definition at line 3525 of file ri_to_transformers.c.

3529 {
3531  expression lhs = EXPRESSION(CAR(args));
3532  syntax slhs = expression_syntax(lhs);
3533 
3534  pips_assert("1 arg for basic_update", CDR(args)==NIL);
3535 
3536  ifdebug(8) (void) print_expression(lhs);
3537 
3538  /* The lhs must be a scalar reference to perform an interesting analysis
3539  * No more, lhs can also be dereferencing
3540  */
3541  if(syntax_reference_p(slhs)) {
3542  reference rlhs = syntax_reference(slhs);
3543  tf = basic_update_reflhs_with_rhs_to_transformer(op, rlhs, lhs, pre, ef);
3544  }
3545  // case constant path in lhs (dereferencing, struct, array)
3546  else if (syntax_call_p(slhs)) {
3547  if (!pt_to_list_undefined_p()) {
3549  FOREACH(CELL, cp, l) {
3551 
3552  // example of case which is normally filter *p when p formal parameter, or dynamic allocation of p
3553  if (analyzed_reference_p(rlhs)) {
3554  entity source_lhs = reference_variable(rlhs);
3555 
3556  ifdebug(7) {
3557  pips_debug(7, "source reference : %s\n", reference_to_string(rlhs));
3558  }
3559 
3560  if (entity_null_locations_p(source_lhs)) {
3561  if (gen_length(l) == 1)
3562  pips_user_error("The pointer \"%s\" points to NULL\n", expression_to_string(lhs));
3563  else
3564  semantics_user_warning("The pointer \"%s\" can point to NULL\n", expression_to_string(lhs));
3565  } else if (entity_typed_nowhere_locations_p(source_lhs)) {
3566  if (gen_length(l) == 1)
3567  pips_user_error("The pointer %s points to undefined/indeterminate (%s)\n", expression_to_string(lhs), reference_to_string(rlhs));
3568  else
3569  semantics_user_warning("The pointer %s can points to undefined/indeterminate (%s)\n", expression_to_string(lhs), reference_to_string(rlhs));
3570  }
3571  else {
3572  // can be improve with a specific function
3573  // we will compute 2 times the path to find the cp
3574  // see assign_rhs_to_cp_to_transformer or update_cp_with_rhs_to_transformer to make basic_update_cp_with_rhs_to_transformer
3575  transformer rt = basic_update_reflhs_with_rhs_to_transformer(op, rlhs, lhs, pre, ef/*ef ou NIL ?? */);
3576  // NL : It must have be a better way to do that but I don't know how
3577  if (transformer_undefined_p(tf))
3578  tf = rt;
3579  else {
3580  tf = transformer_convex_hull(tf, rt);
3581  free_transformer(rt);
3582  }
3583  }
3584  }
3585  }
3586  }
3587  }
3588 
3589  /* if some condition was not met and transformer derivation failed */
3590  if(tf==transformer_undefined)
3591  tf = effects_to_transformer(ef);
3592 
3593  pips_debug(6,"return tf=%p\n", tf);
3594  ifdebug(6) (void) print_transformer(tf);
3595  pips_debug(8,"end\n");
3596  return tf;
3597 }
bool entity_null_locations_p(entity e)
test if an entity is the NULL POINTER
bool entity_typed_nowhere_locations_p(entity e)
test if an entity is the bottom of the lattice
#define cell_reference(x)
Definition: effects.h:469
#define cell_preference(x)
Definition: effects.h:472
#define cell_preference_p(x)
Definition: effects.h:470
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
string expression_to_string(expression e)
Definition: expression.c:77
#define preference_reference(x)
Definition: ri.h:2102
static transformer basic_update_reflhs_with_rhs_to_transformer(entity op, reference rlhs, expression rhs, transformer pre, list ef)
#define semantics_user_warning

References analyzed_reference_p(), basic_update_reflhs_with_rhs_to_transformer(), CAR, CDR, CELL, cell_preference, cell_preference_p, cell_reference, cp, effects_to_transformer(), entity_null_locations_p(), entity_typed_nowhere_locations_p(), EXPRESSION, expression_syntax, expression_to_string(), FOREACH, free_transformer(), gen_length(), ifdebug, NIL, pips_assert, pips_debug, pips_user_error, preference_reference, print_expression(), print_transformer, pt_to_list_undefined_p(), reference_to_string(), reference_variable, semantics_expression_to_points_to_sources(), semantics_user_warning, syntax_call_p, syntax_reference, syntax_reference_p, transformer_convex_hull(), transformer_undefined, and transformer_undefined_p.

Referenced by intrinsic_to_transformer(), and intrinsic_to_transformer_list().

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

◆ any_basic_update_to_transformer_list()

list any_basic_update_to_transformer_list ( entity  op,
list  args,
list  ef,
transformer  pre 
)

precondition

The lhs must be a scalar reference to perform an interesting analysis

if some condition was not met and transformer derivation failed

Parameters
opp
argsrgs
eff
prere

Definition at line 849 of file ri_to_transformer_lists.c.

853 {
854  list tl = NIL;
856  expression lhs = EXPRESSION(CAR(args));
857  syntax slhs = expression_syntax(lhs);
858 
859  pips_internal_error("Not implemented yet.");
860 
861  pips_assert("1 arg for basic_update", CDR(args)==NIL);
862 
863  /* The lhs must be a scalar reference to perform an interesting analysis */
864  if(syntax_reference_p(slhs)) {
865  reference rlhs = syntax_reference(slhs);
866  if(ENDP(reference_indices(rlhs))) {
867  entity v = reference_variable(rlhs);
871 
873  ve = int_to_expression(1);
874  else
875  ve = int_to_expression(-1);
876 
877  n_rhs = MakeBinaryCall(plus, ve, copy_expression(lhs));
878 
879  tf = any_scalar_assign_to_transformer(v, n_rhs, ef, pre);
880  free_expression(n_rhs);
881  }
882  }
883 
884  /* if some condition was not met and transformer derivation failed */
885  if(tf==transformer_undefined)
886  tf = effects_to_transformer(ef);
887 
888  pips_debug(6,"return tl=%p\n", tl);
889  ifdebug(6) (void) print_transformers(tl);
890  pips_debug(8,"end\n");
891  return tl;
892 }
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
void free_expression(expression p)
Definition: ri.c:853

References any_scalar_assign_to_transformer(), CAR, CDR, copy_expression(), effects_to_transformer(), ENDP, entity_intrinsic(), ENTITY_POST_INCREMENT_P, ENTITY_PRE_INCREMENT_P, EXPRESSION, expression_syntax, expression_undefined, free_expression(), ifdebug, int_to_expression(), MakeBinaryCall(), NIL, pips_assert, pips_debug, pips_internal_error, PLUS_C_OPERATOR_NAME, print_transformers(), reference_indices, reference_variable, syntax_reference, syntax_reference_p, and transformer_undefined.

+ Here is the call graph for this function:

◆ any_conditional_to_transformer()

transformer any_conditional_to_transformer ( entity  v,
list  args,
transformer  pre 
)

Take care of the returned value.

About a cut-and-paste of previous function, conditional_to_transformer().

Parameters
argsrgs
prere

Definition at line 5524 of file expression.c.

5527 {
5528  expression cond = EXPRESSION(CAR(args));
5529  expression te = EXPRESSION(CAR(CDR(args)));
5530  expression fe = EXPRESSION(CAR(CDR(CDR(args))));
5532  transformer ttf = condition_to_transformer(cond, pre, true);
5533  transformer t_pre = transformer_apply(ttf, pre);
5534  transformer t_pre_r = transformer_range(t_pre);
5535  transformer tet = safe_any_expression_to_transformer(v, te, t_pre_r, true);
5536  transformer ftf = condition_to_transformer(cond, pre, false);
5537  transformer f_pre = transformer_apply(ftf, pre);
5538  transformer f_pre_r = transformer_range(f_pre);
5539  transformer fet = safe_any_expression_to_transformer(v, fe, f_pre_r, true);
5540 
5541  ttf = transformer_combine(ttf, tet);
5542  ftf = transformer_combine(ftf, fet);
5543  tf = transformer_convex_hull(ttf, ftf);
5544 
5545  free_transformer(ttf);
5546  free_transformer(ftf);
5547  free_transformer(tet);
5548  free_transformer(fet);
5549  free_transformer(t_pre_r);
5550  free_transformer(f_pre_r);
5551  free_transformer(t_pre);
5552  free_transformer(f_pre);
5553 
5554  //if(transformer_undefined_p(tf))
5555  // tf = effects_to_transformer(ef);
5556  return tf;
5557 }
transformer safe_any_expression_to_transformer(entity v, expression expr, transformer pre, bool is_internal)
Always return a usable transformer.
Definition: expression.c:5156
transformer condition_to_transformer(expression cond, transformer pre, bool veracity)
To capture side effects and to add C twist for numerical conditions.
Definition: expression.c:5348
transformer transformer_range(transformer tf)
Return the range of relation tf in a newly allocated transformer.
Definition: transformer.c:714

References CAR, CDR, condition_to_transformer(), EXPRESSION, free_transformer(), safe_any_expression_to_transformer(), transformer_apply(), transformer_combine(), transformer_convex_hull(), transformer_range(), and transformer_undefined.

Referenced by integer_call_expression_to_transformer(), and pointer_call_expression_to_transformer().

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

◆ any_expression_side_effects_to_transformer()

transformer any_expression_side_effects_to_transformer ( expression  ,
transformer  ,
bool   
)

◆ any_expression_to_transformer()

transformer any_expression_to_transformer ( entity  v,
expression  expr,
transformer  pre,
bool  is_internal 
)

A set of functions to compute the transformer associated to an expression evaluated in a given context.

The choices are:

  1. Do I need the value of the expression? It seems strange but in some cases, the expression value is discarded. See for instance the C for construct.

Keyword: "any" implies that the expression value is needed

  1. In case of failure, do I need an approximate transformer based on memory effects or an undefined transformer because I want to try something else?

Keyword: "safe" implies that effects are used and that no undefined transformer is returned.

  1. In case of interprocedural call, am I ready to fail? This might be useful for the libraries "control" and "effects", but is not implemented yet.

Suggested keyword: "light"

  1. Conditional expressions require specific treatment because the bool analysis is not well linked to the integer analysis and because C uses implicit conditions: if(n) means if(n!=0).
  2. Expression lists are a special case of expression. This function may return an undefined transformers if it fails to capture the semantics of expr in the polyhedral framework.

Should basic of expression take care of this?

Assume v is a value

If we are here, it should be an enum type...

Constants, at least, could be typed coerced

Redundant with explicit type coercion also available in PIPS

To be done later

PIPS does not represent negative constants: call to unary_minus

PIPS does not represent complex constants: call to CMPLX

Only constant string are processed

The overloading is supposed to have been lifted by basic_of_expression()

enum type are analyzed like int

This function is called from the region analysis, with extended expressions such as "*", the unbounded expression.

It might be interesting to go further in case the comma operator is used

No need to link the returned value as it must be cast to the proper type.

tf may be transformer_undefined when no information is derived

Parameters
exprxpr
prere
is_internals_internal

Definition at line 4993 of file expression.c.

4998 {
5000  basic be = basic_of_expression(expr);
5002 
5003  if(basic_typedef_p(be)) {
5004  entity te = basic_typedef(be);
5005  type nte = ultimate_type(entity_type(te));
5006 
5007  pips_assert("nte is of type variable", type_variable_p(nte));
5008 
5009  /* Should basic of expression take care of this? */
5010  pips_debug(8, "Fix basic be\n");
5011 
5012  free_basic(be);
5014  }
5015 
5016  ifdebug(8) {
5017  pips_debug(8, "begin for entity %s of type %s and %s expression ",
5018  entity_local_name(v),
5019  basic_to_string(bv), basic_to_string(be));
5020  print_expression(expr);
5021  }
5022 
5023  /* Assume v is a value */
5024  if( (basic_tag(bv)==basic_tag(be))
5025  || (basic_float_p(bv) && basic_int_p(be))
5026  || (basic_derived_p(bv) && basic_int_p(be))
5027  || (basic_derived_p(be) && basic_int_p(bv))
5028  || (basic_logical_p(bv) && basic_int_p(be))
5029  || (basic_logical_p(be) && basic_int_p(bv))
5030  || (basic_pointer_p(bv) && basic_int_p(be))) {
5031  switch(basic_tag(be)) {
5032  case is_basic_int:
5033  if(integer_analyzed_p()) {
5034  if(basic_int_p(bv)) {
5035  tf = integer_expression_to_transformer(v, expr, pre, is_internal);
5036  }
5037  else if(basic_derived_p(bv)) {
5038  /* If we are here, it should be an enum type... */
5039  tf = integer_expression_to_transformer(v, expr, pre, is_internal);
5040  }
5041  else if(basic_logical_p(bv)) {
5042  tf = logical_expression_to_transformer(v, expr, pre, is_internal);
5043  }
5044  else if(basic_pointer_p(bv)) {
5045  //tf = integer_expression_to_transformer(v, expr, pre, is_internal);
5046  // arithmetic for pointer
5047  if(pointer_analyzed_p())
5048  tf = pointer_expression_to_transformer(v, expr, pre, is_internal);
5049  }
5050  else {
5051  semantics_user_warning("Integer expression assigned to float value\n"
5052  "Apply PIPS type checker for better results\n");
5053  /* Constants, at least, could be typed coerced */
5054  /* Redundant with explicit type coercion also available in PIPS */
5055  /* To be done later */
5056  }
5057  }
5058  break;
5059  case is_basic_logical:
5060  if(basic_logical_p(bv) && boolean_analyzed_p())
5061  tf = logical_expression_to_transformer(v, expr, pre, is_internal);
5062  else if(basic_int_p(bv)) { // We should check that integers are analyzed...
5063  tf = integer_expression_to_transformer(v, expr, pre, is_internal);
5064  }
5065  break;
5066  case is_basic_float:
5067  /* PIPS does not represent negative constants: call to unary_minus */
5068  if(float_analyzed_p())
5069  tf = float_expression_to_transformer(v, expr, pre, is_internal);
5070  break;
5071  case is_basic_pointer:
5072  if(pointer_analyzed_p())
5073  tf = pointer_expression_to_transformer(v, expr, pre, is_internal);
5074  break;
5075  case is_basic_complex:
5076  /* PIPS does not represent complex constants: call to CMPLX */
5077  break;
5078  case is_basic_string:
5079  /* Only constant string are processed */
5080  if(string_analyzed_p())
5081  tf = string_expression_to_transformer(v, expr);
5082  break;
5083  case is_basic_overloaded: {
5084  /* The overloading is supposed to have been lifted by
5085  basic_of_expression() */
5087  tf = transformer_identity();
5088  else
5089  pips_internal_error("illegal overloaded type for an expression");
5090  break;
5091  }
5092  case is_basic_derived: {
5093  entity de = basic_derived(be);
5094  type det = ultimate_type(entity_type(de));
5095  if(type_enum_p(det)) {
5096  /* enum type are analyzed like int */
5097  tf = integer_expression_to_transformer(v, expr, pre, is_internal);
5098  }
5099  else {
5100  pips_internal_error("entities of type \"derived\" that are not \"enum\" cannot be analyzed");
5101  }
5102  break;
5103  }
5104  case is_basic_typedef:
5105  pips_internal_error("entities of type \"typedef\" cannot be analyzed");
5106  break;
5107  default:
5108  pips_internal_error("unknown basic b=%d", basic_tag(be));
5109  }
5110  }
5111  else {
5112  if(!basic_overloaded_p(be)) {
5113  semantics_user_warning("Implicit type coercion between variable \"%s\" of type \"%s\" and "
5114  "expression \"%s\" of type \"%s\" may reduce semantic analysis accuracy.\n"
5115  "You might apply 'type_checker' to explicit all type coercions.\n",
5116  entity_user_name(v),
5117  basic_to_string(bv),
5118  expression_to_string(expr),
5119  basic_to_string(be));
5120  }
5121  else if(!unbounded_expression_p(expr)) {
5122  /* This function is called from the region analysis, with
5123  * extended expressions such as "*", the unbounded
5124  * expression.
5125  */
5127  "expression \"%s\" with overloaded type may reduce semantic analysis accuracy for variable \"%s\" of type \"%s\".\n"
5128  "You might apply 'type_checker' to explicit all type coercions.\n",
5129  expression_to_string(expr),
5130  entity_user_name(v),
5131  basic_to_string(bv));
5132  }
5133  /* It might be interesting to go further in case the comma operator is used */
5134  if(comma_expression_p(expr)) {
5135  call c = syntax_call(expression_syntax(expr));
5136  list expr_l = call_arguments(c);
5137 
5138  /* No need to link the returned value as it must be cast to the
5139  proper type. */
5140  tf = expressions_to_transformer(expr_l, pre);
5141  }
5142  }
5143 
5144  /* tf may be transformer_undefined when no information is derived */
5145  ifdebug(1) {
5146  if(!transformer_undefined_p(pre))
5147  pips_assert("No obvious aliasing between tf and pre", tf!=pre);
5148  }
5149  pips_debug(8, "end with tf=%p\n", tf);
5150 
5151  return tf;
5152 }
basic copy_basic(basic p)
BASIC.
Definition: ri.c:104
void free_basic(basic p)
Definition: ri.c:107
transformer transformer_identity()
Allocate an identity transformer.
Definition: basic.c:110
#define ENTITY_CONTINUE_P(e)
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
bool expression_call_p(expression e)
Definition: expression.c:415
call expression_call(expression e)
Definition: expression.c:445
bool comma_expression_p(expression e)
Definition: expression.c:830
bool unbounded_expression_p(expression e)
Definition: expression.c:4329
#define type_enum_p(x)
Definition: ri.h:2968
@ is_basic_derived
Definition: ri.h:579
@ is_basic_string
Definition: ri.h:576
@ is_basic_float
Definition: ri.h:572
@ is_basic_pointer
Definition: ri.h:578
@ is_basic_overloaded
Definition: ri.h:574
@ is_basic_int
Definition: ri.h:571
@ is_basic_logical
Definition: ri.h:573
@ is_basic_typedef
Definition: ri.h:580
@ is_basic_complex
Definition: ri.h:575
#define basic_int_p(x)
Definition: ri.h:614
#define basic_derived(x)
Definition: ri.h:640
#define basic_typedef_p(x)
Definition: ri.h:641
#define basic_pointer_p(x)
Definition: ri.h:635
#define basic_derived_p(x)
Definition: ri.h:638
#define basic_overloaded_p(x)
Definition: ri.h:623
#define basic_typedef(x)
Definition: ri.h:643
#define syntax_call(x)
Definition: ri.h:2736
#define basic_logical_p(x)
Definition: ri.h:620
#define basic_float_p(x)
Definition: ri.h:617
transformer pointer_expression_to_transformer(entity v, expression expr, transformer pre, bool is_internal)
Definition: expression.c:4582
transformer expressions_to_transformer(list expl, transformer pre)
Compute the transformer associated to a list of expressions such as "i=0, j = 1;".
Definition: expression.c:5722
transformer string_expression_to_transformer(entity v, expression rhs)
Definition: expression.c:3994
transformer integer_expression_to_transformer(entity v, expression expr, transformer pre, bool is_internal)
Do check wrt to value mappings...
Definition: expression.c:3476
transformer float_expression_to_transformer(entity v, expression rhs, transformer pre, bool is_internal)
Definition: expression.c:4153
transformer logical_expression_to_transformer(entity v, expression rhs, transformer pre, bool is_internal)
Could be used to compute preconditions too.
Definition: expression.c:3938
bool pointer_analyzed_p(void)
Definition: value.c:325
bool integer_analyzed_p(void)
Definition: value.c:300
bool boolean_analyzed_p(void)
Definition: value.c:305
bool float_analyzed_p(void)
Definition: value.c:315
bool string_analyzed_p(void)
Definition: value.c:310

References basic_derived, basic_derived_p, basic_float_p, basic_int_p, basic_logical_p, basic_of_expression(), basic_overloaded_p, basic_pointer_p, basic_tag, basic_to_string(), basic_typedef, basic_typedef_p, boolean_analyzed_p(), call_arguments, call_function, comma_expression_p(), copy_basic(), ENTITY_CONTINUE_P, entity_local_name(), entity_type, entity_user_name(), expression_call(), expression_call_p(), expression_syntax, expression_to_string(), expressions_to_transformer(), float_analyzed_p(), float_expression_to_transformer(), free_basic(), ifdebug, integer_analyzed_p(), integer_expression_to_transformer(), is_basic_complex, is_basic_derived, is_basic_float, is_basic_int, is_basic_logical, is_basic_overloaded, is_basic_pointer, is_basic_string, is_basic_typedef, logical_expression_to_transformer(), pips_assert, pips_debug, pips_internal_error, pointer_analyzed_p(), pointer_expression_to_transformer(), print_expression(), semantics_user_warning, string_analyzed_p(), string_expression_to_transformer(), syntax_call, transformer_identity(), transformer_undefined, transformer_undefined_p, type_enum_p, type_variable, type_variable_p, ultimate_type(), unbounded_expression_p(), and variable_basic.

Referenced by add_formal_to_actual_bindings(), any_assign_operation_to_transformer(), any_scalar_assign_to_transformer_list(), any_scalar_assign_to_transformer_without_effect(), assigned_expression_to_transformer(), assigned_expression_to_transformer_list(), c_data_to_prec_for_variables(), c_return_to_transformer(), expression_to_transformer(), fortran_user_call_to_transformer(), generic_abs_to_transformer(), generic_minmax_to_transformer(), loop_bound_evaluation_to_transformer(), safe_any_expression_to_transformer(), and unary_minus_operation_to_transformer().

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

◆ any_expressions_side_effects_to_transformer()

transformer any_expressions_side_effects_to_transformer ( list  el,
transformer  p,
bool  is_internal 
)

same as any_expression_side_effects_to_transformer() but for a list of expressions

Parameters
ell
is_internals_internal

Definition at line 4921 of file expression.c.

4922 {
4924  FOREACH(EXPRESSION, e, el) {
4925  transformer etf =
4926  any_expression_side_effects_to_transformer(e, p, is_internal);
4927  if(transformer_undefined_p(tf))
4928  tf = etf;
4929  else {
4930  tf = transformer_combine(tf, etf);
4931  free_transformer(etf);
4932  }
4933  }
4934  return tf;
4935 }
transformer any_expression_side_effects_to_transformer(expression e, transformer p, bool is_internal __attribute__((unused)))
The value of the expression is irrelevant, but its sub-expressions may generate a transformer.
Definition: expression.c:4845

References any_expression_side_effects_to_transformer(), EXPRESSION, FOREACH, free_transformer(), transformer_combine(), transformer_undefined, and transformer_undefined_p.

Referenced by any_expression_side_effects_to_transformer().

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

◆ any_expressions_to_transformer()

transformer any_expressions_to_transformer ( entity  v,
list  expl,
transformer  pre 
)

Compute the transformer associated to a list of expressions such as "i=0, j = 1;".

The value returned is linked to v.

To be merged with the previous function.

el is an over-appoximation; should be replaced by a safe_expression_to_transformer() taking care of computing the precise effects of exp instead of using the effects of expl.

Parameters
explxpl
prere

Definition at line 5754 of file expression.c.

5757 {
5761  expression l_exp = EXPRESSION(CAR(gen_last(expl)));
5762 
5763  FOREACH(EXPRESSION, exp, expl) {
5764  /* el is an over-appoximation; should be replaced by a
5765  safe_expression_to_transformer() taking care of computing the
5766  precise effects of exp instead of using the effects of expl. */
5767  transformer ctf = (exp==l_exp)?
5768  safe_any_expression_to_transformer(v, exp, cpre, false) :
5772 
5773  tf = transformer_combine(tf, ctf);
5774  tf = transformer_normalize(tf, 2);
5775  npre = transformer_apply(ctf, cpre);
5776  npre_r = transformer_range(npre);
5777  npre_r = transformer_normalize(npre_r, 2);
5778  free_transformer(cpre);
5779  free_transformer(npre);
5780  free_transformer(ctf);
5781  cpre = npre_r;
5782  }
5783  free_transformer(cpre);
5784  return tf;
5785 }
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578
transformer transformer_normalize(transformer t, int level)
Eliminate (some) rational or integer redundancy.
Definition: transformer.c:932
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207

References CAR, exp, EXPRESSION, FOREACH, free_transformer(), gen_last(), safe_any_expression_to_transformer(), safe_expression_to_transformer(), transformer_apply(), transformer_combine(), transformer_identity(), transformer_normalize(), transformer_range(), transformer_undefined, and transformer_undefined_p.

Referenced by integer_call_expression_to_transformer(), and pointer_call_expression_to_transformer().

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

◆ any_loop_to_k_transformer()

transformer any_loop_to_k_transformer ( transformer  ,
transformer  ,
transformer  ,
statement  ,
list  ,
transformer  ,
int   
)

loop.c

◆ any_loop_to_postcondition()

transformer any_loop_to_postcondition ( statement  body,
transformer  t_init,
transformer  t_enter,
transformer  t_skip,
transformer  t_body_star,
transformer  t_body,
transformer  t_next,
transformer  t_inc,
transformer  t_exit,
transformer  pre 
)

The precondition to propagate in the body is:

p_body = (t_init ; t_enter)(pre) + (t_body_star ; t_body ; t_next) (pre)

The loop postcondition to return is:

post = (t_init ; t_skip)(pre) + (t_body_star ; t_body ; t_inc ; t_exit) (pre)

To restrict the state at the beginning of the last iteration: should be part of t_body_star

Decompose the computation of p_body

Decompose the computation of post

a_post should be used because it is more accurate than direct recomputation, but we chose for the time being to recompute post entirely

Get rid of now useless transformers

Parameters
bodyody
t_init_init
t_enter_enter
t_skip_skip
t_body_star_body_star
t_body_body
t_next_next
t_inc_inc
t_exit_exit
prere

Definition at line 2634 of file loop.c.

2644 {
2645  /* The precondition to propagate in the body is:
2646  *
2647  * p_body = (t_init ; t_enter)(pre) + (t_body_star ; t_body ; t_next) (pre)
2648  *
2649  * The loop postcondition to return is:
2650  *
2651  * post = (t_init ; t_skip)(pre) + (t_body_star ; t_body ; t_inc ; t_exit) (pre)
2652  */
2655  /* To restrict the state at the beginning of the last iteration:
2656  should be part of t_body_star */
2657  //transformer post_enter = transformer_range(t_enter);
2658  //transformer post_continue = transformer_range(t_next);
2659  //transformer pre_iteration = transformer_convex_hull(post_enter, post_continue);
2660  /* Decompose the computation of p_body */
2661  transformer p_body_1 = transformer_apply(t_enter, transformer_apply(t_init, pre));
2662  transformer p_body_2 = transformer_apply(t_body_star, pre);
2663  //transformer p_body_3 = transformer_apply(pre_iteration, p_body_2);
2664  transformer p_body_4 = transformer_apply(t_body, p_body_2);
2665  transformer p_body_5 = transformer_apply(t_next, p_body_4);
2667  /* Decompose the computation of post */
2668  transformer post_1 = transformer_apply(t_skip, transformer_apply(t_init, pre));
2669  transformer post_2 = transformer_apply(t_body_star, pre);
2670  //transformer post_3 = transformer_apply(pre_iteration, post_2);
2671  transformer post_4 = transformer_apply(t_body, post_2);
2672  transformer post_5 = transformer_apply(t_inc, post_4);
2673  transformer post_6 = transformer_apply(t_exit, post_5);
2674 
2675  p_body = transformer_convex_hull(p_body_1, p_body_5);
2676  a_post = statement_to_postcondition(p_body, body);
2677 
2678  /* a_post should be used because it is more accurate than direct
2679  recomputation, but we chose for the time being to recompute post
2680  entirely */
2681  post = transformer_convex_hull(post_1, post_6);
2682 
2683  /* Get rid of now useless transformers */
2684 
2685  free_transformer(a_post);
2686 
2687  //free_transformer(post_enter);
2688  //free_transformer(post_continue);
2689  //free_transformer(pre_iteration);
2690 
2691  free_transformer(p_body_1);
2692  free_transformer(p_body_2);
2693  //free_transformer(p_body_3);
2694  free_transformer(p_body_4);
2695  free_transformer(p_body_5);
2696 
2697  free_transformer(post_1);
2698  free_transformer(post_2);
2699  //free_transformer(post_3);
2700  free_transformer(post_4);
2701  free_transformer(post_5);
2702  free_transformer(post_6);
2703 
2704  return post;
2705 }
transformer statement_to_postcondition(transformer, statement)
end of the non recursive section

References free_transformer(), statement_to_postcondition(), transformer_apply(), transformer_convex_hull(), and transformer_undefined.

Referenced by forloop_to_postcondition(), and repeatloop_to_postcondition().

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

◆ any_loop_to_transformer()

transformer any_loop_to_transformer ( transformer  ,
transformer  ,
transformer  ,
statement  ,
list  ,
transformer   
)

◆ any_scalar_assign_to_transformer()

transformer any_scalar_assign_to_transformer ( entity  v,
expression  rhs,
list  ef,
transformer  pre 
)

precondition

Parameters
rhshs
eff
prere

Definition at line 2832 of file ri_to_transformers.c.

2836 {
2838 
2839  if(transformer_undefined_p(tf))
2840  tf = effects_to_transformer(ef);
2841 
2842  return tf;
2843 }
transformer any_scalar_assign_to_transformer_without_effect(entity v, expression rhs, transformer pre)
assign to the scalar variable v the expression rhs (a scalar variable has a basic type; it cannot be ...

References any_scalar_assign_to_transformer_without_effect(), effects_to_transformer(), and transformer_undefined_p.

Referenced by add_loop_index_initialization(), any_assign_to_transformer_list(), any_basic_update_to_transformer_list(), any_update_to_transformer_list(), assign_rhs_to_cp_to_transformer(), assign_rhs_to_reflhs_to_transformer(), basic_update_reflhs_with_rhs_to_transformer(), loop_initialization_to_transformer(), and update_reflhs_with_rhs_to_transformer().

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

◆ any_scalar_assign_to_transformer_list()

list any_scalar_assign_to_transformer_list ( entity  v,
expression  rhs,
list  ef,
transformer  pre 
)

precondition

Is it standard compliant? The assigned variable is modified by the rhs.

Take care of aliasing

tf = transformer_value_substitute(tf, v_new, v_old);

Parameters
rhshs
eff
prere

Definition at line 709 of file ri_to_transformer_lists.c.

713 {
714  list tl = NIL;
716 
717  pips_internal_error("Not implemented yet.");
718 
719  if(entity_has_values_p(v)) {
720  entity v_new = entity_to_new_value(v);
721  entity v_old = entity_to_old_value(v);
723 
724  tf = any_expression_to_transformer(tmp, rhs, pre, true);
725 
726  if(!transformer_undefined_p(tf)) {
727 
728  pips_debug(9, "A transformer has been obtained:\n");
729  ifdebug(9) dump_transformer(tf);
730 
732  /* Is it standard compliant? The assigned variable is modified by the rhs. */
733  transformer teq = simple_equality_to_transformer(v, tmp, true);
734  string s = expression_to_string(rhs);
735 
736  semantics_user_warning("Variable \"%s\" in lhs is uselessly or illegally updated by rhs '%s;'\n",
737  entity_user_name(v), s);
738  // entity_local_name(v), s);
739 
740  free(s);
741 
742  tf = transformer_combine(tf, teq);
743  free_transformer(teq);
744  }
745  else {
746  /* Take care of aliasing */
747  entity v_repr = value_to_variable(v_new);
748 
749  /* tf = transformer_value_substitute(tf, v_new, v_old); */
750  tf = transformer_value_substitute(tf, v_new, v_old);
751 
752  pips_debug(9,"After substitution v_new=%s -> v_old=%s\n",
753  entity_local_name(v_new), entity_local_name(v_old));
754 
755  tf = transformer_value_substitute(tf, tmp, v_new);
756 
757  pips_debug(9,"After substitution tmp=%s -> v_new=%s\n",
758  entity_local_name(tmp), entity_local_name(v_new));
759 
761  }
762  }
763  if(!transformer_undefined_p(tf)) {
765  pips_debug(9, "After temporary value projection, tf=%p:\n", tf);
766  ifdebug(9) dump_transformer(tf);
767  }
769  }
770 
772  tf = effects_to_transformer(ef);
773 
774  return tl;
775 }
bool entity_is_argument_p(entity e, cons *args)
Definition: arguments.c:150
transformer transformer_add_modified_variable(transformer tf, entity var)
FI: this function does not end up with a consistent transformer because the old value is not added to...
Definition: basic.c:889
void free(void *)
#define transformer_arguments(x)
Definition: ri.h:2871
return(s1)
transformer transformer_value_substitute(transformer t, entity e1, entity e2)
transformer transformer_value_substitute(transformer t, entity e1, entity e2): if e2 does not appear ...
Definition: transformer.c:1993
transformer transformer_temporary_value_projection(transformer tf)
Definition: transformer.c:1149
transformer simple_equality_to_transformer(entity e, entity f, bool assignment)
e and f are assumed to be values, Type independent.
Definition: transformer.c:58
void reset_temporary_value_counter(void)
Definition: value.c:250

References any_expression_to_transformer(), dump_transformer, effects_to_transformer(), entity_has_values_p(), entity_is_argument_p(), entity_local_name(), entity_to_new_value(), entity_to_old_value(), entity_type, entity_user_name(), expression_to_string(), free(), free_transformer(), ifdebug, make_local_temporary_value_entity(), NIL, pips_debug, pips_internal_error, reset_temporary_value_counter(), semantics_user_warning, simple_equality_to_transformer(), transformer_add_modified_variable(), transformer_arguments, transformer_combine(), transformer_temporary_value_projection(), transformer_undefined, transformer_undefined_p, transformer_value_substitute(), ultimate_type(), and value_to_variable().

+ Here is the call graph for this function:

◆ any_scalar_assign_to_transformer_without_effect()

transformer any_scalar_assign_to_transformer_without_effect ( entity  v,
expression  rhs,
transformer  pre 
)

assign to the scalar variable v the expression rhs (a scalar variable has a basic type; it cannot be an array, a struct or a union; it can be an enum) WARNING : this function can return transformer_undefined

Parameters
ventity/variable to be assign
rhsexpression/value to assign
preprecondition, transformer already present
Returns
transformer_undefined or transformer with the scalar assignment precondition

Is it standard compliant? The assigned variable is modified by the rhs.

Take care of aliasing

tf = transformer_value_substitute(tf, v_new, v_old);

Parameters
rhshs
prere

Definition at line 2766 of file ri_to_transformers.c.

2769 {
2771 
2772  if(entity_has_values_p(v)) {
2773  entity v_new = entity_to_new_value(v);
2774  entity v_old = entity_to_old_value(v);
2776 
2777  tf = any_expression_to_transformer(tmp, rhs, pre, true);
2778 
2779  if(!transformer_undefined_p(tf)) {
2780 
2781  ifdebug(8) {
2782  pips_debug(8, "A transformer has been obtained:\n");
2783  dump_transformer(tf);
2784  }
2785 
2787  /* Is it standard compliant? The assigned variable is modified by the rhs. */
2788  transformer teq = simple_equality_to_transformer(v, tmp, true);
2789  string s = expression_to_string(rhs);
2790 
2791  semantics_user_warning("Variable \"%s\" in lhs is uselessly or "
2792  "illegally updated by rhs '%s'\n",
2793  entity_user_name(v), s);
2794  // entity_local_name(v), s);
2795 
2796  free(s);
2797 
2798  tf = transformer_combine(tf, teq);
2799  free_transformer(teq);
2800  }
2801  else {
2802  /* Take care of aliasing */
2803  entity v_repr = value_to_variable(v_new);
2804 
2805  /* tf = transformer_value_substitute(tf, v_new, v_old); */
2806  tf = transformer_value_substitute(tf, v_new, v_old);
2807 
2808  pips_debug(8,"After substitution v_new=%s -> v_old=%s\n",
2809  entity_local_name(v_new), entity_local_name(v_old));
2810  ifdebug(8) dump_transformer(tf);
2811 
2812  tf = transformer_value_substitute(tf, tmp, v_new);
2813 
2814  pips_debug(8,"After substitution tmp=%s -> v_new=%s\n",
2815  entity_local_name(tmp), entity_local_name(v_new));
2816  ifdebug(8) dump_transformer(tf);
2817 
2819  }
2820  }
2821  if(!transformer_undefined_p(tf)) {
2823  pips_debug(8, "After temporary value projection, tf=%p:\n", tf);
2824  ifdebug(8) dump_transformer(tf);
2825  }
2827  }
2828 
2829  return tf;
2830 }

References any_expression_to_transformer(), dump_transformer, entity_has_values_p(), entity_is_argument_p(), entity_local_name(), entity_to_new_value(), entity_to_old_value(), entity_type, entity_user_name(), expression_to_string(), free(), free_transformer(), ifdebug, make_local_temporary_value_entity(), pips_debug, reset_temporary_value_counter(), semantics_user_warning, simple_equality_to_transformer(), transformer_add_modified_variable(), transformer_arguments, transformer_combine(), transformer_temporary_value_projection(), transformer_undefined, transformer_undefined_p, transformer_value_substitute(), ultimate_type(), and value_to_variable().

Referenced by any_scalar_assign_to_transformer().

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

◆ any_update_to_transformer()

transformer any_update_to_transformer ( entity  op,
list  args,
list  ef,
transformer  pre 
)

precondition

The lhs must be a scalar reference to perform an interesting analysis No more, lhs can also be dereferencing

f ou NIL ??

if some condition was not met and transformer derivation failed

Parameters
opp
argsrgs
eff
prere

Definition at line 3401 of file ri_to_transformers.c.

3405 {
3407  expression lhs = EXPRESSION(CAR(args));
3408  expression rhs = EXPRESSION(CAR(CDR(args)));
3409  syntax slhs = expression_syntax(lhs);
3410 
3411  pips_assert("2 args for regular update", CDR(CDR(args))==NIL);
3412 
3413  /* The lhs must be a scalar reference to perform an interesting analysis
3414  * No more, lhs can also be dereferencing
3415  */
3416  if(syntax_reference_p(slhs)) {
3417  reference rlhs = syntax_reference(slhs);
3418  tf = update_reflhs_with_rhs_to_transformer(op, rlhs, rhs, pre, ef);
3419  }
3420  // case constant path in lhs (dereferencing, struct, array)
3421  else if (syntax_call_p(slhs)) {
3422  if (!pt_to_list_undefined_p()) {
3424  FOREACH(CELL, cp, l) {
3426 
3427  // example of case which is normally filter *p when p formal parameter, or dynamic allocation of p
3428  if (analyzed_reference_p(rlhs)) {
3429  entity source_lhs = reference_variable(rlhs);
3430 
3431  ifdebug(7) {
3432  pips_debug(7, "source reference : %s\n", reference_to_string(rlhs));
3433  }
3434 
3435  if (entity_null_locations_p(source_lhs)) {
3436  if (gen_length(l) == 1)
3437  pips_user_error("The pointer %s points to NULL\n", expression_to_string(lhs));
3438  else
3439  semantics_user_warning("The pointer %s can points to NULL\n", expression_to_string(lhs));
3440  } else if (entity_typed_nowhere_locations_p(source_lhs)) {
3441  if (gen_length(l) == 1)
3442  pips_user_error("The pointer %s points to undefined/indeterminate (%s)\n", expression_to_string(lhs), reference_to_string(rlhs));
3443  else
3444  semantics_user_warning("The pointer %s can points to undefined/indeterminate (%s)\n", expression_to_string(lhs), reference_to_string(rlhs));
3445  }
3446  else {
3447  transformer rt = update_reflhs_with_rhs_to_transformer(op, rlhs, rhs, pre, ef/*ef ou NIL ?? */);
3448  // NL : It must have be a better way to do that but I don't know how
3449  if (transformer_undefined_p(tf))
3450  tf = rt;
3451  else {
3452  tf = transformer_convex_hull(tf, rt);
3453  free_transformer(rt);
3454  }
3455  }
3456  }
3457  }
3458  }
3459  }
3460 
3461  /* if some condition was not met and transformer derivation failed */
3462  if(tf==transformer_undefined)
3463  tf = effects_to_transformer(ef);
3464 
3465  pips_debug(6,"return tf=%p\n", tf);
3466  ifdebug(6) (void) print_transformer(tf);
3467  pips_debug(8,"end\n");
3468  return tf;
3469 }
static transformer update_reflhs_with_rhs_to_transformer(entity op, reference rlhs, expression rhs, transformer pre, list ef)

References analyzed_reference_p(), CAR, CDR, CELL, cell_preference, cell_preference_p, cell_reference, cp, effects_to_transformer(), entity_null_locations_p(), entity_typed_nowhere_locations_p(), EXPRESSION, expression_syntax, expression_to_string(), FOREACH, free_transformer(), gen_length(), ifdebug, NIL, pips_assert, pips_debug, pips_user_error, preference_reference, print_transformer, pt_to_list_undefined_p(), reference_to_string(), reference_variable, semantics_expression_to_points_to_sources(), semantics_user_warning, syntax_call_p, syntax_reference, syntax_reference_p, transformer_convex_hull(), transformer_undefined, transformer_undefined_p, and update_reflhs_with_rhs_to_transformer().

Referenced by intrinsic_to_transformer(), and intrinsic_to_transformer_list().

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

◆ any_update_to_transformer_list()

list any_update_to_transformer_list ( entity  op,
list  args,
list  ef,
transformer  pre 
)

precondition

The lhs must be a scalar reference to perform an interesting analysis

if some condition was not met and transformer derivation failed

Parameters
opp
argsrgs
eff
prere

Definition at line 810 of file ri_to_transformer_lists.c.

814 {
815  list tl = NIL;
817  expression lhs = EXPRESSION(CAR(args));
818  expression rhs = EXPRESSION(CAR(CDR(args)));
819  syntax slhs = expression_syntax(lhs);
820 
821  pips_internal_error("Not implemented yet.");
822 
823  pips_assert("2 args for regular update", CDR(CDR(args))==NIL);
824 
825  /* The lhs must be a scalar reference to perform an interesting analysis */
826  if(syntax_reference_p(slhs)) {
827  reference rlhs = syntax_reference(slhs);
828  if(ENDP(reference_indices(rlhs))) {
829  entity v = reference_variable(rlhs);
832  expression n_rhs = MakeBinaryCall(sop, ve, copy_expression(rhs));
833 
834  tf = any_scalar_assign_to_transformer(v, n_rhs, ef, pre);
835  free_expression(n_rhs);
836  }
837  }
838 
839  /* if some condition was not met and transformer derivation failed */
840  if(tf==transformer_undefined)
841  tf = effects_to_transformer(ef);
842 
843  pips_debug(6,"return tl=%p\n", tl);
844  ifdebug(6) (void) print_transformers(tl);
845  pips_debug(8,"end\n");
846  return tl;
847 }
entity update_operator_to_regular_operator(entity op)
Returns the binary operator associated to a C update operator such as +=.
Definition: entity.c:2154

References any_scalar_assign_to_transformer(), CAR, CDR, copy_expression(), effects_to_transformer(), ENDP, entity_to_expression(), EXPRESSION, expression_syntax, free_expression(), ifdebug, MakeBinaryCall(), NIL, pips_assert, pips_debug, pips_internal_error, print_transformers(), reference_indices, reference_variable, syntax_reference, syntax_reference_p, transformer_undefined, and update_operator_to_regular_operator().

+ Here is the call graph for this function:

◆ any_user_call_site_to_transformer()

transformer any_user_call_site_to_transformer ( entity  ,
list  ,
transformer  ,
list   
)

◆ apply_array_effect_to_transformer()

transformer apply_array_effect_to_transformer ( transformer  ,
effect  ,
bool   
)

◆ array_elements_substitution_in_transformer()

transformer array_elements_substitution_in_transformer ( transformer  ,
entity  ,
type  ,
expression  ,
transformer  ,
list  ,
bool   
)

◆ assign_operation_to_transformer()

transformer assign_operation_to_transformer ( entity  val,
expression  lhs,
expression  rhs,
transformer  pre 
)

Returns an undefined transformer in case of failure.

&& integer_scalar_entity_p(e)

Parameters
valal
lhshs
rhshs
prere

Definition at line 2737 of file expression.c.

2741 {
2743 
2744  pips_debug(8,"begin\n");
2745 
2746  if(expression_reference_p(lhs)) {
2748 
2749  if(entity_has_values_p(e) /* && integer_scalar_entity_p(e) */) {
2750  entity ev = entity_to_new_value(e);
2751  //transformer teq = simple_equality_to_transformer(val, ev, true);
2752  tf = assigned_expression_to_transformer(ev, rhs, pre);
2753  if(!transformer_undefined_p(tf))
2754  tf = transformer_add_equality(tf, val, ev);
2755  //tf = transformer_combine(tf, teq);
2756  //free_transformer(teq);
2757  }
2758  }
2759 
2760  pips_debug(6,"return tf=%lx\n", (unsigned long)tf);
2761  ifdebug(6) (void) dump_transformer(tf);
2762  pips_debug(8,"end\n");
2763  return tf;
2764 }
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
transformer assigned_expression_to_transformer(entity v, expression expr, transformer pre)
transformer assigned_expression_to_transformer(entity e, expression expr, list ef): returns a transfo...

References assigned_expression_to_transformer(), dump_transformer, entity_has_values_p(), entity_to_new_value(), expression_reference_p(), expression_syntax, ifdebug, pips_debug, reference_variable, syntax_reference, transformer_add_equality(), transformer_undefined, and transformer_undefined_p.

Referenced by float_binary_operation_to_transformer(), integer_binary_operation_to_transformer(), logical_binary_function_to_transformer(), and pointer_binary_operation_to_transformer().

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

◆ assigned_expression_to_transformer()

transformer assigned_expression_to_transformer ( entity  v,
expression  expr,
transformer  pre 
)

transformer assigned_expression_to_transformer(entity e, expression expr, list ef): returns a transformer abstracting the effect of assignment "e = expr" when possible, transformer_undefined otherwise.

Note: it might be better to distinguish further between e and expr and to return a transformer stating that e is modified when e is accepted for semantics analysis.

if the assigned variable is also assigned by the expression as in i = (i = 2) + 1, transformer_value_substitute() cannot be used right away. The previous store must be projected out.

v must be assigned

subcase of previous aternative

vect_rm(ve);

Parameters
exprxpr
prere

Definition at line 2595 of file ri_to_transformers.c.

2598 {
2600 
2601  pips_debug(8, "begin\n");
2602 
2603  if(entity_has_values_p(v)) {
2604  entity v_new = entity_to_new_value(v);
2606  //list tf_args = CONS(ENTITY, v, NIL);
2607 
2608  tf = any_expression_to_transformer(tmp, expr, pre, true);
2609  // The assignment may be part of a more complex expression
2610  // This should be guarded by "is_internal==FALSE" if is_internal were an argument
2611  //reset_temporary_value_counter();
2612  if(!transformer_undefined_p(tf)) {
2613  /* if the assigned variable is also assigned by the expression
2614  as in i = (i = 2) + 1, transformer_value_substitute() cannot be
2615  used right away. The previous store must be projected out. */
2617  /* v must be assigned */
2618  transformer teq = simple_equality_to_transformer(v, tmp, true);
2619  tf = transformer_combine(tf, teq);
2620  free_transformer(teq);
2621 
2622  }
2623  else { /* subcase of previous aternative */
2624  entity v_old = entity_to_old_value(v);
2625  tf = transformer_value_substitute(tf, v_new, v_old);
2626  tf = transformer_value_substitute(tf, tmp, v_new);
2627  // v cannot be a temporary variable
2628  //transformer_arguments(tf) =
2629  //arguments_add_entity(transformer_arguments(tf), v);
2630  tf = transformer_add_value_update(tf, v);
2631  }
2633  }
2634  }
2635  else {
2636  /* vect_rm(ve); */
2637  tf = transformer_undefined;
2638  }
2639 
2640  pips_debug(8, "end with tf=%p\n", tf);
2641 
2642  return tf;
2643 }
transformer transformer_add_value_update(transformer t, entity v)
Add an update of variable v to t (a value cannot be updated)
Definition: basic.c:321

References any_expression_to_transformer(), entity_has_values_p(), entity_is_argument_p(), entity_to_new_value(), entity_to_old_value(), entity_type, free_transformer(), make_local_temporary_value_entity(), pips_debug, simple_equality_to_transformer(), transformer_add_value_update(), transformer_arguments, transformer_combine(), transformer_temporary_value_projection(), transformer_undefined, transformer_undefined_p, and transformer_value_substitute().

Referenced by assign_operation_to_transformer(), integer_assign_to_transformer(), integer_assign_to_transformer_list(), loop_to_initialization_transformer(), safe_assigned_expression_to_transformer(), and safe_assigned_expression_to_transformer_list().

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

◆ assigned_expression_to_transformer_list()

list assigned_expression_to_transformer_list ( entity  v,
expression  expr,
transformer  pre 
)

transformer assigned_expression_to_transformer(entity e, expression expr, list ef): returns a transformer abstracting the effect of assignment "e = expr" when possible, transformer_undefined otherwise.

Note: it might be better to distinguish further between e and expr and to return a transformer stating that e is modified when e is accepted for semantics analysis.

if the assigned variable is also assigned by the expression as in i = (i = 2) + 1, transformer_value_substitute() cannot be used right away. The previous store must be projected out.

v must be assigned

subcase of previous aternative

vect_rm(ve);

Parameters
exprxpr
prere

Definition at line 551 of file ri_to_transformer_lists.c.

554 {
555  list tl = NIL;
557 
558  pips_internal_error("Not implemented yet.");
559 
560  pips_debug(8, "begin\n");
561 
562  if(entity_has_values_p(v)) {
563  entity v_new = entity_to_new_value(v);
564  entity v_old = entity_to_old_value(v);
566  //list tf_args = CONS(ENTITY, v, NIL);
567 
568  tf = any_expression_to_transformer(tmp, expr, pre, true);
569  // The assignment may be part of a more complex expression
570  // This should be guarded by "is_internal==FALSE" if is_internal were an argument
571  //reset_temporary_value_counter();
572  if(!transformer_undefined_p(tf)) {
573  /* if the assigned variable is also assigned by the expression
574  as in i = (i = 2) + 1, transformer_value_substitute() cannot be
575  used right away. The previous store must be projected out. */
577  /* v must be assigned */
578  transformer teq = simple_equality_to_transformer(v, tmp, true);
579  tf = transformer_combine(tf, teq);
580  free_transformer(teq);
581 
582  }
583  else { /* subcase of previous aternative */
584  tf = transformer_value_substitute(tf, v_new, v_old);
585  tf = transformer_value_substitute(tf, tmp, v_new);
586  // v cannot be a temporary variable
587  //transformer_arguments(tf) =
588  //arguments_add_entity(transformer_arguments(tf), v);
589  tf = transformer_add_value_update(tf, v);
590  }
592  }
593  }
594  else {
595  /* vect_rm(ve); */
597  }
598 
599  pips_debug(8, "end with tf=%p\n", tl);
600 
601  return tl;
602 }

References any_expression_to_transformer(), entity_has_values_p(), entity_is_argument_p(), entity_to_new_value(), entity_to_old_value(), entity_type, free_transformer(), make_local_temporary_value_entity(), NIL, pips_debug, pips_internal_error, simple_equality_to_transformer(), transformer_add_value_update(), transformer_arguments, transformer_combine(), transformer_temporary_value_projection(), transformer_undefined, transformer_undefined_p, and transformer_value_substitute().

+ Here is the call graph for this function:

◆ bitwise_xor_to_transformer()

transformer bitwise_xor_to_transformer ( entity  v,
list  args,
transformer  pre 
)

returns the transformer associated to a C bitwise xor, ^, applied to two integer argument, when meaningful, and transformer_undefined otherwise.

Effects must be used at a higher level to fall back on a legal transformer.

Parameters
vis the value associated to the expression
argsis assumed to have only one expression element of type int negated by !
preis the current precondition

Something can be done when both arguments have values in [0,1], when both arguments have known numerical values, when both arguments have the same value,... However, all this tests imply lots time consuming projections for a limited result... Unless somebody uses XOR to flip-flop between arrays... for instance to bother Sven Verdoolaege:-). A logical not might be more useful for this:-).

The two values are know at compile time

The two values can be interpreted as booleans

Code about cut-and-pasted from logical_binary_operation_to_transformer()

The two arguments may be equal because they are the same expression and the xor is used to generate a zero or because they have the same value.

Since the difference is zero the two values are equal

Parameters
argsrgs
prere

Definition at line 5619 of file expression.c.

5622 {
5623  /* Something can be done when both arguments have values in [0,1],
5624  when both arguments have known numerical values, when both
5625  arguments have the same value,... However, all this
5626  tests imply lots time consuming projections for a limited
5627  result... Unless somebody uses XOR to flip-flop between
5628  arrays... for instance to bother Sven Verdoolaege:-). A logical
5629  not might be more useful for this:-). */
5630  expression le1 = EXPRESSION(CAR(args));
5631  //basic be1 = basic_of_expression(le1);
5632  expression le2 = EXPRESSION(CAR(CDR(args)));
5633  //basic be2 = basic_of_expression(le2);
5635 
5636  //if(basic_int_p(be1) && basic_int_p(be2)) {
5638  // FI: Even with the "in context" property, the precondition is
5639  // not integrated into the transformer...
5640  transformer tf1 = safe_any_expression_to_transformer(tmp_v1, le1, pre, true);
5641  //transformer tfr1 = transformer_range(tf1);
5642  transformer tfr1 = transformer_apply(tf1, pre);
5643  intptr_t lb1, ub1;
5645  transformer tf2 = safe_any_expression_to_transformer(tmp_v2, le2, pre, true);
5646  // transformer tfr2 = transformer_range(tf2);
5647  transformer tfr2 = transformer_apply(tf2, pre);
5648  intptr_t lb2, ub2;
5649 
5650  if(precondition_minmax_of_value(tmp_v1, tfr1, &lb1, &ub1)
5651  && precondition_minmax_of_value(tmp_v2, tfr2, &lb2, &ub2)) {
5652  if(lb1==ub1 && lb2==ub2) {
5653  /* The two values are know at compile time */
5654  tf = transformer_identity();
5655  tf = transformer_add_equality_with_integer_constant(tf, v, lb1 ^ lb2);
5656  }
5657  else if(0<=lb1 && ub1 <= 1 && 0<=lb2 && ub2 <= 1) {
5658  tf = transformer_identity();
5659  /* The two values can be interpreted as booleans */
5660  /* Code about cut-and-pasted from
5661  logical_binary_operation_to_transformer() */
5662  Pvecteur eq1 = vect_new((Variable) v, VALUE_ONE);
5663  vect_add_elem(&eq1, (Variable) tmp_v1, VALUE_MONE);
5664  vect_add_elem(&eq1, (Variable) tmp_v2, VALUE_MONE);
5665 
5666  Pvecteur eq2 = vect_new((Variable) v, VALUE_ONE);
5667  vect_add_elem(&eq2, (Variable) tmp_v1, VALUE_ONE);
5668  vect_add_elem(&eq2, (Variable) tmp_v2, VALUE_ONE);
5670 
5671  Pvecteur eq3 = vect_new((Variable) v, VALUE_MONE);
5672  vect_add_elem(&eq3, (Variable) tmp_v1, VALUE_ONE);
5673  vect_add_elem(&eq3, (Variable) tmp_v2, VALUE_MONE);
5674 
5675  Pvecteur eq4 = vect_new((Variable) v, VALUE_MONE);
5676  vect_add_elem(&eq4, (Variable) tmp_v1, VALUE_MONE);
5677  vect_add_elem(&eq4, (Variable) tmp_v2, VALUE_ONE);
5678 
5679  tf = transformer_inequality_add(tf, eq1);
5680  tf = transformer_inequality_add(tf, eq2);
5681  tf = transformer_inequality_add(tf, eq3);
5682  tf = transformer_inequality_add(tf, eq4);
5683  }
5684  }
5685  if(transformer_undefined_p(tf)) {
5686  /* The two arguments may be equal because they are the same
5687  expression and the xor is used to generate a zero or because
5688  they have the same value. */
5689  if(expression_equal_p(le1, le2)) {
5690  tf = transformer_identity();
5692  }
5693  else {
5694  transformer tfr1 = transformer_range(tf1);
5695  transformer tfr2 = transformer_range(tf2);
5696  transformer tfi = transformer_intersection(tfr1, tfr2);
5698  Pvecteur eq = vect_new((Variable) tmp_d, VALUE_ONE);
5699  vect_add_elem(&eq, (Variable) tmp_v1, VALUE_MONE);
5700  vect_add_elem(&eq, (Variable) tmp_v2, VALUE_ONE);
5701  tfi = transformer_equality_add(tfi, eq);
5702  intptr_t lbd, ubd;
5703 
5704  if(precondition_minmax_of_value(tmp_d, tfi, &lbd, &ubd)) {
5705  if(lbd==0 && ubd==0) {
5706  /* Since the difference is zero the two values are equal */
5707  tf = transformer_identity();
5709  }
5710  }
5711  }
5712  }
5713  //}
5714  //free_basic(be1), free_basic(be2);
5715  free_transformer(tfr1), free_transformer(tfr2);
5716  return tf;
5717 }
transformer transformer_add_equality_with_integer_constant(transformer tf, entity v, long long int cst)
Add an equality between a value and an integer constant: v==cst.
Definition: basic.c:450
bool expression_equal_p(expression e1, expression e2)
Syntactic equality e1==e2.
Definition: expression.c:1347
bool precondition_minmax_of_value(entity val, transformer tr, intptr_t *pmin, intptr_t *pmax)
compute integer bounds pmax, pmin of value val under preconditions tr require value mappings set !
Definition: expression.c:5790
#define intptr_t
Definition: stdint.in.h:294
transformer transformer_intersection(transformer t1, transformer t2)
tf is a new transformer that receives the constraints in t1 and t2.
Definition: transformer.c:600
entity make_local_temporary_integer_value_entity(void)
Definition: value.c:629

References CAR, CDR, eq, EXPRESSION, expression_equal_p(), free_transformer(), intptr_t, make_local_temporary_integer_value_entity(), precondition_minmax_of_value(), safe_any_expression_to_transformer(), TCST, transformer_add_equality_with_integer_constant(), transformer_apply(), transformer_equality_add(), transformer_identity(), transformer_inequality_add(), transformer_intersection(), transformer_range(), transformer_undefined, transformer_undefined_p, VALUE_MONE, VALUE_ONE, vect_add_elem(), and vect_new().

Referenced by integer_call_expression_to_transformer().

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

◆ c_return_to_transformer()

transformer c_return_to_transformer ( entity  ,
list  ,
list  ,
transformer   
)

◆ c_user_call_to_transformer()

transformer c_user_call_to_transformer ( entity  f,
list  pc,
transformer  pre,
list  ef 
)

Compute the call site transformer, the bindings between formal entities and actual argments

substitute stubs and formal array elements which are passed directly or indirectly by reference if requested

Combine tf with the summary transformer

Project the former parameters and the temporary values.

Check the consistency of the transformer with the constant effects

Parameters
pcc
prere
eff

Definition at line 2196 of file ri_to_transformers.c.

2200 {
2203 
2204  pips_assert("t_callee is consistent", transformer_weak_consistency_p(t_callee));
2205 
2206  /* Compute the call site transformer, the bindings between formal
2207  entities and actual argments */
2208  tf = any_user_call_site_to_transformer(f, pc, pre, ef);
2209 
2210  /* substitute stubs and formal array elements which are passed
2211  directly or indirectly by reference if requested */
2212  transformer t_bound = copy_transformer(t_callee);
2213  if(get_bool_property("SEMANTICS_ANALYZE_CONSTANT_PATH")) {
2214  call c = make_call(f, pc);
2216  // t_bound = substitute_stubs_in_transformer(t_bound, c, s, true);
2217  t_bound = new_substitute_stubs_in_transformer(t_bound, c, s, true);
2218  call_arguments(c) = NIL;
2219  free_call(c);
2220  t_bound = substitute_formal_array_elements_in_transformer(t_bound, f, pc, pre, ef);
2221  }
2222 
2223  /* Combine tf with the summary transformer */
2224  tf = transformer_combine(tf, t_bound);
2225  free_transformer(t_bound);
2226 
2227  /* Project the former parameters and the temporary values. */
2230 
2232 
2233  /* Check the consistency of the transformer with the constant effects */
2234  // list effect_to_constant_path_effects_with_no_pointer_information(effect /*eff*/);
2235  // list simple_effect_to_constant_path_effects_with_pointer_values(effect /*eff*/);
2236  // list simple_effect_to_constant_path_effects_with_points_to(effect /*eff*/);
2237  list cel = list_undefined;
2238  if(get_bool_property("CONSTANT_PATH_EFFECTS"))
2239  cel = ef;
2240  else {
2243  else {
2244  // FI: I used to call pointer_effects_to_constant_path_effects()
2245  // but it is a generic function that requires setting some
2246  // function pointers
2247  cel = NIL;
2249  FOREACH(EFFECT, e, ef) {
2251  cel = gen_nconc(cel, ncel);
2252  }
2253  }
2254  }
2256  list al = transformer_arguments(etf);
2257  tf = transformer_add_variables_update(tf, al);
2258  free_transformer(etf);
2259 
2260  return tf;
2261 }
call make_call(entity a1, list a2)
Definition: ri.c:269
void free_call(call p)
Definition: ri.c:236
transformer copy_transformer(transformer p)
TRANSFORMER.
Definition: ri.c:2613
bool transformer_weak_consistency_p(transformer t)
Interprocedural transformers do not meet all conditions.
Definition: basic.c:626
transformer transformer_add_variables_update(transformer t, list vl)
Definition: basic.c:340
transformer load_summary_transformer(entity e)
list effects_to_constant_path_effects_with_no_pointer_information(list)
list effect_to_constant_path_effects_with_points_to(effect, statement, transformer)
Definition: eval.c:284
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
statement get_current_statement_from_statement_global_stack(void)
Definition: static.c:344
transformer any_user_call_site_to_transformer(entity f, list pc, transformer pre, list __attribute__((unused)) ef)
FI: the handling of varargs had to be modified for Semantics/va_arg.c.
transformer substitute_formal_array_elements_in_transformer(transformer tf, entity f, list pc, transformer pre, list ef)
transformer transformer_formal_parameter_projection(entity f, transformer t)
static transformer transformer_filter_subsumed_variables(transformer tf)
The transformer returned for a call site may be too accurate for the caller.
transformer new_substitute_stubs_in_transformer(transformer tf, call c, statement s, bool backward_p)
Definition: points_to.c:417

References any_user_call_site_to_transformer(), call_arguments, copy_transformer(), EFFECT, effect_to_constant_path_effects_with_points_to(), effects_to_constant_path_effects_with_no_pointer_information(), effects_to_transformer(), f(), FOREACH, free_call(), free_transformer(), gen_nconc(), get_bool_property(), get_current_statement_from_statement_global_stack(), list_undefined, load_summary_transformer(), make_call(), new_substitute_stubs_in_transformer(), NIL, pips_assert, pt_to_list_undefined_p(), substitute_formal_array_elements_in_transformer(), transformer_add_variables_update(), transformer_arguments, transformer_combine(), transformer_filter_subsumed_variables(), transformer_formal_parameter_projection(), transformer_temporary_value_projection(), transformer_undefined, and transformer_weak_consistency_p().

Referenced by c_user_function_call_to_transformer(), and user_call_to_transformer().

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

◆ call_site_count()

int call_site_count ( entity  m)

cproto-generated files

misc.c

cproto-generated files

Francois Irigoin, April 1990

Modifications:

  • passage a l'utilisation de database probably to add to the future callgraph library

number of "call to m" sites within the current program; they are all in m's CALLERS

I do not know yet; let's return 1 to please the semantic analysis

Definition at line 51 of file misc.c.

53 {
54  /* number of "call to m" sites within the current program;
55  they are all in m's CALLERS */
56  pips_assert("call_site_count", value_code_p(entity_initial(m)));
57  /* I do not know yet; let's return 1 to please the semantic analysis */
58  user_warning("call_site_count",
59  "not implemented yet, always returns 1\n");
60  return 1;
61 }
#define user_warning(fn,...)
Definition: misc-local.h:262
#define value_code_p(x)
Definition: ri.h:3065

References entity_initial, pips_assert, user_warning, and value_code_p.

◆ call_site_to_module_precondition_text()

text call_site_to_module_precondition_text ( entity  caller,
entity  callee,
statement  s,
call  c 
)

This function does everything needed.

Called by ICFG with many different contexts.

summary effects for the callee

caller preconditions

callee preconditions

load caller preconditions

first, we deal with the caller

create htable for old_values ...

add to preconditions the links to the callee formal params

transform the preconditions to make sense for the callee

translate_global_values(e_caller, call_site_prec);

Now deal with the callee

Set the htable with its variables because now we work in this frame

Parameters
calleraller
calleeallee

Definition at line 1051 of file interprocedural.c.

1056 {
1057  text result;
1058  /* summary effects for the callee */
1059  list seffects_callee = load_summary_effects(callee);
1060  /* caller preconditions */
1061  transformer caller_prec = transformer_undefined;
1062  /* callee preconditions */
1063  transformer call_site_prec = transformer_undefined;
1064 
1067  (DBR_CUMULATED_EFFECTS,
1068  module_local_name(caller), true));
1069 
1072  (DBR_PRECONDITIONS,
1073  module_local_name(caller),
1074  true) );
1075 
1076  /* load caller preconditions */
1077  caller_prec = transformer_dup(load_statement_semantic(s));
1078 
1080 
1081  /* first, we deal with the caller */
1082  set_current_module_entity(caller);
1083  /* create htable for old_values ... */
1084  module_to_value_mappings(caller);
1085 
1086  /* add to preconditions the links to the callee formal params */
1087  caller_prec = add_formal_to_actual_bindings (c, caller_prec, caller);
1088  /* transform the preconditions to make sense for the callee */
1089  call_site_prec = precondition_intra_to_inter (callee,
1090  caller_prec,
1091  seffects_callee);
1092  call_site_prec = transformer_normalize(call_site_prec, 2);
1093 
1094  /* translate_global_values(e_caller, call_site_prec); */
1097 
1098  /* Now deal with the callee */
1100  /* Set the htable with its variables because now we work
1101  in this frame */
1103 
1104  result = text_for_a_transformer(call_site_prec, false);
1105 
1111 
1112  return result;
1113 }
static entity callee
Definition: alias_pairs.c:62
void set_cumulated_rw_effects(statement_effects)
void reset_cumulated_rw_effects(void)
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
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
transformer add_formal_to_actual_bindings(call c, transformer pre, entity caller)
add_formal_to_actual_bindings(call c, transformer pre, entity caller):
void module_to_value_mappings(entity m)
void module_to_value_mappings(entity m): build hash tables between variables and values (old,...
Definition: mappings.c:624
text text_for_a_transformer(transformer tran, bool is_a_transformer)
call this one from outside.
Definition: prettyprint.c:540
transformer load_statement_semantic(statement)
void set_semantic_map(statement_mapping)
void reset_semantic_map(void)
void free_value_mappings(void)
Normal call to free the mappings.
Definition: value.c:1212

References add_formal_to_actual_bindings(), callee, db_get_memory_resource(), free_value_mappings(), load_statement_semantic(), load_summary_effects(), module_local_name(), module_to_value_mappings(), precondition_intra_to_inter(), reset_cumulated_rw_effects(), reset_current_module_entity(), reset_current_module_statement(), reset_semantic_map(), set_cumulated_rw_effects(), set_current_module_entity(), set_current_module_statement(), set_semantic_map(), text_for_a_transformer(), transformer_dup(), transformer_normalize(), and transformer_undefined.

+ Here is the call graph for this function:

◆ call_to_summary_precondition()

void call_to_summary_precondition ( transformer  pre,
call  c 
)

propagate precondition pre as summary precondition of user functions

propagate precondition pre as summary precondition of user functions

user_warning("call_to_summary_precondition", "call to symbolic %s\n", entity_name(e));

Parameters
prere

Definition at line 989 of file interprocedural.c.

992 {
993  entity e = call_function(c);
994  tag tt;
995  list args = call_arguments(c);
996  transformer pre_callee = transformer_undefined;
997 
998  pips_debug(8, "begin\n");
999 
1000  switch (tt = value_tag(entity_initial(e))) {
1001 
1002  case is_value_intrinsic:
1003  pips_debug(5, "intrinsic function %s\n",
1004  entity_name(e));
1005  /* propagate precondition pre as summary precondition
1006  of user functions */
1008  break;
1009 
1010  case is_value_code:
1011  pips_debug(5, "external function %s\n",
1012  entity_name(e));
1013  pre_callee = transformer_dup(pre);
1014  pre_callee =
1016  add_module_call_site_precondition(e, pre_callee);
1017  /* propagate precondition pre as summary precondition
1018  of user functions */
1020  break;
1021 
1022  case is_value_symbolic:
1023  /* user_warning("call_to_summary_precondition",
1024  "call to symbolic %s\n",
1025  entity_name(e)); */
1026  break;
1027 
1028  case is_value_constant:
1029  user_warning("call_to_summary_precondition",
1030  "call to constant %s\n",
1031  entity_name(e));
1032  break;
1033 
1034  case is_value_unknown:
1035  pips_internal_error("unknown function %s",
1036  entity_name(e));
1037  break;
1038 
1039  default:
1040  pips_internal_error("unknown tag %d", tt);
1041  }
1042 
1043  pips_debug(8, "end\n");
1044 
1045 }
int tag
TAG.
Definition: newgen_types.h:92
#define value_tag(x)
Definition: ri.h:3064
@ 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
void expressions_to_summary_precondition(transformer pre, list le)
void add_module_call_site_precondition(entity m, transformer p)

References add_formal_to_actual_bindings(), add_module_call_site_precondition(), call_arguments, call_function, entity_initial, entity_name, expressions_to_summary_precondition(), get_current_module_entity(), is_value_code, is_value_constant, is_value_intrinsic, is_value_symbolic, is_value_unknown, pips_debug, pips_internal_error, transformer_dup(), transformer_undefined, user_warning, and value_tag.

Referenced by expression_to_summary_precondition().

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

◆ call_to_transformer()

transformer call_to_transformer ( call  c,
transformer  pre,
list  ef 
)

Use to be static, but may be called from expressions in C.

effects of call c

call to an external function; preliminary version: rely on effects

A temporary variable should be allocated and user_function_call_to_transformer() be used. The variable should then be projected to keep only the side effects of the call.

Add information from pre. Invariant information is easy to use. Information about initial values, that is final values in pre, can also be used.

tf = transformer_normalize(tf, 4);

Parameters
prere
eff

Definition at line 1044 of file ri_to_transformers.c.

1047 {
1049  entity e = call_function(c);
1050  cons *pc = call_arguments(c);
1051  tag tt;
1052 
1053  ifdebug(9) {
1054  pips_debug(9,"begin with precondition %p \n", pre);
1055  print_transformer(pre);
1057  ifdebug(9) {
1058  statement curstat = statement_undefined;
1061  if (!statement_undefined_p(curstat))
1062  print_statement(curstat);
1063  }
1064  }
1065 
1066  switch (tt = value_tag(entity_initial(e))) {
1067  case is_value_code:
1068  /* call to an external function; preliminary version:
1069  rely on effects */
1071  type et = ultimate_type(entity_type(e));
1073 
1074  if(type_void_p(rt)) {
1075  tf = user_call_to_transformer(e, pc, pre, ef);
1076  reset_temporary_value_counter(); // might not be a good idea
1077  // with expression lists?
1078  // Get rid of variables that have been subsumed by abstract
1079  // locations
1081  }
1082  else {
1083  if(analyzed_type_p(rt)) {
1084  /* A temporary variable should be allocated and
1085  user_function_call_to_transformer() be used. The variable
1086  should then be projected to keep only the side effects of
1087  the call. */
1089  expression expr = call_to_expression(c);
1090 
1091  tf = user_function_call_to_transformer(trv, expr, pre);
1094  semantics_user_warning("Analyzable result of Function \"%s\" is "
1095  "ignored. Should it be casted to \"(void)\"?\n",
1096  entity_user_name(e));
1097  // Get rid of variables that have been subsumed by abstract
1098  // locations
1100  }
1101  else {
1102  tf = user_call_to_transformer(e, pc, pre, ef);
1103  reset_temporary_value_counter(); // might not be a good idea
1104  semantics_user_warning("Result of function \"%s\" ignored. "
1105  "Should it be casted to \"(void)\"?\n",
1106  entity_user_name(e));
1107  // Get rid of variables that have been subsumed by abstract
1108  // locations
1110  }
1111  }
1112  }
1113  else
1114  tf = effects_to_transformer(ef);
1115  break;
1116  case is_value_symbolic:
1117  case is_value_constant:
1118  tf = transformer_identity();
1119  break;
1120  case is_value_unknown:
1121  pips_internal_error("function %s has an unknown value", entity_name(e));
1122  break;
1123  case is_value_intrinsic:
1124  tf = intrinsic_to_transformer(e, pc, pre, ef);
1125  break;
1126  default:
1127  pips_internal_error("unknown tag %d", tt);
1128  }
1129  pips_assert("transformer tf is consistent",
1131 
1132  ifdebug(8) {
1133  pips_debug(8,"Transformer before intersection with precondition, tf=%p\n",
1134  tf);
1135  (void) print_transformer(tf);
1136  }
1137 
1138  /* Add information from pre. Invariant information is easy to
1139  use. Information about initial values, that is final values in pre,
1140  can also be used. */
1142  ifdebug(8) {
1143  pips_debug(8,"After intersection and before normalization with tf=%p\n", tf);
1144  (void) print_transformer(tf);
1145  }
1146  ifdebug(8) {
1147  pips_debug(8,"with precondition pre=%p\n", pre);
1148  (void) print_transformer(pre);
1149  }
1150 /* tf = transformer_normalize(tf, 4); */
1151  tf = transformer_normalize(tf, 2);
1152 
1153  ifdebug(8) {
1154  pips_debug(8,"end after normalization with tf=%p\n", tf);
1155  (void) print_transformer(tf);
1156  }
1157 
1158  return(tf);
1159 }
bool transformer_consistency_p(transformer t)
FI: I do not know if this procedure should always return or fail when an inconsistency is found.
Definition: basic.c:612
void print_entity_variable(entity e)
print_entity_variable(e)
Definition: entity.c:56
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
#define SEMANTICS_INTERPROCEDURAL
expression call_to_expression(call c)
Build an expression that call a function or procedure.
Definition: expression.c:309
bool statement_global_stack_defined_p(void)
Definition: static.c:364
#define functional_result(x)
Definition: ri.h:1444
#define type_functional(x)
Definition: ri.h:2952
#define type_void_p(x)
Definition: ri.h:2959
#define statement_undefined_p(x)
Definition: ri.h:2420
#define statement_undefined
Definition: ri.h:2419
transformer user_function_call_to_transformer(entity e, expression expr, transformer pre)
a function call is a call to a non void function in C and to a FUNCTION in Fortran
transformer user_call_to_transformer(entity f, list pc, transformer pre, list ef)
transformer intrinsic_to_transformer(entity e, list pc, transformer pre, list ef)
effects of intrinsic call
transformer transformer_safe_domain_intersection(transformer tf, transformer pre)
If tf and pre are defined, update tf.
Definition: transformer.c:696
bool analyzed_type_p(type)
The type t is one of the analyzed types.
Definition: value.c:367

References analyzed_type_p(), call_arguments, call_function, call_to_expression(), effects_to_transformer(), entity_initial, entity_name, entity_type, entity_user_name(), functional_result, get_bool_property(), get_current_statement_from_statement_global_stack(), ifdebug, intrinsic_to_transformer(), is_value_code, is_value_constant, is_value_intrinsic, is_value_symbolic, is_value_unknown, make_local_temporary_value_entity(), pips_assert, pips_debug, pips_internal_error, print_entity_variable(), print_statement(), print_transformer, reset_temporary_value_counter(), SEMANTICS_INTERPROCEDURAL, semantics_user_warning, statement_global_stack_defined_p(), statement_undefined, statement_undefined_p, transformer_consistency_p(), transformer_filter_subsumed_variables(), transformer_identity(), transformer_normalize(), transformer_safe_domain_intersection(), transformer_temporary_value_projection(), transformer_undefined, type_functional, type_void_p, ultimate_type(), user_call_to_transformer(), user_function_call_to_transformer(), and value_tag.

Referenced by expression_to_transformer(), instruction_to_transformer(), and instruction_to_transformer_list().

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

◆ caller_count()

int caller_count ( entity  m)

number of modules calling m within the current program; i.e. number of modules containing at least one call site to m

I do not know yet; let's return 1 to please the semantic analysis

Definition at line 63 of file misc.c.

65 {
66  /* number of modules calling m within the current program;
67  i.e. number of modules containing at least one call site to m */
68  pips_assert("caller_count", value_code_p(entity_initial(m)));
69  /* I do not know yet; let's return 1 to please the semantic analysis */
70  user_warning("caller_count",
71  "not implemented yet, always returns 1\n");
72  return 1;
73 }

References entity_initial, pips_assert, user_warning, and value_code_p.

◆ check_condition_wrt_precondition()

bool check_condition_wrt_precondition ( expression  c,
transformer  pre,
bool  check_true 
)

Check that is is always false in a store s such that p(s)

Parameters
prere
check_trueheck_true

Definition at line 294 of file utils.c.

297 {
298  bool check = true;
299  transformer twc = transformer_dup(pre);
300 
301  pips_debug(8, "begins for check %s\n",
302  bool_to_string(check_true));
303 
304  if(check_true) {
305  twc = transformer_add_condition_information(twc, c, pre, false);
306  }
307  else {
308  /* Check that is is always false in a store s such that p(s) */
309  twc = transformer_add_condition_information(twc, c, pre, true);
310  }
311  check = transformer_empty_p(twc);
312 
313  pips_debug(8, "ends with check=%s for check_true=%s\n",
314  bool_to_string(check), bool_to_string(check_true));
315 
316  return check;
317 }
string bool_to_string(bool)
Definition: string.c:243
transformer transformer_add_condition_information(transformer pre, expression c, transformer context, bool veracity)
Definition: expression.c:1092
bool transformer_empty_p(transformer t)
If true is returned, the transformer certainly is empty.
Definition: transformer.c:2455

References bool_to_string(), pips_debug, transformer_add_condition_information(), transformer_dup(), and transformer_empty_p().

Referenced by condition_false_wrt_precondition_p(), and condition_true_wrt_precondition_p().

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

◆ check_range_wrt_precondition()

bool check_range_wrt_precondition ( range  r,
transformer  p,
bool  check_empty 
)

FI: this function is outdated because it does not compute the transformers for the range expressions, because it does not take side effects into account and ...

We might need a range_to_transformer() or loop_range_to_transformer() instead and check that its range is empty.

gather information about the increment sign

Try to prove that no iterations are performed

Without information about the increment sign, you cannot make a decision. Should we accept increments greater or equal to zero? Lesser or equal to zero?

Try to prove that at least one iteration is performed

Without information about the increment sign, you cannot make a decision. Should we accept increments greater or equal to zero? Lesser or equal to zero?

No decision has been made yet

a numerical range may be empty although no information is available

s = sc_strong_normalize4(s, (char * (*)(Variable)) entity_local_name);

= sc_elim_redund(s);

Parameters
check_emptyheck_empty

Definition at line 135 of file utils.c.

136 {
137  bool check = true;
138  expression lb_e = range_lower(r);
139  expression ub_e = range_upper(r);
140  expression incr_e = range_increment(r);
141  normalized lb_n = NORMALIZE_EXPRESSION(lb_e);
142  normalized ub_n = NORMALIZE_EXPRESSION(ub_e);
143  normalized incr_n = NORMALIZE_EXPRESSION(incr_e);
144  int incr_lb = 0;
145  int incr_ub = 0;
146 
147  pips_debug(8, "begins for check %s\n", check_empty? "empty" : "non-empty");
148 
149  if(normalized_undefined_p(lb_n)
150  || normalized_undefined_p(lb_n)
151  || normalized_undefined_p(lb_n)) {
152  user_error("check_range_wrt_precondition",
153  "Expression should have been normalized. "
154  "Maybe you have DOALL statements in your "
155  "supposedly sequential source code!\n");
156  }
157 
158  if(normalized_linear_p(lb_n)
159  && normalized_linear_p(ub_n)
160  && normalized_linear_p(incr_n)) {
161 
162  /* gather information about the increment sign */
163  expression_and_precondition_to_integer_interval(incr_e, p, &incr_lb, &incr_ub);
164 
165  if(incr_lb==0 && incr_ub==0) {
166  user_error("check_range_wrt_precondition",
167  "Range with illegal zero increment\n");
168  }
169 
170  if(incr_lb<=incr_ub) {
174 
175  if(check_empty) {
176  /* Try to prove that no iterations are performed */
177  if(incr_lb>=1) {
178  Pvecteur ni = vect_substract(lb_v, ub_v);
179 
180  ci = contrainte_make(ni);
181  }
182  else if(incr_ub<=-1) {
183  Pvecteur ni = vect_substract(ub_v, lb_v);
184 
185  ci = contrainte_make(ni);
186  }
187  else {
188  /* Without information about the increment sign,
189  * you cannot make a decision. Should we accept
190  * increments greater or equal to zero? Lesser
191  * or equal to zero?
192  */
193  check = false;
194  }
195  }
196  else {
197  /* Try to prove that at least one iteration is performed */
198  if(incr_lb>=1) {
199  Pvecteur ni = vect_substract(ub_v, lb_v);
200 
201  vect_add_elem(&ni, TCST, (Value) 1);
202  ci = contrainte_make(ni);
203  }
204  else if(incr_ub<=-1) {
205  Pvecteur ni = vect_substract(lb_v, ub_v);
206 
207  vect_add_elem(&ni, TCST, (Value) 1);
208  ci = contrainte_make(ni);
209  }
210  else {
211  /* Without information about the increment sign,
212  * you cannot make a decision. Should we accept
213  * increments greater or equal to zero? Lesser
214  * or equal to zero?
215  */
216  check = false;
217  }
218  }
219 
220  if(check) {
221  /* No decision has been made yet */
222  /* a numerical range may be empty although no information is available */
226 
227  s = sc_inequality_add(s, ci);
228 
229  ifdebug(8) {
230  debug(8, "check_range_wrt_precondition",
231  "Test feasibility for system:\n");
232  sc_fprint(stderr, s, (char * (*)(Variable)) dump_value_name);
233  }
234 
235  /* s = sc_strong_normalize4(s, (char * (*)(Variable)) entity_local_name); */
236  s = sc_strong_normalize5(s, (char * (*)(Variable)) entity_local_name);
237  /*s = sc_elim_redund(s);*/
238  ifdebug(8) {
239  debug(8, "check_range_wrt_precondition",
240  "System after normalization:\n");
241  sc_fprint(stderr, s, (char * (*)(Variable)) dump_value_name);
242  }
243 
244  if(SC_EMPTY_P(s)) {
245  check = true;
246  }
247  else {
248  sc_rm(s);
249  check = false;
250  }
251  }
252  }
253  else {
254  debug(8, "check_range_wrt_precondition",
255  "The loop is never executed because it is in a dead code section\n");
256  check = check_empty;
257  }
258  }
259  else {
260  debug(8, "check_range_wrt_precondition",
261  "No decision can be made because the increment sign is unknown\n");
262  check = false;
263  }
264 
265  debug(8, "check_range_wrt_precondition",
266  "ends with check=%s for check_empty=%s\n",
267  bool_to_string(check), bool_to_string(check_empty));
268 
269  return check;
270 }
char * dump_value_name(entity e)
char * dump_value_name(e): used as functional argument because entity_name is a macro
Definition: io.c:128
#define transformer_relation(x)
Definition: ri.h:2873
#define normalized_undefined_p(x)
Definition: ri.h:1746
#define predicate_system(x)
Definition: ri.h:2069
void sc_rm(Psysteme ps)
void sc_rm(Psysteme ps): liberation de l'espace memoire occupe par le systeme de contraintes ps;
Definition: sc_alloc.c:277
Psysteme sc_dup(Psysteme ps)
Psysteme sc_dup(Psysteme ps): should becomes a link.
Definition: sc_alloc.c:176
Psysteme sc_inequality_add(Psysteme sc, Pcontrainte c)
Definition: sc_insert_eq.c:108
void sc_fprint(FILE *fp, Psysteme ps, get_variable_name_t nom_var)
void sc_fprint(FILE * f, Psysteme ps, char * (*nom_var)()): cette fonction imprime dans le fichier po...
Definition: sc_io.c:220
Psysteme sc_strong_normalize5(Psysteme ps, char *(*variable_name)(Variable))
void expression_and_precondition_to_integer_interval(expression e, transformer p, int *plb, int *pub)
Evaluate expression e in context p, assuming that e is an integer expression.
Definition: utils.c:325

References bool_to_string(), contrainte_make(), CONTRAINTE_UNDEFINED, debug(), dump_value_name(), entity_local_name(), expression_and_precondition_to_integer_interval(), ifdebug, NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, normalized_undefined_p, pips_debug, predicate_system, range_increment, range_lower, range_upper, sc_dup(), sc_fprint(), sc_inequality_add(), sc_make(), sc_rm(), sc_strong_normalize5(), TCST, transformer_relation, transformer_undefined_p, user_error, vect_add_elem(), vect_dup(), and vect_substract().

Referenced by empty_range_wrt_precondition_p(), and non_empty_range_wrt_precondition_p().

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

◆ complete_any_loop_transformer()

transformer complete_any_loop_transformer ( transformer  ,
transformer  ,
transformer  ,
transformer  ,
transformer  ,
transformer  ,
transformer  ,
transformer   
)

◆ complete_any_loop_transformer_list()

list complete_any_loop_transformer_list ( transformer  t_init,
transformer  t_skip,
transformer  t_body_star,
transformer  t_body,
transformer  t_inc,
transformer  t_exit 
)

FI: used to be complete_any_loop_transformer() with a direct reduction by convex hull.

t_loop = t_init ; t_skip + t_bodystar ; t_body ; t_inc; t_exit

Before entering t_body, t_enter or t_next have been applied which let us restrict the set of state modified by t_body. But this information should already been included in t_body_star.

Several cases must be tested:

  1. The loop is always entered and exited (usual case for scientific code: t_skip = transformer_empty).
  2. The loop is always entered and never exited (real-time code situation, t_exit = transformer_empty)
  3. The loop is never entered (in its current context, t_bodystar = transformer_empty because t_enter = transformer_empty).
  4. The loop may be entered and exited (usual case for general purpose computing, think of list handling).
  5. The loop may be entered but is then never exited (real-time code again).

These cases are checked with complete01.c, complete02.c,... complete05.c

loop skipped transformer

add loop entered transformer/condition: should already be in t_body_star

combine both cases in a transformer list

Parameters
t_init_init
t_skip_skip
t_body_star_body_star
t_body_body
t_inc_inc
t_exit_exit

Definition at line 1578 of file loop.c.

1584 {
1585  /* t_loop = t_init ; t_skip + t_bodystar ; t_body ; t_inc; t_exit
1586  *
1587  * Before entering t_body, t_enter or t_next have been applied which
1588  * let us restrict the set of state modified by t_body. But this
1589  * information should already been included in t_body_star.
1590  */
1591 
1592  /* Several cases must be tested:
1593  *
1594  * 1. The loop is always entered and exited (usual case for
1595  * scientific code: t_skip = transformer_empty).
1596  *
1597  * 2. The loop is always entered and never exited (real-time code
1598  * situation, t_exit = transformer_empty)
1599  *
1600  * 3. The loop is never entered (in its current context, t_bodystar
1601  * = transformer_empty because t_enter = transformer_empty).
1602  *
1603  * 4. The loop may be entered and exited (usual case for general
1604  * purpose computing, think of list handling).
1605  *
1606  * 5. The loop may be entered but is then never exited (real-time
1607  * code again).
1608  *
1609  * These cases are checked with complete01.c,
1610  * complete02.c,... complete05.c
1611  */
1612  list ltl = NIL;
1613  // transformer ct = transformer_undefined;
1614  /* loop skipped transformer */
1615  transformer lst = transformer_combine(copy_transformer(t_init), t_skip);
1616  /* add loop entered transformer/condition: should already be in t_body_star */
1617  //transformer post_enter = transformer_range(t_enter);
1618  //transformer post_continue = transformer_range(t_continue);
1619  //transformer pre_body = transformer_convex_hull(post_enter, post_continue);
1620  //transformer let = transformer_combine(copy_transformer(t_body_star), pre_body);
1621  transformer let = copy_transformer(t_body_star);
1622 
1623  ifdebug(8) {
1624  fprintf(stderr, "t_init:\n");
1625  print_transformer(t_init);
1626  fprintf(stderr, "t_skip:\n");
1627  print_transformer(t_skip);
1628  fprintf(stderr, "t_body_star:\n");
1629  print_transformer(t_body_star);
1630  fprintf(stderr, "t_body:inc\n");
1631  print_transformer(t_body);
1632  fprintf(stderr, "t_inc:\n");
1633  print_transformer(t_inc);
1634  fprintf(stderr, "t_exit:\n");
1635  print_transformer(t_exit);
1636  }
1637 
1638  let = transformer_combine(let, t_body);
1639  let = transformer_combine(let, t_inc);
1640  let = transformer_combine(let, t_exit);
1641  let = transformer_normalize(let, 2);
1642 
1643  /* combine both cases in a transformer list */
1644  //ct = transformer_convex_hull(lst, let);
1645  ltl = two_transformers_to_list(lst, let);
1646 
1647  //free_transformer(post_enter);
1648  //free_transformer(post_continue);
1649  //free_transformer(pre_body);
1650 
1651  ifdebug(8) {
1652  fprintf(stderr, "ltl:\n");
1653  print_transformers(ltl);
1654  }
1655 
1656  return ltl;
1657 }
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
list two_transformers_to_list(transformer, transformer)
Transformer two transformers into a correct transformer list.

References copy_transformer(), fprintf(), ifdebug, NIL, print_transformer, print_transformers(), transformer_combine(), transformer_normalize(), and two_transformers_to_list().

Referenced by complete_any_loop_transformer(), and new_complete_whileloop_transformer_list().

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

◆ complete_forloop_transformer()

transformer complete_forloop_transformer ( transformer  t_body_star,
transformer  pre,
forloop  fl 
)

This function does not seem to exist because we only used statement effects in the past and because those are stored in the database.

An effort could be made to compute the precondition for t_exit, especially if the precondition to t_inc is available.

An effort could be made to compute the precondition for t_inc

Make sure you have the effective statement transformer: it is not stored for loops and this is key for nested loops.

Parameters
t_body_star_body_star
prere
fll

Definition at line 1686 of file loop.c.

1689 {
1691  statement body_s = forloop_body(fl);
1692  transformer t_body = load_statement_transformer(body_s);
1695  expression init_e = forloop_initialization(fl);
1696  /* This function does not seem to exist because we only used
1697  statement effects in the past and because those are stored in the
1698  database. */
1699  transformer t_init = safe_expression_to_transformer(init_e, pre);
1700  transformer post_init = transformer_apply(t_init, pre);
1701  expression cond_e = forloop_condition(fl);
1702  expression inc_e = forloop_increment(fl);
1703  transformer t_skip = condition_to_transformer(cond_e, post_init, false);
1704  transformer t_enter = condition_to_transformer(cond_e, post_init, true);
1705 /* An effort could be made to compute the precondition for t_exit,
1706  especially if the precondition to t_inc is available. */
1707  transformer t_continue = condition_to_transformer(cond_e, transformer_undefined, true);
1709  /* An effort could be made to compute the precondition for t_inc */
1711 
1712  /* Make sure you have the effective statement transformer: it is not
1713  stored for loops and this is key for nested loops. */
1714  pre_body = transformer_apply(t_body_star, pre);
1715  ct_body = complete_statement_transformer(t_body, pre_body, body_s);
1716 
1717  ct = complete_any_loop_transformer(t_init, t_enter, t_skip, t_body_star, ct_body, t_continue, t_inc, t_exit);
1718 
1719  free_transformer(ct_body);
1720  free_transformer(pre_body);
1721  free_transformer(t_init);
1722  free_transformer(post_init);
1723  free_transformer(t_skip);
1724  free_transformer(t_enter);
1725  free_transformer(t_continue);
1726  free_transformer(t_exit);
1727  free_transformer(t_inc);
1728 
1729  return ct;
1730 }
#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
transformer complete_statement_transformer(transformer t, transformer pre, statement s)
Returns the effective transformer ct for a given statement s.
transformer complete_any_loop_transformer(transformer t_init, transformer __attribute__((unused)) t_enter, transformer t_skip, transformer t_body_star, transformer t_body, transformer __attribute__((unused)) t_continue, transformer t_inc, transformer t_exit)
Reduce the transformer list associated to a loop to a unique transformer using a convex hull.
Definition: loop.c:1662

References complete_any_loop_transformer(), complete_statement_transformer(), condition_to_transformer(), forloop_body, forloop_condition, forloop_increment, forloop_initialization, free_transformer(), load_statement_transformer(), safe_expression_to_transformer(), transformer_apply(), and transformer_undefined.

Referenced by generic_complete_statement_transformer().

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

◆ complete_forloop_transformer_list()

list complete_forloop_transformer_list ( transformer  t_body_star,
transformer  pre,
forloop  fl 
)

This function does not seem to exist because we only used statement effects in the past and because those are stored in the database.

An effort could be made to compute the precondition for t_exit, especially if the precondition to t_inc is available.

An effort could be made to compute the precondition for t_inc

Make sure you have the effective statement transformer: it is not stored for loops and this is key for nested loops.

Parameters
t_body_star_body_star
prere
fll

Definition at line 1732 of file loop.c.

1735 {
1736  list tfl = list_undefined;
1737  statement body_s = forloop_body(fl);
1738  transformer t_body = load_statement_transformer(body_s);
1741  expression init_e = forloop_initialization(fl);
1742  /* This function does not seem to exist because we only used
1743  statement effects in the past and because those are stored in the
1744  database. */
1745  transformer t_init = safe_expression_to_transformer(init_e, pre);
1746  transformer post_init = transformer_apply(t_init, pre);
1747  expression cond_e = forloop_condition(fl);
1748  expression inc_e = forloop_increment(fl);
1749  transformer t_skip = condition_to_transformer(cond_e, post_init, false);
1750  transformer t_enter = condition_to_transformer(cond_e, post_init, true);
1751 /* An effort could be made to compute the precondition for t_exit,
1752  especially if the precondition to t_inc is available. */
1753  transformer t_continue = condition_to_transformer(cond_e, transformer_undefined, true);
1755  /* An effort could be made to compute the precondition for t_inc */
1757 
1758  pips_internal_error("function is not implemented");
1759 
1760  /* Make sure you have the effective statement transformer: it is not
1761  stored for loops and this is key for nested loops. */
1762  pre_body = transformer_apply(t_body_star, pre);
1763  ct_body = complete_statement_transformer(t_body, pre_body, body_s);
1764 
1765  (void)complete_any_loop_transformer(t_init, t_enter, t_skip, t_body_star, ct_body, t_continue, t_inc, t_exit);
1766 
1767  free_transformer(ct_body);
1768  free_transformer(pre_body);
1769  free_transformer(t_init);
1770  free_transformer(post_init);
1771  free_transformer(t_skip);
1772  free_transformer(t_enter);
1773  free_transformer(t_continue);
1774  free_transformer(t_exit);
1775  free_transformer(t_inc);
1776 
1777  return tfl;
1778 }

References complete_any_loop_transformer(), complete_statement_transformer(), condition_to_transformer(), forloop_body, forloop_condition, forloop_increment, forloop_initialization, free_transformer(), list_undefined, load_statement_transformer(), pips_internal_error, safe_expression_to_transformer(), transformer_apply(), and transformer_undefined.

Referenced by instruction_to_transformer_list().

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

◆ complete_loop_transformer()

transformer complete_loop_transformer ( transformer  ltf,
transformer  pre,
loop  l 
)

The transformer computed and stored for a loop is useful to compute the loop body precondition, but it is not useful to analyze a higher level construct, which need the loop transformer with the exit condition.

Only Fortran DO loops are handled here. The need for nested WHILE loops has not been identified yet. The index variable is always initialized and then the loop is either entered and exited or not entered

loop body transformer

compute the loop body transformer

Since it is not stored, we need to go down recursively. A way to avoid this would be to always have sequences as loop bodies... Let's hope that perfectly nested loops are neither frequent nor deep!

compute the loop body precondition

You do not need a range to recurse. A full precondition with arguments is expected by complete_loop_transformer(). Maybe, but it's much easier to debug with ranges as they only carry the useful information. And the result is correct for Semantics-New/for03.c and 04.c

The final index incrementation is performed later by add_loop_index_exit_value()

btf = transformer_add_loop_index_incrementation(btf, l, pre);

compute the transformer when the loop is entered: T o T*

Semantics-New/for04.c: this leads to t_enter == empty_transformer because the same conditions on the initial values of cpi and cpj are preserved in both ltf, which is OK, and btf, which is not OK.

add the entry condition

but it seems to be in t already

t_enter = transformer_add_loop_index_initialization(t_enter, l);

It would make sense to apply the incrementation, but this is performed as a side effect by add_loop_index_exit_value(), which avoids unfeasability wrt the final loop bound.

add the exit condition, without any information pre to estimate the increment

FI: oops, pre is used in spite of previous comment

add initialization for the unconditional initialization of the loop index variable

It might be better not to compute useless transformer, but it's more readable that way. Since pre is information free, only loops with constant lower and upper bound and constant increment can benefit from this.

pre cannot be used as such. the loop initialization must be applied first: the previous comment seems to be correct.

Parameters
ltftf
prere

Definition at line 1927 of file loop.c.

1928 {
1932  /* loop body transformer */
1934  range r = loop_range(l);
1935  statement s = loop_body(l);
1936 
1937  pips_debug(8,"begin with loop precondition\n");
1938  ifdebug(8) {
1939  (void) print_transformer(pre);
1940  pips_debug(8,"and loop transformer:\n");
1941  (void) print_transformer(ltf);
1942  }
1943 
1944  /* compute the loop body transformer */
1945  if(statement_loop_p(s)) {
1946  /* Since it is not stored, we need to go down recursively. A way to
1947  avoid this would be to always have sequences as loop
1948  bodies... Let's hope that perfectly nested loops are neither
1949  frequent nor deep! */
1951  /* compute the loop body precondition */
1952  transformer raw_ipre = transformer_apply(ltf, pre);
1953  transformer ipre = transformer_range(raw_ipre);
1954  ipre = transformer_normalize(ipre, 2);
1955  /* You do not need a range to recurse. A full precondition with
1956  arguments is expected by complete_loop_transformer(). Maybe,
1957  but it's much easier to debug with ranges as they only carry
1958  the useful information. And the result is correct for
1959  Semantics-New/for03.c and 04.c */
1961  btf = complete_loop_transformer(st, ipre, il);
1962  btf = transformer_normalize(btf, 2);
1963  free_transformer(ipre);
1964  free_transformer(raw_ipre);
1965  }
1966  else {
1968  }
1969  /* The final index incrementation is performed later by add_loop_index_exit_value() */
1970  /* btf = transformer_add_loop_index_incrementation(btf, l, pre); */
1971 
1972  /* compute the transformer when the loop is entered: T o T* */
1973  /* Semantics-New/for04.c: this leads to t_enter ==
1974  empty_transformer because the same conditions on the initial
1975  values of cpi and cpj are preserved in both ltf, which is OK, and
1976  btf, which is not OK. */
1977  t_enter = transformer_combine(transformer_dup(ltf), btf);
1978 
1979  ifdebug(8) {
1980  pips_debug(8, "entered loop transformer t_enter=\n");
1982  }
1983 
1984  /* add the entry condition */
1985  /* but it seems to be in t already */
1986  /* t_enter = transformer_add_loop_index_initialization(t_enter, l); */
1987 
1988  /* It would make sense to apply the incrementation, but this is
1989  performed as a side effect by add_loop_index_exit_value(), which
1990  avoids unfeasability wrt the final loop bound. */
1991  /*
1992  transformer t_inc = transformer_identity();
1993  t_inc = transformer_add_loop_index_incrementation(t_inc, l, pre);
1994  t_enter = transformer_combine(t_enter, t_inc);
1995  */
1996 
1997  /* add the exit condition, without any information pre to estimate the
1998  increment */
1999  transformer tmp = t_enter;
2000  /* FI: oops, pre is used in spite of previous comment */
2001  t_enter = add_loop_index_exit_value(t_enter, l, pre);
2002  transformer_free(tmp);
2003 
2004  ifdebug(8) {
2005  pips_debug(8, "entered and exited loop transformer t_enter=\n");
2007  }
2008 
2009  /* add initialization for the unconditional initialization of the loop
2010  index variable */
2011  tmp = transformer_undefined_p(pre)?
2013  transformer_dup(pre);
2014  t_skip = add_loop_index_initialization(tmp, l, pre);
2015  //transformer ipre = transformer_apply(t_skip, pre);
2016  //transformer ripre = transformer_range(ipre);
2017  transformer_free(tmp);
2018  t_skip = add_loop_skip_condition(t_skip, l, pre);
2019  t_skip = transformer_normalize(t_skip, 2);
2020 
2021  ifdebug(8) {
2022  pips_debug(8, "skipped loop transformer t_skip=\n");
2024  }
2025 
2026  /* It might be better not to compute useless transformer, but it's more
2027  readable that way. Since pre is information free, only loops with
2028  constant lower and upper bound and constant increment can benefit
2029  from this. */
2030  /* pre cannot be used as such. the loop initialization must be
2031  applied first: the previous comment seems to be correct. */
2032  // if(empty_range_wrt_precondition_p(r, ripre)) {
2033  if(empty_range_wrt_precondition_p(r, pre)) {
2034  tf = t_skip;
2035  free_transformer(t_enter);
2036  }
2037  // else if(non_empty_range_wrt_precondition_p(r, ripre)) {
2038  else if(non_empty_range_wrt_precondition_p(r, pre)) {
2039  tf = t_enter;
2040  free_transformer(t_skip);
2041  }
2042  else {
2043  tf = transformer_convex_hull(t_enter, t_skip);
2044  free_transformer(t_enter);
2045  free_transformer(t_skip);
2046  }
2047  //free_transformer(ipre);
2048  //free_transformer(ripre);
2049 
2050  tf = transformer_normalize(tf, 2);
2051 
2052  ifdebug(8) {
2053  pips_debug(8, "full refined loop transformer tf=\n");
2055  pips_debug(8, "end\n");
2056  }
2057 
2058  return tf;
2059 }
bool statement_loop_p(statement)
Definition: statement.c:349
transformer fprint_transformer(FILE *fd, transformer tf, get_variable_name_t value_name)
Definition: io.c:69
#define instruction_loop(x)
Definition: ri.h:1520
#define statement_instruction(x)
Definition: ri.h:2458
transformer complete_loop_transformer(transformer ltf, transformer pre, loop l)
The transformer computed and stored for a loop is useful to compute the loop body precondition,...
Definition: loop.c:1927
static transformer add_loop_index_initialization(transformer tf, loop l, transformer pre)
Always returns newly allocated memory.
Definition: loop.c:825
transformer add_loop_index_exit_value(transformer post, loop l, transformer pre)
The exit value is known if.
Definition: loop.c:878
transformer add_loop_skip_condition(transformer tf, loop l, transformer pre)
tf and pre are a unique data structure when preconditions are computed
Definition: loop.c:495
bool non_empty_range_wrt_precondition_p(range, transformer)
Definition: utils.c:121
bool empty_range_wrt_precondition_p(range, transformer)
A range cannot be tested exactly wrt a precondition You can try to prove that it is empty or you can ...
Definition: utils.c:112
char *(* get_variable_name_t)(Variable)
Definition: vecteur-local.h:62

References add_loop_index_exit_value(), add_loop_index_initialization(), add_loop_skip_condition(), empty_range_wrt_precondition_p(), external_value_name(), fprint_transformer(), free_transformer(), ifdebug, instruction_loop, load_statement_transformer(), loop_body, loop_range, non_empty_range_wrt_precondition_p(), pips_debug, print_transformer, statement_instruction, statement_loop_p(), transformer_apply(), transformer_combine(), transformer_convex_hull(), transformer_dup(), transformer_free(), transformer_identity(), transformer_normalize(), transformer_range(), transformer_undefined, and transformer_undefined_p.

Referenced by complete_loop_transformer_list(), generic_complete_statement_transformer(), and old_complete_whileloop_transformer().

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

◆ complete_loop_transformer_list()

list complete_loop_transformer_list ( transformer  ltf,
transformer  pre,
loop  l 
)

loop body transformer

compute the loop body transformer

Since it is not stored, we need to go down recursively. A way to avoid this would be to always have sequences as loop bodies... Let's hope that perfectly nested loops are neither frequent nor deep!

compute the loop body precondition

You do not need a range to recurse. A full precondition with arguments is expected by complete_loop_transformer().

The final index incrementation is performed later by add_loop_index_exit_value()

btf = transformer_add_loop_index_incrementation(btf, l, pre);

compute the transformer when the loop is entered: T o T*

add the entry condition

but it seems to be in t already

t_enter = transformer_add_loop_index_initialization(t_enter, l);

It would make sense to apply the incrementation, but this is performed as a side effect by add_loop_index_exit_value(), which avoids unfeasability wrt the final loop bound.

add the exit condition, without any information pre to estimate the increment

FI: oops, pre is used in spite of previous comment

add initialization for the unconditional initialization of the loop index variable

It might be better not to compute useless transformer, but it's more readable that way. Since pre is information free, only loops with constant lower and upper bound and constant increment can benefit from this.

Parameters
ltftf
prere

Definition at line 2061 of file loop.c.

2062 {
2063  list tfl = list_undefined;
2067  /* loop body transformer */
2069  range r = loop_range(l);
2070  statement s = loop_body(l);
2071 
2072  pips_internal_error("Function not implemented.");
2073 
2074  pips_debug(8,"begin with loop precondition\n");
2075  ifdebug(8) {
2076  (void) print_transformer(pre);
2077  pips_debug(8,"and loop transformer:\n");
2078  (void) print_transformer(ltf);
2079  }
2080 
2081  /* compute the loop body transformer */
2082  if(statement_loop_p(s)) {
2083  /* Since it is not stored, we need to go down recursively. A way to
2084  avoid this would be to always have sequences as loop
2085  bodies... Let's hope that perfectly nested loops are neither
2086  frequent nor deep! */
2088  /* compute the loop body precondition */
2089  transformer raw_ipre = transformer_apply(ltf, pre);
2090  //transformer ipre = transformer_range(raw_ipre);
2091  //ipre = transformer_normalize(ipre, 2);
2092  /* You do not need a range to recurse. A full precondition with
2093  arguments is expected by complete_loop_transformer(). */
2094  btf = complete_loop_transformer(load_statement_transformer(s), raw_ipre, il);
2095  btf = transformer_normalize(btf, 2);
2096  //free_transformer(ipre);
2097  free_transformer(raw_ipre);
2098  }
2099  else {
2101  }
2102  /* The final index incrementation is performed later by add_loop_index_exit_value() */
2103  /* btf = transformer_add_loop_index_incrementation(btf, l, pre); */
2104 
2105  /* compute the transformer when the loop is entered: T o T* */
2106  t_enter = transformer_combine(transformer_dup(ltf), btf);
2107 
2108  ifdebug(8) {
2109  pips_debug(8, "entered loop transformer t_enter=\n");
2111  }
2112 
2113  /* add the entry condition */
2114  /* but it seems to be in t already */
2115  /* t_enter = transformer_add_loop_index_initialization(t_enter, l); */
2116 
2117  /* It would make sense to apply the incrementation, but this is
2118  performed as a side effect by add_loop_index_exit_value(), which
2119  avoids unfeasability wrt the final loop bound. */
2120  /*
2121  transformer t_inc = transformer_identity();
2122  t_inc = transformer_add_loop_index_incrementation(t_inc, l, pre);
2123  t_enter = transformer_combine(t_enter, t_inc);
2124  */
2125 
2126  /* add the exit condition, without any information pre to estimate the
2127  increment */
2128  transformer tmp = t_enter;
2129  /* FI: oops, pre is used in spite of previous comment */
2130  t_enter = add_loop_index_exit_value(t_enter, l, pre);
2131  transformer_free(tmp);
2132 
2133  ifdebug(8) {
2134  pips_debug(8, "entered and exited loop transformer t_enter=\n");
2136  }
2137 
2138  /* add initialization for the unconditional initialization of the loop
2139  index variable */
2140  tmp = transformer_undefined_p(pre)?
2142  transformer_dup(pre);
2143  t_skip = add_loop_index_initialization(tmp, l, pre);
2144  transformer_free(tmp);
2145  t_skip = add_loop_skip_condition(t_skip, l, pre);
2146  t_skip = transformer_normalize(t_skip, 2);
2147 
2148  ifdebug(8) {
2149  pips_debug(8, "skipped loop transformer t_skip=\n");
2151  }
2152 
2153  /* It might be better not to compute useless transformer, but it's more
2154  readable that way. Since pre is information free, only loops with
2155  constant lower and upper bound and constant increment can benefit
2156  from this. */
2157  if(empty_range_wrt_precondition_p(r, pre)) {
2158  tf = t_skip;
2159  free_transformer(t_enter);
2160  }
2161  else if(non_empty_range_wrt_precondition_p(r, pre)) {
2162  tf = t_enter;
2163  free_transformer(t_skip);
2164  }
2165  else {
2166  tf = transformer_convex_hull(t_enter, t_skip);
2167  free_transformer(t_enter);
2168  free_transformer(t_skip);
2169  }
2170 
2171  tf = transformer_normalize(tf, 2);
2172 
2173  ifdebug(8) {
2174  pips_debug(8, "full refined loop transformer tf=\n");
2176  pips_debug(8, "end\n");
2177  }
2178 
2179  return tfl;
2180 }

References add_loop_index_exit_value(), add_loop_index_initialization(), add_loop_skip_condition(), complete_loop_transformer(), empty_range_wrt_precondition_p(), external_value_name(), fprint_transformer(), free_transformer(), ifdebug, instruction_loop, list_undefined, load_statement_transformer(), loop_body, loop_range, non_empty_range_wrt_precondition_p(), pips_debug, pips_internal_error, print_transformer, statement_instruction, statement_loop_p(), transformer_apply(), transformer_combine(), transformer_convex_hull(), transformer_dup(), transformer_free(), transformer_identity(), transformer_normalize(), transformer_undefined, and transformer_undefined_p.

Referenced by instruction_to_transformer_list().

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

◆ complete_non_identity_statement_transformer()

transformer complete_non_identity_statement_transformer ( transformer  t,
transformer  pre,
statement  s 
)

FI: only implemented for while loops.

Parameters
prere

Definition at line 3685 of file ri_to_transformers.c.

3688 {
3689  return generic_complete_statement_transformer(t, pre, s, false);
3690 }
transformer generic_complete_statement_transformer(transformer t, transformer pre, statement s, bool identity_p)
Loops, do, for, while or repeat, have transformers linked to their body preconditions so as to comput...

References generic_complete_statement_transformer().

+ Here is the call graph for this function:

◆ complete_repeatloop_transformer()

transformer complete_repeatloop_transformer ( transformer  t_body_star,
transformer  pre,
whileloop  wl 
)
Parameters
t_body_star_body_star
prere
wll

Definition at line 1910 of file loop.c.

1913 {
1914  list tl = complete_repeatloop_transformer_list(t_body_star, pre, wl);
1916  return ct;
1917 }
list complete_repeatloop_transformer_list(transformer t_body_star, transformer __attribute__((unused)) pre, whileloop wl)
Definition: loop.c:1845
transformer transformer_list_to_transformer(list)
Reduce the transformer list ltl to one transformer using the convex hull operator.

References complete_repeatloop_transformer_list(), and transformer_list_to_transformer().

Referenced by complete_whileloop_transformer(), and generic_complete_statement_transformer().

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

◆ complete_repeatloop_transformer_list()

list complete_repeatloop_transformer_list ( transformer  ,
transformer  ,
whileloop   
)

◆ complete_statement_transformer()

transformer complete_statement_transformer ( transformer  t,
transformer  pre,
statement  s 
)

Returns the effective transformer ct for a given statement s.

t is the stored transformer. For loops, t is useful to compute the body preconditions but not to compute the loop postcondition. ct can be used to compute the statement s postcondition, no matter what kind of statement s is, and to compute the transformer of a higher-level statement enclosing s.

In other words, load_statement_transformer(s) does not always return a transformer which can be composed with another transformer or applied to a precondition. But statement_to_transformer() always returns such a transformer.

Always allocates a new transformer. This probably creates a memory leak when going up the internal representation because it was originally assumed that the transformer returned recursively was also the transformer stored at a lower level. This is changed because this function calls itself recursively. So now statement_to_transformer() returns a transformer which is not the transformer stored for the statement.

Parameters
prere

Definition at line 3677 of file ri_to_transformers.c.

3680 {
3681  return generic_complete_statement_transformer(t, pre, s, true);
3682 }

References generic_complete_statement_transformer().

Referenced by complete_forloop_transformer(), complete_forloop_transformer_list(), complete_repeatloop_transformer_list(), load_completed_statement_transformer(), new_complete_whileloop_transformer_list(), repeatloop_to_postcondition(), statement_to_transformer(), and whileloop_to_postcondition().

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

◆ complete_whileloop_transformer()

transformer complete_whileloop_transformer ( transformer  ltf,
transformer  pre,
whileloop  wl 
)

FI: I'm not sure this function is useful.

Parameters
ltftf
prere
wll

Definition at line 2183 of file loop.c.

2186 {
2189 
2190  if(evaluation_before_p(lt))
2191  t = new_complete_whileloop_transformer(ltf, pre, wl, false);
2192  else
2193  t = complete_repeatloop_transformer(ltf, pre, wl);
2194 
2195  return t;
2196 }
#define whileloop_evaluation(x)
Definition: ri.h:3166
#define evaluation_before_p(x)
Definition: ri.h:1159
transformer new_complete_whileloop_transformer(transformer t_body_star, transformer pre, whileloop wl, bool entered_p)
entered_p is used to for the execution of at least one iteration
Definition: loop.c:1833
transformer complete_repeatloop_transformer(transformer t_body_star, transformer pre, whileloop wl)
Definition: loop.c:1910

References complete_repeatloop_transformer(), evaluation_before_p, new_complete_whileloop_transformer(), transformer_undefined, and whileloop_evaluation.

Referenced by old_complete_whileloop_transformer().

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

◆ complete_whileloop_transformer_list()

list complete_whileloop_transformer_list ( transformer  ltf,
transformer  pre,
whileloop  wl 
)
Parameters
ltftf
prere
wll

Definition at line 2198 of file loop.c.

2201 {
2202  list tfl = NIL;
2204 
2205  if(evaluation_before_p(lt))
2206  tfl = new_complete_whileloop_transformer_list(ltf, pre, wl, false);
2207  else
2208  tfl = complete_repeatloop_transformer_list(ltf, pre, wl);
2209 
2210  return tfl;
2211 }
list new_complete_whileloop_transformer_list(transformer t_body_star, transformer pre, whileloop wl, bool entered_p __attribute__((__unused__)))
entered_p is used to for the execution of at least one iteration
Definition: loop.c:1781

References complete_repeatloop_transformer_list(), evaluation_before_p, new_complete_whileloop_transformer_list(), NIL, and whileloop_evaluation.

Referenced by instruction_to_transformer_list().

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

◆ compute_path_transformer()

transformer compute_path_transformer ( statement  ,
path  ,
path   
)

◆ compute_postcondition()

statement_mapping compute_postcondition ( statement  stat,
statement_mapping  post_map,
statement_mapping  pre_map 
)

statement_mapping compute_postcondition(stat, post_map, pre_map) statement stat; statement_mapping post_map, pre_map;

computes the postcondition mapping post_map from the precondition mapping pre_map and the related statement tree starting from stat. The rule applied is that the postcondition of one statement is the precondition of the following one. The last postcondition is arbitrary set to transformer_identity, what is not enough. (??? should I take the stat transformer?)

the initial postcondition is empty ???

Top-down definition

Parameters
stattat
post_mapost_map
pre_mapre_map

Definition at line 186 of file postcondition.c.

190 {
191  debug_on("SEMANTICS_POSTCONDITION_DEBUG_LEVEL");
192  pips_debug(1, "computing!\n");
193 
194  current_postcondition_map = post_map;
195  current_precondition_map = pre_map;
196 
197  /* the initial postcondition is empty ??? */
199 
200  /* Top-down definition */
202 
205 
206  debug_off();
207  return post_map;
208 }
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
#define debug_on(env)
Definition: misc-local.h:157
#define debug_off()
Definition: misc-local.h:160
#define hash_table_undefined
Value of an undefined hash_table.
Definition: newgen_hash.h:49
static statement_mapping current_postcondition_map
Definition: postcondition.c:67
#define StorePost(stat, val)
Definition: postcondition.c:69
static bool postcondition_filter(statement stat)
filter used by gen_recurse: Top-down computation of the postcondition mapping
Definition: postcondition.c:88
static statement_mapping current_precondition_map
filtering of postconditions
Definition: postcondition.c:66
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362

References current_postcondition_map, current_precondition_map, debug_off, debug_on, gen_null(), gen_recurse, hash_table_undefined, pips_debug, postcondition_filter(), statement_domain, StorePost, and transformer_identity().

Referenced by set_resources_for_module().

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

◆ condition_false_wrt_precondition_p()

bool condition_false_wrt_precondition_p ( expression  c,
transformer  p 
)

Definition at line 285 of file utils.c.

286 {
287  bool non_empty = false;
288 
289  non_empty = check_condition_wrt_precondition(c, p, false);
290 
291  return non_empty;
292 }
bool check_condition_wrt_precondition(expression c, transformer pre, bool check_true)
Definition: utils.c:294

References check_condition_wrt_precondition().

Referenced by old_complete_whileloop_transformer(), and standard_whileloop_to_transformer().

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

◆ condition_to_transformer()

transformer condition_to_transformer ( expression  cond,
transformer  pre,
bool  veracity 
)

To capture side effects and to add C twist for numerical conditions.

Argument pre may be undefined.

Beware of tricky conditions using the comma or the conditional operator, although they should be handled as the default case, using effects.

upwards should be set to false when computing preconditions (but we have no way to know) or when computing tramsformers in context. And set to true in other cases. upwards is a way to gain execution time at the expense of precision. This speed/accuracy tradeoff has evolved with CPU technology.

If a comma operator is used, the test is the last expression

FI: quid of a conditional operator? e.g. "x>0?1<m:1<n"

FI: quid of assignment operator? e.g. "i = j = k = 1"

FI: we probably need a function tcond = expression_to_condition(cond)

C comparison operators return an integer value

FI: not good when side effects in cond

In case, there are side-effects in the condition. This is very unlikely for standard code and should be simplified with a test to transformer_identity_p(tf)

Make sure you can handle this kind of variable.

This test is added for Semantics-New/transformer01.c which tests a pointer. The underlying bug may still be there when pointers are analyzed by PIPS.

tmpv != 0

tmpv==0

Not yet? We may be in a = c? x : y; or in e1, e2,...; Does it matter?

May be dangerous if this routine is called internally to another routine using temporary variables...

reset_temporary_value_counter();

Parameters
condond
prere
veracityeracity

Definition at line 5348 of file expression.c.

5351 {
5353 
5354  if(expression_cast_p(cond)) {
5356  tf = condition_to_transformer(nc, pre, veracity);
5357  }
5358  else {
5359  //list el = expression_to_proper_effects(cond);
5361  transformer safe_pre = transformer_undefined_p(pre)?
5363  transformer_range(pre);
5364  basic eb = basic_of_expression(cond);
5365  bool relation_p = false;
5366  /* upwards should be set to false when computing preconditions (but
5367  we have no way to know) or when computing tramsformers in
5368  context. And set to true in other cases. upwards is a way to gain
5369  execution time at the expense of precision. This speed/accuracy
5370  tradeoff has evolved with CPU technology. */
5371  bool upwards = false;
5372  expression tcond = cond; // By default; not true for the comma operations
5373 
5374  /* If a comma operator is used, the test is the last expression */
5375  /* FI: quid of a conditional operator? e.g. "x>0?1<m:1<n" */
5376  /* FI: quid of assignment operator? e.g. "i = j = k = 1" */
5377  /* FI: we probably need a function tcond = expression_to_condition(cond) */
5378  if(expression_call_p(cond)) {
5379  call c = syntax_call(expression_syntax(cond));
5380  entity op = call_function(c);
5381  if(ENTITY_COMMA_P(op)) {
5382  list args = call_arguments(c);
5383  tcond = EXPRESSION(CAR(gen_last(args)));
5384  tf = safe_expression_to_transformer(cond, pre);
5385  }
5386  }
5387  if(transformer_undefined_p(tf)) {
5388  tf = transformer_identity();
5389  }
5390 
5391  /* C comparison operators return an integer value */
5392  if(!basic_logical_p(eb) && expression_call_p(tcond)) {
5394 
5395  relation_p = ENTITY_LOGICAL_OPERATOR_P(op);
5396  //relation_p = ENTITY_RELATIONAL_OPERATOR_P(op);
5397  }
5398 
5399  if(basic_logical_p(eb)) {
5400  // entity tmpv = make_local_temporary_value_entity_with_basic(eb);
5401  //tf = logical_expression_to_transformer(tmpv, cond, safe_pre, true);
5402  //tf = transformer_add_condition_information_updown
5403  // (transformer_identity(), cond, safe_pre, veracity, upwards);
5404  /* FI: not good when side effects in cond */
5405  //tf = transformer_add_condition_information_updown
5406  // (copy_transformer(safe_pre), cond, safe_pre, veracity, upwards);
5408  (tf, tcond, safe_pre, veracity, upwards);
5409  tf = transformer_apply(ctf, safe_pre);
5410  free_transformer(ctf);
5411  }
5412  else if(relation_p) {
5413  //tf = transformer_add_condition_information_updown
5414  // (transformer_identity(), cond, safe_pre, veracity, upwards);
5415  //tf = transformer_add_condition_information_updown
5416  // (copy_transformer(safe_pre), cond, safe_pre, veracity, upwards);
5417  /* In case, there are side-effects in the condition. This is very
5418  unlikely for standard code and should be simplified with a
5419  test to transformer_identity_p(tf) */
5420  transformer new_pre = transformer_apply(tf, safe_pre);
5421  transformer new_pre_r = transformer_range(new_pre);
5422  new_pre_r = transformer_normalize(new_pre_r, 2);
5424  (transformer_identity(), tcond, new_pre_r, veracity, upwards);
5426  ctf = transformer_normalize(ctf, 2);
5427  tf = transformer_combine(tf, ctf);
5428  free_transformer(ctf);
5429  free_transformer(new_pre);
5430  free_transformer(new_pre_r);
5431  }
5432  else {
5433  /* Make sure you can handle this kind of variable.
5434 
5435  This test is added for Semantics-New/transformer01.c which
5436  tests a pointer. The underlying bug may still be there when
5437  pointers are analyzed by PIPS.
5438  */
5439  if(analyzed_basic_p(eb)) {
5441  transformer ctf = safe_any_expression_to_transformer(tmpv, tcond, safe_pre, true);
5442  tf = transformer_combine(tf, ctf);
5443  if(veracity) {
5444  /* tmpv != 0 */
5447 
5448  ifdebug(8) {
5449  fprintf(stderr, "tf_plus %p:\n", tf_plus);
5450  dump_transformer(tf_plus);
5451  fprintf(stderr, "tf_minus %p:\n", tf_minus);
5452  dump_transformer(tf_minus);
5453  }
5454 
5455  free_transformer(tf);
5456  tf = transformer_convex_hull(tf_plus, tf_minus);
5457  free_transformer(tf_plus);
5458  free_transformer(tf_minus);
5459  }
5460  else {
5461  /* tmpv==0 */
5462  tf = transformer_add_sign_information(tf, tmpv, 0);
5463  }
5464  }
5465  }
5466 
5467  if(transformer_undefined_p(tf))
5468  tf = effects_to_transformer(el);
5469  else {
5470  /* Not yet? We may be in a = c? x : y; or in e1, e2,...; Does it matter? */
5472  //reset_temporary_value_counter();
5473  }
5474  /* May be dangerous if this routine is called internally to another
5475  routine using temporary variables... */
5476  /* reset_temporary_value_counter(); */
5477 
5478  gen_full_free_list(el);
5479  free_basic(eb);
5480  free_transformer(safe_pre);
5481  }
5482 
5483  return tf;
5484 }
transformer transformer_add_sign_information(transformer tf, entity v, int v_sign)
CHANGE THIS NAME: no loop index please, it's not directly linked to loops!!!
Definition: basic.c:200
list expression_to_proper_constant_path_effects(expression)
#define ENTITY_COMMA_P(e)
#define ENTITY_LOGICAL_OPERATOR_P(e)
Attention : This definition is different with the Fortran Standard where the logical operators are th...
bool expression_cast_p(expression e)
Definition: expression.c:450
cast expression_cast(expression e)
Definition: expression.c:455
#define cast_expression(x)
Definition: ri.h:747
static transformer transformer_add_condition_information_updown(transformer, expression, transformer, bool, bool)
call transformer_add_condition_information_updown() recursively on both sub-expressions if veracity =...
Definition: expression.c:961
bool analyzed_basic_p(basic)
The basic corresponds to one of the analyzed types.
Definition: value.c:337
entity make_local_temporary_value_entity_with_basic(basic)
Definition: value.c:620

References analyzed_basic_p(), basic_logical_p, basic_of_expression(), call_arguments, call_function, CAR, cast_expression, copy_transformer(), dump_transformer, effects_to_transformer(), ENTITY_COMMA_P, ENTITY_LOGICAL_OPERATOR_P, EXPRESSION, expression_call_p(), expression_cast(), expression_cast_p(), expression_syntax, expression_to_proper_constant_path_effects(), fprintf(), free_basic(), free_transformer(), gen_full_free_list(), gen_last(), ifdebug, make_local_temporary_value_entity_with_basic(), safe_any_expression_to_transformer(), safe_expression_to_transformer(), syntax_call, transformer_add_condition_information_updown(), transformer_add_sign_information(), transformer_apply(), transformer_combine(), transformer_convex_hull(), transformer_identity(), transformer_normalize(), transformer_range(), transformer_temporary_value_projection(), transformer_undefined, and transformer_undefined_p.

Referenced by any_conditional_to_transformer(), complete_forloop_transformer(), complete_forloop_transformer_list(), complete_repeatloop_transformer_list(), conditional_to_transformer(), forloop_to_postcondition(), forloop_to_transformer(), intrinsic_to_transformer(), intrinsic_to_transformer_list(), new_complete_whileloop_transformer_list(), new_whileloop_to_k_transformer(), new_whileloop_to_transformer(), repeatloop_to_postcondition(), repeatloop_to_transformer(), simplify_boolean_expression_with_precondition(), test_to_postcondition(), test_to_transformer(), test_to_transformer_list(), and whileloop_to_postcondition().

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

◆ condition_true_wrt_precondition_p()

bool condition_true_wrt_precondition_p ( expression  c,
transformer  p 
)

A condition cannot be tested exactly wrt a precondition You can try to prove that it is always true (because it is never false) or you can try to prove that it is always false (because it is never true).

In both case, you may fail and be unable to decide emptiness or non-emptiness.

Definition at line 276 of file utils.c.

277 {
278  bool empty = false;
279 
281 
282  return empty;
283 }
@ empty
b1 < bj -> h1/hj = empty
Definition: union-local.h:64

References check_condition_wrt_precondition(), and empty.

Referenced by old_complete_whileloop_transformer().

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

◆ conditional_to_transformer()

transformer conditional_to_transformer ( expression  cond,
expression  te,
expression  fe,
transformer  pre,
list  ef 
)

FI: not too smart to start with the special case with no value returned, just side-effects...

Parameters
condond
tee
fee
prere
eff

Definition at line 5488 of file expression.c.

5493 {
5495  transformer ttf = condition_to_transformer(cond, pre, true);
5496  transformer t_pre = transformer_apply(ttf, pre);
5497  transformer t_pre_r = transformer_range(t_pre);
5498  transformer tet = safe_expression_to_transformer(te, t_pre_r);
5499  transformer ftf = condition_to_transformer(cond, pre, false);
5500  transformer f_pre = transformer_apply(ftf, pre);
5501  transformer f_pre_r = transformer_range(f_pre);
5502  transformer fet = safe_expression_to_transformer(fe, f_pre_r);
5503 
5504  ttf = transformer_combine(ttf, tet);
5505  ftf = transformer_combine(ftf, fet);
5506  tf = transformer_convex_hull(ttf, ftf);
5507 
5508  free_transformer(ttf);
5509  free_transformer(ftf);
5510  free_transformer(tet);
5511  free_transformer(fet);
5512  free_transformer(t_pre_r);
5513  free_transformer(f_pre_r);
5514  free_transformer(t_pre);
5515  free_transformer(f_pre);
5516 
5517  if(transformer_undefined_p(tf))
5518  tf = effects_to_transformer(ef);
5519  return tf;
5520 }

References condition_to_transformer(), effects_to_transformer(), free_transformer(), safe_expression_to_transformer(), transformer_apply(), transformer_combine(), transformer_convex_hull(), transformer_range(), transformer_undefined, and transformer_undefined_p.

Referenced by intrinsic_to_transformer(), and intrinsic_to_transformer_list().

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

◆ cumulated_effects_map_print()

void cumulated_effects_map_print ( void  )

ca n'a rien a` faire ici, et en plus, il serait plus inte'ressant d'avoir une fonction void statement_map_print(statement_mapping htp)

hash_table_print_header (htp,f);

Definition at line 1549 of file dbm_interface.c.

1550 {
1551  FILE * f =stderr;
1553 
1554  /* hash_table_print_header (htp,f); */
1555 
1556  STATEMENT_EFFECTS_MAP(k, v, {
1557  fprintf(f, "\n\n%td", statement_ordering((statement) k));
1559  },
1560  htp);
1561 }
statement_effects get_cumulated_rw_effects(void)
#define STATEMENT_EFFECTS_MAP(k, v, c, f)
Definition: effects.h:1057
#define effects_effects(x)
Definition: effects.h:710
#define print_effects(e)
Definition: print.c:334
#define statement_ordering(x)
Definition: ri.h:2454

References effects_effects, f(), fprintf(), get_cumulated_rw_effects(), print_effects, STATEMENT_EFFECTS_MAP, and statement_ordering.

+ Here is the call graph for this function:

◆ cycle_to_flow_sensitive_postconditions_or_transformers()

transformer cycle_to_flow_sensitive_postconditions_or_transformers ( list  partition,
unstructured  ndu,
hash_table  ancestor_map,
hash_table  scc_map,
control_mapping  fix_point_map,
transformer  e_pre,
transformer  n_pre,
hash_table  control_postcondition_map,
bool  postcondition_p 
)

Compute transformers or preconditions.

Parameters
partitionartition
ndudu
ancestor_mapncestor_map
scc_mapcc_map
fix_point_mapix_point_map
e_pre_pre
n_pre_pre
control_postcondition_mapontrol_postcondition_map
postcondition_postcondition_p

Definition at line 1744 of file unstructured.c.

1754 {
1756 
1758  (partition, ndu, ancestor_map, scc_map, fix_point_map, e_pre, n_pre,
1759  control_postcondition_map, postcondition_p, false);
1760 
1761  return tf;
1762 }
transformer dag_or_cycle_to_flow_sensitive_postconditions_or_transformers(list partition, unstructured ndu, hash_table ancestor_map, hash_table scc_map, control_mapping fix_point_map, transformer e_pre, transformer n_pre, hash_table control_postcondition_map, bool postcondition_p, bool is_dag)
Should ndu be a dag or a cycle?

References dag_or_cycle_to_flow_sensitive_postconditions_or_transformers(), and transformer_undefined.

Referenced by process_ready_node().

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

◆ dag_or_cycle_to_flow_sensitive_postconditions_or_transformers()

transformer dag_or_cycle_to_flow_sensitive_postconditions_or_transformers ( list  partition,
unstructured  ndu,
hash_table  ancestor_map,
hash_table  scc_map,
control_mapping  fix_point_map,
transformer  e_pre,
transformer  n_pre,
hash_table  control_postcondition_map,
bool  postcondition_p,
bool  is_dag 
)

Should ndu be a dag or a cycle?

forward reachable nodes in u

The whole business could be simplified by using a larger definition of "to_be_processed".

wide_forward_control_map_get_blocs(unstructured_control(u), &to_be_processed);

Take care of unreachable nodes

FI: Wouldn't it be better to clean up the unstructured? Aren't they supposed to be clean? This piece of code contradict get_control_precondition() where the problem could be fixed at a lower cost. Another place where the problem is handled is ready_to_be_processed_p(), but it is called on still_to_be_processed, which does not take into account unreachable nodes. To make things worse, the daVinci printouts only include, most of the time, only reachable nodes.

Take care of the entry node

The entry node must be handled in a specific way... but not in the specific way implemented in process_ready_node() which only deals with DAG's. The entry node cannot be a meaningless control node.

Since control nodes have been replicated, it is difficult to predict if es has already been processed or not.

make_control_postcondition_map();

Take care of the forward reachable control nodes

process forward

right away because c's cdr might be modified

Compute fix point transformer for cycle

Compute the convex hull of the paths associated to each predecessor of the entry. Since this is a cycle, preds cannot be empty.

transformer fp_tf_plus = transformer_undefined;

If an entry range is known, do not use it as there may be more than one occurence of the cycle and more than one entry range. Keep this refinement to the precondition computation phase? It might be too late. The the data structure should be change to store more than one fix point per cycle.

Not convincing anyway: you should apply fp_tf_plus to e_pre for the next two lines to make sense.

Use the + fix point to preserve more information about the output and do not forget to perform a convex hull when you need a * fix point in process_ready_node()

Instead of computing the convex hull over all paths before computing the fix point, compute the fix point of a list of transformers.

e may have many synonyms

fix point are unique for all replication of a cycle

each cycle replication has its own fix-point

We might want to return the corresponding fix point?

Parameters
partitionartition
ndudu
ancestor_mapncestor_map
scc_mapcc_map
fix_point_mapix_point_map
e_pre_pre
n_pre_pre
control_postcondition_mapontrol_postcondition_map
postcondition_postcondition_p
is_dags_dag

Definition at line 1509 of file unstructured.c.

1520 {
1522  list to_be_processed = NIL; /* forward reachable nodes in u */
1523  list still_to_be_processed = NIL;
1524  list already_processed = NIL;
1525  list cannot_be_reached = NIL;
1526 
1527  ifdebug(2) {
1528  pips_debug(2, "Begin for unstructured %p with e_pre=%p:\n", ndu, e_pre);
1529  print_transformer(e_pre);
1530  }
1531 
1532  /* The whole business could be simplified by using a larger definition of "to_be_processed". */
1533  /* wide_forward_control_map_get_blocs(unstructured_control(u), &to_be_processed); */
1534  forward_control_map_get_blocs(unstructured_control(ndu), &to_be_processed);
1535  control_map_get_blocs(unstructured_control(ndu), &cannot_be_reached);
1536  still_to_be_processed = gen_copy_seq(to_be_processed);
1537  gen_list_and_not(&cannot_be_reached, to_be_processed);
1538 
1539  /* Take care of unreachable nodes */
1540 
1541  if(!ENDP(cannot_be_reached)) {
1542  /* FI: Wouldn't it be better to clean up the unstructured? Aren't they
1543  supposed to be clean? This piece of code contradict
1544  get_control_precondition() where the problem could be fixed at a
1545  lower cost. Another place where the problem is handled is
1546  ready_to_be_processed_p(), but it is called on
1547  still_to_be_processed, which does not take into account unreachable
1548  nodes. To make things worse, the daVinci printouts only include,
1549  most of the time, only reachable nodes. */
1550  ifdebug(3) {
1551  pips_debug(3, "Process unreachable nodes in unstructured %p\n", ndu);
1552  print_control_node_unss_sem(cannot_be_reached);
1553  }
1554  MAP(CONTROL, cbrc, {
1555  if(!meaningless_control_p(cbrc)) {
1557  store_control_postcondition(cbrc, etf, control_postcondition_map);
1558  }
1559  }, cannot_be_reached);
1560  gen_free_list(cannot_be_reached);
1561  cannot_be_reached = list_undefined;
1562  }
1563 
1564  pips_assert("Node lists are defined", !list_undefined_p(to_be_processed)
1565  && !list_undefined_p(still_to_be_processed) && ENDP(already_processed) );
1566 
1567  /* Take care of the entry node */
1568 
1569  if(!is_dag && !postcondition_p) {
1570  /* The entry node must be handled in a specific way... but not in the
1571  specific way implemented in process_ready_node() which only deals
1572  with DAG's. The entry node cannot be a meaningless control node. */
1573  control e = unstructured_control(ndu);
1574  statement es = control_statement(e);
1578 
1579  /* Since control nodes have been replicated, it is difficult to
1580  predict if es has already been processed or not. */
1581  if(transformer_undefined_p(etf)) {
1582  etf = statement_to_transformer(es, n_pre);
1583  }
1584 
1585  post = transformer_apply(etf, init);
1586 
1587  store_control_postcondition(e, post, control_postcondition_map);
1588 
1589  gen_remove(&still_to_be_processed, e);
1590  already_processed = CONS(CONTROL, e, NIL);
1591  }
1592 
1593  /* make_control_postcondition_map(); */
1594 
1595  /* Take care of the forward reachable control nodes */
1596 
1597  while(!ENDP(still_to_be_processed)) {
1598  int count = -1;
1599  do {
1600  list l = list_undefined;
1601 
1602  /* process forward */
1603  pips_debug(5, "Try forward processing for\n");
1604  ifdebug(2) print_control_node_unss_sem(still_to_be_processed);
1605 
1606  count = 0;
1607  for(l=still_to_be_processed; !ENDP(l); ) {
1608  control c = CONTROL(CAR(l));
1609  POP(l); /* right away because c's cdr might be modified */
1610  if(meaningless_control_p(c)
1611  || ready_to_be_processed_p(c, to_be_processed,
1612  still_to_be_processed,
1613  already_processed,
1614  control_postcondition_map)) {
1615  if(!meaningless_control_p(c)) {
1616  process_ready_node(c, e_pre, n_pre, ndu, control_postcondition_map,
1617  ancestor_map, scc_map, partition, fix_point_map, postcondition_p);
1618  }
1619  gen_remove(&still_to_be_processed, c);
1620  already_processed = gen_append(already_processed, CONS(CONTROL, c, NIL));
1621  count++;
1622  }
1623  }
1624  } while(count!=0);
1625  if(!ENDP(still_to_be_processed)) {
1626  pips_assert("still_to_be_processed is empty because of the Bourdoncle's restructuring",
1627  false);
1628  }
1629  }
1630 
1631  /* Compute fix point transformer for cycle */
1632  if(!is_dag && !postcondition_p) {
1634  control e = unstructured_control(ndu);
1635  list preds = control_predecessors(e);
1636  control e_a = control_undefined;
1637  // FI: we also need SEMANTICS_USE_DERIVATIVE_LIST = TRUE
1638  // but this should be soon the default option
1639  if(!get_bool_property("SEMANTICS_USE_TRANSFORMER_LISTS")) {
1640  /* Compute the convex hull of the paths associated to each predecessor
1641  of the entry. Since this is a cycle, preds cannot be empty. */
1642  control pred = CONTROL(CAR(preds));
1643  transformer path_tf =
1644  load_arc_precondition(pred, e, control_postcondition_map);
1645  /* transformer fp_tf_plus = transformer_undefined; */
1646 
1647  POP(preds);
1648  FOREACH(CONTROL, pred, preds) {
1649  transformer pred_tf =
1650  load_arc_precondition(pred, e, control_postcondition_map);
1651  transformer old_path_tf = path_tf;
1652 
1653  pips_assert("Partial path transformer pred_tf is defined",
1654  !transformer_undefined_p(pred_tf));
1655  path_tf = transformer_convex_hull(old_path_tf, pred_tf);
1656  free_transformer(old_path_tf);
1657  }
1658 
1659  fp_tf = (*transformer_fix_point_operator)(path_tf);
1660  /* If an entry range is known, do not use it as there may be more than
1661  one occurence of the cycle and more than one entry range. Keep this
1662  refinement to the precondition computation phase? It might be too
1663  late. The the data structure should be change to store more than
1664  one fix point per cycle. */
1665  /* Not convincing anyway: you should apply fp_tf_plus to e_pre for the
1666  next two lines to make sense. */
1667  /* Use the + fix point to preserve more information about the output
1668  and do not forget to perform a convex hull when you need a * fix
1669  point in process_ready_node() */
1670  fp_tf = transformer_combine(fp_tf, path_tf);
1671  /*
1672  fp_tf = transformer_convex_hull(fp_tf_plus, e_pre);
1673  */
1674  free_transformer(path_tf);
1675  }
1676  else {
1677  /* Instead of computing the convex hull over all paths before
1678  computing the fix point, compute the fix point of a list of
1679  transformers. */
1680  list tl = NIL;
1681  FOREACH(CONTROL, pred, preds) {
1682  transformer pred_tf =
1683  load_arc_precondition(pred, e, control_postcondition_map);
1684  tl = CONS(TRANSFORMER, pred_tf, tl);
1685  }
1687  gen_free_list(tl);
1688  }
1689 
1690  /* e may have many synonyms */
1691 
1692  if(!get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT")) {
1693  /* fix point are unique for all replication of a cycle */
1694  e_a = control_to_ancestor(e, ancestor_map);
1695  }
1696  else {
1697  /* each cycle replication has its own fix-point */
1698  e_a = e;
1699  }
1700  store_control_fix_point(e_a, fp_tf, fix_point_map);
1701 
1702  /* We might want to return the corresponding fix point? */
1703  tf = fp_tf;
1704  }
1705 
1706  gen_free_list(to_be_processed);
1707  to_be_processed = list_undefined;
1708  gen_free_list(still_to_be_processed);
1709  still_to_be_processed = list_undefined;
1710  gen_free_list(already_processed);
1711  already_processed = list_undefined;
1712 
1713  ifdebug(2) {
1714  pips_debug(2, "End for %s of %s %p with entry node %s and with transformer %p\n",
1715  postcondition_p? "postcondition" : "transformer",
1716  is_dag? "dag" : "cycle", ndu,
1718  print_transformer(tf);
1719  }
1720 
1721  return tf;
1722 }
static int count
Definition: SDG.c:519
bool meaningless_control_p(control c)
Is exported to exploit non-deterministic control flow graphs.
Definition: bourdoncle.c:154
control control_to_ancestor(control vertex, hash_table ancestor_map)
If vertex is an ancestor control node from the input control graph, return vertex,...
Definition: bourdoncle.c:854
void forward_control_map_get_blocs(c, l)
Build recursively the list of all controls forward-reachable from a control of an unstructured.
Definition: control.c:208
void control_map_get_blocs(control c, list *l)
Build recursively the list of all controls reachable from a control of an unstructured.
Definition: control.c:75
#define list_undefined_p(c)
Return if a list is undefined.
Definition: newgen_list.h:75
void gen_remove(list *cpp, const void *o)
remove all occurences of item o from list *cpp, which is thus modified.
Definition: list.c:685
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
void gen_list_and_not(list *a, const list b)
Compute A = A inter non B:
Definition: list.c:963
list gen_append(list l1, const list l2)
Definition: list.c:471
#define MAP(_map_CASTER, _map_item, _map_code, _map_list)
Apply/map an instruction block on all the elements of a list (old fashioned)
Definition: newgen_list.h:226
string statement_identification(statement)
Like external_statement_identification(), but with internal information, the hexadecimal address of t...
Definition: statement.c:1700
#define unstructured_control
After the modification in Newgen: unstructured = entry:control x exit:control we have create a macro ...
static int init
Maximal value set for Fortran 77.
Definition: entity.c:320
#define control_undefined
Definition: ri.h:916
#define TRANSFORMER(x)
TRANSFORMER.
Definition: ri.h:2841
#define control_predecessors(x)
Definition: ri.h:943
#define CONTROL(x)
CONTROL.
Definition: ri.h:910
#define control_statement(x)
Definition: ri.h:941
transformer statement_to_transformer(statement s, transformer spre)
stmt precondition
static void store_control_postcondition(control c, transformer post, control_mapping control_postcondition_map)
Definition: unstructured.c:245
static transformer load_arc_precondition(control, control, control_mapping)
forward declaration
Definition: unstructured.c:468
static void process_ready_node(control c, transformer pre_entry, transformer n_pre, unstructured u, control_mapping control_postcondition_map, hash_table ancestor_map, hash_table scc_map, list partition, control_mapping fix_point_map, bool postcondition_p)
Definition: unstructured.c:630
static void store_control_fix_point(control c, transformer fptf, control_mapping control_fix_point_map)
Definition: unstructured.c:382
static bool ready_to_be_processed_p(control c, list to_be_processed, list still_to_be_processed, list already_processed, control_mapping control_postcondition_map)
a control is ready to be processed if all its predecessors have known postconditions or can receive a...
Definition: unstructured.c:427
static void print_control_node_unss_sem(list l)
Definition: unstructured.c:143
transformer transformer_list_transitive_closure_plus(list)
Compute (U tfl)+.

References CAR, CONS, CONTROL, control_map_get_blocs(), control_predecessors, control_statement, control_to_ancestor(), control_undefined, count, ENDP, FOREACH, forward_control_map_get_blocs(), free_transformer(), gen_append(), gen_copy_seq(), gen_free_list(), gen_list_and_not(), gen_remove(), get_bool_property(), ifdebug, init, list_undefined, list_undefined_p, load_arc_precondition(), load_statement_transformer(), MAP, meaningless_control_p(), NIL, pips_assert, pips_debug, POP, print_control_node_unss_sem(), print_transformer, process_ready_node(), ready_to_be_processed_p(), statement_identification(), statement_to_transformer(), store_control_fix_point(), store_control_postcondition(), TRANSFORMER, transformer_apply(), transformer_combine(), transformer_convex_hull(), transformer_empty(), transformer_identity(), transformer_list_transitive_closure_plus(), transformer_undefined, transformer_undefined_p, and unstructured_control.

Referenced by cycle_to_flow_sensitive_postconditions_or_transformers(), and dag_to_flow_sensitive_postconditions_or_transformers().

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

◆ dag_to_flow_sensitive_postconditions_or_transformers()

transformer dag_to_flow_sensitive_postconditions_or_transformers ( list  partition,
unstructured  ndu,
hash_table  ancestor_map,
hash_table  scc_map,
control_mapping  fix_point_map,
transformer  e_pre,
transformer  n_pre,
hash_table  control_postcondition_map,
bool  postcondition_p 
)

Compute transformers or preconditions.

Parameters
partitionartition
ndudu
ancestor_mapncestor_map
scc_mapcc_map
fix_point_mapix_point_map
e_pre_pre
n_pre_pre
control_postcondition_mapontrol_postcondition_map
postcondition_postcondition_p

Definition at line 1724 of file unstructured.c.

1734 {
1736 
1738  (partition, ndu, ancestor_map, scc_map, fix_point_map, e_pre, n_pre,
1739  control_postcondition_map, postcondition_p, true);
1740 
1741  return tf;
1742 }

References dag_or_cycle_to_flow_sensitive_postconditions_or_transformers(), and transformer_undefined.

Referenced by unstructured_to_flow_sensitive_postconditions_or_transformers().

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

◆ data_to_precondition()

transformer data_to_precondition ( entity  m)

restricted to variables with effects.

Definition at line 526 of file ri_to_preconditions.c.

527 {
529  list le = effects_to_entity_list(lef);
531  gen_free_list(le);
532  return pre;
533 }
list load_module_intraprocedural_effects(entity e)
list effects_to_entity_list(list lef)
returns an allocated list of entities that appear in lef.

References data_to_prec_for_variables(), effects_to_entity_list(), gen_free_list(), and load_module_intraprocedural_effects().

Referenced by generic_module_name_to_transformers().

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

◆ declaration_to_transformer()

transformer declaration_to_transformer ( entity  v,
transformer  pre 
)

Note: initializations of static variables are not used as transformers but to initialize the program precondition.

It is not assumed that entity_has_values_p(v)==TRUE A write effect on the declared variable is assumed as required by Beatrice Creusillet for region computation.

if(place_holder_variable_p(v)) {

tf = transformer_identity();

}

FI: the initialization expression might have relevant side-effects? This could ba handled by generalizing variable_to_initial_expression() and by returning expression_undefined incase of failure instead of aborting.

Use the dimension expressions and the initial value

add type information because it will not be done later since declarations with no initialization lead to an identity transformer

Parameters
prere

Definition at line 580 of file ri_to_transformers.c.

581 {
583 
584  pips_debug(8, "Transformer for declaration of \"%s\"\n", entity_name(v));
585 
586  // FI: should not be useful here
587  /* if(place_holder_variable_p(v)) { */
588  /* tf = transformer_identity(); */
589  /* } */
590  if(false && !entity_has_values_p(v)) {
591  /* FI: the initialization expression might have relevant
592  side-effects? This could ba handled by generalizing
593  variable_to_initial_expression() and by returning
594  expression_undefined incase of failure instead of aborting. */
595  tf = transformer_identity();
596  }
597  else if(variable_static_p(v)) {
598  if(get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT"))
599  tf = transformer_range(pre);
600  else
601  tf = transformer_identity();
602  }
603  else {
604  /* Use the dimension expressions and the initial value */
605  transformer prer = transformer_range(pre);
607  free_transformer(prer);
608  transformer npre = transformer_apply(dt, pre);
609  transformer nr = transformer_range(npre);
611  tf = dt;
612  if(!expression_undefined_p(ie)) {
614  tf = transformer_combine(tf, itf);
615  free_transformer(itf);
616  free_expression(ie);
617  }
618  else {
619  if(entity_has_values_p(v)) {
620  /* add type information because it will not be done later
621  since declarations with no initialization lead to an
622  identity transformer */
623  if(get_bool_property("SEMANTICS_USE_TYPE_INFORMATION")
624  || get_bool_property("SEMANTICS_USE_TYPE_INFORMATION_IN_PRECONDITIONS")) {
626  }
627  }
628  }
629  free_transformer(npre);
630  free_transformer(nr);
631  }
632 
633  pips_assert("tf is defined", !transformer_undefined_p(tf));
634 
635  ifdebug(8) {
636  pips_debug(8, "Ends with:\n");
637  (void) print_transformer(tf);
638  }
639 
640  return tf;
641 }
expression variable_initial_expression(entity)
Returns a copy of the initial (i.e.
Definition: variable.c:1899
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
#define expression_undefined_p(x)
Definition: ri.h:1224
transformer safe_assigned_expression_to_transformer(entity v, expression expr, transformer pre)
Always returns a fully defined transformer.
transformer dimensions_to_transformer(entity v, transformer pre)
Assumes that entity_has_values_p(v) holds.
void transformer_add_variable_type_information(transformer, entity)
Definition: type.c:168

References dimensions_to_transformer(), entity_has_values_p(), entity_name, expression_undefined_p, free_expression(), free_transformer(), get_bool_property(), ifdebug, pips_assert, pips_debug, print_transformer, safe_assigned_expression_to_transformer(), transformer_add_variable_type_information(), transformer_apply(), transformer_combine(), transformer_identity(), transformer_range(), transformer_undefined, transformer_undefined_p, variable_initial_expression(), and variable_static_p().

Referenced by declarations_to_transformer(), declarations_to_transformer_list(), and propagate_preconditions_in_declarations().

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

◆ declaration_to_transformer_list()

list declaration_to_transformer_list ( entity  v,
transformer  pre 
)

ri_to_transformer_lists.c

ri_to_transformer_lists.c

This development was prompted by the last example found in the paper by Schrammel and Jeannet at NSAD 2010. See test cases schrammel04, 05 and 06. The minimal goal is to avoid the indentity transformer when performing the convex hull of several transformers.

This could also be useful to automatize the handling of tests within a loop using the technique presented at NSAD 2010 by Ancourt & al. The control structure

"while(c) if(t) T; else F;"

is replaced by

"while(c) {while(c&&t) T; while(c&& !t) F;}".

This replacement could be performed on the equations instead of requiring a program transformation. semantical analysis

phasis 3: compute transformer lists from statements and statement transformers

For refined precondition analysis. Keep track of all control paths within sequences

Francois Irigoin, September 2010 include <stdlib.h> Note: initializations of static variables are not used as transformers but to initialize the program precondition. It is not assumed that entity_has_values_p(v)==true A write effect on the declared variable is assumed as required by Beatrice Creusillet for region computation.

FI: the initialization expression might have relevant side-effects? This could ba handled by generalizing variable_to_initial_expression() and by returning expression_undefined incase of failure instead of aborting.

Use the dimension expressions and the initial value

FI: I preserve the code below in case I have problems with integer typing in the future

Parameters
prere

Definition at line 100 of file ri_to_transformer_lists.c.

101 {
102  list tfl = NIL;
104 
105  pips_internal_error("Not implemented yet.");
106 
107  pips_debug(8, "Transformer for declaration of \"%s\"\n", entity_name(v));
108 
109  if(false && !entity_has_values_p(v)) {
110  /* FI: the initialization expression might have relevant
111  side-effects? This could ba handled by generalizing
112  variable_to_initial_expression() and by returning
113  expression_undefined incase of failure instead of aborting. */
114  tf = transformer_identity();
115  }
116  else if(variable_static_p(v)) {
117  if(get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT"))
118  tf = transformer_range(pre);
119  else
120  tf = transformer_identity();
121  }
122  else {
123  /* Use the dimension expressions and the initial value */
125  transformer npre = transformer_apply(dt, pre);
128  tf = dt;
129  tf = transformer_combine(tf, itf);
130  free_expression(ie);
131  }
132 
133  pips_assert("tf is defined", !transformer_undefined_p(tf));
134 
135  /* FI: I preserve the code below in case I have problems with
136  integer typing in the future*/
137  /*
138  if(entity_has_values_p(v) && !variable_static_p(v)) {
139  value vv = entity_initial(v);
140  if(value_unknown_p(vv)) {
141  tf = transformer_identity();
142  }
143  else if (value_symbolic_p(vv)) {
144  pips_internal_error("Unexpected value tag: symbolic");
145  }
146  else if (value_constant_p(vv)) {
147  tf = transformer_identity();
148  // SG: quickly fix this, unsure about the meaning
149  //pips_internal_error("Unexpected value tag: constant");
150  }
151  else if (value_expression_p(vv)) {
152  expression e = value_expression(vv);
153  basic eb = basic_of_expression(e);
154  type vt = ultimate_type(entity_type(v));
155  basic vb = variable_basic(type_variable(vt));
156 
157  if(same_basic_p(eb, vb)) {
158  tf = safe_any_expression_to_transformer(v, e, pre, false);
159  tf = transformer_temporary_value_projection(tf);
160  }
161  else {
162  if(basic_int_p(eb) && basic_int_p(vb)) {
163  int i1 = basic_int(eb);
164  int i2 = basic_int(vb);
165  if(ABS(i1-i2)==10) {
166  tf = safe_any_expression_to_transformer(v, e, pre, false);
167  tf = transformer_temporary_value_projection(tf);
168  semantics_user_warning("Possible conversion issue between signed and"
169  " unsigned int\n");
170  }
171  else {
172  tf = safe_any_expression_to_transformer(v, e, pre, false);
173  tf = transformer_temporary_value_projection(tf);
174  semantics_user_warning("Possible conversion issue between diffent kinds"
175  " of ints and/or char (%dd and %d)\n", i1, i2);
176  }
177  }
178  else {
179  //list el = expression_to_proper_effects(e);
180  list el = expression_to_proper_constant_path_effects(e);
181 
182  semantics_user_warning("Type mismatch detected in initialization expression."
183  " May be due to overloading and/or implicit confusion"
184  " between logical and integer in C\n");
185  tf = effects_to_transformer(el);
186  }
187  }
188  }
189  else {
190  pips_internal_error("Unexpected value tag");
191  }
192  }
193  else {
194  tf = transformer_identity();
195  }
196  */
197 
198  ifdebug(8) {
199  pips_debug(8, "Ends with:\n");
200  (void) print_transformers(tfl);
201  }
202 
203  return tfl;
204 }

References dimensions_to_transformer(), entity_has_values_p(), entity_name, free_expression(), get_bool_property(), ifdebug, NIL, pips_assert, pips_debug, pips_internal_error, print_transformers(), safe_assigned_expression_to_transformer(), transformer_apply(), transformer_combine(), transformer_identity(), transformer_range(), transformer_undefined, transformer_undefined_p, variable_initial_expression(), and variable_static_p().

+ Here is the call graph for this function:

◆ declarations_to_transformer()

transformer declarations_to_transformer ( list  dl,
transformer  pre 
)

For C declarations.

Very close to a block_to_transformer() as declarations can be seen as a sequence of assignments.

Note: initialization of static variables are not taken into account. They must be used for summary preconditions.

post = transformer_safe_normalize(post, 4);

post = transformer_safe_normalize(post, 4);

btf = transformer_normalize(btf, 4);

Parameters
dll
prere

Definition at line 649 of file ri_to_transformers.c.

650 {
656  list l = dl;
657 
658  pips_debug(8,"begin\n");
659 
660  if(ENDP(l))
661  btf = transformer_identity();
662  else {
663  v = ENTITY(CAR(l));
665  post = transformer_safe_apply(stf, pre);
666 /* post = transformer_safe_normalize(post, 4); */
667  post = transformer_safe_normalize(post, 2);
668  btf = transformer_dup(stf);
669  for (POP(l) ; !ENDP(l); POP(l)) {
670  v = ENTITY(CAR(l));
671  if(!transformer_undefined_p(next_pre))
672  free_transformer(next_pre);
673  next_pre = transformer_range(post);
674  stf = declaration_to_transformer(v, next_pre);
675  post = transformer_safe_apply(stf, next_pre);
676  free_transformer(next_pre);
677  next_pre = transformer_undefined; // FI: works even without this...
678 /* post = transformer_safe_normalize(post, 4); */
679  post = transformer_safe_normalize(post, 2);
680  btf = transformer_combine(btf, stf);
681 /* btf = transformer_normalize(btf, 4); */
682  btf = transformer_normalize(btf, 2);
683 
684  ifdebug(1)
685  pips_assert("btf is a consistent transformer", transformer_consistency_p(btf));
686  pips_assert("post is a consistent transformer if pre is defined",
688  }
689  free_transformer(post);
690  }
691 
692  pips_debug(8, "end\n");
693  return btf;
694 }
#define entity_undefined
Definition: ri.h:2761
transformer declaration_to_transformer(entity v, transformer pre)
Note: initializations of static variables are not used as transformers but to initialize the program ...
bool stf(const string)
standardize_structure.c
transformer transformer_safe_apply(transformer tf, transformer pre)
Definition: transformer.c:1627
transformer transformer_safe_normalize(transformer t, int level)
Definition: transformer.c:1111

References CAR, declaration_to_transformer(), ENDP, ENTITY, entity_undefined, free_transformer(), ifdebug, pips_assert, pips_debug, POP, stf(), transformer_combine(), transformer_consistency_p(), transformer_dup(), transformer_identity(), transformer_normalize(), transformer_range(), transformer_safe_apply(), transformer_safe_normalize(), transformer_undefined, and transformer_undefined_p.

Referenced by statement_to_postcondition(), statement_to_transformer(), and statement_to_transformer_list().

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

◆ declarations_to_transformer_list()

list declarations_to_transformer_list ( list  dl,
transformer  pre 
)

For C declarations.

Very close to a block_to_transformer() as declarations can be seen as a sequence of assignments.

Note: initialization of static variables are not taken into account. They must be used for summary preconditions.

post = transformer_safe_normalize(post, 4);

post = transformer_safe_normalize(post, 4);

btf = transformer_normalize(btf, 4);

Parameters
dll
prere

Definition at line 212 of file ri_to_transformer_lists.c.

213 {
214  list tfl = list_undefined;
220  list l = dl;
221 
222  // May never be useful
223  pips_internal_error("Not implemented yet.");
224 
225  pips_debug(8,"begin\n");
226 
227  if(ENDP(l))
228  btf = transformer_identity();
229  else {
230  v = ENTITY(CAR(l));
232  post = transformer_safe_apply(stf, pre);
233 /* post = transformer_safe_normalize(post, 4); */
234  post = transformer_safe_normalize(post, 2);
235  btf = transformer_dup(stf);
236  for (POP(l) ; !ENDP(l); POP(l)) {
237  v = ENTITY(CAR(l));
238  if(!transformer_undefined_p(next_pre))
239  free_transformer(next_pre);
240  next_pre = transformer_range(post);
241  stf = declaration_to_transformer(v, next_pre);
242  post = transformer_safe_apply(stf, next_pre);
243  free_transformer(next_pre);
244  next_pre = transformer_undefined; // FI: works even without this...
245 /* post = transformer_safe_normalize(post, 4); */
246  post = transformer_safe_normalize(post, 2);
247  btf = transformer_combine(btf, stf);
248 /* btf = transformer_normalize(btf, 4); */
249  btf = transformer_normalize(btf, 2);
250 
251  ifdebug(1)
252  pips_assert("btf is a consistent transformer", transformer_consistency_p(btf));
253  pips_assert("post is a consistent transformer if pre is defined",
255  }
256  free_transformer(post);
257  }
258 
259  pips_debug(8, "end\n");
260  return tfl;
261 }

References CAR, declaration_to_transformer(), ENDP, ENTITY, entity_undefined, free_transformer(), ifdebug, list_undefined, pips_assert, pips_debug, pips_internal_error, POP, stf(), transformer_combine(), transformer_consistency_p(), transformer_dup(), transformer_identity(), transformer_normalize(), transformer_range(), transformer_safe_apply(), transformer_safe_normalize(), transformer_undefined, and transformer_undefined_p.

+ Here is the call graph for this function:

◆ delete_statement_postcondition()

void delete_statement_postcondition ( statement  )

◆ delete_statement_precondition()

void delete_statement_precondition ( statement  )

◆ delete_statement_semantic()

void delete_statement_semantic ( statement  )

◆ delete_statement_total_precondition()

void delete_statement_total_precondition ( statement  )

◆ delete_statement_transformer()

void delete_statement_transformer ( statement  )

◆ dimensions_to_transformer()

transformer dimensions_to_transformer ( entity  v,
transformer  pre 
)

Assumes that entity_has_values_p(v) holds.

FI: this should be done for all variables, regardless of their types.

Parameters
prere

Definition at line 535 of file ri_to_transformers.c.

536 {
539 
540  if(type_variable_p(vt)) {
541  list dl = variable_dimensions(type_variable(vt)); // dimension list
542  if(!ENDP(dl)) { // to save a copy and to simplify debugging
543  transformer cpre = copy_transformer(pre);
544 
545  FOREACH(DIMENSION, d, dl) {
549  transformer lpre = transformer_apply(lt, pre);
550  transformer lpre_r = transformer_range(lpre);
552  transformer upre = transformer_apply(ut, lpre);
553 
554  free_transformer(cpre);
555  cpre = transformer_range(upre);
556  free_transformer(upre);
557  free_transformer(lpre);
558  free_transformer(lpre_r);
559 
560  dt = transformer_combine(transformer_combine(dt, lt), ut);
561  free_transformer(lt);
562  free_transformer(ut);
563  }
564  free_transformer(cpre);
565  }
566  else {
567  // FI: equivalent to copy_transformer(pre) I believe
568  dt = transformer_apply(dt, pre);
569  }
570  }
571 
572  return dt;
573 }

References copy_transformer(), DIMENSION, dimension_lower, dimension_upper, ENDP, entity_basic_concrete_type(), FOREACH, free_transformer(), safe_expression_to_transformer(), transformer_apply(), transformer_combine(), transformer_identity(), transformer_range(), type_variable, type_variable_p, and variable_dimensions.

Referenced by declaration_to_transformer(), and declaration_to_transformer_list().

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

◆ dynamic_call_count()

int dynamic_call_count ( entity  m)

number of call to m during the current program execution; return 0 if m is never called, either because it's a call graph root or because it was linked by mistake; return -1 if the dynamic call count is unknow, for instance because one of m's call site is located in a loop of unknown bounds; return k when it can be evaluated

I do not know yet; let's return 1 to please the semantic analysis

Definition at line 75 of file misc.c.

76 {
77  /* number of call to m during the current program execution;
78  return 0 if m is never called, either because it's a call
79  graph root or because it was linked by mistake;
80  return -1 if the dynamic call count is unknow, for instance
81  because one of m's call site is located in a loop of unknown
82  bounds;
83  return k when it can be evaluated */
84  pips_assert("Entity m is a function with defined code",
86  /* I do not know yet; let's return 1 to please the semantic analysis */
87  pips_internal_error("Not implemented yet, always returns -1.\n");
88  return -1;
89 }

References entity_initial, pips_assert, pips_internal_error, and value_code_p.

◆ dynamic_variables_to_values()

list dynamic_variables_to_values ( list  list_mod)

Build the list of values to be projected when the declaration list list_mod is no longer valid because a block is closed/left.

Values for static variables are preserved. Values for heap variables also, in case their values are computed in the future...

This may not be the best algorithm when locations are used because the list of locations may be much longer, especially for arrays, than the list of values appearing in the transformer.

Parameters
list_modist_mod

Definition at line 1007 of file mappings.c.

1008 {
1009  list list_val = NIL;
1010 
1011  FOREACH(ENTITY, e, list_mod) {
1012  if(entity_has_values_p(e)
1013  && (variable_dynamic_p(e) || variable_stack_p(e))) {
1014  entity v_old = entity_to_old_value(e);
1015  entity v_new = entity_to_new_value(e);
1016 
1017  list_val = CONS(ENTITY, v_old, list_val);
1018  list_val = CONS(ENTITY, v_new, list_val);
1019  }
1020  }
1021  return list_val;
1022 }
bool variable_dynamic_p(entity)
Definition: variable.c:1586
bool variable_stack_p(entity)
Definition: variable.c:1593

References CONS, ENTITY, entity_has_values_p(), entity_to_new_value(), entity_to_old_value(), FOREACH, NIL, variable_dynamic_p(), and variable_stack_p().

Referenced by statement_to_transformer(), and statement_to_transformer_list().

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

◆ effects_to_arguments()

list effects_to_arguments ( list  fx)

list of effects

algorithm: keep only write effects on scalar variable with values

Parameters
fxx

Definition at line 798 of file ri_to_transformers.c.

799 {
800  /* algorithm: keep only write effects on scalar variable with values */
801  list args = NIL;
802 
803  FOREACH(EFFECT, ef, fx) {
805  action a = effect_action(ef);
806  entity e = reference_variable(r);
807 
808  if(action_write_p(a) && entity_has_values_p(e)) {
809  args = arguments_add_entity(args, e);
810  }
811  }
812 
813  return args;
814 }
cons * arguments_add_entity(cons *a, entity e)
Definition: arguments.c:85
#define effect_action(x)
Definition: effects.h:642
#define action_write_p(x)
Definition: effects.h:314

References action_write_p, arguments_add_entity(), EFFECT, effect_action, effect_any_reference, entity_has_values_p(), FOREACH, NIL, and reference_variable.

+ Here is the call graph for this function:

◆ effects_to_entity_list()

list effects_to_entity_list ( list  lef)

returns an allocated list of entities that appear in lef.

an entity may appear several times.

Parameters
lefef

Definition at line 516 of file ri_to_preconditions.c.

517 {
518  list le = NIL;
519  MAP(EFFECT, e,
521  lef);
522  return gen_nreverse(le);
523 }
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304

References CONS, EFFECT, effect_any_reference, ENTITY, gen_nreverse(), MAP, NIL, and reference_variable.

Referenced by data_to_precondition().

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

◆ effects_to_transformer()

transformer effects_to_transformer ( list  e)

list of effects

Definition at line 474 of file ri_to_transformers.c.

475 {
478  return tf;
479 }
static transformer apply_effects_to_transformer(transformer tf, list el, bool apply_p, expression rhs)

References apply_effects_to_transformer(), expression_undefined, and transformer_identity().

Referenced by add_good_loop_conditions(), add_loop_index_initialization(), any_assign_to_transformer_list(), any_basic_update_to_transformer(), any_basic_update_to_transformer_list(), any_loop_to_k_transformer(), any_scalar_assign_to_transformer(), any_scalar_assign_to_transformer_list(), any_update_to_transformer(), any_update_to_transformer_list(), any_user_call_site_to_transformer(), c_return_to_transformer(), c_user_call_to_transformer(), c_user_function_call_to_transformer(), call_to_transformer(), condition_to_transformer(), conditional_to_transformer(), expression_effects_to_transformer(), expression_to_transformer(), fortran_user_call_to_transformer(), integer_assign_to_transformer(), integer_assign_to_transformer_list(), intrinsic_to_transformer(), intrinsic_to_transformer_list(), load_summary_transformer(), loop_to_transformer(), new_loop_to_transformer(), process_ready_node(), safe_any_expression_to_transformer(), standard_whileloop_to_transformer(), test_to_transformer(), test_to_transformer_list(), unstructured_to_transformer(), and user_call_to_transformer().

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

◆ empty_range_wrt_precondition_p()

bool empty_range_wrt_precondition_p ( range  r,
transformer  p 
)

A range cannot be tested exactly wrt a precondition You can try to prove that it is empty or you can try to prove that it is not empty.

In both case, you may fail and be unable to decide emptiness or non-emptiness.

Definition at line 112 of file utils.c.

113 {
114  bool empty = false;
115 
116  empty = check_range_wrt_precondition(r, p, true);
117 
118  return empty;
119 }
bool check_range_wrt_precondition(range r, transformer p, bool check_empty)
FI: this function is outdated because it does not compute the transformers for the range expressions,...
Definition: utils.c:135

References check_range_wrt_precondition(), and empty.

Referenced by complete_loop_transformer(), complete_loop_transformer_list(), loop_to_postcondition(), and loop_to_total_precondition().

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

◆ eval_condition_wrt_precondition_p()

bool eval_condition_wrt_precondition_p ( expression  c,
transformer  pre,
bool  veracity 
)
Parameters
prere
veracityeracity

Definition at line 5909 of file expression.c.

5910 {
5911  bool result = false;
5912  transformer f = transformer_dup(pre);
5913 
5914  if(veracity) {
5915  f = precondition_add_condition_information(f, c, pre, false);
5916  }
5917  else {
5918  f = precondition_add_condition_information(f, c, pre, true);
5919  }
5920 
5921  result = transformer_empty_p(f);
5922 
5923  return result;
5924 }
transformer precondition_add_condition_information(transformer pre, expression c, transformer context, bool veracity)
context might be derivable from pre as transformer_range(pre) but this is sometimes very computationa...
Definition: expression.c:1111

References f(), precondition_add_condition_information(), transformer_dup(), and transformer_empty_p().

Referenced by false_condition_wrt_precondition_p(), and true_condition_wrt_precondition_p().

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

◆ expression_and_precondition_to_integer_interval()

void expression_and_precondition_to_integer_interval ( expression  e,
transformer  p,
int plb,
int pub 
)

Evaluate expression e in context p, assuming that e is an integer expression.

If p is empty, return an empty interval.

Could be more general, I'm lazy (FI).

precondition p is not feasible

OK, we could do something: add a pseudo-variable equal to expression e and check its min abd max values

we are not handling an affine integer expression

Parameters
plblb
pubub

Definition at line 325 of file utils.c.

329 {
331 
332  if(normalized_linear_p(n)) {
334  if(vect_constant_p(v)) {
335  if(VECTEUR_NUL_P(v)) {
336  *plb = 0;
337  }
338  else {
339  Value vi = vect_coeff(TCST, v);
340  *plb = VALUE_TO_INT(vi);
341  }
342  *pub = *plb;
343  }
344  else if(vect_size(v) == 1) {
348  Value lb = VALUE_ZERO, ub = VALUE_ZERO;
349  entity var = (entity) vecteur_var(v);
350 
351  if(sc_minmax_of_variable(s, (Variable) var,
352  &lb, &ub)) {
353  *plb = value_min_p(lb)? INT_MIN : VALUE_TO_INT(lb);
354  *pub = value_max_p(ub)? INT_MAX : VALUE_TO_INT(ub);
355  }
356  else {
357  /* precondition p is not feasible */
358  *plb = 1;
359  *pub = 0;
360  }
361  }
362  else {
363  /* OK, we could do something: add a pseudo-variable
364  * equal to expression e and check its min abd max values
365  */
366  *plb = INT_MIN;
367  *pub = INT_MAX;
368  }
369  }
370  else {
371  /* we are not handling an affine integer expression */
372  *plb = INT_MIN;
373  *pub = INT_MAX;
374  }
375 
376 }
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
#define VALUE_ZERO
#define VALUE_TO_INT(val)
#define value_min_p(val)
#define value_max_p(val)
int vect_size(Pvecteur v)
package vecteur - reductions
Definition: reductions.c:47
bool sc_minmax_of_variable(Psysteme ps, Variable var, Value *pmin, Value *pmax)
void sc_minmax_of_variable(Psysteme ps, Variable var, Value *pmin, *pmax): examine un systeme pour tr...
Definition: sc_eval.c:143
#define vecteur_var(v)
#define VECTEUR_NUL_P(v)

References CONTRAINTE_UNDEFINED, NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, predicate_system, sc_dup(), sc_make(), sc_minmax_of_variable(), TCST, transformer_relation, transformer_undefined_p, value_max_p, value_min_p, VALUE_TO_INT, VALUE_ZERO, vect_coeff(), vect_constant_p(), vect_size(), VECTEUR_NUL_P, and vecteur_var.

Referenced by add_index_range_conditions(), add_loop_index_exit_value(), add_loop_skip_condition(), check_range_wrt_precondition(), loop_basic_workchunk_to_workchunk(), loop_bound_evaluation_to_transformer(), and modulo_to_transformer().

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

◆ expression_effects_to_transformer()

transformer expression_effects_to_transformer ( expression  expr)
Parameters
exprxpr

Definition at line 3465 of file expression.c.

3466 {
3467  //list el = expression_to_proper_effects(expr);
3470 
3471  gen_full_free_list(el);
3472  return tf;
3473 }

References effects_to_transformer(), expression_to_proper_constant_path_effects(), and gen_full_free_list().

Referenced by integer_expression_to_transformer(), safe_any_expression_side_effects_to_transformer(), safe_assigned_expression_to_transformer(), safe_integer_expression_to_transformer(), transformer_add_call_condition_information_updown(), and transformer_add_condition_information_updown().

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

◆ expression_to_summary_precondition()

void expression_to_summary_precondition ( transformer  pre,
expression  e 
)
Parameters
prere

Definition at line 977 of file interprocedural.c.

980 {
981  syntax s = expression_syntax(e);
982 
983  if(syntax_call_p(s)) {
984  call c = syntax_call(s);
986  }
987 }
void call_to_summary_precondition(transformer pre, call c)

References call_to_summary_precondition(), expression_syntax, syntax_call, and syntax_call_p.

Referenced by expressions_to_summary_precondition().

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

◆ expression_to_transformer()

transformer expression_to_transformer ( expression  exp,
transformer  pre,
list  el 
)

Just to capture side effects as the returned value is ignored.

Example: "(void) inc(&i);".

Or to capture the return of a struct, which cannot be expressed with an atomic return value.

FI: I assume this implies a cast to (void) but I'm wrong for any call to a void function.

FI: I do not remember the meaning of the last parameter

Must be a call to a void function

Wait till it happpens...

FI: is_internal_p has an impact on renaming in simple_affine_to_transformer().

FI: there may be (many) other exceptions with intrinsics...

Fortran intrinsics, such as IOs, are not taken into account because these code should not be executed for Fortran code.

If everything else has failed.

Parameters
expxp
prere
ell

Definition at line 5190 of file expression.c.

5194 {
5196  //entity tmpv = entity_undefined;
5198 
5199  if(type_void_p(et)) {
5200  /* FI: I assume this implies a cast to (void) but I'm wrong for
5201  any call to a void function. */
5202  syntax s_exp = expression_syntax(exp);
5203 
5204  if(syntax_cast_p(s_exp)) {
5205  expression sub_exp = cast_expression(syntax_cast(s_exp));
5206  type cet = expression_to_type(sub_exp);
5207 
5208  if(analyzed_type_p(cet)) {
5210 
5211  /* FI: I do not remember the meaning of the last parameter */
5212  // it's use in generic_reference_to_transformer
5213  tf = any_expression_to_transformer(tmpv, sub_exp, pre, false);
5214  }
5215  free_type(cet);
5216  }
5217  else if(syntax_call_p(s_exp)) {
5218  /* Must be a call to a void function */
5219  call c = syntax_call(s_exp);
5220  //list el = expression_to_proper_effects(exp);;
5222  tf = call_to_transformer(c, pre, el);
5223  }
5224  else {
5225  /* Wait till it happpens... */
5226  pips_internal_error("This case is not handled yet");
5227  }
5228  }
5229  else if(analyzed_type_p(et)) {
5231  /* FI: is_internal_p has an impact on renaming in
5232  simple_affine_to_transformer(). */
5233  tf = any_expression_to_transformer(tmpv, exp, pre, true);
5234  }
5235  else {
5236  // FI: we should go down recursively anyway because of casts and
5237  // side effects in C...
5241  }
5242  else if(expression_call_p(exp)) {
5243  call c = expression_call(exp);
5244  entity f = call_function(c);
5245  /* FI: there may be (many) other exceptions with intrinsics...
5246  *
5247  * Fortran intrinsics, such as IOs, are not taken into account
5248  * because these code should not be executed for Fortran code.
5249  */
5252  pre);
5253  }
5254  else if (entity_module_p(f)){
5255  list al = call_arguments(c);
5256  tf = user_call_to_transformer(f, al, pre, el);
5257  }
5258  else
5259  // FI: I am not pleased with this at all, but no time to think
5261  }
5262  else if(expression_cast_p(exp)) {
5263  cast c = expression_cast(exp);
5264  expression sub_exp = cast_expression(c);
5265  tf = safe_expression_to_transformer(sub_exp, pre);
5266  }
5270  expression sub_exp = sizeofexpression_expression(soe);
5271  tf = safe_expression_to_transformer(sub_exp, pre);
5272  }
5273  }
5274  else if(expression_subscript_p(exp)) {
5278  transformer tf2
5280  tf = transformer_combine(tf1, tf2);
5281  free_transformer(tf2); // tf1 is exported in tf
5282  }
5283  else if(expression_application_p(exp)) {
5285  expression func = application_function(a);
5287  transformer tf2
5289  tf = transformer_combine(tf1, tf2);
5290  free_transformer(tf2); // tf1 is exported in tf
5291  }
5292  // FI: Many other possible cases: range, sizeofexpression, subscript,
5293  // application, va_arg
5294  }
5295 
5296  /* If everything else has failed. */
5297  if(transformer_undefined_p(tf))
5298  tf = effects_to_transformer(el);
5299  else
5301 
5302  free_type(et);
5303 
5304  return tf;
5305 }
void free_type(type p)
Definition: ri.c:2658
bdt base
Current expression.
Definition: bdt_read_paf.c:100
#define ENTITY_POINT_TO_P(e)
#define ENTITY_FIELD_P(e)
C data structure and pointer management.
subscript expression_subscript(expression e)
Definition: expression.c:1843
bool expression_sizeofexpression_p(expression e)
Definition: expression.c:460
application expression_application(expression e)
Definition: expression.c:485
bool expression_subscript_p(expression e)
Definition: expression.c:1838
bool expression_application_p(expression e)
Duplicate bool expression_subscript_p(expression e) { return(syntax_subscript_p(expression_syntax(e))...
Definition: expression.c:480
sizeofexpression expression_sizeofexpression(expression e)
Definition: expression.c:465
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
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
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 sizeofexpression_expression(x)
Definition: ri.h:2409
#define syntax_cast(x)
Definition: ri.h:2739
#define application_arguments(x)
Definition: ri.h:510
#define subscript_indices(x)
Definition: ri.h:2563
#define sizeofexpression_expression_p(x)
Definition: ri.h:2407
#define subscript_array(x)
Definition: ri.h:2561
#define application_function(x)
Definition: ri.h:508
#define syntax_cast_p(x)
Definition: ri.h:2737
transformer call_to_transformer(call c, transformer pre, list ef)
Use to be static, but may be called from expressions in C.
transformer generic_reference_to_transformer(entity v, reference r, transformer pre, bool is_internal)
TYPE INDEPENDENT OPERATIONS.
Definition: expression.c:126

References analyzed_type_p(), any_expression_to_transformer(), application_arguments, application_function, base, call_arguments, call_function, call_to_transformer(), CAR, cast_expression, compute_basic_concrete_type(), effects_to_transformer(), ENTITY_FIELD_P, entity_module_p(), ENTITY_POINT_TO_P, entity_undefined, exp, EXPRESSION, expression_application(), expression_application_p(), expression_call(), expression_call_p(), expression_cast(), expression_cast_p(), expression_reference(), expression_reference_p(), expression_sizeofexpression(), expression_sizeofexpression_p(), expression_subscript(), expression_subscript_p(), expression_syntax, expression_to_proper_constant_path_effects(), expression_to_type(), expressions_to_transformer(), f(), free_transformer(), free_type(), generic_reference_to_transformer(), make_local_temporary_value_entity(), pips_internal_error, safe_expression_to_transformer(), sizeofexpression_expression, sizeofexpression_expression_p, subscript_array, subscript_indices, syntax_call, syntax_call_p, syntax_cast, syntax_cast_p, transformer_combine(), transformer_temporary_value_projection(), transformer_undefined, transformer_undefined_p, type_void_p, and user_call_to_transformer().

Referenced by expression_to_postcondition(), instruction_to_transformer(), and safe_expression_to_transformer().

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

◆ expressions_to_summary_precondition()

void expressions_to_summary_precondition ( transformer  pre,
list  le 
)
Parameters
prere
lee

Definition at line 966 of file interprocedural.c.

969 {
970  MAPL(ce, {
971  expression e = EXPRESSION(CAR(ce));
973  },
974  le)
975  }
#define MAPL(_map_list_cp, _code, _l)
Apply some code on the addresses of all the elements of a list.
Definition: newgen_list.h:203
void expression_to_summary_precondition(transformer pre, expression e)

References CAR, EXPRESSION, expression_to_summary_precondition(), and MAPL.

Referenced by call_to_summary_precondition().

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

◆ expressions_to_transformer()

transformer expressions_to_transformer ( list  expl,
transformer  pre 
)

Compute the transformer associated to a list of expressions such as "i=0, j = 1;".

The value returned is ignored.

el is an over-appoximation; should be replaced by a safe_expression_to_transformer() taking care of computing the precise effects of exp instead of using the effects of expl.

Parameters
explxpl
prere

Definition at line 5722 of file expression.c.

5724 {
5728 
5729  FOREACH(EXPRESSION, exp, expl) {
5730  /* el is an over-appoximation; should be replaced by a
5731  safe_expression_to_transformer() taking care of computing the
5732  precise effects of exp instead of using the effects of expl. */
5733  transformer cpre_r = transformer_range(cpre);
5736 
5737  tf = transformer_combine(tf, ctf);
5738  tf = transformer_normalize(tf, 2);
5739  npre = transformer_apply(ctf, cpre);
5740  npre = transformer_normalize(npre, 2);
5741  free_transformer(cpre);
5742  free_transformer(cpre_r);
5743  cpre = npre;
5744  }
5745  free_transformer(cpre);
5746  return tf;
5747 }

References copy_transformer(), exp, EXPRESSION, FOREACH, free_transformer(), safe_expression_to_transformer(), transformer_apply(), transformer_combine(), transformer_identity(), transformer_normalize(), transformer_range(), transformer_undefined, and transformer_undefined_p.

Referenced by any_expression_side_effects_to_transformer(), any_expression_to_transformer(), expression_to_transformer(), generic_reference_to_transformer(), intrinsic_to_transformer(), and intrinsic_to_transformer_list().

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

◆ false_condition_wrt_precondition_p()

bool false_condition_wrt_precondition_p ( expression  c,
transformer  pre 
)
Parameters
prere

Definition at line 5891 of file expression.c.

5892 {
5893  bool result = false;
5894 
5895  result = eval_condition_wrt_precondition_p(c, pre, false);
5896 
5897  return result;
5898 }
bool eval_condition_wrt_precondition_p(expression c, transformer pre, bool veracity)
Definition: expression.c:5909

References eval_condition_wrt_precondition_p().

Referenced by whileloop_to_postcondition(), and whileloop_to_total_precondition().

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

◆ filter_transformer()

transformer filter_transformer ( transformer  t,
list  e 
)

Previous version of effects_to_transformer() transformer effects_to_transformer(list e) { list args = NIL; Pbase b = VECTEUR_NUL; Psysteme s = sc_new();.

s->base = b; s->dimension = vect_size(b);

return make_transformer(args, make_predicate(s)); }

algorithm: keep only information about scalar variables with values appearing in effects e and store it into a newly allocated transformer

action a = effect_action(ef);

action_write_p(a) &&

I do not know yet if I should keep old values...

FI: I should check if sc is sc_empty but I haven't (yet) found a cheap syntactic test

Definition at line 495 of file ri_to_transformers.c.

496 {
497  /* algorithm: keep only information about scalar variables with values
498  * appearing in effects e and store it into a newly allocated transformer
499  */
500  Pbase b = VECTEUR_NUL;
501  Psysteme s = SC_UNDEFINED;
503  list args = NIL;
505 
506  FOREACH(EFFECT, ef, e) {
508  /* action a = effect_action(ef); */
509  entity v = reference_variable(r);
510 
511  if(/* action_write_p(a) && */ entity_has_values_p(v)) {
512  /* I do not know yet if I should keep old values... */
513  entity new_val = entity_to_new_value(v);
514  b = vect_add_variable(b, (Variable) new_val);
515 
517  args = arguments_add_entity(args, v);
518  }
519  }
520  }
521 
522  /* FI: I should check if sc is sc_empty but I haven't (yet) found a
523  cheap syntactic test */
525 
526  return make_transformer(args, make_predicate(s));
527 }
Pbase vect_add_variable(Pbase b, Variable v)
package vecteur - routines sur les bases
Definition: base.c:61
Psysteme sc_restricted_to_variables_transitive_closure(Psysteme sc, Pbase variables)
for an improved dependence test (Beatrice Creusillet)
Definition: sc_misc.c:64

References arguments_add_entity(), EFFECT, effect_any_reference, entity_has_values_p(), entity_is_argument_p(), entity_to_new_value(), FOREACH, make_predicate(), make_transformer(), NIL, predicate_system, reference_variable, sc_restricted_to_variables_transitive_closure(), transformer_arguments, transformer_relation, vect_add_variable(), and VECTEUR_NUL.

Referenced by semantic_to_text().

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

◆ float_expression_to_transformer()

transformer float_expression_to_transformer ( entity  v,
expression  rhs,
transformer  pre,
bool  is_internal 
)

pre can be used if some integer variables with constant values have to be promoted to float.

pips_assert("Precondition is undefined", transformer_undefined_p(pre));

Parameters
rhshs
prere
is_internals_internal

Definition at line 4153 of file expression.c.

4157 {
4159  syntax srhs = expression_syntax(rhs);
4160 
4161  /* pre can be used if some integer variables with constant values have
4162  to be promoted to float. */
4163 
4164  /* pips_assert("Precondition is undefined", transformer_undefined_p(pre)); */
4165 
4166  switch(syntax_tag(srhs)) {
4167  case is_syntax_call:
4168  tf = float_call_expression_to_transformer(v, rhs, pre, is_internal);
4169  break;
4170  case is_syntax_reference:
4171  {
4172  //entity e = reference_variable(syntax_reference(srhs));
4173  // FI: some filtering needed if integer expressions should not
4174  // be exploited...
4175  reference r = syntax_reference(srhs);
4176  tf = generic_reference_to_transformer(v, r, pre, is_internal);
4177  break;
4178  }
4179  case is_syntax_range:
4180  pips_internal_error("Unexpected tag %d", syntax_tag(srhs));
4181  break;
4182  default:
4183  pips_internal_error("Illegal tag %d", syntax_tag(srhs));
4184  }
4185 
4186  return tf;
4187 }
#define syntax_tag(x)
Definition: ri.h:2727
@ is_syntax_range
Definition: ri.h:2692
@ is_syntax_call
Definition: ri.h:2693
@ is_syntax_reference
Definition: ri.h:2691
static transformer float_call_expression_to_transformer(entity v, expression expr, transformer pre, bool is_internal)
Definition: expression.c:4095

References expression_syntax, float_call_expression_to_transformer(), generic_reference_to_transformer(), is_syntax_call, is_syntax_range, is_syntax_reference, pips_internal_error, syntax_reference, syntax_tag, and transformer_undefined.

Referenced by any_expression_to_transformer().

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

◆ forloop_to_postcondition()

transformer forloop_to_postcondition ( transformer  pre,
forloop  fl,
transformer  t_body_star 
)

This function does not seem to exist because we only used statement effects in the past and because those are stored in the database.

An effort could be made to compute the precondition for t_exit, especially if the precondition to t_inc is available.

An effort could be made to compute the precondition for t_inc

Clean up memory

Parameters
prere
fll
t_body_star_body_star

Definition at line 2707 of file loop.c.

2708 {
2710 
2711  statement body_s = forloop_body(fl);
2712  transformer t_body = load_statement_transformer(body_s);
2713 
2714  expression init_e = forloop_initialization(fl);
2715  /* This function does not seem to exist because we only used
2716  statement effects in the past and because those are stored in the
2717  database. */
2718  transformer t_init = safe_expression_to_transformer(init_e, pre);
2719  transformer post_init = transformer_apply(t_init, pre);
2720 
2721  expression cond_e = forloop_condition(fl);
2722  transformer t_skip = condition_to_transformer(cond_e, post_init, false);
2723  transformer t_enter = condition_to_transformer(cond_e, post_init, true);
2724 /* An effort could be made to compute the precondition for t_exit,
2725  especially if the precondition to t_inc is available. */
2726  transformer t_continue = condition_to_transformer(cond_e, transformer_undefined, true);
2728 
2729  expression inc_e = forloop_increment(fl);
2730  /* An effort could be made to compute the precondition for t_inc */
2732 
2733  transformer t_next = transformer_combine(transformer_dup(t_inc), t_continue);
2734 
2735  post = any_loop_to_postcondition(body_s,
2736  t_init,
2737  t_enter,
2738  t_skip,
2739  t_body_star,
2740  t_body,
2741  t_next,
2742  t_inc,
2743  t_exit,
2744  pre);
2745 
2746  /* Clean up memory */
2747 
2748  free_transformer(t_init);
2749  free_transformer(post_init);
2750  free_transformer(t_skip);
2751  free_transformer(t_enter);
2752  free_transformer(t_continue);
2753  free_transformer(t_exit);
2754  free_transformer(t_inc);
2755  free_transformer(t_next);
2756 
2757  return post;
2758 }
transformer any_loop_to_postcondition(statement body, transformer t_init, transformer t_enter, transformer t_skip, transformer t_body_star, transformer t_body, transformer t_next, transformer t_inc, transformer t_exit, transformer pre)
Definition: loop.c:2634

References any_loop_to_postcondition(), condition_to_transformer(), forloop_body, forloop_condition, forloop_increment, forloop_initialization, free_transformer(), load_statement_transformer(), safe_expression_to_transformer(), transformer_apply(), transformer_combine(), transformer_dup(), and transformer_undefined.

Referenced by instruction_to_postcondition().

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

◆ forloop_to_transformer()

transformer forloop_to_transformer ( forloop  fl,
transformer  pre,
list  flel 
)

effects of forloop fl

t_body_star = t_init ; t_enter ;(t_body ; t_next)*

Deal with initialization expression

Deal with condition expression

An effort could be made to compute the precondition for t_continue, especially if the precondition to t_inc is available.

Deal with increment expression

An effort could be made to compute the precondition for t_inc

Let's clean up the memory

Parameters
fll
prere
flellel

Definition at line 326 of file loop.c.

329 {
330  /* t_body_star = t_init ; t_enter ;(t_body ; t_next)* */
331  transformer t_body_star = transformer_undefined;
332  statement body_s = forloop_body(fl);
333 
334  /* Deal with initialization expression */
335  expression init_e = forloop_initialization(fl);
336  transformer t_init = safe_expression_to_transformer(init_e, pre);
337  transformer post_init = transformer_apply(t_init, pre);
338 
339  /* Deal with condition expression */
340  expression cond_e = forloop_condition(fl);
341  transformer t_enter = condition_to_transformer(cond_e, post_init, true);
342  /* An effort could be made to compute the precondition for t_continue,
343  especially if the precondition to t_inc is available. */
344  transformer p_continue = transformer_identity();
345  transformer t_continue = condition_to_transformer(cond_e, p_continue, true);
346 
347  /* Deal with increment expression */
348  expression inc_e = forloop_increment(fl);
349  /* An effort could be made to compute the precondition for t_inc */
351  transformer t_next = transformer_combine(t_inc, t_continue);
352 
353  t_body_star = any_loop_to_transformer(t_init, t_enter, t_next, body_s, flel, post_init);
354 
355  /* Let's clean up the memory */
356 
357  free_transformer(p_continue);
358 
359  free_transformer(t_init);
360  free_transformer(post_init);
361 
362  free_transformer(t_enter);
363  free_transformer(t_continue);
364 
365  // free_transformer(t_inc); it is absorbed by t_next
366  free_transformer(t_next);
367 
368  return t_body_star;
369 }
transformer any_loop_to_transformer(transformer t_init, transformer t_enter, transformer t_next, statement body, list __attribute__((unused)) lel, transformer post_init)
Definition: loop.c:316

References any_loop_to_transformer(), condition_to_transformer(), forloop_body, forloop_condition, forloop_increment, forloop_initialization, free_transformer(), safe_expression_to_transformer(), transformer_apply(), transformer_combine(), transformer_identity(), and transformer_undefined.

Referenced by instruction_to_transformer().

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

◆ forloop_to_transformer_list()

list forloop_to_transformer_list ( forloop  ,
transformer  ,
list   
)

◆ fortran_user_call_to_transformer()

transformer fortran_user_call_to_transformer ( entity  f,
list  pc,
list  ef 
)

Effects are necessary to clean up the transformer t_caller.

For instance, an effect on variable X may not be taken into account in t_callee but it may be equivalenced thru a common to a variable i which is analyzed in the caller. If X is written, I value is lost. See Validation/equiv02.f.

add equations linking formal parameters to argument expressions to transformer t_callee and project along the formal parameters

for performance, it would be better to avoid building formals and to inline entity_to_formal_parameters

it wouls also be useful to distinguish between in and out parameters; I'm not sure the information is really available in a field ???

take care of analyzable formal parameters

type checking. You already know that fp is a scalar variable

formal parameter e is modified. expr must be a reference

normal case: ap_new==fp_new, ap_old==fp_old

Variable ap is not analyzed. The information about fp will be lost.

Attemps at modifying a value: expr is call, fp is modified

Actual argument is not a reference: it might be a user error! Transformers do not carry the may/must information. A check with effect list ef should be performed...

FI: does effect computation emit a MUST/MAYwarning?

Formal parameter fp is not modified. Add fp == expr, if possible.

We should evaluate expr under a precondition pre... which has not been passed down. We set pre==tf_undefined.

temporary value counter cannot be reset because other temporary values may be in use in a case the user call is a user function call

reset_temporary_value_counter();

formal new and old values left over are eliminated

test to insure that entity_to_old_value exists

take care of global variables

FI: are invisible variables taken care of by translate_global_values()? Yes, now... A variable may be invisible because its location is reached thru an array or thru a non-integer scalar variable in the current module, for instance because a COMMON is defined differently. A variable whose location is not reachable in the current module environment is considered visible.

Callee f may have read/write effects on caller's scalar integer variables thru an array and/or non-integer variables.

The relation basis must be updated too

The return value of a function is not yet projected.

Parameters
pcc
eff

Definition at line 2269 of file ri_to_transformers.c.

2272 {
2275  transformer t_effects = transformer_undefined;
2276  entity caller = entity_undefined;
2277  list all_args = list_undefined;
2278 
2279  pips_debug(8, "begin\n");
2280 
2281  /* add equations linking formal parameters to argument expressions
2282  to transformer t_callee and project along the formal parameters */
2283  /* for performance, it would be better to avoid building formals
2284  and to inline entity_to_formal_parameters */
2285  /* it wouls also be useful to distinguish between in and out
2286  parameters; I'm not sure the information is really available
2287  in a field ??? */
2289  list formals_new = NIL;
2290 
2291  t_callee = load_summary_transformer(f);
2292 
2293  ifdebug(8) {
2294  Psysteme s =
2296  pips_debug(8, "Transformer for callee %s:\n",
2297  entity_local_name(f));
2298  dump_transformer(t_callee);
2299  sc_fprint(stderr, s, (char * (*)(Variable)) dump_value_name);
2300  }
2301 
2302  t_caller = transformer_dup(t_callee);
2303 
2304  /* take care of analyzable formal parameters */
2305 
2306  FOREACH(ENTITY, fp, formals) {
2308  expression expr = find_ith_argument(pc, r);
2309 
2310  if(expr == expression_undefined)
2311  pips_user_error("not enough args for %d formal parm."
2312  " %s in call to %s from %s\n",
2315  else {
2316  /* type checking. You already know that fp is a scalar variable */
2317  type tfp = entity_type(fp);
2318  basic bfp = variable_basic(type_variable(tfp));
2319  basic bexpr = basic_of_expression(expr);
2320  //list l_eff = expression_to_proper_effects(expr);
2322 
2323  if(effects_write_at_least_once_p(l_eff)) {
2324  semantics_user_warning("Side effects in actual arguments are not yet taken into account\n."
2325  "Meanwhile, \"atomize\" the call site to avoid the problem.\n");
2326  }
2327  gen_free_list(l_eff);
2328 
2329  if(!basic_equal_p(bfp, bexpr)) {
2330  semantics_user_warning("Type incompatibility (formal %s/actual %s) "
2331  "for formal parameter \"%s\" (rank %d) "
2332  "in call to \"%s\" from \"%s\"\n",
2333  basic_to_string(bfp), basic_to_string(bexpr),
2336  continue;
2337  }
2338  }
2339 
2340  if(entity_is_argument_p(fp, transformer_arguments(t_callee))) {
2341  /* formal parameter e is modified. expr must be a reference */
2342  syntax sexpr = expression_syntax(expr);
2343 
2344  if(syntax_reference_p(sexpr)) {
2346 
2347  if(entity_has_values_p(ap)) {
2349  entity ap_new = entity_to_new_value(ap);
2350  entity ap_old = entity_to_old_value(ap);
2351 
2352  if(base_contains_variable_p(s->base, (Variable) ap_new)) {
2354  "Variable %s seems to be aliased thru variable %s"
2355  " at a call site to %s in %s\n"
2356  "PIPS semantics analysis assumes no aliasing as"
2357  " imposed by the Fortran standard.\n",
2358  entity_name(fp),
2359  entity_name(value_to_variable(ap_new)),
2362  }
2363  else { /* normal case: ap_new==fp_new, ap_old==fp_old */
2364  entity fp_new = external_entity_to_new_value(fp);
2365  entity fp_old = external_entity_to_old_value(fp);
2366 
2367  t_caller = transformer_value_substitute
2368  (t_caller, fp_new, ap_new);
2369  t_caller = transformer_value_substitute
2370  (t_caller, fp_old, ap_old);
2371  }
2372  }
2373  else { /* Variable ap is not analyzed. The information about fp
2374  will be lost. */
2375  ;
2376  }
2377  }
2378  else {
2379  /* Attemps at modifying a value: expr is call, fp is modified */
2380  /* Actual argument is not a reference: it might be a user error!
2381  * Transformers do not carry the may/must information.
2382  * A check with effect list ef should be performed...
2383  *
2384  * FI: does effect computation emit a MUST/MAYwarning?
2385  */
2386  entity fp_new = external_entity_to_new_value(fp);
2387  entity fp_old = external_entity_to_old_value(fp);
2388  list args = arguments_add_entity(arguments_add_entity(NIL, fp_new), fp_old);
2389 
2390  semantics_user_warning("value (!) might be modified by call to %s\n"
2391  "%dth formal parameter %s\n",
2393  t_caller = transformer_filter(t_caller, args);
2394  free_arguments(args);
2395  }
2396  }
2397  else {
2398  /* Formal parameter fp is not modified. Add fp == expr, if possible. */
2399  /* We should evaluate expr under a precondition pre... which has
2400  not been passed down. We set pre==tf_undefined. */
2401  entity fp_new = external_entity_to_new_value(fp);
2402  transformer t_expr = any_expression_to_transformer(fp_new, expr,
2404  false);
2405 
2406  if(!transformer_undefined_p(t_expr)) {
2407  t_expr = transformer_temporary_value_projection(t_expr);
2408  /* temporary value counter cannot be reset because other
2409  temporary values may be in use in a case the user call is a
2410  user function call */
2411  /* reset_temporary_value_counter(); */
2412  t_caller = transformer_safe_image_intersection(t_caller, t_expr);
2413  free_transformer(t_expr);
2414  }
2415  }
2416  }
2417 
2418  pips_debug(8, "Before formal new values left over are eliminated\n");
2419  ifdebug(8) dump_transformer(t_caller);
2420 
2421  /* formal new and old values left over are eliminated */
2422  FOREACH(ENTITY, e, formals) {
2424  formals_new = CONS(ENTITY, e_new, formals_new);
2425  /* test to insure that entity_to_old_value exists */
2426  if(entity_is_argument_p(e_new,
2427  transformer_arguments(t_caller))) {
2429  formals_new = CONS(ENTITY, e_old, formals_new);
2430  }
2431  }
2432 
2433  t_caller = transformer_filter(t_caller, formals_new);
2434 
2435  free_arguments(formals_new);
2436  free_arguments(formals);
2437 
2438  ifdebug(8) {
2440  pips_debug(8,
2441  "After binding formal/real parameters and eliminating formals\n");
2442  dump_transformer(t_caller);
2443  sc_fprint(stderr, s, (char * (*)(Variable)) dump_value_name);
2444  }
2445 
2446  /* take care of global variables */
2447  caller = get_current_module_entity();
2448  translate_global_values(caller, t_caller);
2449 
2450  /* FI: are invisible variables taken care of by translate_global_values()?
2451  * Yes, now...
2452  * A variable may be invisible because its location is reached
2453  * thru an array or thru a non-integer scalar variable in the
2454  * current module, for instance because a COMMON is defined
2455  * differently. A variable whose location is not reachable
2456  * in the current module environment is considered visible.
2457  */
2458 
2459  ifdebug(8) {
2460  pips_debug(8, "After replacing global variables\n");
2461  dump_transformer(t_caller);
2462  }
2463 
2464  if(!transformer_empty_p(t_caller)) {
2465  /* Callee f may have read/write effects on caller's scalar
2466  * integer variables thru an array and/or non-integer variables.
2467  */
2468  t_effects = effects_to_transformer(ef);
2469  all_args = arguments_union(transformer_arguments(t_caller),
2470  transformer_arguments(t_effects));
2471  /*
2472  free_transformer(t_effects);
2473  gen_free_list(transformer_arguments(t_caller));
2474  */
2475  transformer_arguments(t_caller) = all_args;
2476  /* The relation basis must be updated too */
2477  FOREACH(ENTITY, v, transformer_arguments(t_effects)) {
2479  sc_base_add_variable(sc, (Variable) v);
2480  }
2481  }
2482  else {
2483  semantics_user_warning("Call to %s seems never to return."
2484  " This may be due to an infinite loop in %s,"
2485  " or to a systematic exit in %s,"
2486  " or to standard violations (see previous messages)\n",
2489  module_local_name(f));
2490  }
2491 
2492  ifdebug(8) {
2493  pips_debug(8,
2494  "End: after taking all scalar effects in consideration %p\n",
2495  t_caller);
2496  dump_transformer(t_caller);
2497  }
2498 
2499  /* The return value of a function is not yet projected. */
2500  pips_assert("transformer t_caller is consistent",
2501  transformer_weak_consistency_p(t_caller));
2502 
2503  return t_caller;
2504 }
cons * arguments_union(cons *a1, cons *a2)
cons * arguments_union(cons * a1, cons * a2): returns a = union(a1, a2) where a1 and a2 are lists of ...
Definition: arguments.c:116
bool base_contains_variable_p(Pbase b, Variable v)
bool base_contains_variable_p(Pbase b, Variable v): returns true if variable v is one of b's elements...
Definition: base.c:136
bool effects_write_at_least_once_p(list)
const char * get_current_module_name(void)
Get the name of the current module.
Definition: static.c:121
bool basic_equal_p(basic, basic)
Definition: type.c:927
struct Ssysteme * Psysteme
void sc_base_add_variable(Psysteme sc, Variable var)
Definition: sc.c:248
Pbase base
Definition: sc-local.h:75
transformer transformer_filter(transformer t, list args)
transformer transformer_filter(transformer t, cons * args): projection of t along the hyperplane defi...
Definition: transformer.c:1716
entity external_entity_to_old_value(entity)
Definition: value.c:1422

References any_expression_to_transformer(), arguments_add_entity(), arguments_union(), Ssysteme::base, base_contains_variable_p(), basic_equal_p(), basic_of_expression(), basic_to_string(), CONS, dump_transformer, dump_value_name(), effects_to_transformer(), effects_write_at_least_once_p(), ENTITY, entity_has_values_p(), entity_is_argument_p(), entity_local_name(), entity_name, entity_storage, entity_to_new_value(), entity_to_old_value(), entity_type, entity_undefined, expression_syntax, expression_to_proper_constant_path_effects(), expression_undefined, external_entity_to_new_value(), external_entity_to_old_value(), f(), find_ith_argument(), FOREACH, formal_offset, free_arguments(), free_transformer(), gen_free_list(), get_current_module_entity(), get_current_module_name(), ifdebug, list_undefined, load_summary_transformer(), module_local_name(), module_to_formal_analyzable_parameters(), NIL, pips_assert, pips_debug, pips_user_error, predicate_system, reference_variable, sc_base_add_variable(), sc_fprint(), semantics_user_warning, storage_formal, syntax_reference, syntax_reference_p, transformer_arguments, transformer_dup(), transformer_empty_p(), transformer_filter(), transformer_relation, transformer_safe_image_intersection(), transformer_temporary_value_projection(), transformer_undefined, transformer_undefined_p, transformer_value_substitute(), transformer_weak_consistency_p(), translate_global_values(), type_variable, value_to_variable(), and variable_basic.

Referenced by fortran_user_function_call_to_transformer(), and user_call_to_transformer().

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

◆ free_postcondition_map()

void free_postcondition_map ( void  )

Referenced by reset_resources_for_module().

+ Here is the caller graph for this function:

◆ free_precondition_map()

void free_precondition_map ( void  )

◆ free_semantic_map()

void free_semantic_map ( void  )

◆ free_total_precondition_map()

void free_total_precondition_map ( void  )

◆ free_transformer_map()

void free_transformer_map ( void  )

◆ generic_complete_statement_transformer()

transformer generic_complete_statement_transformer ( transformer  t,
transformer  pre,
statement  s,
bool  identity_p 
)

Loops, do, for, while or repeat, have transformers linked to their body preconditions so as to compute those.

But the real loop transformer includes also the possible loop skip and the possible loop exit. This function completes transformer t, which is linked to the loop body precondition, and use additional information carried by statement s, analyzed with precondition pre to return the global loop transformer. If statement s is not a loop, a copy of t is returned.

Parameter identity_p is likely to be useless. It was added to track identity transformers before they were dealt with by transformer lists.

If i is a loop, the expected transformer can be more complex (see nga06) because the stores transformer is later used to compute the loop body precondition. It cannot take into account the exit condition. So the exit condition is added by the complete_xxx functions.

likely memory leak:-(. ct should be allocated in both test branches and freed at call site but I program everything under the opposite assumption

The refined transformer may be lost or stored as a block transformer is the loop is directly surrounded by a bloc or used to compute the transformer of the surroundings blokcs

No need to complete it

The search for an non identity execution path must be propagated downwards

Each component may or not update the state...

Parameters
prere
identity_pdentity_p

Definition at line 3706 of file ri_to_transformers.c.

3710 {
3711  /* If i is a loop, the expected transformer can be more complex (see
3712  nga06) because the stores transformer is later used to compute
3713  the loop body precondition. It cannot take into account the exit
3714  condition. So the exit condition is added by the complete_xxx
3715  functions. */
3718 
3719  if(instruction_loop_p(i)) {
3720  /* likely memory leak:-(. ct should be allocated in both test
3721  branches and freed at call site but I program everything under
3722  the opposite assumption */
3723  /* The refined transformer may be lost or stored as a block
3724  transformer is the loop is directly surrounded by a bloc or used to
3725  compute the transformer of the surroundings blokcs */
3727  }
3728  else if(instruction_whileloop_p(i)) {
3731  // This test could be deported by a call to
3732  // complete_whileloop_transformer()
3733  if(evaluation_before_p(e)) {
3734  ct = new_complete_whileloop_transformer(t, pre, w, !identity_p);
3735  }
3736  else {
3737  ct = complete_repeatloop_transformer(t, pre, w);
3738  }
3739  }
3740  else if(instruction_forloop_p(i)) {
3742  }
3743  else {
3744  if(identity_p) {
3745  /* No need to complete it */
3746  ct = copy_transformer(t);
3747  }
3748  else {
3749  /* The search for an non identity execution path must be propagated
3750  downwards */
3751  if(instruction_sequence_p(i)) {
3752  /* Each component may or not update the state... */
3753  }
3754  }
3755  }
3756  return ct;
3757 }
#define instruction_sequence_p(x)
Definition: ri.h:1512
#define instruction_loop_p(x)
Definition: ri.h:1518
#define instruction_forloop_p(x)
Definition: ri.h:1536
#define instruction_forloop(x)
Definition: ri.h:1538
#define instruction_whileloop(x)
Definition: ri.h:1523
#define instruction_whileloop_p(x)
Definition: ri.h:1521
transformer complete_forloop_transformer(transformer t_body_star, transformer pre, forloop fl)
Definition: loop.c:1686

References complete_forloop_transformer(), complete_loop_transformer(), complete_repeatloop_transformer(), copy_transformer(), evaluation_before_p, instruction_forloop, instruction_forloop_p, instruction_loop, instruction_loop_p, instruction_sequence_p, instruction_whileloop, instruction_whileloop_p, new_complete_whileloop_transformer(), statement_instruction, transformer_undefined, and whileloop_evaluation.

Referenced by complete_non_identity_statement_transformer(), and complete_statement_transformer().

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

◆ generic_module_name_to_transformers()

bool generic_module_name_to_transformers ( const char *  module_name,
bool  in_context 
)

bool generic_module_name_to_transformers(char * module_name, bool in_context): compute a transformer for each statement of a module with a given name; compute also the global transformer for the module

intraprocedural preconditions: proper declarations

This stack is useful to document warnings and to retrieve points-to information.

could be a gen_find_tabulated as well...

cumulated_effects_map_print();

compute the basis related to module m

In the main module, transformers can be computed in context of the initial values

Add declaration information: arrays cannot be empty (Fortran standard, Section 5.1.2)

Get the preconditions: they might prove useful within loops where transformers cannot propagate enough information.

compute intraprocedural transformer

FI: side effect; compute and store the summary transformer, because every needed piece of data is available...

filter out local variables from the global intraprocedural effect

Two auxiliary hash tables allocated by effectsmap_to_listmap()

Parameters
module_nameodule_name
in_contextn_context

Definition at line 918 of file dbm_interface.c.

919 {
922  /* intraprocedural preconditions: proper declarations */
924  list e_inter;
925 
928 
929  /* This stack is useful to document warnings and to retrieve
930  points-to information. */
934  /* could be a gen_find_tabulated as well... */
936  (statement) db_get_memory_resource(DBR_CODE, module_name, true));
938  pips_internal_error("no statement for module %s", module_name);
939 
941  db_get_memory_resource(DBR_PROPER_EFFECTS, module_name, true));
942 
944  db_get_memory_resource(DBR_CUMULATED_EFFECTS, module_name, true));
945 
947 
948  /* cumulated_effects_map_print();*/
949 
950  e_inter = effects_to_list( (effects)
951  db_get_memory_resource(DBR_SUMMARY_EFFECTS, module_name, true));
952 
954 
955  /* compute the basis related to module m */
957 
958  /* In the main module, transformers can be computed in context of the
959  initial values */
961  && get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT"))
962  {
964  {
965  mod_pre = (transformer)
966  db_get_memory_resource(DBR_PROGRAM_PRECONDITION, "", false);
967  if(transformer_empty_p(mod_pre)) {
969  "Initial preconditions are not consistent.\n"
970  " The Fortran standard rules about variable initialization"
971  " with DATA statements are likely to be violated.\n"
972  "set property PARSER_ACCEPT_ANSI_EXTENSIONS to false\n"
973  "and CHECK_FORTRAN_SYNTAX_BEFORE_PIPS to true.\n");
974  }
975  }
976  else
978  }
979  else if(in_context) {
980  mod_pre =
982  }
983  else
984  mod_pre = transformer_identity();
985 
986  /* Add declaration information: arrays cannot be empty (Fortran
987  standard, Section 5.1.2) */
988  if(get_bool_property("SEMANTICS_TRUST_ARRAY_DECLARATIONS")) {
991  }
992 
993  /* Get the preconditions: they might prove useful within loops where
994  transformers cannot propagate enough information. */
995  if(in_context) {
997  db_get_memory_resource(DBR_PRECONDITIONS, module_name, true));
998  }
999 
1000  /* compute intraprocedural transformer */
1002  t_intra = statement_to_transformer(ms, mod_pre);
1003  free_transformer(mod_pre);
1004 
1005  DB_PUT_MEMORY_RESOURCE(DBR_TRANSFORMERS, module_name,
1006  (char*) get_transformer_map() );
1007 
1008  /* FI: side effect; compute and store the summary transformer, because
1009  every needed piece of data is available... */
1010 
1011  /* filter out local variables from the global intraprocedural effect */
1012  t_inter = transformer_intra_to_inter(t_intra, e_inter);
1013  t_inter = transformer_normalize(t_inter, 2);
1016  }
1017  if(!transformer_consistency_p(t_inter)) {
1018  (void) print_transformer(t_inter);
1019  pips_internal_error("Non-consistent summary transformer");
1020  }
1021  DB_PUT_MEMORY_RESOURCE(DBR_SUMMARY_TRANSFORMER,
1023  (char*) t_inter);
1024  pips_debug(8, "t_inter=%p\n", t_inter);
1025 
1028  /* Two auxiliary hash tables allocated by effectsmap_to_listmap() */
1033  if(in_context) reset_precondition_map();
1034 
1037 
1039  debug_off();
1040 
1041  return true;
1042 }
#define database_undefined
Definition: database.h:42
static void transformer_add_declaration_information(transformer pre, entity m)
void set_warning_counters(void)
transformer load_summary_precondition(entity e)
summary_preconditions are expressed in any possible frame, in fact the frame of the last procedure th...
void reset_proper_rw_effects(void)
void set_proper_rw_effects(statement_effects)
void generic_effects_reset_all_methods(void)
void set_methods_for_simple_effects(void)
list effects_to_list(effects)
Definition: effects.c:209
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
#define MAKE_STATEMENT_MAPPING()
Definition: newgen-local.h:43
#define SEMANTICS_DEBUG_LEVEL
bool c_module_p(entity m)
Test if a module "m" is written in C.
Definition: entity.c:2777
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
bool entity_main_module_p(entity e)
Definition: entity.c:700
void free_statement_global_stack(void)
Definition: static.c:358
void make_statement_global_stack(void)
Definition: static.c:318
struct _newgen_struct_transformer_ * transformer
Definition: ri.h:431
transformer data_to_precondition(entity m)
restricted to variables with effects.
transformer transformer_intra_to_inter(transformer tf, list le)
void sc_variable_name_pop(void)
Definition: sc_debug.c:239
void sc_variable_name_push(char *(*fun)(Variable))
Definition: sc_debug.c:217
transformer value_passing_summary_transformer(entity f, transformer tf)
With value passing, writes on formal parameters are not effective interprocedurally unless an array i...
void set_transformer_map(statement_mapping)
void reset_precondition_map(void)
void set_precondition_map(statement_mapping)
statement_mapping get_transformer_map(void)
void reset_transformer_map(void)
const char * readable_value_name(entity)
For debugging purposes, we might have to print system with temporary values.
Definition: value.c:1769

References c_module_p(), data_to_precondition(), database_undefined, db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, effects_to_list(), entity_main_module_p(), free_statement_global_stack(), free_transformer(), free_value_mappings(), generic_effects_reset_all_methods(), get_bool_property(), get_current_module_entity(), get_current_module_statement(), get_transformer_map(), load_summary_precondition(), make_statement_global_stack(), MAKE_STATEMENT_MAPPING, module_local_name(), module_name(), module_name_to_entity(), module_to_value_mappings(), pips_debug, pips_internal_error, pips_user_warning, print_transformer, readable_value_name(), reset_cumulated_rw_effects(), reset_current_module_entity(), reset_current_module_statement(), reset_precondition_map(), reset_proper_rw_effects(), reset_transformer_map(), sc_variable_name_pop(), sc_variable_name_push(), SEMANTICS_DEBUG_LEVEL, SEMANTICS_INTERPROCEDURAL, set_cumulated_rw_effects(), set_current_module_entity(), set_current_module_statement(), set_methods_for_simple_effects(), set_precondition_map(), set_proper_rw_effects(), set_transformer_map(), set_warning_counters(), statement_to_transformer(), transformer_add_declaration_information(), transformer_consistency_p(), transformer_dup(), transformer_empty_p(), transformer_identity(), transformer_intra_to_inter(), transformer_normalize(), transformer_undefined, and value_passing_summary_transformer().

Referenced by module_name_to_transformers(), and module_name_to_transformers_in_context().

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

◆ generic_reference_to_transformer()

transformer generic_reference_to_transformer ( entity  v,
reference  r,
transformer  pre,
bool  is_internal 
)

expression.c

expression.c

May return an undefined transformer

If you are dealing with a C array reference, find transformers for each subscript expression in case of side effects.

Parameters
prere
is_internals_internal

Definition at line 126 of file expression.c.

130 {
132  entity rv = reference_variable(r);
133  list sl = reference_indices(r);
134 
135  //FI: we could do better if the subscripts are constants
136  // we could try to use constant_memory_access_path_to_location_entity()
137  // after checking that the reference is constant
138 
139  if(ENDP(sl) && ((!is_internal && analyzable_scalar_entity_p(rv))
140  || entity_has_values_p(rv))) {
141  if(!entity_undefined_p(v)) {
142  entity rv_new = is_internal?
144  transformer tfr = simple_equality_to_transformer(v, rv_new, false);
145  if(!transformer_undefined_p(pre)) {
146  // FI: assume pre is a range
147  tf = transformer_intersection(tfr, pre);
148  }
149  free_transformer(tfr);
150  }
151  }
152  else if(ENDP(sl)) {
153  // Might be a constant value for a pointer, such as "a", an array
155  if(array_type_p(t)) {
156  // int d = (int) gen_length(variable_indices(type_variable(t)));
157  // list sl = make_zero_subscripts(d);
159  reference r = make_reference(rv, sl);
160  entity l = constant_memory_access_path_to_location_entity(r); // l is a constant location
161  if(!entity_undefined_p(l)) {
162  transformer tfr = simple_equality_to_transformer(v, l, false);
163  if(!transformer_undefined_p(pre)) {
164  // FI: assume pre is a range
165  tf = transformer_intersection(tfr, pre);
166  }
167  free_transformer(tfr);
168  }
169  }
170  }
171  else if(get_bool_property("SEMANTICS_ANALYZE_CONSTANT_PATH")) {
173  // an array reference may have an impact on some values
175  if(analyzed_type_p(t)) {
176  bool processed_p = false;
179  if(!entity_undefined_p(rv) && !entity_undefined_p(v)) {
180  processed_p = true;
181  tf = transformer_add_equality(tf, v, rv);
182  }
183  }
184  if(!processed_p) {
185  // FI: not sure why we would only be interested in modified variables
187  FOREACH(ENTITY, wv, wvl) {
188  if(location_entity_p(wv)) {
189  value val = entity_initial(wv);
190  reference lr = value_reference(val);
191  // FI: when a precondition is available, it should be used
192  // to build almost a dependence test
193  if(references_may_conflict_p(r, lr)) {
194  tf = transformer_add_variable_update(tf, wv);
195  }
196  }
197  }
198  }
199  }
200  }
201 
202  if(transformer_undefined_p(tf)) {
203  /* If you are dealing with a C array reference, find transformers
204  for each subscript expression in case of side effects. */
206  if(c_language_module_p(m)) {
208  }
209  }
210  return tf;
211 }
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
transformer transformer_add_variable_update(transformer t, entity v)
Add an update of variable v into t.
Definition: basic.c:289
bool location_entity_p(entity)
Definition: locations.c:349
type points_to_reference_to_concrete_type(reference)
Definition: type.c:685
entity constant_memory_access_path_to_location_entity(reference)
A constant memory access path may not be considered.
Definition: locations.c:329
bool references_may_conflict_p(reference r1, reference r2)
Check if two references may conflict.
Definition: conflicts.c:426
expression make_zero_expression(void)
Make a zero expression.
Definition: expression.c:1212
bool store_independent_reference_p(reference r)
Does this reference define the same set of memory locations regardless of the current (environment an...
Definition: expression.c:3108
bool c_language_module_p(entity m)
Definition: module.c:447
bool array_type_p(type)
Definition: type.c:2942
#define value_reference(x)
Definition: ri.h:3085
#define entity_undefined_p(x)
Definition: ri.h:2762
list modified_variables_with_values(void)
Return the list of all analyzed variables which are modified in the current module.
Definition: value.c:1094

References analyzable_scalar_entity_p(), analyzed_type_p(), array_type_p(), c_language_module_p(), CONS, constant_memory_access_path_to_location_entity(), ENDP, ENTITY, entity_basic_concrete_type(), entity_has_values_p(), entity_initial, entity_to_new_value(), entity_undefined_p, EXPRESSION, expressions_to_transformer(), external_entity_to_new_value(), FOREACH, free_transformer(), get_bool_property(), get_current_module_entity(), location_entity_p(), make_reference(), make_zero_expression(), modified_variables_with_values(), NIL, points_to_reference_to_concrete_type(), reference_indices, reference_variable, references_may_conflict_p(), simple_equality_to_transformer(), store_independent_reference_p(), transformer_add_equality(), transformer_add_variable_update(), transformer_intersection(), transformer_undefined, transformer_undefined_p, and value_reference.

Referenced by assign_rhs_to_reflhs_to_transformer(), expression_to_transformer(), float_expression_to_transformer(), integer_expression_to_transformer(), pointer_expression_to_transformer(), and points_to_unary_operation_to_transformer().

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

◆ generic_substitute_formal_array_elements_in_transformer()

transformer generic_substitute_formal_array_elements_in_transformer ( transformer  ,
entity  ,
list  ,
transformer  ,
list  ,
bool   
)

◆ generic_transformer_intra_to_inter()

transformer generic_transformer_intra_to_inter ( transformer  tf,
list  le,
bool  preserve_rv_p 
)

transformer translation from the module intraprocedural transformer to the module interprocedural transformer.

Values related to variables local to the module must be eliminated. Note that in C they should be eliminated earlier when the effect of the local declaration is taken into account or when the corresponding scope block is closed.

Filtered TransFormer ftf

cons * old_args = transformer_arguments(ftf);

get rid of tf's arguments that do not appear in effects le

build a list of arguments to suppress

FI: I do not understand anymore why corresponding old values do not have to be suppressed too (6 July 1993)

FI: because only read arguments are eliminated, non? (12 November 1995)

FI: the resulting intermediate transformer is not consistent (18 July 2003)

get rid of them

ftf = transformer_projection(ftf, lost_args);

free the temporary list of entities

get rid of local read variables

FI: why not use this loop to get rid of all local variables, read or written?

Variables with no impact on the caller world are eliminated. However, the return value associated to a function is conditionnally preserved.

get rid of them

free the temporary list of entities

Parameters
tff
lee
preserve_rv_preserve_rv_p

Definition at line 1398 of file ri_to_transformers.c.

1401 {
1402  cons * lost_args = NIL;
1403  /* Filtered TransFormer ftf */
1404  transformer ftf = transformer_dup(tf);
1405  /* cons * old_args = transformer_arguments(ftf); */
1406  Psysteme sc = SC_UNDEFINED;
1407  Pbase b = BASE_UNDEFINED;
1408  Pbase eb = BASE_UNDEFINED;
1409 
1410  pips_debug(8,"begin\n");
1411  pips_debug(8,"argument tf=%p\n",ftf);
1412  ifdebug(8) (void) dump_transformer(ftf);
1413 
1414  /* get rid of tf's arguments that do not appear in effects le */
1415 
1416  /* build a list of arguments to suppress */
1417  /* FI: I do not understand anymore why corresponding old values do not have
1418  * to be suppressed too (6 July 1993)
1419  *
1420  * FI: because only read arguments are eliminated, non? (12 November 1995)
1421  *
1422  * FI: the resulting intermediate transformer is not consistent (18 July 2003)
1423  */
1424  /*
1425  MAPL(ca,
1426  {entity e = ENTITY(CAR(ca));
1427  if(!effects_write_entity_p(le, e) &&
1428  !storage_return_p(entity_storage(e)))
1429  lost_args = arguments_add_entity(lost_args, e);
1430  },
1431  old_args);
1432  */
1433  /* get rid of them */
1434  /* ftf = transformer_projection(ftf, lost_args); */
1435 
1436  /* free the temporary list of entities */
1437  /*
1438  gen_free_list(lost_args);
1439  lost_args = NIL;
1440 
1441  pips_debug(8,"after first filtering ftf=%x\n",ftf);
1442  ifdebug(8) (void) dump_transformer(ftf);
1443  */
1444 
1445  /* get rid of local read variables */
1446 
1447  /* FI: why not use this loop to get rid of *all* local variables, read or written? */
1448 
1450  b = sc_base(sc);
1451  for(eb=b; !BASE_UNDEFINED_P(eb); eb = eb->succ) {
1452  entity e = (entity) vecteur_var(eb);
1453 
1454  if(e != (entity) TCST) {
1455  entity v = value_to_variable(e);
1456  /*
1457  entity v = entity_undefined;
1458 
1459  // Because static Fortran equivalences are indicated by an equality
1460  // Only one of the two equivalenced variables has values ?
1461  if(entity_has_values_p(v))
1462  v = value_to_variable(e);
1463  else
1464  v = e;
1465  */
1466 
1467  /* Variables with no impact on the caller world are eliminated.
1468  * However, the return value associated to a function is
1469  * conditionnally preserved.
1470  */
1471  if(!entity_constant_p(v)) {
1474  && (global_variable_p(v)||formal_parameter_p(v)))) {
1475  if(preserve_rv_p) {
1477  lost_args = arguments_add_entity(lost_args, e);
1478  }
1479  else {
1480  // get rid of non local return entities
1481  storage s = entity_storage(v);
1482  if(storage_return_p(s)) {
1483  entity f = storage_return(s);
1485  if(f!=m)
1486  lost_args = arguments_add_entity(lost_args, e);
1487  }
1488  else
1489  lost_args = arguments_add_entity(lost_args, e);
1490  }
1491  }
1492  }
1493  }
1494  }
1495  }
1496 
1497  /* get rid of them */
1498  ftf = transformer_projection(ftf, lost_args);
1499 
1500  /* free the temporary list of entities */
1501  gen_free_list(lost_args);
1502  lost_args = NIL;
1503 
1504  pips_debug(8,"return ftf=%p\n",ftf);
1505  ifdebug(8) (void) dump_transformer(ftf);
1506  pips_debug(8,"end\n");
1507 
1508  return ftf;
1509 }
bool concrete_effects_may_read_or_write_scalar_entity_p(list fx, entity e)
Definition: conflicts.c:1220
bool effects_may_read_or_write_scalar_entity_p(list fx, entity e)
check whether scalar entity e may be read or written by effects fx or cannot be accessed at all
Definition: conflicts.c:1214
#define entity_constant_p(e)
bool global_variable_p(entity)
Is v a global variable such as "int i;".
Definition: variable.c:1510
bool formal_parameter_p(entity)
Definition: variable.c:1489
#define storage_return(x)
Definition: ri.h:2518
struct Svecteur * succ
Definition: vecteur-local.h:92
transformer transformer_projection(transformer t, list args)
values in args must be in t's base
Definition: transformer.c:1267
#define BASE_UNDEFINED_P(b)
#define BASE_UNDEFINED

References arguments_add_entity(), BASE_UNDEFINED, BASE_UNDEFINED_P, concrete_effects_may_read_or_write_scalar_entity_p(), dump_transformer, effects_may_read_or_write_scalar_entity_p(), entity_constant_p, entity_storage, f(), formal_parameter_p(), gen_free_list(), get_current_module_entity(), global_variable_p(), ifdebug, NIL, pips_debug, predicate_system, storage_return, storage_return_p, Svecteur::succ, TCST, transformer_dup(), transformer_projection(), transformer_relation, value_to_variable(), and vecteur_var.

Referenced by c_return_to_transformer(), and transformer_intra_to_inter().

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

◆ get_call_site_number()

int get_call_site_number ( void  )

Definition at line 1131 of file interprocedural.c.

1132 {
1133  return number_of_call_sites;
1134 }
static int number_of_call_sites

References number_of_call_sites.

Referenced by summary_precondition(), and summary_total_postcondition().

+ Here is the caller graph for this function:

◆ get_module_global_arguments()

list get_module_global_arguments ( void  )

ri_to_preconditions.c

Definition at line 98 of file ri_to_preconditions.c.

99 {
101 }
static list module_global_arguments
semantical analysis

References module_global_arguments.

Referenced by statement_to_postcondition(), and statement_to_total_precondition().

+ Here is the caller graph for this function:

◆ get_module_precondition()

transformer get_module_precondition ( entity  m)

interprocedural.c

interprocedural.c

include <stdlib.h> What follows has to be updated!!!

The SUMMARY_PRECONDITION of a module m is built incrementally when the preconditions of its CALLERS are computed. Each time a call site cs to m is encountered, the precondition for cs is augmented with equations between formal and actual integer arguments. The new precondition so obtained is chained to the other preconditions for m.

In other word, SUMMARY_PRECONDITION is a list of preconditions containing each a relation between formal and actual parameter. Should it be called SUMMARY_PRECONDITIONS?

Before using the list of preconditions for m, each precondition has to:

  • be translated to update references to variables in common; if they are visible in m, their entity names caller:x have to be replaced by m:x;
  • be projected to eliminate variables which are not recognized by m semantics analysis (i.e. they do not appear in its value mappings);
  • be replaced by their unique convex hull, which is the real module precondition.

These steps cannot be performed in the caller because the callee's value mappings are unknown.

Memory management:

  • transformers stored by add_module_call_site_precondition() are copies or modified copies of the precondition argument ;
  • transformers returned as module preconditions are not duplicated; it does not seem to matter for the time being because a module precondition should be used only once. Wait for the strange bugs... db_get_memory_resource() could be not PURE.

Note: illegal request are made to pipsdbm()

FI: this does not work because the summary preconditions is reset each time it should be accumulated

Definition at line 92 of file interprocedural.c.

94 {
95  transformer p;
96 
97  pips_assert("get_module_precondition",entity_module_p(m));
98 
99  if(db_resource_p(DBR_SUMMARY_PRECONDITION, module_local_name(m)))
100  p = (transformer) db_get_memory_resource(DBR_SUMMARY_PRECONDITION,
102  true);
103  else
105 
106  /* FI: this does not work because the summary preconditions is reset
107  each time it should be accumulated */
108  /*
109  if(check_resource_up_to_date(DBR_SUMMARY_PRECONDITION,
110  module_local_name(m))) {
111  p = (transformer) db_get_memory_resource(DBR_SUMMARY_PRECONDITION,
112  module_local_name(m),
113  true);
114  }
115  else {
116  p = transformer_undefined;
117  }
118  */
119 
120  return p;
121 }
bool db_resource_p(const char *rname, const char *oname)
true if exists and in loaded or stored state.
Definition: database.c:524

References db_get_memory_resource(), db_resource_p(), entity_module_p(), module_local_name(), pips_assert, and transformer_undefined.

Referenced by add_module_call_site_precondition().

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

◆ get_postcondition_map()

statement_mapping get_postcondition_map ( void  )

◆ get_precondition_map()

statement_mapping get_precondition_map ( void  )

Referenced by init_use_preconditions(), module_name_to_preconditions(), set_resources_for_module(), and transformer_map_print().

+ Here is the caller graph for this function:

◆ get_semantic_map()

statement_mapping get_semantic_map ( void  )

◆ get_text_preconditions()

text get_text_preconditions ( const  string)
Parameters
stringodule_name

Definition at line 193 of file prettyprint.c.

194 {
195  is_user_view = false;
196  is_transformer = false;
197  is_total_precondition = false;
199  get_bool_property("SEMANTICS_FILTERED_PRECONDITIONS");
200  return get_semantic_text(module_name,false);
201 }
static bool is_total_precondition
Definition: prettyprint.c:73
static bool is_transformer
Definition: prettyprint.c:72
static bool is_user_view
Definition: prettyprint.c:74
static text get_semantic_text(const char *, bool)
Definition: prettyprint.c:254
static bool is_transformer_filtered
Definition: prettyprint.c:75

References get_bool_property(), get_semantic_text(), is_total_precondition, is_transformer, is_transformer_filtered, is_user_view, and module_name().

Referenced by print_call_graph_with_preconditions().

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

◆ get_text_total_preconditions()

text get_text_total_preconditions ( const  string)
Parameters
stringodule_name

Definition at line 203 of file prettyprint.c.

204 {
205  is_user_view = false;
206  is_transformer = false;
207  is_total_precondition = true;
209  get_bool_property("SEMANTICS_FILTERED_PRECONDITIONS");
210  return get_semantic_text(module_name,false);
211 }

References get_bool_property(), get_semantic_text(), is_total_precondition, is_transformer, is_transformer_filtered, is_user_view, and module_name().

Referenced by print_call_graph_with_total_preconditions().

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

◆ get_text_transformers()

text get_text_transformers ( const  string)
Parameters
stringodule_name

Definition at line 184 of file prettyprint.c.

185 {
186  is_user_view = false;
187  is_transformer = true;
188  is_total_precondition = false;
189  is_transformer_filtered = false;
190  return get_semantic_text(module_name,false);
191 }

References get_semantic_text(), is_total_precondition, is_transformer, is_transformer_filtered, is_user_view, and module_name().

Referenced by print_call_graph_with_transformers().

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

◆ get_total_precondition_map()

statement_mapping get_total_precondition_map ( void  )

Referenced by module_name_to_total_preconditions().

+ Here is the caller graph for this function:

◆ get_transformer_map()

statement_mapping get_transformer_map ( void  )

Referenced by generic_module_name_to_transformers().

+ Here is the caller graph for this function:

◆ initial_precondition()

bool initial_precondition ( string  name)

initial.c

initial.c

Filter out local and unused variables from the local precondition? No, because it is not possible to guess what is used or unused at the program level. Filtering is postponed to program_precondition().

Parameters
nameame

Definition at line 75 of file initial.c.

76 {
78  transformer prec;
79 
80  debug_on("SEMANTICS_DEBUG_LEVEL");
81 
84  db_get_memory_resource(DBR_CODE, name, true));
87  db_get_memory_resource(DBR_CUMULATED_EFFECTS, name, true));
89  db_get_memory_resource(DBR_PROPER_EFFECTS, name, true));
91 
93 
94  ifdebug(1)
95  pips_assert("consistent initial precondition before filtering",
97 
98  /* Filter out local and unused variables from the local precondition?
99  * No, because it is not possible to guess what is used or unused at
100  * the program level. Filtering is postponed to program_precondition().
101  */
102 
103  DB_PUT_MEMORY_RESOURCE(DBR_INITIAL_PRECONDITION, strdup(name), (char*) prec);
104 
110 
112 
113  debug_off();
114  return true;
115 }
#define true
Definition: newgen_types.h:81
transformer all_data_to_precondition(entity m)
any variable is included.

References all_data_to_precondition(), db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, free_statement_global_stack(), free_value_mappings(), ifdebug, make_statement_global_stack(), module, module_name_to_entity(), module_to_value_mappings(), pips_assert, reset_cumulated_rw_effects(), reset_current_module_entity(), reset_current_module_statement(), reset_proper_rw_effects(), set_cumulated_rw_effects(), set_current_module_entity(), set_current_module_statement(), set_proper_rw_effects(), strdup(), and transformer_consistency_p().

+ Here is the call graph for this function:

◆ integer_assign_to_transformer()

transformer integer_assign_to_transformer ( expression  lhs,
expression  rhs,
transformer  pre,
list  ef 
)

This function never returns an undefined transformer.

It is used for an assignment statement, not for an assignment operation. effects of assign

algorithm: if lhs and rhs are linear expressions on scalar integer variables, build the corresponding equation; else, use effects ef

should be extended to cope with constant integer division as in N2 = N/2 because it is used in real program; inequalities should be generated in that case 2*N2 <= N <= 2*N2+1

same remark for MOD operator

implementation: part of this function should be moved into transformer.c

&& integer_scalar_entity_p(e)

FI: the initial version was conservative because only affine scalar integer assignments were processed precisely. But non-affine operators and calls to user defined functions can also bring some information as soon as some integer read or write effect exists

check that all read effects are on integer scalar entities

Check that some read or write effects are on integer scalar entities. This is almost always true... Let's hope assigned_expression_to_transformer() returns quickly for array expressions used to initialize a scalar integer entity.

if some condition was not met and transformer derivation failed

Parameters
lhshs
rhshs
prere
eff

Definition at line 2693 of file ri_to_transformers.c.

2697 {
2698  /* algorithm: if lhs and rhs are linear expressions on scalar integer
2699  variables, build the corresponding equation; else, use effects ef
2700 
2701  should be extended to cope with constant integer division as in
2702  N2 = N/2
2703  because it is used in real program; inequalities should be
2704  generated in that case 2*N2 <= N <= 2*N2+1
2705 
2706  same remark for MOD operator
2707 
2708  implementation: part of this function should be moved into
2709  transformer.c
2710  */
2711 
2714 
2715  pips_debug(8,"begin\n");
2716 
2717  if(normalized_linear_p(n)) {
2718  Pvecteur vlhs = (Pvecteur) normalized_linear(n);
2719  entity e = (entity) vecteur_var(vlhs);
2720 
2721  if(entity_has_values_p(e) /* && integer_scalar_entity_p(e) */) {
2722  /* FI: the initial version was conservative because
2723  * only affine scalar integer assignments were processed
2724  * precisely. But non-affine operators and calls to user defined
2725  * functions can also bring some information as soon as
2726  * *some* integer read or write effect exists
2727  */
2728  /* check that *all* read effects are on integer scalar entities */
2729  /*
2730  if(integer_scalar_read_effects_p(ef)) {
2731  tf = assigned_expres`sion_to_transformer(e, rhs, ef);
2732  }
2733  */
2734  /* Check that *some* read or write effects are on integer
2735  * scalar entities. This is almost always true... Let's hope
2736  * assigned_expression_to_transformer() returns quickly for array
2737  * expressions used to initialize a scalar integer entity.
2738  */
2740  tf = assigned_expression_to_transformer(e, rhs, pre);
2741  }
2742  }
2743  }
2744  /* if some condition was not met and transformer derivation failed */
2745  if(tf==transformer_undefined)
2746  tf = effects_to_transformer(ef);
2747 
2748  pips_debug(6,"return tf=%lx\n", (unsigned long)tf);
2749  ifdebug(6) (void) print_transformer(tf);
2750  pips_debug(8,"end\n");
2751  return tf;
2752 }
bool some_integer_scalar_read_or_write_effects_p(cons *)

References assigned_expression_to_transformer(), effects_to_transformer(), entity_has_values_p(), ifdebug, NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, pips_debug, print_transformer, some_integer_scalar_read_or_write_effects_p(), transformer_undefined, and vecteur_var.

+ Here is the call graph for this function:

◆ integer_assign_to_transformer_list()

list integer_assign_to_transformer_list ( expression  lhs,
expression  rhs,
transformer  pre,
list  ef 
)

This function never returns an undefined transformer.

It is used for an assignment statement, not for an assignment operation. effects of assign

algorithm: if lhs and rhs are linear expressions on scalar integer variables, build the corresponding equation; else, use effects ef

should be extended to cope with constant integer division as in N2 = N/2 because it is used in real program; inequalities should be generated in that case 2*N2 <= N <= 2*N2+1

same remark for MOD operator

implementation: part of this function should be moved into transformer.c

&& integer_scalar_entity_p(e)

FI: the initial version was conservative because only affine scalar integer assignments were processed precisely. But non-affine operators and calls to user defined functions can also bring some information as soon as some integer read or write effect exists

check that all read effects are on integer scalar entities

Check that some read or write effects are on integer scalar entities. This is almost always true... Let's hope assigned_expression_to_transformer() returns quickly for array expressions used to initialize a scalar integer entity.

if some condition was not met and transformer derivation failed

Parameters
lhshs
rhshs
prere
eff

Definition at line 645 of file ri_to_transformer_lists.c.

649 {
650  /* algorithm: if lhs and rhs are linear expressions on scalar integer
651  variables, build the corresponding equation; else, use effects ef
652 
653  should be extended to cope with constant integer division as in
654  N2 = N/2
655  because it is used in real program; inequalities should be
656  generated in that case 2*N2 <= N <= 2*N2+1
657 
658  same remark for MOD operator
659 
660  implementation: part of this function should be moved into
661  transformer.c
662  */
663 
664  list tl = NIL;
667 
668  pips_internal_error("Not implemented yet.");
669 
670  pips_debug(8,"begin\n");
671 
672  if(normalized_linear_p(n)) {
673  Pvecteur vlhs = (Pvecteur) normalized_linear(n);
674  entity e = (entity) vecteur_var(vlhs);
675 
676  if(entity_has_values_p(e) /* && integer_scalar_entity_p(e) */) {
677  /* FI: the initial version was conservative because
678  * only affine scalar integer assignments were processed
679  * precisely. But non-affine operators and calls to user defined
680  * functions can also bring some information as soon as
681  * *some* integer read or write effect exists
682  */
683  /* check that *all* read effects are on integer scalar entities */
684  /*
685  if(integer_scalar_read_effects_p(ef)) {
686  tf = assigned_expres`sion_to_transformer(e, rhs, ef);
687  }
688  */
689  /* Check that *some* read or write effects are on integer
690  * scalar entities. This is almost always true... Let's hope
691  * assigned_expression_to_transformer() returns quickly for array
692  * expressions used to initialize a scalar integer entity.
693  */
695  tf = assigned_expression_to_transformer(e, rhs, pre);
696  }
697  }
698  }
699  /* if some condition was not met and transformer derivation failed */
700  if(tf==transformer_undefined)
701  tf = effects_to_transformer(ef);
702 
703  pips_debug(6,"return tl=%lx\n", (unsigned long)tl);
704  ifdebug(6) (void) print_transformers(tl);
705  pips_debug(8,"end\n");
706  return tl;
707 }

References assigned_expression_to_transformer(), effects_to_transformer(), entity_has_values_p(), ifdebug, NIL, NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, pips_debug, pips_internal_error, print_transformers(), some_integer_scalar_read_or_write_effects_p(), transformer_undefined, and vecteur_var.

+ Here is the call graph for this function:

◆ integer_expression_and_precondition_to_integer_interval()

void integer_expression_and_precondition_to_integer_interval ( expression  e,
transformer  p,
int plb,
int pub 
)

Could be used for bool expressions too? Extended to any kind of expression?

p is assumed to be a real precondition, i.e. a transformer_range().

This function is used by semantics as well as exported to other passes. To take care of debug_on()/debug_off(), set and reset_analyzed_types(), a different wrapper is needed.

If expression e is transformer-wise side-effect free (i.e. the ABSTRACT store is not modified)

precondition p is not feasible

Parameters
plblb
pubub

Definition at line 386 of file utils.c.

390 {
391  debug_on("SEMANTICS_DEBUG_LEVEL");
392  // set_analyzed_types();
393  type t = expression_to_type(e);
395  transformer et = integer_expression_to_transformer(tmp, e, p, true);
396 
397  /* If expression e is transformer-wise side-effect free (i.e. the ABSTRACT store is not modified)*/
403  Value lb = VALUE_ZERO, ub = VALUE_ZERO;
404 
405  if(sc_minmax_of_variable(s, (Variable) tmp,
406  &lb, &ub)) {
407  *plb = value_min_p(lb)? INT_MIN : VALUE_TO_INT(lb);
408  *pub = value_max_p(ub)? INT_MAX : VALUE_TO_INT(ub);
409  }
410  else {
411  /* precondition p is not feasible */
412  *plb = 1;
413  *pub = 0;
414  }
415  }
416  else {
417  *plb = INT_MIN;
418  *pub = INT_MAX;
419  }
420  //reset_analyzed_types();
421  debug_off();
422 }
transformer transformer_range_intersection(transformer tf, transformer r)
Allocate a new transformer rtf that is tf with its range restricted by the range r.
Definition: transformer.c:830

References CONTRAINTE_UNDEFINED, debug_off, debug_on, ENDP, expression_to_type(), integer_expression_to_transformer(), make_local_temporary_value_entity(), predicate_system, sc_dup(), sc_make(), sc_minmax_of_variable(), transformer_arguments, transformer_dup(), transformer_range_intersection(), transformer_relation, transformer_undefined_p, value_max_p, value_min_p, VALUE_TO_INT, and VALUE_ZERO.

Referenced by eval_linear_expression(), expression_multiply_sizeof_to_transformer(), generic_abs_to_transformer(), and loop_to_enter_transformer().

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

◆ integer_expression_to_transformer()

transformer integer_expression_to_transformer ( entity  v,
expression  expr,
transformer  pre,
bool  is_internal 
)

Do check wrt to value mappings...

if you are not dealing with interprocedural issues

Assume: e is a value

Is it really useful to keep using this function which does not take the precondition into acount?

vect_rm(ve);

Parameters
exprxpr
prere
is_internals_internal

Definition at line 3476 of file expression.c.

3482 {
3484  normalized n = NORMALIZE_EXPRESSION(expr);
3485  syntax sexpr = expression_syntax(expr);
3486 
3487  pips_debug(8, "begin with precondition %p for expression: ", pre);
3488  ifdebug(8) print_expression(expr);
3489 
3490  /* Assume: e is a value */
3491 
3492  if(normalized_linear_p(n)) {
3493  /* Is it really useful to keep using this function which does not
3494  take the precondition into acount? */
3495  if(transformer_undefined_p(pre)) {
3496  tf = simple_affine_to_transformer(v, (Pvecteur) normalized_linear(n), is_internal);
3497  }
3498  else {
3500  if(transformer_undefined_p(tfl)) {
3502  }
3503 
3504  tf = transformer_combine(copy_transformer(pre), tfl);
3505  free_transformer(tfl);
3506  }
3507  }
3508  else if(syntax_call_p(sexpr)) {
3509  tf = integer_call_expression_to_transformer(v, expr, pre, is_internal);
3510  }
3511  else if(syntax_reference_p(sexpr)) {
3512  //entity e = reference_variable(syntax_reference(sexpr));
3513  reference r = syntax_reference(sexpr);
3514  tf = generic_reference_to_transformer(v, r, pre, is_internal);
3515  }
3516  else if(syntax_cast_p(sexpr)) {
3517  cast c = syntax_cast(sexpr);
3518  type ct = cast_type(c);
3519  expression cexp = cast_expression(c);
3520  type cexpt = expression_to_type(cexp);
3521  if (type_equal_p(ct, cexpt))
3522  tf = integer_expression_to_transformer(v, cexp, pre, is_internal);
3523  else
3524  tf = transformer_undefined;
3525  free_type(cexpt);
3526 
3527  }
3528  else if(syntax_sizeofexpression_p(sexpr)) {
3529  if(get_bool_property("EVAL_SIZEOF")) {
3531  value val = EvalSizeofexpression(soe);
3532  if(value_constant_p(val) && constant_int_p(value_constant(val))) {
3533  long long int i = constant_int(value_constant(val));
3534  tf = transformer_identity();
3536  }
3537  }
3538  else
3539  tf = transformer_undefined;
3540  }
3541  else {
3542  /* vect_rm(ve); */
3543  tf = transformer_undefined;
3544  }
3545 
3546  pips_debug(8, "end with tf=%p\n", tf);
3547 
3548  return tf;
3549 }
value EvalSizeofexpression(sizeofexpression soe)
Definition: eval.c:210
#define value_constant(x)
Definition: ri.h:3073
#define constant_int(x)
Definition: ri.h:850
#define syntax_sizeofexpression_p(x)
Definition: ri.h:2740
#define value_constant_p(x)
Definition: ri.h:3071
#define constant_int_p(x)
Definition: ri.h:848
#define syntax_sizeofexpression(x)
Definition: ri.h:2742
#define cast_type(x)
Definition: ri.h:745
static transformer integer_call_expression_to_transformer(entity e, expression expr, transformer pre, bool is_internal)
Definition: expression.c:3361
transformer expression_effects_to_transformer(expression expr)
Definition: expression.c:3465
transformer simple_affine_to_transformer(entity e, Pvecteur a, bool is_internal)
INTEGER EXPRESSIONS.
Definition: expression.c:1167

References cast_expression, cast_type, constant_int, constant_int_p, copy_transformer(), EvalSizeofexpression(), expression_effects_to_transformer(), expression_syntax, expression_to_type(), free_transformer(), free_type(), generic_reference_to_transformer(), get_bool_property(), ifdebug, integer_call_expression_to_transformer(), NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, pips_debug, print_expression(), simple_affine_to_transformer(), syntax_call_p, syntax_cast, syntax_cast_p, syntax_reference, syntax_reference_p, syntax_sizeofexpression, syntax_sizeofexpression_p, transformer_add_equality_with_integer_constant(), transformer_combine(), transformer_identity(), transformer_undefined, transformer_undefined_p, type_equal_p(), value_constant, and value_constant_p.

Referenced by any_expression_to_transformer(), iabs_to_transformer(), integer_expression_and_precondition_to_integer_interval(), integer_minmax_to_transformer(), and safe_integer_expression_to_transformer().

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

◆ integer_value_and_precondition_to_integer_interval()

void integer_value_and_precondition_to_integer_interval ( entity  v,
transformer  p,
int plb,
int pub 
)

Should be used by previous function, integer_expression_and_precondition_to_integer_interval()

precondition p is not feasible

Parameters
plblb
pubub

Definition at line 427 of file utils.c.

431 {
435  Value lb = VALUE_ZERO, ub = VALUE_ZERO;
436 
437  if(sc_minmax_of_variable(s, (Variable) v,
438  &lb, &ub)) {
439  *plb = value_min_p(lb)? INT_MIN : VALUE_TO_INT(lb);
440  *pub = value_max_p(ub)? INT_MAX : VALUE_TO_INT(ub);
441  }
442  else {
443  /* precondition p is not feasible */
444  *plb = 1;
445  *pub = 0;
446  }
447 }

References CONTRAINTE_UNDEFINED, predicate_system, sc_dup(), sc_make(), sc_minmax_of_variable(), transformer_relation, transformer_undefined_p, value_max_p, value_min_p, VALUE_TO_INT, and VALUE_ZERO.

Referenced by integer_binary_operation_to_transformer(), and integer_multiply_to_transformer().

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

◆ interprocedural_summary_precondition()

bool interprocedural_summary_precondition ( char *  module_name)

The DATA statement from all modules, called or not called, are used, as well as the preconditions at all call sites.

Parameters
module_nameodule_name

Definition at line 545 of file dbm_interface.c.

546 {
547  /* The DATA statement from all modules, called or not called, are used,
548  as well as the preconditions at all call sites. */
551 }
bool summary_precondition(char *module_name)
void set_bool_property(const char *, bool)

References module_name(), SEMANTICS_INTERPROCEDURAL, set_bool_property(), and summary_precondition().

+ Here is the call graph for this function:

◆ interprocedural_summary_precondition_with_points_to()

bool interprocedural_summary_precondition_with_points_to ( char *  module_name)

The DATA statement from all modules, called or not called, are used, as well as the preconditions at all call sites. Points_to information is required to perform a more accurate translation between callesr and callees.

Parameters
module_nameodule_name

Definition at line 571 of file dbm_interface.c.

572 {
573  /* The DATA statement from all modules, called or not called, are
574  * used, as well as the preconditions at all call sites. Points_to
575  * information is required to perform a more accurate translation
576  * between callesr and callees.
577  */
580  bool result_p = summary_precondition(module_name);
582  return result_p;
583 }
static void reset_use_points_to()
static void set_use_points_to()

References module_name(), reset_use_points_to(), SEMANTICS_INTERPROCEDURAL, set_bool_property(), set_use_points_to(), and summary_precondition().

+ Here is the call graph for this function:

◆ intraprocedural_summary_precondition()

bool intraprocedural_summary_precondition ( char *  module_name)

The current module is sufficient to derive it.

Parameters
module_nameodule_name

Definition at line 538 of file dbm_interface.c.

539 {
540  /* The current module is sufficient to derive it. */
543 }

References module_name(), SEMANTICS_INTERPROCEDURAL, set_bool_property(), and summary_precondition().

+ Here is the call graph for this function:

◆ intrinsic_to_transformer()

transformer intrinsic_to_transformer ( entity  e,
list  pc,
transformer  pre,
list  ef 
)

effects of intrinsic call

FI: this may happen, for instance with the macro definition of assert() or because the programmer writes "i>1? (i = 2): (i = 3);" instead of "i = i>1? 2 : 3;"

FI: the condition should be evaluated and considered true on exit, but this is sometimes captured by a macro definition and the code below is then useless

The result is positive and less than RAND_MAX, but it is ignored by the semantics anaysis

Parameters
pcc
prere
eff

Definition at line 911 of file ri_to_transformers.c.

915 {
917 
918  pips_debug(8, "begin\n");
919 
920  if(ENTITY_ASSIGN_P(e)) {
921  tf = any_assign_to_transformer(pc, ef, pre);
922  }
928  //tf = update_addition_operation_to_transformer(pc, ef, pre);
929  tf = any_update_to_transformer(e, pc, ef, pre);
930  }
933  tf = any_basic_update_to_transformer(e, pc, ef, pre);
934  }
935  else if(ENTITY_C_RETURN_P(e)) {
936  tf = c_return_to_transformer(e, pc, ef, pre);
937  }
940  tf = transformer_empty();
941  else if(ENTITY_COMMA_P(e)) {
942  tf = expressions_to_transformer(pc, pre);
943  }
944  else if(ENTITY_CONDITIONAL_P(e)) {
945  /* FI: this may happen, for instance with the macro definition of
946  assert() or because the programmer writes "i>1? (i = 2): (i =
947  3);" instead of "i = i>1? 2 : 3;" */
948  expression cond = EXPRESSION(CAR(pc));
949  expression e1 = EXPRESSION(CAR(CDR(pc)));
950  expression e2 = EXPRESSION(CAR(CDR(CDR(pc))));
951  tf = conditional_to_transformer(cond, e1, e2, pre, ef);
952  }
953  else if(ENTITY_ASSERT_SYSTEM_P(e)) {
954  /* FI: the condition should be evaluated and considered true on
955  exit, but this is sometimes captured by a macro definition and the code
956  below is then useless */
957  expression cond = EXPRESSION(CAR(pc));
958  tf = condition_to_transformer(cond, pre, true);
959  }
960  else if(ENTITY_RAND_P(e)) {
961  /* The result is positive and less than RAND_MAX, but it is
962  ignored by the semantics anaysis */
963  semantics_user_warning("Value returned by intrinsic \"rand\" is ignored.\n");
964  //tf = transformer_add_inequality_with_integer_constraint(transformer_identity(),
965  // e, 0, true);
966  tf = transformer_identity();
967  }
968  else
969  tf = effects_to_transformer(ef);
970 
971  pips_debug(8, "end\n");
972 
973  return tf;
974 }
#define ENTITY_PLUS_UPDATE_P(e)
#define ENTITY_MODULO_UPDATE_P(e)
#define ENTITY_STOP_P(e)
#define ENTITY_BITWISE_AND_UPDATE_P(e)
#define ENTITY_ASSIGN_P(e)
#define ENTITY_ASSERT_SYSTEM_P(e)
include <assert.h>
#define ENTITY_PRE_DECREMENT_P(e)
#define ENTITY_EXIT_SYSTEM_P(e)
#define ENTITY_CONDITIONAL_P(e)
#define ENTITY_RIGHT_SHIFT_UPDATE_P(e)
#define ENTITY_BITWISE_OR_UPDATE_P(e)
#define ENTITY_RAND_P(e)
#define ENTITY_ABORT_SYSTEM_P(e)
#define ENTITY_MULTIPLY_UPDATE_P(e)
#define ENTITY_DIVIDE_UPDATE_P(e)
#define ENTITY_C_RETURN_P(e)
#define ENTITY_BITWISE_XOR_UPDATE_P(e)
#define ENTITY_MINUS_UPDATE_P(e)
#define ENTITY_LEFT_SHIFT_UPDATE_P(e)
#define ENTITY_ASSERT_FAIL_SYSTEM_P(e)
transformer any_basic_update_to_transformer(entity op, list args, list ef, transformer pre)
precondition
transformer any_assign_to_transformer(list args, list ef, transformer pre)
precondition
transformer any_update_to_transformer(entity op, list args, list ef, transformer pre)
precondition
transformer c_return_to_transformer(entity e __attribute__((__unused__)), list pc, list ef, transformer pre)
FI: This transformer carry the information about the value returned, but not the fact that the next s...
transformer conditional_to_transformer(expression cond, expression te, expression fe, transformer pre, list ef)
FI: not too smart to start with the special case with no value returned, just side-effects....
Definition: expression.c:5488

References any_assign_to_transformer(), any_basic_update_to_transformer(), any_update_to_transformer(), c_return_to_transformer(), CAR, CDR, condition_to_transformer(), conditional_to_transformer(), effects_to_transformer(), ENTITY_ABORT_SYSTEM_P, ENTITY_ASSERT_FAIL_SYSTEM_P, ENTITY_ASSERT_SYSTEM_P, ENTITY_ASSIGN_P, ENTITY_BITWISE_AND_UPDATE_P, ENTITY_BITWISE_OR_UPDATE_P, ENTITY_BITWISE_XOR_UPDATE_P, ENTITY_C_RETURN_P, ENTITY_COMMA_P, ENTITY_CONDITIONAL_P, ENTITY_DIVIDE_UPDATE_P, ENTITY_EXIT_SYSTEM_P, ENTITY_LEFT_SHIFT_UPDATE_P, ENTITY_MINUS_UPDATE_P, ENTITY_MODULO_UPDATE_P, ENTITY_MULTIPLY_UPDATE_P, ENTITY_PLUS_UPDATE_P, ENTITY_POST_DECREMENT_P, ENTITY_POST_INCREMENT_P, ENTITY_PRE_DECREMENT_P, ENTITY_PRE_INCREMENT_P, ENTITY_RAND_P, ENTITY_RIGHT_SHIFT_UPDATE_P, ENTITY_STOP_P, EXPRESSION, expressions_to_transformer(), pips_debug, semantics_user_warning, transformer_empty(), transformer_identity(), and transformer_undefined.

Referenced by call_to_postcondition(), and call_to_transformer().

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

◆ intrinsic_to_transformer_list()

list intrinsic_to_transformer_list ( entity  e,
list  pc,
transformer  pre,
list  ef 
)

because of the conditional and the comma C intrinsics at least

effects of intrinsic call

FI: this may happen, for instance with the macro definition of assert() or because the programmer writes "i>1? (i = 2): (i = 3);" instead of "i = i>1? 2 : 3;"

FI: the condition should be evaluated and considered true on exit, but this is sometimes captured by a macro definition and the code below is then useless

Parameters
pcc
prere
eff

Definition at line 480 of file ri_to_transformer_lists.c.

484 {
485  list tl = NIL;
487 
488  pips_internal_error("Not implemented yet.");
489 
490  pips_debug(8, "begin\n");
491 
492  if(ENTITY_ASSIGN_P(e)) {
493  tf = any_assign_to_transformer(pc, ef, pre);
494  }
500  //tf = update_addition_operation_to_transformer(pc, ef, pre);
501  tf = any_update_to_transformer(e, pc, ef, pre);
502  }
505  tf = any_basic_update_to_transformer(e, pc, ef, pre);
506  }
507  else if(ENTITY_C_RETURN_P(e)) {
508  tf = c_return_to_transformer(e, pc, ef, pre);
509  }
512  tf = transformer_empty();
513  else if(ENTITY_COMMA_P(e)) {
514  tf = expressions_to_transformer(pc, pre);
515  }
516  else if(ENTITY_CONDITIONAL_P(e)) {
517  /* FI: this may happen, for instance with the macro definition of
518  assert() or because the programmer writes "i>1? (i = 2): (i =
519  3);" instead of "i = i>1? 2 : 3;" */
520  expression cond = EXPRESSION(CAR(pc));
521  expression e1 = EXPRESSION(CAR(CDR(pc)));
522  expression e2 = EXPRESSION(CAR(CDR(CDR(pc))));
523  tf = conditional_to_transformer(cond, e1, e2, pre, ef);
524  }
525  else if(ENTITY_ASSERT_SYSTEM_P(e)) {
526  /* FI: the condition should be evaluated and considered true on
527  exit, but this is sometimes captured by a macro definition and the code
528  below is then useless */
529  expression cond = EXPRESSION(CAR(pc));
530  tf = condition_to_transformer(cond, pre, true);
531  }
532  else
533  tf = effects_to_transformer(ef);
534 
535  pips_debug(8, "end\n");
536 
537  tl=CONS(TRANSFORMER,tf,NIL);
538  return tl;
539 }

References any_assign_to_transformer(), any_basic_update_to_transformer(), any_update_to_transformer(), c_return_to_transformer(), CAR, CDR, condition_to_transformer(), conditional_to_transformer(), CONS, effects_to_transformer(), ENTITY_ABORT_SYSTEM_P, ENTITY_ASSERT_FAIL_SYSTEM_P, ENTITY_ASSERT_SYSTEM_P, ENTITY_ASSIGN_P, ENTITY_BITWISE_AND_UPDATE_P, ENTITY_BITWISE_OR_UPDATE_P, ENTITY_BITWISE_XOR_UPDATE_P, ENTITY_C_RETURN_P, ENTITY_COMMA_P, ENTITY_CONDITIONAL_P, ENTITY_DIVIDE_UPDATE_P, ENTITY_EXIT_SYSTEM_P, ENTITY_LEFT_SHIFT_UPDATE_P, ENTITY_MINUS_UPDATE_P, ENTITY_MODULO_UPDATE_P, ENTITY_MULTIPLY_UPDATE_P, ENTITY_PLUS_UPDATE_P, ENTITY_POST_DECREMENT_P, ENTITY_POST_INCREMENT_P, ENTITY_PRE_DECREMENT_P, ENTITY_PRE_INCREMENT_P, ENTITY_RIGHT_SHIFT_UPDATE_P, ENTITY_STOP_P, EXPRESSION, expressions_to_transformer(), NIL, pips_debug, pips_internal_error, TRANSFORMER, transformer_empty(), and transformer_undefined.

+ Here is the call graph for this function:

◆ lhs_expression_to_transformer()

transformer lhs_expression_to_transformer ( entity  e,
expression  lhs,
transformer  pre 
)

This function deals with e1.e2 and e1->e2, not with simple references such as x or a[i].

This piece of code has mainly been retrieved from any_assign_to_transformer().

FI: I am not sure how to factorize it out because entity e corresponds to some memory location and is modified in an assignement environment. Here, e is likely to be a temporary value. It is not updated. It should not appear among the transformer arguments

Parameters
lhshs
prere

Definition at line 6262 of file expression.c.

6263 {
6264  syntax slhs = expression_syntax(lhs);
6266 
6267  if(syntax_call_p(slhs)) {
6270  int n = (int) gen_length(l);
6271  // FI: I wonder what happens with side effects in the rhs and
6272  // with pointer dereferencing in the rhs
6273  FOREACH(CELL, cp, l) {
6275 
6276  // example of case which is normally filter *p when p formal
6277  // parameter, or dynamic allocation of p
6278  if(semantics_usable_points_to_reference_p(rlhs, lhs, n)) {
6279  if (analyzed_reference_p(rlhs)) {
6281 
6282  if(!entity_undefined_p(ecp)) { // the location is analyzed
6283  // The preconditions may make the convex hull useful when
6284  // different locations have known values or are
6285  // constrained
6286  transformer rt = copy_transformer(pre);
6287  rt = transformer_add_equality(rt, e, ecp);
6288 
6289  // NL : a better way to do this may exit but I don't know it
6290  if (transformer_undefined_p(tf))
6291  tf = rt;
6292  else {
6293  tf = transformer_convex_hull(tf, rt);
6294  free_transformer(rt);
6295  }
6296  }
6297  }
6298  }
6299  }
6300  }
6301  }
6302  else {
6303  // It might be more useful to process the reference for side effects
6304  pips_internal_error("Improper argument.\n");
6305  }
6306  return tf;
6307 }

References analyzed_reference_p(), CELL, cell_any_reference(), constant_memory_access_path_to_location_entity(), constant_path_analyzed_p(), copy_transformer(), cp, entity_undefined_p, expression_syntax, FOREACH, free_transformer(), gen_length(), int, pips_internal_error, pt_to_list_undefined_p(), semantics_expression_to_points_to_sources(), semantics_usable_points_to_reference_p(), syntax_call_p, transformer_add_equality(), transformer_convex_hull(), transformer_undefined, and transformer_undefined_p.

Referenced by integer_call_expression_to_transformer().

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

◆ load_body_effects()

list load_body_effects ( entity  e)

Definition at line 1508 of file dbm_interface.c.

1509 {
1510  string module_name = (string) module_local_name(e);
1511 
1512  pips_assert("load_summary_effects", entity_module_p(e));
1513 
1514  statement b = (statement) db_get_memory_resource(DBR_CODE, module_name, true);
1516  db_get_memory_resource(DBR_CUMULATED_EFFECTS, module_name, true);
1517  effects be = (effects) (intptr_t)HASH_GET(p, p, statement_effects_hash_table(se), (void *) b);
1518  list bel = effects_effects(be);
1519 
1520  pips_assert("bel is defined", bel != list_undefined);
1521 
1522  return bel;
1523 }
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
#define statement_effects_hash_table(x)
Definition: effects.h:1054
struct _newgen_struct_effects_ * effects
Definition: effects.h:138
struct _newgen_struct_statement_effects_ * statement_effects
Definition: effects.h:210
#define HASH_GET(start, image, h, k)
Definition: newgen_map.h:30
char * string
STRING.
Definition: newgen_types.h:39

References db_get_memory_resource(), effects_effects, entity_module_p(), HASH_GET, intptr_t, list_undefined, module_local_name(), module_name(), pips_assert, and statement_effects_hash_table.

Referenced by user_call_to_points_to_interprocedural().

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

◆ load_completed_statement_transformer()

transformer load_completed_statement_transformer ( statement  s)

three mappings used throughout semantics analysis:

  • transformer_map is computed in a first phase
  • precondition_map is computed in a second phase
  • cumulated_effects is used and assumed computed before (defined in effects.c)
  • proper_effects might be useless... only DO loop analysis could use it (idem) declaration of the previously described mappings with their access functions :

(DEFINE_CURRENT_MAPPING is a macro defined in ~pips/Newgen/mapping.h)

BA, August 26, 1993 Returns the entry to exit transformer associated to a statement, since all statements in PIPS internal representation have a unique exit.

The transformers associated to loops are the transformers linking the loop precondition to the loop body precondition. When dealing with sequences or test or... the transformer linking the loop precondition to its postcondition, i.e. the precondition hodling at the loop exit, is needed.

To complete the statement transformer, a precondition is required. Different preconditions can be used:

  • transformer_identity(): provides no information
  • load_statement_precondition(): provides as much information as possible
  • the transformer domain: provides information available when the transformers are computed, i.e. preconditions do not have to be available; this is unsafe as the loop entrance transition domain may be a subset of the precocndition, unless the loop is always entered.

Unlike load_statement_transformer(), this function allocates a new transformer. See comments associated to:

generic_complete_statement_transformer()

Definition at line 131 of file dbm_interface.c.

132 {
134 
135  // Unsafe if s is a loop, unless you check that the loop is always
136  //entered
137  //transformer pre = transformer_to_domain(t);
139 
141 
142  //pips_assert("te is defined", !transformer_undefined_p(te));
143 
144  free_transformer(pre);
145 
146  return te;
147 }

References complete_statement_transformer(), free_transformer(), load_statement_transformer(), and transformer_identity().

Referenced by set_methods_for_convex_effects(), and set_methods_for_convex_rw_pointer_effects().

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

◆ load_cycle_fix_point()

transformer load_cycle_fix_point ( control  c,
hash_table  fix_point_map 
)
Parameters
fix_point_mapix_point_map

Definition at line 544 of file unstructured.c.

545 {
547 
548  if((fptf = (transformer) hash_get(fix_point_map, (void *) c))
550  pips_assert("c is not a cycle head", false);
551 
552  return fptf;
553 }
void * hash_get(const hash_table htp, const void *key)
this function retrieves in the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:449
#define HASH_UNDEFINED_VALUE
value returned by hash_get() when the key is not found; could also be called HASH_KEY_NOT_FOUND,...
Definition: newgen_hash.h:56

References hash_get(), HASH_UNDEFINED_VALUE, pips_assert, and transformer_undefined.

+ Here is the call graph for this function:

◆ load_cycle_temporary_precondition()

transformer load_cycle_temporary_precondition ( control  ,
control_mapping  ,
hash_table  ,
hash_table   
)

◆ load_module_intraprocedural_effects()

list load_module_intraprocedural_effects ( entity  e)

memoization could be used to improve efficiency

Definition at line 1526 of file dbm_interface.c.

1527 {
1528  /* memoization could be used to improve efficiency */
1529  list t;
1530  statement s;
1531 
1532  pips_assert("is a module", entity_module_p(e));
1533  pips_assert("is the current module", e == get_current_module_entity());
1535  pips_assert("some statement", s!=statement_undefined);
1536 
1538 
1539  pips_assert("some list", t != list_undefined);
1540 
1541  return t;
1542 }
list load_cumulated_rw_effects_list(statement)

References entity_module_p(), get_current_module_entity(), get_current_module_statement(), list_undefined, load_cumulated_rw_effects_list(), pips_assert, and statement_undefined.

Referenced by allocate_module_value_mappings(), data_to_precondition(), and module_to_value_mappings().

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

◆ load_statement_postcondition()

transformer load_statement_postcondition ( statement  )

Referenced by statement_context().

+ Here is the caller graph for this function:

◆ load_statement_precondition()

◆ load_statement_semantic()

transformer load_statement_semantic ( statement  )

◆ load_statement_temporary_precondition()

transformer load_statement_temporary_precondition ( statement  s,
statement_mapping  statement_temporary_precondition_map 
)
Parameters
statement_temporary_precondition_maptatement_temporary_precondition_map

Definition at line 1069 of file unstructured.c.

1071 {
1072  transformer t_pre = (transformer) hash_get(statement_temporary_precondition_map, (void *) s);
1073 
1074  pips_assert("The cycle precondition is available",
1075  t_pre != (transformer) HASH_UNDEFINED_VALUE);
1076 
1077  return t_pre;
1078 }

References hash_get(), HASH_UNDEFINED_VALUE, and pips_assert.

Referenced by cycle_to_flow_sensitive_preconditions().

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

◆ load_statement_total_precondition()

transformer load_statement_total_precondition ( statement  )

Referenced by statement_to_total_precondition().

+ Here is the caller graph for this function:

◆ load_statement_transformer()

◆ load_summary_effects()

list load_summary_effects ( entity  e)

FI->FI, FI->BC: these two functions should be moved into effects-util or effects-simple.

memorization could be used to improve efficiency

Definition at line 1492 of file dbm_interface.c.

1493 {
1494  /* memorization could be used to improve efficiency */
1495  list t;
1496 
1497  pips_assert("load_summary_effects", entity_module_p(e));
1498 
1499  t = effects_to_list( (effects)
1500  db_get_memory_resource(DBR_SUMMARY_EFFECTS, module_local_name(e),
1501  true));
1502 
1503  pips_assert("t is defined", t != list_undefined);
1504 
1505  return t;
1506 }

References db_get_memory_resource(), effects_to_list(), entity_module_p(), list_undefined, module_local_name(), and pips_assert.

Referenced by add_module_call_site_precondition(), call_site_to_module_precondition_text(), compute_summary_reductions(), module_to_value_mappings(), pure_function_p(), update_precondition_with_call_site_preconditions(), and user_call_to_points_to_fast_interprocedural().

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

◆ load_summary_precondition()

transformer load_summary_precondition ( entity  e)

summary_preconditions are expressed in any possible frame, in fact the frame of the last procedure that used/produced it

memoization could be used to improve efficiency

Not done earlier, because the value mappings were not available. On the other hand, htis assumes that the value mappings have been initialized before a call to load_summary_precondition(0 is performed.

Definition at line 1431 of file dbm_interface.c.

1432 {
1433  /* memoization could be used to improve efficiency */
1434  transformer t;
1435 
1436  pips_assert("e is a module", entity_module_p(e));
1437 
1438  pips_debug(8, "begin\n for %s\n",
1439  module_local_name(e));
1440 
1441  t = (transformer)
1442  db_get_memory_resource(DBR_SUMMARY_PRECONDITION, module_local_name(e),
1443  true);
1444  /* Not done earlier, because the value mappings were not available. On
1445  the other hand, htis assumes that the value mappings have been
1446  initialized before a call to load_summary_precondition(0 is
1447  performed.*/
1449 
1450  pips_assert("the summary precondition t is defined", t != transformer_undefined);
1451 
1452  ifdebug(8) {
1453  pips_debug(8, " precondition for %s:\n",
1454  module_local_name(e));
1455  dump_transformer(t);
1456  pips_debug(8, " end\n");
1457  }
1458 
1459  return t;
1460 }

References db_get_memory_resource(), dump_transformer, entity_module_p(), ifdebug, module_local_name(), pips_assert, pips_debug, transformer_undefined, and translate_global_values().

Referenced by generic_module_name_to_transformers(), and module_name_to_preconditions().

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

◆ load_summary_total_postcondition()

transformer load_summary_total_postcondition ( entity  e)

summary_preconditions are expressed in any possible frame, in fact the frame of the last procedure that used/produced it

Definition at line 1465 of file dbm_interface.c.

1466 {
1468 
1469  pips_assert("e is a module", entity_module_p(e));
1470 
1471  pips_debug(8, "begin\n for %s\n",
1472  module_local_name(e));
1473 
1474  t_post = (transformer)
1475  db_get_memory_resource(DBR_SUMMARY_TOTAL_POSTCONDITION, module_local_name(e),
1476  true);
1477 
1478  pips_assert("t is defined", t_post != transformer_undefined);
1479 
1480  ifdebug(8) {
1481  pips_debug(8, " total postcondition for %s:\n",
1482  module_local_name(e));
1483  dump_transformer(t_post);
1484  pips_debug(8, " end\n");
1485  }
1486 
1487  return t_post;
1488 }

References db_get_memory_resource(), dump_transformer, entity_module_p(), ifdebug, module_local_name(), pips_assert, pips_debug, and transformer_undefined.

Referenced by module_name_to_total_preconditions().

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

◆ load_summary_transformer()

transformer load_summary_transformer ( entity  e)

FI: I had to add a guard db_resource_p() on Nov. 14, 1995. I do not understand why the problem never occured before, although it should each time the intra-procedural option is selected.

This may partially be explained because summary transformers are implicitly computed with transformers instead of using an explicit call to summary_transformer (I guess I'm going to change that).

I think it would be better not to call load_summary_transformer() at all when no interprocedural options are selected. I should change that too.

memoization could be used to improve efficiency

db_get_memory_resource never returns database_undefined or resource_undefined

Let's be careful with people using an intraprocedural analysis of the transformers and requesting an interprocedural analysis of the preconditions...

Definition at line 1327 of file dbm_interface.c.

1328 {
1329  /* FI: I had to add a guard db_resource_p() on Nov. 14, 1995.
1330  * I do not understand why the problem never occured before,
1331  * although it should each time the intra-procedural option
1332  * is selected.
1333  *
1334  * This may partially be explained because summary transformers
1335  * are implicitly computed with transformers instead of using
1336  * an explicit call to summary_transformer (I guess I'm going
1337  * to change that).
1338  *
1339  * I think it would be better not to call load_summary_transformer()
1340  * at all when no interprocedural options are selected. I should
1341  * change that too.
1342  */
1343 
1344  /* memoization could be used to improve efficiency */
1346 
1347  pips_assert("e is a module", entity_module_p(e));
1348 
1349  if(db_resource_p(DBR_SUMMARY_TRANSFORMER, module_local_name(e))) {
1350  t = (transformer)
1351  db_get_memory_resource(DBR_SUMMARY_TRANSFORMER,
1352  entity_local_name(e),
1353  true);
1354 
1355  /* db_get_memory_resource never returns database_undefined or
1356  resource_undefined */
1357  pips_assert("load_summary_transformer", t != transformer_undefined);
1358  }
1359  else {
1361  }
1362 
1363  /* Let's be careful with people using an intraprocedural analysis
1364  of the transformers and requesting an interprocedural analysis
1365  of the preconditions... */
1366  if(transformer_undefined_p(t)) {
1367  if(db_resource_p(DBR_SUMMARY_EFFECTS, module_local_name(e))) {
1369  db_get_memory_resource(DBR_SUMMARY_EFFECTS,
1370  entity_local_name(e),
1371  true));
1372  t = effects_to_transformer(el);
1373  }
1374  }
1375 
1376  return t;
1377 }

References db_get_memory_resource(), db_resource_p(), effects_effects, effects_to_transformer(), entity_local_name(), entity_module_p(), module_local_name(), pips_assert, transformer_undefined, and transformer_undefined_p.

Referenced by c_user_call_to_transformer(), and fortran_user_call_to_transformer().

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

◆ logical_expression_to_transformer()

transformer logical_expression_to_transformer ( entity  v,
expression  rhs,
transformer  pre,
bool  is_internal 
)

Could be used to compute preconditions too.

v is assumed to be a new value or a temporary value.

Is likely to be handled as a nullary intrinsics

Parameters
rhshs
prere
is_internals_internal

Definition at line 3938 of file expression.c.

3942 {
3944  syntax srhs = expression_syntax(rhs);
3945 
3946  switch(syntax_tag(srhs)) {
3947  case is_syntax_call: {
3948  call c = syntax_call(srhs);
3949  entity f = call_function(c);
3950  if(intrinsic_entity_p(f))
3951  tf = logical_intrinsic_to_transformer(v, c, pre, is_internal);
3952  else if(call_constant_p(c)) {
3953  entity cf = call_function(c);
3954  int i;
3955  if(logical_constant_p(cf)) {
3956  /* Is likely to be handled as a nullary intrinsics */
3957  tf = logical_intrinsic_to_transformer(v, c, pre, is_internal);
3958  }
3959  else if(integer_constant_p(cf, &i)) {
3960  if(i!=0)
3961  i = 1;
3962  tf = transformer_identity();
3964  }
3965  else
3966  pips_internal_error("Unexpected case.\n");
3967  }
3968  else {
3969  // call to a C or Fortran bool function
3970  //list ef = expression_to_proper_effects(rhs);
3971  tf = user_function_call_to_transformer(v, rhs, pre);
3972  }
3973  break;
3974  }
3975  case is_syntax_reference: {
3976  // FI: information in precondition pre is lost here
3978  is_internal);
3980  // FI: let us assume that pre is a range, not a transformer
3981  tf = transformer_intersection(rtf, pre);
3982  }
3983  break;
3984  }
3985  case is_syntax_range:
3986  pips_internal_error("Unexpected tag %d", syntax_tag(srhs));
3987  break;
3988  default:
3989  pips_internal_error("Illegal tag %d", syntax_tag(srhs));
3990  }
3991  return tf;
3992 }
bool integer_constant_p(entity ent, int *int_p)
Returns the double value associated to a PIPS constant.
Definition: constant.c:542
bool logical_constant_p(entity ent)
Definition: constant.c:463
bool intrinsic_entity_p(entity e)
Definition: entity.c:1272
bool call_constant_p(call c)
bool call_constant_p(call c): Returns true if "c" is a call to a constant, that is,...
Definition: expression.c:1965
static transformer logical_reference_to_transformer(entity v, entity r, bool is_internal)
v is assumed to be a temporary value and r a logical program variable
Definition: expression.c:3894
transformer logical_intrinsic_to_transformer(entity v, call c, transformer pre, bool is_internal)
Definition: expression.c:3911

References call_constant_p(), call_function, expression_syntax, f(), integer_constant_p(), intrinsic_entity_p(), is_syntax_call, is_syntax_range, is_syntax_reference, logical_constant_p(), logical_intrinsic_to_transformer(), logical_reference_to_transformer(), pips_internal_error, reference_variable, syntax_call, syntax_reference, syntax_tag, transformer_add_equality_with_integer_constant(), transformer_identity(), transformer_intersection(), transformer_undefined, transformer_undefined_p, and user_function_call_to_transformer().

Referenced by any_expression_to_transformer(), logical_binary_operation_to_transformer(), and logical_unary_operation_to_transformer().

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

◆ logical_intrinsic_to_transformer()

transformer logical_intrinsic_to_transformer ( entity  v,
call  c,
transformer  pre,
bool  is_internal 
)
Parameters
prere
is_internals_internal

Definition at line 3911 of file expression.c.

3915 {
3917 
3918  switch(gen_length(call_arguments(c))) {
3919  case 0:
3921  break;
3922  case 1:
3923  tf = logical_unary_operation_to_transformer(v, c, pre, is_internal);
3924  break;
3925  case 2:
3926  tf = logical_binary_function_to_transformer(v, c, pre, is_internal);
3927  break;
3928  default:
3929  pips_internal_error("Too many logical arguments, %d, for operator %s",
3932  }
3933  return tf;
3934 }
static transformer logical_binary_function_to_transformer(entity v, call c, transformer pre, bool is_internal)
Definition: expression.c:3769
static transformer logical_unary_operation_to_transformer(entity v, call c, transformer pre, bool is_internal)
Definition: expression.c:3607
static transformer logical_constant_to_transformer(entity v, entity f)
Definition: expression.c:3583

References call_arguments, call_function, entity_name, gen_length(), logical_binary_function_to_transformer(), logical_constant_to_transformer(), logical_unary_operation_to_transformer(), pips_internal_error, and transformer_undefined.

Referenced by logical_expression_to_transformer().

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

◆ logical_not_to_transformer()

transformer logical_not_to_transformer ( entity  v,
list  args,
transformer  pre 
)

returns the transformer associated to a C logical not, !, applied to an integer argument, when meaningful, and transformer_undefined otherwise.

Effects must be used at a higher level to fall back on a legal transformer.

Parameters
vis the value associated to the expression
argsis assumed to have only one expression element of type int or enum negated by !
preis the current precondition
Parameters
argsrgs
prere

Definition at line 5571 of file expression.c.

5574 {
5575  expression le = EXPRESSION(CAR(args));
5576  //basic be = basic_of_expression(le);
5578 
5579  //if(basic_int_p(be)) {
5581  tf = safe_any_expression_to_transformer(tmp_v, le, pre, true);
5582  transformer tfr = transformer_range(tf);
5583  intptr_t lb, ub;
5584 
5585  if(precondition_minmax_of_value(tmp_v, tfr, &lb, &ub)) {
5586  if(lb==ub && lb==0)
5588  else if(lb>0 || ub<0)
5590  else {
5593  }
5594  }
5595  else {
5598  }
5599  free_transformer(tfr);
5600  // }
5601 
5602  //free_basic(be);
5603 
5604  return tf;
5605 }
transformer transformer_add_inequality_with_integer_constraint(transformer tf, entity v, long long int cst, bool less_than_p)
Add the inequality v <= cst or v >= cst.
Definition: basic.c:477

References CAR, EXPRESSION, free_transformer(), intptr_t, make_local_temporary_integer_value_entity(), precondition_minmax_of_value(), safe_any_expression_to_transformer(), transformer_add_equality_with_integer_constant(), transformer_add_inequality_with_integer_constraint(), transformer_range(), and transformer_undefined.

Referenced by integer_call_expression_to_transformer().

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

◆ loop_bound_evaluation_to_transformer()

transformer loop_bound_evaluation_to_transformer ( loop  l,
transformer  pre 
)

Side effects in loop bounds and increment are taken into account.

The conditions on the loop index are given by the range of this transformer.

Parameters
prere

Definition at line 1203 of file loop.c.

1204 {
1206  entity i = loop_index(l);
1207 
1208  //pips_assert("No temporary variables are allocated",
1209  // number_of_temporary_values()==0);
1210 
1211  if(entity_has_values_p(i)) {
1212  expression lbe = range_lower(loop_range(l));
1215  transformer lbt = any_expression_to_transformer(lbv, lbe, pre, true);
1216 
1217  transformer preub = transformer_safe_apply(iit, pre);
1218  expression ube = range_upper(loop_range(l));
1220  transformer ubt = any_expression_to_transformer(ubv, ube, preub, true);
1221 
1222  transformer prei = transformer_safe_apply(ubt, preub);
1225  transformer it = any_expression_to_transformer(iv, ie, prei, true);
1226  transformer pre_inc = transformer_safe_intersection(prei, it);
1227  entity ni = entity_to_new_value(i);
1228  int inc_lb = 0;
1229  int inc_ub = 0;
1230  expression eiv = entity_to_expression(iv);
1231 
1232  expression_and_precondition_to_integer_interval(eiv, pre_inc, &inc_lb, &inc_ub);
1233  free_expression(eiv);
1234 
1235  if(inc_lb>0 || inc_ub<0) {
1236  Pvecteur lb_ineq = vect_new((Variable) ni, VALUE_MONE);
1237  Pvecteur ub_ineq = vect_new((Variable) ni, VALUE_ONE);
1238 
1239  vect_add_elem(&lb_ineq, (Variable) lbv, VALUE_ONE);
1240  vect_add_elem(&ub_ineq, (Variable) ubv, VALUE_MONE);
1241 
1242  if(inc_ub<0) {
1243  lb_ineq = vect_multiply(lb_ineq, VALUE_MONE);
1244  ub_ineq = vect_multiply(ub_ineq, VALUE_MONE);
1245  }
1246  r = transformer_safe_apply(it, prei);
1249  r = transformer_inequality_add(r, lb_ineq);
1250  r = transformer_inequality_add(r, ub_ineq);
1252  }
1254  }
1255  return r;
1256 }
Pvecteur vect_multiply(Pvecteur v, Value x)
Pvecteur vect_multiply(Pvecteur v, Value x): multiplication du vecteur v par le scalaire x,...
Definition: scalaires.c:123
transformer loop_initialization_to_transformer(loop l, transformer pre)
Note: It used to be implemented by computing the effect list of the lower bound expression and and ne...
Definition: loop.c:1266
transformer transformer_safe_intersection(transformer t1, transformer t2)
Allocate a new transformer.
Definition: transformer.c:639

References any_expression_to_transformer(), entity_has_values_p(), entity_to_expression(), entity_to_new_value(), entity_type, expression_and_precondition_to_integer_interval(), free_expression(), loop_index, loop_initialization_to_transformer(), loop_range, make_local_temporary_value_entity(), range_increment, range_lower, range_upper, reset_temporary_value_counter(), transformer_inequality_add(), transformer_safe_apply(), transformer_safe_image_intersection(), transformer_safe_intersection(), transformer_temporary_value_projection(), transformer_undefined, VALUE_MONE, VALUE_ONE, vect_add_elem(), vect_multiply(), and vect_new().

Referenced by add_good_loop_conditions().

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

◆ loop_initialization_to_transformer()

transformer loop_initialization_to_transformer ( loop  l,
transformer  pre 
)

Note: It used to be implemented by computing the effect list of the lower bound expression and and new allocated effect for the loop index definition.

It turns out to be very heavy, because cells must be of kind preference to be usable by several functions because macro effect_reference() expects so without testing it.

However, it is also difficult to add a variable to the transformer t_init because of aliasing. So let's stick to the initial implementation.

over-approximation of effects

free_effects() is not enough, because it is a persistant reference

Parameters
prere

Definition at line 1266 of file loop.c.

1267 {
1273  list l_init_e = CONS(EFFECT, init_e, NIL);
1274  //list l_expr_e = expression_to_proper_effects(range_lower(loop_range(l)));
1275  expression lbe = range_lower(loop_range(l));
1277  list el = list_undefined;
1278 
1279  transformer r_pre = transformer_safe_range(pre);
1281 
1282  ifdebug(9) {
1283  print_effects(l_init_e);
1284  print_effects(l_expr_e);
1285  }
1286 
1287  el = gen_nconc(l_init_e, l_expr_e);
1288 
1289  ifdebug(9) {
1290  print_effects(el);
1291  }
1292 
1293  t_init =
1295  range_lower(loop_range(l)),
1296  el, /* over-approximation of effects */
1297  r_pre);
1298 
1299  ifdebug(9) {
1300  print_effects(el);
1301  }
1302 
1303  gen_free_list(el);
1304  /* free_effects() is not enough, because it is a persistant reference */
1306  free_effect(init_e);
1307  free_transformer(r_pre);
1308 
1309  return t_init;
1310 }
void free_effect(effect p)
Definition: effects.c:451
cell make_cell(enum cell_utype tag, void *val)
Definition: effects.c:290
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
void free_reference(reference p)
Definition: ri.c:2050
preference make_preference(reference a1)
Definition: ri.c:1862
action make_action_write_memory(void)
To ease the extension of action with action_kind.
Definition: effects.c:1011
@ is_cell_preference
Definition: effects.h:446
#define effect_cell(x)
Definition: effects.h:640
transformer transformer_safe_range(transformer tf)
Definition: transformer.c:743

References any_scalar_assign_to_transformer(), cell_preference, CONS, EFFECT, effect_cell, expression_to_proper_constant_path_effects(), free_effect(), free_reference(), free_transformer(), gen_free_list(), gen_nconc(), ifdebug, is_cell_preference, list_undefined, loop_index, loop_range, make_action_write_memory(), make_approximation_exact(), make_cell(), make_descriptor_none(), make_effect(), make_preference(), make_reference(), NIL, preference_reference, print_effects, range_lower, transformer_safe_range(), and transformer_undefined.

Referenced by loop_bound_evaluation_to_transformer(), loop_to_postcondition(), loop_to_total_precondition(), and loop_to_transformer().

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

◆ loop_to_continue_transformer()

transformer loop_to_continue_transformer ( loop  l,
transformer  pre 
)

FI: the function transformer_add_loop_index_incrementation should be rewritten to exploit preconditions better.

Parameters
prere

Definition at line 1501 of file loop.c.

1502 {
1504  /* FI: the function transformer_add_loop_index_incrementation should
1505  be rewritten to exploit preconditions better. */
1508  t = transformer_combine(t, et);
1509  free_transformer(et);
1510  return t;
1511 }
transformer loop_to_enter_transformer(loop l, transformer pre)
Transformer expressiong the conditions between the index and the loop bounds according to the sign of...
Definition: loop.c:1442
transformer transformer_add_loop_index_incrementation(transformer tf, loop l, transformer pre)
Definition: loop.c:1136

References free_transformer(), loop_to_enter_transformer(), transformer_add_loop_index_incrementation(), transformer_combine(), and transformer_identity().

Referenced by new_loop_to_transformer().

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

◆ loop_to_enter_transformer()

transformer loop_to_enter_transformer ( loop  l,
transformer  pre 
)

Transformer expressiong the conditions between the index and the loop bounds according to the sign of the increment.

A zero increment is not legal because the Fortran standard imposes a division by the increment.

Only the loop bopy statement number is available...

Assumption: no side effect in loop bound expressions

The increment is strictly positive

The increment is strictly negative

The sign of the increment is unknown, no information is available

No information is available for loop indices that are not integer

This could be improved, but floating point indices should never be used.

Parameters
prere

Definition at line 1442 of file loop.c.

1443 {
1444  entity i = loop_index(l);
1445  range r = loop_range(l);
1446  expression low = range_lower(r);
1447  expression up = range_upper(r);
1448  expression inc = range_increment(r);
1449  int il, iu;
1451 
1453 
1455 
1456  if(il==iu && il==0) {
1457  /* A zero increment is not legal because the Fortran standard
1458  imposes a division by the increment. */
1459  /* Only the loop bopy statement number is available... */
1460  pips_user_error("Null increment for DO loop detected.\n");
1461  }
1462  else if(il>0||iu<0) {
1463  /* Assumption: no side effect in loop bound expressions */
1465  transformer lt = safe_integer_expression_to_transformer(lv, low, pre, true);
1467  transformer ut = safe_integer_expression_to_transformer(uv, up, pre, true);
1468 
1469  if(il>0) {
1470  /* The increment is strictly positive */
1471  t = transformer_add_inequality_with_linear_term(t, lv, i, 1, true);
1472  t = transformer_add_inequality_with_linear_term(t, i, uv, 1, true);
1473  }
1474  else if(iu<0) {
1475  /* The increment is strictly negative */
1476  t = transformer_add_inequality_with_linear_term(t, uv, i, 1, true);
1477  t = transformer_add_inequality_with_linear_term(t, i, lv, 1, true);
1478  }
1479  t = transformer_intersection(t, lt);
1480  t = transformer_intersection(t, ut);
1482  //t = transformer_normalize(t, 0);
1483  t = transformer_normalize(t, 1);
1484  free_transformers(lt, ut, NULL);
1485  }
1486  else {
1487  /* The sign of the increment is unknown, no information is available */
1488  ;
1489  }
1490  }
1491  else {
1492  /* No information is available for loop indices that are not integer */
1493  /* This could be improved, but floating point indices should never
1494  be used. */
1495  ;
1496  }
1497 
1498  return t;
1499 }
transformer transformer_add_inequality_with_linear_term(transformer tf, entity v, entity x, int a, bool less_than_p)
Add the inequality v <= a x or v >= a x.
Definition: basic.c:530
void free_transformers(transformer t,...)
Definition: basic.c:73
bool scalar_integer_type_p(type)
Definition: type.c:3276
transformer safe_integer_expression_to_transformer(entity v, expression expr, transformer pre, bool is_internal)
Always return a defined transformer, using effects in case a more precise analysis fails.
Definition: expression.c:3552
void integer_expression_and_precondition_to_integer_interval(expression, transformer, int *, int *)
Could be used for bool expressions too? Extended to any kind of expression?
Definition: utils.c:386

References entity_type, free_transformers(), integer_expression_and_precondition_to_integer_interval(), loop_index, loop_range, make_local_temporary_value_entity(), pips_user_error, range_increment, range_lower, range_upper, safe_integer_expression_to_transformer(), scalar_integer_type_p(), transformer_add_inequality_with_linear_term(), transformer_identity(), transformer_intersection(), transformer_normalize(), and transformer_temporary_value_projection().

Referenced by loop_to_continue_transformer(), and new_loop_to_transformer().

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

◆ loop_to_initialization_transformer()

transformer loop_to_initialization_transformer ( loop  l,
transformer  pre 
)

Transformer expression the loop initialization.

Parameters
prere

Definition at line 1430 of file loop.c.

1431 {
1432  entity i = loop_index(l);
1433  range r = loop_range(l);
1434  expression low = range_lower(r);
1436  return t;
1437 }

References assigned_expression_to_transformer(), loop_index, loop_range, and range_lower.

Referenced by new_loop_to_transformer().

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

◆ loop_to_postcondition()

transformer loop_to_postcondition ( transformer  pre,
loop  l,
transformer  tf 
)

pips_internal_error("Equality option not implemented");

the standard version should be OK for SEMANTICS_EQUALITY_INVARIANTS...

basic cheap version: add information on loop index in pre and propagate preb downwards in the loop body; compute the loop postcondition independently using the loop transformer

preb = precondition for loop body; includes a lousy fix-point

Get rid of information related to variables modified in iterations of the loop body (including loop indices).

Apparently, the loop index incrementation is not in tf... according to a test with DO I = I, N although it should be... according to the caller of this function and the display of loop transformers!

Triolet's good loop algorithm

It might be useful to normalize preb and to detect unfeasibility. I choose not to do it because:

  • it almost never happens in user code
  • it's time consuming
  • when it happens in automatically generated code, dead code elimination is performed.

So basically, I shift the burden from precondition computation to dead code elimination. Dead loop testing must use a strong feasibility test.

If this decision is reversed, dead code elimination can be speeded-up.

Note that add_good_loop_conditions() can test trivial cases automatically generated.

Decision reverted: Francois Irigoin, 4 June 1997

preb can now be used to obtain a refined tf, for instance to show that a variable is monotonically increasing.

FI: this is not correct when an invariant is found; we should add one more incrementation of I (to modify the output of the invariant and express the fact that the loop bound is no more true, at least when the increment is one. 6 July 1993

Note 1: this comments was wrong! See Validation/Semantics/induc1.f Note 2: but the result was wrong anyway because it assumed that at least one iteration always was performed. Note 3: This is fixed by reverting the above decision.

propagate an impossible precondition in the loop body

The loop body precondition is not useful any longer

propagate preconditions in the loop body and compute its postcondition...

... or compute directly the postcondition using the loop body transformer. This second approach is slightly less precise because the transformer cannot use preconditions to avoid some convex approximations.

post = transformer_apply(tf, pre);

The loop body effects should be passed as fourth argument to check that the value of the upper bound expression is not modified when the body is executed. But it is not available and it is not yet used by ad_loop_index_exit_value()!

First version: OK, but could be better!

transformer postloop = transformer_apply(tf, pre);

pre must be copied because sc_convex_hull updates is arguments and may make them inconsistent when the two bases are merged to perform the convex hull in a common vector space

Second version: assume it is empty or non-empty and perform the convex hull of both (should be checked on Validation/Semantics/induc1.f)

propagate preconditions in the loop body

post_al = transformer_apply(tf, pre);

We should add (when possible) the non-entry condition in post_ne! For instance, DO I = 1, N leads to N <= 0

FI: Cannot be freed because it was stored for statement s: transformer_free(preb); did I mean to free pre, which is useless since it was changed into preb?

Parameters
prere
tff

Definition at line 2841 of file loop.c.

2844 {
2846  statement s = loop_body(l);
2847  range r = loop_range(l);
2848 
2849  pips_debug(8,"begin\n");
2850 
2852  pips_internal_error("Halbwachs not implemented");
2853  }
2854  else {
2855  /* pips_internal_error("Equality option not implemented"); */
2856  /* the standard version should be OK for SEMANTICS_EQUALITY_INVARIANTS... */
2857 
2858  /* basic cheap version: add information on loop index in pre
2859  and propagate preb downwards in the loop body; compute the
2860  loop postcondition independently using the loop transformer */
2861  /* preb = precondition for loop body; includes a lousy fix-point */
2862  transformer preb = transformer_dup(pre);
2863 
2864  /* Get rid of information related to variables modified in
2865  * iterations of the loop body (including loop indices).
2866  *
2867  * Apparently, the loop index incrementation is not in tf...
2868  * according to a test with DO I = I, N
2869  * although it should be... according to the caller of this function
2870  * and the display of loop transformers!
2871  */
2872  preb = transformer_combine(preb, tf);
2873 
2874  /* Triolet's good loop algorithm */
2875  preb = add_good_loop_conditions(preb, l);
2876 
2877  /* It might be useful to normalize preb and to detect unfeasibility.
2878  * I choose not to do it because:
2879  * - it almost never happens in user code
2880  * - it's time consuming
2881  * - when it happens in automatically generated code,
2882  * dead code elimination is performed.
2883  *
2884  * So basically, I shift the burden from precondition computation
2885  * to dead code elimination. Dead loop testing must use a strong
2886  * feasibility test.
2887  *
2888  * If this decision is reversed, dead code elimination can be
2889  * speeded-up.
2890  *
2891  * Note that add_good_loop_conditions() can test trivial cases
2892  * automatically generated.
2893  *
2894  * Decision reverted: Francois Irigoin, 4 June 1997
2895  */
2896 
2897  /* preb can now be used to obtain a refined tf, for instance to show that a
2898  variable is monotonically increasing. */
2899  if(get_bool_property("SEMANTICS_RECOMPUTE_FIX_POINTS_WITH_PRECONDITIONS")) {
2900  transformer new_tf = recompute_loop_transformer(l, preb);
2901 
2902  free_transformer(preb);
2903  preb = transformer_dup(pre);
2904  preb = transformer_combine(preb, new_tf);
2905  preb = add_good_loop_conditions(preb, l);
2906  }
2907 
2908 
2909  /* FI: this is not correct when an invariant is found; we should add one
2910  * more incrementation of I (to modify the output of the invariant and
2911  * express the fact that the loop bound is no more true, at least when
2912  * the increment is one. 6 July 1993
2913  *
2914  * Note 1: this comments was wrong! See Validation/Semantics/induc1.f
2915  * Note 2: but the result was wrong anyway because it assumed that at
2916  * least one iteration always was performed.
2917  * Note 3: This is fixed by reverting the above decision.
2918  */
2919  if(empty_range_wrt_precondition_p(r, pre)) {
2920  pips_debug(8, "The loop is never executed\n");
2921 
2922  /* propagate an impossible precondition in the loop body */
2924  /* The loop body precondition is not useful any longer */
2925  free_transformer(preb);
2926 
2927  transformer tmp = transformer_dup(pre);
2928  post = add_loop_index_initialization(tmp, l, pre);
2929  transformer_free(tmp);
2930  }
2931  else if(non_empty_range_wrt_precondition_p(r, pre)) {
2932  debug(8, "loop_to_postcondition", "The loop certainly is executed\n");
2933 
2934  /* propagate preconditions in the loop body and compute its postcondition... */
2935  post = statement_to_postcondition(preb, s);
2936 
2937  /* ... or compute directly the postcondition using the loop body transformer.
2938  * This second approach is slightly less precise because the transformer
2939  * cannot use preconditions to avoid some convex approximations. */
2940  /* post = transformer_apply(tf, pre); */
2941 
2942  /* The loop body effects should be passed as fourth argument
2943  * to check that the value of the upper bound expression is
2944  * not modified when the body is executed. But it is not available
2945  * and it is not yet used by ad_loop_index_exit_value()!
2946  */
2947  transformer tmp = post;
2948  post = add_loop_index_exit_value(post, l, pre);
2949  transformer_free(tmp);
2950  }
2951  else {
2952  /* First version: OK, but could be better! */
2953  /* transformer postloop = transformer_apply(tf, pre); */
2954  /* pre must be copied because sc_convex_hull updates is arguments
2955  * and may make them inconsistent when the two bases are merged
2956  * to perform the convex hull in a common vector space
2957  */
2958  /*
2959  transformer preloop = transformer_dup(pre);
2960  debug(8, "loop_to_postcondition", "The loop may be executed or not\n");
2961 
2962  post = transformer_convex_hull(postloop, preloop);
2963  transformer_free(postloop);
2964  transformer_free(preloop);
2965  */
2966 
2967  /* Second version: assume it is empty or non-empty and perform
2968  * the convex hull of both
2969  * (should be checked on Validation/Semantics/induc1.f)
2970  */
2972  transformer post_ne = transformer_apply(t_init, pre);
2974  transformer lpre = transformer_range(post_ne);
2975 
2976  pips_debug(8, "The loop may be executed or not\n");
2977 
2978  /* propagate preconditions in the loop body */
2979  post_al = statement_to_postcondition(preb, s);
2980  /* post_al = transformer_apply(tf, pre); */
2981 
2982  /* We should add (when possible) the non-entry condition in post_ne!
2983  * For instance, DO I = 1, N leads to N <= 0
2984  */
2985  post_ne = add_loop_skip_condition(post_ne, l, lpre);
2986  // FI: already done with t_init
2987  //post_ne = add_loop_index_initialization(post_ne, l, lpre);
2988  free_transformer(lpre);
2989 
2990  transformer tmp = post_al;
2991  post_al = add_loop_index_exit_value(post_al, l, post_al);
2992  transformer_free(tmp);
2993 
2994  ifdebug(8) {
2995  (void) fprintf(stderr,"%s: %s\n","[loop_to_postcondition]",
2996  "Never executed: post_ne %p =");
2997  (void) print_transformer(post_ne);
2998  (void) fprintf(stderr,"%s: %s\n","[loop_to_postcondition]",
2999  "Always executed: post_al %p = ");
3000  (void) print_transformer(post_al);
3001  }
3002  post = transformer_convex_hull(post_ne, post_al);
3003  transformer_free(post_ne);
3004  transformer_free(post_al);
3005  }
3006 
3007  /* FI: Cannot be freed because it was stored for statement s:
3008  transformer_free(preb);
3009  did I mean to free pre, which is useless since it was changed into
3010  preb?
3011  */
3012  }
3013 
3014  ifdebug(8) {
3015  (void) fprintf(stderr,"%s: %s\n","[loop_to_postcondition]",
3016  "resultat post =");
3017  (void) print_transformer(post);
3018  }
3019  pips_debug(8,"end\n");
3020  return post;
3021 }
#define SEMANTICS_FIX_POINT
#define pips_flag_p(p)
for upwards compatibility with Francois's modified version
#define SEMANTICS_INEQUALITY_INVARIANT
static transformer add_good_loop_conditions(transformer pre, loop l)
Definition: loop.c:790
static transformer recompute_loop_transformer(loop l, transformer pre)
Recompute a fixpoint conditionnally to a valid precondition for all iterations.
Definition: loop.c:2310

References add_good_loop_conditions(), add_loop_index_exit_value(), add_loop_index_initialization(), add_loop_skip_condition(), debug(), empty_range_wrt_precondition_p(), fprintf(), free_transformer(), get_bool_property(), ifdebug, loop_body, loop_initialization_to_transformer(), loop_range, non_empty_range_wrt_precondition_p(), pips_debug, pips_flag_p, pips_internal_error, print_transformer, recompute_loop_transformer(), SEMANTICS_FIX_POINT, SEMANTICS_INEQUALITY_INVARIANT, statement_to_postcondition(), transformer_apply(), transformer_combine(), transformer_convex_hull(), transformer_dup(), transformer_empty(), transformer_free(), transformer_range(), and transformer_undefined.

Referenced by instruction_to_postcondition().

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

◆ loop_to_total_precondition()

transformer loop_to_total_precondition ( transformer  t_post,
loop  l,
transformer  tf,
transformer  context 
)

Triolet's good loop algorithm

preb = transformer_dup(pre);

The loop is never executed

impact of loop index initialization, i.e. I = IT(J),.. or I = K/L,..

the loop may be entered for sure, or entered or not

We need a fix_point without the initial condition but with the exit condition

Also performs last incrementation

free_transformer(b_t_pre); it is associated to the loop body!

The loop is always entered

The loop may be skipped or entered

skipped case computed here too

Parameters
t_post_post
tff
contextontext

Definition at line 3023 of file loop.c.

3028 {
3030  statement b = loop_body(l);
3031  range r = loop_range(l);
3032 
3033  pips_debug(8,"begin\n");
3034 
3035  if(get_bool_property("SEMANTICS_RECOMPUTE_FIX_POINTS_WITH_PRECONDITIONS")) {
3038 
3039  preb = transformer_combine(preb, tf);
3040 
3041  /* Triolet's good loop algorithm */
3042  preb = add_good_loop_conditions(preb, l);
3043 
3044  new_tf = recompute_loop_transformer(l, preb);
3045 
3046  free_transformer(preb);
3047  /* preb = transformer_dup(pre); */
3048  preb = transformer_combine(preb, new_tf);
3049  preb = add_good_loop_conditions(preb, l);
3050  }
3051 
3052  if(empty_range_wrt_precondition_p(r, context)) { /* The loop is never executed */
3054  transformer tf_empty = transformer_empty();
3056 
3057  pips_debug(8, "The loop is never executed\n");
3058 
3059  b_t_pre = statement_to_total_precondition(tf_empty, b);
3060  pips_assert("The body total precondition is consistent",
3061  transformer_consistency_p(b_t_pre));
3062 
3063  /* impact of loop index initialization, i.e. I = IT(J),.. or I = K/L,.. */
3064  t_pre = transformer_inverse_apply(tf_init, t_post);
3065  t_pre = transformer_to_domain(t_pre);
3066 
3067  free_transformer(tf_empty);
3068  free_transformer(tf_init);
3069  }
3070  else /* the loop may be entered for sure, or entered or not */ {
3071 
3074  /* We need a fix_point without the initial condition but with the exit
3075  condition */
3081 
3083  ltf = (* transformer_fix_point_operator)(btf);
3084  ltf = add_loop_index_exit_value(ltf, l, context); /* Also performs
3085  last
3086  incrementation */
3087  b_t_post = transformer_inverse_apply(ltf, t_post);
3088  b_t_post = transformer_to_domain(b_t_post);
3089  b_t_pre = statement_to_total_precondition(b_t_post, b);
3090  pips_assert("The body total precondition is consistent",
3091  transformer_consistency_p(b_t_pre));
3092  t_pre_al = transformer_inverse_apply(tf_init, b_t_pre);
3093  t_pre_al = transformer_to_domain(t_pre_al);
3094 
3095  /* free_transformer(b_t_pre); it is associated to the loop body!*/
3096  free_transformer(b_t_post);
3097  free_transformer(btf);
3098  free_transformer(ltf);
3099 
3101  /* The loop is always entered */
3102  t_pre = t_pre_al;
3103 
3104  pips_debug(8, "The loop certainly is executed\n");
3105  }
3106  else /* The loop may be skipped or entered */ {
3107 
3108  pips_debug(8, "The loop may be executed or not\n");
3109 
3110  /* skipped case computed here too */
3111  t_pre_ne = transformer_inverse_apply(tf_init, t_post);
3112  t_pre_ne = transformer_to_domain(t_pre_ne);
3113  t_pre_ne = add_loop_skip_condition(t_pre_ne, l, context);
3114 
3115 
3116  ifdebug(8) {
3117  (void) fprintf(stderr,"%s: %s\n","[loop_to_postcondition]",
3118  "Never executed: t_pre_ne =");
3119  (void) print_transformer(t_pre_ne);
3120  (void) fprintf(stderr,"%s: %s\n","[loop_to_postcondition]",
3121  "Always executed: post_al =");
3122  (void) print_transformer(t_pre_al);
3123  }
3124 
3125  t_pre = transformer_convex_hull(t_pre_ne, t_pre_al);
3126  transformer_free(t_pre_ne);
3127  transformer_free(t_pre_al);
3128  }
3129  free_transformer(tf_init);
3130  }
3131 
3132  ifdebug(8) {
3133  pips_debug(8, "resultat t_pre =%p", t_pre);
3134  (void) print_transformer(t_pre);
3135  pips_debug(8,"end\n");
3136  }
3137  return t_pre;
3138 }
transformer statement_to_total_precondition(transformer, statement)
semantical analysis
Definition: delay.c:253
transformer transformer_inverse_apply(transformer tf, transformer post)
transformer transformer_inverse_apply(transformer tf, transformer post): apply transformer tf on prec...
Definition: transformer.c:1657
transformer transformer_to_domain(transformer tf)
Return the domain of relation tf in a newly allocated transformer.
Definition: transformer.c:772

References add_good_loop_conditions(), add_loop_index_exit_value(), add_loop_skip_condition(), empty_range_wrt_precondition_p(), fprintf(), free_transformer(), get_bool_property(), ifdebug, load_statement_transformer(), loop_body, loop_initialization_to_transformer(), loop_range, non_empty_range_wrt_precondition_p(), pips_assert, pips_debug, print_transformer, recompute_loop_transformer(), statement_to_total_precondition(), transformer_add_loop_index_incrementation(), transformer_combine(), transformer_consistency_p(), transformer_convex_hull(), transformer_dup(), transformer_empty(), transformer_free(), transformer_inverse_apply(), transformer_to_domain(), and transformer_undefined.

Referenced by instruction_to_total_precondition().

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

◆ loop_to_transformer()

transformer loop_to_transformer ( loop  l,
transformer  pre,
list  e 
)

The transformer associated to a DO loop does not include the exit condition because it is used to compute the precondition for any loop iteration.

There is only one attachment for the unbounded transformer and for the bounded one.

loop transformer tf = tfb* or tf = tfb+ or ...

loop body transformer

approximate loop transformer, including loop index updates

loop body precondition

Information about loop local variables is lost

range r = loop_range(l);

eliminate all information about local variables

Mostly useful for Fortran code.

In C, variables declared in the loop body do not exist before the loop is entered and so do not have to be projected. But local variables may have been introduced by a privatization phase.

compute the loop body transformer under loop body precondition preb

add indexation step under loop precondition pre

compute tfb's fix point according to pips flags

restrict the domain of tf by the range of pre, except for the loop index which is assigned in between

add initialization for the unconditional initialization of the loop index variable

we have a problem here: to compute preconditions within the loop body we need a tf using private variables; to return the loop transformer, we need a filtered out tf; only one hook is available in the ri..; let'a assume there are no private variables and that if they are privatizable they are not going to get in our way

Parameters
prere

Definition at line 1319 of file loop.c.

1321 {
1322  /* loop transformer tf = tfb* or tf = tfb+ or ... */
1324  /* loop body transformer */
1326  /* approximate loop transformer, including loop index updates */
1328  /* loop body precondition */
1329  transformer preb = invariant_wrt_transformer(pre, abtf);
1330  /* Information about loop local variables is lost */
1331  list lv = loop_locals(l);
1332  /* range r = loop_range(l); */
1333  statement b = loop_body(l);
1336 
1337  pips_debug(8,"begin with precondition pre=%p\n", pre);
1338  ifdebug(8) {
1339  (void) print_transformer(pre);
1340  }
1341 
1342  /* eliminate all information about local variables
1343  *
1344  * Mostly useful for Fortran code.
1345  *
1346  * In C, variables declared in the loop body do not exist before the
1347  * loop is entered and so do not have to be projected. But local
1348  * variables may have been introduced by a privatization phase.
1349  */
1350  preb = safe_transformer_projection(preb, lv);
1351 
1352  /* compute the loop body transformer under loop body precondition preb */
1353  if(!transformer_undefined_p(preb))
1354  preb = add_good_loop_conditions(preb, l);
1355 
1356  pips_debug(8,"body precondition preb=%p\n", preb);
1357  ifdebug(8) {
1358  (void) print_transformer(preb);
1359  }
1360 
1361  tfb = statement_to_transformer(b, preb);
1362  /* add indexation step under loop precondition pre */
1363  tfb = transformer_add_loop_index_incrementation(tfb, l, pre);
1364 
1365  pips_debug(8,"body transformer tfb=%p\n", tfb);
1366  ifdebug(8) {
1367  (void) print_transformer(tfb);
1368  }
1369 
1370  /* compute tfb's fix point according to pips flags */
1371  tf = (* transformer_fix_point_operator)(tfb);
1372 
1373  free_transformer(tfb);
1374 
1375  ifdebug(8) {
1376  pips_debug(8, "intermediate fix-point tf=\n");
1378  }
1379 
1380  /* restrict the domain of tf by the range of pre, except for the loop
1381  index which is assigned in between */
1382  if(!transformer_undefined_p(pre)
1383  && get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT")) {
1384  list li = CONS(ENTITY, loop_index(l), NIL);
1386  transformer r_pre = transformer_range(preb);
1387 
1388  tf = transformer_domain_intersection(tf, r_pre);
1389  free_transformer(r_pre);
1390  free_transformer(preb);
1391  gen_free_list(li);
1392  }
1393 
1394  /* add initialization for the unconditional initialization of the loop
1395  index variable */
1396  t_init = loop_initialization_to_transformer(l, pre);
1397  old_tf = tf;
1398  tf = transformer_combine(t_init, tf);
1401  free_transformer(old_tf);
1402 
1403  /* we have a problem here: to compute preconditions within the
1404  loop body we need a tf using private variables; to return
1405  the loop transformer, we need a filtered out tf; only
1406  one hook is available in the ri..; let'a assume there
1407  are no private variables and that if they are privatizable
1408  they are not going to get in our way */
1409 
1410  ifdebug(8) {
1411  (void) fprintf(stderr,"%s: %s\n","loop_to_transformer",
1412  "resultat tf =");
1413  (void) (void) print_transformer(tf);
1414  pips_debug(8,"end\n");
1415  }
1416 
1417  return tf;
1418 }
#define loop_locals(x)
Definition: ri.h:1650
transformer add_index_range_conditions(transformer pre, entity i, range r, transformer tfb)
Definition: loop.c:711
transformer safe_transformer_projection(transformer t, list args)
t may be undefined, args may contain values unrelated to t
Definition: transformer.c:1187
transformer transformer_domain_intersection(transformer tf, transformer pre)
Restrict the domain of the relation tf with pre.
Definition: transformer.c:661
transformer invariant_wrt_transformer(transformer p, transformer tf)
transformer invariant_wrt_transformer(transformer p, transformer tf): Assume that tf is a fix-point o...
Definition: transformer.c:1948

References add_good_loop_conditions(), add_index_range_conditions(), CONS, effects_to_transformer(), ENTITY, external_value_name(), fprint_transformer(), fprintf(), free_transformer(), gen_free_list(), get_bool_property(), ifdebug, invariant_wrt_transformer(), load_statement_transformer(), loop_body, loop_index, loop_initialization_to_transformer(), loop_locals, loop_range, NIL, pips_debug, print_transformer, safe_transformer_projection(), statement_to_transformer(), transformer_add_loop_index_incrementation(), transformer_combine(), transformer_domain_intersection(), transformer_dup(), transformer_filter(), transformer_range(), transformer_undefined, and transformer_undefined_p.

Referenced by instruction_to_transformer().

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

◆ loop_to_transformer_list()

list loop_to_transformer_list ( loop  ,
transformer  ,
list   
)

◆ make_postcondition_map()

void make_postcondition_map ( void  )

◆ make_precondition_map()

void make_precondition_map ( void  )

◆ make_pred_commentary_sentence()

sentence make_pred_commentary_sentence ( string  str_pred,
string  comment_prefix 
)

sentence make_pred_commentary_sentence(string str_pred, string comment_prefix) input : a substring formatted to be a commentary output : a sentence, containing the commentary form of this string, beginning with the comment_prefix.

modifies : nothing

Parameters
str_predtr_pred
comment_prefixomment_prefix

Definition at line 678 of file prettyprint.c.

681 {
682  /*
683  char str_tmp[MAX_PRED_COMMENTARY_STRLEN + 1];
684 
685  str_tmp[0] = '\0';
686  (void) strcat(str_tmp, comment_prefix);
687  (void) strcat(str_tmp, " ");
688  (void) strcat(str_tmp, str_pred);
689  (void) strcat(str_tmp, "\n");
690  */
691  char * str_tmp = NULL;
692  sentence sent_pred = sentence_undefined;
693 
694  str_tmp = strdup(concatenate(comment_prefix, " ", str_pred, "\n", NULL));
695  sent_pred = make_sentence_formatted(str_tmp);
696  return(sent_pred);
697 }
sentence make_sentence_formatted(string _field_)
Definition: text.c:62
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define sentence_undefined
Definition: text.h:42

References concatenate(), make_sentence_formatted(), sentence_undefined, and strdup().

Referenced by string_predicate_to_commentary(), and text_comp_region().

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

◆ make_semantic_map()

void make_semantic_map ( void  )

◆ make_total_precondition_map()

void make_total_precondition_map ( void  )

◆ make_transformer_map()

void make_transformer_map ( void  )

◆ module_name_to_preconditions()

bool module_name_to_preconditions ( const char *  module_name)

resource module_name_to_preconditions(char * module_name): compute a transformer for each statement of a module with a given name; compute also the global transformer for the module

set_debug_level(get_int_property(SEMANTICS_DEBUG_LEVEL));

To provide information for warnings

could be a gen_find_tabulated as well...

Used to add reference information when it is trusted... which should always be, at least for automatic parallelization.

cumulated effects are used to compute the value mappings

p_inter is not used!!! FI, 9 February 1994

debug_on(SEMANTICS_DEBUG_LEVEL);

compute the mappings related to module m, that is likely to be unavailable during interprocedural analysis; a module reference should be kept with the mappings to avoid useless recomputation, allocation and frees, including those due to the prettyprinter

set the list of global values. This is a bit too restrictive in C as the formal arguments, even modified in the procedure body, will not appear in the transformer_arguments. Should we add missing formal arguments to this list? See for instance "character01.c".

debug_on(SEMANTICS_DEBUG_LEVEL);

Add declaration information: arrays cannot be empty (Fortran standard, Section 5.1.2). But according to summary_precondition(), this is now supposed to be performed by the transformer phase?

If the module is never called, its precondition is identity and by default no values are listed in its basis. Function add_type_information() has no effect.

if(transformer_identity_p(pre)) {

list el = effects_to_list(

(effects) db_get_memory_resource(DBR_SUMMARY_EFFECTS, module_name, true));

free_transformer(pre);

// FI: memory leak

pre = transformer_range(effects_to_transformer(el));

}

debug_on(SEMANTICS_DEBUG_LEVEL);

propagate the module precondition

post could be stored in the ri for later interprocedural uses but the ri cannot be modified so early before the DRET demo; also our current interprocedural algorithm does not propagate postconditions upwards in the call tree

Parameters
module_nameodule_name

Definition at line 1073 of file dbm_interface.c.

1074 {
1075  transformer t_inter;
1076  transformer pre;
1077  transformer post;
1078 
1079  /* set_debug_level(get_int_property(SEMANTICS_DEBUG_LEVEL)); */
1081  /* To provide information for warnings */
1084 
1086  /* could be a gen_find_tabulated as well... */
1088  (statement) db_get_memory_resource(DBR_CODE, module_name, true));
1090  pips_internal_error("no statement for module %s", module_name);
1091 
1092  /* Used to add reference information when it is trusted... which
1093  should always be, at least for automatic parallelization. */
1095  db_get_memory_resource(DBR_PROPER_EFFECTS, module_name, true));
1096 
1097  /* cumulated effects are used to compute the value mappings */
1099  db_get_memory_resource(DBR_CUMULATED_EFFECTS, module_name, true));
1100 
1102 
1104  db_get_memory_resource(DBR_TRANSFORMERS, module_name, true));
1105 
1106 
1107  /* p_inter is not used!!! FI, 9 February 1994 */
1108  /*
1109  if(get_bool_property(SEMANTICS_INTERPROCEDURAL)) {
1110  p_inter = (transformer)
1111  db_get_memory_resource(DBR_SUMMARY_PRECONDITION,
1112  module_name, true);
1113  }
1114  */
1115 
1116  t_inter = (transformer)
1117  db_get_memory_resource(DBR_SUMMARY_TRANSFORMER, module_name, true);
1118 
1119  /* debug_on(SEMANTICS_DEBUG_LEVEL); */
1120 
1122 
1123  /* compute the mappings related to module m, that is likely to be
1124  unavailable during interprocedural analysis; a module reference
1125  should be kept with the mappings to avoid useless recomputation,
1126  allocation and frees, including those due to the prettyprinter */
1127 
1129 
1130  /* set the list of global values. This is a bit too restrictive in
1131  C as the formal arguments, even modified in the procedure body,
1132  will not appear in the transformer_arguments. Should we add
1133  missing formal arguments to this list? See for instance
1134  "character01.c". */
1136 
1137  /* debug_on(SEMANTICS_DEBUG_LEVEL); */
1138 
1140 
1141  /* Add declaration information: arrays cannot be empty (Fortran
1142  standard, Section 5.1.2). But according to summary_precondition(),
1143  this is now supposed to be performed by the transformer phase? */
1144  if(get_bool_property("SEMANTICS_TRUST_ARRAY_DECLARATIONS")) {
1146  }
1147  if(get_bool_property("SEMANTICS_USE_TYPE_INFORMATION")
1148  || get_bool_property("SEMANTICS_USE_TYPE_INFORMATION_IN_PRECONDITIONS")) {
1149 
1150  /* If the module is never called, its precondition is identity
1151  and by default no values are listed in its basis. Function
1152  add_type_information() has no effect. */
1153 
1154  /* if(transformer_identity_p(pre)) { */
1155  /* list el = effects_to_list( */
1156  /* (effects) db_get_memory_resource(DBR_SUMMARY_EFFECTS, module_name, true)); */
1157  /* free_transformer(pre); */
1158  /* // FI: memory leak */
1159  /* pre = transformer_range(effects_to_transformer(el)); */
1160  /* } */
1161 
1163  }
1164 
1165  /* debug_on(SEMANTICS_DEBUG_LEVEL); */
1166 
1167  /* propagate the module precondition */
1170  close_reachable();
1171 
1172  /* post could be stored in the ri for later interprocedural uses
1173  but the ri cannot be modified so early before the DRET demo;
1174  also our current interprocedural algorithm does not propagate
1175  postconditions upwards in the call tree */
1176 
1177  DB_PUT_MEMORY_RESOURCE(DBR_PRECONDITIONS,
1178  module_name,
1179  (char*) get_precondition_map() );
1180 
1181  pips_debug(8, "postcondition computed for %s\n",
1183  ifdebug(8) (void) print_transformer(post);
1184  debug(1, "module_name_to_preconditions", "end\n");
1185 
1193 
1195 
1198  debug_off();
1199 
1200  return true;
1201 }
void close_reachable(void)
Remove reachability information about previously checked statements.
Definition: unreachable.c:252
void init_reachable(statement)
unreachable.c
Definition: unreachable.c:223
static void precondition_add_declaration_information(transformer pre, entity m)
void set_module_global_arguments(list args)
void transformer_add_type_information(transformer)
type.c
Definition: type.c:162
statement_mapping get_precondition_map(void)

References close_reachable(), copy_transformer(), database_undefined, db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug(), debug_off, debug_on, entity_local_name(), free_statement_global_stack(), free_value_mappings(), generic_effects_reset_all_methods(), get_bool_property(), get_current_module_entity(), get_current_module_statement(), get_precondition_map(), ifdebug, init_reachable(), load_summary_precondition(), make_statement_global_stack(), MAKE_STATEMENT_MAPPING, module_name(), module_name_to_entity(), module_to_value_mappings(), pips_debug, pips_internal_error, precondition_add_declaration_information(), print_transformer, readable_value_name(), reset_cumulated_rw_effects(), reset_current_module_entity(), reset_current_module_statement(), reset_precondition_map(), reset_proper_rw_effects(), reset_transformer_map(), sc_variable_name_pop(), sc_variable_name_push(), SEMANTICS_DEBUG_LEVEL, set_cumulated_rw_effects(), set_current_module_entity(), set_current_module_statement(), set_methods_for_simple_effects(), set_module_global_arguments(), set_precondition_map(), set_proper_rw_effects(), set_transformer_map(), statement_to_postcondition(), transformer_add_type_information(), and transformer_arguments.

Referenced by preconditions_inter_fast(), preconditions_inter_full(), preconditions_inter_full_with_points_to(), preconditions_intra(), and preconditions_intra_fast().

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

◆ module_name_to_total_preconditions()

bool module_name_to_total_preconditions ( const char *  module_name)

set the list of global values

The program postcondition should be used DBR_PROGRAM_POSTCONDITION

that might be because we are at the call tree root or because no information is available; maybe, every module precondition should be initialized to a neutral value?

intra-procedural case, not a main module

propagate the module total postcondition

filter out local variables from the global intraprocedural effect

Parameters
module_nameodule_name

Definition at line 1203 of file dbm_interface.c.

1204 {
1207  transformer t_pre_inter = transformer_undefined;
1209  list e_inter = list_undefined;
1210 
1213 
1216  (statement) db_get_memory_resource(DBR_CODE, module_name, true));
1218  pips_internal_error("no statement for module %s", module_name);
1219 
1221  db_get_memory_resource(DBR_PROPER_EFFECTS, module_name, true));
1222 
1224  db_get_memory_resource(DBR_CUMULATED_EFFECTS, module_name, true));
1225 
1226  e_inter = effects_to_list((effects)
1227  db_get_memory_resource(DBR_SUMMARY_EFFECTS, module_name, true));
1228 
1230  db_get_memory_resource(DBR_TRANSFORMERS, module_name, true));
1231 
1233  db_get_memory_resource(DBR_PRECONDITIONS, module_name, true));
1234 
1235 
1236  t_inter = (transformer)
1237  db_get_memory_resource(DBR_SUMMARY_TRANSFORMER, module_name, true);
1238 
1240 
1242 
1243  /* set the list of global values */
1245 
1247  /* The program postcondition should be used DBR_PROGRAM_POSTCONDITION */
1248  t_post = transformer_identity();
1249  }
1250 
1251  ifdebug(3) {
1252  pips_debug(1, "considering final total postcondition for %s\n", module_name);
1253  print_transformer(t_post);
1254  }
1255 
1257  transformer ip =
1259  if( ip == transformer_undefined) {
1260  /* that might be because we are at the call tree root
1261  or because no information is available;
1262  maybe, every module precondition should be initialized
1263  to a neutral value? */
1264  pips_user_warning("no interprocedural module total postcondition for %s\n",
1266  ;
1267  }
1268  else {
1270  ifdebug(8) {
1271  pips_debug(8, "\t summary_total_postcondition %p after translation:\n",
1272  ip);
1273  print_transformer(ip);
1274  pips_assert("The summary total postcondition is consistent",
1276  }
1277  t_post = transformer_combine(transformer_dup(ip), t_post);
1278  }
1279  }
1280  else if(transformer_undefined_p(t_post)) {
1281  /* intra-procedural case, not a main module */
1282  t_post = transformer_identity();
1283  }
1284 
1285  /* propagate the module total postcondition */
1288  close_reachable();
1289 
1290  DB_PUT_MEMORY_RESOURCE(DBR_TOTAL_PRECONDITIONS,
1291  module_name,
1292  (char*) get_total_precondition_map() );
1293 
1294  /* filter out local variables from the global intraprocedural effect */
1295  t_pre_inter = transformer_intra_to_inter(t_pre, e_inter);
1296  t_pre_inter = transformer_normalize(t_pre_inter, 2);
1297  if(!transformer_consistency_p(t_pre_inter)) {
1298  (void) print_transformer(t_pre_inter);
1299  pips_internal_error("Non-consistent summary transformer");
1300  }
1301  DB_PUT_MEMORY_RESOURCE(DBR_SUMMARY_TOTAL_PRECONDITION,
1303  (char*) t_pre_inter);
1304 
1305  pips_debug(8, "total precondition computed for %s\n",
1307  ifdebug(8) (void) print_transformer(t_pre);
1308  pips_debug(1, "end\n");
1309 
1317 
1319 
1321  debug_off();
1322 
1323  return true;
1324 }
transformer load_summary_total_postcondition(entity e)
summary_preconditions are expressed in any possible frame, in fact the frame of the last procedure th...
void set_total_precondition_map(statement_mapping)
void reset_total_precondition_map(void)
statement_mapping get_total_precondition_map(void)

References close_reachable(), database_undefined, db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, effects_to_list(), entity_local_name(), entity_main_module_p(), free_value_mappings(), get_bool_property(), get_current_module_entity(), get_current_module_statement(), get_total_precondition_map(), ifdebug, init_reachable(), list_undefined, load_summary_total_postcondition(), MAKE_STATEMENT_MAPPING, module_local_name(), module_name(), module_name_to_entity(), module_to_value_mappings(), pips_assert, pips_debug, pips_internal_error, pips_user_warning, print_transformer, readable_value_name(), reset_cumulated_rw_effects(), reset_current_module_entity(), reset_current_module_statement(), reset_precondition_map(), reset_proper_rw_effects(), reset_total_precondition_map(), reset_transformer_map(), sc_variable_name_pop(), sc_variable_name_push(), SEMANTICS_DEBUG_LEVEL, SEMANTICS_INTERPROCEDURAL, set_cumulated_rw_effects(), set_current_module_entity(), set_current_module_statement(), set_module_global_arguments(), set_precondition_map(), set_proper_rw_effects(), set_total_precondition_map(), set_transformer_map(), statement_to_total_precondition(), transformer_arguments, transformer_combine(), transformer_consistency_p(), transformer_dup(), transformer_identity(), transformer_intra_to_inter(), transformer_normalize(), transformer_undefined, transformer_undefined_p, and translate_global_values().

Referenced by total_preconditions_inter(), and total_preconditions_intra().

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

◆ module_name_to_transformers()

bool module_name_to_transformers ( const char *  module_name)
Parameters
module_nameodule_name

Definition at line 1062 of file dbm_interface.c.

1063 {
1064  bool rc = false;
1066  return rc;
1067 }
bool generic_module_name_to_transformers(const char *module_name, bool in_context)
bool generic_module_name_to_transformers(char * module_name, bool in_context): compute a transformer ...

References generic_module_name_to_transformers(), and module_name().

Referenced by transformers_inter_fast(), transformers_inter_full(), transformers_inter_full_with_points_to(), transformers_intra_fast(), and transformers_intra_full().

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

◆ module_name_to_transformers_in_context()

bool module_name_to_transformers_in_context ( const char *  module_name)
Parameters
module_nameodule_name

Definition at line 1044 of file dbm_interface.c.

1045 {
1046  bool rc = false;
1047  bool save_prop = get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT");
1048 
1049  if(!save_prop) {
1050  pips_user_warning("Although property SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT"
1051  " is not set, it is used because it is necessary for this "
1052  "recomputation to be useful\n");
1053  set_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT", true);
1054  }
1055 
1057 
1058  set_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT", save_prop);
1059  return rc;
1060 }

References generic_module_name_to_transformers(), get_bool_property(), module_name(), pips_user_warning, and set_bool_property().

Referenced by refine_transformers(), and refine_transformers_with_points_to().

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

◆ module_to_formal_analyzable_parameters()

list module_to_formal_analyzable_parameters ( entity  f)

returns a module's parameter's list

get unsorted list of formal analyzable parameters for f by declaration filtering; these parameters may not be used by the callee's semantics analysis, but we have no way to know it because value mappings are not available

Definition at line 232 of file interprocedural.c.

233 {
234  /* get unsorted list of formal analyzable parameters for f by declaration
235  filtering; these parameters may not be used by the callee's
236  semantics analysis, but we have no way to know it because
237  value mappings are not available */
238 
239  list formals = NIL;
240  list decl = list_undefined;
241 
242  pips_assert("f is a module",entity_module_p(f));
243 
245  MAPL(ce, {entity e = ENTITY(CAR(ce));
248  formals = CONS(ENTITY, e, formals);},
249  decl);
250 
251  return formals;
252 }
code entity_code(entity e)
Definition: entity.c:1098
#define code_declarations(x)
Definition: ri.h:784

References analyzable_scalar_entity_p(), CAR, code_declarations, CONS, ENTITY, entity_code(), entity_module_p(), entity_storage, f(), list_undefined, MAPL, NIL, pips_assert, and storage_formal_p.

Referenced by add_formal_to_actual_bindings(), and fortran_user_call_to_transformer().

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

◆ module_to_value_mappings()

void module_to_value_mappings ( entity  m)

void module_to_value_mappings(entity m): build hash tables between variables and values (old, new and intermediate), and between values and names for module m, as well as equivalence equalities

NW: before calling "module_to_value_mappings" to set up the hash table to translate value into value names for module with name (string) module_name do:

set_current_module_entity( local_name_to_top_level_entity(module_name) );

(the following call is only necessary if a variable of type entity such as "module" is not already set) module = get_current_module_entity();

set_current_module_statement( (statement) db_get_memory_resource(DBR_CODE, module_name, true) ); set_cumulated_rw_effects((statement_effects) db_get_memory_resource(DBR_CUMULATED_EFFECTS, module_name, true));

(that's it, but we musn't forget to reset everything after the call to "module_to_value_mappings", as below)

reset_current_module_statement(); reset_cumulated_rw_effects(); reset_current_module_entity(); free_value_mappings();

free_value_mappings();

reset local intermediate value counter for make_local_intermediate_value_entity and make_local_old_value_entity

module_inter_effects = code_effects(value_code(entity_initial(m)));

look for interprocedural write effects on scalar analyzable variables and generate proper entries into hash tables

In C, write effects on scalar formal parameter are masked by the value passing mode but the copy may nevertheless be written inside the function.

To keep the summary transformer consistent although the return value has no old value

look for interprocedural read effects on scalar analyzable variables and generate proper entries into hash tables

static variables have an old value too

look for intraprocedural write effects on scalar analyzable variables and generate proper entries into hash tables

look for intraprocedural read effects on scalar analyzable variables and generate proper entry into value name hash table if it has not been entered before; interprocedural read effects are implicitly dealed with since they are included; most entities are likely to have been encountered before; however in parameters and uninitialized variables have to be dealt with

FI: although it may only be read within this procedure, e might be written in another one thru a COMMON; this write is not visible from OUT, but only from a caller of out; because we have only a local intraprocedural or a global interprocedural view of aliasing, we have to create useless values:-(

add_new_value(e);

Note: this makes the control structure of this procedure obsolete!

This call is useless because it only is effective if entity_has_values_p() is true: add_intraprocedural_value_entities(e);

A stronger call to the same subroutine is included in the previous call: add_or_kill_equivalenced_variables(e, true);

scan declarations to make sure that private variables are taken into account; assume a read and write effects on these variables, although they may not even be used.

Only intraprocedural variables can be privatized (1 Aug. 92)

This should be useless if return variables are taken into account by effect analysis. No problem with Fortran because the return variable really is assigned a value. Not obvious in C because the assignment is implicit in the return statement. In C the return variable is more like a value: it cannot be re-assigned.

FI: Only return variables are forgotten by effects

FI: no, this is wrong in C; local variables are dropped from effect when their declaration statements are processed. They cannot be found in the effects of the module statement.

We need references to all fields, direct or indirect when a field is itself a struct

scan other referenced variables to make sure everyone has an entry in the symbol table

|| storage_return_p(es)

We need references to all fields, direct or indirect when a field is itself a struct

Beware of struct return values which may generate additional locations and location values

To be sure to retrieve all relevant locations, including array elements

for debug, print hash tables

Definition at line 624 of file mappings.c.

625 {
626  list module_inter_effects;
627  list module_intra_effects;
628 
629  pips_debug(8,"begin for module %s\n", module_local_name(m));
630 
631  pips_assert("m is a module", entity_module_p(m));
632 
633  // hook cleanup in free_value_mappings
635  /* free_value_mappings(); */
636 
638 
639  /* reset local intermediate value counter for
640  make_local_intermediate_value_entity and
641  make_local_old_value_entity */
646 
647  /* module_inter_effects = code_effects(value_code(entity_initial(m))); */
648  module_inter_effects = load_summary_effects(m);
649 
650  /* look for interprocedural write effects on scalar analyzable variables
651  and generate proper entries into hash tables */
652  FOREACH(EFFECT, ef, module_inter_effects) {
653  if(store_effect_p(ef)) {
655  entity e = reference_variable(r);
656  action a = effect_action(ef);
657  if(analyzable_scalar_entity_p(e) // check type
659  && (
660  action_write_p(a)
661  ||
662  /* In C, write effects on scalar formal parameter are
663  masked by the value passing mode but the copy may
664  nevertheless be written inside the function. */
665  (c_module_p(m) && entity_formal_p(e))
666  ||
667  /* To keep the summary transformer consistent
668  although the return value has no old value */
670  ))
671  )
673  else if(entity_abstract_location_p(e) && action_write_p(a)) {
674  add_implicit_interprocedural_write_effects(e, module_inter_effects);
675  }
678  if(analyzed_type_p(t)) {
681  }
682  free_type(t);
683  }
684  }
685  }
686 
687  /* look for interprocedural read effects on scalar analyzable variables
688  and generate proper entries into hash tables */
689  FOREACH(EFFECT, ef, module_inter_effects) {
690  if(store_effect_p(ef)) {
692  action a = effect_action(ef);
694  if(c_module_p(m) &&
696  /* static variables have an old value too */
698  )
699  )
701  else
703  }
704  }
705  }
706 
707  module_intra_effects = load_module_intraprocedural_effects(m);
708 
709  /* look for intraprocedural write effects on scalar analyzable variables
710  and generate proper entries into hash tables */
711  FOREACH(EFFECT, ef, module_intra_effects) {
712  if(store_effect_p(ef)) {
714  action a = effect_action(ef);
718  }
719  else {
722  && !entity_heap_location_p(e))
724  }
725  }
726  else if(constant_path_analyzed_p() && action_write_p(a)) {
728 
729  if (analyzed_reference_p(rlhs)) {
730  entity le = make_location_entity(rlhs);
732  }
733  }
734  }
735  }
736 
737  /* look for intraprocedural read effects on scalar analyzable variables
738  and generate proper entry into value name hash table if it has
739  not been entered before; interprocedural read effects are implicitly
740  dealed with since they are included;
741  most entities are likely to have been encountered before; however
742  in parameters and uninitialized variables have to be dealt with */
743  FOREACH(EFFECT, ef, module_intra_effects) {
744  if(store_effect_p(ef)) {
747  /* FI: although it may only be read within this procedure, e
748  * might be written in another one thru a COMMON; this write
749  * is not visible from OUT, but only from a caller of out;
750  * because we have only a local intraprocedural or a global
751  * interprocedural view of aliasing, we have to create useless
752  * values:-(
753  *
754  * add_new_value(e);
755  *
756  * Note: this makes the control structure of this procedure
757  * obsolete!
758  */
759  /* This call is useless because it only is effective if
760  * entity_has_values_p() is true:
761  * add_intraprocedural_value_entities(e);
762  */
765  && !entity_heap_location_p(e))
767  /* A stronger call to the same subroutine is included in
768  * the previous call:
769  * add_or_kill_equivalenced_variables(e, true);
770  */
771  }
772  }
773  }
774 
775  /* scan declarations to make sure that private variables are
776  * taken into account; assume a read and write effects on these
777  * variables, although they may not even be used.
778  *
779  * Only intraprocedural variables can be privatized (1 Aug. 92)
780  */
782  FOREACH(ENTITY, e, dl) {
786  /* This should be useless if return variables are taken
787  into account by effect analysis. No problem with
788  Fortran because the return variable really is assigned
789  a value. Not obvious in C because the assignment is
790  implicit in the return statement. In C the return
791  variable is more like a value: it cannot be re-assigned. */
793  }
794  else {
796  }
797  }
798  else if(entity_variable_p(e) && !entity_abstract_location_p(e)) {
799  storage es = entity_storage(e);
800  // FI: do not process named or derived types
801  //if(storage_ram_p(es) || storage_return_p(es)) {
802  /* FI: Only return variables are forgotten by effects
803  *
804  * FI: no, this is wrong in C; local variables are dropped
805  * from effect when their declaration statements are
806  * processed. They cannot be found in the effects of the
807  * module statement.
808  */
809  if(storage_ram_p(es) || storage_return_p(es)) {
812  /* We need references to all fields, direct or indirect when
813  * a field is itself a struct
814  */
815  reference r = make_reference(e, NIL);
816  list fl = struct_type_to_fields(t);
818  free_reference(r);
819  }
820  }
821  }
822  }
823 
824  /* scan other referenced variables to make sure everyone has an
825  * entry in the symbol table
826  */
828  SET_FOREACH(entity, e, re) {
830  pips_assert("should not go there ?", !storage_return_p(entity_storage(e)));
832  }
833  }
834 
835  // FI: to analyze array elements with constant subscripts, we would
836  // need to get a list of all constant atomic references with types
837  // that are analyzed.
838 
839  // FI: for points-to analysis, we need to know all formal virtual
840  // entities that have been created by the points-to pass. It is not
841  // clear the information may be retrieved from the module statement
842  // cumulated effect, especially if scopes are used by the
843  // programmer, or the module summary cumulated effects.
845  SET_FOREACH(entity, e, re) {
846  // FI: place holder variables are supposed to have been removed
847  // from internal representation by C parser?
849  storage es = entity_storage(e);
850  if(storage_ram_p(es)/* || storage_return_p(es)*/) {
852  if(struct_type_p(t)) {
853  /* We need references to all fields, direct or indirect when
854  * a field is itself a struct
855  */
856  reference r = make_reference(e, NIL);
857  list fl = struct_type_to_fields(t);
859  free_reference(r);
860  }
861  }
862  }
863  }
864  }
865  set_free(re);
866 
867  /* Beware of struct return values which may generate additional
868  * locations and location values
869  */
871  const char * module_name = entity_local_name(m);
872  callees c = (callees) db_get_memory_resource(DBR_CALLEES,
873  module_name,
874  true);
875  list lc = callees_callees(c);
876  FOREACH(STRING, callee_name, lc) {
877  entity f = module_name_to_entity(callee_name);
880  if(struct_type_p(rt)) {
882  reference rvr = make_reference(rv, NIL);
883  list fl = struct_type_to_fields(rt);
885  free_reference(rvr);
886  }
887  }
888  }
889 
890  /* To be sure to retrieve all relevant locations, including array elements */
893  }
894 
895  /* for debug, print hash tables */
896  ifdebug(8) {
897  pips_debug(8, "hash tables for module %s\n", module_local_name(m));
900  }
901 
902  pips_debug(1, "Number of analyzed variables for module %s: %d\n",
905  pips_debug(1, "Number of analyzed values for module %s: %d\n",
908 
909  pips_debug(8,"end for module %s\n", module_local_name(m));
910 }
bool entity_heap_location_p(entity b)
package abstract location.
bool entity_typed_anywhere_locations_p(entity e)
Test if an entity is the bottom of the lattice.
bool entity_anywhere_locations_p(entity e)
test if an entity is the bottom of the lattice
bool store_effect_p(effect)
Definition: effects.c:1062
entity make_location_entity(reference)
locations.c
Definition: locations.c:274
#define action_read_p(x)
Definition: effects.h:311
#define STRING(x)
Definition: genC.h:87
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
void reset_hooks_register(reset_func_t)
reset_hooks.c
Definition: reset_hooks.c:44
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
void set_free(set)
Definition: set.c:332
#define entity_variable_p(e)
An entity_variable_p(e) may hide a typedef and hence a functional type.
bool entity_formal_p(entity p)
is p a formal parameter?
Definition: entity.c:1935
set get_referenced_entities_filtered(void *elem, bool(*chunk_filter)(void *), bool(*entity_filter)(entity))
Same as get_referenced_entities, but will only consider entities that fulfills entity_filter and will...
Definition: entity.c:2982
bool effects_package_entity_p(entity e)
checks if an entity is an IO_EFFECTS_PACKAGE_NAME, a MALLOC_EFFECTS_NAME or a RAND_EFFECTS_PACKAGE_NA...
Definition: entity.c:1181
entity function_to_return_value(entity m)
Returns the entity rv that carries the value returned by module m, when m is not a C void function or...
Definition: module.c:509
bool entity_static_variable_p(entity)
return true if the entity is declared with the keyword static
Definition: variable.c:1146
bool place_holder_variable_p(entity)
Definition: variable.c:2069
list struct_type_to_fields(type)
Definition: type.c:5798
bool struct_type_p(type)
Returns true if t is of type derived and if the derived type is a struct.
Definition: type.c:3121
struct _newgen_struct_callees_ * callees
Definition: ri.h:55
#define callees_callees(x)
Definition: ri.h:675
static bool entity_for_value_mapping_p(entity e)
Definition: mappings.c:418
static void allocate_module_value_mappings(entity m)
Definition: mappings.c:325
void add_intraprocedural_value_entities(entity e)
Use to be static, but may be called from ri_to_transformer.
Definition: mappings.c:181
static void reset_equivalence_equalities()
Definition: mappings.c:76
static void values_for_current_module_intraprocedural_simple_effects(void)
Definition: mappings.c:578
static void add_interprocedural_field_entities(reference r, list fl)
Definition: mappings.c:466
static void add_interprocedural_new_value_entity(entity e)
Definition: mappings.c:152
static void add_intraprocedural_field_entities(reference r, list fl)
Definition: mappings.c:461
void add_implicit_interprocedural_write_effects(entity al, list el)
It is assumed that al is an abstract location that is written and which may conflict with effects in ...
Definition: mappings.c:382
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
void reset_value_counters(void)
Definition: value.c:244
void set_analyzed_types(void)
Definition: value.c:271
void test_mapping_entry_consistency(void)
Definition: value.c:1113
int aproximate_number_of_analyzed_variables(void)
Definition: value.c:1153
void print_value_mappings(void)
Definition: value.c:993
void error_reset_value_mappings(void)
To be called by error handler only.
Definition: value.c:1205
int number_of_analyzed_values(void)
Definition: value.c:1148
list current_module_declarations()
Definition: module.c:78

References action_read_p, action_write_p, add_implicit_interprocedural_write_effects(), add_interprocedural_field_entities(), add_interprocedural_new_value_entity(), add_interprocedural_value_entities(), add_intraprocedural_field_entities(), add_intraprocedural_value_entities(), add_intraprocedural_value_entities_unconditionally(), allocate_module_value_mappings(), analyzable_scalar_entity_p(), analyzed_reference_p(), analyzed_type_p(), aproximate_number_of_analyzed_variables(), c_module_p(), callees_callees, cell_any_reference(), compute_basic_concrete_type(), constant_path_analyzed_p(), current_module_declarations(), db_get_memory_resource(), EFFECT, effect_action, effect_any_reference, effect_cell, effects_package_entity_p(), ENTITY, entity_abstract_location_p(), entity_anywhere_locations_p(), entity_basic_concrete_type(), entity_for_value_mapping_p(), entity_formal_p(), entity_has_values_p(), entity_heap_location_p(), entity_local_name(), entity_module_p(), entity_static_variable_p(), entity_storage, entity_typed_anywhere_locations_p(), entity_variable_p, error_reset_value_mappings(), f(), FOREACH, free_reference(), free_type(), function_to_return_value(), functional_result, gen_true(), get_current_module_statement(), get_referenced_entities_filtered(), ifdebug, load_module_intraprocedural_effects(), load_summary_effects(), location_entity_p(), make_location_entity(), make_reference(), module_local_name(), module_name(), module_name_to_entity(), NIL, number_of_analyzed_values(), pips_assert, pips_debug, place_holder_variable_p(), points_to_reference_to_concrete_type(), print_value_mappings(), reference_variable, reset_equivalence_equalities(), reset_hooks_register(), reset_temporary_value_counter(), reset_value_counters(), set_analyzed_types(), SET_FOREACH, set_free(), storage_ram_p, storage_return_p, store_effect_p(), STRING, struct_type_p(), struct_type_to_fields(), test_mapping_entry_consistency(), type_functional, and values_for_current_module_intraprocedural_simple_effects().

Referenced by add_alias_pairs_for_this_caller(), alias_classes(), alias_lists(), alias_pairs(), aliases_text(), any_complexities(), array_expansion(), bdsc_code_instrumentation(), call_site_to_module_precondition_text(), comp_regions(), continuation_conditions(), dsc_code_parallelization(), generic_module_name_to_transformers(), generic_print_xml_application(), get_any_comp_regions_text(), get_continuation_condition_text(), get_semantic_text(), hbdsc_parallelization(), init_convex_in_out_regions(), init_convex_rw_regions(), init_convex_summary_in_out_regions(), init_convex_summary_rw_regions(), initial_precondition(), isolate_statement(), kernel_data_mapping(), kernel_load_store_engine(), module_name_to_preconditions(), module_name_to_total_preconditions(), out_regions_from_caller_to_callee(), partial_eval(), phrase_comEngine_distributor(), phrase_distributor(), phrase_distributor_control_code(), pragma_outliner(), print_initial_precondition(), print_program_precondition(), program_precondition(), safescale_distributor(), safescale_module_analysis(), sequence_dependence_graph(), solve_hardware_constraints(), spire_distributed_unstructured_to_structured(), summary_precondition(), summary_total_postcondition(), and update_precondition_with_call_site_preconditions().

+ Here is the caller graph for this function:

◆ modulo_by_a_constant_to_transformer()

transformer modulo_by_a_constant_to_transformer ( entity  v1,
transformer  prec,
entity  v2,
int  k 
)

Analyze v2 % k, with v2 constrainted by tf, assuming tf is a precondition.

See if exist a set v_i such that v2 = sum_i a_i v_i + c. Then v2 can be rewritten as v2 = gcd_i(a_i) lambda + c.

if k divides gcd(a_i) then v2>0 ? v1 = v2 % k = c % k : v1 = v2 % k = ck-k

If the sign of v2 is unknown, ck-k<=v1<=ck

Parameters
v11
precrec
v22

Definition at line 1481 of file expression.c.

1482 {
1484  Value gcd, c, K = (Value) k;
1485 
1486  // exists lambda s.t. v2 = lambda gcd + c ^ 0<=c<gcd
1487  if(transformer_to_1D_lattice(v2, prec, &gcd, &c)) {
1488 
1489  // The sign of gcd does not matter more than the sign of lambda
1490  if(gcd<0) gcd = -gcd;
1491 
1492  // Is v2's sign known ?
1493  // Adding the sign constraint and using LP might be more efficient
1494  bool is_positive_p = false;
1495  bool is_negative_p = false;
1496  intptr_t imin = 0, imax = 0;
1497 
1498  if (precondition_minmax_of_value(v2, prec, &imin, &imax)) {
1499  is_positive_p = imin>=0;
1500  is_negative_p = imax<=0;
1501  }
1502 
1503  if (imin==imax) {
1504  // This piece of code should be useless because we expect
1505  // gcd = 0 and c = imin = imax in such a case
1506  // But it fails with Semantics-New/modulo16.c
1507  mtf = transformer_add_equality_with_integer_constant(mtf, v1, imin%K);
1508  }
1509  else if (gcd!=0) {
1510  if(gcd%k==0) {
1511  if(is_positive_p)
1513  else if(is_negative_p)
1514  mtf = transformer_add_equality_with_integer_constant(mtf, v1, c%K-K);
1515  else {
1516  mtf = transformer_add_inequality_with_integer_constraint(mtf, v1, c%K, true);
1517  mtf = transformer_add_inequality_with_integer_constraint(mtf, v1, c%K-K, false);
1518  }
1519  }
1520  else {
1521  if(is_positive_p) {
1522  mtf = transformer_add_inequality_with_integer_constraint(mtf, v1, K-1, true);
1523  mtf = transformer_add_inequality_with_integer_constraint(mtf, v1, 0, false);
1524  }
1525  else if(is_negative_p) {
1527  mtf = transformer_add_inequality_with_integer_constraint(mtf, v1, -K+1, false);
1528  }
1529  else {
1530  mtf = transformer_add_inequality_with_integer_constraint(mtf, v1, K-1, true);
1531  mtf = transformer_add_inequality_with_integer_constraint(mtf, v1, -K+1, false);
1532  }
1533  }
1534  }
1535  else { // Same result
1536  // v2 = c
1537  if(is_positive_p)
1539  else if(is_negative_p)
1540  mtf = transformer_add_equality_with_integer_constant(mtf, v1, c%K-K);
1541  else {
1542  mtf = transformer_add_inequality_with_integer_constraint(mtf, v1, c%K, true);
1543  mtf = transformer_add_inequality_with_integer_constraint(mtf, v1, c%K-K, false);
1544  }
1545  }
1546  }
1547  else {
1548  // There is no solution. E.g. v2==2 ^ v2==1 or 0==1
1549  // This case should be detected earlier and this piece of code is
1550  // probably unreachable
1551  mtf = empty_transformer(mtf);
1552  }
1553  return mtf;
1554 }
transformer empty_transformer(transformer t)
Do not allocate an empty transformer, but transform an allocated transformer into an empty_transforme...
Definition: basic.c:144
bool transformer_to_1D_lattice(entity v, transformer pre, Value *gcd_p, Value *c_p)
See if the equations in transformer "pre" constraint variable "v" by v = gcd x + c,...
Definition: transformer.c:2480

References empty_transformer(), intptr_t, precondition_minmax_of_value(), transformer_add_equality_with_integer_constant(), transformer_add_inequality_with_integer_constraint(), transformer_identity(), and transformer_to_1D_lattice().

Referenced by modulo_to_transformer().

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

◆ new_add_formal_to_actual_bindings()

transformer new_add_formal_to_actual_bindings ( call  c,
transformer  pre,
entity  caller 
)

Take side effects into account:

pre := (t(expr )...(t_expr ))(pre) U {f = expr } n 1 i i for all i such that formal f_i is an analyzable scalar variable and as far as expression expr_i is analyzable and of the same type.

The algorithmic structure has to be different from the previous one.

pre is modified by side effects.

Parameters
prere
calleraller

Definition at line 375 of file interprocedural.c.

376 {
377  entity f = call_function(c);
378  list args = call_arguments(c);
379 
381  transformer new_pre = transformer_apply(tf, pre);
382 
383  ifdebug(6) {
384  pips_debug(6, "new pre=%p\n", new_pre);
385  dump_transformer(new_pre);
386  pips_debug(6, "end for call to %s from %s\n", module_local_name(f),
387  module_local_name(caller));
388  }
389 
390  free_transformer(tf);
391 
392  return new_pre;
393 }

References any_user_call_site_to_transformer(), call_arguments, call_function, dump_transformer, f(), free_transformer(), ifdebug, module_local_name(), NIL, pips_debug, and transformer_apply().

Referenced by process_call_for_summary_precondition().

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

◆ new_array_element_backward_substitution_in_transformer()

transformer new_array_element_backward_substitution_in_transformer ( transformer  tf,
entity  l,
reference  fr,
reference  ar 
)

Substitute formal location entity l by a location entity corresponding to ar, if it is possible.

Parameters
tff
frr
arr

Definition at line 1723 of file ri_to_transformers.c.

1724 {
1725  reference nar = copy_reference(ar);
1727  reference_indices(nar) =
1728  gen_nconc(reference_indices(nar), nsl);
1730  if(entity_undefined_p(al)) {
1731  semantics_user_warning("Untranslatable reference \"%s\" because of"
1732  " imprecise effects.\n",
1733  reference_to_string(nar));
1734  list pl = CONS(ENTITY, l, NIL);
1735  tf = transformer_projection(tf, pl);
1736  gen_free_list(pl);
1737  }
1738  else {
1739  list pl = NIL;
1740  tf = substitute_scalar_stub_in_transformer(tf, l, al, true, &pl);
1741  if(ENDP(pl)) {
1742  ;
1743  }
1744  else {
1745  semantics_user_warning("Translation issues for location \"%s\"\n.",
1746  entity_user_name(l));
1747  tf = transformer_projection(tf, pl);
1748  gen_free_list(pl);
1749  }
1750  }
1751  free_reference(nar);
1752  return tf;
1753 }
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
static hash_table pl
properties are stored in this hash table (string -> property) for fast accesses.
Definition: properties.c:783
transformer substitute_scalar_stub_in_transformer(transformer tf, entity se, entity de, bool backward_p, list *ppl)
If both "se", source entity, and "de", destination entity, are defined, substitute the values of "se"...
Definition: points_to.c:136

References CONS, constant_memory_access_path_to_location_entity(), copy_reference(), ENDP, ENTITY, entity_undefined_p, entity_user_name(), free_reference(), gen_free_list(), gen_full_copy_list(), gen_nconc(), NIL, pl, reference_indices, reference_to_string(), semantics_user_warning, substitute_scalar_stub_in_transformer(), and transformer_projection().

Referenced by new_array_elements_backward_substitution_in_transformer().

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

◆ new_array_elements_backward_substitution_in_transformer()

transformer new_array_elements_backward_substitution_in_transformer ( transformer  ,
entity  ,
type  ,
expression  ,
transformer  ,
list   
)

◆ new_array_elements_forward_substitution_in_transformer()

transformer new_array_elements_forward_substitution_in_transformer ( transformer  ,
entity  ,
type  ,
expression  ,
transformer  ,
list   
)

◆ new_array_elements_substitution_in_transformer()

transformer new_array_elements_substitution_in_transformer ( transformer  ,
entity  ,
type  ,
expression  ,
transformer  ,
list  ,
bool   
)

◆ new_complete_whileloop_transformer()

transformer new_complete_whileloop_transformer ( transformer  t_body_star,
transformer  pre,
whileloop  wl,
bool  entered_p 
)

entered_p is used to for the execution of at least one iteration

Parameters
t_body_star_body_star
prere
wll
entered_pntered_p

Definition at line 1833 of file loop.c.

1837 {
1838  list tfl =
1839  new_complete_whileloop_transformer_list(t_body_star, pre, wl, entered_p);
1841  // tfl is destroyed by transformer_list_to_transformer()
1842  return ct;
1843 }

References new_complete_whileloop_transformer_list(), and transformer_list_to_transformer().

Referenced by complete_whileloop_transformer(), and generic_complete_statement_transformer().

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

◆ new_complete_whileloop_transformer_list()

list new_complete_whileloop_transformer_list ( transformer  ,
transformer  ,
whileloop  ,
bool   
)

◆ new_loop_to_transformer()

transformer new_loop_to_transformer ( loop  l,
transformer  pre,
list  lel 
)

loop_to_transformer() was developed first but is not as powerful as the new algorithm used for all kinds of loops.

See flip-flop01.c.

Equation:

t_body_star = t_init ; t_enter ;(t_body ; t_inc; t_continue)*

t_init, t_enter and t_continue, which includes t_inc, must be computed from the loop and its precondition, pre, and extended body effects, lel. In case the loop index appears in the bound or increment expressions, the Fortran standard should be used to determine the precondition to use. The same is true in case of side-effects in the loop expressions.

t_body must be computed from the loop body and a preliminary loop invariant.

Deal with initialization expression, which may be included in the condition as in while(i++, j=0, i<m)? No because the expression is going to be evaluated at each cycle. The ised effects must be part of the condition transformer, tcond

Deal with enter transformers

An effort could be made to compute the precondition for t_continue. Precondition pre and the loop effect list lel could be used.

approximate loop transformer, including loop index updates

first approximation of the loop body precondition

FI: could do better with body_transformer

Let's clean up the memory

Parameters
prere
lelel

Definition at line 1516 of file loop.c.

1518 {
1519  /* Equation:
1520  *
1521  * t_body_star = t_init ; t_enter ;(t_body ; t_inc; t_continue)*
1522  *
1523  * t_init, t_enter and t_continue, which includes t_inc, must be
1524  * computed from the loop and its precondition, pre, and extended
1525  * body effects, lel. In case the loop index appears in the bound or
1526  * increment expressions, the Fortran standard should be used to
1527  * determine the precondition to use. The same is true in case of
1528  * side-effects in the loop expressions.
1529  *
1530  * t_body must be computed from the loop body and a preliminary loop
1531  * invariant.
1532  */
1533  transformer t_body_star = transformer_undefined;
1534  statement body_s = loop_body(l);
1535 
1536  /* Deal with initialization expression, which may be included in
1537  the condition as in while(i++, j=0, i<m)? No because the
1538  expression is going to be evaluated at each cycle. The ised
1539  effects must be part of the condition transformer, tcond */
1541  // FI Memory leak
1542  transformer post_i = transformer_range(transformer_apply(t_init, pre));
1543 
1544  /* Deal with enter transformers */
1545  transformer t_enter = loop_to_enter_transformer(l, post_i);
1546  transformer pre_b = transformer_apply(t_enter, post_i);
1547 
1548  /* An effort could be made to compute the precondition for t_continue.
1549  * Precondition pre and the loop effect list lel could be used.
1550  */
1551  //transformer p_continue = transformer_identity();
1552  /* approximate loop transformer, including loop index updates */
1553  transformer abtf = effects_to_transformer(lel);
1554  /* first approximation of the loop body precondition */
1555  // invariant_wrt_transformer() seems to add arguments to the
1556  // filtered precondition...
1557  // FI: memory leak
1558  transformer p_continue = transformer_range(invariant_wrt_transformer(pre_b, abtf));
1559  /* FI: could do better with body_transformer */
1560  transformer t_continue = loop_to_continue_transformer(l, p_continue);
1561 
1562  t_body_star = any_loop_to_transformer(t_init, t_enter, t_continue, body_s, lel, pre_b);
1563 
1564  /* Let's clean up the memory */
1565 
1566  free_transformer(p_continue);
1567  free_transformer(t_enter);
1568  free_transformer(t_continue);
1569  free_transformer(post_i);
1570  free_transformer(pre_b);
1571 
1572  return t_body_star;
1573 }
transformer loop_to_continue_transformer(loop l, transformer pre)
Definition: loop.c:1501
transformer loop_to_initialization_transformer(loop l, transformer pre)
Transformer expression the loop initialization.
Definition: loop.c:1430

References any_loop_to_transformer(), effects_to_transformer(), free_transformer(), invariant_wrt_transformer(), loop_body, loop_to_continue_transformer(), loop_to_enter_transformer(), loop_to_initialization_transformer(), transformer_apply(), transformer_range(), and transformer_undefined.

+ Here is the call graph for this function:

◆ new_substitute_stubs_in_transformer()

transformer new_substitute_stubs_in_transformer ( transformer  tf,
call  c,
statement  s,
bool  backward_p 
)

This leads to an empty transformer because the statement is unreachable. Some kind of dereferencement error has occured earlier in the execution

Parameters
tff
backward_packward_p

Definition at line 417 of file points_to.c.

418 {
419  if(pt_to_list_undefined_p()) {
420  // Return tf as is
421  }
422  else {
424  bool bottom_p = points_to_graph_bottom(ptg);
425 
426  if(bottom_p) {
427  /* This leads to an empty transformer because the statement is
428  * unreachable. Some kind of dereferencement error has occured
429  * earlier in the execution
430  */
431  free_transformer(tf);
432  tf = transformer_empty();
433  }
434  else {
436  pt_map binding_g = make_points_to_graph(false, binding);
437  tf = substitute_stubs_in_transformer_with_translation_binding(tf, binding_g, backward_p);
438  free_points_to_graph(binding_g);
439  }
440  }
441  return tf;
442 }
void free_points_to_graph(points_to_graph p)
points_to_graph make_points_to_graph(bool a1, set a2)
#define points_to_graph_bottom(x)
static transformer substitute_stubs_in_transformer_with_translation_binding(transformer tf, pt_map binding_g, bool backward_p)
Definition: points_to.c:375
points_to_graph get_points_to_graph_from_statement(_UNUSED_ statement st)
Interface with points-to library.
Definition: points_to.c:56
set user_call_to_points_to_interprocedural_binding_set(call c, pt_map pt_caller)
Compute the binding relations in a complete interprocedural way: be as accurate as possible.
Definition: points_to.c:79

References free_points_to_graph(), free_transformer(), get_points_to_graph_from_statement(), make_points_to_graph(), points_to_graph_bottom, pt_to_list_undefined_p(), substitute_stubs_in_transformer_with_translation_binding(), transformer_empty(), and user_call_to_points_to_interprocedural_binding_set().

Referenced by c_user_call_to_transformer().

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

◆ new_whileloop_to_k_transformer()

transformer new_whileloop_to_k_transformer ( whileloop  wl,
transformer  pre,
list  wlel,
int  k 
)

t_body_star = t_init ; t_enter ;(t_body ; t_next)*

Deal with initialization expression

Deal with condition expression

An effort could be made to compute the precondition for t_continue.

Let's clean up the memory

Parameters
wll
prere
wlellel
keffects of whileloop wl

Definition at line 416 of file loop.c.

422 {
423  /* t_body_star = t_init ; t_enter ;(t_body ; t_next)* */
424  transformer t_body_star = transformer_undefined;
425  statement body_s = whileloop_body(wl);
426 
427  /* Deal with initialization expression */
429 
430  /* Deal with condition expression */
431  expression cond_e = whileloop_condition(wl);
432  transformer t_enter = condition_to_transformer(cond_e, pre, true);
433  /* An effort could be made to compute the precondition for t_continue. */
434  transformer p_continue = transformer_identity();
435  transformer t_continue = condition_to_transformer(cond_e, p_continue, true);
436 
437  t_body_star = any_loop_to_k_transformer(t_init, t_enter, t_continue, body_s, wlel, pre, k);
438 
439  /* Let's clean up the memory */
440 
441  free_transformer(p_continue);
442 
443  free_transformer(t_enter);
444  free_transformer(t_continue);
445 
446  return t_body_star;
447 }
#define whileloop_body(x)
Definition: ri.h:3162
#define whileloop_condition(x)
Definition: ri.h:3160
transformer any_loop_to_k_transformer(transformer t_init, transformer t_enter, transformer t_next, statement body, list __attribute__((unused)) lel, transformer post_init, int k)
Processing of loops for transformers, preconditions and transformer lists.
Definition: loop.c:203

References any_loop_to_k_transformer(), condition_to_transformer(), free_transformer(), transformer_identity(), transformer_undefined, whileloop_body, and whileloop_condition.

Referenced by whileloop_to_k_transformer().

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

◆ new_whileloop_to_transformer()

transformer new_whileloop_to_transformer ( whileloop  wl,
transformer  pre,
list  wlel 
)

effects of whileloop wl

Equation:

t_body_star = t_init ; t_enter ;(t_body ; t_continue)*

Deal with initialization expression, which may be included in the condition as in while(i++, j=0, i<m)? No because the expression is going to be evaluated at each cycle. The ised effects must be part of the condition transformer, tcond

Deal with condition expression

An effort could be made to compute the precondition for t_continue.

Let's clean up the memory

Parameters
wll
prere
wlellel

Definition at line 380 of file loop.c.

383 {
384  /* Equation:
385  *
386  * t_body_star = t_init ; t_enter ;(t_body ; t_continue)*
387  */
388  transformer t_body_star = transformer_undefined;
389  statement body_s = whileloop_body(wl);
390 
391  /* Deal with initialization expression, which may be included in
392  the condition as in while(i++, j=0, i<m)? No because the
393  expression is going to be evaluated at each cycle. The ised
394  effects must be part of the condition transformer, tcond */
396 
397  /* Deal with condition expression */
398  expression cond_e = whileloop_condition(wl);
399  transformer t_enter = condition_to_transformer(cond_e, pre, true);
400  /* An effort could be made to compute the precondition for t_continue. */
401  transformer p_continue = transformer_identity();
402  transformer t_continue = condition_to_transformer(cond_e, p_continue, true);
403 
404  t_body_star = any_loop_to_transformer(t_init, t_enter, t_continue, body_s, wlel, pre);
405 
406  /* Let's clean up the memory */
407 
408  free_transformer(p_continue);
409 
410  free_transformer(t_enter);
411  free_transformer(t_continue);
412 
413  return t_body_star;
414 }

References any_loop_to_transformer(), condition_to_transformer(), free_transformer(), transformer_identity(), transformer_undefined, whileloop_body, and whileloop_condition.

Referenced by whileloop_to_transformer().

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

◆ non_empty_range_wrt_precondition_p()

bool non_empty_range_wrt_precondition_p ( range  r,
transformer  p 
)

Definition at line 121 of file utils.c.

122 {
123  bool non_empty = false;
124 
125  non_empty = check_range_wrt_precondition(r, p, false);
126 
127  return non_empty;
128 }

References check_range_wrt_precondition().

Referenced by complete_loop_transformer(), complete_loop_transformer_list(), loop_to_postcondition(), and loop_to_total_precondition().

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

◆ number_of_usable_functional_parameters()

unsigned int number_of_usable_functional_parameters ( list  pl)

Number of formal parameters in pl before a vararg is reached.

The varargs are not analyzed.

Parameters
pll

Definition at line 1518 of file ri_to_transformers.c.

1519 {
1520  int n = 0;
1521  bool void_p = false;
1522  FOREACH(PARAMETER, p, pl) {
1523  type lpt = ultimate_type(parameter_type(p));
1524  if(type_void_p(lpt))
1525  void_p = true;
1526  else if(type_varargs_p(lpt))
1527  break;
1528  else
1529  n++;
1530  }
1531  if(void_p && n!=0)
1532  pips_internal_error("Inconsistent internal representation: \"void\" type used among several formal parameters.\n");
1533  return n;
1534 }
#define parameter_type(x)
Definition: ri.h:1819
#define PARAMETER(x)
PARAMETER.
Definition: ri.h:1788
#define type_varargs_p(x)
Definition: ri.h:2953

References FOREACH, PARAMETER, parameter_type, pips_internal_error, pl, type_varargs_p, type_void_p, and ultimate_type().

Referenced by any_user_call_site_to_transformer().

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

◆ old_complete_whileloop_transformer()

transformer old_complete_whileloop_transformer ( transformer  ltf,
transformer  pre,
whileloop  l 
)

loop body transformer

Recompute the exact loop body transformer. This is weird: it should have already been done by statement_to_transformer and propagated bask. However, we need to recompute it because it has not been stored and cannot be retrieved. It might be better to use complete_statement_transformer(retrieved t, preb, s).

Since it is not stored, we need to go down recursively. A way to avoid this would be to always have sequences as loop bodies... Let's hope that perfectly nested loops are neither frequent nor deep!

The proper transformer has been stored.

btf = transformer_add_condition_information(btf, cond, preb, true);

add the exit condition

add initialization for the unconditional initialization of the loop index variable

It might be better not to compute useless transformer, but it's more readable that way. Since pre is information free, only loops with constant lower and upper bound and constant increment can benefit from this.

Parameters
ltftf
prere

Definition at line 2213 of file loop.c.

2216 {
2220  /* loop body transformer */
2222  expression cond = whileloop_condition(l);
2223  statement s = whileloop_body(l);
2224  transformer preb = invariant_wrt_transformer(pre, ltf);
2225 
2226  pips_debug(8,"begin with whileloop precondition\n");
2227  ifdebug(8) {
2228  (void) print_transformer(pre);
2229  pips_debug(8,"and whileloop transformer:\n");
2230  (void) print_transformer(ltf);
2231  }
2232 
2233  /* Recompute the exact loop body transformer. This is weird: it
2234  should have already been done by statement_to_transformer and
2235  propagated bask. However, we need to recompute it because it has
2236  not been stored and cannot be retrieved. It might be better to
2237  use complete_statement_transformer(retrieved t, preb, s). */
2238  if(statement_loop_p(s)) {
2239  /* Since it is not stored, we need to go down recursively. A way to
2240  avoid this would be to always have sequences as loop
2241  bodies... Let's hope that perfectly nested loops are neither
2242  frequent nor deep! */
2245  }
2246  else if(statement_whileloop_p(s)) {
2249  }
2250  else { /* The proper transformer has been stored. */
2252  }
2253 
2254  /* btf = transformer_add_condition_information(btf, cond, preb, true); */
2255  t_enter = transformer_combine(transformer_dup(ltf), btf);
2256 
2257  ifdebug(8) {
2258  pips_debug(8, "entered loop transformer t_enter=\n");
2260  }
2261 
2262  /* add the exit condition */
2263  t_enter = transformer_add_condition_information(t_enter, cond, preb, false);
2264 
2265  ifdebug(8) {
2266  pips_debug(8, "entered and exited loop transformer t_enter=\n");
2268  }
2269 
2270  /* add initialization for the unconditional initialization of the loop
2271  index variable */
2272  t_skip = transformer_undefined_p(pre)?
2274  transformer_dup(pre);
2275  t_skip = transformer_add_condition_information(t_skip, cond, pre, false);
2276 
2277  ifdebug(8) {
2278  pips_debug(8, "skipped loop transformer t_skip=\n");
2280  }
2281 
2282  /* It might be better not to compute useless transformer, but it's more
2283  readable that way. Since pre is information free, only loops with
2284  constant lower and upper bound and constant increment can benefit
2285  from this. */
2287  tf = t_skip;
2288  free_transformer(t_enter);
2289  }
2290  else if(!transformer_undefined_p(pre) && condition_true_wrt_precondition_p(cond, pre)) {
2291  tf = t_enter;
2292  free_transformer(t_skip);
2293  }
2294  else {
2295  tf = transformer_convex_hull(t_enter, t_skip);
2296  free_transformer(t_enter);
2297  free_transformer(t_skip);
2298  }
2299 
2300  ifdebug(8) {
2301  pips_debug(8, "full refined loop transformer tf=\n");
2303  pips_debug(8, "end\n");
2304  }
2305 
2306  return tf;
2307 }
bool statement_whileloop_p(statement)
Definition: statement.c:354
transformer complete_whileloop_transformer(transformer ltf, transformer pre, whileloop wl)
FI: I'm not sure this function is useful.
Definition: loop.c:2183
bool condition_true_wrt_precondition_p(expression, transformer)
A condition cannot be tested exactly wrt a precondition You can try to prove that it is always true (...
Definition: utils.c:276
bool condition_false_wrt_precondition_p(expression, transformer)
Definition: utils.c:285

References complete_loop_transformer(), complete_whileloop_transformer(), condition_false_wrt_precondition_p(), condition_true_wrt_precondition_p(), external_value_name(), fprint_transformer(), free_transformer(), ifdebug, instruction_loop, instruction_whileloop, invariant_wrt_transformer(), load_statement_transformer(), pips_debug, print_transformer, statement_instruction, statement_loop_p(), statement_whileloop_p(), transformer_add_condition_information(), transformer_combine(), transformer_convex_hull(), transformer_dup(), transformer_identity(), transformer_undefined, transformer_undefined_p, whileloop_body, and whileloop_condition.

+ Here is the call graph for this function:

◆ old_summary_precondition()

bool old_summary_precondition ( char *  module_name)

do not nothing because it has been computed by side effects; or provide an empty precondition for root modules; maybe a touch to look nicer?

touch it

Parameters
module_nameodule_name

Definition at line 500 of file dbm_interface.c.

501 {
502  /* do not nothing because it has been computed by side effects;
503  * or provide an empty precondition for root modules;
504  * maybe a touch to look nicer?
505  */
506 
507  transformer t;
508 
510 
511  debug(8, "summary_precondition", "begin\n");
512 
513  if(db_resource_p(DBR_SUMMARY_PRECONDITION, module_name)) {
514  /* touch it */
515  t = (transformer) db_get_memory_resource(DBR_SUMMARY_PRECONDITION,
516  module_name,
517  true);
518  }
519  else {
520  t = transformer_identity();
521  }
522 
523  DB_PUT_MEMORY_RESOURCE(DBR_SUMMARY_PRECONDITION,
524  module_name, (char * )t);
525 
526  ifdebug(8) {
527  pips_debug(8, "initial summary precondition %p for %s:\n",
528  t, module_name);
529  dump_transformer(t);
530  pips_debug(8, "end\n");
531  }
532 
533  debug_off();
534 
535  return true;
536 }

References db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, db_resource_p(), debug(), debug_off, debug_on, dump_transformer, ifdebug, module_name(), pips_debug, SEMANTICS_DEBUG_LEVEL, and transformer_identity().

+ Here is the call graph for this function:

◆ path_initialize()

void path_initialize ( statement  ,
statement  ,
statement  ,
path ,
path  
)

path_transformer.c

Referenced by sequence_dg().

+ Here is the caller graph for this function:

◆ path_transformer()

bool path_transformer ( const  string)
Parameters
stringodule_name

◆ path_transformer_on()

transformer path_transformer_on ( statement  ,
path  ,
path  ,
int   
)

◆ pointer_expression_to_transformer()

transformer pointer_expression_to_transformer ( entity  v,
expression  expr,
transformer  pre,
bool  is_internal 
)

This function may return an undefined transformers if it fails to capture the semantics of expr in the polyhedral framework. cf any_expression_to_transformer which call it

Parameters
vvalue of the expression
exprpointer expression
pretransformer, no side effect
is_internal?? use in generic_reference_to_transformer
Returns
transformer with the pointer expression or transformer_undefined if failed

Assume: v is a value

Parameters
exprxpr
prere
is_internals_internal

Definition at line 4582 of file expression.c.

4586 {
4588  syntax sexpr = expression_syntax(expr);
4589 
4590  ifdebug(8) {
4591  pips_debug(8, "begin with precondition %p for expression: ", pre);
4592  print_expression(expr);
4593  }
4594 
4595  /* Assume: v is a value */
4596  switch (syntax_tag(sexpr)) {
4597  case is_syntax_call:
4598  {
4599  tf = transformer_undefined;
4600  tf = pointer_call_expression_to_transformer(v, expr, pre, is_internal);
4601  break;
4602  }
4603  case is_syntax_reference:
4604  {
4605  // pips_user_warning("reference for pointer analysis not be tested\n");
4606  // can occur for arithmetic for pointer
4607  reference rexpr = syntax_reference(sexpr);
4608 
4609  entity rvexpr = reference_variable(rexpr);
4610  type texpr = entity_type(rvexpr);
4611  type bctexpr = compute_basic_concrete_type(texpr);
4612  if(type_variable_p(bctexpr)) {
4613  variable vexpr = type_variable(bctexpr);
4614  if (!volatile_variable_p(vexpr)
4615  && ENDP(variable_dimensions(vexpr))
4616  && !basic_pointer_p(variable_basic(vexpr))) {
4617  // compute the multiply with sizeof
4618  tf = expression_multiply_sizeof_to_transformer(v, expr, pre, is_internal);
4619  }
4620  else
4621  tf = generic_reference_to_transformer(v, rexpr, pre, is_internal);
4622  }
4623  break;
4624  }
4625  case is_syntax_cast:
4626  {
4627  cast c = syntax_cast(sexpr);
4628  type ct = cast_type(c);
4629  expression cexp = cast_expression(c);
4630  type cexpt = expression_to_type(cexp);
4631 
4632  if (expression_null_p(expr)) {
4633  // make the transformer for the equality (take from generic_reference_to_transformer)
4635  if(!transformer_undefined_p(pre)) {
4636  // FI: assume pre is a range
4637  tf = transformer_intersection(tfr, pre);
4638  }
4639  free_transformer(tfr);
4640  } else {
4641  semantics_user_warning("Cast for pointer analysis not tested "
4642  "(except for NULL pointer).\n");
4643  if (type_equal_p(ct, cexpt))
4644  tf = pointer_expression_to_transformer(v, cexp, pre, is_internal);
4645  else
4646  tf = transformer_undefined;
4647  //pips_internal_error("Illegal tag %d", syntax_tag(sexpr));
4648  free_type(cexpt);
4649  }
4650  break;
4651  }
4652  default:
4653  tf = transformer_undefined;
4654  //pips_internal_error("Illegal tag %d", syntax_tag(sexpr));
4655  }
4656 
4657  pips_debug(8, "end with tf=%p\n", tf);
4658 
4659  return tf;
4660 }
entity null_pointer_value_entity(void)
bool expression_null_p(expression exp)
returns true if the expression is equal to zero or NULL (even if there is a cast before such as in (v...
Definition: expression.c:2611
bool volatile_variable_p(variable)
Definition: variable.c:1649
@ is_syntax_cast
Definition: ri.h:2694
static transformer pointer_call_expression_to_transformer(entity e, expression expr, transformer pre, bool is_internal)
Definition: expression.c:4495
static transformer expression_multiply_sizeof_to_transformer(entity v, expression e1, transformer prec, bool is_internal)
cut-and-pasted and adapted from multiply_to_transformer();
Definition: expression.c:2169

References basic_pointer_p, cast_expression, cast_type, compute_basic_concrete_type(), ENDP, entity_type, expression_multiply_sizeof_to_transformer(), expression_null_p(), expression_syntax, expression_to_type(), free_transformer(), free_type(), generic_reference_to_transformer(), ifdebug, is_syntax_call, is_syntax_cast, is_syntax_reference, null_pointer_value_entity(), pips_debug, pointer_call_expression_to_transformer(), print_expression(), reference_variable, semantics_user_warning, simple_equality_to_transformer(), syntax_cast, syntax_reference, syntax_tag, transformer_intersection(), transformer_undefined, transformer_undefined_p, type_equal_p(), type_variable, type_variable_p, variable_basic, variable_dimensions, and volatile_variable_p().

Referenced by any_expression_to_transformer().

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

◆ points_to_unary_operation_to_transformer()

transformer points_to_unary_operation_to_transformer ( entity  e,
entity  op,
expression  e1,
transformer  pre,
bool  is_internal,
bool  is_pointer 
)

This function is redundant with generic_unary_operation_to_transformer() except for its use of parameter is_pointer.

Parameters
opp
e11
prere
is_internals_internal
is_pointers_pointer

Definition at line 2770 of file expression.c.

2776 {
2777  pips_debug(8, "begin \n");
2779 
2780  if (!pt_to_list_undefined_p()) {
2781  // FI: may have to be adapted to implement ANALYZE_CONSTANT_PATHS
2782  //statement curstat = get_current_statement_from_statement_global_stack();
2783  //points_to_graph ptg = get_points_to_graph_from_statement(curstat);
2784 
2786  // compute the assignment for each cell pointed with the convex hull
2787  FOREACH(CELL, cp, l) {
2789  entity rhs = reference_variable(rrhs);
2790 
2791  if (!is_pointer && entity_null_locations_p(rhs)) {
2792  if (gen_length(l) == 1) {
2793  tf = transformer_empty();
2794  pips_user_error("The pointer %s points to NULL\n", expression_to_string(e1));
2795  }
2796  else {
2797  semantics_user_warning("The pointer %s can points to NULL\n", expression_to_string(e1));
2798  }
2799  } else if (entity_typed_nowhere_locations_p(rhs)) {
2800  if (gen_length(l) == 1) {
2801  tf = transformer_empty();
2802  pips_user_error("The pointer %s points to undefined/indeterminate (%s)\n", expression_to_string(e1), reference_to_string(rrhs));
2803  }
2804  else {
2805  semantics_user_warning("The pointer %s can points to undefined/indeterminate (%s)\n", expression_to_string(e1), reference_to_string(rrhs));
2806  }
2807  }
2808  else {
2809  // check if rrhs is a constant path and can be analyze or not
2810  // (not really exact, see detail in analyzed_reference_p)
2811  if (analyzed_reference_p(rrhs)) {
2812  transformer rt = generic_reference_to_transformer(e, rrhs, pre, is_internal);
2813  // NL : It must have be a better way to do that but I don't know how
2814  if (transformer_undefined_p(tf))
2815  tf = rt;
2816  else {
2817  tf = transformer_convex_hull(tf, rt);
2818  free_transformer(rt);
2819  }
2820  }
2821  }
2822  }
2823  }
2824 
2825  if (transformer_undefined_p(tf)) {
2827  if(test_warning_counters()) {
2828  extern bool active_phase_p(const char *);
2829  if(active_phase_p("TRANSFORMERS_INTER_FULL_WITH_POINTS_TO")) {
2830  if(get_bool_property("SEMANTICS_ANALYZE_CONSTANT_PATH"))
2831  ;
2832  else
2833  semantics_user_warning("Set property SEMANTICS_ANALYZE_CONSTANT_PATH TRUE."
2834  " It might generate more accurate transformers.\n");
2835  }
2836  else {
2837  if(get_bool_property("SEMANTICS_ANALYZE_CONSTANT_PATH"))
2838  semantics_user_warning("Activate TRANSFORMERS_INTER_FULL_WITH_POINTS_TO."
2839  " It might generate more accurate transformers.\n");
2840  else
2841  semantics_user_warning("Activate TRANSFORMERS_INTER_FULL_WITH_POINTS_TO and "
2842  "setproperty SEMANTICS_ANALYZE_CONSTANT_PATH TRUE."
2843  " It might generate more accurate transformers.\n");
2844  }
2845  }
2846  }
2847  }
2848 
2849  ifdebug (8) dump_transformer(tf);
2850  pips_debug(8, "end \n");
2851  return tf;
2852 }
bool active_phase_p(const char *phase)
Definition: activate.c:80
bool test_warning_counters(void)
#define ENTITY_DEREFERENCING_P(e)
list semantics_expression_to_points_to_sinks(expression e)
Returns a list of cells.
Definition: points_to.c:112

References active_phase_p(), analyzed_reference_p(), CELL, cell_preference, cell_preference_p, cell_reference, cp, dump_transformer, ENTITY_DEREFERENCING_P, ENTITY_FIELD_P, entity_null_locations_p(), ENTITY_POINT_TO_P, entity_typed_nowhere_locations_p(), expression_to_string(), FOREACH, free_transformer(), gen_length(), generic_reference_to_transformer(), get_bool_property(), ifdebug, pips_debug, pips_user_error, preference_reference, pt_to_list_undefined_p(), reference_to_string(), reference_variable, semantics_expression_to_points_to_sinks(), semantics_user_warning, test_warning_counters(), transformer_convex_hull(), transformer_empty(), transformer_undefined, and transformer_undefined_p.

+ Here is the call graph for this function:

◆ postcondition_map_undefined_p()

bool postcondition_map_undefined_p ( void  )

◆ precondition_add_condition_information()

transformer precondition_add_condition_information ( transformer  pre,
expression  c,
transformer  context,
bool  veracity 
)

context might be derivable from pre as transformer_range(pre) but this is sometimes very computationally intensive, e.g.

in ocean.

Parameters
prere
contextontext
veracityeracity

Definition at line 1111 of file expression.c.

1116 {
1118 
1122  (pre, c, context, veracity, false);
1123  }
1124  else {
1125  transformer new_context = transformer_range(context);
1126 
1128  (pre, c, new_context, veracity, false);
1129  free_transformer(new_context);
1130  }
1131 
1134 
1135  return post;
1136 }

References ENDP, free_transformer(), reset_temporary_value_counter(), transformer_add_condition_information_updown(), transformer_arguments, transformer_range(), transformer_temporary_value_projection(), transformer_undefined, and transformer_undefined_p.

Referenced by dag_to_flow_sensitive_preconditions(), eval_condition_wrt_precondition_p(), load_arc_precondition(), process_ready_node(), standard_whileloop_to_transformer(), transformer_add_range_condition(), unstructured_to_postconditions(), whileloop_to_postcondition(), and whileloop_to_total_precondition().

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

◆ precondition_add_reference_information()

void precondition_add_reference_information ( transformer  pre,
statement  s 
)
Parameters
prere

Definition at line 695 of file ri_to_preconditions.c.

696 {
697  add_reference_information(pre, s, false);
698 }
static void add_reference_information(transformer pre, statement s, bool renaming)
Assume that all references are legal.

References add_reference_information().

Referenced by statement_to_postcondition().

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

◆ precondition_add_type_information()

void precondition_add_type_information ( transformer  pre)
Parameters
prere

Definition at line 705 of file ri_to_preconditions.c.

706 {
708 }

References transformer_add_type_information().

+ Here is the call graph for this function:

◆ precondition_filter_old_values()

transformer precondition_filter_old_values ( transformer  pre)
Parameters
prere

Definition at line 1065 of file loop.c.

1066 {
1068  Pbase b = BASE_UNDEFINED;
1069 
1070  for(b = sc_base(sc); !BASE_NULLE_P(b); b = vecteur_succ(b)) {
1071  entity old_v = (entity) vecteur_var(b);
1072 
1073  if(old_value_entity_p(old_v)) {
1074  pips_assert("No old values are left", false);
1075  }
1076  }
1077 
1078  return pre;
1079 }
bool old_value_entity_p(entity)
Definition: value.c:936
#define vecteur_succ(v)
#define BASE_NULLE_P(b)

References BASE_NULLE_P, BASE_UNDEFINED, old_value_entity_p(), pips_assert, predicate_system, transformer_relation, vecteur_succ, and vecteur_var.

+ Here is the call graph for this function:

◆ precondition_intra_to_inter()

transformer precondition_intra_to_inter ( entity  callee,
transformer  pre,
list  le 
)

precondition cannot be printed because equations linking formal parameters have been added to the real precondition

make sure you do not export a (potentially) meaningless old value

Thru DATA statements, old values of other modules may appear

get rid of old_values

sc_elim_redund

no_elim

get rid of pre's variables that do not appear in effects le

we should not have to know about these internal objects, Psysteme and Pvecteur!

build a list of values to suppress

get rid of variables that are not referenced, directly or indirectly, by the callee; translate what you can

For clarity, all cases are presented

No need to substitute or eliminate this value

This is a short term improvement for partial_eval01-02 that works only for values local to the callee not for values updated indirectedly by callees of "callee".

It resulted in many core dumps in array privatization

no conflicts

list of conflicting entities

case 1: only one entity

case 1.1: one conflicting integer entity

Type mismatch

case 1.22: one conflicting non analyzable scalar entity

case 2: at least 2 conflicting entities

case 2.1: all entities have the same type, according to mapping_values the subtitution is made with the first list element e_callee

case 2.2: all entities do not have the same type

Get rid of variables local to the caller

Get rid of unused or untouched variables, even though they may appear as global variables or formal parameters

This happens with automatically generated modules and for routine XERCLT in KIVA (Renault) because it has been emptied.

No information but feasibility can be preserved

Get rid of the basis and arguments to define the empty set

No information: the all value space is OK

sc_elim_redund

no_elim

free the temporary list of entities

get rid of arguments because they are meaningless for a module precondition: v_new == v_old by definition

Parameters
calleeallee
prere
lee

Definition at line 395 of file interprocedural.c.

398 {
399 #define DEBUG_PRECONDITION_INTRA_TO_INTER 1
400  list values = NIL;
401  list lost_values = NIL;
402  list preserved_values = NIL;
403  Psysteme r;
404  Pbase b;
405  cons * ca;
406 
408  {
410  "begin for call to %s\nwith precondition:\n",
412  /* precondition cannot be printed because equations linking formal
413  * parameters have been added to the real precondition
414  */
415  dump_transformer(pre);
416  }
417 
419 
420  /* make sure you do not export a (potentially) meaningless old value */
421  for( ca = transformer_arguments(pre); !ENDP(ca); POP(ca) )
422  {
423  entity e = ENTITY(CAR(ca));
424  entity e_old;
425 
426  /* Thru DATA statements, old values of other modules may appear */
430  "entitiy %s not belonging to module %s\n",
431  entity_name(e),
433  }
434 
435  e_old = entity_to_old_value(e);
436 
437  if(base_contains_variable_p(sc_base(r), (Variable) e_old))
438  lost_values = arguments_add_entity(lost_values,
439  e_old);
440  }
441 
443  {
445  "meaningless old value(s):\n");
446  dump_arguments(lost_values);
447  }
448 
449  /* get rid of old_values */
451  (pre, lost_values, /* sc_elim_redund */ /* no_elim */ sc_safe_normalize);
452 
453  gen_free_list(lost_values);
454 
455 
457 
458  /* get rid of pre's variables that do not appear in effects le */
459  /* we should not have to know about these internal objects, Psysteme
460  and Pvecteur! */
461  lost_values = NIL;
463  for(b = r->base; b != NULL; b = b->succ) {
464  entity v = (entity) vecteur_var(b);
465 
466  if(!entity_constant_p(v))
467  values = arguments_add_entity(values, v);
468  }
469 
470  /* build a list of values to suppress*/
471  if(true || fortran_language_module_p(callee)) {
472  /* get rid of variables that are not referenced, directly or indirectly,
473  by the callee; translate what you can */
474  pips_debug(9, "Module effect list:");
475  ifdebug(9) print_effects(le);
476 
477  for(ca = values; !ENDP(ca); POP(ca)) {
478  entity e = ENTITY(CAR(ca));
479  // FI: concrete effects are now killed by abstract effects
480  list l_callee =
482  // FI: the association with an abstract effect kills the
483  // translation process below
484  // list l_callee = (list) effects_entities_which_may_conflict_with_scalar_entity(le, e);
485  /* For clarity, all cases are presented */
487  /* No need to substitute or eliminate this value */
488  /* This is a short term improvement for partial_eval01-02
489  that works only for values local to the callee not for
490  values updated indirectedly by callees of "callee". */
491  /* It resulted in many core dumps in array privatization */
492  ;
493  }
494  else if (ENDP(l_callee)) { /* no conflicts */
495  lost_values = arguments_add_entity(lost_values, e);
497  "value %s lost according to effect list\n",
498  entity_name(e));
499  }
500  else {
501  /* list of conflicting entities */
502  entity e_callee = ENTITY(CAR(l_callee));
503  /* case 1: only one entity*/
504  if (gen_length(l_callee)==1) {
505  /* case 1.1: one conflicting integer entity */
506  if (analyzable_scalar_entity_p(e_callee)) {
507  if(e_callee != e) {
508  if(type_equal_p(entity_type(e_callee), entity_type(e))) {
510  e, e_callee);
513  "value %s substituted by %s according to effect list le:\n",
514  entity_name(e), entity_name(e_callee));
515  dump_arguments(lost_values);
516  }
517  }
518  else {
519  /* Type mismatch */
520  lost_values = arguments_add_entity(lost_values, e);
522  "value %s lost because non analyzable scalar entity\n",
523  entity_name(e));
524  }
525  }
526  }
527  /* case 1.22: one conflicting non analyzable scalar entity*/
528  else {
529  lost_values = arguments_add_entity(lost_values, e);
531  "value %s lost because non analyzable scalar entity\n",
532  entity_name(e));
533  }
534  }
535  else { /* case 2: at least 2 conflicting entities */
537  /* case 2.1: all entities have the same type,
538  according to mapping_values the subtitution
539  is made with the first list element e_callee*/
540  if(e_callee != e) {
542  e, e_callee);
545  "value %s substituted by %s the first element list according to effect list le:\n",
546  entity_name(e), entity_name(e_callee));
547  dump_arguments(lost_values);
548  }
549  }
550  }
551 
552  else { /* case 2.2: all entities do not have the same type*/
553  lost_values = arguments_add_entity(lost_values, e);
555  "value %s lost - list of conflicting entities with different types\n",
556  entity_name(e));
557  }
558  }
559  }
560 
561  }
562  }
563  else if(false && c_language_module_p(callee)) {
564  /* Get rid of variables local to the caller */
565  ;
566  }
567 
568  preserved_values = arguments_difference(values, lost_values);
569 
572  "values lost because they do not appear in the effect list le:\n");
573  dump_arguments(lost_values);
575  "values preserved because they do appear in the effect list le"
576  " and in the transformer basis:\n");
577  dump_arguments(preserved_values);
578  }
579 
580  /* Get rid of unused or untouched variables, even though they may
581  * appear as global variables or formal parameters
582  *
583  * This happens with automatically generated modules and for routine
584  * XERCLT in KIVA (Renault) because it has been emptied.
585  *
586  */
587  if(ENDP(preserved_values)) {
588  /* No information but feasibility can be preserved */
589  if(transformer_empty_p(pre)) {
590  /* Get rid of the basis and arguments to define the empty set */
591  free_transformer(pre);
592  pre = transformer_empty();
593  }
594  else{
595  /* No information: the all value space is OK */
596  free_transformer(pre);
597  pre = transformer_identity();
598  }
599  }
600  else {
602  (pre, lost_values, /* sc_elim_redund */ /* no_elim */ sc_safe_normalize);
603  }
604 
605  /* free the temporary list of entities */
606  gen_free_list(preserved_values);
607  gen_free_list(lost_values);
608  gen_free_list(values);
609 
610  /* get rid of arguments because they are meaningless for
611  a module precondition: v_new == v_old by definition */
613  transformer_arguments(pre) = NIL;
614 
617  "return pre=%p\n",pre);
618  dump_transformer(pre);
620  }
621 
622  return pre;
623 }
void dump_arguments(cons *args)
entity_name is a macro, hence the code replication
Definition: arguments.c:69
cons * arguments_difference(cons *a1, cons *a2)
set difference: a1 - a2 ; similar to set intersection
Definition: arguments.c:233
list concrete_effects_entities_which_may_conflict_with_scalar_entity(list fx, entity e)
Definition: conflicts.c:1278
#define same_string_p(s1, s2)
struct cons * list
Definition: newgen_types.h:106
bool local_entity_of_module_p(entity e, entity module)
This test shows that "e" has been declared in "module".
Definition: entity.c:1069
const char * entity_module_name(entity e)
See comments about module_name().
Definition: entity.c:1092
bool fortran_language_module_p(entity m)
Definition: module.c:452
Psysteme sc_safe_normalize(Psysteme ps)
Psysteme sc_safe_normalize(Psysteme ps) output : ps, normalized.
bool same_analyzable_type_scalar_entity_list_p(list l)
#define DEBUG_PRECONDITION_INTRA_TO_INTER
transformer transformer_projection_with_redundancy_elimination(transformer t, list args, Psysteme(*elim)(Psysteme))
It is not clear if this function projects values or variables.
Definition: transformer.c:1322

References analyzable_scalar_entity_p(), arguments_add_entity(), arguments_difference(), Ssysteme::base, base_contains_variable_p(), c_language_module_p(), callee, CAR, concrete_effects_entities_which_may_conflict_with_scalar_entity(), DEBUG_PRECONDITION_INTRA_TO_INTER, dump_arguments(), dump_transformer, ENDP, ENTITY, entity_constant_p, entity_module_name(), entity_name, entity_to_old_value(), entity_type, fortran_language_module_p(), free_transformer(), gen_free_list(), gen_length(), get_current_module_entity(), ifdebug, local_entity_of_module_p(), module_local_name(), NIL, pips_debug, POP, predicate_system, print_effects, same_analyzable_type_scalar_entity_list_p(), same_string_p, sc_safe_normalize(), Svecteur::succ, transformer_arguments, transformer_empty(), transformer_empty_p(), transformer_identity(), transformer_projection_with_redundancy_elimination(), transformer_relation, transformer_value_substitute(), translate_global_values(), type_equal_p(), and vecteur_var.

Referenced by add_module_call_site_precondition(), call_site_to_module_precondition_text(), and process_call_for_summary_precondition().

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

◆ precondition_map_undefined_p()

bool precondition_map_undefined_p ( void  )

◆ precondition_minmax_of_expression()

bool precondition_minmax_of_expression ( expression  exp,
transformer  tr,
intptr_t pmin,
intptr_t pmax 
)

compute integer bounds pmax, pmin of expression exp under preconditions tr require value mappings set !

create a temporary value

compute its preconditions

tidy & return

Parameters
expxp
trr
pminmin
pmaxmax

Definition at line 5818 of file expression.c.

5822 {
5823  bool success;
5824  /* create a temporary value */
5825  basic bas = basic_of_expression(exp);
5827  free_basic(bas);
5828 
5829  /* compute its preconditions */
5830  transformer var_tr = safe_any_expression_to_transformer(var,exp,tr,false);
5831  transformer pre = transformer_apply(var_tr, tr);
5832 
5833  //success = precondition_minmax_of_value(var, var_tr, pmin, pmax);
5834  success = precondition_minmax_of_value(var, pre, pmin, pmax);
5835 
5836  /* tidy & return */
5837  predicate_system(transformer_relation(var_tr))=SC_UNDEFINED;
5838  free_transformer(var_tr);
5839  free_entity(var);
5840  return success;
5841 }
void free_entity(entity p)
Definition: ri.c:2524
bool success
Definition: gpips-local.h:59

References basic_of_expression(), exp, free_basic(), free_entity(), free_transformer(), make_local_temporary_value_entity_with_basic(), precondition_minmax_of_value(), predicate_system, safe_any_expression_to_transformer(), transformer_apply(), and transformer_relation.

Referenced by bounds_of_expression(), integer_minmax_to_transformer(), integer_power_to_transformer(), partial_eval_min_or_max_operator(), and simplify_minmax_expression().

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

◆ precondition_minmax_of_value()

bool precondition_minmax_of_value ( entity  val,
transformer  tr,
intptr_t pmin,
intptr_t pmax 
)

compute integer bounds pmax, pmin of value val under preconditions tr require value mappings set !

retrieve the associated psysteme

compute min / max bounds

special case to handle VMIN and VMAX in 32 bits

Parameters
valal
trr
pminmin
pmaxmax

Definition at line 5790 of file expression.c.

5793 {
5794  bool success;
5795  /* retrieve the associated psysteme*/
5797  /* compute min / max bounds */
5798  Value vmin,vmax;
5799  if((success=sc_minmax_of_variable(ps,val,&vmin,&vmax)))
5800  {
5801  /* special case to handle VMIN and VMAX in 32 bits*/
5802  if(vmax != (Value)(intptr_t)(vmax) && vmax == VALUE_MAX) vmax= INT_MAX;
5803  if(vmin != (Value)(intptr_t)(vmin) && vmin == VALUE_MIN) vmin= INT_MIN;
5804  pips_assert("no data loss", vmin == (Value)(intptr_t)(vmin));
5805  pips_assert("no data loss", vmax == (Value)(intptr_t)(vmax));
5806  *pmin=(intptr_t)vmin;
5807  *pmax=(intptr_t)vmax;
5808  }
5809  // FI: ps is destroyed by sc_minmax_of_variable(). Should it
5810  // nevertheless be freed?
5811  return success;
5812 }
#define VALUE_MIN
#define VALUE_MAX

References intptr_t, pips_assert, predicate_system, sc_dup(), sc_minmax_of_variable(), transformer_relation, VALUE_MAX, and VALUE_MIN.

Referenced by add_type_information(), bitwise_xor_to_transformer(), integer_left_shift_to_transformer(), logical_binary_function_to_transformer(), logical_not_to_transformer(), modulo_by_a_constant_to_transformer(), and precondition_minmax_of_expression().

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

◆ preconditions_inter_fast()

bool preconditions_inter_fast ( char *  module_name)

set_int_property(SEMANTICS_DEBUG_LEVEL, 0);

Parameters
module_nameodule_name

Definition at line 435 of file dbm_interface.c.

436 {
443  /* set_int_property(SEMANTICS_DEBUG_LEVEL, 0); */
445 }
static void select_fix_point_operator()
bool module_name_to_preconditions(const char *module_name)
resource module_name_to_preconditions(char * module_name): compute a transformer for each statement o...
#define SEMANTICS_FLOW_SENSITIVE
#define SEMANTICS_STDOUT

References module_name(), module_name_to_preconditions(), select_fix_point_operator(), SEMANTICS_FIX_POINT, SEMANTICS_FLOW_SENSITIVE, SEMANTICS_INEQUALITY_INVARIANT, SEMANTICS_INTERPROCEDURAL, SEMANTICS_STDOUT, and set_bool_property().

+ Here is the call graph for this function:

◆ preconditions_inter_full()

bool preconditions_inter_full ( char *  module_name)

set_int_property(SEMANTICS_DEBUG_LEVEL, 0);

Parameters
module_nameodule_name

Definition at line 447 of file dbm_interface.c.

448 {
455  /* set_int_property(SEMANTICS_DEBUG_LEVEL, 0); */
457 }

References module_name(), module_name_to_preconditions(), select_fix_point_operator(), SEMANTICS_FIX_POINT, SEMANTICS_FLOW_SENSITIVE, SEMANTICS_INEQUALITY_INVARIANT, SEMANTICS_INTERPROCEDURAL, SEMANTICS_STDOUT, and set_bool_property().

+ Here is the call graph for this function:

◆ preconditions_inter_full_with_points_to()

bool preconditions_inter_full_with_points_to ( char *  module_name)

set_int_property(SEMANTICS_DEBUG_LEVEL, 0);

Parameters
module_nameodule_name

Definition at line 459 of file dbm_interface.c.

460 {
467  /* set_int_property(SEMANTICS_DEBUG_LEVEL, 0); */
469  db_get_memory_resource(DBR_POINTS_TO, module_name, true) );
470  bool result_p = module_name_to_preconditions(module_name);
472  return result_p;
473 }
void set_pt_to_list(statement_points_to)
void reset_pt_to_list(void)

References db_get_memory_resource(), module_name(), module_name_to_preconditions(), reset_pt_to_list(), select_fix_point_operator(), SEMANTICS_FIX_POINT, SEMANTICS_FLOW_SENSITIVE, SEMANTICS_INEQUALITY_INVARIANT, SEMANTICS_INTERPROCEDURAL, SEMANTICS_STDOUT, set_bool_property(), and set_pt_to_list().

+ Here is the call graph for this function:

◆ preconditions_intra()

bool preconditions_intra ( char *  module_name)

nothing to do: transformers are preconditions for this intraprocedural option

Maybe we should have an intra fast and an intra full as with other semantics entries

set_bool_property(SEMANTICS_FIX_POINT, false);

set_int_property(SEMANTICS_DEBUG_LEVEL, 0);

Parameters
module_nameodule_name

Definition at line 399 of file dbm_interface.c.

400 {
401  /* nothing to do: transformers are preconditions for this
402  intraprocedural option */
403 
406  /* Maybe we should have an intra fast and an intra full as with other
407  semantics entries */
408  /* set_bool_property(SEMANTICS_FIX_POINT, false); */
413  /* set_int_property(SEMANTICS_DEBUG_LEVEL, 0); */
415 }

References module_name(), module_name_to_preconditions(), select_fix_point_operator(), SEMANTICS_FIX_POINT, SEMANTICS_FLOW_SENSITIVE, SEMANTICS_INEQUALITY_INVARIANT, SEMANTICS_INTERPROCEDURAL, SEMANTICS_STDOUT, and set_bool_property().

+ Here is the call graph for this function:

◆ preconditions_intra_fast()

bool preconditions_intra_fast ( char *  module_name)

nothing to do: transformers are preconditions for this intraprocedural option

Maybe we should have an intra fast and an intra full as with other semantics entries

set_bool_property(SEMANTICS_FIX_POINT, false);

set_int_property(SEMANTICS_DEBUG_LEVEL, 0);

Parameters
module_nameodule_name

Definition at line 417 of file dbm_interface.c.

418 {
419  /* nothing to do: transformers are preconditions for this
420  intraprocedural option */
421 
424  /* Maybe we should have an intra fast and an intra full as with other
425  semantics entries */
426  /* set_bool_property(SEMANTICS_FIX_POINT, false); */
431  /* set_int_property(SEMANTICS_DEBUG_LEVEL, 0); */
433 }

References module_name(), module_name_to_preconditions(), select_fix_point_operator(), SEMANTICS_FIX_POINT, SEMANTICS_FLOW_SENSITIVE, SEMANTICS_INEQUALITY_INVARIANT, SEMANTICS_INTERPROCEDURAL, SEMANTICS_STDOUT, and set_bool_property().

+ Here is the call graph for this function:

◆ print_call_graph_with_preconditions()

bool print_call_graph_with_preconditions ( const  string)
Parameters
stringodule_name

Definition at line 712 of file prettyprint.c.

713 {
714  bool success = false;
716  return success;
717 }
bool print_decorated_call_graph(const string, text(*)(const string))
Definition: print.c:64
text get_text_preconditions(const string module_name)
Definition: prettyprint.c:193

References get_text_preconditions(), module_name(), and print_decorated_call_graph().

+ Here is the call graph for this function:

◆ print_call_graph_with_total_preconditions()

bool print_call_graph_with_total_preconditions ( const  string)
Parameters
stringodule_name

Definition at line 722 of file prettyprint.c.

723 {
724  bool success = false;
727  return success;
728 }
text get_text_total_preconditions(const string module_name)
Definition: prettyprint.c:203

References get_text_total_preconditions(), module_name(), and print_decorated_call_graph().

+ Here is the call graph for this function:

◆ print_call_graph_with_transformers()

bool print_call_graph_with_transformers ( const  string)
Parameters
stringodule_name

Definition at line 702 of file prettyprint.c.

703 {
704  bool success = false;
706  return success;
707 }
text get_text_transformers(const string module_name)
Definition: prettyprint.c:184

References get_text_transformers(), module_name(), and print_decorated_call_graph().

+ Here is the call graph for this function:

◆ print_code_as_a_graph_preconditions()

bool print_code_as_a_graph_preconditions ( const  string)
Parameters
stringod_name

Definition at line 120 of file prettyprint.c.

121 {
122  bool success;
123 
124  set_bool_property("PRETTYPRINT_UNSTRUCTURED_AS_A_GRAPH", true);
125  success = print_code_preconditions(mod_name);
126  set_bool_property("PRETTYPRINT_UNSTRUCTURED_AS_A_GRAPH", false);
127 
128  return success;
129 }
bool print_code_preconditions(const char *module_name)
Definition: prettyprint.c:110

References print_code_preconditions(), and set_bool_property().

+ Here is the call graph for this function:

◆ print_code_as_a_graph_total_preconditions()

bool print_code_as_a_graph_total_preconditions ( const  string)
Parameters
stringod_name

Definition at line 144 of file prettyprint.c.

145 {
146  bool success;
147 
148  set_bool_property("PRETTYPRINT_UNSTRUCTURED_AS_A_GRAPH", true);
150  set_bool_property("PRETTYPRINT_UNSTRUCTURED_AS_A_GRAPH", false);
151 
152  return success;
153 }
bool print_code_total_preconditions(const char *module_name)
Definition: prettyprint.c:131

References print_code_total_preconditions(), and set_bool_property().

+ Here is the call graph for this function:

◆ print_code_as_a_graph_transformers()

bool print_code_as_a_graph_transformers ( const  string)
Parameters
stringod_name

Definition at line 99 of file prettyprint.c.

100 {
101  bool success;
102 
103  set_bool_property("PRETTYPRINT_UNSTRUCTURED_AS_A_GRAPH", true);
104  success = print_code_transformers(mod_name);
105  set_bool_property("PRETTYPRINT_UNSTRUCTURED_AS_A_GRAPH", false);
106 
107  return success;
108 }
bool print_code_transformers(const char *module_name)
Definition: prettyprint.c:90

References print_code_transformers(), and set_bool_property().

+ Here is the call graph for this function:

◆ print_code_preconditions()

bool print_code_preconditions ( const char *  module_name)
Parameters
module_nameodule_name

Definition at line 110 of file prettyprint.c.

111 {
112  is_user_view = false;
113  is_transformer = false;
114  is_total_precondition = false;
116  get_bool_property("SEMANTICS_FILTERED_PRECONDITIONS");
118 }
static bool print_code_semantics()

References get_bool_property(), is_total_precondition, is_transformer, is_transformer_filtered, is_user_view, module_name(), and print_code_semantics().

Referenced by print_code_as_a_graph_preconditions().

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

◆ print_code_total_preconditions()

bool print_code_total_preconditions ( const char *  module_name)
Parameters
module_nameodule_name

Definition at line 131 of file prettyprint.c.

132 {
133  bool success;
134 
135  is_user_view = false;
136  is_transformer = false;
137  is_total_precondition = true;
139  get_bool_property("SEMANTICS_FILTERED_PRECONDITIONS");
141  return success;
142 }

References get_bool_property(), is_total_precondition, is_transformer, is_transformer_filtered, is_user_view, module_name(), and print_code_semantics().

Referenced by print_code_as_a_graph_total_preconditions().

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

◆ print_code_transformers()

bool print_code_transformers ( const char *  module_name)
Parameters
module_nameodule_name

Definition at line 90 of file prettyprint.c.

91 {
92  is_user_view = false;
93  is_transformer = true;
94  is_total_precondition = false;
97 }

References is_total_precondition, is_transformer, is_transformer_filtered, is_user_view, module_name(), and print_code_semantics().

Referenced by print_code_as_a_graph_transformers().

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

◆ print_control_postcondition_map()

void print_control_postcondition_map ( control_mapping  control_postcondition_map)

unstructured.c

Parameters
control_postcondition_mapontrol_postcondition_map

Definition at line 294 of file unstructured.c.

296 {
297  if(hash_table_entry_count(control_postcondition_map)>0) {
298  HASH_MAP(c, p, {
300  fprintf(stderr, "Control %p, Statement %s, Temporary postcondition:\n",
303  }, control_postcondition_map);
304  }
305  else {
306  pips_assert("The CFG contains at least one node with one statement",
307  false);
308  }
309 }
int hash_table_entry_count(hash_table htp)
now we define observers in order to hide the hash_table type...
Definition: hash.c:818
#define HASH_MAP(k, v, code, ht)
Definition: newgen_hash.h:60

References control_statement, fprintf(), HASH_MAP, hash_table_entry_count(), pips_assert, print_transformer, and statement_identification().

Referenced by dag_to_flow_sensitive_preconditions().

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

◆ print_icfg_with_control_preconditions()

bool print_icfg_with_control_preconditions ( const  string)
Parameters
stringodule_name

◆ print_icfg_with_control_total_preconditions()

bool print_icfg_with_control_total_preconditions ( const  string)
Parameters
stringodule_name

◆ print_icfg_with_control_transformers()

bool print_icfg_with_control_transformers ( const  string)
Parameters
stringodule_name

◆ print_icfg_with_loops_preconditions()

bool print_icfg_with_loops_preconditions ( const  string)
Parameters
stringodule_name

◆ print_icfg_with_loops_total_preconditions()

bool print_icfg_with_loops_total_preconditions ( const  string)
Parameters
stringodule_name

◆ print_icfg_with_loops_transformers()

bool print_icfg_with_loops_transformers ( const  string)
Parameters
stringodule_name

◆ print_icfg_with_preconditions()

bool print_icfg_with_preconditions ( const  string)
Parameters
stringodule_name

◆ print_icfg_with_total_preconditions()

bool print_icfg_with_total_preconditions ( const  string)
Parameters
stringodule_name

◆ print_icfg_with_transformers()

bool print_icfg_with_transformers ( const  string)
Parameters
stringodule_name

◆ print_initial_precondition()

bool print_initial_precondition ( const  string)
Parameters
stringame

Definition at line 261 of file initial.c.

262 {
263  bool ok;
265  transformer t = (transformer)
266  db_get_memory_resource(DBR_INITIAL_PRECONDITION, name, true);
267 
268  debug_on("SEMANTICS_DEBUG_LEVEL");
269 
272  db_get_memory_resource(DBR_CODE, name, true));
274  db_get_memory_resource(DBR_CUMULATED_EFFECTS,
275  name,
276  true));
278 
279  ok = make_text_resource_and_free(name, DBR_PRINTED_FILE, ".ipred",
280  text_transformer(t));
281 
285 
287 
288  debug_off();
289 
290  return ok;
291 }
bool make_text_resource_and_free(const char *, const char *, const char *, text)
Definition: print.c:82
text text_transformer(transformer tran)
text text_transformer(transformer tran) input : a transformer representing a transformer or a precond...
Definition: prettyprint.c:464
static bool ok

References db_get_memory_resource(), debug_off, debug_on, free_value_mappings(), make_text_resource_and_free(), module, module_name_to_entity(), module_to_value_mappings(), ok, reset_cumulated_rw_effects(), reset_current_module_entity(), reset_current_module_statement(), set_cumulated_rw_effects(), set_current_module_entity(), set_current_module_statement(), and text_transformer().

+ Here is the call graph for this function:

◆ print_program_precondition()

bool print_program_precondition ( const  string)

A small function that would require pipsdbm and ri-util

Parameters
stringame

Definition at line 293 of file initial.c.

294 {
295  bool ok;
296  transformer t = (transformer)
297  db_get_memory_resource(DBR_PROGRAM_PRECONDITION, "", true);
298 
299  /* A small function that would require pipsdbm and ri-util*/
300  const string mn = get_main_entity_name();
302  free(mn);
303 
304  debug_on("SEMANTICS_DEBUG_LEVEL");
305  pips_debug(1, "for \"%s\"\n", name);
306 
309  db_get_memory_resource(DBR_CODE,
311  true));
313  db_get_memory_resource(DBR_CUMULATED_EFFECTS,
315  true));
317 
318  ok = make_text_resource_and_free(name, DBR_PRINTED_FILE, ".pipred",
319  text_transformer(t));
320 
324 
326 
327  debug_off();
328 
329  return ok;
330 }
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

References db_get_memory_resource(), debug_off, debug_on, free(), free_value_mappings(), get_main_entity_name(), make_text_resource_and_free(), module_local_name(), module_name_to_entity(), module_to_value_mappings(), ok, pips_debug, reset_cumulated_rw_effects(), reset_current_module_entity(), reset_current_module_statement(), set_cumulated_rw_effects(), set_current_module_entity(), set_current_module_statement(), and text_transformer().

+ Here is the call graph for this function:

◆ print_source_preconditions()

bool print_source_preconditions ( const char *  module_name)
Parameters
module_nameodule_name

Definition at line 164 of file prettyprint.c.

165 {
166  is_user_view = true;
167  is_transformer = false;
168  is_total_precondition = false;
170  get_bool_property("SEMANTICS_FILTERED_PRECONDITIONS");
172 }

References get_bool_property(), is_total_precondition, is_transformer, is_transformer_filtered, is_user_view, module_name(), and print_code_semantics().

+ Here is the call graph for this function:

◆ print_source_total_preconditions()

bool print_source_total_preconditions ( const char *  module_name)
Parameters
module_nameodule_name

Definition at line 174 of file prettyprint.c.

175 {
176  is_user_view = true;
177  is_transformer = false;
178  is_total_precondition = true;
180  get_bool_property("SEMANTICS_FILTERED_PRECONDITIONS");
182 }

References get_bool_property(), is_total_precondition, is_transformer, is_transformer_filtered, is_user_view, module_name(), and print_code_semantics().

+ Here is the call graph for this function:

◆ print_source_transformers()

bool print_source_transformers ( const char *  module_name)
Parameters
module_nameodule_name

Definition at line 155 of file prettyprint.c.

156 {
157  is_user_view = true;
158  is_transformer = true;
159  is_total_precondition = false;
160  is_transformer_filtered = false;
162 }

References is_total_precondition, is_transformer, is_transformer_filtered, is_user_view, module_name(), and print_code_semantics().

+ Here is the call graph for this function:

◆ print_statement_temporary_precondition()

void print_statement_temporary_precondition ( statement_mapping  statement_temporary_precondition_map)
Parameters
statement_temporary_precondition_maptatement_temporary_precondition_map

Definition at line 1006 of file unstructured.c.

1008 {
1009  if(hash_table_entry_count(statement_temporary_precondition_map)>0) {
1010  HASH_MAP(s, p, {
1011  fprintf(stderr, "Statement %s, Temporary precondition:\n",
1014  }, statement_temporary_precondition_map);
1015  }
1016  else {
1017  pips_assert("The DAG contains at least one control node with one statement", false);
1018  }
1019 }

References fprintf(), HASH_MAP, hash_table_entry_count(), pips_assert, print_transformer, and statement_identification().

Referenced by dag_to_flow_sensitive_preconditions().

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

◆ program_postcondition()

bool program_postcondition ( const string  name)

The program correctness postcondition cannot be infered.

It should be provided by the user.

A small function that would require pipsdbm and ri-util

Parameters
nameame

Definition at line 233 of file initial.c.

234 {
236 
237  /* A small function that would require pipsdbm and ri-util*/
238  const string mn = get_main_entity_name();
239  entity the_main = module_name_to_entity(mn);
240  free(mn);
241 
242  debug_on("SEMANTICS_DEBUG_LEVEL");
243  pips_debug(1, "considering program \"%s\" with main \"%s\"\n", name,
244  module_local_name(the_main));
245 
246  pred_debug(1, "assumed program postcondition:\n", post);
247 
248  ifdebug(1)
249  pips_assert("consistent program postcondition",
251 
252  DB_PUT_MEMORY_RESOURCE(DBR_PROGRAM_POSTCONDITION, "", post);
253 
254  debug_off();
255  return true;
256 }
#define pred_debug(level, msg, trans)
Definition: initial.c:129

References DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, free(), get_main_entity_name(), ifdebug, module_local_name(), module_name_to_entity(), pips_assert, pips_debug, pred_debug, transformer_consistency_p(), and transformer_identity().

+ Here is the call graph for this function:

◆ program_precondition()

bool program_precondition ( const  string)

Compute the union of all initial preconditions.

A small function that would require pipsdbm and ri-util

e_inter = effects_to_list(get_cumulated_rw_effects(get_current_module_statement()));

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

no dup & false => core

modifies tm!

tm = transformer_normalize(tm, 2);

Parameters
stringame

Definition at line 134 of file initial.c.

135 {
137 
138  /* A small function that would require pipsdbm and ri-util*/
139  const string mn = get_main_entity_name();
140  entity the_main = module_name_to_entity(mn);
141 
142  pips_assert("main was found", the_main!=entity_undefined);
143 
144  free(mn);
145 
146  int i, nmodules;
147  gen_array_t modules;
148  list e_inter = NIL;
149 
150  debug_on("SEMANTICS_DEBUG_LEVEL");
151  pips_debug(1, "considering program \"%s\" with main \"%s\"\n", name,
152  module_local_name(the_main));
153 
154  set_current_module_entity(the_main);
156  db_get_memory_resource(DBR_CODE,
157  module_local_name(the_main),
158  true));
161  db_get_memory_resource(DBR_CUMULATED_EFFECTS,
162  module_local_name(the_main),
163  true));
165  db_get_memory_resource(DBR_PROPER_EFFECTS,
166  module_local_name(the_main),
167  true));
168 
169  /* e_inter = effects_to_list(get_cumulated_rw_effects(get_current_module_statement())); */
170 
171  e_inter = effects_to_list( (effects)
172  db_get_memory_resource(DBR_SUMMARY_EFFECTS,
173  module_local_name(the_main),
174  true));
175 
176  module_to_value_mappings(the_main);
177 
178  /* Unavoidable pitfall: initializations in uncalled modules may be
179  * taken into account. It all depends on the "create" command.
180  */
181  modules = db_get_module_list();
182  nmodules = gen_array_nitems(modules);
183  pips_assert("some modules in the program", nmodules>0);
184 
185  for(i=0; i<nmodules; i++) {
186  transformer tm;
187  string mname = gen_array_item(modules, i);
188  pips_debug(1, "considering module %s\n", mname);
189 
190  tm = transformer_dup((transformer) /* no dup & false => core */
191  db_get_memory_resource(DBR_INITIAL_PRECONDITION,
192  mname, true));
193 
194  pred_debug(3, "current: t =\n", t);
195  pred_debug(2, "to be added: tm =\n", tm);
196  translate_global_values(the_main, tm); /* modifies tm! */
197  pred_debug(3, "to be added after translation:\n", tm);
198  tm = transformer_intra_to_inter(tm, e_inter);
199  /* tm = transformer_normalize(tm, 2); */
200  if(!transformer_consistency_p(tm)) {
201  (void) print_transformer(tm);
202  pips_internal_error("Non-consistent filtered initial precondition");
203  }
204  pred_debug(3, "to be added after filtering:\n", tm);
205 
206  intersect(t, tm);
207  free_transformer(tm);
208  }
209 
210  pred_debug(1, "resulting program precondition:\n", t);
211 
212  ifdebug(1)
213  pips_assert("consistent program precondition",
215 
216  DB_PUT_MEMORY_RESOURCE(DBR_PROGRAM_PRECONDITION, "", t);
217 
223 
225  gen_array_full_free(modules);
226 
227  debug_off();
228  return true;
229 }
size_t gen_array_nitems(const gen_array_t a)
Definition: array.c:131
void gen_array_full_free(gen_array_t a)
Definition: array.c:77
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
static void intersect(transformer t1, transformer t2)
returns t1 inter= t2;
Definition: initial.c:120

References db_get_memory_resource(), db_get_module_list(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, effects_to_list(), entity_undefined, free(), free_statement_global_stack(), free_transformer(), free_value_mappings(), gen_array_full_free(), gen_array_item(), gen_array_nitems(), get_main_entity_name(), ifdebug, intersect(), make_statement_global_stack(), module_local_name(), module_name_to_entity(), module_to_value_mappings(), NIL, pips_assert, pips_debug, pips_internal_error, pred_debug, print_transformer, reset_cumulated_rw_effects(), reset_current_module_entity(), reset_current_module_statement(), reset_proper_rw_effects(), set_cumulated_rw_effects(), set_current_module_entity(), set_current_module_statement(), set_proper_rw_effects(), transformer_consistency_p(), transformer_dup(), transformer_identity(), transformer_intra_to_inter(), and translate_global_values().

+ Here is the call graph for this function:

◆ propagate_preconditions_in_declarations()

transformer propagate_preconditions_in_declarations ( list  dl,
transformer  pre,
void(*)(expression, transformer process_initial_expression 
)

This function is mostly copied from declarations_to_transformer().

It is used to recompute intermediate preconditions and to process the initialization expressions with the proper precondition. For instance, in:

int i = 10, j = i+1, a[i], k = foo(i);

you need to collect information about i's value to initialize j, dimension a and compute the summary precondition of function foo().

We assume that the precondition does not change within the expression as in:

int k = i++ + foo(i);

I do not remember if the standard prohibits this or not, but it may well forbid such expressions or state that the result is undefined.

But you can also have:

int a[i++][foo(i)];

or

int a[i++][j=foo(i)];

and the intermediate steps are overlooked by declaration_to_transformer() but can be checked with a proper process_dimensions() function.

This function can be called from ri_to_preconditions.c to propagate preconditions or from interprocedural.c to compute summary preconditions. In the second case, the necessary side effects are provided by the two functional parameters.

post = transformer_safe_normalize(post, 4);

post = transformer_safe_normalize(post, 4);

btf = transformer_normalize(btf, 4);

Parameters
dll
prere

Definition at line 977 of file ri_to_preconditions.c.

984 {
985  //entity v = entity_undefined;
986  //transformer btf = transformer_undefined;
987  //transformer stf = transformer_undefined;
989  list l = dl;
990 
991  pips_debug(8,"begin\n");
992 
993  if(ENDP(l))
994  post = copy_transformer(pre);
995  else {
996  entity v = ENTITY(CAR(l));
999  // FI: ongoing implementation
1000  //transformer stf = (*process_dimensions)(v, pre);
1003 
1004  if(!expression_undefined_p(ie)) {
1005  (*process_initial_expression)(ie, pre);
1006  free_expression(ie);
1007  }
1008 
1009  post = transformer_safe_apply(stf, pre);
1010 /* post = transformer_safe_normalize(post, 4); */
1011  post = transformer_safe_normalize(post, 2);
1012 
1013  for (POP(l) ; !ENDP(l); POP(l)) {
1014  v = ENTITY(CAR(l));
1016  if(!expression_undefined_p(ie)) {
1017  (*process_initial_expression)(ie, post);
1018  free_expression(ie);
1019  }
1020 
1021  if(!transformer_undefined_p(next_pre))
1022  free_transformer(next_pre);
1023  next_pre = post;
1024  stf = declaration_to_transformer(v, next_pre);
1025  post = transformer_safe_apply(stf, next_pre);
1026 /* post = transformer_safe_normalize(post, 4); */
1027  post = transformer_safe_normalize(post, 2);
1028  btf = transformer_combine(btf, stf);
1029 /* btf = transformer_normalize(btf, 4); */
1030  btf = transformer_normalize(btf, 2);
1031 
1032  ifdebug(1)
1033  pips_assert("btf is a consistent transformer", transformer_consistency_p(btf));
1034  pips_assert("post is a consistent transformer if pre is defined",
1036  }
1037  free_transformer(btf);
1038  }
1039 
1040  pips_debug(8, "end\n");
1041  return post;
1042 }

References CAR, copy_transformer(), declaration_to_transformer(), ENDP, ENTITY, expression_undefined_p, free_expression(), free_transformer(), ifdebug, pips_assert, pips_debug, POP, stf(), transformer_combine(), transformer_consistency_p(), transformer_dup(), transformer_normalize(), transformer_safe_apply(), transformer_safe_normalize(), transformer_undefined, transformer_undefined_p, and variable_initial_expression().

Referenced by memorize_precondition_for_summary_precondition().

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

◆ refine_transformers()

bool refine_transformers ( char *  module_name)

set_int_property(SEMANTICS_DEBUG_LEVEL, 0);

Parameters
module_nameodule_name

Definition at line 354 of file dbm_interface.c.

355 {
356  bool res;
362  /* set_int_property(SEMANTICS_DEBUG_LEVEL, 0); */
363  refine_transformers_p = true;
365  refine_transformers_p = false;
366  return res;
367 }
bool refine_transformers_p
Transformer recomputation cannot be of real use unless an interprocedural analysis is performed.
bool module_name_to_transformers_in_context(const char *module_name)

References module_name(), module_name_to_transformers_in_context(), refine_transformers_p, select_fix_point_operator(), SEMANTICS_FIX_POINT, SEMANTICS_FLOW_SENSITIVE, SEMANTICS_INTERPROCEDURAL, SEMANTICS_STDOUT, and set_bool_property().

+ Here is the call graph for this function:

◆ refine_transformers_with_points_to()

bool refine_transformers_with_points_to ( char *  module_name)

set_int_property(SEMANTICS_DEBUG_LEVEL, 0);

Parameters
module_nameodule_name

Definition at line 369 of file dbm_interface.c.

370 {
371  bool res;
377  /* set_int_property(SEMANTICS_DEBUG_LEVEL, 0); */
379  db_get_memory_resource(DBR_POINTS_TO, module_name, true) );
380  refine_transformers_p = true;
382  refine_transformers_p = false;
384  return res;
385 }

References db_get_memory_resource(), module_name(), module_name_to_transformers_in_context(), refine_transformers_p, reset_pt_to_list(), select_fix_point_operator(), SEMANTICS_FIX_POINT, SEMANTICS_FLOW_SENSITIVE, SEMANTICS_INTERPROCEDURAL, SEMANTICS_STDOUT, set_bool_property(), and set_pt_to_list().

+ Here is the call graph for this function:

◆ repeatloop_to_postcondition()

transformer repeatloop_to_postcondition ( transformer  pre,
whileloop  wl,
transformer  t_body_star 
)

An effort could be made to compute the precondition for t_exit, especially if the precondition to t_inc is available.

The repeat loop does not fit well in the current generic approach. Most of the basic transformers such as t_init, t_skip, t_enter,... are meaningless. Instead of dealing with zero or at least one iteration, we have to deal with one or at least two.

post = (t_body_c ; t_exit)(pre) + (t_body_c ; t_continue ; t_body_star ; t_body_c ; t_exit)(pre)

where we assume that t_body_star includes the continuation condition.

Clean up memory

Parameters
prere
wll
t_body_star_body_star

Definition at line 2760 of file loop.c.

2761 {
2763 
2764  statement body_s = whileloop_body(wl);
2765  transformer t_body = load_statement_transformer(body_s);
2766  transformer t_body_c = complete_statement_transformer(t_body, pre, body_s);
2767  transformer t_init = transformer_identity();
2768  transformer post_init = copy_transformer(pre);
2769  expression cond_e = whileloop_condition(wl);
2770  transformer t_continue = condition_to_transformer(cond_e, transformer_undefined, true);
2772  transformer t_skip = transformer_empty();
2773  //transformer t_skip = transformer_combine(copy_transformer(t_body), t_exit);
2774  transformer t_enter = transformer_identity();
2775  //transformer t_enter = transformer_combine(copy_transformer(t_body), t_continue);
2776  /* An effort could be made to compute the precondition for t_exit,
2777  especially if the precondition to t_inc is available. */
2785 
2786  post = any_loop_to_postcondition(body_s,
2787  t_init,
2788  t_enter,
2789  t_skip,
2790  t_body_star,
2791  t_body_c,
2792  t_continue, //since t_inc is ineffective
2793  t_inc,
2794  t_exit,
2795  pre);
2796 
2797  /* The repeat loop does not fit well in the current generic
2798  * approach. Most of the basic transformers such as t_init, t_skip,
2799  * t_enter,... are meaningless. Instead of dealing with zero or at
2800  * least one iteration, we have to deal with one or at least two.
2801  *
2802  * post = (t_body_c ; t_exit)(pre) +
2803  * (t_body_c ; t_continue ; t_body_star ; t_body_c ; t_exit)(pre)
2804  *
2805  * where we assume that t_body_star includes the continuation condition.
2806  */
2807 
2808  free_transformer(post);
2809 
2810  post_1 = transformer_apply(t_body_c, pre);
2811  post_2 = transformer_apply(t_exit, post_1);
2812 
2813  post_3 = transformer_apply(t_continue, post_1);
2814  post_4 = transformer_apply(t_body_star, post_3);
2815  post_5 = transformer_apply(t_body_c, post_4);
2816  post_6 = transformer_apply(t_exit, post_5);
2817 
2818  post = transformer_convex_hull(post_2, post_6);
2819 
2820  /* Clean up memory */
2821 
2822  free_transformer(t_init);
2823  free_transformer(post_init);
2824  free_transformer(t_skip);
2825  free_transformer(t_enter);
2826  free_transformer(t_continue);
2827  free_transformer(t_exit);
2828  free_transformer(t_inc);
2829  free_transformer(t_body_c);
2830 
2831  free_transformer(post_1);
2832  free_transformer(post_2);
2833  free_transformer(post_3);
2834  free_transformer(post_4);
2835  free_transformer(post_5);
2836  free_transformer(post_6);
2837 
2838  return post;
2839 }

References any_loop_to_postcondition(), complete_statement_transformer(), condition_to_transformer(), copy_transformer(), free_transformer(), load_statement_transformer(), transformer_apply(), transformer_convex_hull(), transformer_empty(), transformer_identity(), transformer_undefined, whileloop_body, and whileloop_condition.

Referenced by instruction_to_postcondition().

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

◆ repeatloop_to_transformer()

transformer repeatloop_to_transformer ( whileloop  wl,
transformer  pre,
list  wlel 
)

effects of whileloop wl

t_body_star = t_init ; t_enter ; (t_body ; t_next)+

t_once = t_body; t_exit

t_repeat = t_body_star + t_once

An effort could be made to compute the precondition for t_continue, especially if the precondition to t_inc is available.

FI: it should be computed with the postcondition of the body

The loop is executed at least twice; FI: I'm note sure the twice is captured

FI: example dowhile02 seems to show this is wrong with t_next empty, in spite of the star

The loop is executed only once

global transformer

Parameters
wll
prere
wlellel

Definition at line 449 of file loop.c.

452 {
453  /* t_body_star = t_init ; t_enter ; (t_body ; t_next)+
454  *
455  * t_once = t_body; t_exit
456  *
457  * t_repeat = t_body_star + t_once
458  */
459  transformer t_body_star = transformer_undefined;
460  statement body_s = whileloop_body(wl);
461  transformer t_body = transformer_undefined; // load_statement_transformer(body_s);
463  expression cond_e = whileloop_condition(wl);
464  transformer t_enter = transformer_identity();
465  /* An effort could be made to compute the precondition for t_continue,
466  especially if the precondition to t_inc is available. */
467  transformer t_continue = condition_to_transformer(cond_e, transformer_undefined, true);
468  /* FI: it should be computed with the postcondition of the body */
470  //transformer t_inc = transformer_identity();
471  transformer t_next = t_continue;
472 
473  /* The loop is executed at least twice; FI: I'm note sure the twice is captured */
474  /* FI: example dowhile02 seems to show this is wrong with t_next
475  empty, in spite of the star */
476  t_body_star = any_loop_to_transformer(t_init, t_enter, t_next, body_s, wlel, pre);
477 
478  /* The loop is executed only once */
479  // any_loop_to_transformer() has computed the body transformer
480  t_body = load_statement_transformer(body_s);
481  transformer t_once = transformer_combine(copy_transformer(t_body), t_exit);
482 
483  /* global transformer */
484  transformer t_repeat = transformer_convex_hull(t_once, t_body_star);
485 
486  // free_transformer(t_once), free_transformer(t_body_star), free_transformer(t_next), free_transformer(t_exit), free_transformer(t_enter);
487 
488  return t_repeat;
489 }

References any_loop_to_transformer(), condition_to_transformer(), copy_transformer(), load_statement_transformer(), transformer_combine(), transformer_convex_hull(), transformer_identity(), transformer_undefined, whileloop_body, and whileloop_condition.

Referenced by whileloop_to_transformer().

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

◆ reset_call_site_number()

void reset_call_site_number ( void  )

Definition at line 1126 of file interprocedural.c.

1127 {
1129 }

References number_of_call_sites.

Referenced by ordinary_summary_precondition(), and summary_total_postcondition().

+ Here is the caller graph for this function:

◆ reset_postcondition_map()

void reset_postcondition_map ( void  )

◆ reset_precondition_map()

◆ reset_semantic_map()

void reset_semantic_map ( void  )

◆ reset_total_precondition_map()

void reset_total_precondition_map ( void  )

Referenced by module_name_to_total_preconditions(), and reset_static_phase_variables().

+ Here is the caller graph for this function:

◆ reset_transformer_map()

◆ safe_any_assign_operation_to_transformer()

transformer safe_any_assign_operation_to_transformer ( entity  tmp,
list  args,
transformer  pre,
bool  is_internal 
)
Parameters
tmpmp
argsrgs
prere
is_internals_internal

Definition at line 575 of file expression.c.

579 {
580  transformer tf = any_assign_operation_to_transformer(tmp, args, pre, is_internal);
581  if(transformer_undefined_p(tf)) {
582  // FI: I'd like tmp to appear in the basis...
583  tf = transformer_identity();
584  }
585  return tf;
586 }

References any_assign_operation_to_transformer(), transformer_identity(), and transformer_undefined_p.

+ Here is the call graph for this function:

◆ safe_any_expression_side_effects_to_transformer()

transformer safe_any_expression_side_effects_to_transformer ( expression  e,
transformer  p,
bool  is_internal 
)

Same as any_expression_side_effects_to_transformer() but effects are used to always generate a transformer.

FI: I do not know how effects should be used. It might be useful to allow special transformers using location abstraction to simplify the recurrence. Currently, effects are used or not. It might be necessary to use only some of them at a given time in the evaluation process as variables can be assigned almost anywhere in C.

Parameters
is_internals_internal

Definition at line 4947 of file expression.c.

4951 {
4952  transformer tf =
4953  any_expression_side_effects_to_transformer(e, p, is_internal);
4954  if(transformer_undefined_p(tf)) {
4956  }
4957 
4958  return tf;
4959 }

References any_expression_side_effects_to_transformer(), expression_effects_to_transformer(), and transformer_undefined_p.

+ Here is the call graph for this function:

◆ safe_any_expression_to_transformer()

transformer safe_any_expression_to_transformer ( entity  v,
expression  expr,
transformer  pre,
bool  is_internal 
)

Always return a usable transformer.

Use effects if no better transformer can be found

Parameters
exprxpr
prere
is_internals_internal

Definition at line 5156 of file expression.c.

5161 {
5164  transformer tf = any_expression_to_transformer(v, expr, npre, is_internal);
5165 
5166  if(transformer_undefined_p(tf)) {
5167  //list el = expression_to_proper_effects(expr);
5169  tf = effects_to_transformer(el);
5170 
5171  /*
5172  pips_assert("effect references are protected by persistant",
5173  effect_list_can_be_safely_full_freed_p(el));*/
5174 
5176 
5177  gen_full_free_list(el);
5178  }
5179  free_transformer(npre);
5180 
5181  return tf;
5182 }
bool effect_list_can_be_safely_full_freed_p(list)
Check if some references might be freed with the effects.
Definition: effects.c:1159

References any_expression_to_transformer(), copy_transformer(), effect_list_can_be_safely_full_freed_p(), effects_to_transformer(), expression_to_proper_constant_path_effects(), free_transformer(), gen_full_free_list(), transformer_identity(), and transformer_undefined_p.

Referenced by add_index_bound_conditions(), addition_operation_to_transformer(), any_conditional_to_transformer(), any_expressions_to_transformer(), any_user_call_site_to_transformer(), bitwise_xor_to_transformer(), condition_to_transformer(), fortran_data_to_prec_for_variables(), logical_not_to_transformer(), modulo_to_transformer(), precondition_minmax_of_expression(), transformer_add_any_relation_information(), and update_cp_with_rhs_to_transformer().

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

◆ safe_assigned_expression_to_transformer()

transformer safe_assigned_expression_to_transformer ( entity  v,
expression  expr,
transformer  pre 
)

Always returns a fully defined transformer.

FI: The property to compute transformers in context is not taken into account to add information from pre within tf. pre is used to evaluate expr, but is not made part of tf.

Side effects in expression ?

Parameters
exprxpr
prere

Definition at line 2651 of file ri_to_transformers.c.

2654 {
2656 
2657  if(expression_undefined_p(expr)) {
2658  ; // That is fixed below
2659  }
2660  else
2661  tf = assigned_expression_to_transformer(v, expr, pre);
2662 
2663  if(transformer_undefined_p(tf)) {
2664  if(get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT"))
2665  tf = transformer_range(pre);
2666  else
2667  tf = transformer_identity();
2668 
2669  /* Side effects in expression ? */
2671  tf = transformer_combine(tf, setf);
2672  free_transformer(setf);
2673 
2674  // FI: need to investigate interplay between typedef and
2675  // qualifier?
2676  // FI: Issue: a static variable qualified with const and accessed thru
2677  // a function. See hs_list_smoothing() in hyantes
2678  // Or you see the issue as using assignment analysis for static definition...
2681  }
2682  }
2683 
2684  pips_assert("tf is defined", !transformer_undefined_p(tf));
2685  pips_assert("tf is consistent", transformer_consistency_p(tf));
2686 
2687  return tf;
2688 }
transformer transformer_add_modified_variable_entity(transformer tf, entity var)
FI: like the previous function, but supposed to end up with a consistent transformer.
Definition: basic.c:909
bool type_with_const_qualifier_p(type)
Is there a const qualifier associated to type t.
Definition: type.c:5483

References assigned_expression_to_transformer(), entity_has_values_p(), entity_type, expression_effects_to_transformer(), expression_undefined_p, free_transformer(), get_bool_property(), pips_assert, transformer_add_modified_variable_entity(), transformer_combine(), transformer_consistency_p(), transformer_identity(), transformer_range(), transformer_undefined, transformer_undefined_p, and type_with_const_qualifier_p().

Referenced by declaration_to_transformer(), and declaration_to_transformer_list().

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

◆ safe_assigned_expression_to_transformer_list()

list safe_assigned_expression_to_transformer_list ( entity  v,
expression  expr,
transformer  pre 
)

Always returns a fully defined transformer.

FI: The property to compute transformers in context is not taken into account to add information from pre within tf. pre is used to evaluate expr, but is not made part of tf.

Parameters
exprxpr
prere

Definition at line 610 of file ri_to_transformer_lists.c.

613 {
614  list tl = NIL;
616 
617  pips_internal_error("Not implemented yet.");
618 
619  if(expression_undefined_p(expr)) {
620  ; // That is fixed below
621  }
622  else
623  tf = assigned_expression_to_transformer(v, expr, pre);
624 
625  if(transformer_undefined_p(tf)) {
626  if(get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT"))
627  tf = transformer_range(pre);
628  else
629  tf = transformer_identity();
630 
631  if(entity_has_values_p(v)) {
633  }
634  }
635 
636  //pips_assert("tf is defined", !transformer_undefined_p(tf));
637  pips_assert("tl is consistent", transformers_consistency_p(tl));
638 
639  return tl;
640 }
bool transformers_consistency_p(list tl)
Definition: basic.c:616

References assigned_expression_to_transformer(), entity_has_values_p(), expression_undefined_p, get_bool_property(), NIL, pips_assert, pips_internal_error, transformer_add_modified_variable_entity(), transformer_identity(), transformer_range(), transformer_undefined, transformer_undefined_p, and transformers_consistency_p().

+ Here is the call graph for this function:

◆ safe_expression_to_transformer()

transformer safe_expression_to_transformer ( expression  exp,
transformer  pre 
)

This simple function does not take points-to information into account. Furthermore, precise points-to information is not available when side effects occur as in comma expressions.

FI: I do not see a simple way out. I can try to fix partly the problem in statement_to_transformer where the effects are known... Or I can play safer and use an effect function that replaces dereferencements by anywhere effects.

See anywhere03.c as an example of the issue.

Parameters
expxp
prere

Definition at line 5307 of file expression.c.

5308 {
5309  /* This simple function does not take points-to information into
5310  account. Furthermore, precise points-to information is not
5311  available when side effects occur as in comma expressions.
5312 
5313  FI: I do not see a simple way out. I can try to fix partly the
5314  problem in statement_to_transformer where the effects are
5315  known... Or I can play safer and use an effect function that
5316  replaces dereferencements by anywhere effects.
5317 
5318  See anywhere03.c as an example of the issue.
5319  */
5321  // To be careful with extended expressions generated by points-to information
5324  entity v = reference_variable(r);
5325  if(entity_field_p(v)) { // s[var1], not effect no a constant
5326  tf = transformer_identity();
5327  }
5328  }
5329 
5330  if(transformer_undefined_p(tf)) {
5331  //list el = expression_to_proper_effects(exp);
5333  tf = expression_to_transformer(exp, pre, el);
5334 
5335  gen_full_free_list(el);
5336  }
5337 
5338  return tf;
5339 }
bool entity_field_p(entity e)
e is the field of a structure
Definition: entity.c:857
transformer expression_to_transformer(expression exp, transformer pre, list el)
Just to capture side effects as the returned value is ignored.
Definition: expression.c:5190

References entity_field_p(), exp, expression_reference(), expression_reference_p(), expression_to_proper_constant_path_effects(), expression_to_transformer(), gen_full_free_list(), reference_variable, transformer_identity(), transformer_undefined, and transformer_undefined_p.

Referenced by any_assign_to_transformer(), any_expressions_to_transformer(), assign_rhs_to_reflhs_to_transformer(), complete_forloop_transformer(), complete_forloop_transformer_list(), condition_to_transformer(), conditional_to_transformer(), dimensions_to_transformer(), expression_to_transformer(), expressions_to_transformer(), forloop_to_postcondition(), forloop_to_transformer(), and struct_reference_assignment_or_equality_to_transformer().

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

◆ safe_integer_expression_to_transformer()

transformer safe_integer_expression_to_transformer ( entity  v,
expression  expr,
transformer  pre,
bool  is_internal 
)

Always return a defined transformer, using effects in case a more precise analysis fails.

Do check wrt to value mappings... if you are not dealing with interprocedural issues

Parameters
exprxpr
prere
is_internals_internal

Definition at line 3552 of file expression.c.

3558 {
3559  transformer tf = integer_expression_to_transformer(v, expr, pre, is_internal);
3560 
3561  if(transformer_undefined_p(tf))
3563 
3564  return tf;
3565 }

References expression_effects_to_transformer(), integer_expression_to_transformer(), and transformer_undefined_p.

Referenced by expression_multiply_sizeof_to_transformer(), integer_binary_operation_to_transformer(), integer_left_shift_to_transformer(), integer_multiply_to_transformer(), loop_to_enter_transformer(), and transformer_add_condition_information_updown().

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

◆ same_analyzable_type_scalar_entity_list_p()

bool same_analyzable_type_scalar_entity_list_p ( list  l)

Definition at line 255 of file interprocedural.c.

256 {
257  bool result = true;
258 
259  if (!ENDP(l)) {
260  entity e1 = ENTITY(CAR(l));
261  type t1 = entity_type(e1);
262  result = analyzable_scalar_entity_p(e1);
263 
264  MAP(ENTITY,el, {
265  if (result) {
266  type t = entity_type(el);
267  result = result && analyzable_scalar_entity_p(el)
268  && type_equal_p(t1, t);
269  }
270  },
271  CDR(l));
272  }
273  return result;
274 }

References analyzable_scalar_entity_p(), CAR, CDR, ENDP, ENTITY, entity_type, MAP, and type_equal_p().

Referenced by precondition_intra_to_inter().

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

◆ semantic_map_undefined_p()

bool semantic_map_undefined_p ( void  )

prettyprint.c

◆ semantic_to_text()

text semantic_to_text ( entity  module,
int  margin,
statement  stmt 
)

this function name is VERY misleading - it should be changed, sometime FI

Parameters
moduleodule
marginargin
stmttmt

Definition at line 354 of file prettyprint.c.

358 {
359  transformer t;
360  text txt;
361 
362  pips_assert("To please the compiler", module==module && margin==margin);
363 
364  if(is_user_view) {
366 
367  if(!statement_undefined_p(i)) {
369  }
370  else
372  }
373  else
375 
377  && t != (transformer) HASH_UNDEFINED_VALUE) {
379  t = filter_transformer(t, ef);
380  }
381 
382  txt = text_transformer(t);
383 
384  if (is_transformer)
386  else if (is_total_precondition)
388  else
390 
391  return txt;
392 }
void attach_transformers_decoration_to_text(text t)
Attach a transformers decoration:
void attach_preconditions_decoration_to_text(text t)
Attach a preconditions decoration:
void attach_total_preconditions_decoration_to_text(text __attribute__((unused)) t)
Attach a total preconditions decoration:
statement apply_number_to_statement(hash_table, _int)
Definition: statement.c:1495
#define statement_number(x)
Definition: ri.h:2452
transformer filter_transformer(transformer t, list e)
Previous version of effects_to_transformer() transformer effects_to_transformer(list e) { list args =...
static hash_table nts
Definition: prettyprint.c:84
Definition: statement.c:54

References apply_number_to_statement(), attach_preconditions_decoration_to_text(), attach_total_preconditions_decoration_to_text(), attach_transformers_decoration_to_text(), filter_transformer(), HASH_UNDEFINED_VALUE, is_total_precondition, is_transformer, is_transformer_filtered, is_user_view, load_cumulated_rw_effects_list(), load_statement_semantic(), module, nts, pips_assert, statement_number, statement_undefined_p, text_transformer(), and transformer_undefined_p.

Referenced by get_semantic_text().

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

◆ semantics_expression_to_points_to_sinks()

list semantics_expression_to_points_to_sinks ( expression  e)

Returns a list of cells.

Definition at line 112 of file points_to.c.

113 {
114  list ll = list_undefined;
115  if(pt_to_list_undefined_p()) {
118  ll = CONS(CELL, c, NIL);
119  }
120  else {
123  ll = expression_to_points_to_sinks(e, ptg);
124  }
125  return ll;
126 }
cell make_anywhere_points_to_cell(type t)
Function storing points to information attached to a statement.
Definition: points_to.c:87
type points_to_expression_to_concrete_type(expression)
The type returned is stored in a hash-table.
Definition: type.c:617
list expression_to_points_to_sinks(_UNUSED_ expression e, _UNUSED_ points_to_graph in)
Definition: points_to.c:63

References CELL, CONS, expression_to_points_to_sinks(), get_current_statement_from_statement_global_stack(), get_points_to_graph_from_statement(), list_undefined, make_anywhere_points_to_cell(), NIL, points_to_expression_to_concrete_type(), and pt_to_list_undefined_p().

Referenced by generic_unary_operation_to_transformer(), and points_to_unary_operation_to_transformer().

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

◆ semantics_expression_to_points_to_sources()

list semantics_expression_to_points_to_sources ( expression  e)

points_to.c

points_to.c

FI: check if new cells are allocated to build the returned location list ll...

Definition at line 94 of file points_to.c.

95 {
97  if (!pt_to_list_undefined_p()) {
99  if(statement_undefined_p(curstat)) {
100  // The points-to IN information should be used
101  ;
102  }
103  else
104  ptg = get_points_to_graph_from_statement(curstat);
105  }
106 
108  return ll;
109 }
#define points_to_graph_undefined
list expression_to_points_to_sources(_UNUSED_ expression e, _UNUSED_ points_to_graph in)
Definition: points_to.c:71

References expression_to_points_to_sources(), get_current_statement_from_statement_global_stack(), get_points_to_graph_from_statement(), points_to_graph_undefined, pt_to_list_undefined_p(), and statement_undefined_p.

Referenced by any_assign_to_transformer(), any_basic_update_to_transformer(), any_update_to_transformer(), lhs_expression_to_transformer(), new_array_elements_backward_substitution_in_transformer(), new_array_elements_forward_substitution_in_transformer(), and struct_reference_assignment_or_equality_to_transformer().

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

◆ semantics_usable_points_to_reference_p()

bool semantics_usable_points_to_reference_p ( reference  rlhs,
expression  lhs,
int  n 
)

See if references rlhs is usable and process null, undefined and anywhere locations defined by rlhs.

Expression lhs is passed to clarify the error and warning messages.

n is the number of alternative references. It is used to check the severity of unusable references. If n=1, a NULL rlhs implies a bug. If n>1, the points-to analysis could not determine precisely the target location.

This function is designed to check constant references in a loop over a list of references returned by the points-to analysis.

A heap location may represent several locations. p==heap ^ q==heap does not imply p==q

An anywhere location may represent several locations. p==heap ^ q==heap does not imply p==q

Parameters
rlhslhs
lhshs

Definition at line 6194 of file expression.c.

6195 {
6196  bool usable_p = false;
6197  entity source_lhs = reference_variable(rlhs);
6198  string lhss = expression_undefined_p(lhs)?
6200 
6201  ifdebug(7) {
6202  pips_debug(7, "source reference : %s\n", reference_to_string(rlhs));
6203  }
6204 
6205  if (entity_null_locations_p(source_lhs)) {
6206  if (n == 1)
6207  // An empty transformer should be returned...
6208  pips_user_error("The pointer expression \"%s\" always points to NULL\n",
6209  lhss);
6210  else
6211  semantics_user_warning("The pointer \"%s\" can point to NULL\n",
6212  lhss);
6213  }
6214  else if (entity_typed_nowhere_locations_p(source_lhs)) {
6215  if (n == 1)
6216  pips_user_error("The pointer expression \"%s\" always points to undefined/indeterminate (%s)\n", lhss, reference_to_string(rlhs));
6217  else {
6218  semantics_user_warning("The pointer expression \"%s\" can point to undefined/indeterminate (%s)\n", lhss, reference_to_string(rlhs));
6219  }
6220  }
6221  else if(entity_heap_location_p(source_lhs)) {
6222  // entity_all_heap_locations_p()
6223  // entity_all_module_heap_locations_p()
6224  // entity_all_module_heap_locations_typed : the predicate does not seem to exist
6225  /* A heap location may represent several locations. p==heap ^
6226  q==heap does not imply p==q */
6227  usable_p = false;
6228  }
6229  else if(entity_anywhere_locations_p(source_lhs)
6230  || entity_typed_anywhere_locations_p(source_lhs)) {
6231  /* An anywhere location may represent several locations. p==heap ^
6232  q==heap does not imply p==q */
6233  usable_p = false;
6234  }
6235  else {
6236  // usable_p = atomic_points_to_reference_p(rlhs);
6238  usable_p = analyzed_type_p(t)
6240  }
6241 
6242  ifdebug(7) {
6243  pips_debug(7, "source reference \"%s\" is %s\n", reference_to_string(rlhs),
6244  usable_p ? "usable" : "not usable");
6245  }
6246 
6247  return usable_p;
6248 }
bool type_struct_variable_p(type)
Definition: type.c:3867

References analyzed_type_p(), entity_anywhere_locations_p(), entity_heap_location_p(), entity_null_locations_p(), entity_typed_anywhere_locations_p(), entity_typed_nowhere_locations_p(), expression_to_string(), expression_undefined_p, ifdebug, pips_debug, pips_user_error, points_to_reference_to_concrete_type(), reference_to_string(), reference_variable, semantics_user_warning, type_struct_variable_p(), and type_variable_p.

Referenced by any_assign_to_transformer(), generic_unary_operation_to_transformer(), lhs_expression_to_transformer(), new_array_elements_backward_substitution_in_transformer(), new_array_elements_forward_substitution_in_transformer(), and struct_reference_assignment_or_equality_to_transformer().

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

◆ semantics_user_warning_func()

void semantics_user_warning_func ( const char *  func_name,
const char *  format,
  ... 
)
Parameters
func_nameunc_name
formatormat

Definition at line 118 of file misc.c.

122 {
123  va_list args;
124  va_start(args, format);
125  semantics_user_warning_alist(func_name, format, &args);
126  va_end(args);
127 }
static void semantics_user_warning_alist(const char *func_name, const char *format, va_list *args)
Some other warnings include the pass name.
Definition: misc.c:93

References semantics_user_warning_alist().

+ Here is the call graph for this function:

◆ semantics_user_warning_func2()

void semantics_user_warning_func2 ( const char *  format,
  ... 
)
Parameters
formatormat

Definition at line 129 of file misc.c.

132 {
133  va_list args;
134  va_start(args, format);
136  va_end(args);
137 }
#define pips_unknown_function
Definition: misc-local.h:63

References pips_unknown_function, and semantics_user_warning_alist().

+ Here is the call graph for this function:

◆ set_module_global_arguments()

void set_module_global_arguments ( list  args)
Parameters
argsrgs

Definition at line 103 of file ri_to_preconditions.c.

104 {
106 }

References module_global_arguments.

Referenced by module_name_to_preconditions(), and module_name_to_total_preconditions().

+ Here is the caller graph for this function:

◆ set_postcondition_map()

void set_postcondition_map ( statement_mapping  )

Referenced by set_resources_for_module().

+ Here is the caller graph for this function:

◆ set_precondition_map()

◆ set_prettyprint_transformer()

void set_prettyprint_transformer ( void  )

Definition at line 77 of file prettyprint.c.

78 {
79  is_transformer = true;
80  is_total_precondition = false;
82 }

References is_total_precondition, is_transformer, and is_transformer_filtered.

◆ set_semantic_map()

void set_semantic_map ( statement_mapping  )

◆ set_total_precondition_map()

void set_total_precondition_map ( statement_mapping  )

Referenced by module_name_to_total_preconditions().

+ Here is the caller graph for this function:

◆ set_transformer_map()

◆ set_warning_counters()

void set_warning_counters ( void  )

Definition at line 903 of file dbm_interface.c.

904 {
905  wc = 0;
906 }
static int wc
FI: Provisional management of warnings.

References wc.

Referenced by generic_module_name_to_transformers().

+ Here is the caller graph for this function:

◆ simple_affine_to_transformer()

transformer simple_affine_to_transformer ( entity  e,
Pvecteur  a,
bool  is_internal 
)

INTEGER EXPRESSIONS.

FI: I do no longer understand the semantics of "is_internal"... although I designed it. The intent was probably to manage temporary values: they should be preserved as long as the analysis is internal and else projected.

Furthermore, this function is no longer very useful as normalization can be performed dynamically again and again at a low cost.

The renaming from variables in a to new values in ve and vexpr is performed as a side-effect by value_mappings_compatible_vector_p() which fails when a renaming fails.

This is very dangerous when is_internal==false

Parameters
is_internals_internal

Definition at line 1167 of file expression.c.

1168 {
1170  Pvecteur ve = vect_new((Variable) e, VALUE_ONE);
1171  Pvecteur vexpr = vect_dup(a);
1172  Pcontrainte c;
1174 
1175  pips_debug(8, "begin with is_internal=%s\n", bool_to_string(is_internal));
1176 
1177  ifdebug(9) {
1178  pips_debug(9, "\nLinearized expression:\n");
1179  vect_dump(vexpr);
1180  }
1181 
1182  /* The renaming from variables in a to new values in ve and vexpr is
1183  * performed as a side-effect by
1184  * value_mappings_compatible_vector_p() which fails when a
1185  * renaming fails.
1186  *
1187  * This is very dangerous when is_internal==false
1188  */
1189  if(!is_internal
1192  eq = vect_substract(ve, vexpr);
1193  vect_rm(ve);
1194  vect_rm(vexpr);
1195  c = contrainte_make(eq);
1196  tf = make_transformer(NIL,
1198  }
1199  else {
1200  vect_rm(eq);
1201  vect_rm(ve);
1202  vect_rm(vexpr);
1203  tf = transformer_undefined;
1204  }
1205 
1206  pips_debug(8, "end with tf=%p\n", tf);
1207  ifdebug(8) dump_transformer(tf);
1208 
1209  return tf;
1210 }

References bool_to_string(), contrainte_make(), CONTRAINTE_UNDEFINED, dump_transformer, eq, ifdebug, make_predicate(), make_transformer(), NIL, pips_debug, sc_make(), transformer_undefined, value_mappings_compatible_vector_p(), VALUE_ONE, vect_dump(), vect_dup(), vect_new(), vect_rm(), vect_substract(), and VECTEUR_NUL.

Referenced by integer_expression_to_transformer().

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

◆ simple_dead_loop_p()

bool simple_dead_loop_p ( expression  lower,
expression  upper 
)
Parameters
lowerower
upperpper

Definition at line 1028 of file loop.c.

1029 {
1030  bool dead_loop_p = false;
1031  normalized n_lower = NORMALIZE_EXPRESSION(lower);
1032  normalized n_upper = NORMALIZE_EXPRESSION(upper);
1033 
1034  if(normalized_linear_p(n_upper) && normalized_linear_p(n_lower)) {
1035  Pvecteur v_lower = normalized_linear(n_lower);
1036  Pvecteur v_upper = normalized_linear(n_upper);
1037 
1038  if(VECTEUR_NUL_P(v_lower)) {
1039  if (!VECTEUR_NUL_P(v_upper)) {
1040  if(term_cst(v_upper)
1041  && VECTEUR_NUL_P(vecteur_succ(v_upper))) {
1042  dead_loop_p = value_neg_p(vecteur_val(v_upper));
1043  }
1044  }
1045  }
1046  else if(VECTEUR_NUL_P(v_upper)) {
1047  if (!VECTEUR_NUL_P(v_lower)) {
1048  if(term_cst(v_lower)
1049  && VECTEUR_NUL_P(vecteur_succ(v_lower))) {
1050  dead_loop_p = value_pos_p(vecteur_val(v_lower));
1051  }
1052  }
1053  }
1054  else if(term_cst(v_upper) && term_cst(v_lower)
1055  && VECTEUR_NUL_P(vecteur_succ(v_upper))
1056  && VECTEUR_NUL_P(vecteur_succ(v_lower))) {
1057  dead_loop_p =
1058  value_gt(vecteur_val(v_lower),vecteur_val(v_upper));
1059  }
1060  }
1061 
1062  return dead_loop_p;
1063 }
#define value_pos_p(val)
#define value_gt(v1, v2)
#define value_neg_p(val)
#define vecteur_val(v)
#define term_cst(varval)

References NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, term_cst, value_gt, value_neg_p, value_pos_p, VECTEUR_NUL_P, vecteur_succ, and vecteur_val.

Referenced by add_index_range_conditions().

+ Here is the caller graph for this function:

◆ simplify_boolean_expression_with_precondition()

int simplify_boolean_expression_with_precondition ( expression  e,
transformer  p 
)

Simplification of bool expressions with precondition.

Expression e is modified, if necessary, by side effect.

The value returned is 1 if the expression e is always true (never false) under condition p, 0 if is the expression is always false (never true), and -1 otherwise.

This function is not used within the semantics library. It is exported for partial_eval and suppress_dead_code or similar passes.

Because of C flexibility, all kinds of "boolean" expressions may arise. Think of the conditional and comma operators, think of all kinds of side effects, think of integer expressions,...

FI: In the short term, I only need to deal with bool operators and, or and not.

Definition at line 6080 of file expression.c.

6082 {
6083  int validity = -1; // unknown
6084  bool done = false;
6086  // We could try the global simplification as in the other case...
6087  syntax s = expression_syntax(e);
6088  call c = syntax_call(s);
6089  entity op = call_function(c);
6090  if(ENTITY_NOT_P(op)) {
6093  if(validity>=0)
6094  validity = 1 - validity;
6095  done = true;
6096  }
6097  else if(ENTITY_OR_P(op)) {
6100  if(v1==1)
6101  validity = 1;
6102  else {
6105  if(v2==1)
6106  validity = 1;
6107  else if(v2==0) { // a2 has no impact
6108  if(v1==0)
6109  validity = 0;
6110  else {
6111  validity = -1;
6113  }
6114  }
6115  else // v2==-1
6116  if(v1==0) { // a1 has no impact
6117  validity = -1;
6119  }
6120  else
6121  validity = -1;
6122  }
6123  done =true;
6124  }
6125  else if(ENTITY_AND_P(op)) {
6128  if(v1==0)
6129  validity = 0;
6130  else { // v1 == -1 or 1, no conclusion yet
6133  if(v2==0)
6134  validity = 0;
6135  else if(v2==1) {
6136  if(v1==1)
6137  validity = 1;
6138  else { // get rid of a2
6139  validity = -1;
6141  }
6142  }
6143  else { // v2==-1
6144  if(v1==1) {// a1 is useless
6145  validity = -1;
6147  }
6148  else {
6149  validity = -1;
6150  }
6151  }
6152  }
6153  done =true;
6154  }
6155  }
6156  if (!done) {
6157  transformer tt = condition_to_transformer(e,p, true);
6158  transformer ft = condition_to_transformer(e,p, false);
6159 
6160  if(transformer_empty_p(tt)) {
6161  // Then the condition is always false
6162  validity = 0;
6163  }
6164  if(transformer_empty_p(ft)) {
6165  // Then the condition is always true
6166  validity = 1;
6167  }
6168  // Both can be true simultaneously when the precondition p is
6169  // empty... but it does not matter
6170  }
6171 
6172  if(validity==0||validity==1) {
6173  // e must be replaced by a call to true or false
6176  }
6177 
6178  return validity;
6179 }
#define ENTITY_OR_P(e)
#define ENTITY_AND_P(e)
#define ENTITY_NOT_P(e)
bool logical_operator_expression_p(expression e)
C xor is missing.
Definition: expression.c:573
expression replace_expression_content(expression e1, expression e2)
Use side effects to move the content of e2, s2 and n2, into e1; s1 and n1 are freed,...
Definition: expression.c:3864
expression make_false_expression()
Definition: expression.c:1108
expression make_true_expression()
Definition: expression.c:1103
int simplify_boolean_expression_with_precondition(expression e, transformer p)
Simplification of bool expressions with precondition.
Definition: expression.c:6080

References call_arguments, call_function, CAR, CDR, condition_to_transformer(), copy_expression(), ENTITY_AND_P, ENTITY_NOT_P, ENTITY_OR_P, EXPRESSION, expression_syntax, logical_operator_expression_p(), make_false_expression(), make_true_expression(), replace_expression_content(), syntax_call, and transformer_empty_p().

+ Here is the call graph for this function:

◆ simplify_minmax_expression()

void simplify_minmax_expression ( expression  e,
transformer  tr 
)

tries hard to simplify expression e if it is a min or a max operator, by evaluating it under preconditions tr.

Two approaches are tested: check bounds of lhs-rhs, or compare bounds of lhs and rhs

Parameters
trr

Definition at line 5849 of file expression.c.

5850 {
5851  if(expression_minmax_p(e)) {
5852  call c =expression_call(e);
5853  bool is_max = ENTITY_MAX_P(call_function(c));
5854 
5855  expression lhs = binary_call_lhs(c);
5856  expression rhs = binary_call_rhs(c);
5857  expression diff = make_op_exp(
5859  copy_expression(lhs),
5860  copy_expression(rhs)
5861  );
5862  intptr_t lhs_lbound,lhs_ubound,rhs_lbound,rhs_ubound,diff_lbound,diff_ubound;
5863  if(precondition_minmax_of_expression(diff,tr,&diff_lbound,&diff_ubound) &&
5864  (diff_lbound>=0 || diff_ubound<=0)) {
5865  if(is_max) {
5866  if(diff_lbound>=0) local_assign_expression(e,lhs);
5867  else local_assign_expression(e,rhs);
5868  }
5869  else {
5870  if(diff_lbound>=0) local_assign_expression(e,rhs);
5871  else local_assign_expression(e,lhs);
5872  }
5873  }
5874  else if(precondition_minmax_of_expression(lhs,tr,&lhs_lbound,&lhs_ubound) &&
5875  precondition_minmax_of_expression(rhs,tr,&rhs_lbound,&rhs_ubound))
5876  {
5877  if(is_max)
5878  {
5879  if(lhs_lbound >=rhs_ubound) local_assign_expression(e,lhs);
5880  else if(rhs_lbound >= lhs_ubound) local_assign_expression(e,rhs);
5881  }
5882  else
5883  {
5884  if(lhs_lbound >=rhs_ubound) local_assign_expression(e,rhs);
5885  else if(rhs_lbound >= lhs_ubound) local_assign_expression(e,lhs);
5886  }
5887  }
5888  }
5889 }
@ is_max
Definition: optimize.c:710
#define binary_call_rhs(c)
#define MINUS_OPERATOR_NAME
#define ENTITY_MAX_P(e)
#define binary_call_lhs(c)
bool expression_minmax_p(expression e)
Definition: expression.c:3882
void local_assign_expression(expression caller, expression field)
replace expression caller by expression field , where field is contained by caller
Definition: expression.c:3571
expression make_op_exp(char *op_name, expression exp1, expression exp2)
================================================================
Definition: expression.c:2012
bool precondition_minmax_of_expression(expression exp, transformer tr, intptr_t *pmin, intptr_t *pmax)
compute integer bounds pmax, pmin of expression exp under preconditions tr require value mappings set...
Definition: expression.c:5818

References binary_call_lhs, binary_call_rhs, call_function, copy_expression(), ENTITY_MAX_P, expression_call(), expression_minmax_p(), intptr_t, is_max, local_assign_expression(), make_op_exp(), MINUS_OPERATOR_NAME, and precondition_minmax_of_expression().

Referenced by do_array_expansion(), do_solve_hardware_constraints_on_nb_proc(), and region_to_minimal_dimensions().

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

◆ standard_whileloop_to_transformer()

transformer standard_whileloop_to_transformer ( whileloop  l,
transformer  pre,
list  e 
)

This function computes the effect of K loop iteration, with K positive.

This function does not take the loop exit into account because its result is used to compute the precondition of the loop body. Hence the loop exit condition only is added when preconditions are computed. This is confusing when transformers are prettyprinted with the source code.

loop transformer tf = tfb* or tf = tfb+ or ...

loop body transformer

Make sure not to leave too much information in pre. Perform a very simplistic fix point based on effects.

If the while entry condition is usable, it must be added on the old values

I'd like to use pre_n as context to evaluate the condition cond, but I'm not sure it's safe (Francois Irigoin)

Side effects in cond are ignored!

compute the whileloop body transformer, including the initial conditions

The convex hull of the image of pre and of the image of tfb can be added as conditions on tfb's domain, if some information is available in pre

compute tfb's fix point according to pips flags

The second clause is probably stronger than the first one

The loop is never entered

Side effects of the condition evaluation should be taken into account

A temporary variable is expected as first argument. There is something to fix.

tf = any_expression_to_transformer();

The loop is never exited, e.g. because there is a STOP or an infinite loop inside

Dirty looking fix for a fix point computation error: sometimes, the basis is restricted to a subset of the integer scalar variables. Should be useless with proper fixpoint opertors.

we have a problem here: to compute preconditions within the whileloop body we need a tf using private variables; to return the loop transformer, we need a filtered out tf; only one hook is available in the ri..; let'a assume there are no private variables and that if they are privatizable they are not going to get in our way

basic cheap version: do not use the whileloop body transformer and avoid fix-points; local variables do not have to be filtered out because this was already done while computing effects

The loop body transformers could benefit from pre_n instead of transformer_undefined, but who would think of combining these two options?

Parameters
prere

Definition at line 2456 of file loop.c.

2459 {
2460  /* loop transformer tf = tfb* or tf = tfb+ or ... */
2461  transformer tf;
2462  /* loop body transformer */
2463  transformer tfb;
2464  expression cond = whileloop_condition(l);
2465  statement s = whileloop_body(l);
2466 
2467  pips_debug(8,"begin\n");
2468 
2471 
2472  if(transformer_undefined_p(pre)) {
2473  pre_n = transformer_identity();
2474  }
2475  else {
2476  /* Make sure not to leave too much information in pre. Perform a very
2477  simplistic fix point based on effects. */
2478  transformer tf_star = effects_to_transformer(e);
2479 
2480  pre_n = invariant_wrt_transformer(pre, tf_star);
2481  free_transformer(tf_star);
2482  }
2483  /* If the while entry condition is usable, it must be added
2484  * on the old values
2485  */
2486  /* I'd like to use pre_n as context to evaluate the condition cond,
2487  but I'm not sure it's safe (Francois Irigoin) */
2488  /* Side effects in cond are ignored! */
2489  pre_n = precondition_add_condition_information(pre_n, cond,
2490  transformer_undefined, true);
2491 
2492  ifdebug(8) {
2493  pips_debug(8, "Precondition for loop body pre_n=\n");
2495  }
2496 
2497  /* compute the whileloop body transformer, including the initial conditions */
2498  tfb = transformer_dup(statement_to_transformer(s, pre_n));
2499 
2500  /* The convex hull of the image of pre and of the image of tfb can be
2501  added as conditions on tfb's domain, if some information is available in pre */
2502  if(!transformer_undefined_p(pre))
2504 
2505  /* compute tfb's fix point according to pips flags */
2508  }
2509  else if ((!transformer_undefined_p(pre)
2510  && condition_false_wrt_precondition_p(cond, pre))
2511  /* The second clause is probably stronger than the first one */
2512  || transformer_empty_p(pre_n)) {
2513  /* The loop is never entered */
2514  /* Side effects of the condition evaluation should be taken into account */
2515  tf = transformer_identity();
2516  /* A temporary variable is expected as first argument. There is something to fix. */
2517  /* tf = any_expression_to_transformer(); */
2518  }
2519  else if(transformer_empty_p(tfb)) {
2520  /* The loop is never exited, e.g. because there is a STOP or an infinite loop inside */
2521  tf = transformer_empty();
2522  }
2523  else {
2524  transformer ftf = (* transformer_fix_point_operator)(tfb);
2525 
2528  Psysteme sc = SC_UNDEFINED;
2529 
2530  /* Dirty looking fix for a fix point computation error:
2531  * sometimes, the basis is restricted to a subset of
2532  * the integer scalar variables. Should be useless with proper
2533  * fixpoint opertors.
2534  */
2535  tf = effects_to_transformer(e);
2537 
2538  sc = sc_append(sc, fsc);
2539 
2540  free_transformer(ftf);
2541  }
2542  else {
2543  tf = ftf;
2544  }
2545 
2546  ifdebug(8) {
2547  pips_debug(8, "intermediate fix-point tf=\n");
2549  }
2550 
2551  }
2552 
2553  free_transformer(pre_n);
2554 
2555  /* we have a problem here: to compute preconditions within the
2556  whileloop body we need a tf using private variables; to return
2557  the loop transformer, we need a filtered out tf; only
2558  one hook is available in the ri..; let'a assume there
2559  are no private variables and that if they are privatizable
2560  they are not going to get in our way */
2561  }
2562  else {
2563  /* basic cheap version: do not use the whileloop body transformer and
2564  avoid fix-points; local variables do not have to be filtered out
2565  because this was already done while computing effects */
2566 
2567  /* The loop body transformers could benefit from pre_n instead of
2568  transformer_undefined, but who would think of combining these
2569  two options? */
2571  tf = effects_to_transformer(e);
2572  }
2573 
2574  ifdebug(8) {
2575  (void) fprintf(stderr,"%s: %s\n","standard_whileloop_to_transformer",
2576  "resultat tf =");
2577  (void) print_transformer(tf);
2578  }
2579  pips_debug(8,"end\n");
2580  return tf;
2581 }
transformer transformer_equality_fix_point(transformer)
Let A be the affine loop transfert function.
Definition: fix_point.c:266
transformer(* transformer_fix_point_operator)(transformer)
Interface between the untyped database manager and clean code and between pipsmake and clean code.
Definition: fix_point.c:114
transformer transformer_halbwachs_fix_point(transformer tf)
Definition: fix_point.c:143
Psysteme sc_append(Psysteme s1, Psysteme s2)
Psysteme sc_append(Psysteme s1, Psysteme s2): calcul de l'intersection des polyedres definis par s1 e...
static transformer loop_body_transformer_add_entry_and_iteration_information(transformer tfb, transformer pre)
FI: I do not have one test case to show that this function is of some use.
Definition: loop.c:2412

References condition_false_wrt_precondition_p(), effects_to_transformer(), external_value_name(), fprint_transformer(), fprintf(), free_transformer(), ifdebug, invariant_wrt_transformer(), loop_body_transformer_add_entry_and_iteration_information(), pips_debug, pips_flag_p, precondition_add_condition_information(), predicate_system, print_transformer, sc_append(), SEMANTICS_FIX_POINT, SEMANTICS_INEQUALITY_INVARIANT, statement_to_transformer(), transformer_dup(), transformer_empty(), transformer_empty_p(), transformer_equality_fix_point(), transformer_fix_point_operator, transformer_halbwachs_fix_point(), transformer_identity(), transformer_relation, transformer_undefined, transformer_undefined_p, whileloop_body, and whileloop_condition.

+ Here is the call graph for this function:

◆ statement_feasible_p()

bool statement_feasible_p ( statement  s)

Return true if statement s is reachable according to its precondition.

Definition at line 92 of file utils.c.

93 {
95  return feasible_p;
96 }
static bool parametric_statement_feasible_p(statement s, bool empty_p(transformer))
Return true if statement s is reachable according to its precondition.
Definition: utils.c:47

References parametric_statement_feasible_p(), and transformer_empty_p().

+ Here is the call graph for this function:

◆ statement_postcondition_undefined_p()

bool statement_postcondition_undefined_p ( statement  )

◆ statement_precondition_undefined_p()

bool statement_precondition_undefined_p ( statement  )

◆ statement_semantic_undefined_p()

bool statement_semantic_undefined_p ( statement  )

◆ statement_strongly_feasible_p()

bool statement_strongly_feasible_p ( statement  s)

Return true if statement s is reachable according to its precondition.

Definition at line 99 of file utils.c.

100 {
101  bool feasible_p =
103  return feasible_p;
104 }
bool transformer_strongly_empty_p(transformer t)
If true is returned, the transformer certainly is empty.
Definition: transformer.c:2465

References parametric_statement_feasible_p(), and transformer_strongly_empty_p().

Referenced by set_methods_for_convex_effects(), and set_methods_for_convex_rw_pointer_effects().

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

◆ statement_to_postcondition()

transformer statement_to_postcondition ( transformer  pre,
statement  s 
)

end of the non recursive section

Refine the precondition pre of s using side effects and compute its postcondition post.

Postcondition post is returned.

FI: if the statement s is a loop, the transformer tf is not the statement transformer but the transformer T* which maps the precondition pre onto the loop body precondition. The real statement transformer is obtained by executing the loop till it is exited. See complete_any_loop_transformer()

ACHTUNG! "pre" is likely to be misused! FI, Sept. 3, 1990

To provide information for warnings

FC: if the code is not reachable (thanks to STOP or GOTO), which is a structural information, the precondition is just empty.

keep only global initial scalar integer values; else, you might end up giving the same xxx::old name to two different local values

FI: OK, to be fixed when the declaration representation is frozen.

add array references information

add type information

Add information from declarations when useful

FI: it might be better to have another function, declarations_to_postconditions(), which might be slightly more accurate? Note that declarations_to_transformer() does compute the postcondition, but free it before returning the transformer

Remove information when leaving a block

add equivalence equalities

eliminate redundancy, rational redundancy but not integer redundancy.

FI: nice... but time consuming!

Version 3 is OK. Equations are over-used and make inequalities uselessly conplex

pre = transformer_normalize(pre, 3);

pre = transformer_normalize(pre, 6);

pre = transformer_normalize(pre, 7);

The double normalization could be avoided with a non-heuristics approach. For ocean, its overhead is 34s out of 782.97 to give 816.62s: 5 %. The double normalization is also useful for some exit conditions of WHILE loops (w05, w06, w07). It is not powerful enough for preconditions containing equations with three or more variables such as fraer01,...

BC: pre = transformer_normalize(pre, 4);

FI->BC: why keep a first normalization before the next one? FI: Because a level 2 normalization does things that a level 4 does not perform! Although level 2 is much faster...

pre = transformer_normalize(pre, 2);

Do not keep too many initial variables in the preconditions: not so smart? invariance01.c: information is lost... Since C passes values, it is usually useless to keep track of the initial values of arguments because programmers usually do not modify them. However, when they do modify the formal parameter, information is lost.

See character01.c, but other counter examples above about non_initial_values.

FI: redundancy possibly added. See asopt02. Maybe this should be moved up before the normalization step.

store the precondition in the ri

pre = statement_precondition(s);

post = instruction_to_postcondition(pre, i, tf);

Parameters
prere
spostcondition of predecessor

Definition at line 712 of file ri_to_preconditions.c.

715 {
718  /* FI: if the statement s is a loop, the transformer tf is not the
719  statement transformer but the transformer T* which maps the
720  precondition pre onto the loop body precondition. The real
721  statement transformer is obtained by executing the loop till
722  it is exited. See complete_any_loop_transformer() */
724 
725  /* ACHTUNG! "pre" is likely to be misused! FI, Sept. 3, 1990 */
726 
727  pips_debug(1,"begin\n");
728 
729  pips_assert("The statement precondition is defined",
730  pre != transformer_undefined);
731 
732  ifdebug(1) {
733  int so = statement_ordering(s);
734  (void) fprintf(stderr, "statement %03td (%d,%d), precondition %p:\n",
736  ORDERING_STATEMENT(so), pre);
737  (void) print_transformer(pre) ;
738  }
739 
740  pips_assert("The statement transformer is defined",
741  tf != transformer_undefined);
742  ifdebug(1) {
743  int so = statement_ordering(s);
744  (void) fprintf(stderr, "statement %03td (%d,%d), transformer %p:\n",
746  ORDERING_STATEMENT(so), tf);
747  (void) print_transformer(tf) ;
748  }
749 
750  /* To provide information for warnings */
752 
753  if (!statement_reachable_p(s))
754  {
755  /* FC: if the code is not reachable (thanks to STOP or GOTO), which
756  * is a structural information, the precondition is just empty.
757  */
758  pre = empty_transformer(pre);
759  }
760 
762  /* keep only global initial scalar integer values;
763  else, you might end up giving the same xxx#old name to
764  two different local values */
765  list non_initial_values =
769 
770  /* FI: OK, to be fixed when the declaration representation is
771  frozen. */
773  && !declaration_statement_p(s)) {
774  // FI: Just to gain some time before dealing with controlizer and declarations updates
775  //pips_internal_error("Statement %p carries declarations");
776  pips_user_warning("Statement %p with instruction carries declarations\n",
778  }
779 
780  MAPL(cv,
781  {
782  entity v = ENTITY(CAR(cv));
783  ENTITY_(CAR(cv)) = entity_to_old_value(v);
784  },
785  non_initial_values);
786 
787  /* add array references information */
788  if(get_bool_property("SEMANTICS_TRUST_ARRAY_REFERENCES")) {
790  }
791 
792  /* add type information */
793  if(get_bool_property("SEMANTICS_USE_TYPE_INFORMATION")
794  || get_bool_property("SEMANTICS_USE_TYPE_INFORMATION_IN_PRECONDITIONS")) {
796  }
797 
798  /* Add information from declarations when useful */
799  if(declaration_statement_p(s) && !ENDP(dl)) {
800  /* FI: it might be better to have another function,
801  declarations_to_postconditions(), which might be
802  slightly more accurate? Note that
803  declarations_to_transformer() does compute the
804  postcondition, but free it before returning the transformer */
806  transformer dpre = transformer_apply(dt, pre);
807 
808  //post = instruction_to_postcondition(dpre, i, tf);
809  //free_transformer(dpre);
810  // FI: Let's assume that declaration statement do not
811  //require further analysis
812  post = dpre;
813  }
814  else {
815  post = instruction_to_postcondition(pre, i, tf);
816  }
817 
818  /* Remove information when leaving a block */
821 
822  if(!ENDP(vl))
823  post = safe_transformer_projection(post, vl);
824  }
825  else if(statement_loop_p(s)
826  && !get_bool_property("SEMANTICS_KEEP_DO_LOOP_EXIT_CONDITION")) {
827  loop l = statement_loop(s);
828  entity i = loop_index(l);
829  list vl = variable_to_values(i);
830  post = safe_transformer_projection(post, vl);
831  }
832 
833  /* add equivalence equalities */
835 
836  /* eliminate redundancy, rational redundancy but not integer redundancy. */
837 
838  /* FI: nice... but time consuming! */
839  /* Version 3 is OK. Equations are over-used and make
840  * inequalities uselessly conplex
841  */
842  /* pre = transformer_normalize(pre, 3); */
843 
844  /* pre = transformer_normalize(pre, 6); */
845  /* pre = transformer_normalize(pre, 7); */
846 
847  /* The double normalization could be avoided with a non-heuristics
848  approach. For ocean, its overhead is 34s out of 782.97 to give
849  816.62s: 5 %. The double normalization is also useful for some
850  exit conditions of WHILE loops (w05, w06, w07). It is not
851  powerful enough for preconditions containing equations with
852  three or more variables such as fraer01,...*/
853 
854  if(!transformer_consistency_p(pre)) {
855  ;
856  }
857  /* BC: pre = transformer_normalize(pre, 4); */
858  /* FI->BC: why keep a first normalization before the next
859  one? FI: Because a level 2 normalization does things that
860  a level 4 does not perform! Although level 2 is much
861  faster... */
862  pre = transformer_normalize(pre, 2);
863 
864  if(!transformer_consistency_p(pre)) {
865  ;
866  }
867  /* pre = transformer_normalize(pre, 2); */
868  if(get_int_property("SEMANTICS_NORMALIZATION_LEVEL_BEFORE_STORAGE")
869  == 4)
870  // FI HardwareAccelerator/freia_52: this level does not
871  // handle the signs properly for simple equations like -i==0
872  // and it does not sort constraints lexicographically!
873  pre = transformer_normalize(pre, 4);
874  else
875  pre = transformer_normalize(pre, 2);
876 
877  if(!transformer_consistency_p(pre)) {
878  int so = statement_ordering(s);
879  fprintf(stderr, "statement %03td (%d,%d), precondition %p end:\n",
881  ORDERING_STATEMENT(so), pre);
882  print_transformer(pre);
883  pips_internal_error("Non-consistent precondition after update");
884  }
885 
886  /* Do not keep too many initial variables in the
887  * preconditions: not so smart? invariance01.c: information is
888  * lost... Since C passes values, it is usually useless to
889  * keep track of the initial values of arguments because
890  * programmers usually do not modify them. However, when they
891  * do modify the formal parameter, information is lost.
892  *
893  * See character01.c, but other counter examples above about
894  * non_initial_values.
895  *
896  * FI: redundancy possibly added. See asopt02. Maybe this
897  * should be moved up before the normalization step.
898  */
899  if(get_bool_property("SEMANTICS_FILTER_INITIAL_VALUES")) {
900  pre = transformer_filter(pre, non_initial_values);
901  pre = transformer_normalize(pre, 2);
902  }
903 
904  /* store the precondition in the ri */
906 
907  gen_free_list(non_initial_values);
908  }
909  else {
910  pips_debug(8,"precondition already available\n");
911  /* pre = statement_precondition(s); */
912  (void) print_transformer(pre);
913  pips_internal_error("precondition already computed");
914  }
915 
916  /* post = instruction_to_postcondition(pre, i, tf); */
917 
918  ifdebug(1) {
919  int so = statement_ordering(s);
920  fprintf(stderr, "statement %03td (%d,%d), precondition %p end:\n",
924  }
925 
926  ifdebug(1) {
927  int so = statement_ordering(s);
928  fprintf(stderr, "statement %03td (%d,%d), postcondition %p:\n",
930  ORDERING_STATEMENT(so), post);
931  print_transformer(post) ;
932  }
933 
934  pips_assert("no sharing",post!=pre);
936 
937  pips_debug(1, "end\n");
938 
939  return post;
940 }
int get_int_property(const string)
bool statement_reachable_p(statement)
Test if the given statement is reachable from some statements given at init_reachable(start)
Definition: unreachable.c:234
loop statement_loop(statement)
Get the loop of a statement.
Definition: statement.c:1374
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
string instruction_identification(instruction i)
Return a constant string representing symbolically the instruction type.
Definition: instruction.c:284
#define ORDERING_NUMBER(o)
#define ORDERING_STATEMENT(o)
#define statement_block_p(stat)
statement pop_statement_global_stack(void)
Definition: static.c:352
void push_statement_on_statement_global_stack(statement)
Definition: static.c:333
#define ENTITY_(x)
Definition: ri.h:2758
#define statement_declarations(x)
Definition: ri.h:2460
void precondition_add_reference_information(transformer pre, statement s)
static transformer instruction_to_postcondition(transformer pre, instruction i, transformer tf)
list get_module_global_arguments()
ri_to_preconditions.c
transformer declarations_to_transformer(list dl, transformer pre)
For C declarations.
transformer tf_equivalence_equalities_add(transformer tf)
mappings.c
Definition: mappings.c:83
list variables_to_values(list list_mod)
Definition: mappings.c:966
list variable_to_values(entity e)
Definition: mappings.c:982
transformer load_statement_precondition(statement)
void store_statement_precondition(statement, transformer)

References arguments_difference(), CAR, declaration_statement_p(), declarations_to_transformer(), empty_transformer(), ENDP, ENTITY, ENTITY_, entity_to_old_value(), fprintf(), gen_free_list(), get_bool_property(), get_int_property(), get_module_global_arguments(), ifdebug, instruction_identification(), instruction_to_postcondition(), load_statement_precondition(), load_statement_transformer(), loop_index, MAPL, NIL, ORDERING_NUMBER, ORDERING_STATEMENT, pips_assert, pips_debug, pips_internal_error, pips_user_warning, pop_statement_global_stack(), precondition_add_reference_information(), print_transformer, push_statement_on_statement_global_stack(), safe_transformer_projection(), statement_block_p, statement_declarations, statement_instruction, statement_loop(), statement_loop_p(), statement_number, statement_ordering, statement_reachable_p(), store_statement_precondition(), tf_equivalence_equalities_add(), transformer_add_type_information(), transformer_apply(), transformer_arguments, transformer_consistency_p(), transformer_filter(), transformer_normalize(), transformer_undefined, variable_to_values(), and variables_to_values().

Referenced by any_loop_to_postcondition(), block_to_postcondition(), dag_to_flow_sensitive_preconditions(), loop_to_postcondition(), module_name_to_preconditions(), process_unreachable_node(), test_to_postcondition(), unstructured_to_postcondition(), unstructured_to_postconditions(), whileloop_to_postcondition(), and whileloop_to_total_precondition().

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

◆ statement_to_total_precondition()

transformer statement_to_total_precondition ( transformer  t_post,
statement  s 
)

ri_to_total_preconditions.c

ri_to_total_preconditions.c

phasis 3: propagate total preconditions from statement to sub-statement, starting from the module unique return statement. Total preconditions are over-approximation of the theoretical total preconditions, i.e. the conditions that must be met by the store before a statement is executed to reach the end of the module (intra-procedural) or the end of the program (interprocedural). Since over-approximations are computed, the end of the module or of the program cannot be reached if it is not met.

For (simple) interprocedural analysis, this phasis should be performed top-down on the call tree.

Most functions are called xxx_to_total_precondition. They receive a total postcondition as input and use a transformer to convert it into a total precondition.

Total preconditions are NEVER shared. Sharing would introduce desastrous side effects when they are updated as for equivalenced variables and would make freeing them impossible. Thus on a recursive path from statement_to_total_precondition() to itself the precondition must have been reallocated even when its value is not changed as between a block precondition and the first statement of the block precondition. In the same way statement_to_total_precondition() should never returned a total_precondition aliased with its precondition argument. Somewhere in the recursive call down the data structures towards call_to_total_precondition() some allocation must take place even if the statement as no effect on preconditions.

Ambiguity: the type "transformer" is used to abstract statement effects as well as effects combined from the beginning of the module to just before the current statement (precondition) to just after the current statement (total_precondition). This is because it was not realized that preconditions could advantageously be seen as transformers of the initial state when designing the ri. include <stdlib.h>

Preconditions may be useful to deal with tests and loops and to find out if some control paths do not exist

transformer context = transformer_undefined;

If the code is not reachable, thanks to STOP or GOTO, which is a structural information, the total precondition is just empty.

keep only global initial scalar integer values; else, you might end up giving the same xxx::old name to two different local values (?)

add equivalence equalities

t_pre = transformer_normalize(t_pre, 4);

store the total precondition in the ri

Parameters
t_post_post

Definition at line 355 of file ri_to_total_preconditions.c.

358 {
362  /* Preconditions may be useful to deal with tests and loops and to find
363  out if some control paths do not exist */
364  /* transformer context = transformer_undefined; */
367 
368  pips_debug(1,"begin\n");
369 
370  pips_assert("The statement total postcondition is defined", t_post != transformer_undefined);
371 
372  ifdebug(1) {
373  _int so = statement_ordering(s);
374  (void) fprintf(stderr, "statement %03td (%td,%td), total postcondition %p:\n",
376  ORDERING_STATEMENT(so), t_post);
377  (void) print_transformer(t_post) ;
378  }
379 
380  pips_assert("The statement transformer is defined", tf != transformer_undefined);
381  ifdebug(1) {
382  _int so = statement_ordering(s);
383  pips_debug(9,"statement %03td (%td,%td), transformer %p:\n",
385  ORDERING_STATEMENT(so), tf);
386  (void) print_transformer(tf) ;
387  }
388 
389  if (!statement_reachable_p(s))
390  {
391  /* If the code is not reachable, thanks to STOP or GOTO, which
392  * is a structural information, the total precondition is just empty.
393  */
394 
395  t_pre = transformer_empty();
396  }
397 
399  list non_initial_values = list_undefined;
400 
401  t_pre = instruction_to_total_precondition(t_post, i, tf, context);
402 
403  /* keep only global initial scalar integer values;
404  else, you might end up giving the same xxx#old name to
405  two different local values (?) */
406  non_initial_values =
409 
410  MAPL(cv,
411  {
412  entity v = ENTITY(CAR(cv));
413  ENTITY_(CAR(cv)) = entity_to_old_value(v);
414  },
415  non_initial_values);
416 
417  /* add equivalence equalities */
418  t_pre = tf_equivalence_equalities_add(t_pre);
419 
420 /* t_pre = transformer_normalize(t_pre, 4); */
421  t_pre = transformer_normalize(t_pre, 2);
422 
423  if(!transformer_consistency_p(t_pre)) {
424  _int so = statement_ordering(s);
425  fprintf(stderr, "statement %03td (%td,%td), precondition %p end:\n",
427  ORDERING_STATEMENT(so), t_pre);
428  print_transformer(t_pre);
429  pips_internal_error("Non-consistent precondition after update");
430  }
431 
432  t_pre = transformer_filter(t_pre, non_initial_values);
433 
434  /* store the total precondition in the ri */
436 
437  gen_free_list(non_initial_values);
438  }
439  else {
440  _int so = statement_ordering(s);
441  pips_debug(8, "total precondition already available:\n");
442  (void) print_transformer(t_pre);
443  pips_debug(8, "for statement %03td (%td,%td), total precondition %p end:\n",
446  pips_internal_error("total precondition already computed");
447  }
448 
449  ifdebug(1) {
450  _int so = statement_ordering(s);
451  fprintf(stderr, "statement %03td (%td,%td), total precondition %p end:\n",
455  }
456 
457  ifdebug(1) {
458  _int so = statement_ordering(s);
459  fprintf(stderr, "statement %03td (%td,%td), total_precondition %p:\n",
461  ORDERING_STATEMENT(so), t_pre);
462  print_transformer(t_pre) ;
463  }
464 
466 
467  pips_assert("unexpected sharing",t_post!=t_pre);
468 
469  pips_debug(1,"end\n");
470 
471  return t_pre;
472 }
intptr_t _int
_INT
Definition: newgen_types.h:53
static transformer instruction_to_total_precondition(transformer t_post, instruction i, transformer tf, transformer context)
transformer load_statement_total_precondition(statement)
void store_statement_total_precondition(statement, transformer)

References arguments_difference(), CAR, ENTITY, ENTITY_, entity_to_old_value(), fprintf(), free_transformer(), gen_free_list(), get_module_global_arguments(), ifdebug, instruction_to_total_precondition(), list_undefined, load_statement_precondition(), load_statement_total_precondition(), load_statement_transformer(), MAPL, ORDERING_NUMBER, ORDERING_STATEMENT, pips_assert, pips_debug, pips_internal_error, print_transformer, statement_instruction, statement_number, statement_ordering, statement_reachable_p(), store_statement_total_precondition(), tf_equivalence_equalities_add(), transformer_arguments, transformer_consistency_p(), transformer_empty(), transformer_filter(), transformer_normalize(), transformer_range(), and transformer_undefined.

Referenced by block_to_total_precondition(), loop_to_total_precondition(), module_name_to_total_preconditions(), test_to_total_precondition(), and unstructured_to_total_precondition().

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

◆ statement_to_transformer()

transformer statement_to_transformer ( statement  s,
transformer  spre 
)

stmt precondition

old transformer for s

new transformer for s under spre

nt updated with loop exit information

Transformation REFINE_TRANSFORMERS is being executed: add information available from the statement precondition

it would be nicer to control warning_on_redefinition

FI: OK, we will have to switch to the new declaration representation some day, but the old representation is still fine.

not very smart because declarations_to_transformer() computes post and free it...

add type information

FI: how do we want to handle declarations:

int i = 1; => T() {i==1}

or

int i = 1; => T(i) {i==1}

What is the impact of this choice? BC prefers the second one because it it consistent for convex effect computation.

Note: this issue could be dealt with earlier in declarations_to_transformer()

FI: the code below might be useful again when declarations are carried by any kind of statement

Option 1

Option 2, currently bugged

Currently, the preconditions is useless as only the effects will be used to compute the CONTINUE transformer.

Remove information cancelled by abstract effects

This correction should be moved down in test_to_transformer(), loop_to_transformer() and call_to_transformer() to reduce its impact. See Ticket 792.

add array references information using proper effects

nt = transformer_normalize(nt, 0);

add type information

nt = transformer_normalize(nt, 0);

When we leave a block the local stack allocated variables disappear

Get rid of the dynamic and stack variables declared in this block statement. No stack variable should be analyzed as the stack area is used only for dependent types.

nt = transformer_normalize(nt, 7);

nt = transformer_normalize(nt, 4);

(void) print_transformer(load_statement_transformer(s));

When the statement is virtually replicated via control nodes, the statement transformer is the convex hull of all its replicate transformers.

This implies that transformers are computed in context and that we are dealing with a non-deterministic unstructured with several nodes for a unique statement.

Written abstract locations may require some information destruction

The current implementation is too crude. A new function is needed, abstract_effects_to_transformer(). The current implementation is OK for anywhere effects.

Also, abstract effects should not be applied several times. For instance, a block statement cannot add new effects that have not already been taken into account. A test or a loop only add abstract effects linked to the condition or the loop control. Which leaves us mostly with call statements. Which means that abstract effects should be taken into account at a lower level.

This is mathematically correct but very inefficient (see ticket 644) and useless as long anymodule:anywhere is the only abstract effect we have to deal with.

Not a sufficient solution: free_transformer(t); t = etf;

store or update the statement transformer

delete_statement_transformer(s);

store_statement_transformer(s, t);

The transformer returned for the statement is not always the transformer stored for the statement. This happens for loops and for context sensitive transformers for replicated statements in CFG/unstructured. See comments in loop.c

Parameters
sprepre

Definition at line 3759 of file ri_to_transformers.c.

3762 {
3764  list e = NIL;
3766  transformer ot = transformer_undefined; /* old transformer for s */
3767  transformer nt = transformer_undefined; /* new transformer for s under spre */
3768  transformer te = transformer_undefined; /* nt updated with loop exit information */
3770 
3771  pips_debug(8,"begin for statement %03td (%td,%td) with precondition %p:\n",
3774  ifdebug(8) {
3775  pips_assert("The statement and its substatements are fully defined",
3777  (void) print_transformer(spre);
3778  }
3779 
3780  pips_assert("spre is a consistent precondition",
3781  transformer_consistent_p(spre));
3782 
3785 
3786  if(get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT")) {
3788  transformer_range(spre); // FI: transformer_range() implies
3789  // projection(s) and a possibly strong
3790  // increase of the number of
3791  // constraints. Many constraints may be
3792  // redundant as far as integer points
3793  // are concerned, but not redundant for
3794  // rational numbers. We could use an
3795  // approximate projection, elimination
3796  // of all constraints containing an old value...
3797  if(refine_transformers_p) {
3798  /* Transformation REFINE_TRANSFORMERS is being executed: add
3799  information available from the statement precondition */
3801  transformer srpre_r = transformer_range(srpre);
3802 
3803  pre = transformer_domain_intersection(pre, srpre_r);
3804  pre = transformer_normalize(pre, 2); // FI: redundancy
3805  // elimination required
3806  free_transformer(srpre_r);
3807  }
3808  }
3809  else {
3810  // Avoid lots of test in the callees ot statement_to_transformer
3811  // pre = transformer_undefined;
3812  pre = transformer_identity();
3813  }
3814 
3815  pips_assert("pre is a consistent precondition",
3817 
3818  pips_debug(8,"Range precondition pre:\n");
3819  ifdebug(8) {
3820  (void) print_transformer(pre);
3821  }
3822 
3825 
3826  /* it would be nicer to control warning_on_redefinition */
3827  if (transformer_undefined_p(ot)
3828  || get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT")) {
3829  //list dl = declaration_statement_p(s) ? statement_declarations(s) : NIL;
3831 
3832  /* FI: OK, we will have to switch to the new declaration
3833  representation some day, but the old representation is still
3834  fine.*/
3836  && !declaration_statement_p(s)) {
3837  // FI: Just to gain some time before dealing with controlizer and declarations updates
3838  //pips_internal_error("Statement %p carries declarations");
3839  semantics_user_warning("Statement %d (%p) carries declarations\n",
3840  statement_number(s), s);
3841  }
3842 
3843  if(!ENDP(dl)) {
3845  /* not very smart because declarations_to_transformer() computes post and free it...*/
3846  transformer post = transformer_apply(dt, pre);
3847  transformer ipre = transformer_range(post);
3849 
3850  // FI: this should not be duplicated. Temporary fix for modulo07.c
3851  /* add type information */
3852  /*
3853  if(get_bool_property("SEMANTICS_USE_TYPE_INFORMATION")) {
3854  transformer_add_type_information(nt);
3855  }
3856  */
3857 
3858  ifdebug(8) {
3859  pips_debug(8, "Statement local preconditions due to declarations:");
3860  print_transformer(ipre);
3861  }
3862 
3863  /* FI: how do we want to handle declarations:
3864  *
3865  * int i = 1; => T() {i==1}
3866  *
3867  * or
3868  *
3869  * int i = 1; => T(i) {i==1}
3870  *
3871  * What is the impact of this choice? BC prefers the second one
3872  * because it it consistent for convex effect computation.
3873  *
3874  * Note: this issue could be dealt with earlier in
3875  * declarations_to_transformer()
3876  */
3877  /* FI: the code below might be useful again when declarations
3878  are carried by any kind of statement */
3879  //it = instruction_to_transformer(i, ipre, e);
3880  //nt = transformer_combine(dt, it);
3881  //free_transformer(it);
3882  if(false) {
3883  /* Option 1 */
3884  nt = dt;
3885  }
3886  else if(false) {
3887  /* Option 2, currently bugged */
3888  /* Currently, the preconditions is useless as only the
3889  effects will be used to compute the CONTINUE transformer. */
3890  it = instruction_to_transformer(i, pre, e);
3891  nt = transformer_image_intersection(it, dt);
3892  free_transformer(it);
3893  free_transformer(dt);
3894  }
3895  else {
3896  nt = dt; // Do nothing because everything has been taken care of by
3897  // declaration_to_transformer()
3898  }
3899  free_transformer(post);
3900  // free_transformer(ipre);
3901  }
3902  else {
3903  nt = instruction_to_transformer(i, pre, e);
3904  }
3905 
3906  /* Remove information cancelled by abstract effects */
3907  /* This correction should be moved down in test_to_transformer(),
3908  loop_to_transformer() and call_to_transformer() to reduce its
3909  impact. See Ticket 792. */
3912  }
3913 
3914  /* add array references information using proper effects */
3915  if(get_bool_property("SEMANTICS_TRUST_ARRAY_REFERENCES")) {
3917  /* nt = transformer_normalize(nt, 0); */
3918  }
3919 
3920  /* add type information */
3921  if(get_bool_property("SEMANTICS_USE_TYPE_INFORMATION")
3922  || get_bool_property("SEMANTICS_USE_TYPE_INFORMATION_IN_TRANSFORMERS")) {
3924  /* nt = transformer_normalize(nt, 0); */
3925  }
3926 
3927  /* When we leave a block the local stack allocated variables
3928  disappear */
3929  if(statement_block_p(s) && !ENDP(dl=statement_declarations(s))) {
3930  /* Get rid of the dynamic and stack variables declared in this block
3931  statement. No stack variable should be analyzed as the stack
3932  area is used only for dependent types. */
3933  bool location_p = get_bool_property("SEMANTICS_ANALYZE_CONSTANT_PATH");
3934  if(location_p) {
3935  // This is a general case that should always work
3936  // The complexity is controlled by the length of the transformer basis
3937  list vl = transformer_to_local_values(nt, dl);
3938  if(!ENDP(vl))
3939  nt = safe_transformer_projection(nt, vl);
3940  }
3941  else { // The complexity is controlled by the length of dl
3943  if(!ENDP(vl))
3944  nt = safe_transformer_projection(nt, vl);
3945  }
3946  }
3947  /* nt = transformer_normalize(nt, 7); */
3948  /* nt = transformer_normalize(nt, 4); */
3949  nt = transformer_normalize(nt, 2);
3950 
3951  if(!transformer_consistency_p(nt)) {
3952  _int so = statement_ordering(s);
3953  (void) fprintf(stderr, "statement %03td (%td,%td):\n",
3954  statement_number(s),
3956  /* (void) print_transformer(load_statement_transformer(s)); */
3957  (void) print_transformer(nt);
3958  dump_transformer(nt);
3959  pips_internal_error("Inconsistent transformer detected");
3960  }
3961  ifdebug(1) {
3962  pips_assert("Transformer is internally consistent",
3964  }
3965 
3966  /* When the statement is virtually replicated via control nodes, the
3967  statement transformer is the convex hull of all its replicate
3968  transformers. */
3969  if(transformer_undefined_p(ot)) {
3970  if (get_int_property("SEMANTICS_NORMALIZATION_LEVEL_BEFORE_STORAGE") == 4)
3971  nt = transformer_normalize(nt, 4);
3972  t = copy_transformer(nt);
3973  }
3974  else {
3975  /* This implies that transformers are computed in context and that
3976  we are dealing with a non-deterministic unstructured with several
3977  nodes for a unique statement. */
3978  t = transformer_convex_hull(nt, ot);
3979 
3980  ifdebug(1) {
3981  pips_assert("transformers are computed in context",
3982  get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT"));
3983  pips_debug(1, "Convex hull for transformer of statement %03td (%td,%td)\n",
3986  pips_debug(1, "Previous transformer:\n");
3987  (void) print_transformer(ot);
3988  pips_debug(1, "New transformer:\n");
3989  (void) print_transformer(nt);
3990  pips_debug(1, "Resulting transformer:\n");
3991  (void) print_transformer(t);
3992  }
3993  }
3994 
3995  /* Written abstract locations may require some information destruction
3996  *
3997  * The current implementation is too crude. A new function is
3998  * needed, abstract_effects_to_transformer(). The current
3999  * implementation is OK for anywhere effects.
4000  *
4001  * Also, abstract effects should not be applied several times. For
4002  * instance, a block statement cannot add new effects that have not
4003  * already been taken into account. A test or a loop only add
4004  * abstract effects linked to the condition or the loop
4005  * control. Which leaves us mostly with call statements. Which means
4006  * that abstract effects should be taken into account at a lower
4007  * level.
4008  */
4009 
4010  //if(effects_abstract_location_p(e) && !statement_block_p(s)) {
4011  // FI: it would be better to use directly
4012  // apply_effects_to_transformer() and maybe legal to use
4013  // apply_additional_effects_to_transformer(). FI: it might be
4014  // safer to define apply_abstract_effects_to_transformer() as
4015  // suggested above.
4016  //transformer etf = effects_to_transformer(e);
4017  /* This is mathematically correct but very inefficient (see ticket
4018  644) and useless as long *anymodule*:*anywhere* is the only
4019  abstract effect we have to deal with.
4020  */
4021  //t = transformer_combine(t, etf);
4022  //nt = transformer_combine(nt, etf);
4023  //free_transformer(etf);
4024  //t = apply_abstract_effects_to_transformer(t, e);
4025  //nt = apply_abstract_effects_to_transformer(nt, e);
4026  /* Not a sufficient solution:
4027  free_transformer(t);
4028  t = etf;
4029  */
4030  //}
4031 
4032  /* store or update the statement transformer */
4033  if(transformer_undefined_p(ot)) {
4035  }
4036  else {
4037  transformer_free(ot);
4039  /* delete_statement_transformer(s); */
4040  /* store_statement_transformer(s, t); */
4041  }
4042  }
4043  else {
4044  semantics_user_warning("redefinition for statement %03d (%d,%d)\n",
4047  pips_internal_error("transformer redefinition");
4048  }
4049 
4050  ifdebug(1) {
4051  _int so = statement_ordering(s);
4053 
4054  (void) fprintf(stderr, "statement %03td (%td,%td), transformer %p:\n",
4055  statement_number(s),
4057  stf);
4058  (void) print_transformer(stf);
4059  pips_assert("same pointer", stf==t);
4060  }
4061 
4062  /* The transformer returned for the statement is not always the
4063  transformer stored for the statement. This happens for loops and for
4064  context sensitive transformers for replicated statements in
4065  CFG/unstructured. See comments in loop.c */
4066 
4067  te = complete_statement_transformer(nt, pre, s);
4068 
4069  free_transformer(pre);
4070 
4071  ifdebug(8) {
4072  pips_assert("The statement and its substatements are still fully defined",
4074  }
4075 
4076  pips_debug(8,"end for statement %03td (%td,%td) with t=%p, nt=%p and te=%p\n",
4078  ORDERING_STATEMENT(statement_ordering(s)), t, nt, te);
4079 
4081  (void) pop_statement_global_stack();
4082 
4083  return te;
4084 }
bool transformer_consistent_p(transformer p)
Definition: ri.c:2622
bool transformer_internal_consistency_p(transformer t)
Same as above but equivalenced variables should not appear in the argument list or in the predicate b...
Definition: basic.c:790
bool effects_abstract_location_p(list)
Returns true if at least one effect of effect list el is related to an abstract location.
Definition: effects.c:288
bool all_statements_defined_p(statement)
Definition: statement.c:3213
void transformer_add_reference_information(transformer tf, statement s)
static transformer instruction_to_transformer(instruction i, transformer pre, list e)
effects associated to instruction i
static transformer apply_abstract_effects_to_transformer(transformer tf, list el)
list dynamic_variables_to_values(list list_mod)
Build the list of values to be projected when the declaration list list_mod is no longer valid becaus...
Definition: mappings.c:1007
void store_statement_transformer(statement, transformer)
void update_statement_transformer(statement, transformer)
transformer transformer_image_intersection(transformer t1, transformer t2)
allocate a new transformer based on transformer t1 and postcondition t2
Definition: transformer.c:608
list transformer_to_local_values(transformer tf, list dl)
Build a list of values appearing in tf that are linked to a variable in dl.
Definition: transformer.c:2821

References all_statements_defined_p(), apply_abstract_effects_to_transformer(), complete_statement_transformer(), copy_transformer(), declaration_statement_p(), declarations_to_transformer(), dump_transformer, dynamic_variables_to_values(), effects_abstract_location_p(), ENDP, fprintf(), free_transformer(), get_bool_property(), get_int_property(), ifdebug, instruction_to_transformer(), load_cumulated_rw_effects_list(), load_statement_precondition(), load_statement_transformer(), NIL, ORDERING_NUMBER, ORDERING_STATEMENT, pips_assert, pips_debug, pips_internal_error, pop_statement_global_stack(), print_transformer, push_statement_on_statement_global_stack(), refine_transformers_p, safe_transformer_projection(), semantics_user_warning, statement_block_p, statement_declarations, statement_global_stack_defined_p(), statement_instruction, statement_number, statement_ordering, stf(), store_statement_transformer(), transformer_add_reference_information(), transformer_add_type_information(), transformer_apply(), transformer_consistency_p(), transformer_consistent_p(), transformer_convex_hull(), transformer_domain_intersection(), transformer_free(), transformer_identity(), transformer_image_intersection(), transformer_internal_consistency_p(), transformer_normalize(), transformer_range(), transformer_to_local_values(), transformer_undefined, transformer_undefined_p, and update_statement_transformer().

Referenced by any_loop_to_k_transformer(), block_to_transformer(), dag_or_cycle_to_flow_sensitive_postconditions_or_transformers(), generic_module_name_to_transformers(), loop_to_transformer(), process_ready_node(), process_unreachable_node(), standard_whileloop_to_transformer(), test_to_transformer(), test_to_transformer_list(), unreachable_node_to_transformer(), and unstructured_to_transformers().

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

◆ statement_to_transformer_list()

list statement_to_transformer_list ( statement  s,
transformer  spre 
)

A transformer is already available for statement s, but it is going to be refined into a list of transformers to isolate at least the identity transformer from effective transformers.

stmt precondition

Transformation REFINE_TRANSFORMERS is being executed: add information available from the statement precondition

it would be nicer to control warning_on_redefinition

FI: an empty tl means that s does not return. An undefined tl means that instruction_to_transformer() is not implemented in a satisfactory way. So the existing transformer is used by default.

add array references information using proper effects

nt = transformer_normalize(nt, 0);

When we leave a block the local stack allocated variables disappear

Get rid of the dynamic and stack variables declared in this block statement. No stack variable should be analyzed as the stack area is used only for dependent types.

nt = transformer_normalize(nt, 7);

nt = transformer_normalize(nt, 4);

(void) print_transformer(load_statement_transformer(s));

The transformer returned for the statement is not always the transformer stored for the statement. This happens for loops and for context sensitive transformers for replicated statements in CFG/unstructured. See comments in loop.c

Parameters
sprepre

Definition at line 978 of file ri_to_transformer_lists.c.

980 {
983  list tl = NIL;
984  list e = NIL;
985  //transformer t = transformer_undefined;
986  //transformer ot = transformer_undefined; /* old transformer for s */
987  //transformer nt = transformer_undefined; /* new transformer for s under spre */
988  //transformer te = transformer_undefined; /* nt updated with loop exit information */
990 
991  pips_debug(8,"begin for statement %03td (%td,%td) with precondition %p:\n",
994  ifdebug(8) {
995  pips_assert("The statement and its substatements are fully defined",
997  (void) print_transformer(spre);
998  }
999 
1000  pips_assert("spre is a consistent precondition",
1001  transformer_consistent_p(spre));
1002 
1003  if(get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT")) {
1005  transformer_range(spre);
1006  if(refine_transformers_p) {
1007  /* Transformation REFINE_TRANSFORMERS is being executed: add
1008  information available from the statement precondition */
1010  transformer srpre_r = transformer_range(srpre);
1011 
1012  pre = transformer_domain_intersection(pre, srpre_r);
1013  free_transformer(srpre_r);
1014  }
1015  }
1016  else {
1017  // Avoid lots of test in the callees
1018  // pre = transformer_undefined;
1019  pre = transformer_identity();
1020  }
1021 
1022  pips_assert("pre is a consistent precondition",
1024 
1025  pips_debug(8,"Range precondition pre:\n");
1026  ifdebug(8) {
1027  (void) print_transformer(pre);
1028  }
1029 
1030  // Probably not useful
1032 
1033  /* it would be nicer to control warning_on_redefinition */
1034  if (true) {
1036 
1037  if(!ENDP(dl)) {
1039  tl = CONS(TRANSFORMER, dt, NIL);
1040  }
1041  else {
1042  tl = instruction_to_transformer_list(i, tf, pre, e);
1043  /* FI: an empty tl means that s does not return. An undefined
1044  tl means that instruction_to_transformer() is not
1045  implemented in a satisfactory way. So the existing
1046  transformer is used by default. */
1047  if(list_undefined_p(tl)) {
1049  tl = CONS(TRANSFORMER, copy_transformer(tf), NIL);
1050  }
1051  }
1052 
1053  FOREACH(TRANSFORMER, nt, tl) {
1054  /* add array references information using proper effects */
1055  if(get_bool_property("SEMANTICS_TRUST_ARRAY_REFERENCES")) {
1057  /* nt = transformer_normalize(nt, 0); */
1058  }
1059 
1060  /* When we leave a block the local stack allocated variables
1061  disappear */
1062  if(statement_block_p(s) && !ENDP(dl=statement_declarations(s))) {
1063  /* Get rid of the dynamic and stack variables declared in this block
1064  statement. No stack variable should be analyzed as the stack
1065  area is used only for dependent types. */
1067  if(!ENDP(vl))
1068  nt = safe_transformer_projection(nt, vl);
1069  }
1070  /* nt = transformer_normalize(nt, 7); */
1071  /* nt = transformer_normalize(nt, 4); */
1072  nt = transformer_normalize(nt, 2);
1073 
1074  if(!transformer_consistency_p(nt)) {
1075  _int so = statement_ordering(s);
1076  (void) fprintf(stderr, "statement %03td (%td,%td):\n",
1077  statement_number(s),
1079  /* (void) print_transformer(load_statement_transformer(s)); */
1080  (void) print_transformer(nt);
1081  dump_transformer(nt);
1082  pips_internal_error("Inconsistent transformer detected");
1083  }
1084  ifdebug(1) {
1085  pips_assert("Transformer is internally consistent",
1087  }
1088  }
1089 
1090 #if 0
1091  /* When the statement is virtually replicated via control nodes, the
1092  statement transformer is the convex hull of all its replicate
1093  transformers. */
1094  if(transformer_undefined_p(ot)) {
1095  if (get_int_property("SEMANTICS_NORMALIZATION_LEVEL_BEFORE_STORAGE") == 4)
1096  nt = transformer_normalize(nt, 4);
1097  t = copy_transformer(nt);
1098  }
1099  else {
1100  /* This implies that transformers are computed in context and that
1101  we are dealing with a non-deterministic unstructured with several
1102  nodes for a unique statement. */
1103  t = transformer_convex_hull(nt, ot);
1104 
1105  ifdebug(1) {
1106  pips_assert("transformers are computed in context",
1107  get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT"));
1108  pips_debug(1, "Convex hull for transformer of statement %03td (%td,%td)\n",
1111  pips_debug(1, "Previous transformer:\n");
1112  (void) print_transformer(ot);
1113  pips_debug(1, "New transformer:\n");
1114  (void) print_transformer(nt);
1115  pips_debug(1, "Resulting transformer:\n");
1116  (void) print_transformer(t);
1117  }
1118  }
1119 
1120  /* store or update the statement transformer */
1121  if(transformer_undefined_p(ot)) {
1123  }
1124  else {
1125  transformer_free(ot);
1127  /* delete_statement_transformer(s); */
1128  /* store_statement_transformer(s, t); */
1129  }
1130 #endif
1131  }
1132  else {
1133  semantics_user_warning("redefinition for statement %03d (%d,%d)\n",
1134  statement_number(s),
1137  pips_internal_error("transformer redefinition");
1138  }
1139 
1140  /* The transformer returned for the statement is not always the
1141  transformer stored for the statement. This happens for loops and for
1142  context sensitive transformers for replicated statements in
1143  CFG/unstructured. See comments in loop.c */
1144 
1145  // FI: Should not be useful for transformer lists? Why?
1146  // te = complete_statement_transformer(nt, pre, s);
1147 
1148  free_transformer(pre);
1149 
1150  ifdebug(8) {
1151  pips_assert("The statement and its substatements are still fully defined",
1153  }
1154 
1155  //pips_debug(8,"end for statement %03td (%td,%td) with t=%p, nt=%p and te=%p\n",
1156  // statement_number(s), ORDERING_NUMBER(statement_ordering(s)),
1157  // ORDERING_STATEMENT(statement_ordering(s)), t, nt, te);
1158 
1159  ifdebug(1) {
1160  pips_debug(1, "Transformer list has %zd elements:\n", gen_length(tl));
1161  print_transformers(tl);
1162  }
1163 
1164  return tl;
1165 }
static list instruction_to_transformer_list(instruction i, transformer tf, transformer pre, list e)
effects associated to instruction i

References all_statements_defined_p(), CONS, copy_transformer(), declaration_statement_p(), declarations_to_transformer(), dump_transformer, dynamic_variables_to_values(), ENDP, FOREACH, fprintf(), free_transformer(), gen_length(), get_bool_property(), get_int_property(), ifdebug, instruction_to_transformer_list(), list_undefined_p, load_cumulated_rw_effects_list(), load_statement_precondition(), load_statement_transformer(), NIL, ORDERING_NUMBER, ORDERING_STATEMENT, pips_assert, pips_debug, pips_internal_error, print_transformer, print_transformers(), refine_transformers_p, safe_transformer_projection(), semantics_user_warning, statement_block_p, statement_declarations, statement_instruction, statement_number, statement_ordering, store_statement_transformer(), TRANSFORMER, transformer_add_reference_information(), transformer_consistency_p(), transformer_consistent_p(), transformer_convex_hull(), transformer_domain_intersection(), transformer_free(), transformer_identity(), transformer_internal_consistency_p(), transformer_normalize(), transformer_range(), transformer_undefined, transformer_undefined_p, and update_statement_transformer().

Referenced by block_to_transformer_list(), test_to_transformer_list(), and whileloop_to_postcondition().

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

◆ statement_total_precondition_undefined_p()

bool statement_total_precondition_undefined_p ( statement  )

◆ statement_transformer_undefined_p()

bool statement_transformer_undefined_p ( statement  )

◆ statement_weakly_feasible_p()

bool statement_weakly_feasible_p ( statement  s)

utils.c

utils.c

bool feasible_p = !transformer_empty_p(pre);

FI: this test is much stronger than I intended. I just wanted to check that the predicate of pre was exactly sc_empty()!

Now I'm afraid to change it. suppress_dead_code isn't that slow on ocean. I'm not sure that I could validate Transformations.

Definition at line 72 of file utils.c.

73 {
75  /* bool feasible_p = !transformer_empty_p(pre); */
76 
77  /* FI: this test is much stronger than I intended. I just wanted
78  * to check that the predicate of pre was exactly sc_empty()!
79  *
80  * Now I'm afraid to change it. suppress_dead_code isn't that slow
81  * on ocean. I'm not sure that I could validate Transformations.
82  */
83 
85 
86  bool feasible_p = !sc_empty_p(sc);
87 
88  return feasible_p;
89 }
bool sc_empty_p(Psysteme sc)
bool sc_empty_p(Psysteme sc): check if the set associated to sc is the constant sc_empty or not.
Definition: sc_alloc.c:350

References load_statement_precondition(), predicate_system, sc_empty_p(), and transformer_relation.

Referenced by interprocedural_abc_arrays().

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

◆ store_statement_postcondition()

void store_statement_postcondition ( statement  ,
transformer   
)

◆ store_statement_precondition()

void store_statement_precondition ( statement  ,
transformer   
)

Referenced by statement_to_postcondition().

+ Here is the caller graph for this function:

◆ store_statement_semantic()

void store_statement_semantic ( statement  ,
transformer   
)

◆ store_statement_total_precondition()

void store_statement_total_precondition ( statement  ,
transformer   
)

Referenced by statement_to_total_precondition().

+ Here is the caller graph for this function:

◆ store_statement_transformer()

void store_statement_transformer ( statement  ,
transformer   
)

Referenced by statement_to_transformer(), and statement_to_transformer_list().

+ Here is the caller graph for this function:

◆ string_expression_to_transformer()

transformer string_expression_to_transformer ( entity  v,
expression  rhs 
)

tf = constant_to_transformer(v, call_function(syntax_call(srhs)));

Parameters
rhshs

Definition at line 3994 of file expression.c.

3996 {
3998  syntax srhs = expression_syntax(rhs);
3999 
4000  switch(syntax_tag(srhs)) {
4001  case is_syntax_call:
4002  switch(gen_length(call_arguments(syntax_call(srhs)))) {
4003  case 0:
4004  /* tf = constant_to_transformer(v, call_function(syntax_call(srhs))); */
4005  tf = constant_to_transformer(v, rhs);
4006  break;
4007  case 1:
4008  break;
4009  case 2:
4010  break;
4011  case 3:
4012  break;
4013  default:
4014  pips_internal_error("Too many arguments, %d, for operator %s",
4017  }
4018  break;
4019  case is_syntax_reference:
4020  {
4022 
4023  if(entity_has_values_p(r)) {
4026 
4027  if(basic_string_p(bv) && basic_string_p(br)) {
4028  int llhs = string_type_size(bv);
4029  int lrhs = string_type_size(br);
4030 
4031  if(llhs == -1 || llhs >= lrhs) {
4032  entity r_new = entity_to_new_value(r);
4033  tf = simple_equality_to_transformer(v, r_new, false);
4034  }
4035  }
4036  else {
4037  pips_user_error("Incompatible type in CHARACTER assignment: %s\n",
4038  basic_to_string(br));
4039  }
4040  }
4041  break;
4042  }
4043  case is_syntax_range:
4044  pips_internal_error("Unexpected tag %d", syntax_tag(srhs));
4045  break;
4046  default:
4047  pips_internal_error("Illegal tag %d", syntax_tag(srhs));
4048  }
4049 
4050  return tf;
4051 }
int string_type_size(basic)
Definition: type.c:1047
#define basic_string_p(x)
Definition: ri.h:629
static transformer constant_to_transformer(entity v, expression rhs)
Definition: expression.c:645

References basic_string_p, basic_to_string(), call_arguments, call_function, constant_to_transformer(), entity_has_values_p(), entity_name, entity_to_new_value(), entity_type, expression_syntax, gen_length(), is_syntax_call, is_syntax_range, is_syntax_reference, pips_internal_error, pips_user_error, reference_variable, simple_equality_to_transformer(), string_type_size(), syntax_call, syntax_reference, syntax_tag, transformer_undefined, type_variable, and variable_basic.

Referenced by any_expression_to_transformer().

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

◆ string_predicate_to_commentary()

text string_predicate_to_commentary ( string  str_pred,
string  comment_prefix 
)

text string_predicate_to_commentary(string str_pred, string comment_prefix) input : a string, part of which represents a predicate.

output : a text consisting of several lines of commentaries, containing the string str_pred, and beginning with comment_prefix. modifies : str_pred;

if str_pred is too long, it must be splitted in several lines; the hyphenation must be done only between the constraints of the predicate, when there is a "," or a ")". A space is added at the beginning of extra lines, for indentation.

search the maximal substring which length is less than longueur_max

add it to the text

if the remaining string fits in one line

Parameters
str_predtr_pred
comment_prefixomment_prefix

Definition at line 570 of file prettyprint.c.

573 {
574  text t_pred = make_text(NIL);
575  string str_suiv = NULL;
576  string str_prefix = comment_prefix;
577  char str_tmp[MAX_PRED_COMMENTARY_STRLEN];
578  int len, new_str_pred_len, longueur_max;
579  bool premiere_ligne = true;
580  bool foresys = get_bool_property("PRETTYPRINT_FOR_FORESYS");
581  longueur_max = MAX_PRED_COMMENTARY_STRLEN - strlen(str_prefix) - 2;
582 
583  /* if str_pred is too long, it must be splitted in several lines;
584  * the hyphenation must be done only between the constraints of the
585  * predicate, when there is a "," or a ")". A space is added at the beginning
586  * of extra lines, for indentation. */
587  while((len = strlen(str_pred)) > 0) {
588  if (len > longueur_max) {
589 
590  /* search the maximal substring which length
591  * is less than longueur_max */
592  str_tmp[0] = '\0';
593  (void) strncat(str_tmp, str_pred, longueur_max);
594 
595  if (foresys)
596  str_suiv = strrchr(str_tmp, ')');
597  else
598  str_suiv = strrchr(str_tmp, ',');
599 
600  new_str_pred_len = (strlen(str_tmp) - strlen(str_suiv)) + 1;
601  str_suiv = strdup(&(str_pred[new_str_pred_len]));
602 
603  str_tmp[0] = '\0';
604  if (!premiere_ligne)
605  (void) strcat(str_tmp, " ");
606  (void) strncat(str_tmp, str_pred, new_str_pred_len);
607 
608  /* add it to the text */
609  ADD_SENTENCE_TO_TEXT(t_pred,
611  str_prefix));
612  str_pred = str_suiv;
613  }
614  else {
615  /* if the remaining string fits in one line */
616  str_tmp[0] = '\0';
617  if (!premiere_ligne)
618  (void) strcat(str_tmp, " ");
619  (void) strcat(str_tmp, str_pred);
620 
621  ADD_SENTENCE_TO_TEXT(t_pred,
623  str_prefix));
624  str_pred[0] = '\0';
625  }
626 
627  if (premiere_ligne) {
628  premiere_ligne = false;
629  longueur_max = longueur_max - 1;
630  if (foresys){
631  int i;
632  int nb_espaces = strlen(str_prefix) -
634 
635  str_prefix = strdup(str_prefix);
636  str_prefix[0] = '\0';
637  (void) strcat(str_prefix, FORESYS_CONTINUATION_PREFIX);
638  for (i=1; i <= nb_espaces; i++)
639  (void) strcat(str_prefix, " ");
640  }
641  }
642  }
643 
644  return(t_pred);
645 }
text make_text(list a)
Definition: text.c:107
sentence make_pred_commentary_sentence(string str_pred, string comment_prefix)
sentence make_pred_commentary_sentence(string str_pred, string comment_prefix) input : a substring fo...
Definition: prettyprint.c:678
#define MAX_PRED_COMMENTARY_STRLEN
to convert strings containing predicates to text of commentaries
Definition: prettyprint.c:560
#define FORESYS_CONTINUATION_PREFIX
#define ADD_SENTENCE_TO_TEXT(t, p)

References ADD_SENTENCE_TO_TEXT, FORESYS_CONTINUATION_PREFIX, get_bool_property(), make_pred_commentary_sentence(), make_text(), MAX_PRED_COMMENTARY_STRLEN, NIL, and strdup().

Referenced by words_predicate_to_commentary().

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

◆ struct_reference_assignment_to_transformer()

transformer struct_reference_assignment_to_transformer ( reference  r,
type  t,
expression  rhs,
transformer  pre,
list  ef 
)
Parameters
rhshs
prere
eff

Definition at line 3078 of file ri_to_transformers.c.

3079 {
3080  return struct_reference_assignment_or_equality_to_transformer(r, t, rhs, pre, ef, true);
3081 }
static transformer struct_reference_assignment_or_equality_to_transformer(reference r, type t, expression rhs, transformer pre, list ef __attribute__((unused)), bool assign_p)

References struct_reference_assignment_or_equality_to_transformer().

Referenced by assign_rhs_to_reflhs_to_transformer(), and struct_variable_assignment_to_transformer().

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

◆ struct_reference_equality_to_transformer()

transformer struct_reference_equality_to_transformer ( reference  r,
type  t,
expression  rhs,
transformer  pre,
list  ef 
)
Parameters
rhshs
prere
eff

Definition at line 3083 of file ri_to_transformers.c.

3084 {
3085  return struct_reference_assignment_or_equality_to_transformer(r, t, rhs, pre, ef, false);
3086 }

References struct_reference_assignment_or_equality_to_transformer().

Referenced by struct_variable_equality_to_transformer().

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

◆ struct_variable_assignment_to_transformer()

transformer struct_variable_assignment_to_transformer ( entity  v,
type  t,
expression  rhs,
transformer  pre,
list  ef 
)
Parameters
vassigned struct variable (does not handle the general case, "e1==e2;" where e1 and e2 are lhs expressions
ttype of v, which much be matched by rhs expression type and which must not contain any named type
rhsright-hand side expression
eflist of effects
preprecondition of the assignment
Returns
a transformer that must be defined as some field assignments may be analyzable whereas others just generate side-effects
Parameters
rhshs
prere
eff

Definition at line 3100 of file ri_to_transformers.c.

3101 {
3102  reference r = make_reference(v, NIL);
3104  free_reference(r);
3105  return tf;
3106 }
transformer struct_reference_assignment_to_transformer(reference r, type t, expression rhs, transformer pre, list ef)

References free_reference(), make_reference(), NIL, and struct_reference_assignment_to_transformer().

Referenced by assign_rhs_to_reflhs_to_transformer(), and c_return_to_transformer().

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

◆ struct_variable_equality_to_transformer()

transformer struct_variable_equality_to_transformer ( entity  v,
type  t,
expression  rhs,
transformer  pre,
list  ef 
)
Parameters
rhshs
prere
eff

Definition at line 3108 of file ri_to_transformers.c.

3109 {
3110  reference r = make_reference(v, NIL);
3111  transformer tf = struct_reference_equality_to_transformer(r, t, rhs, pre, ef);
3112  free_reference(r);
3113  return tf;
3114 }
transformer struct_reference_equality_to_transformer(reference r, type t, expression rhs, transformer pre, list ef)

References free_reference(), make_reference(), NIL, and struct_reference_equality_to_transformer().

Referenced by any_user_call_site_to_transformer().

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

◆ substitute_formal_array_elements_in_precondition()

transformer substitute_formal_array_elements_in_precondition ( transformer  tf,
entity  f,
list  pc,
transformer  pre,
list  ef 
)
Parameters
tff
pcc
prere
eff

Definition at line 2014 of file ri_to_transformers.c.

2015 {
2016  return generic_substitute_formal_array_elements_in_transformer(tf, f, pc, pre, ef, false);
2017 }
transformer generic_substitute_formal_array_elements_in_transformer(transformer tf, entity f, list pc, transformer pre, list ef __attribute__((unused)), bool backward_p)
Early version.

References f(), and generic_substitute_formal_array_elements_in_transformer().

Referenced by process_call_for_summary_precondition().

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

◆ substitute_formal_array_elements_in_transformer()

transformer substitute_formal_array_elements_in_transformer ( transformer  tf,
entity  f,
list  pc,
transformer  pre,
list  ef 
)
Parameters
tff
pcc
prere
eff

Definition at line 2009 of file ri_to_transformers.c.

2010 {
2011  return generic_substitute_formal_array_elements_in_transformer(tf, f, pc, pre, ef, true);
2012 }

References f(), and generic_substitute_formal_array_elements_in_transformer().

Referenced by c_user_call_to_transformer().

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

◆ substitute_scalar_stub_in_transformer()

transformer substitute_scalar_stub_in_transformer ( transformer  tf,
entity  se,
entity  de,
bool  backward_p,
list ppl 
)

If both "se", source entity, and "de", destination entity, are defined, substitute the values of "se" by the values of "de" in "backward_p" mode, when translating a callee transformer at a call site of a caller.

If the "se" entity cannot be substituted, its value must be project.

Parameters
tff
see
dee
backward_packward_p
pplpl

Definition at line 136 of file points_to.c.

137 {
138  if(entity_undefined_p(se))
139  ;
140  else if(entity_undefined_p(de))
141  *ppl = CONS(ENTITY, se, *ppl);
142  else if(entity_has_values_p(de)) {
143  // Not in the caller's frame
144  // entity nsv = entity_to_new_value(se);
145  entity nsv = se;
146  entity ndv = entity_to_new_value(de);
147  if(backward_p) { // For transformers
148  tf = transformer_value_substitute(tf, nsv, ndv);
149  }
150  else { // For preconditions
151  tf = transformer_value_substitute(tf, ndv, nsv);
152  }
153  // Careful, se has been substituted in the argument too
156  entity odv = entity_to_old_value(de);
157  if(backward_p) { // For transformers
158  tf = transformer_value_substitute(tf, osv, odv);
159  }
160  else { // For preconditions
161  tf = transformer_value_substitute(tf, odv, osv);
162  }
163  }
164  }
165  else {
166  // FI: could be some debugging stuff
167  pips_user_warning("Stub \"%s\" cannot be substituted.\n",
168  entity_user_name(de));
169  // FI: entity "de" must be projected
170  *ppl = CONS(ENTITY, se, *ppl);
171  }
172  return tf;
173 }
entity global_new_value_to_global_old_value(entity)
Definition: value.c:716

References CONS, ENTITY, entity_has_values_p(), entity_is_argument_p(), entity_to_new_value(), entity_to_old_value(), entity_undefined_p, entity_user_name(), global_new_value_to_global_old_value(), pips_user_warning, transformer_arguments, and transformer_value_substitute().

Referenced by forward_substitute_array_location_in_transformer(), new_array_element_backward_substitution_in_transformer(), substitute_struct_stub_in_transformer(), and substitute_stubs_in_transformer().

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

◆ substitute_struct_stub_in_transformer()

transformer substitute_struct_stub_in_transformer ( transformer  ,
reference  ,
type  ,
reference  ,
type  ,
bool  ,
list  
)

◆ substitute_stubs_in_transformer()

transformer substitute_stubs_in_transformer ( transformer  tf,
call  c,
statement  s,
bool  backward_p 
)

Exploit the binding map to substitute calles's stubs by actual arguments, which may be stubs of the callers,.

backward_p request a substitution from the callees' frame into the caller's frame, which is useful for transformers. Flag backward_p is set to false to compute summary preconditions.

FI: this function is now only used for preconditions. It has been rewritten for transformers to speed up the process when array elements are involved. It is better to start from the needs, the stubs used in the transformer, than from all possible stubs, but it is much easier for a backward translation. With a forward translation, regular variables may have to be translated into stubs.

FI: A quick improvement would to return when no translation is needed... but you do not always know it when backward_p is set to false.

Parameters
tff
backward_packward_p

Definition at line 256 of file points_to.c.

257 {
259  list ll = backward_p? transformer_to_analyzed_locations(tf)
261  if(ENDP(ll)) {
262  // Return tf as is
263  ;
264  }
265  else if(pt_to_list_undefined_p()) {
266  // Return tf as is
267  }
268  else {
270  bool bottom_p = points_to_graph_bottom(ptg);
271 
272  if(bottom_p) {
273  // FI: should this lead to an empty transformer?
274  pips_internal_error("Not implemented yet.\n");
275  }
276  else {
278  list pl = NIL; // FI: I am not sure we can managed forward and
279  // backward projections with one variable
280  SET_FOREACH(points_to, pt, binding) {
282  if(relevant_translation_pair_p(pt, ll)
284  cell s = points_to_source(pt); // callee if backward_p
285  cell d = points_to_sink(pt); // caller if backward_p
288  // This test should be useless because this is guaranteed by
289  // the approximation, except if binding is corrupted.
291  list srs = reference_indices(sr);
292  list drs = reference_indices(dr);
293  if(ENDP(srs) && ENDP(drs)) {
294  entity se = reference_variable(sr);
295  entity de = reference_variable(dr);
296  //type se_t = entity_basic_concrete_type(se);
297  //type de_t = entity_basic_concrete_type(de);
298  if(entity_has_values_p(de))
299  tf = substitute_scalar_stub_in_transformer(tf, se, de, backward_p, &pl);
300  else {
301  type se_t = entity_basic_concrete_type(se);
302  type de_t = entity_basic_concrete_type(de);
303  if(type_struct_variable_p(se_t)) {
304  tf = substitute_struct_stub_in_transformer(tf, sr, se_t, dr, de_t, backward_p, &pl);
305  }
306  else
307  pl = CONS(ENTITY, se, pl);
308  }
309  }
310  else if(ENDP(srs) && !ENDP(drs)) {
311  entity se = reference_variable(sr);
312  if(analyzed_reference_p(dr)) {
314  tf = substitute_scalar_stub_in_transformer(tf, se, de, backward_p, &pl);
315  }
316  else {
317  pl = CONS(ENTITY, se, pl);
318  }
319  }
320  else if(!ENDP(srs) && ENDP(drs)) {
321  entity de = reference_variable(dr);
322  if(entity_has_values_p(de)) {
324  if(!entity_undefined_p(se))
325  tf = substitute_scalar_stub_in_transformer(tf, se, de, backward_p, &pl);
326  else
327  pips_internal_error("Not implemented yet.\n");
328  }
329  else {
330  type de_t = entity_basic_concrete_type(de);
331  if(type_struct_variable_p(de_t)) {
332  tf = substitute_struct_stub_in_transformer(tf, sr, de_t, dr, de_t, backward_p, &pl);
333  // tf = substitute_struct_stub_reference_in_transformer(tf, sr, de, backward_p, &pl);
334  }
335  else {
336  // Do nothing
337  // entity se = reference_variable(sr);
338  // pl = CONS(ENTITY, se, pl);
339  ;
340  }
341  }
342  }
343  else { // !ENDP(srs) & !ENDP(drs)
344  if(analyzed_reference_p(dr)) {
347  tf = substitute_scalar_stub_in_transformer(tf, se, de, backward_p, &pl);
348  }
349  else {
350  type st = reference_to_type(sr);
352  if(type_struct_variable_p(cst))
353  tf = substitute_struct_stub_in_transformer(tf, sr, cst, dr, cst, backward_p, &pl);
354  else {
355  // No useful information in this binding
356  ;
357  }
358  }
359  }
360  }
361  }
362  }
363  if(!ENDP(pl)) {
364  // Get rid on untranslatable entities
366  }
367  }
368  }
369 
370  gen_free_list(ll);
371 
372  return tf;
373 }
bool atomic_points_to_reference_p(reference r)
Definition: points_to.c:519
#define approximation_exact_p(x)
Definition: effects.h:369
#define approximation_must_p(x)
Definition: effects.h:366
#define points_to_approximation(x)
#define points_to_sink(x)
#define points_to_source(x)
type reference_to_type(reference)
Definition: type.c:2354
transformer substitute_struct_stub_in_transformer(transformer t, reference l, type lt, reference r, type rt __attribute__((unused)), bool backward_p, list *ppl)
Definition: points_to.c:175
static bool relevant_translation_pair_p(points_to pt, list ll)
The sources of the relevant points-to.
Definition: points_to.c:226
list transformer_to_analyzed_locations(transformer tf)
The list of location entities that appear in the basis of the transformer predicate.
Definition: transformer.c:2785
list transformer_to_potential_stub_translation(transformer tf, entity m __attribute__((unused)))
Provide a list of variables that might be forward translated into a stub when preconditions are propa...
Definition: transformer.c:2720

References analyzed_reference_p(), approximation_exact_p, approximation_must_p, atomic_points_to_reference_p(), cell_any_reference(), compute_basic_concrete_type(), CONS, constant_memory_access_path_to_location_entity(), ENDP, ENTITY, entity_basic_concrete_type(), entity_has_values_p(), entity_undefined_p, gen_free_list(), get_current_module_entity(), get_points_to_graph_from_statement(), NIL, pips_internal_error, pl, points_to_approximation, points_to_graph_bottom, points_to_sink, points_to_source, pt_to_list_undefined_p(), reference_indices, reference_to_type(), reference_variable, relevant_translation_pair_p(), safe_transformer_projection(), SET_FOREACH, substitute_scalar_stub_in_transformer(), substitute_struct_stub_in_transformer(), transformer_to_analyzed_locations(), transformer_to_potential_stub_translation(), type_struct_variable_p(), and user_call_to_points_to_interprocedural_binding_set().

Referenced by process_call_for_summary_precondition().

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

◆ summary_precondition()

bool summary_precondition ( char *  module_name)

transformer t = transformer_identity();

Add declaration information: arrays cannot be empty (Fortran standard, Section 5.1.2)

It does not seem to be a good idea for the semantics of SUMMARY_PRECONDITION. It seems better to have this information in the summary transformer as an input validity condition.

Try to put the summary precondition in a (partially) canonical form.

Parameters
module_nameodule_name

Definition at line 719 of file dbm_interface.c.

720 {
721  /* transformer t = transformer_identity(); */
724 
726 
730 
733  }
734  else {
736  }
737 
738  /* Add declaration information: arrays cannot be empty (Fortran
739  * standard, Section 5.1.2)
740  *
741  * It does not seem to be a good idea for the semantics of
742  * SUMMARY_PRECONDITION. It seems better to have this information in the
743  * summary transformer as an input validity condition.
744  *
745  */
746  if(false && get_bool_property("SEMANTICS_TRUST_ARRAY_DECLARATIONS")) {
748  db_get_memory_resource(DBR_CUMULATED_EFFECTS, module_name, true));
750  db_get_memory_resource(DBR_PROPER_EFFECTS, module_name, true));
757  }
758 
759  pips_assert("t is defined", !transformer_undefined_p(t));
760 
761  /* Try to put the summary precondition in a (partially) canonical form. */
762  t = transformer_normalize(t, 4);
763  t = transformer_normalize(t, 4);
764 
765  ifdebug(3) {
766  pips_debug(1, "considering summary precondition for %s\n", module_name);
767  dump_transformer(t);
768  }
769 
770  DB_PUT_MEMORY_RESOURCE(DBR_SUMMARY_PRECONDITION,
771  module_name, (char * )t);
772 
773  ifdebug(1) {
774  pips_debug(1,
775  "initial summary precondition %p for %s (%d call sites):\n",
777  dump_transformer(t);
778  pips_debug(1, "end for module %s\n", module_name);
779  }
780 
784  debug_off();
785 
786  return true;
787 }
static transformer main_summary_precondition(entity callee)
Special case: main module.
static transformer ordinary_summary_precondition(const char *module_name, entity callee)
Standard cases: called modules.
int get_call_site_number()

References callee, db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, dump_transformer, entity_main_module_p(), free_statement_global_stack(), free_value_mappings(), get_bool_property(), get_call_site_number(), get_current_module_entity(), ifdebug, main_summary_precondition(), make_statement_global_stack(), module_name(), module_name_to_entity(), module_to_value_mappings(), ordinary_summary_precondition(), pips_assert, pips_debug, reset_cumulated_rw_effects(), reset_current_module_entity(), reset_current_module_statement(), reset_proper_rw_effects(), SEMANTICS_DEBUG_LEVEL, set_cumulated_rw_effects(), set_current_module_entity(), set_current_module_statement(), set_proper_rw_effects(), transformer_add_declaration_information(), transformer_normalize(), transformer_undefined, and transformer_undefined_p.

Referenced by interprocedural_summary_precondition(), interprocedural_summary_precondition_with_points_to(), and intraprocedural_summary_precondition().

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

◆ summary_total_postcondition()

bool summary_total_postcondition ( char *  module_name)

Look for all call sites in the callers

transformer t = transformer_identity();

no callers => empty precondition (but the main). FC. 08/01/1999.

try to eliminate (some) redundancy at a reasonnable cost

t = transformer_normalize(t, 2);

what cost?

Add declaration information: arrays cannot be empty (Fortran standard, Section 5.1.2)

It does not seem to be a good idea for the semantics of SUMMARY_PRECONDITION. It seems better to have this information in the summary transformer as an input validity condition.

Parameters
module_nameodule_name

Definition at line 789 of file dbm_interface.c.

790 {
791  /* Look for all call sites in the callers
792  */
793  callees callers = (callees) db_get_memory_resource(DBR_CALLERS,
794  module_name,
795  true);
797  /* transformer t = transformer_identity(); */
799 
801 
802  pips_assert("Not implemented yet", false);
803 
805 
806  ifdebug(1) {
807  debug(1, "summary_precondition", "begin for %s with %d callers\n",
808  module_name,
809  gen_length(callees_callees(callers)));
811  (void) fprintf(stderr, "%s, ", caller_name);
812  }, callees_callees(callers));
813  (void) fprintf(stderr, "\n");
814  }
815 
817 
819  {
822  }, callees_callees(callers));
823 
824  if (!callees_callees(callers) &&
827  {
828  /* no callers => empty precondition (but the main).
829  FC. 08/01/1999.
830  */
831  pips_user_warning("empty precondition to %s "
832  "because not in call tree from main.\n", module_name);
833  t = transformer_empty();
834  } else if (transformer_undefined_p(t)) {
835  t = transformer_identity();
836  } else {
837  /* try to eliminate (some) redundancy at a reasonnable cost */
838  /* t = transformer_normalize(t, 2); */
839 
840  /* what cost? */
841  t = transformer_normalize(t, 7);
842  }
843 
844  /* Add declaration information: arrays cannot be empty (Fortran
845  * standard, Section 5.1.2)
846  *
847  * It does not seem to be a good idea for the semantics of
848  * SUMMARY_PRECONDITION. It seems better to have this information in the
849  * summary transformer as an input validity condition.
850  *
851  */
852  if(false && get_bool_property("SEMANTICS_TRUST_ARRAY_DECLARATIONS")) {
854  (statement) db_get_memory_resource(DBR_CODE, module_name, true));
856  db_get_memory_resource(DBR_CUMULATED_EFFECTS, module_name, true));
858  db_get_memory_resource(DBR_PROPER_EFFECTS, module_name, true));
866  }
867 
868  DB_PUT_MEMORY_RESOURCE(DBR_SUMMARY_TOTAL_POSTCONDITION,
869  module_name, (char * )t);
870 
871  ifdebug(1) {
872  pips_debug(1,
873  "summary total postcondition %p for %s (%d call sites):\n",
875  dump_transformer(t);
876  pips_debug(1, "end for module %s\n", module_name);
877  }
878 
880  debug_off();
881 
882  return true;
883 }
static const char * caller_name
Definition: alias_check.c:122
bool some_main_entity_p(void)
util.c
Definition: util.c:37
transformer update_precondition_with_call_site_preconditions(transformer t, entity caller, entity callee)
Update precondition t for callee with preconditions of call sites to callee in caller.
void reset_call_site_number()

References callee, callees_callees, caller_name, db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug(), debug_off, debug_on, dump_transformer, entity_main_module_p(), fprintf(), free_value_mappings(), gen_length(), get_bool_property(), get_call_site_number(), get_current_module_entity(), ifdebug, MAP, module_name(), module_name_to_entity(), module_to_value_mappings(), pips_assert, pips_debug, pips_user_warning, reset_call_site_number(), reset_cumulated_rw_effects(), reset_current_module_entity(), reset_current_module_statement(), reset_proper_rw_effects(), SEMANTICS_DEBUG_LEVEL, set_cumulated_rw_effects(), set_current_module_entity(), set_current_module_statement(), set_proper_rw_effects(), some_main_entity_p(), STRING, transformer_add_declaration_information(), transformer_empty(), transformer_identity(), transformer_normalize(), transformer_undefined, transformer_undefined_p, and update_precondition_with_call_site_preconditions().

+ Here is the call graph for this function:

◆ summary_total_precondition()

bool summary_total_precondition ( char *  module_name)

there is a choice: do nothing and leave the effective computation in module_name_to_total_preconditions or move it here

Parameters
module_nameodule_name

Definition at line 885 of file dbm_interface.c.

886 {
887  /* there is a choice: do nothing and leave the effective computation
888  in module_name_to_total_preconditions or move it here */
889  pips_debug(1, "considering module %s\n", module_name);
890  return true;
891 }

References module_name(), and pips_debug.

+ Here is the call graph for this function:

◆ summary_transformer()

bool summary_transformer ( char *  module_name)

There is a choice: do nothing and leave the effective computation in module_name_to_transformers, or move it here

There is another choice: distinguish between inter- and intra-procedural analyses at the summary level or in module_name_to_transformers(). The choice does not have to be consistent with the similar choice made for summary_precondition.

Parameters
module_nameodule_name

Definition at line 387 of file dbm_interface.c.

388 {
389  /* There is a choice: do nothing and leave the effective computation
390  in module_name_to_transformers, or move it here */
391  /* There is another choice: distinguish between inter- and
392  intra-procedural analyses at the summary level or in
393  module_name_to_transformers(). The choice does not have to be
394  consistent with the similar choice made for summary_precondition. */
395  pips_debug(1, "considering module %s\n", module_name);
396  return true;
397 }

References module_name(), and pips_debug.

+ Here is the call graph for this function:

◆ test_warning_counters()

bool test_warning_counters ( void  )

Definition at line 908 of file dbm_interface.c.

909 {
910  return wc++==0;
911 }

References wc.

Referenced by points_to_unary_operation_to_transformer().

+ Here is the caller graph for this function:

◆ text_for_a_transformer()

text text_for_a_transformer ( transformer  tran,
bool  is_a_transformer 
)

call this one from outside.

Parameters
tranran
is_a_transformers_a_transformer

Definition at line 540 of file prettyprint.c.

541 {
542  bool save_is_transformer = is_transformer;
543  bool save_is_total_precondition = is_total_precondition;
544  text t = text_undefined;
545 
546  is_transformer = is_a_transformer;
547  is_total_precondition = false;
548  t = text_transformer(tran);
549  is_transformer = save_is_transformer;
550  is_total_precondition = save_is_total_precondition;
551  return t;
552 }
#define text_undefined
Definition: text.h:91

References is_total_precondition, is_transformer, text_transformer(), and text_undefined.

Referenced by call_site_to_module_precondition_text().

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

◆ text_transformer()

text text_transformer ( transformer  tran)

text text_transformer(transformer tran) input : a transformer representing a transformer or a precondition output : a text containing commentaries representing the transformer modifies : nothing.

Modification: AP, Nov 10th, 1995. Instead of building a (very long) string, I directly use the transformer to build the prettyprint in text format. This is to avoid the problem occuring when the buffer used in transformer[precondition]_to_string() is too small. I also use a static buffer to build each constraint; we are restricted to constraints of lengths smaller than the line length.

If in EMACS mode, does not add any separator line:

Parameters
tranran

Definition at line 464 of file prettyprint.c.

465 {
466  text txt = make_text(NIL);
467  bool foresys = get_bool_property("PRETTYPRINT_FOR_FORESYS");
468  string str_prefix;
469  char crt_line[MAX_LINE_LENGTH];
470 
471  /* If in EMACS mode, does not add any separator line: */
472  if (get_bool_property("PRETTYPRINT_ANALYSES_WITH_LF")
473  && !get_bool_property("PRETTYPRINT_ADD_EMACS_PROPERTIES"))
475  strdup("\n")));
476 
477  str_prefix = foresys? FORESYS_CONTINUATION_PREFIX: get_comment_continuation();
478  crt_line[0] = '\0';
479 
480  if (foresys)
482  else
484 
485  if(tran != (transformer) HASH_UNDEFINED_VALUE &&
486  tran != (transformer) list_undefined) {
487  if(tran==transformer_undefined) {
488  if (is_transformer)
489  append(" TRANSFORMER: TRANSFORMER_UNDEFINED");
490  else if(is_total_precondition)
491  append(" TOTAL PRECONDITION: TRANSFORMER_UNDEFINED");
492  else
493  append(" PRECONDITION: TRANSFORMER_UNDEFINED");
494  }
495  else {
496  Psysteme ps;
497  list args = transformer_arguments(tran);
498 
499  append(is_transformer? " T(": (is_total_precondition? " TP(" : " P("));
500 
501  entity_list_text_format(crt_line, str_prefix, txt,
502  args, entity_minimal_name);
503 
504  append(")");
505  if (foresys) append(",");
506  append(" ");
507 
510 
511  ifdebug(7) {
512  pips_debug(7, "sys %p\n", ps);
513  sc_syst_debug(ps);
514  }
515 
516  system_text_format(crt_line, str_prefix, txt, ps,
517  (char * (*)(Variable)) pips_user_value_name, foresys);
518 
519  sc_rm(ps);
520  }
521 
522  close_current_line(crt_line, txt, str_prefix);
523  }
524 
525  if (get_bool_property("PRETTYPRINT_ANALYSES_WITH_LF")
526  && !get_bool_property("PRETTYPRINT_ADD_EMACS_PROPERTIES"))
528  strdup("\n")));
529 
530  ifdebug(7){
531  pips_debug(7, "final txt: \n");
532  dump_text(txt);
533  }
534 
535  return txt;
536 }
sentence make_sentence(enum sentence_utype tag, void *val)
Definition: text.c:59
void entity_list_text_format(string line, string continuation, text t, list le, const char *(*var_name)(entity))
appends the list of entity...
void system_text_format(string line, string prefix, text txt, Psysteme ps, string(*variable_name)(Variable), bool a_la_fortran)
appends ps to line/txt with prefix continuations.
void sc_syst_debug(Psysteme s)
constraint_to_text.c
const char * entity_minimal_name(entity e)
Do preserve scope informations.
Definition: naming.c:214
string get_comment_sentinel()
Start a single line comment.
Definition: misc.c:154
string get_comment_continuation()
Start a single line comment with continuation (blank spaces)
Definition: misc.c:167
Psysteme sc_copy(Psysteme ps)
Psysteme sc_copy(Psysteme ps): duplication d'un systeme (allocation et copie complete des champs sans...
Definition: sc_alloc.c:230
void sc_lexicographic_sort(Psysteme sc, int(*compare)(Pvecteur *, Pvecteur *))
Minimize first the lexico-graphic weight of each constraint according to the comparison function "com...
Definition: sc_unaires.c:206
static int semantics_is_inferior_pvarval(Pvecteur *pvarval1, Pvecteur *pvarval2)
The strange argument type is required by qsort(), deep down in the calls.
Definition: prettyprint.c:402
#define PREC_FORESYS_PREFIX
Definition: prettyprint.c:67
#define TRAN_FORESYS_PREFIX
Definition: prettyprint.c:68
#define append(s)
Definition: prettyprint.c:433
#define MAX_LINE_LENGTH
maximum length of a line when prettyprinting...
void dump_text(text t)
FI: print_text() should be fprint_text() and dump_text(), print_text()
Definition: print.c:205
void close_current_line(string, text, string)
Definition: util.c:235
@ is_sentence_formatted
Definition: text.h:57
const char * pips_user_value_name(entity)
This function is called many times when the constraints and the system of constraints are sorted usin...
Definition: value.c:815

References ADD_SENTENCE_TO_TEXT, append, close_current_line(), dump_text(), entity_list_text_format(), entity_minimal_name(), FORESYS_CONTINUATION_PREFIX, get_bool_property(), get_comment_continuation(), get_comment_sentinel(), HASH_UNDEFINED_VALUE, ifdebug, is_sentence_formatted, is_total_precondition, is_transformer, list_undefined, make_sentence(), make_text(), MAX_LINE_LENGTH, NIL, pips_debug, pips_user_value_name(), PREC_FORESYS_PREFIX, predicate_system, sc_copy(), sc_lexicographic_sort(), sc_rm(), sc_syst_debug(), semantics_is_inferior_pvarval(), strdup(), system_text_format(), TRAN_FORESYS_PREFIX, transformer_arguments, transformer_relation, and transformer_undefined.

Referenced by get_semantic_text(), print_initial_precondition(), print_program_precondition(), semantic_to_text(), and text_for_a_transformer().

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

◆ tf_equivalence_equalities_add()

transformer tf_equivalence_equalities_add ( transformer  tf)

mappings.c

I need here a contraintes_dup() that is not yet available in Linear and I cannot change Linear just before the DRET meeting; I've got to modify transformer_equalities_add() and to give it a behavior different from transformer_equality_add()

Parameters
tff

Definition at line 83 of file mappings.c.

84 {
85  /* I need here a contraintes_dup() that is not yet available
86  in Linear and I cannot change Linear just before the DRET meeting;
87  I've got to modify transformer_equalities_add() and to give it
88  a behavior different from transformer_equality_add() */
90  return tf;
91 }
transformer transformer_equalities_add(transformer tf, Pcontrainte eqs)
Definition: basic.c:391
static Pcontrainte equivalence_equalities
Variable value mappings package.
Definition: mappings.c:74

References equivalence_equalities, and transformer_equalities_add().

Referenced by statement_to_postcondition(), and statement_to_total_precondition().

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

◆ total_precondition_map_undefined_p()

bool total_precondition_map_undefined_p ( void  )

◆ total_preconditions_inter()

bool total_preconditions_inter ( char *  module_name)

set_int_property(SEMANTICS_DEBUG_LEVEL, 0);

Parameters
module_nameodule_name

Definition at line 487 of file dbm_interface.c.

488 {
495  /* set_int_property(SEMANTICS_DEBUG_LEVEL, 0); */
497 }
bool module_name_to_total_preconditions(const char *module_name)

References module_name(), module_name_to_total_preconditions(), select_fix_point_operator(), SEMANTICS_FIX_POINT, SEMANTICS_FLOW_SENSITIVE, SEMANTICS_INEQUALITY_INVARIANT, SEMANTICS_INTERPROCEDURAL, SEMANTICS_STDOUT, and set_bool_property().

+ Here is the call graph for this function:

◆ total_preconditions_intra()

bool total_preconditions_intra ( char *  module_name)

set_int_property(SEMANTICS_DEBUG_LEVEL, 0);

Parameters
module_nameodule_name

Definition at line 475 of file dbm_interface.c.

476 {
483  /* set_int_property(SEMANTICS_DEBUG_LEVEL, 0); */
485 }

References module_name(), module_name_to_total_preconditions(), select_fix_point_operator(), SEMANTICS_FIX_POINT, SEMANTICS_FLOW_SENSITIVE, SEMANTICS_INEQUALITY_INVARIANT, SEMANTICS_INTERPROCEDURAL, SEMANTICS_STDOUT, and set_bool_property().

+ Here is the call graph for this function:

◆ transformer_add_any_relation_information()

transformer transformer_add_any_relation_information ( transformer  pre,
entity  op,
expression  e1,
expression  e2,
transformer  context,
bool  veracity,
bool  upwards 
)

compute transformer or precondition

This is not satisfactory: when going upwards you might nevertheless benefit from some precondition information. But you would then need to pass two transformers as argument: a context transformer and a to-be-modified transformer

context = upwards? transformer_undefined : pre;

context = transformer_range(pre);

Logical are represented by integer values

PIPS does not represent negative constants: call to unary_minus

PIPS does not represent complex constants: call to CMPLX

Only constant string are processed

Pointer analysis

This is not correct if side effects occur in e1 or e2

This is very complicated to add constraints from tf1, tf2 and rel in pre!

tf1 may modify the initial context. See w10.f

tf1 disappears into cond

try to break rel it into two convex components

pre disappears into newpre2

pre disappears into newpre

newpre stays undefined or newpre is pre

free_transformer(tf1); already gone

Nothing to be done with struct and union

pre may be unchanged when no information is derived

Parameters
prere
opp
e11
e22
contextontext
veracityeracity
upwardspwards

Definition at line 4686 of file expression.c.

4694 {
4697  int t1 = semantics_basic_tag(b1);
4698  int t2 = semantics_basic_tag(b2);
4699 
4700  pips_debug(8, "begin %s with pre=%p\n",
4701  upwards? "upwards" : "downwards", pre);
4702 
4703  /* This is not satisfactory: when going upwards you might nevertheless
4704  benefit from some precondition information. But you would then need
4705  to pass two transformers as argument: a context transformer and a
4706  to-be-modified transformer */
4707 
4708  /* context = upwards? transformer_undefined : pre; */
4709  /* context = transformer_range(pre); */
4710 
4711  if( (t1==t2)
4712  || (t1==is_basic_int && t2==is_basic_string)
4713  || (t2==is_basic_int && t1==is_basic_string) ) {
4714 
4715  switch(t1) {
4716  case is_basic_logical:
4717  /* Logical are represented by integer values*/
4718  case is_basic_float:
4719  /* PIPS does not represent negative constants: call to unary_minus */
4720  case is_basic_complex:
4721  /* PIPS does not represent complex constants: call to CMPLX */
4722  case is_basic_string:
4723  /* Only constant string are processed */
4724  case is_basic_pointer:
4725  /* Pointer analysis */
4726  case is_basic_int:
4727  {
4728  /* This is not correct if side effects occur in e1 or e2 */
4729  /* This is very complicated to add constraints from tf1, tf2 and
4730  rel in pre! */
4734  /* tf1 may modify the initial context. See w10.f */
4736  : transformer_apply(tf1, context);
4737  transformer ncontext = transformer_range(pcontext);
4738  transformer tf2 = safe_any_expression_to_transformer(tmp2, e2, ncontext, true);
4739  // FI: not precise because the context is not taken into
4740  // account when non-convex information is available,
4741  // non-convex information that could be convex within the
4742  // context. But see below.
4743  transformer rel = relation_to_transformer(op, tmp1, tmp2, veracity);
4746 
4747  free_transformer(pcontext);
4748  free_transformer(ncontext);
4749 
4750  /* tf1 disappears into cond */
4751  cond = transformer_safe_combine_with_warnings(tf1, tf2);
4752 
4754  /* try to break rel it into two convex components */
4755  if((ENTITY_NON_EQUAL_P(op) && veracity)
4756  || (ENTITY_EQUAL_P(op) && !veracity)) {
4759  transformer rel1 = relation_to_transformer(lt, tmp1, tmp2, true);
4760  transformer rel2 = relation_to_transformer(gt, tmp1, tmp2, true);
4761  transformer full_cond1 = transformer_safe_image_intersection(cond, rel1);
4762  transformer full_cond2 = transformer_safe_image_intersection(cond, rel2);
4763  /* pre disappears into newpre2 */
4764  transformer newpre1 = transformer_combine(transformer_dup(pre), full_cond1);
4765  transformer newpre2 = transformer_combine(pre, full_cond2);
4766 
4767  free_transformer(rel1);
4768  free_transformer(rel2);
4769 
4770  newpre = transformer_convex_hull(newpre1, newpre2);
4771 
4772  free_transformer(full_cond1);
4773  free_transformer(full_cond2);
4774  free_transformer(newpre1);
4775  free_transformer(newpre2);
4776  }
4777  }
4778  else if (!transformer_undefined_p(cond)){
4779  transformer full_cond = transformer_safe_image_intersection(cond, rel);
4780  /* pre disappears into newpre */
4781  newpre = transformer_combine(pre, full_cond);
4782  free_transformer(full_cond);
4783  }
4784  else {
4785  /* newpre stays undefined or newpre is pre*/
4786  newpre = pre;
4787  }
4788 
4789  transformer_free(cond);
4790  pre = newpre;
4791 
4792  pips_assert("Pre is still consistent with tf1 and tf2 and rel",
4794 
4795  /* free_transformer(tf1); already gone */
4796  free_transformer(tf2);
4797  free_transformer(rel);
4798  break;
4799  }
4800  case is_basic_overloaded:
4801  pips_internal_error("illegal overloaded type for operator %s",
4802  entity_name(op));
4803  break;
4804  case is_basic_bit:
4805  // Do not emit the same message during the second analysis of
4806  // the condition
4807  if(veracity)
4808  semantics_user_warning("bit type not analyzed for operator %s\n",
4809  entity_name(op));
4810  break;
4811 // case is_basic_pointer:
4812 // if(veracity)
4813 // semantics_user_warning("pointer type not analyzed for operator %s\n",
4814 // entity_name(op));
4815 // break;
4816  case is_basic_derived:
4817  /* Nothing to be done with struct and union */
4818  break;
4819  case is_basic_typedef:
4820  pips_internal_error("typedef should ne converted to concrete types for operator %s",
4821  entity_name(op));
4822  break;
4823  default:
4824  pips_internal_error("unknown basic b=%d", basic_tag(b1));
4825  }
4826  }
4827 
4828  free_basic(b1);
4829  free_basic(b2);
4830 
4831  pre = transformer_normalize(pre, 2);
4832 
4833  /* pre may be unchanged when no information is derived */
4834  pips_debug(8, "end with pre=%p\n", pre);
4835 
4836  return pre;
4837 }
bool transformer_argument_consistency_p(transformer t)
Definition: basic.c:551
#define GREATER_THAN_OPERATOR_NAME
#define ENTITY_NON_EQUAL_P(e)
#define ENTITY_EQUAL_P(e)
#define LESS_THAN_OPERATOR_NAME
entity local_name_to_top_level_entity(const char *n)
This function try to find a top-level entity from a local name.
Definition: entity.c:1450
@ is_basic_bit
Definition: ri.h:577
Value b2
Definition: sc_gram.c:105
Value b1
booleen indiquant quel membre est en cours d'analyse
Definition: sc_gram.c:105
static int semantics_basic_tag(basic b)
Assimilate enum and logical to int (used when they appear in logical operations)
Definition: expression.c:4670
transformer relation_to_transformer(entity op, entity e1, entity e2, bool veracity)
e and f are assumed to be values.
Definition: transformer.c:139
transformer transformer_safe_combine_with_warnings(transformer tf1, transformer tf2)
Transformer tf1 and tf2 are supposed to be independent but they may interfere, for instance because s...
Definition: transformer.c:493

References b1, b2, basic_of_expression(), basic_tag, ENTITY_EQUAL_P, entity_name, ENTITY_NON_EQUAL_P, free_basic(), free_transformer(), GREATER_THAN_OPERATOR_NAME, is_basic_bit, is_basic_complex, is_basic_derived, is_basic_float, is_basic_int, is_basic_logical, is_basic_overloaded, is_basic_pointer, is_basic_string, is_basic_typedef, LESS_THAN_OPERATOR_NAME, local_name_to_top_level_entity(), make_local_temporary_value_entity_with_basic(), pips_assert, pips_debug, pips_internal_error, relation_to_transformer(), safe_any_expression_to_transformer(), semantics_basic_tag(), semantics_user_warning, transformer_apply(), transformer_argument_consistency_p(), transformer_combine(), transformer_convex_hull(), transformer_dup(), transformer_free(), transformer_identity(), transformer_normalize(), transformer_range(), transformer_safe_combine_with_warnings(), transformer_safe_image_intersection(), transformer_undefined, and transformer_undefined_p.

Referenced by logical_binary_function_to_transformer(), and transformer_add_call_condition_information_updown().

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

◆ transformer_add_condition_information()

transformer transformer_add_condition_information ( transformer  pre,
expression  c,
transformer  context,
bool  veracity 
)
Parameters
prere
contextontext
veracityeracity

Definition at line 1092 of file expression.c.

1097 {
1098  transformer post =
1100  veracity, true);
1101 
1104 
1105  return post;
1106 }

References reset_temporary_value_counter(), transformer_add_condition_information_updown(), and transformer_temporary_value_projection().

Referenced by check_condition_wrt_precondition(), old_complete_whileloop_transformer(), and transformer_add_domain_condition().

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

◆ transformer_add_domain_condition()

transformer transformer_add_domain_condition ( transformer  tf,
expression  c,
transformer  context,
bool  veracity 
)
Parameters
tff
contextontext
veracityeracity

Definition at line 1138 of file expression.c.

1142 {
1143  tf = transformer_add_condition_information(tf, c, context, veracity);
1144  return tf;
1145 }

References transformer_add_condition_information().

Referenced by test_to_total_precondition().

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

◆ transformer_add_integer_relation_information()

transformer transformer_add_integer_relation_information ( transformer  pre,
entity  relop,
expression  e1,
expression  e2,
bool  veracity,
bool  upwards 
)

It is supposed to be obsolete but is still called.

Maybe, it's only partly obsolete... If upwards is false, it is worth performing more convex hulls because the precondition on entry may restrain the space. upwards = transformer, !upwards = precondition

default: no change

both expressions e1 and e2 must be affine

Make sure that new values only are used in v1 and v2

v1 - v2 == 0

v2 - v1 + 1 <= 0 ou v1 - v2 + 1 <= 0

FI: I do not know if this is valid when your are moving upwards variables in v2 and v1 may have to be renamed as init values (i.e. old values)

FI: I think that this should be programmed (see comment above) but I'm waiting for a bug to occur... (6 July 1993)

FI: Well, the bug was eventually seen:-) (8 November 1995)

free_transformer(prea);

free_transformer(preb);

v2 - v1 + 1 <= 0

v1 - v2 <= 0

v2 - v1 <= 0

v1 - v2 + 1 <= 0

do nothing... although Malik may have tried harder!

do nothing, although MODULO and INTEGER DIVIDE could be handled

Parameters
prere
relopelop
e11
e22
veracityeracity
upwardspwards

Definition at line 5929 of file expression.c.

5936 {
5937 # define DEBUG_TRANSFORMER_ADD_RELATION_INFORMATION 7
5938  /* default: no change */
5939  transformer newpre = pre;
5940  /* both expressions e1 and e2 must be affine */
5943 
5946  "begin upwards=%s veracity=%s relop=%s e1=",
5947  bool_to_string(upwards), bool_to_string(veracity),
5948  entity_local_name(relop));
5949  print_expression(e1);
5950  (void) fprintf(stderr,"e2=");
5951  print_expression(e2);
5952  (void) fprintf(stderr,"pre=");
5953  print_transformer(pre);
5954  }
5955 
5961 
5962  /* Make sure that new values only are used in v1 and v2 */
5965 
5966  if((ENTITY_EQUAL_P(relop) && veracity) ||
5967  (ENTITY_NON_EQUAL_P(relop) && !veracity)) {
5968  /* v1 - v2 == 0 */
5969  Pvecteur v = vect_substract(v1, v2);
5970  if(upwards) {
5971  upwards_vect_rename(v, pre);
5972  }
5973  newpre = transformer_equality_add(pre, v);
5974  }
5975  else if((ENTITY_EQUAL_P(relop) && !veracity) ||
5976  (ENTITY_NON_EQUAL_P(relop) && veracity)) {
5977  /* v2 - v1 + 1 <= 0 ou v1 - v2 + 1 <= 0 */
5978  /* FI: I do not know if this is valid when your are moving upwards
5979  * variables in v2 and v1 may have to be renamed as #init values (i.e. old values)
5980  */
5981  transformer prea = transformer_dup(pre);
5982  transformer preb = pre;
5983  Pvecteur va = vect_substract(v2, v1);
5984  Pvecteur vb = vect_substract(v1, v2);
5985  vect_add_elem(&va, TCST, VALUE_ONE);
5986  vect_add_elem(&vb, TCST, VALUE_ONE);
5987  /* FI: I think that this should be programmed (see comment above)
5988  * but I'm waiting for a bug to occur... (6 July 1993)
5989  *
5990  * FI: Well, the bug was eventually seen:-) (8 November 1995)
5991  */
5992  if(upwards) {
5993  upwards_vect_rename(va, pre);
5994  upwards_vect_rename(vb, pre);
5995  }
5996  prea = transformer_inequality_add(prea, va);
5997  preb = transformer_inequality_add(preb, vb);
5998  newpre = transformer_convex_hull(prea, preb);
5999  /* free_transformer(prea); */
6000  /* free_transformer(preb); */
6001  }
6002  else if ((ENTITY_GREATER_THAN_P(relop) && veracity) ||
6003  (ENTITY_LESS_OR_EQUAL_P(relop) && !veracity)) {
6004  /* v2 - v1 + 1 <= 0 */
6005  Pvecteur v = vect_substract(v2, v1);
6007  if(upwards) {
6008  upwards_vect_rename(v, pre);
6009  }
6010  newpre = transformer_inequality_add(pre, v);
6011  }
6012  else if ((ENTITY_GREATER_THAN_P(relop) && !veracity) ||
6013  (ENTITY_LESS_OR_EQUAL_P(relop) && veracity)) {
6014  /* v1 - v2 <= 0 */
6015  Pvecteur v = vect_substract(v1, v2);
6016  if(upwards) {
6017  upwards_vect_rename(v, pre);
6018  }
6019  newpre = transformer_inequality_add(pre, v);
6020  }
6021  else if ((ENTITY_GREATER_OR_EQUAL_P(relop) && veracity) ||
6022  (ENTITY_LESS_THAN_P(relop) && !veracity)) {
6023  /* v2 - v1 <= 0 */
6024  Pvecteur v = vect_substract(v2, v1);
6025  if(upwards) {
6026  upwards_vect_rename(v, pre);
6027  }
6028  newpre = transformer_inequality_add(pre, v);
6029  }
6030  else if ((ENTITY_GREATER_OR_EQUAL_P(relop) && !veracity) ||
6031  (ENTITY_LESS_THAN_P(relop) && veracity)) {
6032  /* v1 - v2 + 1 <= 0 */
6033  Pvecteur v = vect_substract(v1, v2);
6035  if(upwards) {
6036  upwards_vect_rename(v, pre);
6037  }
6038  newpre = transformer_inequality_add(pre, v);
6039  }
6040  else {
6041  /* do nothing... although Malik may have tried harder! */
6042  newpre = pre;
6043  }
6044  vect_rm(v1);
6045  vect_rm(v2);
6046  }
6047  else
6048  /* do nothing, although MODULO and INTEGER DIVIDE could be handled */
6049  newpre = pre;
6050 
6053  "end newpre=\n");
6054  print_transformer(newpre);
6055  pips_assert("Transformer is internally consistent",
6057  }
6058 
6059  return newpre;
6060 }
#define ENTITY_LESS_THAN_P(e)
#define ENTITY_GREATER_THAN_P(e)
#define ENTITY_LESS_OR_EQUAL_P(e)
#define ENTITY_GREATER_OR_EQUAL_P(e)
#define DEBUG_TRANSFORMER_ADD_RELATION_INFORMATION
void variables_to_new_values(Pvecteur v)
replace variables by new values which is necessary for equivalenced variables
Definition: mappings.c:1038

References bool_to_string(), DEBUG_TRANSFORMER_ADD_RELATION_INFORMATION, ENTITY_EQUAL_P, ENTITY_GREATER_OR_EQUAL_P, ENTITY_GREATER_THAN_P, ENTITY_LESS_OR_EQUAL_P, ENTITY_LESS_THAN_P, entity_local_name(), ENTITY_NON_EQUAL_P, fprintf(), ifdebug, NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, pips_assert, pips_debug, print_expression(), print_transformer, TCST, transformer_convex_hull(), transformer_dup(), transformer_equality_add(), transformer_inequality_add(), transformer_internal_consistency_p(), upwards_vect_rename(), value_mappings_compatible_vector_p(), VALUE_ONE, variables_to_new_values(), vect_add_elem(), vect_dup(), vect_rm(), and vect_substract().

+ Here is the call graph for this function:

◆ transformer_add_loop_index_incrementation()

transformer transformer_add_loop_index_incrementation ( transformer  tf,
loop  l,
transformer  pre 
)

SHOULD BE REWRITTEN WITH EXPRESSION_TO_TRANSFORMER

it does not contain the loop index update the loop increment expression must be linear to find inductive variables related to the loop index

Parameters
tff
prere

Definition at line 1136 of file loop.c.

1139 {
1140  entity i = loop_index(l);
1141  range r = loop_range(l);
1142  expression incr = range_increment(r);
1143  Pvecteur v_incr = VECTEUR_UNDEFINED;
1144 
1145  /* SHOULD BE REWRITTEN WITH EXPRESSION_TO_TRANSFORMER */
1146 
1147  pips_assert("To please the compiler", pre==pre);
1148 
1149  pips_assert("Transformer tf is consistent before update",
1151 
1152  /* it does not contain the loop index update the loop increment
1153  expression must be linear to find inductive variables related to
1154  the loop index */
1155  if(!VECTEUR_UNDEFINED_P(v_incr = expression_to_affine(incr))) {
1156  if(entity_has_values_p(i)) {
1158  tf = transformer_add_variable_incrementation(tf, i, v_incr);
1159  }
1160  else {
1161  entity i_old = entity_to_old_value(i);
1162  entity i_new = entity_to_new_value(i);
1164  Pbase b = sc_base(sc);
1165 
1167  b = base_add_variable(b, (Variable) i_old);
1168  b = base_add_variable(b, (Variable) i_new);
1169  sc_base(sc) = b;
1170  sc_dimension(sc) = base_dimension(sc_base(sc));
1171  }
1172  }
1173  else {
1174  pips_user_warning("non-integer or equivalenced loop index %s?\n",
1175  entity_local_name(i));
1176  }
1177  }
1178  else {
1179  if(entity_has_values_p(i)) {
1180  entity i_old = entity_to_old_value(i);
1181  entity i_new = entity_to_new_value(i);
1183  Pbase b = sc_base(sc);
1184 
1186  b = base_add_variable(b, (Variable) i_old);
1187  b = base_add_variable(b, (Variable) i_new);
1188  sc_base(sc) = b;
1189  sc_dimension(sc) = base_dimension(sc_base(sc));
1190  }
1191  }
1192 
1193  pips_assert("Transformer tf is consistent after update",
1195 
1196  return tf;
1197 }
Pbase base_add_variable(Pbase b, Variable var)
Pbase base_add_variable(Pbase b, Variable v): add variable v as a new dimension to basis b at the end...
Definition: base.c:88
transformer transformer_add_variable_incrementation(transformer t, entity i, Pvecteur incr)
transformer transformer_add_loop_index(transformer t, entity i, Pvecteur incr): add the index increme...
Definition: basic.c:260
Pvecteur expression_to_affine(expression e)
Definition: normalize.c:461
#define base_dimension(b)
#define VECTEUR_UNDEFINED_P(v)

References arguments_add_entity(), base_add_variable(), base_dimension, entity_has_values_p(), entity_local_name(), entity_to_new_value(), entity_to_old_value(), expression_to_affine(), loop_index, loop_range, pips_assert, pips_user_warning, predicate_system, range_increment, transformer_add_variable_incrementation(), transformer_arguments, transformer_consistency_p(), transformer_relation, value_mappings_compatible_vector_p(), VECTEUR_UNDEFINED, and VECTEUR_UNDEFINED_P.

Referenced by loop_to_continue_transformer(), loop_to_total_precondition(), loop_to_transformer(), and recompute_loop_transformer().

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

◆ transformer_add_loop_index_initialization()

transformer transformer_add_loop_index_initialization ( transformer  tf,
loop  l,
transformer  pre 
)

The loop initialization is performed before tf.

EXPRESSION_TO_TRANSFORMER SHOULD BE USED

The new variables in eq must be added to sc; otherwise, further consistency checks core dump. bc.

sc_add_egalite(sc, eq);

The call to sc_projection_with_eq frees eq

FI: a NULL is not acceptable; I assume that we cannot end up with a SC_EMPTY...

Get rid of the initial value since it is unknowable

Parameters
tff
prere

Definition at line 1082 of file loop.c.

1085 {
1086  entity i = loop_index(l);
1087  range r = loop_range(l);
1089 
1090  /* EXPRESSION_TO_TRANSFORMER SHOULD BE USED */
1091  pips_assert("To please the compiler", pre==pre);
1092 
1093  if(entity_has_values_p(i) && normalized_linear_p(nlb)) {
1096  Pvecteur v_lb = vect_dup(normalized_linear(nlb));
1097  Pbase b_tmp, b_lb = make_base_from_vect(v_lb);
1098  entity i_init = entity_to_old_value(i);
1099 
1100  vect_add_elem(&v_lb, (Variable) i_init, VALUE_MONE);
1101  eq = contrainte_make(v_lb);
1102  /* The new variables in eq must be added to sc; otherwise,
1103  * further consistency checks core dump. bc.
1104  */
1105  /* sc_add_egalite(sc, eq); */
1106  /* The call to sc_projection_with_eq frees eq */
1107  sc = sc_projection_by_eq(sc, eq, (Variable) i_init);
1108  b_tmp = sc_base(sc);
1109  sc_base(sc) = base_union(b_tmp, b_lb);
1110  sc_dimension(sc) = base_dimension(sc_base(sc));
1111  base_rm(b_tmp);
1112  base_rm(b_lb);
1113  if(SC_RN_P(sc)) {
1114  /* FI: a NULL is not acceptable; I assume that we cannot
1115  * end up with a SC_EMPTY...
1116  */
1120  }
1121  else
1123  newgen_Psysteme(sc);
1124  }
1125  else if(entity_has_values_p(i)) {
1126  /* Get rid of the initial value since it is unknowable */
1127  entity i_init = entity_to_old_value(i);
1128  list l_i_init = CONS(ENTITY, i_init, NIL);
1129 
1130  tf = transformer_projection(tf, l_i_init);
1131  }
1132 
1133 return tf;
1134 }
Pbase make_base_from_vect(Pvecteur pv)
Definition: base.c:109
Pbase base_union(Pbase b1, Pbase b2)
Pbase base_union(Pbase b1, Pbase b2): compute a new basis containing all elements of b1 and all eleme...
Definition: base.c:428
#define newgen_Psysteme(p)
Definition: effects.h:47
#define predicate_system_(x)
Definition: ri.h:2068
#define base_rm(b)

References base_dimension, base_rm, base_union(), CONS, contrainte_make(), CONTRAINTE_UNDEFINED, ENTITY, entity_has_values_p(), entity_to_old_value(), eq, loop_index, loop_range, make_base_from_vect(), newgen_Psysteme, NIL, NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, pips_assert, predicate_system, predicate_system_, range_lower, sc_make(), transformer_projection(), transformer_relation, VALUE_MONE, vect_add_elem(), and vect_dup().

Referenced by recompute_loop_transformer().

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

◆ transformer_add_range_condition()

transformer transformer_add_range_condition ( transformer  tf,
expression  c,
transformer  context,
bool  veracity 
)
Parameters
tff
contextontext
veracityeracity

Definition at line 1147 of file expression.c.

1151 {
1152  tf = precondition_add_condition_information(tf, c, context, veracity);
1153  return tf;
1154 }

References precondition_add_condition_information().

+ Here is the call graph for this function:

◆ transformer_add_reference_information()

void transformer_add_reference_information ( transformer  tf,
statement  s 
)
Parameters
tff

Definition at line 700 of file ri_to_preconditions.c.

701 {
702  add_reference_information(tf, s, true);
703 }

References add_reference_information().

Referenced by statement_to_transformer(), and statement_to_transformer_list().

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

◆ transformer_add_type_information()

void transformer_add_type_information ( transformer  tf)

type.c

Parameters
tff

Definition at line 162 of file type.c.

163 {
165  return;
166 }
static void add_type_information(transformer tf)
Add some of the constraints linked to the type of a variable.
Definition: type.c:61

References add_type_information().

Referenced by module_name_to_preconditions(), precondition_add_type_information(), statement_to_postcondition(), statement_to_transformer(), and transformer_add_variable_type_information().

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

◆ transformer_add_variable_type_information()

void transformer_add_variable_type_information ( transformer  tf,
entity  v 
)
Parameters
tff

Definition at line 168 of file type.c.

169 {
170  pips_assert("entity has values", entity_has_values_p(v));
171  entity vv = entity_to_new_value(v);
175  return;
176 }
bool value_belongs_to_transformer_space(entity v, transformer tf)
Definition: basic.c:842
void add_value_to_transformer_space(entity v, transformer tf)
Definition: basic.c:859
void transformer_add_type_information(transformer tf)
type.c
Definition: type.c:162

References add_value_to_transformer_space(), entity_has_values_p(), entity_to_new_value(), pips_assert, transformer_add_type_information(), and value_belongs_to_transformer_space().

Referenced by declaration_to_transformer().

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

◆ transformer_apply_field_assignments()

transformer transformer_apply_field_assignments ( transformer  t,
reference  l,
reference  r,
type  st 
)
Parameters
stt

Definition at line 2925 of file ri_to_transformers.c.

2926 {
2927  return transformer_apply_field_assignments_or_equalities(t, l, r, st, true);
2928 }
transformer transformer_apply_field_assignments_or_equalities(transformer t, reference l, reference r, type st, bool assign_p)
For all analyzable fields f, apply the assignment "le.f = re.f;" to transformer t.

References transformer_apply_field_assignments_or_equalities().

Referenced by struct_reference_assignment_or_equality_to_transformer(), and transformer_apply_field_assignments_or_equalities().

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

◆ transformer_apply_field_assignments_or_equalities()

transformer transformer_apply_field_assignments_or_equalities ( transformer  t,
reference  l,
reference  r,
type  st,
bool  assign_p 
)

For all analyzable fields f, apply the assignment "le.f = re.f;" to transformer t.

If s1.f is a struct, go down recursively.

It is assumed that s1 and s2 have the exact same concrete struct type, st.

Transformer t is updated. It is assumed to contain the current precondition.

Parameters
stt
assign_pssign_p

Definition at line 2876 of file ri_to_transformers.c.

2877 {
2878  list fl = struct_type_to_fields(st);
2879  FOREACH(ENTITY, f, fl) {
2881  if(analyzed_type_p(ft)) {
2888 
2889  if(!entity_undefined_p(l1)) {
2891  // The value of location l1 is changed
2892  if(assign_p)
2893  tf = transformer_add_modified_variable(tf, l1);
2894  if(!entity_undefined_p(l2)) {
2895  // both locations are analyzed
2896  tf = transformer_add_equality(tf, l1, l2);
2897  }
2898  t = transformer_combine(t, tf);
2899  free_transformer(tf);
2900  }
2901  else {
2902  pips_internal_error("Not implemented yet.\n");
2903  }
2904  free_reference(r1);
2905  free_reference(r2); // another option would be to remove the last subscript
2906  }
2907  else if(type_struct_p(ft)) {
2908  // This piece of code could be integrate in the previous
2909  // alternative to share most of its code
2915  // GO down recursively
2916  tf = transformer_apply_field_assignments(tf, l1, r1, ft);
2917  if(!transformer_undefined_p(tf))
2918  t = transformer_combine(t, tf);
2920  }
2921  }
2922  return t;
2923 }
reference add_subscript_to_reference(reference r, expression s)
Add a last subscript expression s to a reference r.
Definition: expression.c:224
#define type_struct_p(x)
Definition: ri.h:2962
transformer transformer_apply_field_assignments(transformer t, reference l, reference r, type st)

References add_subscript_to_reference(), analyzed_type_p(), constant_memory_access_path_to_location_entity(), copy_reference(), ENTITY, entity_basic_concrete_type(), entity_to_expression(), entity_undefined_p, f(), FOREACH, free_reference(), free_transformer(), pips_internal_error, struct_type_to_fields(), transformer_add_equality(), transformer_add_modified_variable(), transformer_apply_field_assignments(), transformer_combine(), transformer_identity(), transformer_undefined_p, and type_struct_p.

Referenced by transformer_apply_field_assignments(), and transformer_apply_field_equalities().

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

◆ transformer_apply_field_equalities()

transformer transformer_apply_field_equalities ( transformer  t,
reference  l,
reference  r,
type  st 
)
Parameters
stt

Definition at line 2930 of file ri_to_transformers.c.

2931 {
2932  return transformer_apply_field_assignments_or_equalities(t, l, r, st, false);
2933 }

References transformer_apply_field_assignments_or_equalities().

Referenced by struct_reference_assignment_or_equality_to_transformer().

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

◆ transformer_apply_unknown_field_assignments()

transformer transformer_apply_unknown_field_assignments ( transformer  t,
reference  l,
type  st 
)
Parameters
stt

Definition at line 2976 of file ri_to_transformers.c.

2977 {
2979 }
static transformer transformer_apply_unknown_field_assignments_or_equalities(transformer t, reference l, type st, bool assign_p)
Simplified version of transformer_apply_field_assignments() with an unknown rhs.

References transformer_apply_unknown_field_assignments_or_equalities().

Referenced by struct_reference_assignment_or_equality_to_transformer().

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

◆ transformer_apply_unknown_field_equalities()

transformer transformer_apply_unknown_field_equalities ( transformer  t,
reference  l,
type  st 
)
Parameters
stt

Definition at line 2981 of file ri_to_transformers.c.

2982 {
2984 }

References transformer_apply_unknown_field_assignments_or_equalities().

Referenced by struct_reference_assignment_or_equality_to_transformer().

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

◆ transformer_formal_parameter_projection()

transformer transformer_formal_parameter_projection ( entity  f,
transformer  t 
)

Dealing with an interprocedural transformer, weak consistency is not true

pips_assert("t is weakly consistent", transformer_weak_consistency_p(t));

Definition at line 1537 of file ri_to_transformers.c.

1538 {
1540  Pbase b = sc_base(sc);
1541  Pbase cd = BASE_UNDEFINED;
1542  list fpl = NIL;
1543 
1544  /* Dealing with an interprocedural transformer, weak consistency is
1545  not true */
1546  /* pips_assert("t is weakly consistent",
1547  transformer_weak_consistency_p(t));*/
1548  pips_assert("sc is consistent", sc_weak_consistent_p(sc));
1549  pips_assert("t is weakly consistent", transformer_weak_consistency_p(t));
1550 
1551  for(cd = b; !BASE_NULLE_P(cd); cd = vecteur_succ(cd)) {
1552  entity val = (entity) vecteur_var(cd);
1553  entity var = value_to_variable(val);
1554  if(!location_entity_p(var)) {
1555  storage s = entity_storage(var);
1556 
1558  fpl = CONS(ENTITY, var, fpl);
1559  }
1560  }
1561 
1562  ifdebug(1) {
1563  pips_debug(1, "Transformer before projection:\n");
1564  dump_transformer(t);
1565  pips_debug(1, "Projected variables:\n");
1566  print_entities(fpl);
1567  fprintf(stderr, "\n");
1568  }
1569 
1570  t = transformer_projection(t, fpl);
1571 
1572  gen_free_list(fpl);
1573 
1574  return t;
1575 }
void print_entities(list l)
Definition: entity.c:167
#define formal_function(x)
Definition: ri.h:1406
bool sc_weak_consistent_p(Psysteme sc)
check that sc is well defined, that the numbers of equalities and inequalities are consistent with th...
Definition: sc.c:362

References BASE_NULLE_P, BASE_UNDEFINED, CONS, dump_transformer, ENTITY, entity_storage, f(), formal_function, fprintf(), gen_free_list(), ifdebug, location_entity_p(), NIL, pips_assert, pips_debug, predicate_system, print_entities(), sc_weak_consistent_p(), storage_formal, storage_formal_p, transformer_projection(), transformer_relation, transformer_weak_consistency_p(), value_to_variable(), vecteur_succ, and vecteur_var.

Referenced by c_user_call_to_transformer().

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

◆ transformer_intra_to_inter()

transformer transformer_intra_to_inter ( transformer  tf,
list  le 
)
Parameters
tff
lee

Definition at line 1510 of file ri_to_transformers.c.

1512 {
1513  return generic_transformer_intra_to_inter(tf, le, true);
1514 }
transformer generic_transformer_intra_to_inter(transformer tf, list le, bool preserve_rv_p)
transformer translation from the module intraprocedural transformer to the module interprocedural tra...

References generic_transformer_intra_to_inter().

Referenced by generic_module_name_to_transformers(), module_name_to_total_preconditions(), and program_precondition().

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

◆ transformer_logical_inequalities_add()

transformer transformer_logical_inequalities_add ( transformer  tf,
entity  v 
)

PROCESSING OF LOGICAL EXPRESSIONS.

the values of v are between 0 and 1

Parameters
tff

Definition at line 3569 of file expression.c.

3570 {
3571  /* the values of v are between 0 and 1 */
3572  Pvecteur ineq1 = vect_new((Variable) v, VALUE_ONE);
3573  Pvecteur ineq2 = vect_new((Variable) v, VALUE_MONE);
3574 
3575  vect_add_elem(&ineq1, TCST, VALUE_MONE);
3576 
3577  tf = transformer_inequality_add(tf, ineq1);
3578  tf = transformer_inequality_add(tf, ineq2);
3579 
3580  return tf;
3581 }

References TCST, transformer_inequality_add(), VALUE_MONE, VALUE_ONE, vect_add_elem(), and vect_new().

Referenced by logical_binary_operation_to_transformer(), logical_reference_to_transformer(), and logical_unary_operation_to_transformer().

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

◆ transformer_map_undefined_p()

bool transformer_map_undefined_p ( void  )

◆ transformers_inter_fast()

bool transformers_inter_fast ( char *  module_name)

set_int_property(SEMANTICS_DEBUG_LEVEL, 0);

Parameters
module_nameodule_name

Definition at line 310 of file dbm_interface.c.

311 {
317  /* set_int_property(SEMANTICS_DEBUG_LEVEL, 0); */
319 }
bool module_name_to_transformers(const char *module_name)

References module_name(), module_name_to_transformers(), select_fix_point_operator(), SEMANTICS_FIX_POINT, SEMANTICS_FLOW_SENSITIVE, SEMANTICS_INTERPROCEDURAL, SEMANTICS_STDOUT, and set_bool_property().

+ Here is the call graph for this function:

◆ transformers_inter_full()

bool transformers_inter_full ( char *  module_name)

set_int_property(SEMANTICS_DEBUG_LEVEL, 0);

Parameters
module_nameodule_name

Definition at line 321 of file dbm_interface.c.

322 {
328  /* set_int_property(SEMANTICS_DEBUG_LEVEL, 0); */
330 }

References module_name(), module_name_to_transformers(), select_fix_point_operator(), SEMANTICS_FIX_POINT, SEMANTICS_FLOW_SENSITIVE, SEMANTICS_INTERPROCEDURAL, SEMANTICS_STDOUT, and set_bool_property().

+ Here is the call graph for this function:

◆ transformers_inter_full_with_points_to()

bool transformers_inter_full_with_points_to ( char *  module_name)

set_int_property(SEMANTICS_DEBUG_LEVEL, 0);

Parameters
module_nameodule_name

Definition at line 332 of file dbm_interface.c.

333 {
339  /* set_int_property(SEMANTICS_DEBUG_LEVEL, 0); */
341  db_get_memory_resource(DBR_POINTS_TO, module_name, true) );
344 
345  return result;
346 }

References db_get_memory_resource(), module_name(), module_name_to_transformers(), reset_pt_to_list(), select_fix_point_operator(), SEMANTICS_FIX_POINT, SEMANTICS_FLOW_SENSITIVE, SEMANTICS_INTERPROCEDURAL, SEMANTICS_STDOUT, set_bool_property(), and set_pt_to_list().

+ Here is the call graph for this function:

◆ transformers_intra_fast()

bool transformers_intra_fast ( char *  module_name)

Functions to make transformers.

Set properties as required for a very fast semantics analysis

No need to select a fix point operator given the above property, but just in case...

set_int_property(SEMANTICS_DEBUG_LEVEL, 0);

Restaure initial values of modified properties

Parameters
module_nameodule_name

Definition at line 254 of file dbm_interface.c.

255 {
259  bool result = true;
260 
261  /* Set properties as required for a very fast semantics analysis */
262  if(si) {
263  pips_user_warning("Property SEMANTICS_INTERPROCEDURAL is ignored\n");
265  }
266  if(!sfs) {
267  pips_user_warning("Property SEMANTICS_FLOW_SENSITIVE is ignored\n");
269  }
270  if(sfp) {
271  pips_user_warning("Property SEMANTICS_FIX_POINT is ignored\n");
273  }
274  /* No need to select a fix point operator given the above property, but just in case... */
276 
278  /* set_int_property(SEMANTICS_DEBUG_LEVEL, 0); */
279 
280  if(get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT")) {
281  pips_user_warning("If you really want to set property "
282  "SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT, "
283  "you should activate TRANSFORMERS_INTER_FULL\n");
284  }
285 
287 
288  /* Restaure initial values of modified properties */
289  if(si)
291  if(!sfs)
293  if(sfp)
295 
296  return result;
297 }

References get_bool_property(), module_name(), module_name_to_transformers(), pips_user_warning, select_fix_point_operator(), SEMANTICS_FIX_POINT, SEMANTICS_FLOW_SENSITIVE, SEMANTICS_INTERPROCEDURAL, SEMANTICS_STDOUT, and set_bool_property().

+ Here is the call graph for this function:

◆ transformers_intra_full()

bool transformers_intra_full ( char *  module_name)

set_int_property(SEMANTICS_DEBUG_LEVEL, 0);

Parameters
module_nameodule_name

Definition at line 299 of file dbm_interface.c.

300 {
306  /* set_int_property(SEMANTICS_DEBUG_LEVEL, 0); */
308 }

References module_name(), module_name_to_transformers(), select_fix_point_operator(), SEMANTICS_FIX_POINT, SEMANTICS_FLOW_SENSITIVE, SEMANTICS_INTERPROCEDURAL, SEMANTICS_STDOUT, and set_bool_property().

+ Here is the call graph for this function:

◆ translate_global_value()

void translate_global_value ( entity  m,
transformer  tf,
entity  v 
)

Try to convert an value on a non-local variable into an value on a local variable using a guessed name (instead of a location identity: M and N declared as COMMON/FOO/M and COMMON/FOO/N are not identified as a unique variable/location).

Mo more true: It might also fail to translate variable C:M into A:M if C is indirectly called from A thru B and if M is not defined in B.

This routine is not too safe. It accepts non-translatable variable as input and does not refuse them, most of the time.

Filter out constant and values local to the current module

FI: to be modified to account for global values that have a name but that should nevertheless be translated on their canonical representant; this occurs for non-visible global variables

FI: to be completed later... 3 December 1993 entity var = value_to_variable(v);

pips_debug(7, "%s is translated into %s\n", entity_name(v), entity_name(e)); transformer_value_substitute(tf, v, e);

Filter out old values: they are translated when the new value is encountered, and the new value has to appear if the old value does appear.

Instead, old values could be translated into new values and processing could go on...

FI, 26 October 1994

Should it be projected? No, this should occur later for xxxx::init variables when the xxxx is translated. Or before if xxxx has been translated

must be a common; dynamic and static area must have been filtered out before

try to find an equivalent entity by its name (whereas we should use locations)

no equivalent name found, get rid of v

transformer_projection(tf, CONS(ENTITY, v_old, NIL));

no equivalent location found, get rid of v

no equivalent location found, get rid of v

e has already been introduced and v eliminated; this happens when a COMMON variable is also passed as real argument

FI: v may still appear in the constraints as in spice.f (Perfect Club) and spice01.f (Validation)

this cannot happen when the summary transformer of a called procedure is translated because the write effect in the callee that is implied by v_init existence must have been passed upwards and must have led to the creation of e_init

this should not happen when a caller precondition at a call site is transformed into a piece of a summary precondition for the callee because v_init becomes meaningless; at the callee's entry point, by definition, e == e_init; v_init should have been projected before

forget e_init: there is no v_init in tf

there is no v_init to worry about; v is not changed in the caller (or its subtree of callees)

this value does not need to be translated

Parameters
tff

Definition at line 657 of file interprocedural.c.

661 {
662  storage store = storage_undefined;
663  ram r = ram_undefined;
665  entity section = entity_undefined;
666 
667  ifdebug(7) {
668  pips_debug(7, "begin v = %s and tf = %p\n", entity_name(v), tf);
669  }
670 
671 
672  if(v == NULL) {
673  pips_internal_error("Trying to translate TCST");
674  return;
675  }
676 
677  /* Filter out constant and values *local* to the current module */
678  if(value_entity_p(v) || entity_constant_p(v)) {
679  /* FI: to be modified to account for global values that have a name
680  * but that should nevertheless be translated on their canonical
681  * representant; this occurs for non-visible global variables
682  */
683  /* FI: to be completed later... 3 December 1993
684  entity var = value_to_variable(v);
685 
686  pips_debug(7,
687  "%s is translated into %s\n",
688  entity_name(v), entity_name(e));
689  transformer_value_substitute(tf, v, e);
690  */
691 
692  pips_debug(7, "end: No need to translate %s\n", entity_name(v));
693  return;
694  }
695 
696  /* Filter out old values: they are translated when the new value is
697  * encountered, and the new value has to appear if the old value does
698  * appear.
699  *
700  * Instead, old values could be translated into new values and processing
701  * could go on...
702  *
703  * FI, 26 October 1994
704  */
705  if(global_old_value_p(v)) {
706  pips_debug(7, "end: No need to translate %s yet\n",
707  entity_name(v));
708  return;
709  }
710 
711  store = entity_storage(v);
712 
713  pips_debug(7, "Trying to translate %s\n", entity_name(v));
714 
715  if(!storage_ram_p(store)) {
716  if(storage_rom_p(store)) {
717  pips_debug(7, "%s is not translatable: store tag %d\n",
718  entity_name(v), storage_tag(store));
719  /* Should it be projected? No, this should occur later for
720  * xxxx#init variables when the xxxx is translated. Or before if
721  * xxxx has been translated
722  */
723  return;
724  }
725  else
726  if(storage_formal_p(store)) {
727  pips_debug(7, "formal %s is not translatable\n",
728  entity_name(v));
729  return;
730  }
731  if(storage_return_p(store)) {
732  pips_debug(7, "return %s is not translatable\n",
733  entity_name(v));
734  return;
735  }
736  else
737  pips_internal_error("%s is not translatable: store tag %d",
738  entity_name(v), storage_tag(store));
739  }
740 
741  ifdebug(7) {
742  pips_debug(7, "let's do it for v = %s and tf =\n",
743  entity_name(v));
744  dump_transformer(tf);
745  }
746 
747  r = storage_ram(store);
748  rf = ram_function(r);
749  section = ram_section(r);
750 
751  if(rf != m && top_level_entity_p(section)) {
752  /* must be a common; dynamic and static area must
753  have been filtered out before */
754  entity e;
755  entity v_init = entity_undefined;
756  Psysteme sc = SC_UNDEFINED;
757  Pbase b = BASE_UNDEFINED;
758 
759  if(top_level_entity_p(v)) {
760  // No need to translate
761  return;
762  }
763 
764  /* try to find an equivalent entity by its name
765  (whereas we should use locations) */
766  /*
767  e = FindEntity(module_local_name(m),
768  entity_local_name(v));
769  e = value_alias(value_to_variable(v));
770  */
771  e = value_alias(v);
772  if(e == entity_undefined) {
773  /* no equivalent name found, get rid of v */
774  pips_debug(7, "No equivalent for %s in %s: project %s\n",
775  entity_name(v), entity_name(m), entity_name(v));
776  user_warning("translate_global_value",
777  "Information about %s lost,\n"
778  "check structure of common /%s/ in modules %s and %s\n",
780  module_local_name(m));
783  /* transformer_projection(tf, CONS(ENTITY, v_old, NIL)); */
784  (void) transformer_filter(tf, CONS(ENTITY, v_old, NIL));
785  }
787  return;
788  }
789 
790  if(!same_scalar_location_p(v, e)) {
791  /* no equivalent location found, get rid of v */
792  pips_debug(7, "No equivalent location for %s and %s: project %s\n",
793  entity_name(v), entity_name(e), entity_name(v));
795  user_warning("translate_global_value",
796  "Information about %s lost,\n"
797  "check structure of common /%s/ in modules %s and %s\n",
799  module_local_name(m));
802  transformer_projection(tf, CONS(ENTITY, v_old, NIL));
803  }
805  return;
806  }
807 
808  if(!type_equal_p(entity_type(v), entity_type(e))) {
809  /* no equivalent location found, get rid of v */
810  pips_debug(7, "Same location but different types for %s (%s) and %s (%s):"
811  " project both %s and %s\n",
814  entity_name(e), entity_name(v));
816  user_warning("translate_global_value",
817  "Information about %s lost,\n"
818  "check types for variables in common /%s/ in modules %s and %s\n",
820  module_local_name(m));
823  transformer_projection(tf, CONS(ENTITY, v_old, NIL));
824  }
827  transformer_filter(tf, CONS(ENTITY, e_old, NIL));
828  }
829  transformer_filter(tf, CONS(ENTITY, v, NIL));
830  transformer_filter(tf, CONS(ENTITY, e, NIL));
831  return;
832  }
833 
834  sc = (Psysteme)
836  b = sc_base(sc);
837  if(base_contains_variable_p(b, (Variable) e)) {
838  /* e has already been introduced and v eliminated;
839  this happens when a COMMON variable is
840  also passed as real argument */
841  /* FI: v may still appear in the constraints as in spice.f
842  (Perfect Club) and spice01.f (Validation) */
843  Pvecteur subst = vect_new((Variable) v, (Value) 1);
845  list args = CONS(ENTITY, v, NIL);
846 
847  vect_add_elem(&subst, (Variable) e, (Value) -1);
848  eq = contrainte_make(subst);
849  sc_add_egalite(sc, eq);
850 
854  Pvecteur subst_old = vect_new((Variable) v_old, (Value) 1);
856 
857  args = CONS(ENTITY, v_old, args);
858 
859  vect_add_elem(&subst_old, (Variable) e_old, (Value) -1);
860  eq_old = contrainte_make(subst_old);
861  sc_equation_add(sc, eq_old);
862  }
863 
864  pips_debug(7, "%s has already been translated into %s\n",
865  entity_name(v), entity_name(e));
866  if(!language_c_p(module_language(m))) {
867  user_warning("translate_global_value",
868  "Variable %s is probably aliased with a formal parameter"
869  " by the current call to %s from %s.\n"
870  "This is forbidden by the Fortran 77 standard.\n",
872  }
873  ifdebug(7) {
874  pips_debug(7,
875  "%s should again be translated into %s by projection of %s\n",
876  entity_name(v), entity_name(e), entity_name(v));
877  dump_transformer(tf);
878  }
879 
883  }
884 
885  tf = transformer_projection(tf, args);
886  gen_free_list(args);
887 
888  ifdebug(7) {
889  pips_debug(7, "After projection of %s\n",
890  entity_name(v));
891  dump_transformer(tf);
892  }
893  }
894  else {
895  pips_debug(7, "%s is translated into %s\n",
896  entity_name(v), entity_name(e));
898  }
899 
900  v_init = (entity)
903  (char *) NULL),
904  entity_domain);
905  if(v_init != entity_undefined) {
906  entity e_init = (entity)
909  (char *) NULL),
910  entity_domain);
911  if(e_init == entity_undefined) {
912  /* this cannot happen when the summary transformer
913  of a called procedure is translated because
914  the write effect in the callee that is implied
915  by v_init existence must have been passed
916  upwards and must have led to the creation
917  of e_init */
918  /* this should not happen when a caller
919  precondition at a call site is transformed
920  into a piece of a summary precondition for
921  the callee because v_init becomes meaningless;
922  at the callee's entry point, by definition,
923  e == e_init; v_init should have been projected
924  before
925  */
926  Psysteme r =
928 
929  if(base_contains_variable_p(sc_base(r), (Variable) v_init))
930  pips_internal_error("Cannot find value %s",
931  strdup(
932  concatenate(
937  (char *) NULL)));
938  else {
939  /* forget e_init: there is no v_init in tf */
940  ;
941  pips_debug(7, "%s is not used in tf\n",
942  entity_name(v_init));
943  }
944  }
945  else {
946  pips_debug(7, "%s is translated into %s\n",
947  entity_name(v), entity_name(e));
948  if(transformer_value_substitutable_p(tf, v_init, e_init))
949  transformer_value_substitute(tf, v_init, e_init);
950  else {
951  pips_user_error("Unsupported aliasing linked to %s and %s\n",
952  entity_name(v_init), entity_name(e_init));
953  }
954  }
955  }
956  else {
957  /* there is no v_init to worry about; v is not changed in
958  the caller (or its subtree of callees) */
959  }
960  }
961  else {
962  /* this value does not need to be translated */
963  }
964 }
#define MODULE_SEP_STRING
Definition: naming-local.h:30
void * gen_find_tabulated(const char *, int)
Definition: tabulated.c:218
#define module_language(e)
implemented as a macro to allow lhs
bool top_level_entity_p(entity e)
Check if the scope of entity e is global.
Definition: entity.c:1130
bool same_scalar_location_p(entity, entity)
FI: transferred from semantics (should be used for effect translation as well)
Definition: variable.c:1992
#define ram_undefined
Definition: ri.h:2221
#define ram_function(x)
Definition: ri.h:2247
#define storage_rom_p(x)
Definition: ri.h:2525
#define entity_domain
newgen_syntax_domain_defined
Definition: ri.h:410
#define storage_undefined
Definition: ri.h:2476
void sc_add_egalite(Psysteme p, Pcontrainte e)
void sc_add_egalite(Psysteme p, Pcontrainte e): macro ajoutant une egalite e a un systeme p; la base ...
Definition: sc_alloc.c:389
Psysteme sc_equation_add(Psysteme sc, Pcontrainte c)
The basis of the constraint system is updated.
Definition: sc_insert_eq.c:101
#define OLD_VALUE_SUFFIX
bool transformer_value_substitutable_p(transformer t, entity e1, entity e2)
If e1 does not appear in t, it is substitutable.
Definition: transformer.c:2033
bool value_entity_p(entity)
Definition: value.c:976
entity value_alias(entity)
Static aliasing.
Definition: value.c:1729
bool global_old_value_p(entity)
Return true if an entity is a global old value (such as "i#init"...).
Definition: value.c:690

References arguments_add_entity(), base_contains_variable_p(), BASE_UNDEFINED, concatenate(), CONS, contrainte_make(), CONTRAINTE_UNDEFINED, dump_transformer, ENTITY, entity_constant_p, entity_domain, entity_is_argument_p(), entity_local_name(), entity_module_name(), entity_name, entity_storage, entity_type, entity_undefined, eq, gen_find_tabulated(), gen_free_list(), global_new_value_to_global_old_value(), global_old_value_p(), ifdebug, language_c_p, module_language, module_local_name(), MODULE_SEP_STRING, NIL, OLD_VALUE_SUFFIX, pips_debug, pips_internal_error, pips_user_error, predicate_system, ram_function, ram_section, ram_undefined, same_scalar_location_p(), sc_add_egalite(), sc_equation_add(), storage_formal_p, storage_ram, storage_ram_p, storage_return_p, storage_rom_p, storage_tag, storage_undefined, strdup(), top_level_entity_p(), transformer_arguments, transformer_filter(), transformer_projection(), transformer_relation, transformer_value_substitutable_p(), transformer_value_substitute(), type_equal_p(), type_to_string(), user_warning, value_alias(), value_entity_p(), vect_add_elem(), and vect_new().

Referenced by translate_global_values().

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

◆ translate_global_values()

void translate_global_values ( entity  m,
transformer  tf 
)

a copy of sc_base(s) is needed because translate_global_value() modifies it at the same time

Parameters
tff

Definition at line 625 of file interprocedural.c.

626 {
628  /* a copy of sc_base(s) is needed because translate_global_value()
629  modifies it at the same time */
630  Pbase b = (Pbase) vect_dup(sc_base(s));
631  Pbase bv;
632 
633  ifdebug(6) {
634  pips_debug(6, "Predicate for tf:\n");
635  sc_fprint(stderr, s, (char * (*)(Variable)) dump_value_name);
636  }
637 
638  for(bv = b; bv != NULL; bv = bv->succ) {
640 
641  }
642 
643  base_rm(b);
644 }
void translate_global_value(entity m, transformer tf, entity v)
Try to convert an value on a non-local variable into an value on a local variable using a guessed nam...
struct Svecteur * Pbase

References base_rm, dump_value_name(), ifdebug, pips_debug, predicate_system, sc_fprint(), Svecteur::succ, transformer_relation, translate_global_value(), vect_dup(), and vecteur_var.

Referenced by add_module_call_site_precondition(), fortran_user_call_to_transformer(), get_semantic_text(), load_summary_precondition(), module_name_to_total_preconditions(), precondition_intra_to_inter(), process_call_for_summary_precondition(), and program_precondition().

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

◆ true_condition_wrt_precondition_p()

bool true_condition_wrt_precondition_p ( expression  c,
transformer  pre 
)
Parameters
prere

Definition at line 5900 of file expression.c.

5901 {
5902  bool result = false;
5903 
5904  result = eval_condition_wrt_precondition_p(c, pre, true);
5905 
5906  return result;
5907 }

References eval_condition_wrt_precondition_p().

Referenced by whileloop_to_postcondition(), and whileloop_to_total_precondition().

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

◆ unstructured_to_flow_insensitive_transformer()

transformer unstructured_to_flow_insensitive_transformer ( unstructured  u)

This simple fix-point over-approximates the CFG by a fully connected graph.

Each vertex can be executed at any time any number of times.

The fix point is easy to compute because it is the fix point of the convex hull all each node transformers.

The result is sometimes surprising as users see the real paths and cannot understand why a variable is declared modified when it obviously is not. This mostly choses in node preconditions since the overall unstructured transformer is not displayed usually and since it is globally correct.

But it is a perfectly valid over-approximation usable by automatic analyses.

Using the effects of the unstructured to derive a fix point leads to the same surprise although it is as correct, using the same over approximation of the control flow graph but a cruder version of the transformers.

This function is also used when computing preconditions if the exit node is not reached (?). It assumes that transformers for all statements in the unstructured have already been computed.

Two modes are possible: the transitive closure of the convex hull of all elementary transformers, or the transitive closure of the transformer list.

Assume any reachable node is executed at each iteration. A fix-point of the result can be used to approximate the node preconditions. Some nodes can be discarded because they do not modify the store such as IF statements (always) and CONTINUE statements (if they do not link the entry and the exit nodes).

Entry node

transformer_convex_hull has side effects on its arguments:-(

Should be fixed now, 29 June 2000

transformer tf_st = copy_transformer(load_statement_transformer(st));

Any side effect?

test

continue

other

Definition at line 2206 of file unstructured.c.

2207 {
2208  /* Assume any reachable node is executed at each iteration. A fix-point
2209  of the result can be used to approximate the node preconditions. Some
2210  nodes can be discarded because they do not modify the store such as
2211  IF statements (always) and CONTINUE statements (if they do not link
2212  the entry and the exit nodes). */
2213 
2214  list nodes = NIL;
2215  /* Entry node */
2216  control entry_node = unstructured_control(u);
2217  control exit_node = unstructured_exit(u);
2218  transformer tf_u = transformer_empty();
2220  bool tfl_p = get_bool_property("SEMANTICS_USE_TRANSFORMER_LISTS");
2221  list tfl = NIL;
2222 
2223  pips_debug(8,"begin\n");
2224 
2225  FORWARD_CONTROL_MAP(c, {
2226  statement st = control_statement(c);
2227  /* transformer_convex_hull has side effects on its arguments:-( */
2228  /* Should be fixed now, 29 June 2000 */
2229  /* transformer tf_st = copy_transformer(load_statement_transformer(st)); */
2231  transformer tf_old = tf_u;
2232 
2233  if(statement_test_p(st)) {
2234  /* Any side effect? */
2235  if(!ENDP(transformer_arguments(tf_st))) {
2236  if(tfl_p) {
2237  tfl = CONS(TRANSFORMER, tf_st, tfl);
2238  }
2239  else {
2240  tf_u = transformer_convex_hull(tf_old, tf_st); /* test */
2241  free_transformer(tf_old);
2242  }
2243  }
2244  }
2245  else {
2246  if(continue_statement_p(st)) {
2248  && gen_find_eq(exit_node, control_successors(c))!=chunk_undefined) {
2249  if(tfl_p) {
2250  tfl = CONS(TRANSFORMER, tf_st, tfl);
2251  }
2252  else {
2253  tf_u = transformer_convex_hull(tf_old, tf_st); /* continue */
2254  free_transformer(tf_old);
2255  }
2256  }
2257  }
2258  else {
2259  if(tfl_p) {
2260  tfl = CONS(TRANSFORMER, tf_st, tfl);
2261  }
2262  else {
2263  tf_u = transformer_convex_hull(tf_old, tf_st); /* other */
2264  free_transformer(tf_old);
2265  }
2266  }
2267  }
2268 
2269  ifdebug(1) {
2270  pips_assert("tf_st is internally consistent",
2272  if(!tfl_p)
2273  pips_assert("tf_u is internally consistent",
2275  }
2276 
2277  }, entry_node, nodes) ;
2278 
2279  gen_free_list(nodes) ;
2280 
2281  if(tfl_p) {
2282  // FI: apparently, we need T* rather than T+
2283  fp_tf_u = transformer_list_transitive_closure(tfl);
2284  gen_free_list(tfl);
2285  }
2286  else
2287  fp_tf_u = (*transformer_fix_point_operator)(tf_u);
2288 
2289  ifdebug(8) {
2290  pips_debug(8,"Result for one step tf_u:\n");
2291  print_transformer(tf_u);
2292  pips_assert("tf_u is internally consistent",
2294  pips_debug(8,"Result for fix-point fp_tf_u:\n");
2295  print_transformer(fp_tf_u);
2296  pips_assert("fp_tf_u is internally consistent",
2298  }
2299 
2300  pips_debug(8,"end\n");
2301 
2302  return fp_tf_u;
2303 }
#define chunk_undefined
obsolete
Definition: genC.h:79
#define FORWARD_CONTROL_MAP(ctl, code, c, list)
Walk through all the controls forward-reachable from a given control node of an unstructured.
void * gen_find_eq(const void *item, const list seq)
Definition: list.c:422
bool statement_test_p(statement)
Definition: statement.c:343
bool continue_statement_p(statement)
Test if a statement is a CONTINUE, that is the FORTRAN nop, the ";" in C or the "pass" in Python....
Definition: statement.c:203
#define control_successors(x)
Definition: ri.h:945
#define unstructured_exit(x)
Definition: ri.h:3006
transformer transformer_list_transitive_closure(list)
Compute (U tfl)*.

References chunk_undefined, CONS, continue_statement_p(), control_predecessors, control_statement, control_successors, ENDP, FORWARD_CONTROL_MAP, free_transformer(), gen_find_eq(), gen_free_list(), get_bool_property(), ifdebug, load_statement_transformer(), NIL, pips_assert, pips_debug, print_transformer, statement_test_p(), TRANSFORMER, transformer_arguments, transformer_convex_hull(), transformer_empty(), transformer_internal_consistency_p(), transformer_list_transitive_closure(), transformer_undefined, unstructured_control, and unstructured_exit.

Referenced by unstructured_to_postcondition(), unstructured_to_total_precondition(), and unstructured_to_transformer().

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

◆ unstructured_to_flow_sensitive_postconditions()

transformer unstructured_to_flow_sensitive_postconditions ( transformer  pre_u,
transformer  pre,
unstructured  u 
)

compute pre- and post-conditions in an unstructured from the entry precondition pre and return the exit postcondition.

pre_u is pre filtered by the u's transformer and can be used for any node.

control tail = unstructured_exit(u);

Parameters
pre_ure_u
prere

Definition at line 2040 of file unstructured.c.

2042 {
2044  list succs = NIL;
2045  control head = unstructured_control(u);
2046  /* control tail = unstructured_exit(u); */
2047 
2048  forward_control_map_get_blocs(head, &succs);
2049 
2050  if(((int)gen_length(succs))>get_int_property("SEMANTICS_MAX_CFG_SIZE1")) {
2051  semantics_user_warning("\nControl flow graph too large for an accurate analysis (%d nodes)\n"
2052  "Have you fully restructured your code?\n", gen_length(succs));
2053  post = unstructured_to_postconditions(pre, pre_u, u);
2054  }
2055  else if(!get_bool_property("SEMANTICS_ANALYZE_UNSTRUCTURED")) {
2056  semantics_user_warning("\nControl flow graph not analyzed accurately"
2057  " because property SEMANTICS_ANALYZE_UNSTRUCTURED is not set\n");
2058  post = unstructured_to_postconditions(pre_u, pre, u);
2059  }
2060  else if(!get_bool_property("SEMANTICS_FIX_POINT")) {
2061  post = unstructured_to_postconditions(pre_u, pre, u);
2062  }
2063  else {
2065  (pre_u, pre, u, true);
2066  }
2067  gen_free_list(succs);
2068 
2069  pips_assert("Postcondition for unstructured is consistent",
2071 
2072  return post;
2073 }
static transformer unstructured_to_postconditions(transformer pre, transformer pre_first, unstructured u)
transformer unstructured_to_flow_sensitive_postconditions_or_transformers(transformer pre_u, transformer pre, unstructured u, bool postcondition_p)
compute either the postconditions in an unstructured or the transformer of this unstructured.

References forward_control_map_get_blocs(), gen_free_list(), gen_length(), get_bool_property(), get_int_property(), NIL, pips_assert, semantics_user_warning, transformer_consistency_p(), transformer_undefined, unstructured_control, unstructured_to_flow_sensitive_postconditions_or_transformers(), and unstructured_to_postconditions().

Referenced by unstructured_to_postcondition().

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

◆ unstructured_to_flow_sensitive_postconditions_or_transformers()

transformer unstructured_to_flow_sensitive_postconditions_or_transformers ( transformer  pre_u,
transformer  pre,
unstructured  u,
bool  postcondition_p 
)

compute either the postconditions in an unstructured or the transformer of this unstructured.

In both cases, transformers for all nodes used to be supposed to be available.

Do not go down into nested unstructured

Propagate the precondition in the DAG and recompute the cycle transformers or compute the path transformers and the cycle fix point transformers.

Compute the real precondition for each statement and propagate postconditions in it.

Take care of unreachable nodes

Get rid of the auxiliary data structures

Parameters
pre_ure_u
preprecondition at entry: e_pre
uprecondition true for every node: n_pre
postcondition_postcondition_p

Definition at line 1821 of file unstructured.c.

1826 {
1828  hash_table ancestor_map = hash_table_undefined;
1829  hash_table scc_map = hash_table_undefined;
1830  control_mapping fix_point_map = make_control_fix_point_map();
1832  list partition = bourdoncle_partition(u, &ndu, &ancestor_map, &scc_map);
1833  control_mapping control_postcondition_map = make_control_postcondition_map();
1834  transformer pre_u_r = transformer_range(pre_u);
1835  transformer pre_r = transformer_range(pre);
1836 
1837  recursive_context context = { postcondition_p, control_postcondition_map };
1838 
1839  recursive_context fcontext = { postcondition_p, fix_point_map };
1840 
1841  ifdebug(2) {
1842  pips_debug(2, "Begin for %s with nodes:\n",
1843  postcondition_p? "postconditions" : "transformer");
1844  /* Do not go down into nested unstructured */
1847  pips_debug(2, "With entry nodes\n");
1849  pips_debug(2, "And exit node\n");
1851  pips_debug(2, "And embedding graph:\n");
1854  }
1855 
1856  /* Propagate the precondition in the DAG and recompute the cycle
1857  transformers or compute the path transformers and the cycle fix point
1858  transformers. */
1860  (partition, ndu, ancestor_map, scc_map, fix_point_map,
1861  postcondition_p? pre_u : pre_u_r, postcondition_p? pre : pre_r,
1862  control_postcondition_map, postcondition_p);
1863 
1864  if(postcondition_p) {
1865  /* Compute the real precondition for each statement and propagate
1866  postconditions in it. */
1867 
1869  (partition, ndu, ancestor_map, scc_map, fix_point_map, pre_u, pre,
1870  control_postcondition_map);
1871  }
1872 
1873  /* Take care of unreachable nodes */
1875  ndu, (void *) & context,
1878  NULL);
1879 
1880  ifdebug(2) {
1881  pips_debug(2, "%s for unstructured\n",
1882  postcondition_p? "Postconditions": "Path transformer");
1884  ndu, (void *) & context,
1888  NULL);
1889  pips_debug(2, "End of map\n");
1890  if(hash_table_entry_count(fix_point_map)>0) {
1891  pips_debug(2, "Fix point map:\n");
1893  u, (void *) & fcontext,
1897  NULL);
1898  pips_debug(2, "End of fix point map\n");
1899  pips_debug(2, "Dump fix point map %p:\n", fix_point_map);
1900  HASH_MAP(k, v, {
1901  control c = (control) k;
1903  transformer fp_tf = (transformer) v;
1904 
1906  fprintf(stderr, "Statement %s", statement_identification(s));
1907  print_transformer(fp_tf);
1908  }, fix_point_map);
1909  pips_debug(2, "End of fix point map dump\n");
1910  }
1911  else {
1912  fprintf(stderr, "No fix point. Empty fix point map\n");
1913  }
1914  }
1915 
1916  post = copy_transformer
1918  control_postcondition_map));
1919  control_postcondition_map = free_control_postcondition_map(control_postcondition_map);
1920  fix_point_map = free_control_fix_point_map(fix_point_map);
1921 
1922  ifdebug(2) {
1923  pips_assert("The postcondition post is defined", !transformer_undefined_p(post));
1924  pips_debug(2, "End with unstructured postcondition:\n");
1925  print_transformer(post);
1926  }
1927 
1928  /* Get rid of the auxiliary data structures */
1929  bourdoncle_free(ndu, ancestor_map, scc_map);
1930 
1931  return post;
1932 }
void bourdoncle_free(unstructured ndu, hash_table ancestor_map, hash_table scc_map)
Definition: bourdoncle.c:2506
list bourdoncle_partition(unstructured u, unstructured *p_ndu, hash_table *p_ancestor_map, hash_table *p_scc_map)
Definition: bourdoncle.c:1902
void gen_multi_recurse(void *o,...)
Multi recursion visitor function.
Definition: genClib.c:3428
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
bool gen_false(__attribute__((unused)) gen_chunk *unused)
Return false and ignore the argument.
Definition: genClib.c:2796
struct _newgen_struct_control_ * control
#define unstructured_undefined
Definition: ri.h:2980
#define control_domain
newgen_controlmap_domain_defined
Definition: ri.h:98
static control_mapping free_control_postcondition_map(control_mapping control_postcondition_map)
Definition: unstructured.c:318
static control_mapping make_control_postcondition_map()
Definition: unstructured.c:311
static control_mapping free_control_fix_point_map(control_mapping control_fix_point_map)
Definition: unstructured.c:412
static control_mapping make_control_fix_point_map()
Definition: unstructured.c:405
static void local_process_unreachable_node(control c, recursive_context *pcontext)
static void dag_to_flow_sensitive_preconditions(list partition, unstructured ndu, hash_table ancestor_map, hash_table scc_map, control_mapping fix_point_map, transformer pre_u, transformer pre, control_mapping control_postcondition_map)
transformer dag_to_flow_sensitive_postconditions_or_transformers(list partition, unstructured ndu, hash_table ancestor_map, hash_table scc_map, control_mapping fix_point_map, transformer e_pre, transformer n_pre, hash_table control_postcondition_map, bool postcondition_p)
Compute transformers or preconditions.
static transformer load_control_postcondition(control c, control_mapping control_postcondition_map)
Definition: unstructured.c:169
static void print_control_node_uns(control c)
semantical analysis
Definition: unstructured.c:122
static void print_cycle_head_to_fixpoint(control c, recursive_context *pcontext)
A debug function to prettyprint the fix points.
static void node_to_path_transformer_or_postcondition(control c, recursive_context *pcontext)
A debug function to prettyprint the result.

References bourdoncle_free(), bourdoncle_partition(), control_domain, control_statement, copy_transformer(), dag_to_flow_sensitive_postconditions_or_transformers(), dag_to_flow_sensitive_preconditions(), fprintf(), free_control_fix_point_map(), free_control_postcondition_map(), gen_context_multi_recurse(), gen_false(), gen_multi_recurse(), gen_null(), gen_true(), HASH_MAP, hash_table_entry_count(), hash_table_undefined, ifdebug, load_control_postcondition(), local_process_unreachable_node(), make_control_fix_point_map(), make_control_postcondition_map(), node_to_path_transformer_or_postcondition(), pips_assert, pips_debug, print_control_node_uns(), print_cycle_head_to_fixpoint(), print_transformer, statement_domain, statement_identification(), transformer_range(), transformer_undefined, transformer_undefined_p, unstructured_control, unstructured_exit, and unstructured_undefined.

Referenced by unstructured_to_flow_sensitive_postconditions(), and unstructured_to_transformer().

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

◆ unstructured_to_flow_sensitive_total_preconditions()

transformer unstructured_to_flow_sensitive_total_preconditions ( transformer  t_post_u,
transformer  pre,
unstructured  u 
)

control tail = unstructured_exit(u);

Parameters
t_post_u_post_u
prere

Definition at line 2473 of file unstructured.c.

2475 {
2478  /* control tail = unstructured_exit(u); */
2479 
2480  pips_assert("Not implemented yet", false);
2481  pips_assert("Shut up the compiler", t_post_u==t_post_u && pre==pre && u==u);
2482 
2483  pips_assert("Total precondition for unstructured is consistent",
2484  transformer_consistency_p(t_pre));
2485 
2486  return post;
2487 }

References pips_assert, transformer_consistency_p(), and transformer_undefined.

Referenced by unstructured_to_total_precondition().

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

◆ unstructured_to_postcondition()

transformer unstructured_to_postcondition ( transformer  pre,
unstructured  u,
transformer  tf 
)

there is only one statement and no arcs in u; no need for a fix-point

FI: pre should not be duplicated because statement_to_postcondition() means that pre is not going to be changed, just post produced.

Do not try anything clever! God knows what may happen in unstructured code. Postcondition post is not computed recursively from its components but directly derived from u's transformer. Preconditions associated to its components are then computed independently, hence the name unstructured_to_postconditionS instead of unstructured_to_postcondition

propagate as precondition an invariant for the whole unstructured u assuming that all nodes in the CFG are fully connected, unless tf is not feasible because the unstructured is never exited or exited thru a call to STOP which invalidates the previous assumption.

FI: I do not know if I should duplicate pre or not.

FI: well, dumdum, you should have duplicated tf!

FI: euh... why? According to comments about transformer_apply() neither arguments are modified...

post = unstructured_to_postconditions(pre_n, pre, u);

Parameters
prere
tff

Definition at line 2075 of file unstructured.c.

2079 {
2080  transformer post;
2081  control c;
2082 
2083  pips_debug(8, "begin\n");
2084 
2085  pips_assert("unstructured u is defined", u!=unstructured_undefined);
2086 
2087  c = unstructured_control(u);
2088  if(control_predecessors(c) == NIL && control_successors(c) == NIL) {
2089  /* there is only one statement and no arcs in u; no need for a
2090  fix-point */
2091  pips_debug(8, "unique node\n");
2092  /* FI: pre should not be duplicated because
2093  * statement_to_postcondition() means that pre is not
2094  * going to be changed, just post produced.
2095  */
2097  control_statement(c));
2098  }
2099  else {
2100  /* Do not try anything clever! God knows what may happen in
2101  unstructured code. Postcondition post is not computed recursively
2102  from its components but directly derived from u's transformer.
2103  Preconditions associated to its components are then computed
2104  independently, hence the name unstructured_to_postconditionS
2105  instead of unstructured_to_postcondition */
2106  /* propagate as precondition an invariant for the whole
2107  unstructured u assuming that all nodes in the CFG are fully
2108  connected, unless tf is not feasible because the unstructured
2109  is never exited or exited thru a call to STOP which invalidates
2110  the previous assumption. */
2113 
2114  pips_debug(8, "complex: based on transformer\n");
2115  if(transformer_empty_p(tf)) {
2117  }
2118  else {
2119  tf_u = tf;
2120  }
2121  pre_n = invariant_wrt_transformer(pre, tf_u);
2122  ifdebug(8) {
2123  pips_debug(8, "filtered over approximated precondition holding for any node pre_n:\n");
2124  (void) print_transformer(pre_n) ;
2125  }
2126  /* FI: I do not know if I should duplicate pre or not. */
2127  /* FI: well, dumdum, you should have duplicated tf! */
2128  /* FI: euh... why? According to comments about transformer_apply()
2129  * neither arguments are modified...
2130  */
2131  /* post = unstructured_to_postconditions(pre_n, pre, u); */
2132  post = unstructured_to_flow_sensitive_postconditions(pre, pre_n, u);
2133  pips_assert("A valid postcondition is returned",
2134  !transformer_undefined_p(post));
2135  if(transformer_undefined_p(post)) {
2136  post = transformer_apply(transformer_dup(tf), pre);
2137  }
2138  transformer_free(pre_n);
2139  }
2140 
2141  pips_debug(8, "end\n");
2142 
2143  return post;
2144 }
transformer unstructured_to_flow_sensitive_postconditions(transformer pre_u, transformer pre, unstructured u)
compute pre- and post-conditions in an unstructured from the entry precondition pre and return the ex...
transformer unstructured_to_flow_insensitive_transformer(unstructured u)
This simple fix-point over-approximates the CFG by a fully connected graph.

References control_predecessors, control_statement, control_successors, ifdebug, invariant_wrt_transformer(), NIL, pips_assert, pips_debug, print_transformer, statement_to_postcondition(), transformer_apply(), transformer_dup(), transformer_empty_p(), transformer_free(), transformer_undefined, transformer_undefined_p, unstructured_control, unstructured_to_flow_insensitive_transformer(), unstructured_to_flow_sensitive_postconditions(), and unstructured_undefined.

Referenced by instruction_to_postcondition().

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

◆ unstructured_to_transformer()

transformer unstructured_to_transformer ( unstructured  u,
transformer  e_pre,
list  e 
)

effects of u

approximate store condition for all control nodes: simple context for improved transformer derivation; it is not a precondition and should have no arguments.

Same as previous one for the store on entry in the unstructured. This the entry node usually has predecessors in the CFG, this is not the context for the entry node. It is not a precondition.

No information available on entrance

Cheapest fix point transformer. The flow insensitive fix point could be used instead.

pre is replaced by its range condition later when needed

Transformers should be computed precisely whether the unstructured is left by the exit node or by an explicit or implicit call to STOP.

computing the transformer for u is like computing the postcondition with no information on entry: no, the input context may be used to refine the transformer.

pre_u is restricted to its range later when needed.

These tests should be performed at the scc level

Not really linked to fix point issue, but a way to know we are using a FAST option.

Do something for nodes unreachable from the entry but linked to the exit

The control flow graph is never exited... by the exit node

The unstructured is never exited, but all nodes are supposed to have transformers. This would never occur if the control restructuration were clean unless an infinite loop is stopped within a called procedure. Control effects are not reported.

FI: pre should be used!

Might be useless because it's now performed just above and more generally by a gen_multi_recurse()

Parameters
e_pre_pre
eprecondition on entrance

Definition at line 2332 of file unstructured.c.

2335 {
2337  list succs = NIL;
2338  control head = unstructured_control(u);
2339  control tail = unstructured_exit(u);
2340  /* approximate store condition for all control nodes: simple context for
2341  improved transformer derivation; it is not a precondition and should have no
2342  arguments. */
2344  /* Same as previous one for the store on entry in the unstructured. This
2345  the entry node usually has predecessors in the CFG, this is not the
2346  context for the entry node. It is not a precondition. */
2348 
2349  if(transformer_undefined_p(e_pre)) {
2350  /* No information available on entrance */
2351  pre = transformer_identity();
2352  }
2353  else {
2354  /* Cheapest fix point transformer. The flow insensitive fix point
2355  could be used instead. */
2357 
2358  /* pre is replaced by its range condition later when needed*/
2359  pre = transformer_safe_apply(fpf, e_pre);
2360  free_transformer(fpf);
2361  }
2362 
2363  pips_debug(8,"begin\n");
2364 
2365  forward_control_map_get_blocs(head, &succs);
2366 
2367  /* Transformers should be computed precisely whether the unstructured is
2368  left by the exit node or by an explicit or implicit call to STOP. */
2369  if(true || gen_in_list_p(tail, succs)) {
2370  /* computing the transformer for u is like computing the postcondition
2371  with no information on entry: no, the input context may be used to
2372  refine the transformer. */
2373 
2374  if(transformer_undefined_p(e_pre)) {
2375  pre_u = transformer_identity();
2376  }
2377  else {
2378  /* pre_u is restricted to its range later when needed. */
2379  pre_u = transformer_dup(e_pre);
2380  }
2381 
2382  /* These tests should be performed at the scc level */
2383  if(((int)gen_length(succs))>get_int_property("SEMANTICS_MAX_CFG_SIZE2")) {
2384  semantics_user_warning("\nControl flow graph too large for any analysis (%d nodes)\n"
2385  "Have you fully restructured your code?\n", gen_length(succs));
2387 
2388  if(!gen_in_list_p(tail, succs)) {
2389  tf = transformer_empty();
2390  }
2391  else {
2392  tf = effects_to_transformer(e);
2393  }
2394  }
2395  else if(((int)gen_length(succs))>get_int_property("SEMANTICS_MAX_CFG_SIZE1")) {
2396  semantics_user_warning("\nControl flow graph too large for an accurate analysis (%d nodes)\n"
2397  "Have you fully restructured your code?\n", gen_length(succs));
2399 
2400  if(!gen_in_list_p(tail, succs)) {
2401  tf = transformer_empty();
2402  }
2403  else {
2405  }
2406  }
2407  else if(!get_bool_property("SEMANTICS_ANALYZE_UNSTRUCTURED")) {
2408  semantics_user_warning("\nControl flow graph not analyzed accurately"
2409  " because property SEMANTICS_ANALYZE_UNSTRUCTURED is not set\n");
2411 
2412  if(!gen_in_list_p(tail, succs)) {
2413  tf = transformer_empty();
2414  }
2415  else {
2417  }
2418  }
2419  else if(!get_bool_property("SEMANTICS_FIX_POINT")) {
2420  /* Not really linked to fix point issue, but a way to know we are
2421  using a FAST option. */
2423 
2424  if(!gen_in_list_p(tail, succs)) {
2425  tf = transformer_empty();
2426  }
2427  else {
2429  }
2430  }
2431  else {
2433  (pre_u, pre, u, false);
2434  }
2435  free_transformer(pre_u);
2436  }
2437 
2438  if(!gen_in_list_p(tail, succs)) {
2439  /* Do something for nodes unreachable from the entry but linked to the exit */
2440  /* The control flow graph is never exited... by the exit node */
2441  /* The unstructured is never exited, but all nodes are supposed to
2442  have transformers. This would never occur if the control
2443  restructuration were clean unless an infinite loop is stopped
2444  within a called procedure. Control effects are not reported. */
2445  /* FI: pre should be used! */
2447  u,
2450  NULL);
2451  }
2452 
2453  /* Might be useless because it's now performed just above and more
2454  generally by a gen_multi_recurse() */
2455  if(!gen_in_list_p(tail, succs)) {
2456  pips_assert("if exit is not reached, tf is empty", transformer_empty_p(tf));
2457  tf = transformer_empty();
2458  }
2459 
2460  gen_free_list(succs);
2461  free_transformer(pre);
2462 
2463  pips_debug(8,"end\n");
2464 
2465  return tf;
2466 }
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
static void unreachable_node_to_transformer(control c)
static void unstructured_to_transformers(unstructured u, transformer pre)
Computation of transformers associated to each node of u and to each of its sub-statements.

References control_domain, effects_to_transformer(), forward_control_map_get_blocs(), free_transformer(), gen_false(), gen_free_list(), gen_in_list_p(), gen_length(), gen_multi_recurse(), gen_null(), gen_true(), get_bool_property(), get_int_property(), NIL, pips_assert, pips_debug, semantics_user_warning, statement_domain, transformer_dup(), transformer_empty(), transformer_empty_p(), transformer_identity(), transformer_safe_apply(), transformer_undefined, transformer_undefined_p, unreachable_node_to_transformer(), unstructured_control, unstructured_exit, unstructured_to_flow_insensitive_transformer(), unstructured_to_flow_sensitive_postconditions_or_transformers(), and unstructured_to_transformers().

Referenced by instruction_to_transformer().

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

◆ update_cycle_temporary_precondition()

void update_cycle_temporary_precondition ( control  c,
transformer  pre,
control_mapping  cycle_temporary_precondition_map 
)
Parameters
prere
cycle_temporary_precondition_mapycle_temporary_precondition_map

Definition at line 1021 of file unstructured.c.

1024 {
1026 
1027  pips_debug(2, "For control %p with statement %s:\n", c, statement_identification(s));
1029  ((void *) c, pre, (hash_table) cycle_temporary_precondition_map);
1030 
1031  ifdebug(6) {
1032  pips_debug(6, "Precondition %p for cycle %p:\n", pre, c);
1033  print_transformer(pre);
1034  }
1035 }
void update_temporary_precondition(void *k, transformer pre, hash_table precondition_map)
Definition: unstructured.c:975

References control_statement, ifdebug, pips_debug, print_transformer, statement_identification(), and update_temporary_precondition().

Referenced by cycle_to_flow_sensitive_preconditions(), and dag_to_flow_sensitive_preconditions().

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

◆ update_precondition_with_call_site_preconditions()

transformer update_precondition_with_call_site_preconditions ( transformer  t,
entity  caller,
entity  callee 
)

Update precondition t for callee with preconditions of call sites to callee in caller.

Call sites are found in the statement of caller, but also in its declarations. Return the updated precondition t.

summary effects for the callee

calls hidden in dimension declarations are not caught because entities are not traversed by gen_recurse().

This normalization seems pretty uneffective for fraer01.tpips

Parameters
calleraller
calleeallee

Definition at line 1371 of file interprocedural.c.

1374 {
1375  statement caller_statement = (statement) db_get_memory_resource
1376  (DBR_CODE, module_local_name(caller), true);
1377  /* summary effects for the callee */
1379 
1380  pips_assert("callee is the current module",
1382 
1383  entity old_entity = get_current_module_entity();
1384  statement old_statement = get_current_module_statement();
1385 
1388 
1389  set_current_module_entity(caller);
1390  set_current_module_statement(caller_statement);
1392  current_caller = caller;
1394 
1395  if(use_points_to_p())
1397  db_get_memory_resource(DBR_POINTS_TO,
1398  module_local_name(caller), true) );
1399 
1402  (DBR_CUMULATED_EFFECTS,
1403  module_local_name(caller), true));
1404 
1407  (DBR_PROPER_EFFECTS,
1408  module_local_name(caller), true));
1409 
1412  (DBR_PRECONDITIONS,
1413  module_local_name(caller),
1414  true) );
1415 
1416  module_to_value_mappings(caller);
1417 
1418  /* calls hidden in dimension declarations are not caught because
1419  entities are not traversed by gen_recurse(). */
1420  gen_multi_recurse(caller_statement,
1423  // FI: to be checked. Should be useless.
1424  //statement_domain, process_declaration_for_summary_precondition, gen_null,
1425  NULL);
1426 
1430  if(use_points_to_p())
1431  reset_pt_to_list();
1435  set_current_module_entity(old_entity);
1436  set_current_module_statement(old_statement);
1437 
1442 
1444  // Problem: the initializer pass does not notify pipsmake that the
1445  // module list, a.k.a. %ALL, has been changed.
1446  // I do not know how to fix pipsmake. Add a new exception to
1447  // restart the computation of the requested resource list? How can
1448  // we combine this one with the pips_user_error() exception?
1449  pips_user_error("No summary precondition for module \"%s\". The callgraph "
1450  "is probably broken because stubs have been generated."
1451  "Please (re)compute the call graph,"
1452  " e.g. display CALLGRAPH_FILE.\n",
1453  entity_name(caller));
1454  }
1455 
1456  /* This normalization seems pretty uneffective for fraer01.tpips */
1459 
1460  return t;
1461 }
bool transformer_defined_p(transformer p)
Definition: ri.c:2626
bool use_points_to_p()
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
static transformer current_precondition
static bool memorize_precondition_for_summary_precondition(statement s)
Each time a statement is entered, its precondition is memorized.
static bool process_call_for_summary_precondition(call c)
Update the current_summary_precondition, if necessary.
static entity current_caller
Context to compute summary preconditions.
static transformer current_summary_precondition
static entity current_callee
static list summary_effects_of_callee

References call_domain, callee, current_callee, current_caller, current_precondition, current_summary_precondition, db_get_memory_resource(), entity_name, entity_undefined, free_value_mappings(), gen_multi_recurse(), gen_null(), get_current_module_entity(), get_current_module_statement(), list_undefined, load_summary_effects(), memorize_precondition_for_summary_precondition(), module_local_name(), module_to_value_mappings(), pips_assert, pips_user_error, pop_statement_global_stack(), process_call_for_summary_precondition(), reset_cumulated_rw_effects(), reset_current_module_entity(), reset_current_module_statement(), reset_proper_rw_effects(), reset_pt_to_list(), reset_semantic_map(), set_cumulated_rw_effects(), set_current_module_entity(), set_current_module_statement(), set_proper_rw_effects(), set_pt_to_list(), set_semantic_map(), statement_domain, summary_effects_of_callee, transformer_defined_p(), transformer_normalize(), transformer_undefined, and use_points_to_p().

Referenced by ordinary_summary_precondition(), and summary_total_postcondition().

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

◆ update_statement_postcondition()

void update_statement_postcondition ( statement  ,
transformer   
)

◆ update_statement_precondition()

void update_statement_precondition ( statement  ,
transformer   
)

◆ update_statement_semantic()

void update_statement_semantic ( statement  ,
transformer   
)

◆ update_statement_temporary_precondition()

void update_statement_temporary_precondition ( statement  s,
transformer  pre,
statement_mapping  statement_temporary_precondition_map 
)
Parameters
prere
statement_temporary_precondition_maptatement_temporary_precondition_map

Definition at line 997 of file unstructured.c.

1000 {
1001  pips_debug(2, "For statement %s:\n", statement_identification(s));
1003  ((void *) s, pre, (hash_table) statement_temporary_precondition_map);
1004 }

References pips_debug, statement_identification(), and update_temporary_precondition().

Referenced by cycle_to_flow_sensitive_preconditions(), and dag_to_flow_sensitive_preconditions().

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

◆ update_statement_total_precondition()

void update_statement_total_precondition ( statement  ,
transformer   
)

◆ update_statement_transformer()

void update_statement_transformer ( statement  ,
transformer   
)

Referenced by statement_to_transformer(), and statement_to_transformer_list().

+ Here is the caller graph for this function:

◆ update_summary_precondition()

void update_summary_precondition ( entity  e,
transformer  t 
)

void update_summary_precondition(e, t): t is supposed to be a precondition related to one of e's call sites and translated into e's basis;

the current global precondition for e is replaced by its convex hull with t;

t may be slightly modified by transformer_convex_hull because of bad design (FI)

Definition at line 1390 of file dbm_interface.c.

1391 {
1394 
1395  pips_assert("update_summary_precondition", entity_module_p(e));
1396 
1397  debug(8, "update_summary_precondition", "begin\n");
1398 
1399  t_old = (transformer)
1400  db_get_memory_resource(DBR_SUMMARY_PRECONDITION, module_local_name(e),
1401  true);
1402 
1403  ifdebug(8) {
1404  debug(8, "update_summary_precondition", " old precondition for %s:\n",
1405  entity_local_name(e));
1406  print_transformer(t_old);
1407  }
1408 
1409  if(t_old == transformer_undefined)
1410  t_new = transformer_dup(t);
1411  else {
1412  t_new = transformer_convex_hull(t_old, t);
1413  transformer_free(t_old);
1414  }
1415 
1416  DB_PUT_MEMORY_RESOURCE(DBR_SUMMARY_PRECONDITION,
1417  module_local_name(e),
1418  (char*) t_new );
1419 
1420  ifdebug(8) {
1421  debug(8, "update_summary_precondition", "new precondition for %s:\n",
1422  entity_local_name(e));
1423  print_transformer(t_new);
1424  debug(8, "update_summary_precondition", "end\n");
1425  }
1426 }

References db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug(), entity_local_name(), entity_module_p(), ifdebug, module_local_name(), pips_assert, print_transformer, transformer_convex_hull(), transformer_dup(), transformer_free(), and transformer_undefined.

+ Here is the call graph for this function:

◆ update_summary_precondition_in_declaration()

void update_summary_precondition_in_declaration ( expression  e,
transformer  pre 
)

This function is called to deal with call sites located in initialization expressions carried by declarations.

Parameters
prere

Definition at line 1356 of file interprocedural.c.

1358 {
1359  current_precondition = pre;
1360  gen_recurse(e,
1361  call_domain,
1362  (bool (*)(void *)) process_call_for_summary_precondition,
1363  gen_null);
1364 }

References call_domain, current_precondition, gen_null(), gen_recurse, and process_call_for_summary_precondition().

Referenced by memorize_precondition_for_summary_precondition().

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

◆ update_temporary_precondition()

void update_temporary_precondition ( void *  k,
transformer  pre,
hash_table  precondition_map 
)
Parameters
prere
precondition_maprecondition_map

Definition at line 975 of file unstructured.c.

978 {
979  transformer t_pre = (transformer) hash_get(precondition_map, k);
980 
981  if(t_pre == (transformer) HASH_UNDEFINED_VALUE) {
982  pips_debug(2, "No previous precondition. Current one %p:\n", pre);
983  ifdebug(2) print_transformer(pre);
984  hash_put(precondition_map, k, (void *) transformer_dup(pre));
985  }
986  else {
987  transformer n_t_pre = transformer_convex_hull(pre, t_pre);
988  hash_update(precondition_map, k, (void *) n_t_pre);
989  pips_debug(2, "Previous precondition %p:\n", t_pre);
990  ifdebug(2) print_transformer(t_pre);
991  pips_debug(2, "New precondition %p:\n", n_t_pre);
992  ifdebug(2) print_transformer(n_t_pre);
993  free_transformer(t_pre);
994  }
995 }
void hash_put(hash_table htp, const void *key, const void *val)
This functions stores a couple (key,val) in the hash table pointed to by htp.
Definition: hash.c:364
void hash_update(hash_table htp, const void *key, const void *val)
update key->val in htp, that MUST be pre-existent.
Definition: hash.c:491
#define New
else
Definition: set.c:239

References free_transformer(), hash_get(), hash_put(), HASH_UNDEFINED_VALUE, hash_update(), ifdebug, pips_debug, print_transformer, transformer_convex_hull(), and transformer_dup().

Referenced by update_cycle_temporary_precondition(), and update_statement_temporary_precondition().

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

◆ upwards_vect_rename()

void upwards_vect_rename ( Pvecteur  v,
transformer  post 
)

Renaming of variables in v according to transformations occuring later.

If a variable is modified by post, its old value must be used in v

FI: it would probably ne more efficient to scan va and vb than the argument list...

Parameters
postost

Definition at line 1062 of file mappings.c.

1063 {
1064  /* FI: it would probably ne more efficient to
1065  * scan va and vb than the argument list...
1066  */
1067  list modified_values = transformer_arguments(post);
1068 
1069  FOREACH(ENTITY, v_new, modified_values) {
1070  entity v_init = new_value_to_old_value(v_new);
1071 
1072  (void) vect_variable_rename(v, (Variable) v_new,
1073  (Variable) v_init);
1074  }
1075 }
entity new_value_to_old_value(entity)
Definition: value.c:1710

References ENTITY, FOREACH, new_value_to_old_value(), transformer_arguments, and vect_variable_rename().

Referenced by add_declaration_list_information(), add_reference_information(), and transformer_add_integer_relation_information().

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

◆ use_points_to_p()

bool use_points_to_p ( void  )

Definition at line 565 of file dbm_interface.c.

566 {
568 }
static bool use_points_to_information_p

References use_points_to_information_p.

Referenced by update_precondition_with_call_site_preconditions().

+ Here is the caller graph for this function:

◆ user_call_to_transformer()

transformer user_call_to_transformer ( entity  f,
list  pc,
transformer  pre,
list  ef 
)
Parameters
pcc
prere
eff

Definition at line 2506 of file ri_to_transformers.c.

2510 {
2512 
2513  pips_debug(7, "begin\n");
2514  pips_assert("f is a module", entity_module_p(f));
2515 
2517  t_caller = effects_to_transformer(ef);
2518  }
2519  else {
2520  if(c_module_p(f))
2521  t_caller = c_user_call_to_transformer(f, pc, pre, ef);
2522  else
2523  t_caller = fortran_user_call_to_transformer(f, pc, ef);
2524  }
2525  pips_debug(7, "end\n");
2526  return t_caller;
2527 }
transformer fortran_user_call_to_transformer(entity f, list pc, list ef)
Effects are necessary to clean up the transformer t_caller.
transformer c_user_call_to_transformer(entity f, list pc, transformer pre, list ef)

References c_module_p(), c_user_call_to_transformer(), effects_to_transformer(), entity_module_p(), f(), fortran_user_call_to_transformer(), get_bool_property(), pips_assert, pips_debug, SEMANTICS_INTERPROCEDURAL, and transformer_undefined.

Referenced by call_to_transformer(), and expression_to_transformer().

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

◆ user_function_call_to_transformer()

transformer user_function_call_to_transformer ( entity  e,
expression  expr,
transformer  pre 
)

a function call is a call to a non void function in C and to a FUNCTION in Fortran

its precondition

Parameters
expra value
prea call to a function

Definition at line 1373 of file ri_to_transformers.c.

1377 {
1379  call c = expression_call(expr);
1380  entity f = call_function(c);
1381 
1382  if(c_module_p(f))
1383  tf = c_user_function_call_to_transformer(e, expr, pre);
1384  else
1385  tf = fortran_user_function_call_to_transformer(e, expr, pre);
1386 
1387  return tf;
1388 }
static transformer c_user_function_call_to_transformer(entity e, expression expr, transformer pre)
The Fortran and C versions are about the same.
static transformer fortran_user_function_call_to_transformer(entity e, expression expr, transformer __attribute__((unused)) pre)
its precondition

References c_module_p(), c_user_function_call_to_transformer(), call_function, expression_call(), f(), fortran_user_function_call_to_transformer(), and transformer_undefined.

Referenced by call_to_transformer(), float_call_expression_to_transformer(), integer_call_expression_to_transformer(), logical_expression_to_transformer(), and pointer_call_expression_to_transformer().

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

◆ value_mappings_compatible_vector_p()

bool value_mappings_compatible_vector_p ( Pvecteur  iv)

transform a vector based on variable entities into a vector based on new value entities when possible; does nothing most of the time; does a little in the presence of equivalenced variables

Ugly because it has a hidden side effect on v to handle Fortran equivalences and because its implementation is dependent on type Pvecteur.

Assume that the value mappings are available (as implied by the function's name!), which may not be true when dealing with call sites.

The variable may denote a constant with compatible type

or a temporary variable

Or a variable value

Or a phi variable, when transformers are computed by the region analysis

Or the vector cannot be used in the semantics analysis

Parameters
ivv

Definition at line 924 of file mappings.c.

925 {
926  Pvecteur v = iv;
927  for(;!VECTEUR_NUL_P(v); v = v->succ) {
928  if(vecteur_var(v) != TCST) {
929  entity e = (entity) vecteur_var(v);
930 
931  /* The variable may denote a constant with compatible type */
932  if(entity_constant_p(e) && !analyzed_constant_p(e)) {
933  return false;
934  }
935 
936  /* or a temporary variable */
937  else if(local_temporary_value_entity_p(e)) {
938  ;
939  }
940 
941  /* Or a variable value */
942  else if(entity_has_values_p(e)) {
943  entity new_v = entity_to_new_value(e);
944 
945  if(new_v != entity_undefined)
946  vecteur_var(v) = (Variable) new_v;
947  else
948  return false;
949  }
950 
951  /* Or a phi variable, when transformers are computed by the
952  region analysis */
953  else if(variable_phi_p(e)) {
954  ;
955  }
956 
957  /* Or the vector cannot be used in the semantics analysis */
958  else {
959  return false;
960  }
961  }
962  }
963  return true;
964 }
#define variable_phi_p(e)
true if e is a phi variable PHI entities have a name like: REGIONS:PHI#, where # is a number.
bool analyzed_constant_p(entity)
The constant may appear as a variable in the linear systems.
Definition: value.c:487
bool local_temporary_value_entity_p(entity)
Definition: value.c:654

References analyzed_constant_p(), entity_constant_p, entity_has_values_p(), entity_to_new_value(), entity_undefined, local_temporary_value_entity_p(), Svecteur::succ, TCST, variable_phi_p, VECTEUR_NUL_P, and vecteur_var.

Referenced by add_affine_bound_conditions(), add_declaration_list_information(), add_loop_index_exit_value(), add_loop_skip_condition(), add_reference_information(), affine_to_transformer(), integer_divide_to_transformer(), integer_right_shift_to_transformer(), simple_affine_to_transformer(), transformer_add_integer_relation_information(), and transformer_add_loop_index_incrementation().

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

◆ value_passing_summary_transformer()

transformer value_passing_summary_transformer ( entity  f,
transformer  tf 
)

With value passing, writes on formal parameters are not effective interprocedurally unless an array is passed as parameter.

All new values corresponding to formal arguments of f must be projected out and removed from the arguments list.

Performed by side-effect on tf.

The old values cannot be renamed directly after projection, because the transformer projection opearator detects an inconsistency.

Rename old values as temporary values in the caller frame.

Updates the argument list after the projections

Rename tmp values as new values in the caller frame.

oav renamed oav1 because of FOREACH macro implementation

Parameters
tff

Definition at line 1471 of file interprocedural.c.

1472 {
1473  list al = transformer_arguments(tf); // argument list
1474  list mfl = NIL; // modified formal list
1475  list omfl = NIL; // modified formal list
1476  list tvl = NIL; // temporary value list
1477  list ctvl = NIL; // current pointer in tvl
1478 
1479  FOREACH(ENTITY, a, al) {
1480  storage s = entity_storage(a);
1481 
1482  if(storage_formal_p(s)) {
1483  formal fs = storage_formal(s);
1484  if(formal_function(fs)==f) {
1485  //value v = entity_initial(a);
1486  if(!location_entity_p(a)) {
1487  // We are not dealing with a location entity, such as an
1488  // element of a formal array, which may be written in spite
1489  // of the value passing scheme
1490  entity nav = entity_to_new_value(a);
1491  entity oav = entity_to_old_value(a);
1492  mfl = CONS(ENTITY, nav, mfl);
1493  omfl = CONS(ENTITY, oav, omfl);
1494  }
1495  }
1496  }
1497  }
1498 
1499  /* The old values cannot be renamed directly after projection,
1500  because the transformer projection opearator detects an
1501  inconsistency. */
1502 
1503  /* Rename old values as temporary values in the caller frame. */
1504  FOREACH(ENTITY, oav, omfl) {
1506 
1507  tvl = CONS(ENTITY, tv, tvl);
1508  tf = transformer_value_substitute(tf, oav, tv);
1509  }
1510 
1511  /* Updates the argument list after the projections */
1512  tf = transformer_projection(tf, mfl);
1513 
1514  /* Rename tmp values as new values in the caller frame. */
1515  tvl = gen_nreverse(tvl);
1516  ctvl = tvl;
1517  /* oav renamed oav1 because of FOREACH macro implementation */
1518  FOREACH(ENTITY, oav1, omfl) {
1519  entity tv = ENTITY(CAR(ctvl));
1520  entity v = value_to_variable(oav1);
1521  entity nav = entity_to_new_value(v);
1522 
1523  tf = transformer_value_substitute(tf, tv, nav);
1524  POP(ctvl);
1525  }
1526 
1527  gen_free_list(tvl);
1528 
1529  return tf;
1530 }

References CAR, CONS, ENTITY, entity_storage, entity_to_new_value(), entity_to_old_value(), entity_type, f(), FOREACH, formal_function, gen_free_list(), gen_nreverse(), location_entity_p(), make_local_temporary_value_entity(), NIL, POP, storage_formal, storage_formal_p, transformer_arguments, transformer_projection(), transformer_value_substitute(), ultimate_type(), and value_to_variable().

Referenced by generic_module_name_to_transformers().

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

◆ variable_to_values()

list variable_to_values ( entity  e)

Definition at line 982 of file mappings.c.

983 {
984  list list_val = NIL;
985 
986  if(entity_has_values_p(e)) {
987  entity v_old = entity_to_old_value(e);
988  entity v_new = entity_to_new_value(e);
989 
990  list_val = CONS(ENTITY, v_old, list_val);
991  list_val = CONS(ENTITY, v_new, list_val);
992  }
993 
994  return list_val;
995 }

References CONS, ENTITY, entity_has_values_p(), entity_to_new_value(), entity_to_old_value(), and NIL.

Referenced by statement_to_postcondition().

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

◆ variables_to_new_values()

void variables_to_new_values ( Pvecteur  v)

replace variables by new values which is necessary for equivalenced variables

Definition at line 1038 of file mappings.c.

1039 {
1040  Pvecteur elem = VECTEUR_UNDEFINED;
1041 
1042  for(elem = v; !VECTEUR_NUL_P(elem); elem = vecteur_succ(elem)) {
1043  entity var = (entity) vecteur_var(elem);
1044 
1045  if(vecteur_var(elem)!=TCST) {
1046  entity v_new = entity_to_new_value(var);
1047 
1048  if(v_new!=var) {
1049  (void) vect_variable_rename(v, (Variable) var,
1050  (Variable) v_new);
1051  }
1052  }
1053  }
1054 }

References entity_to_new_value(), TCST, vect_variable_rename(), VECTEUR_NUL_P, vecteur_succ, VECTEUR_UNDEFINED, and vecteur_var.

Referenced by transformer_add_integer_relation_information().

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

◆ variables_to_old_values()

list variables_to_old_values ( list  list_mod)
Parameters
list_modist_mod

Definition at line 1024 of file mappings.c.

1025 {
1026  list list_val = NIL;
1027 
1028  MAP(ENTITY, e, {
1029  entity v_old = entity_to_old_value(e);
1030 
1031  list_val = CONS(ENTITY, v_old, list_val);
1032  }, list_mod);
1033  return list_val;
1034 }

References CONS, ENTITY, entity_to_old_value(), MAP, and NIL.

Referenced by recompute_loop_transformer().

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

◆ variables_to_values()

list variables_to_values ( list  list_mod)
Parameters
list_modist_mod

Definition at line 966 of file mappings.c.

967 {
968  list list_val = NIL;
969 
970  FOREACH(ENTITY, e, list_mod) {
971  if(entity_has_values_p(e)) {
972  entity v_old = entity_to_old_value(e);
973  entity v_new = entity_to_new_value(e);
974 
975  list_val = CONS(ENTITY, v_old, list_val);
976  list_val = CONS(ENTITY, v_new, list_val);
977  }
978  }
979  return list_val;
980 }

References CONS, ENTITY, entity_has_values_p(), entity_to_new_value(), entity_to_old_value(), FOREACH, and NIL.

Referenced by recompute_loop_transformer(), and statement_to_postcondition().

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

◆ whileloop_to_k_transformer()

transformer whileloop_to_k_transformer ( whileloop  l,
transformer  pre,
list  e,
int  k 
)
Parameters
prere
keffects of whileloop l

Definition at line 2617 of file loop.c.

2622 {
2625 
2626  if(evaluation_before_p(lt))
2627  t = new_whileloop_to_k_transformer(l, pre, e, k);
2628  else
2629  pips_internal_error("repeatloop_to_k_transformer() not implemented.");
2630  //t = repeatloop_to_k_transformer(l, pre, e);
2631  return t;
2632 }
transformer new_whileloop_to_k_transformer(whileloop wl, transformer pre, list wlel, int k)
Definition: loop.c:416

References evaluation_before_p, new_whileloop_to_k_transformer(), pips_internal_error, transformer_undefined, and whileloop_evaluation.

Referenced by whileloop_to_postcondition().

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

◆ whileloop_to_postcondition()

transformer whileloop_to_postcondition ( transformer  pre,
whileloop  l,
transformer  tf 
)

propagate an impossible precondition in the loop body

do not add the exit condition since it is redundant with pre, but take care of side effects in the condition c

transformer_apply() generates a lot of warnings

The loop may be entered at least once.

The standard transformer tb is not enough, especially if the loop body s is a loop since then it is not even the statement transformer, but more generally we do not want the identity to be taken into account in tb since it is already added with P0. So we would like to guarantee that at least one state change occurs: we are not interested in identity iterations. For instance, if s is a loop, this means that the loop is entered, except if the loop condition has side effects.

To recompute this transformer, we use a pre_fuzzy=T*(P0) because we have nothing better.

complete_statement_transformer() is not really useful here because we usually do not have tighly nested while loops.

Nothing special in the loop body: no tests, no while,...

Recompute the body transformer without taking identity transformers into account. This is not enough because the decision about "activity" should be made dimension by dimension. We cannot get good result in general with a convex hull performed here: only specific cases are handled. We need instead a complex formulae to compute the loop precondition as a function of p_0 and all t_i

btl is copied because the function below frees at least its components

The loop fix point transformer T* could be used to obtain the set of stores for any number of iterations, including 0. Instead, use T+ and a convex hull with the precondition for the first iteration, which preserves more information when the fixpoint is not precise:

P^* = P_0 U cond(c)(tb(cond(c)(tb^*(P_0))))

Bertrand Jeannet suggests that we compute P0 U T(P0) U T^2(P0) U T_3(P0) where T_3 is the transitive closure obtained for iterations 3 to infinity by setting the initial iteration number k to 3 before projection. NSAD 2010. No test case has been forwarded to show that this would be useful.

We need the loop effects to recompute the unrolled transformer. Let's use NIL to start with... disaster. Let's use the body effects and hope for no side effects in loop condition.

FI: since pre_next is no longer useful, pre_next2 could be avoided. It just makes debugging easier.

propagate preconditions in the loop body and get its postcondition

At least one iteration is executed. The postcondition can be computed into three different ways:

  • use the loop body postcondition and apply the loop exit condition transformer or precondition_add_condition_information;
  • or use the loop precondition, the loop transformer, the loop entry condition, the loop body transformer and the loop exit transformer;

or use both and use their intersection as unique postcondition (the added redundant information seems to result in less information after a projection for w09.f, Halbwachs car example).

The second way is more likely to suffer from non-convexity as it uses many more steps.

Also, note that precondition_add_condition_information() is more geared towards Fortran as it assumes no side effects in the condition evaluation. However, it is better at handling non-convex condition than condition_to_transformer(), but condition_to_transformer(), which is built on top of precondition_add_condition_information() could be improved/might be improvable... In case the condition is not convex, there is no single transformer which fits it. But the postcondition can be updated with different convex components and then different results united in a unique postcondition by a convex hull.

Let's execute the last iteration since it certainly exists

Assume the loop is entered, post_al, or not, post_ne, and perform the convex hull of both

The loop is executed at least once: let's execute the last iteration

The loop is never executed

Parameters
prere
tff

Definition at line 3141 of file loop.c.

3145 {
3147  statement s = whileloop_body(l);
3149 
3150  pips_debug(8, "begin\n");
3151 
3154  pips_internal_error("Halbwachs not implemented");
3155  }
3156 
3158  transformer c_t = condition_to_transformer(c, pre, false);
3159  pips_debug(8, "The loop is never executed\n");
3160 
3161  /* propagate an impossible precondition in the loop body */
3163  /* do not add the exit condition since it is redundant with pre,
3164  but take care of side effects in the condition c */
3165  /* transformer_apply() generates a lot of warnings */
3166  post = transformer_combine(copy_transformer(pre), c_t);
3167  //post = transformer_apply(c_t, pre);
3168  free_transformer(c_t);
3169  }
3170  else { /* The loop may be entered at least once. */
3171  transformer pre_next = transformer_dup(pre);
3172  transformer pre_init =
3174  c, pre, true);
3175  // FI: this should work but is not compatible with the following
3176  //code; by definition, tf also include the side effect of pre
3177  //transformer pre_init = transformer_apply(c_t, pre);
3178  transformer preb = transformer_undefined; // body precondition
3179  transformer postb = transformer_undefined; // body postcondition
3180  transformer tb = load_statement_transformer(s); // body transformer
3181  int k = get_int_property("SEMANTICS_K_FIX_POINT");
3182 
3183  /* The standard transformer tb is not enough, especially if the
3184  loop body s is a loop since then it is not even the statement
3185  transformer, but more generally we do not want the identity to
3186  be taken into account in tb since it is already added with
3187  P0. So we would like to guarantee that at least one state change
3188  occurs: we are not interested in identity iterations. For
3189  instance, if s is a loop, this means that the loop is entered,
3190  except if the loop condition has side effects.
3191 
3192  To recompute this transformer, we use a pre_fuzzy=T*(P0)
3193  because we have nothing better.
3194 
3195  complete_statement_transformer() is not really useful here
3196  because we usually do not have tighly nested while loops.
3197  */
3198  transformer pre_fuzzy = transformer_apply(tf, pre);
3199  //tb = complete_non_identity_statement_transformer(tb, pre_fuzzy, s);
3200  list btl = list_undefined;
3201  int fbtll = 0;
3202 
3203  if(get_bool_property("SEMANTICS_USE_TRANSFORMER_LISTS")) {
3204  list fbtl = statement_to_transformer_list(s, pre_fuzzy);
3205  fbtll = (int) gen_length(fbtl);
3206  // filter out transformers that do not modify the state
3207  // FI: this is not a general approach since it depends on the
3208  // framework used and on the other variables, but it helps!
3210  gen_full_free_list(fbtl);
3211 
3212  if(gen_length(btl)==0) {
3214  }
3215  else if(gen_length(btl)==1) {
3216  /* Nothing special in the loop body: no tests, no while,... */
3217  if(fbtll==1)
3218  tb = complete_statement_transformer(tb, pre_fuzzy, s);
3219  else
3220  // FI: not to sure about reuse and memory leaks...
3221  tb = copy_transformer(TRANSFORMER(CAR(btl)));
3222  }
3223  else {
3224  /* Recompute the body transformer without taking identity
3225  transformers into account. This is not enough because the
3226  decision about "activity" should be made dimension by
3227  dimension. We cannot get good result in general with a
3228  convex hull performed here: only specific cases are
3229  handled. We need instead a complex formulae to compute the
3230  loop precondition as a function of p_0 and all t_i*/
3231  /* btl is copied because the function below frees at least
3232  its components */
3234  }
3235  }
3236  else {
3237  tb = complete_statement_transformer(tb, pre_fuzzy, s);
3238  }
3239 
3240  pips_debug(8, "The loop may be executed and preconditions must"
3241  " be propagated in the loop body\n");
3242 
3243  if(k==1) {
3244  if(!get_bool_property("SEMANTICS_USE_TRANSFORMER_LISTS")
3245  || gen_length(btl)==1) {
3246  /* The loop fix point transformer T* could be used to obtain the
3247  * set of stores for any number of iterations, including
3248  * 0. Instead, use T+ and a convex hull with the precondition for
3249  * the first iteration, which preserves more information when the
3250  * fixpoint is not precise:
3251  *
3252  * P^* = P_0 U cond(c)(tb(cond(c)(tb^*(P_0))))
3253  *
3254  * Bertrand Jeannet suggests that we compute P0 U T(P0) U
3255  * T^2(P0) U T_3(P0) where T_3 is the transitive closure
3256  * obtained for iterations 3 to infinity by setting the initial
3257  * iteration number k to 3 before projection. NSAD 2010. No test
3258  * case has been forwarded to show that this would be useful.
3259  */
3260  // FI: I do not know why pre_next==pre is used instead of
3261  // pre_init==P_0 in the statement just below
3262  pre_next = transformer_combine(pre_next, tf);
3263  pre_next = precondition_add_condition_information(pre_next, c,
3264  pre_next, true);
3265  pre_next = transformer_combine(pre_next, tb);
3266  pre_next = precondition_add_condition_information(pre_next, c,
3267  pre_next, true);
3268  preb = transformer_convex_hull(pre_init, pre_next);
3269  }
3270  else { // transformer lists are used and at least two
3271  // transformers have been found
3272  transformer c_t = condition_to_transformer(c, pre_fuzzy, true);
3273  //transformer preb1 = transformer_list_closure_to_precondition(btl, c_t, pre_init);
3275  //pre_next = transformer_combine(pre_next, tf);
3276  //pre_next = precondition_add_condition_information(pre_next, c,
3277  // pre_next, true);
3278  //pre_next = transformer_combine(pre_next, tb);
3279  //pre_next = precondition_add_condition_information(pre_next, c,
3280  // pre_next, true);
3281  //transformer preb2 = transformer_convex_hull(pre_init, pre_next);
3282  //pips_assert("The two preconditions have the same arguments",
3283  // arguments_equal_p(transformer_arguments(preb1),
3284  // transformer_arguments(preb2)));
3285  // FI: the intersection generates overflows
3286  //preb = transformer_intersection(preb1, preb2);
3287  preb = preb1;
3288  }
3289  }
3290  else if (k==2) {
3291  /* We need the loop effects to recompute the unrolled
3292  transformer. Let's use NIL to start with... disaster.
3293  Let's use the body effects and hope for no side effects in
3294  loop condition.
3295  */
3296  list bel = load_cumulated_rw_effects_list(s); // Should be lel
3297  transformer tf2 = whileloop_to_k_transformer(l, pre, bel, 2);
3298  transformer pre_next2 = transformer_undefined;
3299  pre_next = transformer_combine(pre_next, tf2);
3300  pre_next = precondition_add_condition_information(pre_next, c,
3301  pre_next, true);
3302  pre_next = transformer_combine(pre_next, tb);
3303  pre_next = precondition_add_condition_information(pre_next, c,
3304  pre_next, true);
3305  preb = transformer_convex_hull(pre_init, pre_next);
3306 
3307  /* FI: since pre_next is no longer useful, pre_next2 could be
3308  avoided. It just makes debugging easier. */
3309  pre_next2 = copy_transformer(pre_next);
3310  pre_next2 = precondition_add_condition_information(pre_next2, c,
3311  pre_next2, true);
3312  pre_next2 = transformer_combine(pre_next2, tb);
3313  pre_next2 = precondition_add_condition_information(pre_next2, c,
3314  pre_next2, true);
3315  preb = transformer_convex_hull(preb, pre_next2);
3316  free_transformer(tf2);
3317  free_transformer(pre_next2);
3318  }
3319  else
3320  pips_user_error("Unexpected value %d for k.\n", k);
3321 
3322  free_transformer(pre_fuzzy);
3323 
3324  /* propagate preconditions in the loop body and get its postcondition */
3325 
3326  postb = statement_to_postcondition(preb, s);
3327 
3328  if(true_condition_wrt_precondition_p(c, pre)) {
3329  /* At least one iteration is executed. The postcondition can be
3330  * computed into three different ways:
3331  *
3332  * - use the loop body postcondition and apply the loop exit
3333  * condition transformer or precondition_add_condition_information;
3334  *
3335  * - or use the loop precondition, the loop transformer, the loop
3336  * entry condition, the loop body transformer and the loop exit
3337  * transformer;
3338  *
3339  * - or use both and use their intersection as unique
3340  * postcondition (the added redundant information seems to
3341  * result in *less* information after a projection for w09.f,
3342  * Halbwachs car example).
3343  *
3344  * The second way is more likely to suffer from non-convexity as
3345  * it uses many more steps.
3346  *
3347  * Also, note that precondition_add_condition_information() is
3348  * more geared towards Fortran as it assumes no side effects in
3349  * the condition evaluation. However, it is better at handling
3350  * non-convex condition than condition_to_transformer(), but
3351  * condition_to_transformer(), which is built on top of
3352  * precondition_add_condition_information() could be
3353  * improved/might be improvable... In case the condition is not
3354  * convex, there is no single transformer which fits it. But the
3355  * postcondition can be updated with different convex components
3356  * and then different results united in a unique postcondition
3357  * by a convex hull.
3358  */
3359 
3360  pips_debug(8, "The loop certainly is executed.\n");
3361 
3362  if(false) {
3364  transformer cpost = transformer_undefined; // combined postcondition
3365  ntl = transformer_apply(tf, pre);
3366  /* Let's execute the last iteration since it certainly exists */
3367  ntl = precondition_add_condition_information(ntl, c, ntl, true);
3368  post = transformer_apply(tb, ntl);
3369  free_transformer(ntl);
3370  post = precondition_add_condition_information(post, c, post, false);
3371 
3372  postb = precondition_add_condition_information(postb, c, postb, false);
3373 
3374  cpost = transformer_intersection(post, postb);
3375 
3376  free_transformer(post);
3377  free_transformer(postb);
3378 
3379  post = cpost;
3380  }
3381  else {
3382  // FI: does not work with side effects
3383  //post = precondition_add_condition_information(postb, c, postb, false);
3384  transformer pre_c = transformer_range(postb);
3385  transformer ctf = condition_to_transformer(c, pre_c, false);
3386  post = transformer_apply(ctf, postb);
3387  free_transformer(pre_c);
3388  free_transformer(ctf);
3389  }
3390  }
3391  else {
3392  /* Assume the loop is entered, post_al, or not, post_ne, and perform
3393  * the convex hull of both
3394  */
3395  transformer post_ne = transformer_dup(pre);
3397  //transformer tb = load_statement_transformer(s);
3398 
3399  pips_debug(8, "The loop may be executed or not\n");
3400 
3401  /* The loop is executed at least once: let's execute the last iteration */
3402  //post_al = transformer_apply(tb, preb);
3403 
3404  // FI: does not work with side effects
3405  //post = precondition_add_condition_information(postb, c, postb, false);
3406  transformer pre_c = transformer_range(postb);
3407  transformer ctf = condition_to_transformer(c, pre_c, false);
3408  // Mmeory leak? Do we still need postb?
3409  post_al = transformer_apply(ctf, postb);
3410  free_transformer(pre_c);
3411  free_transformer(ctf);
3412  // post_al = precondition_add_condition_information(postb, c, postb, false);
3413 
3414  /* The loop is never executed */
3415  // FI: does not work with side effects
3416  // post_ne = precondition_add_condition_information(post_ne, c, post_ne, false);
3417  pre_c = transformer_range(post_ne);
3418  ctf = condition_to_transformer(c, pre_c, false);
3419  // Mmeory leak
3420  post_ne = transformer_apply(ctf, post_ne);
3421  free_transformer(pre_c);
3422  free_transformer(ctf);
3423 
3424  post = transformer_convex_hull(post_ne, post_al);
3425  // free for postb too? hidden within post_al?
3426  transformer_free(post_ne);
3427  transformer_free(post_al);
3428  }
3429  }
3430 
3431  ifdebug(8) {
3432  pips_debug(8, "resultat post =");
3433  (void) print_transformer(post);
3434  }
3435  pips_debug(8, "end\n");
3436  return post;
3437 }
list statement_to_transformer_list(statement s, transformer spre)
A transformer is already available for statement s, but it is going to be refined into a list of tran...
bool false_condition_wrt_precondition_p(expression c, transformer pre)
Definition: expression.c:5891
bool true_condition_wrt_precondition_p(expression c, transformer pre)
Definition: expression.c:5900
transformer whileloop_to_k_transformer(whileloop l, transformer pre, list e, int k)
Definition: loop.c:2617
transformer transformer_list_multiple_closure_to_precondition(list, transformer, transformer)
When some variables are not modified by some transformers, use projections on subsets to increase the...
list transformer_list_to_active_transformer_list(list)
transformer active_transformer_list_to_transformer(list)
Reduce the sublist of active transformers in the transformer list ltl to one transformer using the co...

References active_transformer_list_to_transformer(), CAR, complete_statement_transformer(), condition_to_transformer(), copy_transformer(), empty_transformer(), false_condition_wrt_precondition_p(), free_transformer(), gen_full_copy_list(), gen_full_free_list(), gen_length(), get_bool_property(), get_int_property(), ifdebug, int, list_undefined, load_cumulated_rw_effects_list(), load_statement_transformer(), pips_debug, pips_flag_p, pips_internal_error, pips_user_error, precondition_add_condition_information(), print_transformer, SEMANTICS_FIX_POINT, SEMANTICS_INEQUALITY_INVARIANT, statement_to_postcondition(), statement_to_transformer_list(), TRANSFORMER, transformer_apply(), transformer_combine(), transformer_convex_hull(), transformer_dup(), transformer_empty(), transformer_free(), transformer_identity(), transformer_intersection(), transformer_list_multiple_closure_to_precondition(), transformer_list_to_active_transformer_list(), transformer_range(), transformer_undefined, true_condition_wrt_precondition_p(), whileloop_body, whileloop_condition, and whileloop_to_k_transformer().

Referenced by instruction_to_postcondition().

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

◆ whileloop_to_total_precondition()

transformer whileloop_to_total_precondition ( transformer  t_post,
whileloop  l,
transformer  tf,
transformer  context 
)

transformer_dup(pre)

Apply the loop fix point transformer T* to obtain the set of stores for any number of iteration, including 0.

propagate an impossible precondition in the loop body

The loop body precondition is not useful any longer

do not add the exit condition since it is redundant with pre

post = transformer_dup(pre);

At least one iteration is executed. The transformer of the loop body is not useful!

transformer tb = load_statement_transformer(s);

propagate preconditions in the loop body

ntl = transformer_apply(tf, pre);

Let's execute the last iteration since it certainly exists

post = transformer_apply(tb, ntl);

post = precondition_add_condition_information(post, c, post, false);

Assume the loop is entered, post_al, or not, post_ne, and perform the convex hull of both

= transformer_dup(pre)

propagate preconditions in the loop body

The loop is executed at least once: let's execute the last iteration

The loop is never executed

post = transformer_convex_hull(post_ne, post_al);

Parameters
t_post_post
tff
contextontext

Definition at line 3439 of file loop.c.

3444 {
3446  statement s = whileloop_body(l);
3448 
3449  pips_assert("not implemented yet", false && t_post==t_post);
3450 
3451  pips_debug(8,"begin\n");
3452 
3454  pips_internal_error("Halbwachs not implemented");
3455  }
3456  else {
3457  transformer preb = transformer_undefined /*= transformer_dup(pre)*/ ;
3458 
3459  /* Apply the loop fix point transformer T* to obtain the set of stores
3460  * for any number of iteration, including 0.
3461  */
3462  preb = transformer_combine(preb, tf);
3463 
3465  pips_debug(8, "The loop is never executed\n");
3466 
3467  /* propagate an impossible precondition in the loop body */
3469  /* The loop body precondition is not useful any longer */
3470  free_transformer(preb);
3471  /* do not add the exit condition since it is redundant with pre */
3472  /* post = transformer_dup(pre); */
3473  }
3475  /* At least one iteration is executed. The transformer of
3476  * the loop body is not useful!
3477  */
3478  /* transformer tb = load_statement_transformer(s); */
3480 
3481  pips_debug(8, "The loop certainly is executed\n");
3482 
3483  /* propagate preconditions in the loop body */
3484  preb = precondition_add_condition_information(preb, c, preb, true);
3485  (void) statement_to_postcondition(preb, s);
3486 
3487  /* ntl = transformer_apply(tf, pre); */
3488  /* Let's execute the last iteration since it certainly exists */
3489  ntl = precondition_add_condition_information(ntl, c, ntl, true);
3490  /* post = transformer_apply(tb, ntl); */
3491  free_transformer(ntl);
3492  /* post = precondition_add_condition_information(post, c, post, false); */
3493  }
3494  else {
3495  /* Assume the loop is entered, post_al, or not, post_ne, and perform
3496  * the convex hull of both
3497  */
3498  transformer post_ne = transformer_undefined /* = transformer_dup(pre) */ ;
3501 
3502  pips_debug(8, "The loop may be executed or not\n");
3503 
3504  /* propagate preconditions in the loop body */
3505  precondition_add_condition_information(preb, c, preb, true);
3506  (void) statement_to_postcondition(preb, s);
3507 
3508  /* The loop is executed at least once: let's execute the last iteration */
3509  post_al = transformer_apply(tb, preb);
3510  post_al = precondition_add_condition_information(post_al, c, post_al, false);
3511 
3512  /* The loop is never executed */
3513  post_ne = precondition_add_condition_information(post_ne, c, post_ne, false);
3514 
3515  /* post = transformer_convex_hull(post_ne, post_al); */
3516  transformer_free(post_ne);
3517  transformer_free(post_al);
3518  }
3519  }
3520 
3521  ifdebug(8) {
3522  pips_debug(8, "resultat t_pre=%p\n", t_pre);
3523  (void) print_transformer(t_pre);
3524  pips_debug(8,"end\n");
3525  }
3526 
3527  return t_pre;
3528 }

References false_condition_wrt_precondition_p(), free_transformer(), ifdebug, load_statement_transformer(), pips_assert, pips_debug, pips_flag_p, pips_internal_error, precondition_add_condition_information(), print_transformer, SEMANTICS_FIX_POINT, SEMANTICS_INEQUALITY_INVARIANT, statement_to_postcondition(), transformer_apply(), transformer_combine(), transformer_empty(), transformer_free(), transformer_undefined, true_condition_wrt_precondition_p(), whileloop_body, and whileloop_condition.

Referenced by instruction_to_total_precondition().

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

◆ whileloop_to_transformer()

transformer whileloop_to_transformer ( whileloop  l,
transformer  pre,
list  e 
)

effects of whileloop l

Parameters
prere

Definition at line 2583 of file loop.c.

2586 {
2589 
2590  if(evaluation_before_p(lt))
2591  t = new_whileloop_to_transformer(l, pre, e);
2592  else
2593  t = repeatloop_to_transformer(l, pre, e);
2594  return t;
2595 }
transformer repeatloop_to_transformer(whileloop wl, transformer pre, list wlel)
effects of whileloop wl
Definition: loop.c:449
transformer new_whileloop_to_transformer(whileloop wl, transformer pre, list wlel)
effects of whileloop wl
Definition: loop.c:380

References evaluation_before_p, new_whileloop_to_transformer(), repeatloop_to_transformer(), transformer_undefined, and whileloop_evaluation.

Referenced by instruction_to_transformer().

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

◆ words_predicate_to_commentary()

text words_predicate_to_commentary ( list  w_pred,
string  comment_prefix 
)

text words_predicate_to_commentary(list w_pred, string comment_prefix) input : a list of strings, one of them representing a predicate.

output : a text of several lines of commentaries containing this list of strings, and beginning with comment_prefix. modifies : nothing.

str_pred is the string corresponding to the concatenation of the strings in w_pred

Parameters
w_pred_pred
comment_prefixomment_prefix

Definition at line 653 of file prettyprint.c.

656 {
657  string str_pred;
658  text t_pred;
659 
660  /* str_pred is the string corresponding to the concatenation
661  * of the strings in w_pred */
662  str_pred = words_to_string(w_pred);
663 
664  t_pred = string_predicate_to_commentary(str_pred, comment_prefix);
665 
666  return(t_pred);
667 }
text string_predicate_to_commentary(string str_pred, string comment_prefix)
text string_predicate_to_commentary(string str_pred, string comment_prefix) input : a string,...
Definition: prettyprint.c:570
string words_to_string(cons *lw)
Definition: print.c:211

References string_predicate_to_commentary(), and words_to_string().

Referenced by print_any_reductions(), text_comp_region(), text_points_to(), and text_reductions().

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

Variable Documentation

◆ refine_transformers_p

bool refine_transformers_p
extern

Transformer recomputation cannot be of real use unless an interprocedural analysis is performed.

For intraprocedural analyses, using property SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT is sufficient.

Definition at line 198 of file semantics.h.

Referenced by process_ready_node(), refine_transformers(), refine_transformers_with_points_to(), statement_to_transformer(), and statement_to_transformer_list().