cprover
lift_clinit_calls.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Static initializer call lifting
4 
5 Author: Diffblue Ltd.
6 
7 \*******************************************************************/
8 
10 
11 #include "lift_clinit_calls.h"
12 
14 
15 #include <util/expr_iterator.h>
16 
17 #include <algorithm>
18 
20 {
21  // 1. Gather any clinit calls present in `input`:
22  std::vector<symbol_exprt> clinit_wrappers_called;
23 
24  for(auto it = input.depth_begin(), itend = input.depth_end(); it != itend;
25  ++it)
26  {
27  if(const auto code = expr_try_dynamic_cast<codet>(*it))
28  {
29  if(code->get_statement() == ID_function_call)
30  {
31  if(
32  const auto callee = expr_try_dynamic_cast<symbol_exprt>(
34  {
35  if(is_clinit_wrapper_function(callee->get_identifier()))
36  {
37  clinit_wrappers_called.push_back(*callee);
38  // Replace call with skip:
39  it.mutate() = code_skipt();
40  }
41  }
42  }
43  }
44  }
45 
46  if(clinit_wrappers_called.empty())
47  return input;
48 
49  // 2. Unique, such that each clinit method is only called once:
50  std::sort(clinit_wrappers_called.begin(), clinit_wrappers_called.end());
51  auto delete_after =
52  std::unique(clinit_wrappers_called.begin(), clinit_wrappers_called.end());
53  clinit_wrappers_called.erase(delete_after, clinit_wrappers_called.end());
54 
55  // 3. Lift static init calls to top of function:
56  code_blockt result;
57  for(const auto &callee : clinit_wrappers_called)
58  {
59  code_function_callt new_call(callee);
60  // Nuke the source location, now that the call doesn't really relate to any
61  // one particular line:
62  new_call.function().drop_source_location();
63  result.add(new_call);
64  }
65 
66  result.add(std::move(input));
67 
68  return std::move(result);
69 }
java_static_initializers.h
code_blockt
A codet representing sequential composition of program statements.
Definition: std_code.h:170
lift_clinit_calls
codet lift_clinit_calls(codet input)
file Static initializer call lifting
Definition: lift_clinit_calls.cpp:19
exprt::depth_begin
depth_iteratort depth_begin()
Definition: expr.cpp:331
code_function_callt
codet representation of a function call statement.
Definition: std_code.h:1183
to_code_function_call
const code_function_callt & to_code_function_call(const codet &code)
Definition: std_code.h:1294
code_blockt::add
void add(const codet &code)
Definition: std_code.h:208
exprt::drop_source_location
void drop_source_location()
Definition: expr.h:264
code_skipt
A codet representing a skip statement.
Definition: std_code.h:270
expr_iterator.h
Forward depth-first search iterators These iterators' copy operations are expensive,...
lift_clinit_calls.h
exprt::depth_end
depth_iteratort depth_end()
Definition: expr.cpp:333
is_clinit_wrapper_function
bool is_clinit_wrapper_function(const irep_idt &function_id)
Check if function_id is a clinit wrapper.
Definition: java_static_initializers.cpp:78
code_function_callt::function
exprt & function()
Definition: std_code.h:1218
codet
Data structure for representing an arbitrary statement in a program.
Definition: std_code.h:35