CBMC
dump_loop_contracts.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Dump Loop Contracts as JSON
4 
5 Author: Qinheping Hu, qinhh@amazon.com
6 
7 \*******************************************************************/
8 
11 
12 #include "dump_loop_contracts.h"
13 
14 #include <util/json_stream.h>
15 #include <util/simplify_expr.h>
16 
17 #include <ansi-c/expr2c.h>
18 
20  goto_modelt &goto_model,
21  const std::map<loop_idt, exprt> &invariant_map,
22  const std::map<loop_idt, std::set<exprt>> &assigns_map,
23  const std::string &json_output_str,
24  std::ostream &out)
25 {
26  // {
27  // "source" : [SOURCE_NAME_ARRAY],
28  // "functions" : [{
29  // FUN_NAME_1 : [LOOP_CONTRACTS_ARRAY],
30  // FUN_NAME_2 : [LOOP_CONTRACTS_ARRAY],
31  // ...
32  // }],
33  // "output" : OUTPUT
34  // }
35 
36  INVARIANT(!invariant_map.empty(), "No synthesized loop contracts to dump");
37 
38  namespacet ns(goto_model.symbol_table);
39 
40  // Set of names of source files.
41  std::set<std::string> sources_set;
42 
43  // Map from function name to LOOP_CONTRACTS_ARRAY json array of the function.
44  std::map<std::string, json_arrayt> function_map;
45 
46  json_arrayt json_sources;
47 
48  for(const auto &invariant_entry : invariant_map)
49  {
50  const auto head = get_loop_head(
51  invariant_entry.first.loop_number,
52  goto_model.goto_functions
53  .function_map[invariant_entry.first.function_id]);
54 
55  const auto source_file = id2string(head->source_location().get_file());
56  // Add source files.
57  if(sources_set.insert(source_file).second)
58  json_sources.push_back(json_stringt(source_file));
59 
60  // Get the LOOP_CONTRACTS_ARRAY for the function from the map.
61  auto it_function =
62  function_map.find(id2string(head->source_location().get_function()));
63  if(it_function == function_map.end())
64  {
65  std::string function_name =
66  id2string(head->source_location().get_function());
67 
68  // New LOOP_CONTRACTS_ARRAY
69  json_arrayt loop_contracts_array;
70  it_function =
71  function_map.emplace(function_name, loop_contracts_array).first;
72  }
73  json_arrayt &loop_contracts_array = it_function->second;
74 
75  // Adding loop invariants
76  // The loop number in Crangler is 1-indexed instead of 0-indexed.
77  std::string inv_string =
78  "loop " + std::to_string(invariant_entry.first.loop_number + 1) +
79  " invariant " +
80  expr2c(
81  simplify_expr(invariant_entry.second, ns),
82  ns,
84  loop_contracts_array.push_back(json_stringt(inv_string));
85 
86  // Adding loop assigns
87  const auto it_assigns = assigns_map.find(invariant_entry.first);
88  if(it_assigns != assigns_map.end())
89  {
90  std::string assign_string =
91  "loop " + std::to_string(invariant_entry.first.loop_number + 1) +
92  " assigns ";
93 
94  bool in_first_iter = true;
95  for(const auto &a : it_assigns->second)
96  {
97  if(!in_first_iter)
98  {
99  assign_string += ",";
100  }
101  else
102  {
103  in_first_iter = false;
104  }
105  assign_string += expr2c(
107  }
108  loop_contracts_array.push_back(json_stringt(assign_string));
109  }
110  }
111 
112  json_stream_objectt json_stream(out);
113  json_stream.push_back("sources", json_sources);
114 
115  // Initialize functions object.
116  json_arrayt json_functions;
117  json_objectt json_functions_object;
118  for(const auto &loop_contracts : function_map)
119  {
120  json_functions_object[loop_contracts.first] = loop_contracts.second;
121  }
122  json_functions.push_back(json_functions_object);
123  json_stream.push_back("functions", json_functions);
124 
125  // Destination of the Crangler output.
126  json_stringt json_output(json_output_str);
127  json_stream.push_back("output", json_output);
128 }
function_mapt function_map
symbol_tablet symbol_table
Symbol table.
Definition: goto_model.h:31
goto_functionst goto_functions
GOTO functions.
Definition: goto_model.h:34
jsont & push_back(const jsont &json)
Definition: json.h:212
Provides methods for streaming JSON objects.
Definition: json_stream.h:140
void push_back(const std::string &key, const jsont &json)
Push back a JSON element into the current object stream.
Definition: json_stream.h:178
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
void dump_loop_contracts(goto_modelt &goto_model, const std::map< loop_idt, exprt > &invariant_map, const std::map< loop_idt, std::set< exprt >> &assigns_map, const std::string &json_output_str, std::ostream &out)
Dump Loop Contracts as JSON.
std::string expr2c(const exprt &expr, const namespacet &ns, const expr2c_configurationt &configuration)
Definition: expr2c.cpp:4155
const std::string & id2string(const irep_idt &d)
Definition: irep.h:44
exprt simplify_expr(exprt src, const namespacet &ns)
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition: invariant.h:423
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
static expr2c_configurationt clean_configuration
This prints compilable C that loses some of the internal details of the GOTO program.
Definition: expr2c.h:75
Loop id used to identify loops.
Definition: loop_ids.h:28
goto_programt::targett get_loop_head(const unsigned int target_loop_number, goto_functiont &function)
Find and return the first instruction of the natural loop with loop_number in function.
Definition: utils.cpp:640