Skip to content

Commit 68a96a9

Browse files
committed
Linking: perform macro expansion and type updates just once
This reduces the Linux kernel link time by more than 90% as the previous approach would repeatedly attempt renamings and replacements across all hitherto read goto program instructions.
1 parent d49d053 commit 68a96a9

File tree

3 files changed

+65
-43
lines changed

3 files changed

+65
-43
lines changed

src/goto-programs/link_goto_model.cpp

+46-38
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ static bool link_functions(
5858
const symbol_tablet &src_symbol_table,
5959
goto_functionst &src_functions,
6060
const rename_symbolt &rename_symbol,
61-
const std::unordered_set<irep_idt> &weak_symbols,
62-
const replace_symbolt &object_type_updates)
61+
const std::unordered_set<irep_idt> &weak_symbols)
6362
{
6463
namespacet ns(dest_symbol_table);
6564
namespacet src_ns(src_symbol_table);
@@ -120,6 +119,51 @@ static bool link_functions(
120119
}
121120
}
122121

122+
return false;
123+
}
124+
125+
void link_goto_model(
126+
goto_modelt &dest,
127+
goto_modelt &src,
128+
replace_symbolt &object_type_updates,
129+
message_handlert &message_handler)
130+
{
131+
std::unordered_set<irep_idt> weak_symbols;
132+
133+
for(const auto &symbol_pair : dest.symbol_table.symbols)
134+
{
135+
if(symbol_pair.second.is_weak)
136+
weak_symbols.insert(symbol_pair.first);
137+
}
138+
139+
linkingt linking(dest.symbol_table, src.symbol_table, message_handler);
140+
141+
if(linking.typecheck_main())
142+
throw invalid_source_file_exceptiont("typechecking main failed");
143+
144+
if(link_functions(
145+
dest.symbol_table,
146+
dest.goto_functions,
147+
src.symbol_table,
148+
src.goto_functions,
149+
linking.rename_symbol,
150+
weak_symbols))
151+
{
152+
throw invalid_source_file_exceptiont("linking failed");
153+
}
154+
155+
object_type_updates.get_expr_map().insert(
156+
linking.object_type_updates.get_expr_map().begin(),
157+
linking.object_type_updates.get_expr_map().end());
158+
}
159+
160+
void finalize_linking(
161+
goto_modelt &dest,
162+
const replace_symbolt &object_type_updates)
163+
{
164+
goto_functionst &dest_functions = dest.goto_functions;
165+
symbol_tablet &dest_symbol_table = dest.symbol_table;
166+
123167
// apply macros
124168
rename_symbolt macro_application;
125169

@@ -164,40 +208,4 @@ static bool link_functions(
164208
});
165209
}
166210
}
167-
168-
return false;
169-
}
170-
171-
void link_goto_model(
172-
goto_modelt &dest,
173-
goto_modelt &src,
174-
message_handlert &message_handler)
175-
{
176-
std::unordered_set<irep_idt> weak_symbols;
177-
178-
for(const auto &symbol_pair : dest.symbol_table.symbols)
179-
{
180-
if(symbol_pair.second.is_weak)
181-
weak_symbols.insert(symbol_pair.first);
182-
}
183-
184-
linkingt linking(dest.symbol_table,
185-
src.symbol_table,
186-
message_handler);
187-
188-
if(linking.typecheck_main())
189-
{
190-
throw invalid_source_file_exceptiont("typechecking main failed");
191-
}
192-
if(link_functions(
193-
dest.symbol_table,
194-
dest.goto_functions,
195-
src.symbol_table,
196-
src.goto_functions,
197-
linking.rename_symbol,
198-
weak_symbols,
199-
linking.object_type_updates))
200-
{
201-
throw invalid_source_file_exceptiont("linking failed");
202-
}
203211
}

src/goto-programs/link_goto_model.h

+6
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,16 @@ Author: Daniel Kroening, [email protected]
1414

1515
class goto_modelt;
1616
class message_handlert;
17+
class replace_symbolt;
1718

1819
void link_goto_model(
1920
goto_modelt &dest,
2021
goto_modelt &src,
22+
replace_symbolt &object_type_updates,
2123
message_handlert &);
2224

25+
void finalize_linking(
26+
goto_modelt &dest,
27+
const replace_symbolt &object_type_updates);
28+
2329
#endif // CPROVER_GOTO_PROGRAMS_LINK_GOTO_MODEL_H

src/goto-programs/read_goto_binary.cpp

+13-5
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ Module: Read Goto Programs
1414
#include <fstream>
1515
#include <unordered_set>
1616

17+
#include <util/config.h>
1718
#include <util/message.h>
18-
#include <util/unicode.h>
19-
#include <util/tempfile.h>
2019
#include <util/rename_symbol.h>
21-
#include <util/config.h>
20+
#include <util/replace_symbol.h>
21+
#include <util/tempfile.h>
22+
#include <util/unicode.h>
2223

2324
#include "goto_model.h"
2425
#include "link_goto_model.h"
@@ -265,11 +266,13 @@ bool is_goto_binary(
265266
/// \brief reads an object file, and also updates config
266267
/// \param file_name: file name of the goto binary
267268
/// \param dest: the goto model returned
269+
/// \param [out] object_type_updates: collects type replacements to be applied
268270
/// \param message_handler: for diagnostics
269271
/// \return true on error, false otherwise
270272
static bool read_object_and_link(
271273
const std::string &file_name,
272274
goto_modelt &dest,
275+
replace_symbolt &object_type_updates,
273276
message_handlert &message_handler)
274277
{
275278
messaget(message_handler).status()
@@ -282,7 +285,7 @@ static bool read_object_and_link(
282285

283286
try
284287
{
285-
link_goto_model(dest, *temp_model, message_handler);
288+
link_goto_model(dest, *temp_model, object_type_updates, message_handler);
286289
}
287290
catch(...)
288291
{
@@ -300,14 +303,19 @@ bool read_objects_and_link(
300303
if(file_names.empty())
301304
return false;
302305

306+
replace_symbolt object_type_updates;
307+
303308
for(const auto &file_name : file_names)
304309
{
305-
const bool failed = read_object_and_link(file_name, dest, message_handler);
310+
const bool failed = read_object_and_link(
311+
file_name, dest, object_type_updates, message_handler);
306312

307313
if(failed)
308314
return true;
309315
}
310316

317+
finalize_linking(dest, object_type_updates);
318+
311319
// reading successful, let's update config
312320
config.set_from_symbol_table(dest.symbol_table);
313321

0 commit comments

Comments
 (0)