CBMC
local_control_flow_history.h
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Abstract Interpretation
4 
5 Author: Martin Brain, martin.brain@cs.ox.ac.uk
6 
7 \*******************************************************************/
8 
11 
12 #ifndef CPROVER_ANALYSES_LOCAL_CONTROL_FLOW_HISTORY_H
13 #define CPROVER_ANALYSES_LOCAL_CONTROL_FLOW_HISTORY_H
14 
15 #include "ai_history.h"
16 
21 
24 {
25 public:
29  typedef std::shared_ptr<const local_control_flow_decisiont> lcfd_ptrt;
30  lcfd_ptrt previous; // null at the start of the function
31 
33  : branch_location(loc), branch_taken(taken), previous(ptr)
34  {
35  }
36 
37  bool operator<(const local_control_flow_decisiont &op) const;
38  bool operator==(const local_control_flow_decisiont &op) const;
39 };
40 
44 template <bool track_forward_jumps, bool track_backward_jumps>
46 {
47 protected:
49 
53 
54  // A repeating idiom -- can cast from interface type to this type
55  // caller's responsibility to ensure correct types
56  std::shared_ptr<const local_control_flow_historyt<
57  track_forward_jumps,
58  track_backward_jumps>>
60  {
61  PRECONDITION(in != nullptr);
62  auto tmp = std::dynamic_pointer_cast<const local_control_flow_historyt<
63  track_forward_jumps,
64  track_backward_jumps>>(in);
65  PRECONDITION(tmp != nullptr);
66  return tmp;
67  }
68 
69 public:
70  // nullptr denotes this is the "merge all other CFG paths" node
71  bool is_path_merge_history(void) const
72  {
73  return control_flow_decision_history == nullptr;
74  }
75 
76  // Set to 0 to disable but be aware that this may well diverge
77  // and not terminate
79  {
80  return max_histories_per_location != 0;
81  }
82 
84  : ai_history_baset(loc),
85  current_loc(loc),
87  std::make_shared<local_control_flow_decisiont>(loc, true, nullptr)),
89  {
90  }
91 
92  local_control_flow_historyt(locationt loc, lcfd_ptrt hist, size_t max_hist)
93  : ai_history_baset(loc),
94  current_loc(loc),
97  {
98  }
99 
101  : ai_history_baset(loc),
102  current_loc(loc),
104  std::make_shared<local_control_flow_decisiont>(loc, true, nullptr)),
106  {
107  }
108 
111  &old)
116  {
117  }
118 
120  locationt to,
121  const trace_sett &others,
122  trace_ptrt caller_hist) const override;
123 
124  bool operator<(const ai_history_baset &op) const override;
125  bool operator==(const ai_history_baset &op) const override;
126 
127  const locationt &current_location(void) const override
128  {
129  return current_loc;
130  }
131 
132  // If there is no history, then it is because we have merged
133  // If we are merging control flow histories then we should probably
134  // also widen on domain merge so that analysis converges faster.
135  bool should_widen(const ai_history_baset &other) const override
136  {
137  return is_path_merge_history();
138  }
139 
140  void output(std::ostream &out) const override;
141 };
142 
143 // Sets the kind of jumps to track and the max number of histories per location
145 {
146 protected:
150 
151 public:
153  bool track_f,
154  bool track_b,
155  size_t max_hist)
156  : track_forward_jumps(track_f),
157  track_backward_jumps(track_b),
159  {
160  }
161 
163  {
165  {
167  {
168  // All local control flow branches
169  return std::make_shared<local_control_flow_historyt<true, true>>(
171  }
172  else
173  {
174  // "Path sensitive" but merge loops eagerly
175  return std::make_shared<local_control_flow_historyt<true, false>>(
177  }
178  }
179  else
180  {
182  {
183  // Loop unwinding but merge branches eagerly
184  return std::make_shared<local_control_flow_historyt<false, true>>(
186  }
187  else
188  {
189  // Ignore all branches. Same effect as ahistorical but at more cost???
190  return std::make_shared<local_control_flow_historyt<false, false>>(
192  }
193  }
194  UNREACHABLE;
195  }
196 
198  {
199  // Pointer is reference counted.
200  }
201 };
202 
203 #endif // CPROVER_ANALYSES_LOCAL_CONTROL_FLOW_HISTORY_H
Abstract Interpretation history.
A history object is an abstraction / representation of the control-flow part of a set of traces.
Definition: ai_history.h:37
std::shared_ptr< const ai_history_baset > trace_ptrt
History objects are intended to be immutable so they can be shared to reduce memory overhead.
Definition: ai_history.h:43
std::pair< step_statust, trace_ptrt > step_returnt
Definition: ai_history.h:88
goto_programt::const_targett locationt
Definition: ai_history.h:39
std::set< trace_ptrt, compare_historyt > trace_sett
Definition: ai_history.h:79
As more detailed histories can get complex (for example, nested loops or deep, mutually recursive cal...
Definition: ai_history.h:242
Records all local control-flow decisions up to a limit of number of histories per location.
local_control_flow_decisiont(locationt loc, bool taken, lcfd_ptrt ptr)
std::shared_ptr< const local_control_flow_decisiont > lcfd_ptrt
bool operator<(const local_control_flow_decisiont &op) const
bool operator==(const local_control_flow_decisiont &op) const
ai_history_baset::locationt locationt
ai_history_baset::trace_ptrt epoch(ai_history_baset::locationt l) override
Creates a new history from the given starting point.
local_control_flow_history_factoryt(bool track_f, bool track_b, size_t max_hist)
Whether we track forwards and / or backwards jumps is compile-time fixed as it does not need to be va...
bool operator<(const ai_history_baset &op) const override
The order for history_sett.
bool should_widen(const ai_history_baset &other) const override
Domains with a substantial height may need to widen when merging this method allows the history to pr...
void output(std::ostream &out) const override
bool operator==(const ai_history_baset &op) const override
History objects should be comparable.
local_control_flow_decisiont::lcfd_ptrt lcfd_ptrt
local_control_flow_historyt(locationt loc, size_t max_hist)
std::shared_ptr< const local_control_flow_historyt< track_forward_jumps, track_backward_jumps > > to_local_control_flow_history(trace_ptrt in) const
const locationt & current_location(void) const override
The current location in the history, used to compute the transformer POSTCONDITION(return value is de...
step_returnt step(locationt to, const trace_sett &others, trace_ptrt caller_hist) const override
Step creates a new history by advancing the current one to location "to" It is given the set of all o...
local_control_flow_historyt(locationt loc, lcfd_ptrt hist, size_t max_hist)
local_control_flow_historyt(const local_control_flow_historyt< track_forward_jumps, track_backward_jumps > &old)
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:525
#define PRECONDITION(CONDITION)
Definition: invariant.h:463