CBMC
link_to_library.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Library Linking
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
11 
12 #include "link_to_library.h"
13 
15 
17 #include "goto_convert_functions.h"
18 #include "goto_model.h"
19 #include "link_goto_model.h"
20 
22 static std::pair<std::optional<replace_symbolt::expr_mapt>, bool>
24  goto_modelt &goto_model,
25  message_handlert &message_handler,
26  const std::function<void(
27  const std::set<irep_idt> &,
28  const symbol_tablet &,
29  symbol_tablet &,
30  message_handlert &)> &library,
31  const irep_idt &missing_function)
32 {
33  goto_modelt library_model;
34  library(
35  {missing_function},
36  goto_model.symbol_table,
37  library_model.symbol_table,
38  message_handler);
39 
40  // convert to CFG
41  if(
42  library_model.symbol_table.symbols.find(missing_function) !=
43  library_model.symbol_table.symbols.end())
44  {
46  missing_function,
47  library_model.symbol_table,
48  library_model.goto_functions,
49  message_handler);
50  }
51  // We might need a function that's outside our own library, but brought in via
52  // some header file included by the library. Those functions already exist in
53  // goto_model.symbol_table, but haven't been converted just yet.
54  else if(
55  goto_model.symbol_table.symbols.find(missing_function) !=
56  goto_model.symbol_table.symbols.end())
57  {
59  missing_function,
60  goto_model.symbol_table,
61  library_model.goto_functions,
62  message_handler);
63  }
64 
65  // check whether additional initialization may be required
66  bool init_required = false;
67  if(
69  goto_model.goto_functions.function_map.end())
70  {
71  for(const auto &entry : library_model.symbol_table)
72  {
73  if(
74  entry.second.is_static_lifetime && !entry.second.is_type &&
75  !entry.second.is_macro && entry.second.type.id() != ID_code &&
76  !goto_model.symbol_table.has_symbol(entry.first))
77  {
78  init_required = true;
79  break;
80  }
81  }
82  }
83 
84  return {
85  link_goto_model(goto_model, std::move(library_model), message_handler),
86  init_required};
87 }
88 
99  goto_modelt &goto_model,
100  message_handlert &message_handler,
101  const std::function<void(
102  const std::set<irep_idt> &,
103  const symbol_tablet &,
104  symbol_tablet &,
105  message_handlert &)> &library)
106 {
107  // this needs a fixedpoint, as library functions
108  // may depend on other library functions
109 
110  std::set<irep_idt> added_functions;
111  // Linking in library functions (now seeing full definitions rather than
112  // forward declarations, or perhaps even cases of missing forward
113  // declarations) may result in type changes to objects.
114  replace_symbolt::expr_mapt object_type_updates;
115  bool need_reinit = false;
116 
117  while(true)
118  {
119  std::unordered_set<irep_idt> called_functions =
121 
122  bool changed = false;
123  for(const auto &id : called_functions)
124  {
125  goto_functionst::function_mapt::const_iterator f_it =
126  goto_model.goto_functions.function_map.find(id);
127 
128  if(
129  f_it != goto_model.goto_functions.function_map.end() &&
130  f_it->second.body_available())
131  {
132  // it's overridden!
133  }
134  else if(added_functions.find(id) != added_functions.end())
135  {
136  // already added
137  }
138  else
139  {
140  changed = true;
141  added_functions.insert(id);
142 
143  auto one_result =
144  add_one_function(goto_model, message_handler, library, id);
145  auto updates_opt = one_result.first;
146  need_reinit |= one_result.second;
147  if(!updates_opt.has_value())
148  {
149  messaget log{message_handler};
150  log.warning() << "Linking library function '" << id << "' failed"
151  << messaget::eom;
152  continue;
153  }
154  object_type_updates.insert(updates_opt->begin(), updates_opt->end());
155  }
156  }
157 
158  // done?
159  if(!changed)
160  break;
161  }
162 
163  if(need_reinit && goto_model.can_produce_function(INITIALIZE_FUNCTION))
164  recreate_initialize_function(goto_model, message_handler);
165 
166  if(!object_type_updates.empty())
167  finalize_linking(goto_model, object_type_updates);
168 }
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
function_mapt function_map
bool can_produce_function(const irep_idt &id) const override
Determines if this model can produce a body for the given function.
Definition: goto_model.h:95
symbol_tablet symbol_table
Symbol table.
Definition: goto_model.h:31
goto_functionst goto_functions
GOTO functions.
Definition: goto_model.h:34
Class that provides messages with a built-in verbosity 'level'.
Definition: message.h:155
static eomt eom
Definition: message.h:297
std::unordered_map< irep_idt, exprt > expr_mapt
const symbolst & symbols
Read-only field, used to look up symbols given their names.
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
The symbol table.
Definition: symbol_table.h:14
std::unordered_set< irep_idt > compute_called_functions(const goto_functionst &goto_functions)
computes the functions that are (potentially) called
Query Called Functions.
void goto_convert(const codet &code, symbol_table_baset &symbol_table, goto_programt &dest, message_handlert &message_handler, const irep_idt &mode)
Goto Programs with Functions.
Symbol Table + CFG.
double log(double x)
Definition: math.c:2776
void recreate_initialize_function(goto_modelt &goto_model, message_handlert &message_handler)
Regenerates the CPROVER_INITIALIZE function, which initializes all non-function symbols of the goto m...
#define INITIALIZE_FUNCTION