Skip to content

Commit 673e247

Browse files
zhixing-xutautschnig
authored andcommitted
Refine data dependency across function calls
When generating dependences for a parameter in a function call, its data dependence node is set to be the line this function call happens. The result is unrelated variables are pulled into the dependence chain. The fix does a 1-1 mapping between the symbols of function call parameters and the symbols of the arguments given for the call.
1 parent bbb1ce8 commit 673e247

File tree

5 files changed

+95
-14
lines changed

5 files changed

+95
-14
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
void bar(int a, int b)
2+
{
3+
int result = b;
4+
}
5+
6+
void main()
7+
{
8+
int a = 1;
9+
int b = 2;
10+
int c = 3;
11+
bar(a, b + c);
12+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
CORE
2+
main.c
3+
--dependence-graph --show
4+
activate-multi-line-match
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
\/\/ ([0-9]+).*\n.*b = 2;(.*\n)*Data dependencies: (([0-9]+,\1)|(\1,[0-9]+))\n(.*\n){2,3}.*result = b
8+
\/\/ ([0-9]+).*\n.*c = 3;(.*\n)*Data dependencies: (([0-9]+,\1)|(\1,[0-9]+))\n(.*\n){2,3}.*result = b
9+
--
10+
^warning: ignoring
11+
--
12+
13+
The two regular expressions above match output portions like shown below (with
14+
<N> being a location number). The intention is to check whether a function
15+
parameter in the callee correctly depends on the caller-provided argument.
16+
17+
// 3 file main.c line 11 function main
18+
b = 2;
19+
...
20+
**** 12 file main.c line 5 function bar
21+
Data dependencies: (<N>,...)|(...,<N>)
22+
23+
// 12 file main.c line 5 function bar
24+
result = b;
25+
26+
The second regex matches for c.

src/analyses/goto_rw.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,23 @@ void rw_range_sett::add(
493493

494494
static_cast<range_domaint&>(*entry->second).push_back(
495495
{range_start, range_end});
496+
497+
// add to the single expression read set
498+
if(mode == get_modet::READ && expr_r_range_set.has_value())
499+
{
500+
objectst::iterator expr_entry =
501+
expr_r_range_set
502+
->insert(
503+
std::pair<const irep_idt &, std::unique_ptr<range_domain_baset>>(
504+
identifier, nullptr))
505+
.first;
506+
507+
if(expr_entry->second == nullptr)
508+
expr_entry->second = util_make_unique<range_domaint>();
509+
510+
static_cast<range_domaint &>(*expr_entry->second)
511+
.push_back({range_start, range_end});
512+
}
496513
}
497514

498515
void rw_range_sett::get_objects_rec(

src/analyses/goto_rw.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,7 @@ class rw_range_sett
121121

122122
virtual ~rw_range_sett();
123123

124-
explicit rw_range_sett(const namespacet &_ns):
125-
ns(_ns)
124+
explicit rw_range_sett(const namespacet &_ns) : ns(_ns)
126125
{
127126
}
128127

@@ -136,6 +135,21 @@ class rw_range_sett
136135
return w_range_set;
137136
}
138137

138+
/// Enable maintaining a read set for a single expression
139+
void enable_expr_read_set()
140+
{
141+
expr_r_range_set = objectst{};
142+
}
143+
144+
/// Obtain the read set for a single expression. Requires a prior call to
145+
/// \ref enable_expr_read_set.
146+
objectst fetch_expr_read_set()
147+
{
148+
objectst result = std::move(*expr_r_range_set);
149+
expr_r_range_set.reset();
150+
return result;
151+
}
152+
139153
const range_domaint &get_ranges(objectst::const_iterator it) const
140154
{
141155
PRECONDITION(dynamic_cast<range_domaint*>(it->second.get())!=nullptr);
@@ -167,6 +181,7 @@ class rw_range_sett
167181
const namespacet &ns;
168182

169183
objectst r_range_set, w_range_set;
184+
optionalt<objectst> expr_r_range_set;
170185

171186
virtual void get_objects_rec(
172187
get_modet mode,

src/analyses/reaching_definitions.cpp

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -211,22 +211,33 @@ void rd_range_domaint::transform_function_call(
211211
++it;
212212
}
213213

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

218-
for(const auto &param : code_type.parameters())
216+
const code_typet &code_type = to_code_type(ns.lookup(function_to).type);
217+
PRECONDITION(code_type.parameters().size() == code.arguments().size());
218+
auto arg_it = code.arguments().begin();
219+
for(const auto &parameter : code_type.parameters())
219220
{
220-
const irep_idt &identifier=param.get_identifier();
221+
const irep_idt &identifier = parameter.get_identifier();
221222

222-
if(identifier.empty())
223-
continue;
223+
// get read set of the argument
224+
rw_set.enable_expr_read_set();
225+
rw_set.get_objects_rec(
226+
function_from, from, rw_range_sett::get_modet::READ, *arg_it);
224227

225-
auto param_bits = pointer_offset_bits(param.type(), ns);
226-
if(param_bits.has_value())
227-
gen(from, identifier, 0, to_range_spect(*param_bits));
228-
else
229-
gen(from, identifier, 0, -1);
228+
for(const auto &r_set_pair : rw_set.fetch_expr_read_set())
229+
{
230+
const rd_range_domaint::ranges_at_loct &w_ranges =
231+
rd[from].get(r_set_pair.first);
232+
for(const auto &w_range : w_ranges)
233+
{
234+
for(const auto &wr : w_range.second)
235+
gen(w_range.first, identifier, wr.first, wr.second);
236+
}
237+
}
238+
239+
// next argument/parameter pair
240+
++arg_it;
230241
}
231242
}
232243
else

0 commit comments

Comments
 (0)