@@ -42,6 +42,7 @@ Date: June 2006
42
42
#include < langapi/language_file.h>
43
43
#include < langapi/mode.h>
44
44
45
+ #include < linking/linking.h>
45
46
#include < linking/static_lifetime_init.h>
46
47
47
48
#define DOTGRAPHSETTINGS " color=black;" \
@@ -56,8 +57,6 @@ Date: June 2006
56
57
// / \return true on error, false otherwise
57
58
bool compilet::doit ()
58
59
{
59
- goto_model.goto_functions .clear ();
60
-
61
60
add_compiler_specific_defines ();
62
61
63
62
// Parse command line for source and object file names
@@ -98,15 +97,15 @@ bool compilet::doit()
98
97
const unsigned warnings_before=
99
98
get_message_handler ().get_message_count (messaget::M_WARNING);
100
99
101
- if (!source_files. empty ())
102
- if (compile ())
103
- return true ;
100
+ auto symbol_table_opt = compile ();
101
+ if (!symbol_table_opt. has_value ())
102
+ return true ;
104
103
105
104
if (mode==LINK_LIBRARY ||
106
105
mode==COMPILE_LINK ||
107
106
mode==COMPILE_LINK_EXECUTABLE)
108
107
{
109
- if (link ())
108
+ if (link (*symbol_table_opt ))
110
109
return true ;
111
110
}
112
111
@@ -308,11 +307,14 @@ bool compilet::find_library(const std::string &name)
308
307
309
308
// / parses object files and links them
310
309
// / \return true on error, false otherwise
311
- bool compilet::link ()
310
+ bool compilet::link (optionalt<symbol_tablet> &&symbol_table )
312
311
{
313
312
// "compile" hitherto uncompiled functions
314
313
statistics () << " Compiling functions" << eom;
315
- convert_symbols (goto_model.goto_functions );
314
+ goto_modelt goto_model;
315
+ if (symbol_table.has_value ())
316
+ goto_model.symbol_table = std::move (*symbol_table);
317
+ convert_symbols (goto_model);
316
318
317
319
// parse object files
318
320
for (const auto &file_name : object_files)
@@ -343,7 +345,7 @@ bool compilet::link()
343
345
return true ;
344
346
345
347
// entry_point may (should) add some more functions.
346
- convert_symbols (goto_model. goto_functions );
348
+ convert_symbols (goto_model);
347
349
}
348
350
349
351
if (keep_file_local)
@@ -359,11 +361,13 @@ bool compilet::link()
359
361
return add_written_cprover_symbols (goto_model.symbol_table );
360
362
}
361
363
362
- // / parses source files and writes object files, or keeps the symbols in the
363
- // / symbol_table depending on the doLink flag .
364
- // / \return true on error, false otherwise
365
- bool compilet::compile ()
364
+ // / Parses source files and writes object files, or keeps the symbols in the
365
+ // / symbol_table if not compiling/assembling only .
366
+ // / \return Symbol table, if parsing and type checking succeeded, else empty
367
+ optionalt<symbol_tablet> compilet::compile ()
366
368
{
369
+ symbol_tablet symbol_table;
370
+
367
371
while (!source_files.empty ())
368
372
{
369
373
std::string file_name=source_files.front ();
@@ -374,9 +378,9 @@ bool compilet::compile()
374
378
if (echo_file_name)
375
379
std::cout << get_base_name (file_name, false ) << ' \n ' << std::flush;
376
380
377
- bool r= parse_source (file_name); // don't break the program!
381
+ auto file_symbol_table = parse_source (file_name);
378
382
379
- if (r )
383
+ if (!file_symbol_table. has_value () )
380
384
{
381
385
const std::string &debug_outfile=
382
386
cmdline.get_value (" print-rejected-preprocessed-source" );
@@ -388,15 +392,17 @@ bool compilet::compile()
388
392
warning () << " Failed sources in " << debug_outfile << eom;
389
393
}
390
394
391
- return true ; // parser/typecheck error
395
+ return {} ; // parser/typecheck error
392
396
}
393
397
394
398
if (mode==COMPILE_ONLY || mode==ASSEMBLE_ONLY)
395
399
{
396
400
// output an object file for every source file
397
401
398
402
// "compile" functions
399
- convert_symbols (goto_model.goto_functions );
403
+ goto_modelt file_goto_model;
404
+ file_goto_model.symbol_table = std::move (*file_symbol_table);
405
+ convert_symbols (file_goto_model);
400
406
401
407
std::string cfn;
402
408
@@ -416,21 +422,26 @@ bool compilet::compile()
416
422
if (keep_file_local)
417
423
{
418
424
function_name_manglert<file_name_manglert> mangler (
419
- get_message_handler (), goto_model , file_local_mangle_suffix);
425
+ get_message_handler (), file_goto_model , file_local_mangle_suffix);
420
426
mangler.mangle ();
421
427
}
422
428
423
- if (write_bin_object_file (cfn, goto_model))
424
- return true ;
425
-
426
- if (add_written_cprover_symbols (goto_model.symbol_table ))
427
- return true ;
429
+ if (write_bin_object_file (cfn, file_goto_model))
430
+ return {};
428
431
429
- goto_model.clear (); // clean symbol table for next source file.
432
+ if (add_written_cprover_symbols (file_goto_model.symbol_table ))
433
+ return {};
434
+ }
435
+ else
436
+ {
437
+ if (linking (symbol_table, *file_symbol_table, get_message_handler ()))
438
+ {
439
+ return {};
440
+ }
430
441
}
431
442
}
432
443
433
- return false ;
444
+ return std::move (symbol_table) ;
434
445
}
435
446
436
447
// / parses a source file (low-level parsing)
@@ -600,37 +611,37 @@ bool compilet::write_bin_object_file(
600
611
return false ;
601
612
}
602
613
603
- // / parses a source file
604
- // / \return true on error, false otherwise
605
- bool compilet::parse_source (const std::string &file_name)
614
+ // / Parses and type checks a source file located at \p file_name.
615
+ // / \return A symbol table if, and only if, parsing and type checking succeeded.
616
+ optionalt<symbol_tablet> compilet::parse_source (const std::string &file_name)
606
617
{
607
618
language_filest language_files;
608
619
language_files.set_message_handler (get_message_handler ());
609
620
610
621
if (parse (file_name, language_files))
611
- return true ;
622
+ return {} ;
612
623
613
624
// we just typecheck one file here
614
- if (language_files.typecheck (goto_model.symbol_table , keep_file_local))
625
+ symbol_tablet file_symbol_table;
626
+ if (language_files.typecheck (file_symbol_table, keep_file_local))
615
627
{
616
628
error () << " CONVERSION ERROR" << eom;
617
- return true ;
629
+ return {} ;
618
630
}
619
631
620
- if (language_files.final (goto_model. symbol_table ))
632
+ if (language_files.final (file_symbol_table ))
621
633
{
622
634
error () << " CONVERSION ERROR" << eom;
623
- return true ;
635
+ return {} ;
624
636
}
625
637
626
- return false ;
638
+ return std::move (file_symbol_table) ;
627
639
}
628
640
629
641
// / constructor
630
642
// / \return nothing
631
643
compilet::compilet (cmdlinet &_cmdline, message_handlert &mh, bool Werror)
632
644
: messaget(mh),
633
- ns(goto_model.symbol_table),
634
645
cmdline(_cmdline),
635
646
warning_is_fatal(Werror),
636
647
keep_file_local(
@@ -678,7 +689,7 @@ void compilet::add_compiler_specific_defines() const
678
689
std::string (" __GOTO_CC_VERSION__=" ) + CBMC_VERSION);
679
690
}
680
691
681
- void compilet::convert_symbols (goto_functionst &dest )
692
+ void compilet::convert_symbols (goto_modelt &goto_model )
682
693
{
683
694
symbol_table_buildert symbol_table_builder =
684
695
symbol_table_buildert::wrap (goto_model.symbol_table );
@@ -712,7 +723,8 @@ void compilet::convert_symbols(goto_functionst &dest)
712
723
s_it->second .value .is_not_nil ())
713
724
{
714
725
debug () << " Compiling " << s_it->first << eom;
715
- converter.convert_function (s_it->first , dest.function_map [s_it->first ]);
726
+ converter.convert_function (
727
+ s_it->first , goto_model.goto_functions .function_map [s_it->first ]);
716
728
symbol_table_builder.get_writeable_ref (symbol).set_compiled ();
717
729
}
718
730
}
0 commit comments