Skip to content

Improvement for data dependency across function calls [blocks: #2871] #2707

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions regression/goto-analyzer/dependence-graph13/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
void bar(int a, int b)
{
int result = b;
}

void main()
{
int a = 1;
int b = 2;
int c = 3;
bar(a, b + c);
}
26 changes: 26 additions & 0 deletions regression/goto-analyzer/dependence-graph13/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
CORE
main.c
--dependence-graph --show
activate-multi-line-match
^EXIT=0$
^SIGNAL=0$
\/\/ ([0-9]+).*\n.*b = 2;(.*\n)*Data dependencies: (([0-9]+,\1)|(\1,[0-9]+))\n(.*\n){2,3}.*result = b
\/\/ ([0-9]+).*\n.*c = 3;(.*\n)*Data dependencies: (([0-9]+,\1)|(\1,[0-9]+))\n(.*\n){2,3}.*result = b
--
^warning: ignoring
--

The two regular expressions above match output portions like shown below (with
<N> being a location number). The intention is to check whether a function
parameter in the callee correctly depends on the caller-provided argument.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This description comment is really helpful, thanks!


// 3 file main.c line 11 function main
b = 2;
...
**** 12 file main.c line 5 function bar
Data dependencies: (<N>,...)|(...,<N>)

// 12 file main.c line 5 function bar
result = b;

The second regex matches for c.
17 changes: 17 additions & 0 deletions src/analyses/goto_rw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,23 @@ void rw_range_sett::add(

static_cast<range_domaint&>(*entry->second).push_back(
{range_start, range_end});

// add to the single expression read set
if(mode == get_modet::READ && expr_r_range_set.has_value())
{
objectst::iterator expr_entry =
expr_r_range_set
->insert(
std::pair<const irep_idt &, std::unique_ptr<range_domain_baset>>(
identifier, nullptr))
.first;

if(expr_entry->second == nullptr)
expr_entry->second = util_make_unique<range_domaint>();

static_cast<range_domaint &>(*expr_entry->second)
.push_back({range_start, range_end});
}
}

void rw_range_sett::get_objects_rec(
Expand Down
19 changes: 17 additions & 2 deletions src/analyses/goto_rw.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,7 @@ class rw_range_sett

virtual ~rw_range_sett();

explicit rw_range_sett(const namespacet &_ns):
ns(_ns)
explicit rw_range_sett(const namespacet &_ns) : ns(_ns)
{
}

Expand All @@ -136,6 +135,21 @@ class rw_range_sett
return w_range_set;
}

/// Enable maintaining a read set for a single expression
void enable_expr_read_set()
{
expr_r_range_set = objectst{};
}

/// Obtain the read set for a single expression. Requires a prior call to
/// \ref enable_expr_read_set.
objectst fetch_expr_read_set()
{
objectst result = std::move(*expr_r_range_set);
expr_r_range_set.reset();
return result;
}

const range_domaint &get_ranges(objectst::const_iterator it) const
{
PRECONDITION(dynamic_cast<range_domaint*>(it->second.get())!=nullptr);
Expand Down Expand Up @@ -167,6 +181,7 @@ class rw_range_sett
const namespacet &ns;

objectst r_range_set, w_range_set;
optionalt<objectst> expr_r_range_set;

virtual void get_objects_rec(
get_modet mode,
Expand Down
35 changes: 23 additions & 12 deletions src/analyses/reaching_definitions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,22 +211,33 @@ void rd_range_domaint::transform_function_call(
++it;
}

const symbol_exprt &fn_symbol_expr=to_symbol_expr(code.function());
const code_typet &code_type=
to_code_type(ns.lookup(fn_symbol_expr.get_identifier()).type);
rw_range_set_value_sett rw_set(ns, rd.get_value_sets());

for(const auto &param : code_type.parameters())
const code_typet &code_type = to_code_type(ns.lookup(function_to).type);
PRECONDITION(code_type.parameters().size() == code.arguments().size());
auto arg_it = code.arguments().begin();
for(const auto &parameter : code_type.parameters())
{
const irep_idt &identifier=param.get_identifier();
const irep_idt &identifier = parameter.get_identifier();

if(identifier.empty())
continue;
// get read set of the argument
rw_set.enable_expr_read_set();
rw_set.get_objects_rec(
function_from, from, rw_range_sett::get_modet::READ, *arg_it);

auto param_bits = pointer_offset_bits(param.type(), ns);
if(param_bits.has_value())
gen(from, identifier, 0, to_range_spect(*param_bits));
else
gen(from, identifier, 0, -1);
for(const auto &r_set_pair : rw_set.fetch_expr_read_set())
{
const rd_range_domaint::ranges_at_loct &w_ranges =
rd[from].get(r_set_pair.first);
for(const auto &w_range : w_ranges)
{
for(const auto &wr : w_range.second)
gen(w_range.first, identifier, wr.first, wr.second);
}
}

// next argument/parameter pair
++arg_it;
}
}
else
Expand Down