Skip to content

Commit 36c17c4

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

File tree

4 files changed

+94
-4
lines changed

4 files changed

+94
-4
lines changed

jbmc/src/java_bytecode/java_bytecode_language.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,7 +1106,15 @@ bool java_bytecode_languaget::convert_single_method(
11061106
get_message_handler());
11071107
break;
11081108
case synthetic_method_typet::USER_SPECIFIED_STATIC_INITIALIZER:
1109+
{
1110+
const auto class_name =
1111+
declaring_class(symbol_table.lookup_ref(function_id));
1112+
INVARIANT(
1113+
class_name, "user_specified_clinit must be declared by a class.");
1114+
writable_symbol.value = get_user_specified_clinit_body(
1115+
*class_name, static_values_file, symbol_table, get_message_handler());
11091116
break;
1117+
}
11101118
case synthetic_method_typet::STUB_CLASS_STATIC_INITIALIZER:
11111119
writable_symbol.value =
11121120
stub_global_initializer_factory.get_stub_initializer_body(

jbmc/src/java_bytecode/java_static_initializers.cpp

Lines changed: 59 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
@@ -750,6 +751,61 @@ code_ifthenelset get_clinit_wrapper_body(
750751
return code_ifthenelset(std::move(check_already_run), std::move(init_body));
751752
}
752753

754+
code_blockt get_user_specified_clinit_body(
755+
const irep_idt &class_id,
756+
const std::string &static_values_file,
757+
symbol_table_baset &symbol_table,
758+
message_handlert &message_handler)
759+
{
760+
jsont json;
761+
if(
762+
!static_values_file.empty() &&
763+
!parse_json(static_values_file, message_handler, json) && json.is_object())
764+
{
765+
const auto &json_object = to_json_object(json);
766+
const auto class_entry =
767+
json_object.find(id2string(strip_java_namespace_prefix(class_id)));
768+
if(class_entry != json_object.end())
769+
{
770+
const auto &class_json_value = class_entry->second;
771+
if(class_json_value.is_object())
772+
{
773+
const auto &class_json_object = to_json_object(class_json_value);
774+
std::map<symbol_exprt, jsont> static_field_values;
775+
for(const auto &symbol_pair : symbol_table)
776+
{
777+
const symbolt &symbol = symbol_pair.second;
778+
if(
779+
declaring_class(symbol) && *declaring_class(symbol) == class_id &&
780+
symbol.is_static_lifetime)
781+
{
782+
const symbol_exprt &static_field_expr = symbol.symbol_expr();
783+
const auto &static_field_entry =
784+
class_json_object.find(id2string(symbol.base_name));
785+
if(static_field_entry != class_json_object.end())
786+
{
787+
static_field_values.insert(
788+
{static_field_expr, static_field_entry->second});
789+
}
790+
}
791+
}
792+
code_blockt body;
793+
for(const auto &value_pair : static_field_values)
794+
{
795+
// TODO append code to `body` to assign value_pair.first to
796+
// TODO value_pair.second
797+
(void)value_pair;
798+
}
799+
return body;
800+
}
801+
}
802+
}
803+
const irep_idt &real_clinit_name = clinit_function_name(class_id);
804+
if(const auto clinit_func = symbol_table.lookup(real_clinit_name))
805+
return code_blockt{{code_function_callt{clinit_func->symbol_expr()}}};
806+
return code_blockt{};
807+
}
808+
753809
/// Create static initializer wrappers and possibly user-specified functions for
754810
/// initial static field value assignments for all classes that need them.
755811
/// For each class that will require a static initializer wrapper, create a

jbmc/src/java_bytecode/java_static_initializers.h

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

51+
/// Create the body of a user_specified_clinit function for a given class, which
52+
/// includes assignments for all static fields of the class to values read from
53+
/// an input file. If the file could not be parsed or an entry for this class
54+
/// could not be found in it, the user_specified_clinit function will only
55+
/// contain a call to the "real" clinit function, and not include any
56+
/// assignments itself. If an entry for this class is found but some of its
57+
/// static fields are not mentioned in the input file, those fields will be
58+
/// assigned default values (zero or null).
59+
/// \param class_id: the id of the class to create a user_specified_clinit
60+
/// function body for.
61+
/// \param static_values_file: input file containing values of static fields.
62+
/// The format is expected to be a map whose keys are class names, and whose
63+
/// values are maps from static field names to values. Currently only JSON
64+
/// is supported as a file format.
65+
/// \param symbol_table: used to look up and create new symbols
66+
/// \param message_handler: used to log any errors with parsing the input file
67+
/// \return the body of the user_specified_clinit function as a code block.
68+
code_blockt get_user_specified_clinit_body(
69+
const irep_idt &class_id,
70+
const std::string &static_values_file,
71+
symbol_table_baset &symbol_table,
72+
message_handlert &message_handler);
73+
5174
class stub_global_initializer_factoryt
5275
{
5376
/// Maps class symbols onto the stub globals that belong to them

jbmc/src/java_bytecode/synthetic_methods_map.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +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-
/// TODO Currently has no content, future commits will add it.
31+
/// If a given type has an entry in the file given by this option, the "user
32+
/// specified static initializer" contains a sequence of assignments from
33+
/// static field expressions to values read from the file.
34+
/// Otherwise, this function simply calls the regular clinit.
3235
USER_SPECIFIED_STATIC_INITIALIZER,
3336
/// A generated (synthetic) static initializer function for a stub type.
3437
/// Because we don't have the bytecode for a stub type (by definition), we

0 commit comments

Comments
 (0)