Skip to content

Commit a847d8c

Browse files
authored
Merge pull request #4599 from smowton/smowton/feature/remove-virtual-functions-class-hierarchy
Remove-virtual-functions: avoid computing class_hierarchyt when possible
2 parents 0863c63 + 4be7670 commit a847d8c

File tree

3 files changed

+117
-55
lines changed

3 files changed

+117
-55
lines changed

jbmc/src/jbmc/jbmc_parse_options.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ void jbmc_parse_optionst::process_goto_function(
753753
*class_hierarchy,
754754
ui_message_handler);
755755
// Java virtual functions -> explicit dispatch tables:
756-
remove_virtual_functions(function);
756+
remove_virtual_functions(function, *class_hierarchy);
757757

758758
auto function_is_stub = [&symbol_table, &model](const irep_idt &id) {
759759
return symbol_table.lookup_ref(id).value.is_nil() &&

src/goto-programs/remove_virtual_functions.cpp

Lines changed: 99 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,6 @@ class remove_virtual_functionst
7676
const irep_idt &function_id,
7777
goto_programt &goto_program);
7878

79-
goto_programt::targett remove_virtual_function(
80-
const irep_idt &function_id,
81-
goto_programt &goto_program,
82-
goto_programt::targett target,
83-
const dispatch_table_entriest &functions,
84-
virtual_dispatch_fallback_actiont fallback_action);
85-
8679
private:
8780
const class_hierarchyt &class_hierarchy;
8881
symbol_table_baset &symbol_table;
@@ -94,42 +87,6 @@ class remove_virtual_functionst
9487
goto_programt::targett target);
9588
};
9689

97-
/// Replace specified virtual function call with a static call to its
98-
/// most derived implementation
99-
/// \param function_id: The identifier of the function we are currently
100-
/// analysing
101-
/// \param [in,out] goto_program: GOTO program to modify
102-
/// \param target: iterator to a function in the supplied GOTO program
103-
/// to replace. Must point to a virtual function call.
104-
/// \return Returns a pointer to the statement in the supplied GOTO
105-
/// program after replaced function call
106-
goto_programt::targett remove_virtual_functionst::remove_virtual_function(
107-
const irep_idt &function_id,
108-
goto_programt &goto_program,
109-
goto_programt::targett target)
110-
{
111-
const code_function_callt &code = target->get_function_call();
112-
113-
const exprt &function=code.function();
114-
INVARIANT(
115-
function.id()==ID_virtual_function,
116-
"remove_virtual_function must take a virtual function call instruction");
117-
INVARIANT(
118-
!code.arguments().empty(),
119-
"virtual function calls must have at least a this-argument");
120-
121-
get_virtual_calleest get_callees(symbol_table, class_hierarchy);
122-
dispatch_table_entriest functions;
123-
get_callees.get_functions(function, functions);
124-
125-
return remove_virtual_function(
126-
function_id,
127-
goto_program,
128-
target,
129-
functions,
130-
virtual_dispatch_fallback_actiont::CALL_LAST_FUNCTION);
131-
}
132-
13390
/// Create a concrete function call to replace a virtual one
13491
/// \param [in,out] call: the function call to update
13592
/// \param function_symbol: the function to be called
@@ -285,6 +242,7 @@ static void process_this_argument(
285242
/// implementation. If there's a type mismatch between implementation
286243
/// and the instance type or if fallback_action is set to
287244
/// ASSUME_FALSE, then function is substituted with a call to ASSUME(false)
245+
/// \param symbol_table: Symbol table associated with \p goto_program
288246
/// \param function_id: The identifier of the function we are currently
289247
/// analysing
290248
/// \param [in,out] goto_program: GOTO program to modify
@@ -297,7 +255,8 @@ static void process_this_argument(
297255
/// with the most derived matching call
298256
/// \return Returns a pointer to the statement in the supplied GOTO
299257
/// program after replaced function call
300-
goto_programt::targett remove_virtual_functionst::remove_virtual_function(
258+
static goto_programt::targett replace_virtual_function_with_dispatch_table(
259+
symbol_table_baset &symbol_table,
301260
const irep_idt &function_id,
302261
goto_programt &goto_program,
303262
goto_programt::targett target,
@@ -308,6 +267,7 @@ goto_programt::targett remove_virtual_functionst::remove_virtual_function(
308267
target->is_function_call(),
309268
"remove_virtual_function must target a FUNCTION_CALL instruction");
310269

270+
namespacet ns(symbol_table);
311271
goto_programt::targett next_target = std::next(target);
312272

313273
if(functions.empty())
@@ -499,6 +459,43 @@ goto_programt::targett remove_virtual_functionst::remove_virtual_function(
499459
return next_target;
500460
}
501461

462+
/// Replace specified virtual function call with a static call to its
463+
/// most derived implementation
464+
/// \param function_id: The identifier of the function we are currently
465+
/// analysing
466+
/// \param [in,out] goto_program: GOTO program to modify
467+
/// \param target: iterator to a function in the supplied GOTO program
468+
/// to replace. Must point to a virtual function call.
469+
/// \return Returns a pointer to the statement in the supplied GOTO
470+
/// program after replaced function call
471+
goto_programt::targett remove_virtual_functionst::remove_virtual_function(
472+
const irep_idt &function_id,
473+
goto_programt &goto_program,
474+
goto_programt::targett target)
475+
{
476+
const code_function_callt &code = target->get_function_call();
477+
478+
const exprt &function = code.function();
479+
INVARIANT(
480+
function.id() == ID_virtual_function,
481+
"remove_virtual_function must take a virtual function call instruction");
482+
INVARIANT(
483+
!code.arguments().empty(),
484+
"virtual function calls must have at least a this-argument");
485+
486+
get_virtual_calleest get_callees(symbol_table, class_hierarchy);
487+
dispatch_table_entriest functions;
488+
get_callees.get_functions(function, functions);
489+
490+
return replace_virtual_function_with_dispatch_table(
491+
symbol_table,
492+
function_id,
493+
goto_program,
494+
target,
495+
functions,
496+
virtual_dispatch_fallback_actiont::CALL_LAST_FUNCTION);
497+
}
498+
502499
/// Used by get_functions to track the most-derived parent that provides an
503500
/// override of a given function.
504501
/// \param this_id: class name
@@ -740,6 +737,8 @@ void remove_virtual_functionst::operator()(goto_functionst &functions)
740737

741738
/// Remove virtual function calls from all functions in the specified
742739
/// list and replace them with their most derived implementations
740+
/// \param symbol_table: symbol table associated with \p goto_functions
741+
/// \param goto_functions: functions from which to remove virtual function calls
743742
void remove_virtual_functions(
744743
symbol_table_baset &symbol_table,
745744
goto_functionst &goto_functions)
@@ -750,14 +749,47 @@ void remove_virtual_functions(
750749
rvf(goto_functions);
751750
}
752751

752+
/// Remove virtual function calls from all functions in the specified
753+
/// list and replace them with their most derived implementations
754+
/// \param symbol_table: symbol table associated with \p goto_functions
755+
/// \param goto_functions: functions from which to remove virtual function calls
756+
/// \param class_hierarchy: class hierarchy derived from symbol_table
757+
/// This should already be populated (i.e. class_hierarchyt::operator() has
758+
/// already been called)
759+
void remove_virtual_functions(
760+
symbol_table_baset &symbol_table,
761+
goto_functionst &goto_functions,
762+
const class_hierarchyt &class_hierarchy)
763+
{
764+
remove_virtual_functionst rvf(symbol_table, class_hierarchy);
765+
rvf(goto_functions);
766+
}
767+
753768
/// Remove virtual function calls from the specified model
769+
/// \param goto_model: model from which to remove virtual functions
754770
void remove_virtual_functions(goto_modelt &goto_model)
755771
{
756772
remove_virtual_functions(
757773
goto_model.symbol_table, goto_model.goto_functions);
758774
}
759775

776+
/// Remove virtual function calls from the specified model
777+
/// \param goto_model: model from which to remove virtual functions
778+
/// \param class_hierarchy: class hierarchy derived from model.symbol_table
779+
/// This should already be populated (i.e. class_hierarchyt::operator() has
780+
/// already been called)
781+
void remove_virtual_functions(
782+
goto_modelt &goto_model,
783+
const class_hierarchyt &class_hierarchy)
784+
{
785+
remove_virtual_functions(
786+
goto_model.symbol_table, goto_model.goto_functions, class_hierarchy);
787+
}
788+
760789
/// Remove virtual function calls from the specified model function
790+
/// May change the location numbers in `function`.
791+
/// \param function: function from which virtual functions should be converted
792+
/// to explicit dispatch tables.
761793
void remove_virtual_functions(goto_model_functiont &function)
762794
{
763795
class_hierarchyt class_hierarchy;
@@ -767,6 +799,22 @@ void remove_virtual_functions(goto_model_functiont &function)
767799
function.get_function_id(), function.get_goto_function().body);
768800
}
769801

802+
/// Remove virtual function calls from the specified model function
803+
/// May change the location numbers in `function`.
804+
/// \param function: function from which virtual functions should be converted
805+
/// to explicit dispatch tables.
806+
/// \param class_hierarchy: class hierarchy derived from function.symbol_table
807+
/// This should already be populated (i.e. class_hierarchyt::operator() has
808+
/// already been called)
809+
void remove_virtual_functions(
810+
goto_model_functiont &function,
811+
const class_hierarchyt &class_hierarchy)
812+
{
813+
remove_virtual_functionst rvf(function.get_symbol_table(), class_hierarchy);
814+
rvf.remove_virtual_functions(
815+
function.get_function_id(), function.get_goto_function().body);
816+
}
817+
770818
/// Replace virtual function call with a static function call
771819
/// Achieved by substituting a virtual function with its most derived
772820
/// implementation. If there's a type mismatch between implementation
@@ -793,12 +841,13 @@ goto_programt::targett remove_virtual_function(
793841
const dispatch_table_entriest &dispatch_table,
794842
virtual_dispatch_fallback_actiont fallback_action)
795843
{
796-
class_hierarchyt class_hierarchy;
797-
class_hierarchy(symbol_table);
798-
remove_virtual_functionst rvf(symbol_table, class_hierarchy);
799-
800-
goto_programt::targett next = rvf.remove_virtual_function(
801-
function_id, goto_program, instruction, dispatch_table, fallback_action);
844+
goto_programt::targett next = replace_virtual_function_with_dispatch_table(
845+
symbol_table,
846+
function_id,
847+
goto_program,
848+
instruction,
849+
dispatch_table,
850+
fallback_action);
802851

803852
goto_program.update();
804853

src/goto-programs/remove_virtual_functions.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,32 @@ class goto_model_functiont;
2626
class goto_modelt;
2727
class symbol_table_baset;
2828

29+
// For all of the following the class-hierarchy and non-class-hierarchy
30+
// overloads are equivalent, but the class-hierarchy-taking one saves time if
31+
// you already have a class-hierarchy object available.
32+
2933
void remove_virtual_functions(
3034
goto_modelt &goto_model);
3135

36+
void remove_virtual_functions(
37+
goto_modelt &goto_model,
38+
const class_hierarchyt &class_hierarchy);
39+
3240
void remove_virtual_functions(
3341
symbol_table_baset &symbol_table,
3442
goto_functionst &goto_functions);
3543

36-
/// Remove virtual functions from one function.
37-
/// May change the location numbers in `function`.
38-
/// \param function: function from which virtual functions should be converted
39-
/// to explicit dispatch tables.
44+
void remove_virtual_functions(
45+
symbol_table_baset &symbol_table,
46+
goto_functionst &goto_functions,
47+
const class_hierarchyt &class_hierarchy);
48+
4049
void remove_virtual_functions(goto_model_functiont &function);
4150

51+
void remove_virtual_functions(
52+
goto_model_functiont &function,
53+
const class_hierarchyt &class_hierarchy);
54+
4255
/// Specifies remove_virtual_function's behaviour when the actual supplied
4356
/// parameter does not match any of the possible callee types
4457
enum class virtual_dispatch_fallback_actiont

0 commit comments

Comments
 (0)