Skip to content

Commit 5d6c793

Browse files
committed
Set up structure of function for json_clinit body
To get the assignments from the JSON file, we will have to - parse the JSON file - look up the given class name in the JSON file - for each static field of this class in the symbol table, look up the field name in the class entry of the JSON file - if an entry was found, the "TODO" is hit: in the following commits the actual assignments will be added here.
1 parent 2c8fa77 commit 5d6c793

File tree

4 files changed

+92
-3
lines changed

4 files changed

+92
-3
lines changed

jbmc/src/java_bytecode/java_bytecode_language.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,11 @@ bool java_bytecode_languaget::convert_single_method(
11021102
get_message_handler());
11031103
break;
11041104
case synthetic_method_typet::JSON_STATIC_INITIALIZER:
1105+
writable_symbol.value = get_json_clinit_body(
1106+
function_id,
1107+
static_values_file,
1108+
symbol_table,
1109+
get_message_handler());
11051110
break;
11061111
case synthetic_method_typet::STUB_CLASS_STATIC_INITIALIZER:
11071112
writable_symbol.value =

jbmc/src/java_bytecode/java_static_initializers.cpp

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ Author: Chris Smowton, [email protected]
1010
#include "java_object_factory.h"
1111
#include "java_utils.h"
1212
#include <goto-programs/class_hierarchy.h>
13-
#include <util/std_types.h>
14-
#include <util/std_expr.h>
13+
#include <json/json_parser.h>
14+
#include <util/arith_tools.h>
1515
#include <util/std_code.h>
16+
#include <util/std_expr.h>
17+
#include <util/std_types.h>
1618
#include <util/suffix.h>
17-
#include <util/arith_tools.h>
1819

1920
/// The three states in which a `<clinit>` method for a class can be before,
2021
/// after, and during static class initialization. These states are only used
@@ -744,6 +745,60 @@ code_ifthenelset get_clinit_wrapper_body(
744745
return code_ifthenelset(std::move(check_already_run), std::move(init_body));
745746
}
746747

748+
code_blockt get_json_clinit_body(
749+
const irep_idt &function_id,
750+
const std::string &static_values_file,
751+
symbol_table_baset &symbol_table,
752+
message_handlert &message_handler)
753+
{
754+
const auto class_name = declaring_class(symbol_table.lookup_ref(function_id));
755+
INVARIANT(class_name, "json_clinit must be declared by a class.");
756+
jsont json;
757+
if(
758+
!static_values_file.empty() &&
759+
!parse_json(static_values_file, message_handler, json) && json.is_object())
760+
{
761+
const auto &json_object = to_json_object(json);
762+
const auto class_entry =
763+
json_object.find(id2string(strip_java_namespace_prefix(*class_name)));
764+
if(class_entry != json_object.end())
765+
{
766+
const auto &class_json_value = class_entry->second;
767+
if(class_json_value.is_object())
768+
{
769+
const auto &class_json_object = to_json_object(class_json_value);
770+
std::map<symbol_exprt, jsont> static_field_values;
771+
for(const auto &symbol_pair : symbol_table)
772+
{
773+
const symbolt &symbol = symbol_pair.second;
774+
if(declaring_class(symbol) == class_name && symbol.is_static_lifetime)
775+
{
776+
const symbol_exprt &static_field_expr = symbol.symbol_expr();
777+
const auto &static_field_entry =
778+
class_json_object.find(id2string(symbol.base_name));
779+
if(static_field_entry != class_json_object.end())
780+
{
781+
static_field_values.insert(
782+
{static_field_expr, static_field_entry->second});
783+
}
784+
}
785+
}
786+
code_blockt body;
787+
for(const auto &value_pair : static_field_values)
788+
{
789+
// TODO append code to `body` to assign value_pair.first to
790+
// TODO value_pair.second
791+
}
792+
return body;
793+
}
794+
}
795+
}
796+
const irep_idt &real_clinit_name = clinit_function_name(*class_name);
797+
if(const auto clinit_func = symbol_table.lookup(real_clinit_name))
798+
return code_blockt{{code_function_callt{clinit_func->symbol_expr()}}};
799+
return code_blockt{};
800+
}
801+
747802
/// Create static initializer wrappers and possibly assignments from a JSON file
748803
/// for all classes that need them.
749804
/// For each class that will require a static initializer wrapper, create a

jbmc/src/java_bytecode/java_static_initializers.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,31 @@ code_ifthenelset get_clinit_wrapper_body(
4848
const select_pointer_typet &pointer_type_selector,
4949
message_handlert &message_handler);
5050

51+
/// Creates the body of a json_clinit function, which includes assignments for
52+
/// all static fields of a class to values read from a JSON file. If the JSON
53+
/// file could not be parsed or an entry for this class could not be found in
54+
/// the JSON file, the function will only include a call to the "real" clinit
55+
/// function, and not include any assignments itself. If an entry for this class
56+
/// is found but some of its static fields are not mentioned in the JSON file,
57+
/// those fields will be assigned default values.
58+
/// \param function_id: the id of this json_clinit function
59+
/// \param static_values_file: JSON file containing values of static fields. The
60+
/// format is expected to be a map whose keys are class names, and whose
61+
/// values are maps from static field names to values.
62+
/// \param symbol_table: used to look up and create new symbols
63+
/// \param message_handler: used log any errors with parsing the JSON
64+
/// \param needed_lazy_methods: used to mark any runtime types given in the JSON
65+
/// file as needed
66+
/// \param max_user_array_length: maximum value for constant or variable length
67+
/// arrays. Any arrays that were specified to be of nondeterministic length in
68+
/// the JSON file will be limited by this value.
69+
/// \param references:
70+
/// \return the body of the json_clinit function as a code block.
71+
code_blockt get_json_clinit_body(
72+
const irep_idt &function_id,
73+
const std::string &static_values_file,
74+
symbol_table_baset &symbol_table,
75+
message_handlert &message_handler);
5176
class stub_global_initializer_factoryt
5277
{
5378
/// Maps class symbols onto the stub globals that belong to them

jbmc/src/java_bytecode/synthetic_methods_map.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ enum class synthetic_method_typet
2828
/// static initializer is only run once on any given path.
2929
STATIC_INITIALIZER_WRAPPER,
3030
/// Only exists if the `--static-values` option was used.
31+
/// If a given type has an entry in the file given by this option, the JSON
32+
/// JSON static initializer contains a sequence of assignments from static
33+
/// field expressions to values read from the JSON file.
34+
/// Otherwise, this function simply calls the regular clinit.
3135
JSON_STATIC_INITIALIZER,
3236
/// A generated (synthetic) static initializer function for a stub type.
3337
/// Because we don't have the bytecode for a stub type (by definition), we

0 commit comments

Comments
 (0)