CBMC
link_goto_model.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Link Goto Programs
4 
5 Author: Michael Tautschnig, Daniel Kroening
6 
7 \*******************************************************************/
8 
11 
12 #include "link_goto_model.h"
13 
14 #include <unordered_set>
15 
16 #include <util/symbol.h>
17 #include <util/rename_symbol.h>
18 
19 #include <linking/linking_class.h>
20 
21 #include "goto_model.h"
22 
25  irep_idt &new_function_name,
26  const rename_symbolt &rename_symbol)
27 {
28  for(auto &identifier : function.parameter_identifiers)
29  {
30  auto entry = rename_symbol.expr_map.find(identifier);
31  if(entry != rename_symbol.expr_map.end())
32  identifier = entry->second;
33  }
34 
35  for(auto &instruction : function.body.instructions)
36  {
37  rename_symbol(instruction.code_nonconst());
38 
39  if(instruction.has_condition())
40  rename_symbol(instruction.condition_nonconst());
41  }
42 }
43 
46 static bool link_functions(
47  symbol_tablet &dest_symbol_table,
48  goto_functionst &dest_functions,
49  const symbol_tablet &src_symbol_table,
50  goto_functionst &src_functions,
51  const rename_symbolt &rename_symbol,
52  const std::unordered_set<irep_idt> &weak_symbols)
53 {
54  namespacet ns(dest_symbol_table);
55  namespacet src_ns(src_symbol_table);
56 
57  // merge functions
58  for(auto &gf_entry : src_functions.function_map)
59  {
60  // the function might have been renamed
61  rename_symbolt::expr_mapt::const_iterator e_it =
62  rename_symbol.expr_map.find(gf_entry.first);
63 
64  irep_idt final_id = gf_entry.first;
65 
66  if(e_it!=rename_symbol.expr_map.end())
67  final_id=e_it->second;
68 
69  // already there?
70  goto_functionst::function_mapt::iterator dest_f_it=
71  dest_functions.function_map.find(final_id);
72 
73  goto_functionst::goto_functiont &src_func = gf_entry.second;
74  if(dest_f_it==dest_functions.function_map.end()) // not there yet
75  {
76  rename_symbols_in_function(src_func, final_id, rename_symbol);
77  dest_functions.function_map.emplace(final_id, std::move(src_func));
78  }
79  else // collision!
80  {
81  goto_functionst::goto_functiont &in_dest_symbol_table = dest_f_it->second;
82 
83  if(in_dest_symbol_table.body.instructions.empty() ||
84  weak_symbols.find(final_id)!=weak_symbols.end())
85  {
86  // the one with body wins!
87  rename_symbols_in_function(src_func, final_id, rename_symbol);
88 
89  in_dest_symbol_table.body.swap(src_func.body);
90  in_dest_symbol_table.parameter_identifiers.swap(
91  src_func.parameter_identifiers);
92  }
93  else if(
94  src_func.body.instructions.empty() ||
95  src_ns.lookup(gf_entry.first).is_weak)
96  {
97  // just keep the old one in dest
98  }
99  else if(to_code_type(ns.lookup(final_id).type).get_inlined())
100  {
101  // ok, we silently ignore
102  }
103  }
104  }
105 
106  return false;
107 }
108 
110  goto_modelt &dest,
111  goto_modelt &&src,
112  message_handlert &message_handler)
113 {
114  std::unordered_set<irep_idt> weak_symbols;
115 
116  for(const auto &symbol_pair : dest.symbol_table.symbols)
117  {
118  if(symbol_pair.second.is_weak)
119  weak_symbols.insert(symbol_pair.first);
120  }
121 
122  linkingt linking(dest.symbol_table, src.symbol_table, message_handler);
123 
124  if(linking.typecheck_main())
125  {
126  messaget log{message_handler};
127  log.error() << "typechecking main failed" << messaget::eom;
128  return {};
129  }
130 
131  if(link_functions(
132  dest.symbol_table,
133  dest.goto_functions,
134  src.symbol_table,
135  src.goto_functions,
136  linking.rename_symbol,
137  weak_symbols))
138  {
139  messaget log{message_handler};
140  log.error() << "linking failed" << messaget::eom;
141  return {};
142  }
143 
144  return linking.object_type_updates.get_expr_map();
145 }
146 
148  goto_modelt &dest,
149  const replace_symbolt::expr_mapt &type_updates)
150 {
151  unchecked_replace_symbolt object_type_updates;
152  object_type_updates.get_expr_map().insert(
153  type_updates.begin(), type_updates.end());
154 
155  goto_functionst &dest_functions = dest.goto_functions;
156  symbol_tablet &dest_symbol_table = dest.symbol_table;
157 
158  // apply macros
159  rename_symbolt macro_application;
160 
161  for(const auto &symbol_pair : dest_symbol_table.symbols)
162  {
163  if(symbol_pair.second.is_macro && !symbol_pair.second.is_type)
164  {
165  const symbolt &symbol = symbol_pair.second;
166 
167  INVARIANT(symbol.value.id() == ID_symbol, "must have symbol");
168  const irep_idt &id = to_symbol_expr(symbol.value).get_identifier();
169 
170  #if 0
171  if(!base_type_eq(symbol.type, ns.lookup(id).type, ns))
172  {
173  std::cerr << symbol << '\n';
174  std::cerr << ns.lookup(id) << '\n';
175  }
176  INVARIANT(base_type_eq(symbol.type, ns.lookup(id).type, ns),
177  "type matches");
178  #endif
179 
180  macro_application.insert_expr(symbol.name, id);
181  }
182  }
183 
184  if(!macro_application.expr_map.empty())
185  {
186  for(auto &gf_entry : dest_functions.function_map)
187  {
188  irep_idt final_id = gf_entry.first;
189  rename_symbols_in_function(gf_entry.second, final_id, macro_application);
190  }
191  }
192 
193  if(!object_type_updates.empty())
194  {
195  for(auto &gf_entry : dest_functions.function_map)
196  {
197  for(auto &instruction : gf_entry.second.body.instructions)
198  {
199  instruction.transform([&object_type_updates](exprt expr) {
200  object_type_updates(expr);
201  return expr;
202  });
203  }
204  }
205  }
206 }
messaget
Class that provides messages with a built-in verbosity 'level'.
Definition: message.h:154
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
symbol_tablet
The symbol table.
Definition: symbol_table.h:13
linking
bool linking(symbol_tablet &dest_symbol_table, const symbol_tablet &new_symbol_table, message_handlert &message_handler)
Merges the symbol table new_symbol_table into dest_symbol_table, renaming symbols from new_symbol_tab...
Definition: linking.cpp:1475
symbolt::type
typet type
Type of symbol.
Definition: symbol.h:31
rename_symbolt::expr_map
expr_mapt expr_map
Definition: rename_symbol.h:63
replace_symbolt::expr_mapt
std::unordered_map< irep_idt, exprt > expr_mapt
Definition: replace_symbol.h:30
replace_symbolt::get_expr_map
const expr_mapt & get_expr_map() const
Definition: replace_symbol.h:82
goto_model.h
exprt
Base class for all expressions.
Definition: expr.h:55
goto_modelt
Definition: goto_model.h:25
messaget::eom
static eomt eom
Definition: message.h:297
goto_functionst::function_map
function_mapt function_map
Definition: goto_functions.h:29
rename_symbol.h
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
namespacet::lookup
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:138
to_code_type
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:744
symbol_exprt::get_identifier
const irep_idt & get_identifier() const
Definition: std_expr.h:142
linkingt
Definition: linking_class.h:28
to_symbol_expr
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:222
symbol.h
Symbol table entry.
irept::id
const irep_idt & id() const
Definition: irep.h:396
message_handlert
Definition: message.h:27
replace_symbolt::empty
bool empty() const
Definition: replace_symbol.h:59
optionalt
nonstd::optional< T > optionalt
Definition: optional.h:35
goto_functionst::goto_functiont
::goto_functiont goto_functiont
Definition: goto_functions.h:27
goto_functionst
A collection of goto functions.
Definition: goto_functions.h:24
symbolt::value
exprt value
Initial value of symbol.
Definition: symbol.h:34
linking_class.h
goto_modelt::goto_functions
goto_functionst goto_functions
GOTO functions.
Definition: goto_model.h:33
symbolt
Symbol table entry.
Definition: symbol.h:27
symbol_table_baset::symbols
const symbolst & symbols
Read-only field, used to look up symbols given their names.
Definition: symbol_table_base.h:30
rename_symbolt::insert_expr
void insert_expr(const irep_idt &old_id, const irep_idt &new_id)
Definition: rename_symbol.h:31
rename_symbolt
Definition: rename_symbol.h:25
unchecked_replace_symbolt
Definition: replace_symbol.h:102
code_typet::get_inlined
bool get_inlined() const
Definition: std_types.h:665
goto_modelt::symbol_table
symbol_tablet symbol_table
Symbol table.
Definition: goto_model.h:30
symbolt::name
irep_idt name
The unique identifier.
Definition: symbol.h:40
validation_modet::INVARIANT
@ INVARIANT