|
| 1 | +/*******************************************************************\ |
| 2 | +
|
| 3 | +Module: Link Goto Programs |
| 4 | +
|
| 5 | +Author: Michael Tautschnig, Daniel Kroening |
| 6 | +
|
| 7 | +\*******************************************************************/ |
| 8 | + |
| 9 | +/// \file |
| 10 | +/// Link Goto Programs |
| 11 | + |
| 12 | +#include "link_goto_model.h" |
| 13 | + |
| 14 | +#include <unordered_set> |
| 15 | + |
| 16 | +#include <util/base_type.h> |
| 17 | +#include <util/symbol.h> |
| 18 | +#include <util/rename_symbol.h> |
| 19 | + |
| 20 | +#include <linking/linking_class.h> |
| 21 | + |
| 22 | +#include "goto_model.h" |
| 23 | + |
| 24 | +static void rename_symbols_in_function( |
| 25 | + goto_functionst::goto_functiont &function, |
| 26 | + const rename_symbolt &rename_symbol) |
| 27 | +{ |
| 28 | + goto_programt &program=function.body; |
| 29 | + rename_symbol(function.type); |
| 30 | + |
| 31 | + Forall_goto_program_instructions(iit, program) |
| 32 | + { |
| 33 | + rename_symbol(iit->code); |
| 34 | + rename_symbol(iit->guard); |
| 35 | + } |
| 36 | +} |
| 37 | + |
| 38 | +/// Link a set of goto functions, considering weak symbols |
| 39 | +/// and symbol renaming |
| 40 | +static bool link_functions( |
| 41 | + symbol_tablet &dest_symbol_table, |
| 42 | + goto_functionst &dest_functions, |
| 43 | + const symbol_tablet &src_symbol_table, |
| 44 | + goto_functionst &src_functions, |
| 45 | + const rename_symbolt &rename_symbol, |
| 46 | + const std::unordered_set<irep_idt, irep_id_hash> &weak_symbols, |
| 47 | + const replace_symbolt &object_type_updates) |
| 48 | +{ |
| 49 | + namespacet ns(dest_symbol_table); |
| 50 | + namespacet src_ns(src_symbol_table); |
| 51 | + |
| 52 | + // merge functions |
| 53 | + Forall_goto_functions(src_it, src_functions) |
| 54 | + { |
| 55 | + // the function might have been renamed |
| 56 | + rename_symbolt::expr_mapt::const_iterator e_it= |
| 57 | + rename_symbol.expr_map.find(src_it->first); |
| 58 | + |
| 59 | + irep_idt final_id=src_it->first; |
| 60 | + |
| 61 | + if(e_it!=rename_symbol.expr_map.end()) |
| 62 | + final_id=e_it->second; |
| 63 | + |
| 64 | + // already there? |
| 65 | + goto_functionst::function_mapt::iterator dest_f_it= |
| 66 | + dest_functions.function_map.find(final_id); |
| 67 | + |
| 68 | + if(dest_f_it==dest_functions.function_map.end()) // not there yet |
| 69 | + { |
| 70 | + rename_symbols_in_function(src_it->second, rename_symbol); |
| 71 | + |
| 72 | + goto_functionst::goto_functiont &in_dest_symbol_table= |
| 73 | + dest_functions.function_map[final_id]; |
| 74 | + |
| 75 | + in_dest_symbol_table.body.swap(src_it->second.body); |
| 76 | + in_dest_symbol_table.type=src_it->second.type; |
| 77 | + } |
| 78 | + else // collision! |
| 79 | + { |
| 80 | + goto_functionst::goto_functiont &in_dest_symbol_table= |
| 81 | + dest_functions.function_map[final_id]; |
| 82 | + |
| 83 | + goto_functionst::goto_functiont &src_func=src_it->second; |
| 84 | + |
| 85 | + if(in_dest_symbol_table.body.instructions.empty() || |
| 86 | + weak_symbols.find(final_id)!=weak_symbols.end()) |
| 87 | + { |
| 88 | + // the one with body wins! |
| 89 | + rename_symbols_in_function(src_func, rename_symbol); |
| 90 | + |
| 91 | + in_dest_symbol_table.body.swap(src_func.body); |
| 92 | + in_dest_symbol_table.type=src_func.type; |
| 93 | + } |
| 94 | + else if(src_func.body.instructions.empty() || |
| 95 | + src_ns.lookup(src_it->first).is_weak) |
| 96 | + { |
| 97 | + // just keep the old one in dest |
| 98 | + } |
| 99 | + else if(in_dest_symbol_table.type.get_bool(ID_C_inlined)) |
| 100 | + { |
| 101 | + // ok, we silently ignore |
| 102 | + } |
| 103 | + else |
| 104 | + { |
| 105 | + // the linking code will have ensured that types match |
| 106 | + rename_symbol(src_func.type); |
| 107 | + INVARIANT(base_type_eq(in_dest_symbol_table.type, src_func.type, ns), |
| 108 | + "linking ensures that types match"); |
| 109 | + } |
| 110 | + } |
| 111 | + } |
| 112 | + |
| 113 | + // apply macros |
| 114 | + rename_symbolt macro_application; |
| 115 | + |
| 116 | + forall_symbols(it, dest_symbol_table.symbols) |
| 117 | + if(it->second.is_macro && !it->second.is_type) |
| 118 | + { |
| 119 | + const symbolt &symbol=it->second; |
| 120 | + |
| 121 | + INVARIANT(symbol.value.id()==ID_symbol, "must have symbol"); |
| 122 | + const irep_idt &id=to_symbol_expr(symbol.value).get_identifier(); |
| 123 | + |
| 124 | + #if 0 |
| 125 | + if(!base_type_eq(symbol.type, ns.lookup(id).type, ns)) |
| 126 | + { |
| 127 | + std::cerr << symbol << '\n'; |
| 128 | + std::cerr << ns.lookup(id) << '\n'; |
| 129 | + } |
| 130 | + INVARIANT(base_type_eq(symbol.type, ns.lookup(id).type, ns), |
| 131 | + "type matches"); |
| 132 | + #endif |
| 133 | + |
| 134 | + macro_application.insert_expr(symbol.name, id); |
| 135 | + } |
| 136 | + |
| 137 | + if(!macro_application.expr_map.empty()) |
| 138 | + Forall_goto_functions(dest_it, dest_functions) |
| 139 | + rename_symbols_in_function(dest_it->second, macro_application); |
| 140 | + |
| 141 | + if(!object_type_updates.expr_map.empty()) |
| 142 | + { |
| 143 | + Forall_goto_functions(dest_it, dest_functions) |
| 144 | + Forall_goto_program_instructions(iit, dest_it->second.body) |
| 145 | + { |
| 146 | + object_type_updates(iit->code); |
| 147 | + object_type_updates(iit->guard); |
| 148 | + } |
| 149 | + } |
| 150 | + |
| 151 | + return false; |
| 152 | +} |
| 153 | + |
| 154 | +void link_goto_model( |
| 155 | + goto_modelt &dest, |
| 156 | + goto_modelt &src, |
| 157 | + message_handlert &message_handler) |
| 158 | +{ |
| 159 | + typedef std::unordered_set<irep_idt, irep_id_hash> id_sett; |
| 160 | + id_sett weak_symbols; |
| 161 | + |
| 162 | + forall_symbols(it, dest.symbol_table.symbols) |
| 163 | + if(it->second.is_weak) |
| 164 | + weak_symbols.insert(it->first); |
| 165 | + |
| 166 | + linkingt linking(dest.symbol_table, |
| 167 | + src.symbol_table, |
| 168 | + message_handler); |
| 169 | + |
| 170 | + if(linking.typecheck_main()) |
| 171 | + throw 0; |
| 172 | + |
| 173 | + if(link_functions( |
| 174 | + dest.symbol_table, |
| 175 | + dest.goto_functions, |
| 176 | + src.symbol_table, |
| 177 | + src.goto_functions, |
| 178 | + linking.rename_symbol, |
| 179 | + weak_symbols, |
| 180 | + linking.object_type_updates)) |
| 181 | + throw 0; |
| 182 | +} |
0 commit comments