CBMC
Loading...
Searching...
No Matches
reaching_definitions.h
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Range-based reaching definitions analysis (following Field-
4 Sensitive Program Dependence Analysis, Litvak et al., FSE 2010)
5
6Author: Michael Tautschnig
7
8Date: February 2013
9
10\*******************************************************************/
11
24
25#ifndef CPROVER_ANALYSES_REACHING_DEFINITIONS_H
26#define CPROVER_ANALYSES_REACHING_DEFINITIONS_H
27
28#include <util/threeval.h>
29
30#include "ai.h"
31#include "goto_rw.h"
32
33class dirtyt; // IWYU pragma: keep
35
39template<typename V>
41{
42public:
43 const V &get(const std::size_t value_index) const
44 {
45 PRECONDITION(value_index < values.size());
46 return values[value_index]->first;
47 }
48
49 std::size_t add(const V &value)
50 {
51 inner_mapt &m=value_map[value.identifier];
52
53 std::pair<typename inner_mapt::iterator, bool> entry=
54 m.insert(std::make_pair(value, values.size()));
55
56 if(entry.second)
57 values.push_back(entry.first);
58
59 return entry.first->second;
60 }
61
62 void clear()
63 {
64 value_map.clear();
65 values.clear();
66 }
67
68protected:
69 typedef typename std::map<V, std::size_t> inner_mapt;
74 std::vector<typename inner_mapt::const_iterator> values;
78 std::unordered_map<irep_idt, inner_mapt> value_map;
79};
80
108
111inline bool operator<(
112 const reaching_definitiont &a,
113 const reaching_definitiont &b)
114{
116 return true;
118 return false;
119
121 return a.bit_begin.is_unknown();
122
123 if(!a.bit_begin.is_unknown())
124 {
125 if(a.bit_begin < b.bit_begin)
126 return true;
127 if(b.bit_begin < a.bit_begin)
128 return false;
129 }
130
131 if(a.bit_end.is_unknown() != b.bit_end.is_unknown())
132 return a.bit_end.is_unknown();
133
134 if(!a.bit_end.is_unknown())
135 {
136 if(a.bit_end < b.bit_end)
137 return true;
138 if(b.bit_end < a.bit_end)
139 return false;
140 }
141
142 // we do not expect comparison of unrelated definitions
143 // as this operator< is only used in sparse_bitvector_analysist
144 INVARIANT(
145 a.identifier == b.identifier, "comparison of unrelated definitions");
146
147 return false;
148}
149
157{
158public:
169
182 void transform(
183 const irep_idt &function_from,
184 trace_ptrt trace_from,
185 const irep_idt &function_to,
186 trace_ptrt trace_to,
187 ai_baset &ai,
188 const namespacet &ns) final override;
189
190 void output(
191 std::ostream &out,
192 const ai_baset &,
193 const namespacet &) const final override
194 {
195 output(out);
196 }
197
198 void make_top() final override
199 {
200 values.clear();
201 if(bv_container)
202 bv_container->clear();
203 has_values=tvt(true);
204 }
205
206 void make_bottom() final override
207 {
208 values.clear();
209 if(bv_container)
210 bv_container->clear();
211 has_values=tvt(false);
212 }
213
214 bool is_top() const override final
215 {
216 DATA_INVARIANT(!has_values.is_true() || values.empty(),
217 "If domain is top, the value map must be empty");
218 return has_values.is_true();
219 }
220
221 bool is_bottom() const override final
222 {
223 DATA_INVARIANT(!has_values.is_false() || values.empty(),
224 "If domain is bottom, the value map must be empty");
225 return has_values.is_false();
226 }
227
240 bool merge(const rd_range_domaint &other, trace_ptrt from, trace_ptrt to);
241
242 bool merge_shared(
243 const rd_range_domaint &other,
244 locationt from,
245 locationt to,
246 const namespacet &ns);
247
248 // each element x represents a range of bits [x.first, x.second)
249 typedef std::multimap<range_spect, range_spect> rangest;
250 typedef std::map<locationt, rangest, goto_programt::target_less_than>
252
253 const ranges_at_loct &get(const irep_idt &identifier) const;
254 void clear_cache(const irep_idt &identifier) const
255 {
256 export_cache[identifier].clear();
257 }
258
259private:
264
273
274 typedef std::set<std::size_t> values_innert;
275 typedef std::map<irep_idt, values_innert> valuest;
282
283 typedef std::map<irep_idt, ranges_at_loct> export_cachet;
296
297 void populate_cache(const irep_idt &identifier) const;
298
299 void transform_dead(
300 const namespacet &ns,
301 locationt from);
303 const namespacet &ns,
306 const namespacet &ns,
307 const irep_idt &function_from,
308 locationt from,
309 const irep_idt &function_to,
312 const namespacet &ns,
313 const irep_idt &function_from,
314 locationt from,
315 const irep_idt &function_to,
316 locationt to,
318 void transform_assign(
319 const namespacet &ns,
320 locationt from,
321 const irep_idt &function_to,
322 locationt to,
324
325 void kill(
326 const irep_idt &identifier,
327 const range_spect &range_start,
328 const range_spect &range_end);
329 void kill_inf(
330 const irep_idt &identifier,
331 const range_spect &range_start);
332 bool gen(
333 locationt from,
334 const irep_idt &identifier,
335 const range_spect &range_start,
336 const range_spect &range_end);
337
338 void output(std::ostream &out) const;
339
340 bool merge_inner(
341 values_innert &dest,
342 const values_innert &other);
343
345};
346
348 public concurrency_aware_ait<rd_range_domaint>,
349 public sparse_bitvector_analysist<reaching_definitiont>
350{
351public:
352 // constructor
354
356
357 void initialize(const goto_functionst &goto_functions) override;
358
360 {
362 return *value_sets;
363 }
364
366 {
368 return *is_threaded;
369 }
370
371 const dirtyt &get_is_dirty() const
372 {
374 return *is_dirty;
375 }
376
377protected:
379 std::unique_ptr<value_setst> value_sets;
380 std::unique_ptr<is_threadedt> is_threaded;
381 std::unique_ptr<dirtyt> is_dirty;
382};
383
384#endif // CPROVER_ANALYSES_REACHING_DEFINITIONS_H
Abstract Interpretation.
This is the basic interface of the abstract interpreter with default implementations of the core func...
Definition ai.h:117
ai_domain_baset()
The constructor is expected to produce 'false' or 'bottom' A default constructor is not part of the d...
Definition ai_domain.h:58
ai_history_baset::trace_ptrt trace_ptrt
Definition ai_domain.h:73
goto_programt::const_targett locationt
Definition ai_domain.h:72
Dirty variables are ones which have their address taken so we can't reliably work out where they may ...
Definition dirty.h:28
A collection of goto functions.
instructiont::target_less_than target_less_than
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
Data type to describe upper and lower bounds of the range of bits that a read or write access may aff...
Definition goto_rw.h:63
bool is_unknown() const
Definition goto_rw.h:76
Because the class is inherited from ai_domain_baset, its instance represents an element of a domain o...
std::map< irep_idt, ranges_at_loct > export_cachet
void populate_cache(const irep_idt &identifier) const
Given the passed variable name identifier it collects data from bv_container for each ID in values[id...
export_cachet export_cache
It is a helper data structure.
void output(std::ostream &out, const ai_baset &, const namespacet &) const final override
void make_top() final override
all states – the analysis doesn't use this directly (see make_entry) and domains may refuse to implem...
void kill_inf(const irep_idt &identifier, const range_spect &range_start)
void transform_dead(const namespacet &ns, locationt from)
Computes an instance obtained from a *this by transformation over DEAD v GOTO instruction.
void transform_start_thread(const namespacet &ns, reaching_definitions_analysist &rd)
bool is_top() const override final
const ranges_at_loct & get(const irep_idt &identifier) const
void clear_cache(const irep_idt &identifier) const
bool is_bottom() const override final
sparse_bitvector_analysist< reaching_definitiont > *const bv_container
It points to the actual reaching definitions data of individual program variables.
void transform_function_call(const namespacet &ns, const irep_idt &function_from, locationt from, const irep_idt &function_to, reaching_definitions_analysist &rd)
rd_range_domaint(sparse_bitvector_analysist< reaching_definitiont > *_bv_container, message_handlert &message_handler)
bool merge(const rd_range_domaint &other, trace_ptrt from, trace_ptrt to)
Implements the "join" operation of two instances *this and other.
void transform_end_function(const namespacet &ns, const irep_idt &function_from, locationt from, const irep_idt &function_to, locationt to, reaching_definitions_analysist &rd)
void make_bottom() final override
no states
void transform_assign(const namespacet &ns, locationt from, const irep_idt &function_to, locationt to, reaching_definitions_analysist &rd)
bool merge_inner(values_innert &dest, const values_innert &other)
std::multimap< range_spect, range_spect > rangest
bool gen(locationt from, const irep_idt &identifier, const range_spect &range_start, const range_spect &range_end)
A utility function which updates internal data structures by inserting a new reaching definition reco...
void kill(const irep_idt &identifier, const range_spect &range_start, const range_spect &range_end)
std::map< locationt, rangest, goto_programt::target_less_than > ranges_at_loct
tvt has_values
This (three value logic) flag determines, whether the instance represents top, bottom,...
void transform(const irep_idt &function_from, trace_ptrt trace_from, const irep_idt &function_to, trace_ptrt trace_to, ai_baset &ai, const namespacet &ns) final override
Computes an instance obtained from the instance *this by transformation over a GOTO instruction refer...
std::map< irep_idt, values_innert > valuest
valuest values
It is an ordered map from program variable names to IDs of reaching_definitiont instances stored in m...
bool merge_shared(const rd_range_domaint &other, locationt from, locationt to, const namespacet &ns)
std::set< std::size_t > values_innert
message_handlert & message_handler
std::unique_ptr< is_threadedt > is_threaded
const is_threadedt & get_is_threaded() const
std::unique_ptr< dirtyt > is_dirty
std::unique_ptr< value_setst > value_sets
reaching_definitions_analysist(const namespacet &_ns, message_handlert &)
void initialize(const goto_functionst &goto_functions) override
Initialize all the abstract states for a whole program.
An instance of this class provides an assignment of unique numeric ID to each inserted reaching_defin...
std::map< V, std::size_t > inner_mapt
const V & get(const std::size_t value_index) const
std::vector< typename inner_mapt::const_iterator > values
It is a map from an ID to the corresponding reaching_definitiont instance inside the map value_map.
std::unordered_map< irep_idt, inner_mapt > value_map
A map from names of program variables to a set of pairs (reaching_definitiont, ID).
std::size_t add(const V &value)
Definition threeval.h:20
bool operator<(const reaching_definitiont &a, const reaching_definitiont &b)
In order to use instances of this structure as keys in ordered containers, such as std::map,...
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition invariant.h:534
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
Identifies a GOTO instruction where a given variable is defined (i.e.
range_spect bit_begin
The two integers below define a range of bits (i.e.
ai_domain_baset::locationt definition_at
The iterator to the GOTO instruction where the variable has been written to.
reaching_definitiont(const irep_idt &identifier, const ai_domain_baset::locationt &definition_at, const range_spect &bit_begin, const range_spect &bit_end)
irep_idt identifier
The name of the variable which was defined.
dstringt irep_idt