Skip to content

Commit 8c4d15b

Browse files
authored
Merge pull request #2254 from tautschnig/linear-linking
Linking: perform macro expansion and type updates just once
2 parents 303b3aa + ee42ac6 commit 8c4d15b

File tree

10 files changed

+130
-130
lines changed

10 files changed

+130
-130
lines changed

jbmc/src/java_bytecode/lazy_goto_model.cpp

+3-15
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,7 @@ void lazy_goto_modelt::initialize(
126126
"language");
127127
}
128128

129-
std::vector<std::string> binaries, sources;
130-
binaries.reserve(files.size());
131-
sources.reserve(files.size());
129+
std::list<std::string> binaries, sources;
132130

133131
for(const auto &file : files)
134132
{
@@ -211,18 +209,8 @@ void lazy_goto_modelt::initialize(
211209
}
212210
}
213211

214-
for(const std::string &file : binaries)
215-
{
216-
msg.status() << "Reading GOTO program from file" << messaget::eom;
217-
218-
if(read_object_and_link(file, *goto_model, message_handler))
219-
{
220-
source_locationt source_location;
221-
source_location.set_file(file);
222-
throw incorrect_goto_program_exceptiont(
223-
"failed to read/link goto model", source_location);
224-
}
225-
}
212+
if(read_objects_and_link(binaries, *goto_model, message_handler))
213+
throw incorrect_goto_program_exceptiont{"failed to read/link goto model"};
226214

227215
bool binaries_provided_start =
228216
symbol_table.has_symbol(goto_functionst::entry_point());

regression/goto-gcc/archives/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ CORE
33
main.c -L. -lour_archive --verbosity
44
^EXIT=0$
55
^SIGNAL=0$
6-
^Reading: .*/foo.o$
6+
^Reading GOTO program from file .*/foo.o$
77
--
88
^warning: ignoring
99
^CONVERSION ERROR$

src/goto-cc/compile.cpp

+2-5
Original file line numberDiff line numberDiff line change
@@ -322,11 +322,8 @@ bool compilet::link(optionalt<symbol_tablet> &&symbol_table)
322322
convert_symbols(goto_model);
323323

324324
// parse object files
325-
for(const auto &file_name : object_files)
326-
{
327-
if(read_object_and_link(file_name, goto_model, log.get_message_handler()))
328-
return true;
329-
}
325+
if(read_objects_and_link(object_files, goto_model, log.get_message_handler()))
326+
return true;
330327

331328
// produce entry point?
332329

src/goto-programs/initialize_goto_model.cpp

+4-11
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,7 @@ goto_modelt initialize_goto_model(
7171
"one or more paths to program files");
7272
}
7373

74-
std::vector<std::string> binaries, sources;
75-
binaries.reserve(files.size());
76-
sources.reserve(files.size());
74+
std::list<std::string> binaries, sources;
7775

7876
for(const auto &file : files)
7977
{
@@ -135,15 +133,10 @@ goto_modelt initialize_goto_model(
135133
}
136134
}
137135

138-
for(const auto &file : binaries)
136+
if(read_objects_and_link(binaries, goto_model, message_handler))
139137
{
140-
msg.status() << "Reading GOTO program from file" << messaget::eom;
141-
142-
if(read_object_and_link(file, goto_model, message_handler))
143-
{
144-
throw invalid_source_file_exceptiont(
145-
"failed to read object or link in file '" + file + '\'');
146-
}
138+
throw invalid_source_file_exceptiont{
139+
"failed to read object or link in files"};
147140
}
148141

149142
bool binaries_provided_start=

src/goto-programs/link_goto_model.cpp

+53-39
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ Author: Michael Tautschnig, Daniel Kroening
1717
#include <util/rename_symbol.h>
1818

1919
#include <linking/linking_class.h>
20-
#include <util/exception_utils.h>
2120

2221
#include "goto_model.h"
2322

@@ -54,8 +53,7 @@ static bool link_functions(
5453
const symbol_tablet &src_symbol_table,
5554
goto_functionst &src_functions,
5655
const rename_symbolt &rename_symbol,
57-
const std::unordered_set<irep_idt> &weak_symbols,
58-
const replace_symbolt &object_type_updates)
56+
const std::unordered_set<irep_idt> &weak_symbols)
5957
{
6058
namespacet ns(dest_symbol_table);
6159
namespacet src_ns(src_symbol_table);
@@ -109,6 +107,58 @@ static bool link_functions(
109107
}
110108
}
111109

110+
return false;
111+
}
112+
113+
optionalt<replace_symbolt::expr_mapt> link_goto_model(
114+
goto_modelt &dest,
115+
goto_modelt &&src,
116+
message_handlert &message_handler)
117+
{
118+
std::unordered_set<irep_idt> weak_symbols;
119+
120+
for(const auto &symbol_pair : dest.symbol_table.symbols)
121+
{
122+
if(symbol_pair.second.is_weak)
123+
weak_symbols.insert(symbol_pair.first);
124+
}
125+
126+
linkingt linking(dest.symbol_table, src.symbol_table, message_handler);
127+
128+
if(linking.typecheck_main())
129+
{
130+
messaget log{message_handler};
131+
log.error() << "typechecking main failed" << messaget::eom;
132+
return {};
133+
}
134+
135+
if(link_functions(
136+
dest.symbol_table,
137+
dest.goto_functions,
138+
src.symbol_table,
139+
src.goto_functions,
140+
linking.rename_symbol,
141+
weak_symbols))
142+
{
143+
messaget log{message_handler};
144+
log.error() << "linking failed" << messaget::eom;
145+
return {};
146+
}
147+
148+
return linking.object_type_updates.get_expr_map();
149+
}
150+
151+
void finalize_linking(
152+
goto_modelt &dest,
153+
const replace_symbolt::expr_mapt &type_updates)
154+
{
155+
unchecked_replace_symbolt object_type_updates;
156+
object_type_updates.get_expr_map().insert(
157+
type_updates.begin(), type_updates.end());
158+
159+
goto_functionst &dest_functions = dest.goto_functions;
160+
symbol_tablet &dest_symbol_table = dest.symbol_table;
161+
112162
// apply macros
113163
rename_symbolt macro_application;
114164

@@ -157,40 +207,4 @@ static bool link_functions(
157207
}
158208
}
159209
}
160-
161-
return false;
162-
}
163-
164-
void link_goto_model(
165-
goto_modelt &dest,
166-
goto_modelt &src,
167-
message_handlert &message_handler)
168-
{
169-
std::unordered_set<irep_idt> weak_symbols;
170-
171-
for(const auto &symbol_pair : dest.symbol_table.symbols)
172-
{
173-
if(symbol_pair.second.is_weak)
174-
weak_symbols.insert(symbol_pair.first);
175-
}
176-
177-
linkingt linking(dest.symbol_table,
178-
src.symbol_table,
179-
message_handler);
180-
181-
if(linking.typecheck_main())
182-
{
183-
throw invalid_source_file_exceptiont("typechecking main failed");
184-
}
185-
if(link_functions(
186-
dest.symbol_table,
187-
dest.goto_functions,
188-
src.symbol_table,
189-
src.goto_functions,
190-
linking.rename_symbol,
191-
weak_symbols,
192-
linking.object_type_updates))
193-
{
194-
throw invalid_source_file_exceptiont("linking failed");
195-
}
196210
}

src/goto-programs/link_goto_model.h

+15-3
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,24 @@ Author: Daniel Kroening, [email protected]
1212
#ifndef CPROVER_GOTO_PROGRAMS_LINK_GOTO_MODEL_H
1313
#define CPROVER_GOTO_PROGRAMS_LINK_GOTO_MODEL_H
1414

15+
#include <util/nodiscard.h>
16+
#include <util/replace_symbol.h>
17+
1518
class goto_modelt;
1619
class message_handlert;
1720

18-
void link_goto_model(
21+
/// Link goto model \p src into goto model \p dest, invalidating \p src in this
22+
/// process. Linking may require updates to object types contained in \p dest,
23+
/// which need to be applied using \ref finalize_linking.
24+
/// \return nullopt if linking fails, else a (possibly empty) collection of
25+
/// replacements to be applied.
26+
NODISCARD optionalt<replace_symbolt::expr_mapt>
27+
link_goto_model(goto_modelt &dest, goto_modelt &&src, message_handlert &);
28+
29+
/// Apply \p type_updates to \p dest, where \p type_updates were constructed
30+
/// from one or more calls to \p link_goto_model.
31+
void finalize_linking(
1932
goto_modelt &dest,
20-
goto_modelt &src,
21-
message_handlert &);
33+
const replace_symbolt::expr_mapt &type_updates);
2234

2335
#endif // CPROVER_GOTO_PROGRAMS_LINK_GOTO_MODEL_H

src/goto-programs/read_goto_binary.cpp

+26-38
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Module: Read Goto Programs
1515

1616
#include <util/config.h>
1717
#include <util/message.h>
18+
#include <util/replace_symbol.h>
1819
#include <util/tempfile.h>
1920

2021
#ifdef _MSC_VER
@@ -270,59 +271,46 @@ bool is_goto_binary(
270271
/// \param file_name: file name of the goto binary
271272
/// \param dest: the goto model returned
272273
/// \param message_handler: for diagnostics
273-
/// \return true on error, false otherwise
274-
bool read_object_and_link(
274+
/// \return nullopt on error, type replacements to be applied otherwise
275+
static optionalt<replace_symbolt::expr_mapt> read_object_and_link(
275276
const std::string &file_name,
276277
goto_modelt &dest,
277278
message_handlert &message_handler)
278279
{
279-
messaget(message_handler).statistics() << "Reading: "
280-
<< file_name << messaget::eom;
280+
messaget(message_handler).status()
281+
<< "Reading GOTO program from file " << file_name << messaget::eom;
281282

282283
// we read into a temporary model
283284
auto temp_model = read_goto_binary(file_name, message_handler);
284285
if(!temp_model.has_value())
285-
return true;
286-
287-
try
288-
{
289-
link_goto_model(dest, *temp_model, message_handler);
290-
}
291-
catch(...)
292-
{
293-
return true;
294-
}
295-
296-
// reading successful, let's update config
297-
config.set_from_symbol_table(dest.symbol_table);
286+
return {};
298287

299-
return false;
288+
return link_goto_model(dest, std::move(*temp_model), message_handler);
300289
}
301290

302-
/// \brief reads an object file, and also updates the config
303-
/// \param file_name: file name of the goto binary
304-
/// \param dest_symbol_table: symbol table to update
305-
/// \param dest_functions: collection of goto functions to update
306-
/// \param message_handler: for diagnostics
307-
/// \return true on error, false otherwise
308-
bool read_object_and_link(
309-
const std::string &file_name,
310-
symbol_tablet &dest_symbol_table,
311-
goto_functionst &dest_functions,
291+
bool read_objects_and_link(
292+
const std::list<std::string> &file_names,
293+
goto_modelt &dest,
312294
message_handlert &message_handler)
313295
{
314-
goto_modelt goto_model;
296+
if(file_names.empty())
297+
return false;
298+
299+
replace_symbolt::expr_mapt object_type_updates;
315300

316-
goto_model.symbol_table.swap(dest_symbol_table);
317-
goto_model.goto_functions.swap(dest_functions);
301+
for(const auto &file_name : file_names)
302+
{
303+
auto updates_opt = read_object_and_link(file_name, dest, message_handler);
304+
if(!updates_opt.has_value())
305+
return true;
306+
307+
object_type_updates.insert(updates_opt->begin(), updates_opt->end());
308+
}
318309

319-
bool result=read_object_and_link(
320-
file_name,
321-
goto_model,
322-
message_handler);
310+
finalize_linking(dest, object_type_updates);
323311

324-
goto_model.symbol_table.swap(dest_symbol_table);
325-
goto_model.goto_functions.swap(dest_functions);
312+
// reading successful, let's update config
313+
config.set_from_symbol_table(dest.symbol_table);
326314

327-
return result;
315+
return false;
328316
}

src/goto-programs/read_goto_binary.h

+10-12
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,27 @@ Author: Daniel Kroening, [email protected]
1212
#ifndef CPROVER_GOTO_PROGRAMS_READ_GOTO_BINARY_H
1313
#define CPROVER_GOTO_PROGRAMS_READ_GOTO_BINARY_H
1414

15+
#include <list>
1516
#include <string>
1617

1718
#include <util/optional.h>
1819

19-
class goto_functionst;
2020
class goto_modelt;
2121
class message_handlert;
22-
class symbol_tablet;
2322

2423
optionalt<goto_modelt>
2524
read_goto_binary(const std::string &filename, message_handlert &);
2625

2726
bool is_goto_binary(const std::string &filename, message_handlert &);
2827

29-
bool read_object_and_link(
30-
const std::string &file_name,
31-
symbol_tablet &,
32-
goto_functionst &,
33-
message_handlert &);
34-
35-
bool read_object_and_link(
36-
const std::string &file_name,
37-
goto_modelt &,
38-
message_handlert &);
28+
/// Reads object files and updates the config if any files were read.
29+
/// \param file_names: file names of goto binaries; if empty, just returns false
30+
/// \param dest: goto model to update
31+
/// \param message_handler: for diagnostics
32+
/// \return True on error, false otherwise
33+
bool read_objects_and_link(
34+
const std::list<std::string> &file_names,
35+
goto_modelt &dest,
36+
message_handlert &message_handler);
3937

4038
#endif // CPROVER_GOTO_PROGRAMS_READ_GOTO_BINARY_H

src/symtab2gb/module_dependencies.txt

+1
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ json-symtab-language
33
langapi
44
goto-programs
55
ansi-c
6+
linking

0 commit comments

Comments
 (0)