Skip to content

Commit afe32b7

Browse files
author
martin
committed
Refactor the methods that access "the abstract domain at a location".
This allows us to be a lot more flexible about the relationship between location and domain rather than assuming it is a 1-to-1 map.
1 parent 709b45f commit afe32b7

File tree

5 files changed

+48
-29
lines changed

5 files changed

+48
-29
lines changed

src/analyses/ai.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ void ai_baset::output(
5050
out << "**** " << i_it->location_number << " "
5151
<< i_it->source_location << "\n";
5252

53-
find_state(i_it).output(out, *this, ns);
53+
abstract_state_before(i_it)->output(out, *this, ns);
5454
out << "\n";
5555
#if 1
5656
goto_program.output_instruction(ns, identifier, out, *i_it);
@@ -101,7 +101,8 @@ jsont ai_baset::output_json(
101101
json_numbert(std::to_string(i_it->location_number));
102102
location["sourceLocation"]=
103103
json_stringt(i_it->source_location.as_string());
104-
location["abstractState"]=find_state(i_it).output_json(*this, ns);
104+
location["abstractState"] =
105+
abstract_state_before(i_it)->output_json(*this, ns);
105106

106107
// Ideally we need output_instruction_json
107108
std::ostringstream out;
@@ -162,7 +163,7 @@ xmlt ai_baset::output_xml(
162163
"source_location",
163164
i_it->source_location.as_string());
164165

165-
location.new_element(find_state(i_it).output_xml(*this, ns));
166+
location.new_element(abstract_state_before(i_it)->output_xml(*this, ns));
166167

167168
// Ideally we need output_instruction_xml
168169
std::ostringstream out;

src/analyses/ai.h

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,23 @@ class ai_baset
8282
finalize();
8383
}
8484

85+
/// Accessing individual domains at particular locations
86+
/// (without needing to know what kind of domain or history is used)
87+
/// A pointer to a copy as the method should be const and
88+
/// there are some non-trivial cases including merging domains, etc.
89+
/// Intended for users of the abstract interpreter; don't use internally.
90+
8591
/// Returns the abstract state before the given instruction
86-
virtual const ai_domain_baset & abstract_state_before(
87-
goto_programt::const_targett t) const = 0;
92+
/// PRECONDITION(l is dereferenceable)
93+
virtual std::unique_ptr<statet> abstract_state_before(locationt l) const = 0;
8894

8995
/// Returns the abstract state after the given instruction
90-
virtual const ai_domain_baset & abstract_state_after(
91-
goto_programt::const_targett t) const
96+
virtual std::unique_ptr<statet> abstract_state_after(locationt l) const
9297
{
93-
return abstract_state_before(std::next(t));
98+
/// PRECONDITION(l is dereferenceable && std::next(l) is dereferenceable)
99+
/// Check relies on a DATA_INVARIANT of goto_programs
100+
INVARIANT(!l->is_end_function(), "No state after the last instruction");
101+
return abstract_state_before(std::next(l));
94102
}
95103

96104
virtual void clear()
@@ -304,10 +312,17 @@ class ait:public ai_baset
304312
return it->second;
305313
}
306314

307-
const ai_domain_baset & abstract_state_before(
308-
goto_programt::const_targett t) const override
315+
std::unique_ptr<statet> abstract_state_before(locationt t) const override
309316
{
310-
return (*this)[t];
317+
typename state_mapt::const_iterator it = state_map.find(t);
318+
if(it == state_map.end())
319+
{
320+
std::unique_ptr<statet> d = util_make_unique<domainT>();
321+
CHECK_RETURN(d->is_bottom());
322+
return d;
323+
}
324+
325+
return util_make_unique<domainT>(it->second);
311326
}
312327

313328
void clear() override

src/goto-analyzer/static_simplifier.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ bool static_simplifier(
6565

6666
if(i_it->is_assert())
6767
{
68-
bool unchanged=
69-
ai.abstract_state_before(i_it).ai_simplify(i_it->guard, ns);
68+
bool unchanged =
69+
ai.abstract_state_before(i_it)->ai_simplify(i_it->guard, ns);
7070

7171
if(unchanged)
7272
unmodified.asserts++;
@@ -75,8 +75,8 @@ bool static_simplifier(
7575
}
7676
else if(i_it->is_assume())
7777
{
78-
bool unchanged=
79-
ai.abstract_state_before(i_it).ai_simplify(i_it->guard, ns);
78+
bool unchanged =
79+
ai.abstract_state_before(i_it)->ai_simplify(i_it->guard, ns);
8080

8181
if(unchanged)
8282
unmodified.assumes++;
@@ -85,8 +85,8 @@ bool static_simplifier(
8585
}
8686
else if(i_it->is_goto())
8787
{
88-
bool unchanged=
89-
ai.abstract_state_before(i_it).ai_simplify(i_it->guard, ns);
88+
bool unchanged =
89+
ai.abstract_state_before(i_it)->ai_simplify(i_it->guard, ns);
9090

9191
if(unchanged)
9292
unmodified.gotos++;
@@ -102,11 +102,11 @@ bool static_simplifier(
102102
// <i=0, j=1> i=j
103103
// should simplify to i=1, not to 0=1.
104104

105-
bool unchanged_lhs=
106-
ai.abstract_state_before(i_it).ai_simplify_lhs(assign.lhs(), ns);
105+
bool unchanged_lhs =
106+
ai.abstract_state_before(i_it)->ai_simplify_lhs(assign.lhs(), ns);
107107

108-
bool unchanged_rhs=
109-
ai.abstract_state_before(i_it).ai_simplify(assign.rhs(), ns);
108+
bool unchanged_rhs =
109+
ai.abstract_state_before(i_it)->ai_simplify(assign.rhs(), ns);
110110

111111
if(unchanged_lhs && unchanged_rhs)
112112
unmodified.assigns++;
@@ -117,13 +117,13 @@ bool static_simplifier(
117117
{
118118
code_function_callt &fcall=to_code_function_call(i_it->code);
119119

120-
bool unchanged=
121-
ai.abstract_state_before(i_it).ai_simplify(fcall.function(), ns);
120+
bool unchanged =
121+
ai.abstract_state_before(i_it)->ai_simplify(fcall.function(), ns);
122122

123123
exprt::operandst &args=fcall.arguments();
124124

125125
for(auto &o : args)
126-
unchanged&=ai.abstract_state_before(i_it).ai_simplify(o, ns);
126+
unchanged &= ai.abstract_state_before(i_it)->ai_simplify(o, ns);
127127

128128
if(unchanged)
129129
unmodified.function_calls++;

src/goto-analyzer/static_verifier.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ bool static_verifier(
5555
continue;
5656

5757
exprt e(i_it->guard);
58-
const ai_domain_baset &domain(ai.abstract_state_before(i_it));
58+
auto dp = ai.abstract_state_before(i_it);
59+
const ai_domain_baset &domain(*dp);
5960
domain.ai_simplify(e, ns);
6061

6162
json_objectt &j=json_result.push_back().make_object();
@@ -104,7 +105,8 @@ bool static_verifier(
104105
continue;
105106

106107
exprt e(i_it->guard);
107-
const ai_domain_baset &domain(ai.abstract_state_before(i_it));
108+
auto dp = ai.abstract_state_before(i_it);
109+
const ai_domain_baset &domain(*dp);
108110
domain.ai_simplify(e, ns);
109111

110112
xmlt &x=xml_result.new_element("result");
@@ -160,7 +162,8 @@ bool static_verifier(
160162
continue;
161163

162164
exprt e(i_it->guard);
163-
const ai_domain_baset &domain(ai.abstract_state_before(i_it));
165+
auto dp = ai.abstract_state_before(i_it);
166+
const ai_domain_baset &domain(*dp);
164167
domain.ai_simplify(e, ns);
165168

166169
out << '[' << i_it->source_location.get_property_id()

src/goto-analyzer/unreachable_instructions.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ static void build_dead_map_from_ai(
5959
dead_mapt &dest)
6060
{
6161
forall_goto_program_instructions(it, goto_program)
62-
if(ai.abstract_state_before(it).is_bottom())
62+
if(ai.abstract_state_before(it)->is_bottom())
6363
dest.insert(std::make_pair(it->location_number, it));
6464
}
6565

@@ -418,7 +418,7 @@ std::unordered_set<irep_idt> compute_called_functions_from_ai(
418418

419419
const goto_programt &p = f_it->second.body;
420420

421-
if(!ai.abstract_state_before(p.instructions.begin()).is_bottom())
421+
if(!ai.abstract_state_before(p.instructions.begin())->is_bottom())
422422
called.insert(f_it->first);
423423
}
424424

0 commit comments

Comments
 (0)