@@ -48,7 +48,6 @@ Author: Daniel Kroening, kroening@kroening.com
48
48
49
49
#include < goto-instrument/full_slicer.h>
50
50
#include < goto-instrument/nondet_static.h>
51
- #include < goto-instrument/cover.h>
52
51
53
52
#include < pointer-analysis/add_failed_symbols.h>
54
53
@@ -378,6 +377,23 @@ void jbmc_parse_optionst::get_command_line_options(optionst &options)
378
377
cmdline.get_value (" symex-coverage-report" ));
379
378
380
379
PARSE_OPTIONS_GOTO_TRACE (cmdline, options);
380
+
381
+ if (cmdline.isset (" symex-driven-lazy-loading" ))
382
+ {
383
+ options.set_option (" symex-driven-lazy-loading" , true );
384
+ for (const char *opt :
385
+ { " nondet-static" ,
386
+ " full-slice" ,
387
+ " show-properties" ,
388
+ " lazy-methods" })
389
+ {
390
+ if (cmdline.isset (opt))
391
+ {
392
+ throw std::string (" Option " ) + opt +
393
+ " can't be used with --symex-driven-lazy-loading" ;
394
+ }
395
+ }
396
+ }
381
397
}
382
398
383
399
// / invoke main modules
@@ -472,24 +488,7 @@ int jbmc_parse_optionst::doit()
472
488
return 0 ;
473
489
}
474
490
475
- std::unique_ptr<goto_modelt> goto_model_ptr;
476
- int get_goto_program_ret=get_goto_program (goto_model_ptr, options);
477
- if (get_goto_program_ret!=-1 )
478
- return get_goto_program_ret;
479
-
480
- goto_modelt &goto_model = *goto_model_ptr;
481
-
482
- if (cmdline.isset (" show-properties" ))
483
- {
484
- show_properties (
485
- goto_model, get_message_handler (), ui_message_handler.get_ui ());
486
- return 0 ; // should contemplate EX_OK from sysexits.h
487
- }
488
-
489
- if (set_properties (goto_model))
490
- return 7 ; // should contemplate EX_USAGE from sysexits.h
491
-
492
- std::function<void (bmct &, const symbol_tablet &)> configure_bmc;
491
+ std::function<void (bmct &, const symbol_tablet &)> configure_bmc = nullptr ;
493
492
if (options.get_bool_option (" java-unwind-enum-static" ))
494
493
{
495
494
configure_bmc = [](
@@ -508,15 +507,72 @@ int jbmc_parse_optionst::doit()
508
507
});
509
508
};
510
509
}
510
+
511
+ if (!cmdline.isset (" symex-driven-lazy-loading" ))
512
+ {
513
+ std::unique_ptr<goto_modelt> goto_model_ptr;
514
+ int get_goto_program_ret=get_goto_program (goto_model_ptr, options);
515
+ if (get_goto_program_ret!=-1 )
516
+ return get_goto_program_ret;
517
+
518
+ goto_modelt &goto_model = *goto_model_ptr;
519
+
520
+ if (cmdline.isset (" show-properties" ))
521
+ {
522
+ show_properties (
523
+ goto_model, get_message_handler (), ui_message_handler.get_ui ());
524
+ return 0 ; // should contemplate EX_OK from sysexits.h
525
+ }
526
+
527
+ if (set_properties (goto_model))
528
+ return 7 ; // should contemplate EX_USAGE from sysexits.h
529
+
530
+ return bmct::do_language_agnostic_bmc (
531
+ options, goto_model, ui_message_handler.get_ui (), *this , configure_bmc);
532
+ }
511
533
else
512
534
{
513
- configure_bmc = [](
514
- bmct &bmc, const symbol_tablet &symbol_table) { // NOLINT (*)
515
- // NOOP
535
+ // Use symex-driven lazy loading:
536
+ lazy_goto_modelt lazy_goto_model=lazy_goto_modelt::from_handler_object (
537
+ *this , options, get_message_handler ());
538
+ lazy_goto_model.initialize (cmdline);
539
+
540
+ // The precise wording of this error matches goto-symex's complaint when no
541
+ // __CPROVER_start exists (if we just go ahead and run it anyway it will
542
+ // trip an invariant when it tries to load it)
543
+ if (!lazy_goto_model.symbol_table .has_symbol (goto_functionst::entry_point ()))
544
+ {
545
+ error () << " the program has no entry point" ;
546
+ return 6 ;
547
+ }
548
+
549
+ // Add failed symbols for any symbol created prior to loading any
550
+ // particular function:
551
+ add_failed_symbols (lazy_goto_model.symbol_table );
552
+
553
+ // If applicable, parse the coverage instrumentation configuration, which
554
+ // will be used in process_goto_function:
555
+ cover_config =
556
+ get_cover_config (
557
+ options, lazy_goto_model.symbol_table , get_message_handler ());
558
+
559
+ // Provide show-goto-functions and similar dump functions after symex
560
+ // executes. If --paths is active, these dump routines run after every
561
+ // paths iteration. Its return value indicates that if we ran any dump
562
+ // function, then we should skip the actual solver phase.
563
+ auto callback_after_symex = [this , &lazy_goto_model]() { // NOLINT (*)
564
+ return show_loaded_functions (lazy_goto_model);
516
565
};
566
+
567
+ return
568
+ bmct::do_language_agnostic_bmc (
569
+ options,
570
+ lazy_goto_model,
571
+ ui_message_handler.get_ui (),
572
+ *this ,
573
+ configure_bmc,
574
+ callback_after_symex);
517
575
}
518
- return bmct::do_language_agnostic_bmc (
519
- options, goto_model, ui_message_handler.get_ui (), *this , configure_bmc);
520
576
}
521
577
522
578
bool jbmc_parse_optionst::set_properties (goto_modelt &goto_model)
@@ -643,13 +699,30 @@ void jbmc_parse_optionst::process_goto_function(
643
699
journalling_symbol_tablet &symbol_table = function.get_symbol_table ();
644
700
namespacet ns (symbol_table);
645
701
goto_functionst::goto_functiont &goto_function = function.get_goto_function ();
702
+
703
+ bool using_symex_driven_loading =
704
+ options.get_bool_option (" symex-driven-lazy-loading" );
705
+
646
706
try
647
707
{
648
708
// Removal of RTTI inspection:
649
709
remove_instanceof (goto_function, symbol_table);
650
710
// Java virtual functions -> explicit dispatch tables:
651
711
remove_virtual_functions (function);
652
712
713
+ if (using_symex_driven_loading)
714
+ {
715
+ // remove exceptions
716
+ // If using symex-driven function loading we need to do this now so that
717
+ // symex doesn't have to cope with exception-handling constructs; however
718
+ // the results are slightly worse than running it in whole-program mode
719
+ // (e.g. dead catch sites will be retained)
720
+ remove_exceptions (
721
+ goto_function.body ,
722
+ symbol_table,
723
+ remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF);
724
+ }
725
+
653
726
auto function_is_stub =
654
727
[&symbol_table, &model](const irep_idt &id) { // NOLINT(*)
655
728
return symbol_table.lookup_ref (id).value .is_nil () &&
@@ -699,6 +772,28 @@ void jbmc_parse_optionst::process_goto_function(
699
772
symbol_table);
700
773
}
701
774
775
+ // If using symex-driven function loading we must insert the coverage goals
776
+ // now so symex sees its targets; otherwise we leave this until
777
+ // process_goto_functions, as we haven't run remove_exceptions yet, and that
778
+ // pass alters the CFG.
779
+ if (using_symex_driven_loading)
780
+ {
781
+ // instrument cover goals
782
+ if (cmdline.isset (" cover" ))
783
+ {
784
+ INVARIANT (
785
+ cover_config != nullptr , " cover config should have been parsed" );
786
+ instrument_cover_goals (*cover_config, function, get_message_handler ());
787
+ }
788
+
789
+ // label the assertions
790
+ label_properties (goto_function.body );
791
+
792
+ goto_function.body .update ();
793
+ function.compute_location_numbers ();
794
+ goto_function.body .compute_loop_numbers ();
795
+ }
796
+
702
797
// update the function member in each instruction
703
798
function.update_instructions_function ();
704
799
}
@@ -722,14 +817,57 @@ void jbmc_parse_optionst::process_goto_function(
722
817
}
723
818
}
724
819
820
+ bool jbmc_parse_optionst::show_loaded_functions (
821
+ const abstract_goto_modelt &goto_model)
822
+ {
823
+ if (cmdline.isset (" show-symbol-table" ))
824
+ {
825
+ show_symbol_table (
826
+ goto_model.get_symbol_table (), ui_message_handler.get_ui ());
827
+ return true ;
828
+ }
829
+
830
+ if (cmdline.isset (" show-loops" ))
831
+ {
832
+ show_loop_ids (ui_message_handler.get_ui (), goto_model.get_goto_functions ());
833
+ return true ;
834
+ }
835
+
836
+ if (
837
+ cmdline.isset (" show-goto-functions" ) ||
838
+ cmdline.isset (" list-goto-functions" ))
839
+ {
840
+ namespacet ns (goto_model.get_symbol_table ());
841
+ show_goto_functions (
842
+ ns,
843
+ get_message_handler (),
844
+ ui_message_handler.get_ui (),
845
+ goto_model.get_goto_functions (),
846
+ cmdline.isset (" list-goto-functions" ));
847
+ return true ;
848
+ }
849
+
850
+ return false ;
851
+ }
852
+
725
853
bool jbmc_parse_optionst::process_goto_functions (
726
854
goto_modelt &goto_model,
727
855
const optionst &options)
728
856
{
729
857
try
730
858
{
731
859
status () << " Running GOTO functions transformation passes" << eom;
732
- // remove catch and throw (introduces instanceof but request it is removed)
860
+
861
+ bool using_symex_driven_loading =
862
+ options.get_bool_option (" symex-driven-lazy-loading" );
863
+
864
+ // When using symex-driven lazy loading, *all* relevant processing is done
865
+ // during process_goto_function, so we have nothing to do here.
866
+ if (using_symex_driven_loading)
867
+ return false ;
868
+
869
+ // remove catch and throw
870
+ // (introduces instanceof but request it is removed)
733
871
remove_exceptions (
734
872
goto_model, remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF);
735
873
@@ -865,6 +1003,8 @@ void jbmc_parse_optionst::help()
865
1003
// This one is handled by jbmc_parse_options not by the Java frontend,
866
1004
// hence its presence here:
867
1005
" --java-unwind-enum-static try to unwind loops in static initialization of enums\n " // NOLINT(*)
1006
+ // Currently only supported in the JBMC frontend:
1007
+ " --symex-driven-lazy-loading only load functions when first entered by symbolic execution\n " // NOLINT(*)
868
1008
" \n "
869
1009
" BMC options:\n "
870
1010
HELP_BMC
0 commit comments