Merge pull request #5156 from thomasspriggs/tas/lazy_initialize

Support for an external lazy methods driver to control when the `INITIALIZE_FUNCTION` is generated
This commit is contained in:
thomasspriggs 2019-10-09 16:20:14 +01:00 committed by GitHub
commit e1e7a74454
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 105 additions and 15 deletions

View File

@ -10,6 +10,8 @@ Author: Daniel Kroening, kroening@kroening.com
#include <string>
#include <linking/static_lifetime_init.h>
#include <util/cmdline.h>
#include <util/config.h>
#include <util/expr_iterator.h>
@ -757,6 +759,7 @@ bool java_bytecode_languaget::typecheck(
"the Java front-end should only be used with an empty symbol table");
java_internal_additions(symbol_table);
create_java_initialize(symbol_table);
if(language_options->string_refinement_enabled)
string_preprocess.initialize_conversion_table();
@ -942,6 +945,8 @@ bool java_bytecode_languaget::typecheck(
convert_single_method(
method_sig.first, journalling_symbol_table, class_to_declared_symbols);
}
convert_single_method(
INITIALIZE_FUNCTION, journalling_symbol_table, class_to_declared_symbols);
// Now convert all newly added string methods
for(const auto &fn_name : journalling_symbol_table.get_inserted())
{
@ -1095,6 +1100,7 @@ void java_bytecode_languaget::methods_provided(
// Add all synthetic methods to map
for(const auto &kv : synthetic_methods)
methods.insert(kv.first);
methods.insert(INITIALIZE_FUNCTION);
}
/// \brief Promote a lazy-converted method (one whose type is known but whose
@ -1119,8 +1125,9 @@ void java_bytecode_languaget::convert_lazy_method(
lazy_class_to_declared_symbols_mapt class_to_declared_symbols;
convert_single_method(function_id, symbol_table, class_to_declared_symbols);
// Instrument runtime exceptions (unless symbol is a stub)
if(symbol.value.is_not_nil())
// Instrument runtime exceptions (unless symbol is a stub or is the
// INITIALISE_FUNCTION).
if(symbol.value.is_not_nil() && function_id != INITIALIZE_FUNCTION)
{
java_bytecode_instrument_symbol(
symbol_table,
@ -1201,6 +1208,20 @@ bool java_bytecode_languaget::convert_single_method(
// Nothing to do if body is already loaded
if(symbol.value.is_not_nil())
return false;
if(function_id == INITIALIZE_FUNCTION)
{
java_static_lifetime_init(
symbol_table,
symbol.location,
language_options->assume_inputs_non_null,
object_factory_parameters,
*pointer_type_selector,
language_options->string_refinement_enabled,
get_message_handler());
return false;
}
INVARIANT(declaring_class(symbol), "Method must have a declaring class.");
bool ret = convert_single_method_code(

View File

@ -53,7 +53,6 @@ void create_java_initialize(symbol_table_baset &symbol_table)
initialize.mode=ID_java;
initialize.type = java_method_typet({}, java_void_type());
symbol_table.add(initialize);
}
@ -104,7 +103,7 @@ static constant_exprt constant_bool(bool val)
return from_integer(val ? 1 : 0, java_boolean_type());
}
static void java_static_lifetime_init(
void java_static_lifetime_init(
symbol_table_baset &symbol_table,
const source_locationt &source_location,
bool assume_init_pointers_not_null,
@ -115,6 +114,7 @@ static void java_static_lifetime_init(
{
symbolt &initialize_symbol =
symbol_table.get_writeable_ref(INITIALIZE_FUNCTION);
PRECONDITION(initialize_symbol.value.is_nil());
code_blockt code_block;
const symbol_exprt rounding_mode =
@ -590,17 +590,6 @@ bool java_entry_point(
assert(symbol.type.id()==ID_code);
create_java_initialize(symbol_table);
java_static_lifetime_init(
symbol_table,
symbol.location,
assume_init_pointers_not_null,
object_factory_parameters,
pointer_type_selector,
string_refinement_enabled,
message_handler);
return generate_java_start_function(
symbol,
symbol_table,

View File

@ -190,4 +190,14 @@ std::pair<code_blockt, std::vector<exprt>> java_build_arguments(
/// code for it yet.
void create_java_initialize(symbol_table_baset &symbol_table);
/// Adds the body to __CPROVER_initialize
void java_static_lifetime_init(
symbol_table_baset &symbol_table,
const source_locationt &source_location,
bool assume_init_pointers_not_null,
java_object_factory_parameterst object_factory_parameters,
const select_pointer_typet &pointer_type_selector,
bool string_refinement_enabled,
message_handlert &message_handler);
#endif // CPROVER_JAVA_BYTECODE_JAVA_ENTRY_POINT_H

View File

@ -12,6 +12,9 @@ Author: Diffblue Limited.
#include <java-testing-utils/load_java_class.h>
#include <java-testing-utils/require_type.h>
#include <java_bytecode/java_bytecode_language.h>
#include <linking/static_lifetime_init.h>
#include <util/options.h>
SCENARIO(
"java_bytecode_language_opaque_field",
@ -45,3 +48,68 @@ SCENARIO(
}
}
}
static void use_external_driver(java_bytecode_languaget &language)
{
optionst options;
options.set_option("symex-driven-lazy-loading", true);
language.set_language_options(options);
}
SCENARIO(
"LAZY_METHODS_MODE_EXTERNAL_DRIVER based generation of cprover_initialise",
"[core][java_bytecode_language]")
{
java_bytecode_languaget language;
null_message_handlert null_message_handler;
language.set_message_handler(null_message_handler);
use_external_driver(language);
symbol_tablet symbol_table;
GIVEN("java_bytecode_languaget::typecheck is run.")
{
language.typecheck(symbol_table, "");
THEN("The " INITIALIZE_FUNCTION " is in the symbol table without code.")
{
const symbolt *const initialise =
symbol_table.lookup(INITIALIZE_FUNCTION);
REQUIRE(initialise);
REQUIRE(initialise->value.is_nil());
}
GIVEN(
"java_bytecode_languaget::convert_lazy_method is used to "
"generate " INITIALIZE_FUNCTION)
{
language.convert_lazy_method(INITIALIZE_FUNCTION, symbol_table);
THEN("The " INITIALIZE_FUNCTION " is in the symbol table with code.")
{
const symbolt *const initialise =
symbol_table.lookup(INITIALIZE_FUNCTION);
REQUIRE(initialise);
REQUIRE(can_cast_expr<codet>(initialise->value));
}
}
}
}
TEST_CASE(
"Standard generation of cprover_initialise",
"[core][java_bytecode_language]")
{
java_bytecode_languaget language;
null_message_handlert null_message_handler;
language.set_message_handler(null_message_handler);
language.set_language_options(optionst{});
symbol_tablet symbol_table;
GIVEN("java_bytecode_languaget::typecheck is run.")
{
language.typecheck(symbol_table, "");
THEN("The " INITIALIZE_FUNCTION
" function is in the symbol table with code.")
{
const symbolt *const initialise =
symbol_table.lookup(INITIALIZE_FUNCTION);
REQUIRE(initialise);
REQUIRE(can_cast_expr<codet>(initialise->value));
}
}
}

View File

@ -1,3 +1,5 @@
java_bytecode
java-testing-utils
linking
testing-utils
util