Skip to content

Commit 7eb318e

Browse files
committed
Discover lexical scopes for anonymous variables
This enables tight variable scoping even when Java debug information is not available, which helps with analyses that benefit from DEAD instructions keeping their domains as small as possible.
1 parent 02aea58 commit 7eb318e

File tree

2 files changed

+90
-42
lines changed

2 files changed

+90
-42
lines changed

src/java_bytecode/java_bytecode_convert_method.cpp

Lines changed: 89 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,43 @@ code_blockt &java_bytecode_convert_methodt::get_or_create_block_for_pcrange(
692692
to_code(this_block_children[child_offset])).code());
693693
}
694694

695+
static void gather_symbol_live_ranges(
696+
unsigned pc,
697+
const exprt &e,
698+
std::map<irep_idt, java_bytecode_convert_methodt::variablet> &result)
699+
{
700+
if(e.id()==ID_symbol)
701+
{
702+
const auto &symexpr=to_symbol_expr(e);
703+
auto findit=
704+
result.insert({
705+
symexpr.get_identifier(),
706+
java_bytecode_convert_methodt::variablet()});
707+
auto &var=findit.first->second;
708+
if(findit.second)
709+
{
710+
var.symbol_expr=symexpr;
711+
var.start_pc=pc;
712+
var.length=1;
713+
}
714+
else
715+
{
716+
if(pc<var.start_pc)
717+
{
718+
var.length+=(var.start_pc-pc);
719+
var.start_pc=pc;
720+
}
721+
else
722+
{
723+
var.length=std::max(var.length, (pc-var.start_pc)+1);
724+
}
725+
}
726+
}
727+
else
728+
forall_operands(it, e)
729+
gather_symbol_live_ranges(pc, *it, result);
730+
}
731+
695732
/*******************************************************************\
696733
697734
Function: java_bytecode_convert_methodt::convert_instructions
@@ -1809,10 +1846,9 @@ codet java_bytecode_convert_methodt::convert_instructions(
18091846
// review successor computation of athrow!
18101847
code_blockt code;
18111848

1812-
// locals
1849+
// Add anonymous locals to the symtab:
18131850
for(const auto &var : used_local_names)
18141851
{
1815-
code.add(code_declt(var));
18161852
symbolt new_symbol;
18171853
new_symbol.name=var.get_identifier();
18181854
new_symbol.type=var.type();
@@ -1825,11 +1861,6 @@ codet java_bytecode_convert_methodt::convert_instructions(
18251861
new_symbol.is_lvalue=true;
18261862
symbol_table.add(new_symbol);
18271863
}
1828-
// temporaries
1829-
for(const auto &var : tmp_vars)
1830-
{
1831-
code.add(code_declt(var));
1832-
}
18331864

18341865
// Try to recover block structure as indicated in the local variable table:
18351866

@@ -1875,44 +1906,61 @@ codet java_bytecode_convert_methodt::convert_instructions(
18751906
start_new_block=address_pair.second.successors.size()>1;
18761907
}
18771908

1909+
// Find out where temporaries are used:
1910+
std::map<irep_idt, variablet> temporary_variable_live_ranges;
1911+
for(const auto &aentry : address_map)
1912+
gather_symbol_live_ranges(
1913+
aentry.first,
1914+
aentry.second.code,
1915+
temporary_variable_live_ranges);
1916+
1917+
std::vector<const variablet*> vars_to_process;
18781918
for(const auto &vlist : variables)
1879-
{
18801919
for(const auto &v : vlist)
1881-
{
1882-
if(v.is_parameter)
1883-
continue;
1884-
// Merge lexical scopes as far as possible to allow us to
1885-
// declare these variable scopes faithfully.
1886-
// Don't insert yet, as for the time being the blocks' only
1887-
// operands must be other blocks.
1888-
// The declarations will be inserted in the next pass instead.
1889-
get_or_create_block_for_pcrange(
1890-
root,
1891-
root_block,
1892-
v.start_pc,
1893-
v.start_pc+v.length,
1894-
std::numeric_limits<unsigned>::max(),
1895-
address_map);
1896-
}
1920+
vars_to_process.push_back(&v);
1921+
1922+
for(const auto &v : tmp_vars)
1923+
vars_to_process.push_back(
1924+
&temporary_variable_live_ranges.at(v.get_identifier()));
1925+
1926+
for(const auto &v : used_local_names)
1927+
vars_to_process.push_back(
1928+
&temporary_variable_live_ranges.at(v.get_identifier()));
1929+
1930+
for(const auto vp : vars_to_process)
1931+
{
1932+
const auto &v=*vp;
1933+
if(v.is_parameter)
1934+
continue;
1935+
// Merge lexical scopes as far as possible to allow us to
1936+
// declare these variable scopes faithfully.
1937+
// Don't insert yet, as for the time being the blocks' only
1938+
// operands must be other blocks.
1939+
// The declarations will be inserted in the next pass instead.
1940+
get_or_create_block_for_pcrange(
1941+
root,
1942+
root_block,
1943+
v.start_pc,
1944+
v.start_pc+v.length,
1945+
std::numeric_limits<unsigned>::max(),
1946+
address_map);
18971947
}
1898-
for(const auto &vlist : variables)
1948+
for(const auto vp : vars_to_process)
18991949
{
1900-
for(const auto &v : vlist)
1901-
{
1902-
if(v.is_parameter)
1903-
continue;
1904-
// Skip anonymous variables:
1905-
if(v.symbol_expr.get_identifier()==irep_idt())
1906-
continue;
1907-
auto &block=get_block_for_pcrange(
1908-
root,
1909-
root_block,
1910-
v.start_pc,
1911-
v.start_pc+v.length,
1912-
std::numeric_limits<unsigned>::max());
1913-
code_declt d(v.symbol_expr);
1914-
block.operands().insert(block.operands().begin(), d);
1915-
}
1950+
const auto &v=*vp;
1951+
if(v.is_parameter)
1952+
continue;
1953+
// Skip anonymous variables:
1954+
if(v.symbol_expr.get_identifier()==irep_idt())
1955+
continue;
1956+
auto &block=get_block_for_pcrange(
1957+
root,
1958+
root_block,
1959+
v.start_pc,
1960+
v.start_pc+v.length,
1961+
std::numeric_limits<unsigned>::max());
1962+
code_declt d(v.symbol_expr);
1963+
block.operands().insert(block.operands().begin(), d);
19161964
}
19171965

19181966
for(auto &block : root_block.operands())

src/java_bytecode/java_bytecode_convert_method_class.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ class java_bytecode_convert_methodt:public messaget
6363
typedef std::vector<local_variable_with_holest>
6464
local_variable_table_with_holest;
6565

66-
protected:
6766
class variablet
6867
{
6968
public:
@@ -75,6 +74,7 @@ class java_bytecode_convert_methodt:public messaget
7574
variablet() : symbol_expr(), is_parameter(false) {}
7675
};
7776

77+
protected:
7878
typedef std::vector<variablet> variablest;
7979
expanding_vector<variablest> variables;
8080
std::set<symbol_exprt> used_local_names;

0 commit comments

Comments
 (0)