@@ -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 (write_bin_object_file (output_file_executable, goto_model))
@@ -352,11 +354,13 @@ bool compilet::link()
352
354
return add_written_cprover_symbols (goto_model.symbol_table );
353
355
}
354
356
355
- // / parses source files and writes object files, or keeps the symbols in the
356
- // / symbol_table depending on the doLink flag .
357
- // / \return true on error, false otherwise
358
- bool compilet::compile ()
357
+ // / Parses source files and writes object files, or keeps the symbols in the
358
+ // / symbol_table if not compiling/assembling only .
359
+ // / \return Symbol table, if parsing and type checking succeeded, else empty
360
+ optionalt<symbol_tablet> compilet::compile ()
359
361
{
362
+ symbol_tablet symbol_table;
363
+
360
364
while (!source_files.empty ())
361
365
{
362
366
std::string file_name=source_files.front ();
@@ -367,9 +371,9 @@ bool compilet::compile()
367
371
if (echo_file_name)
368
372
std::cout << get_base_name (file_name, false ) << ' \n ' << std::flush;
369
373
370
- bool r= parse_source (file_name); // don't break the program!
374
+ auto file_symbol_table = parse_source (file_name);
371
375
372
- if (r )
376
+ if (!file_symbol_table. has_value () )
373
377
{
374
378
const std::string &debug_outfile=
375
379
cmdline.get_value (" print-rejected-preprocessed-source" );
@@ -381,15 +385,17 @@ bool compilet::compile()
381
385
warning () << " Failed sources in " << debug_outfile << eom;
382
386
}
383
387
384
- return true ; // parser/typecheck error
388
+ return {} ; // parser/typecheck error
385
389
}
386
390
387
391
if (mode==COMPILE_ONLY || mode==ASSEMBLE_ONLY)
388
392
{
389
393
// output an object file for every source file
390
394
391
395
// "compile" functions
392
- convert_symbols (goto_model.goto_functions );
396
+ goto_modelt file_goto_model;
397
+ file_goto_model.symbol_table = std::move (*file_symbol_table);
398
+ convert_symbols (file_goto_model);
393
399
394
400
std::string cfn;
395
401
@@ -409,21 +415,26 @@ bool compilet::compile()
409
415
if (keep_file_local)
410
416
{
411
417
function_name_manglert<file_name_manglert> mangler (
412
- get_message_handler (), goto_model , file_local_mangle_suffix);
418
+ get_message_handler (), file_goto_model , file_local_mangle_suffix);
413
419
mangler.mangle ();
414
420
}
415
421
416
- if (write_bin_object_file (cfn, goto_model))
417
- return true ;
418
-
419
- if (add_written_cprover_symbols (goto_model.symbol_table ))
420
- return true ;
422
+ if (write_bin_object_file (cfn, file_goto_model))
423
+ return {};
421
424
422
- goto_model.clear (); // clean symbol table for next source file.
425
+ if (add_written_cprover_symbols (file_goto_model.symbol_table ))
426
+ return {};
427
+ }
428
+ else
429
+ {
430
+ if (linking (symbol_table, *file_symbol_table, get_message_handler ()))
431
+ {
432
+ return {};
433
+ }
423
434
}
424
435
}
425
436
426
- return false ;
437
+ return std::move (symbol_table) ;
427
438
}
428
439
429
440
// / parses a source file (low-level parsing)
@@ -593,37 +604,37 @@ bool compilet::write_bin_object_file(
593
604
return false ;
594
605
}
595
606
596
- // / parses a source file
597
- // / \return true on error, false otherwise
598
- bool compilet::parse_source (const std::string &file_name)
607
+ // / Parses and type checks a source file located at \p file_name.
608
+ // / \return A symbol table if, and only if, parsing and type checking succeeded.
609
+ optionalt<symbol_tablet> compilet::parse_source (const std::string &file_name)
599
610
{
600
611
language_filest language_files;
601
612
language_files.set_message_handler (get_message_handler ());
602
613
603
614
if (parse (file_name, language_files))
604
- return true ;
615
+ return {} ;
605
616
606
617
// we just typecheck one file here
607
- if (language_files.typecheck (goto_model.symbol_table , keep_file_local))
618
+ symbol_tablet file_symbol_table;
619
+ if (language_files.typecheck (file_symbol_table, keep_file_local))
608
620
{
609
621
error () << " CONVERSION ERROR" << eom;
610
- return true ;
622
+ return {} ;
611
623
}
612
624
613
- if (language_files.final (goto_model. symbol_table ))
625
+ if (language_files.final (file_symbol_table ))
614
626
{
615
627
error () << " CONVERSION ERROR" << eom;
616
- return true ;
628
+ return {} ;
617
629
}
618
630
619
- return false ;
631
+ return std::move (file_symbol_table) ;
620
632
}
621
633
622
634
// / constructor
623
635
// / \return nothing
624
636
compilet::compilet (cmdlinet &_cmdline, message_handlert &mh, bool Werror)
625
637
: messaget(mh),
626
- ns(goto_model.symbol_table),
627
638
cmdline(_cmdline),
628
639
warning_is_fatal(Werror),
629
640
keep_file_local(cmdline.isset(" export-function-local-symbols" )),
@@ -663,7 +674,7 @@ void compilet::add_compiler_specific_defines() const
663
674
std::string (" __GOTO_CC_VERSION__=" ) + CBMC_VERSION);
664
675
}
665
676
666
- void compilet::convert_symbols (goto_functionst &dest )
677
+ void compilet::convert_symbols (goto_modelt &goto_model )
667
678
{
668
679
symbol_table_buildert symbol_table_builder =
669
680
symbol_table_buildert::wrap (goto_model.symbol_table );
@@ -697,7 +708,8 @@ void compilet::convert_symbols(goto_functionst &dest)
697
708
s_it->second .value .is_not_nil ())
698
709
{
699
710
debug () << " Compiling " << s_it->first << eom;
700
- converter.convert_function (s_it->first , dest.function_map [s_it->first ]);
711
+ converter.convert_function (
712
+ s_it->first , goto_model.goto_functions .function_map [s_it->first ]);
701
713
symbol_table_builder.get_writeable_ref (symbol).set_compiled ();
702
714
}
703
715
}
0 commit comments