CBMC
Loading...
Searching...
No Matches
link_goto_model.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Link Goto Programs
4
5Author: Michael Tautschnig, Daniel Kroening
6
7\*******************************************************************/
8
11
12#include "link_goto_model.h"
14
15#include <util/message.h>
16#include <util/rename_symbol.h>
17#include <util/symbol.h>
18
19#include "goto_model.h"
20
21#include <unordered_set>
22
26{
27 for(auto &identifier : function.parameter_identifiers)
28 {
29 auto entry = rename_symbol.expr_map.find(identifier);
30 if(entry != rename_symbol.expr_map.end())
31 identifier = entry->second;
32 }
33
34 for(auto &instruction : function.body.instructions)
35 {
36 rename_symbol(instruction.code_nonconst());
37
38 if(instruction.has_condition())
39 rename_symbol(instruction.condition_nonconst());
40 }
41}
42
45static bool link_functions(
52 const std::unordered_set<irep_idt> &weak_symbols)
53{
56
57 // rename existing functions if linking requires us to do so
58 for(const auto &rename_entry : rename_dest_symbol.expr_map)
59 {
60 auto fn_candidate = dest_functions.function_map.find(rename_entry.first);
61 if(fn_candidate == dest_functions.function_map.end())
62 continue;
63
64 dest_functions.function_map.insert(
65 {rename_entry.second, std::move(fn_candidate->second)});
66 dest_functions.function_map.erase(fn_candidate);
67 }
68
69 // rename symbols in existing functions
70 for(auto &dest_entry : dest_functions.function_map)
72
73 // merge functions
74 for(auto &gf_entry : src_functions.function_map)
75 {
76 // the function might have been renamed
77 rename_symbolt::expr_mapt::const_iterator e_it =
78 rename_src_symbol.expr_map.find(gf_entry.first);
79
81
82 if(e_it != rename_src_symbol.expr_map.end())
83 final_id=e_it->second;
84
85 // already there?
86 goto_functionst::function_mapt::iterator dest_f_it=
87 dest_functions.function_map.find(final_id);
88
90 if(dest_f_it==dest_functions.function_map.end()) // not there yet
91 {
93 dest_functions.function_map.emplace(final_id, std::move(src_func));
94 }
95 else // collision!
96 {
98
99 if(in_dest_symbol_table.body.instructions.empty() ||
101 {
102 // the one with body wins!
104
105 in_dest_symbol_table.body.swap(src_func.body);
106 in_dest_symbol_table.parameter_identifiers.swap(
107 src_func.parameter_identifiers);
108 }
109 else if(
110 src_func.body.instructions.empty() ||
111 src_ns.lookup(gf_entry.first).is_weak)
112 {
113 // just keep the old one in dest
114 }
115 else if(to_code_type(ns.lookup(final_id).type).get_inlined())
116 {
117 // ok, we silently ignore
118 }
119 }
120 }
121
122 return false;
123}
124
125std::optional<replace_symbolt::expr_mapt> link_goto_model(
126 goto_modelt &dest,
127 goto_modelt &&src,
128 message_handlert &message_handler)
129{
130 std::unordered_set<irep_idt> weak_symbols;
131
132 for(const auto &symbol_pair : dest.symbol_table.symbols)
133 {
134 if(symbol_pair.second.is_weak)
135 weak_symbols.insert(symbol_pair.first);
136 }
137
138 linkingt linking(dest.symbol_table, message_handler);
139
140 if(linking.link(src.symbol_table))
141 {
142 messaget log{message_handler};
143 log.error() << "typechecking main failed" << messaget::eom;
144 return {};
145 }
146
148 dest.symbol_table,
149 dest.goto_functions,
150 src.symbol_table,
151 src.goto_functions,
152 linking.rename_main_symbol,
153 linking.rename_new_symbol,
155 {
156 messaget log{message_handler};
157 log.error() << "linking failed" << messaget::eom;
158 return {};
159 }
160
161 return linking.object_type_updates.get_expr_map();
162}
163
165 goto_modelt &dest,
167{
168 casting_replace_symbolt object_type_updates;
169 object_type_updates.get_expr_map().insert(
170 type_updates.begin(), type_updates.end());
171
174
175 // apply macros
177
178 for(const auto &symbol_pair : dest_symbol_table.symbols)
179 {
180 if(symbol_pair.second.is_macro && !symbol_pair.second.is_type)
181 {
182 const symbolt &symbol = symbol_pair.second;
183
184 INVARIANT(symbol.value.id() == ID_symbol, "must have symbol");
185 const irep_idt &id = to_symbol_expr(symbol.value).get_identifier();
186
187 #if 0
188 if(!base_type_eq(symbol.type, ns.lookup(id).type, ns))
189 {
190 std::cerr << symbol << '\n';
191 std::cerr << ns.lookup(id) << '\n';
192 }
193 INVARIANT(base_type_eq(symbol.type, ns.lookup(id).type, ns),
194 "type matches");
195 #endif
196
197 macro_application.insert_expr(symbol.name, id);
198 }
199 }
200
201 if(!macro_application.expr_map.empty())
202 {
203 for(auto &gf_entry : dest_functions.function_map)
205 }
206
207 if(!object_type_updates.empty())
208 {
209 for(auto &gf_entry : dest_functions.function_map)
210 {
211 for(auto &instruction : gf_entry.second.body.instructions)
212 {
213 if(instruction.is_function_call())
214 {
215 const bool changed =
216 !object_type_updates.replace(instruction.call_function());
217 if(changed && instruction.call_lhs().is_not_nil())
218 {
219 object_type_updates(instruction.call_lhs());
220 if(
221 instruction.call_lhs().type() !=
222 to_code_type(instruction.call_function().type()).return_type())
223 {
224 instruction.call_lhs() = typecast_exprt{
225 instruction.call_lhs(),
226 to_code_type(instruction.call_function().type()).return_type()};
227 }
228 }
229 }
230 else
231 {
232 instruction.transform([&object_type_updates](exprt expr) {
233 const bool changed = !object_type_updates.replace(expr);
234 return changed ? std::optional<exprt>{expr} : std::nullopt;
235 });
236 }
237 }
238 }
239 }
240}
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
A variant of replace_symbolt that does not require types to match, but instead inserts type casts as ...
bool replace(exprt &dest) const override
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
Base class for all expressions.
Definition expr.h:56
A collection of goto functions.
::goto_functiont goto_functiont
symbol_tablet symbol_table
Symbol table.
Definition goto_model.h:31
goto_functionst goto_functions
GOTO functions.
Definition goto_model.h:34
const irep_idt & id() const
Definition irep.h:388
Class that provides messages with a built-in verbosity 'level'.
Definition message.h:154
static eomt eom
Definition message.h:289
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
bool empty() const
const expr_mapt & get_expr_map() const
std::unordered_map< irep_idt, exprt > expr_mapt
const symbolst & symbols
Read-only field, used to look up symbols given their names.
The symbol table.
Symbol table entry.
Definition symbol.h:28
typet type
Type of symbol.
Definition symbol.h:31
irep_idt name
The unique identifier.
Definition symbol.h:40
exprt value
Initial value of symbol.
Definition symbol.h:34
Semantic type conversion.
Definition std_expr.h:2073
Symbol Table + CFG.
bool linking(symbol_table_baset &dest_symbol_table, const symbol_table_baset &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:1130
ANSI-C Linking.
double log(double x)
Definition math.c:2449
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:272
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:788
Symbol table entry.