@@ -42,6 +42,7 @@ Date: June 2006
4242#include < langapi/language_file.h>
4343#include < langapi/mode.h>
4444
45+ #include < linking/linking.h>
4546#include < linking/static_lifetime_init.h>
4647
4748#define DOTGRAPHSETTINGS " color=black;" \
@@ -56,8 +57,6 @@ Date: June 2006
5657// / \return true on error, false otherwise
5758bool compilet::doit ()
5859{
59- goto_model.goto_functions .clear ();
60-
6160 add_compiler_specific_defines ();
6261
6362 // Parse command line for source and object file names
@@ -98,15 +97,15 @@ bool compilet::doit()
9897 const unsigned warnings_before=
9998 get_message_handler ().get_message_count (messaget::M_WARNING);
10099
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 ;
104103
105104 if (mode==LINK_LIBRARY ||
106105 mode==COMPILE_LINK ||
107106 mode==COMPILE_LINK_EXECUTABLE)
108107 {
109- if (link ())
108+ if (link (*symbol_table_opt ))
110109 return true ;
111110 }
112111
@@ -308,11 +307,14 @@ bool compilet::find_library(const std::string &name)
308307
309308// / parses object files and links them
310309// / \return true on error, false otherwise
311- bool compilet::link ()
310+ bool compilet::link (optionalt<symbol_tablet> &&symbol_table )
312311{
313312 // "compile" hitherto uncompiled functions
314313 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);
316318
317319 // parse object files
318320 for (const auto &file_name : object_files)
@@ -343,7 +345,7 @@ bool compilet::link()
343345 return true ;
344346
345347 // entry_point may (should) add some more functions.
346- convert_symbols (goto_model. goto_functions );
348+ convert_symbols (goto_model);
347349 }
348350
349351 if (keep_file_local)
@@ -359,11 +361,13 @@ bool compilet::link()
359361 return add_written_cprover_symbols (goto_model.symbol_table );
360362}
361363
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 ()
366368{
369+ symbol_tablet symbol_table;
370+
367371 while (!source_files.empty ())
368372 {
369373 std::string file_name=source_files.front ();
@@ -374,9 +378,9 @@ bool compilet::compile()
374378 if (echo_file_name)
375379 std::cout << get_base_name (file_name, false ) << ' \n ' << std::flush;
376380
377- bool r= parse_source (file_name); // don't break the program!
381+ auto file_symbol_table = parse_source (file_name);
378382
379- if (r )
383+ if (!file_symbol_table. has_value () )
380384 {
381385 const std::string &debug_outfile=
382386 cmdline.get_value (" print-rejected-preprocessed-source" );
@@ -388,15 +392,17 @@ bool compilet::compile()
388392 warning () << " Failed sources in " << debug_outfile << eom;
389393 }
390394
391- return true ; // parser/typecheck error
395+ return {} ; // parser/typecheck error
392396 }
393397
394398 if (mode==COMPILE_ONLY || mode==ASSEMBLE_ONLY)
395399 {
396400 // output an object file for every source file
397401
398402 // "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);
400406
401407 std::string cfn;
402408
@@ -416,21 +422,26 @@ bool compilet::compile()
416422 if (keep_file_local)
417423 {
418424 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);
420426 mangler.mangle ();
421427 }
422428
423- if (write_bin_object_file (cfn, goto_model ))
424- return true ;
429+ if (write_bin_object_file (cfn, file_goto_model ))
430+ return {} ;
425431
426- if (add_written_cprover_symbols (goto_model.symbol_table ))
427- return true ;
428-
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+ }
430441 }
431442 }
432443
433- return false ;
444+ return std::move (symbol_table) ;
434445}
435446
436447// / parses a source file (low-level parsing)
@@ -556,32 +567,33 @@ bool compilet::parse_stdin(languaget &language)
556567 return false ;
557568}
558569
559- // / Writes the goto functions of \p src_goto_model to a binary format object
560- // / file.
561- // / \param file_name: Target file to serialize \p src_goto_model to
562- // / \param src_goto_model: goto model to serialize
563- // / \return true on error, false otherwise
564570bool compilet::write_bin_object_file (
565571 const std::string &file_name,
566- const goto_modelt &src_goto_model)
572+ const goto_modelt &src_goto_model,
573+ bool validate_goto_model,
574+ message_handlert &message_handler)
567575{
576+ messaget log (message_handler);
577+
568578 if (validate_goto_model)
569579 {
570- status () << " Validating goto model" << eom;
580+ log. status () << " Validating goto model" << messaget:: eom;
571581 src_goto_model.validate ();
572582 }
573583
574- statistics () << " Writing binary format object '" << file_name << " '" << eom;
584+ log.statistics () << " Writing binary format object '" << file_name << " '"
585+ << messaget::eom;
575586
576587 // symbols
577- statistics () << " Symbols in table: "
578- << src_goto_model.symbol_table .symbols .size () << eom;
588+ log.statistics () << " Symbols in table: "
589+ << src_goto_model.symbol_table .symbols .size ()
590+ << messaget::eom;
579591
580592 std::ofstream outfile (file_name, std::ios::binary);
581593
582594 if (!outfile.is_open ())
583595 {
584- error () << " Error opening file '" << file_name << " '" << eom;
596+ log. error () << " Error opening file '" << file_name << " '" << messaget:: eom;
585597 return true ;
586598 }
587599
@@ -590,47 +602,46 @@ bool compilet::write_bin_object_file(
590602
591603 const auto cnt = function_body_count (src_goto_model.goto_functions );
592604
593- statistics () << " Functions: "
594- << src_goto_model.goto_functions .function_map .size () << " ; "
595- << cnt << " have a body." << eom;
605+ log. statistics () << " Functions: "
606+ << src_goto_model.goto_functions .function_map .size () << " ; "
607+ << cnt << " have a body." << messaget:: eom;
596608
597609 outfile.close ();
598- wrote_object=true ;
599610
600611 return false ;
601612}
602613
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)
606617{
607618 language_filest language_files;
608619 language_files.set_message_handler (get_message_handler ());
609620
610621 if (parse (file_name, language_files))
611- return true ;
622+ return {} ;
612623
613624 // 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))
615627 {
616628 error () << " CONVERSION ERROR" << eom;
617- return true ;
629+ return {} ;
618630 }
619631
620- if (language_files.final (goto_model. symbol_table ))
632+ if (language_files.final (file_symbol_table ))
621633 {
622634 error () << " CONVERSION ERROR" << eom;
623- return true ;
635+ return {} ;
624636 }
625637
626- return false ;
638+ return std::move (file_symbol_table) ;
627639}
628640
629641// / constructor
630642// / \return nothing
631643compilet::compilet (cmdlinet &_cmdline, message_handlert &mh, bool Werror)
632644 : messaget(mh),
633- ns(goto_model.symbol_table),
634645 cmdline(_cmdline),
635646 warning_is_fatal(Werror),
636647 keep_file_local(
@@ -661,8 +672,7 @@ compilet::~compilet()
661672 delete_directory (dir);
662673}
663674
664- std::size_t
665- compilet::function_body_count (const goto_functionst &functions) const
675+ std::size_t compilet::function_body_count (const goto_functionst &functions)
666676{
667677 std::size_t count = 0 ;
668678
@@ -679,7 +689,7 @@ void compilet::add_compiler_specific_defines() const
679689 std::string (" __GOTO_CC_VERSION__=" ) + CBMC_VERSION);
680690}
681691
682- void compilet::convert_symbols (goto_functionst &dest )
692+ void compilet::convert_symbols (goto_modelt &goto_model )
683693{
684694 symbol_table_buildert symbol_table_builder =
685695 symbol_table_buildert::wrap (goto_model.symbol_table );
@@ -713,7 +723,8 @@ void compilet::convert_symbols(goto_functionst &dest)
713723 s_it->second .value .is_not_nil ())
714724 {
715725 debug () << " Compiling " << s_it->first << eom;
716- 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 ]);
717728 symbol_table_builder.get_writeable_ref (symbol).set_compiled ();
718729 }
719730 }
0 commit comments