CBMC
interrupt.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Interrupt Instrumentation
4 
5 Author: Daniel Kroening
6 
7 Date: September 2011
8 
9 \*******************************************************************/
10 
13 
14 #include "interrupt.h"
15 
16 #include <util/range.h>
17 #include <util/std_code.h>
18 
20 
21 #ifdef LOCAL_MAY
23 #endif
24 
25 #include "rw_set.h"
26 
28  const rw_set_baset &code_rw_set,
29  const rw_set_baset &isr_rw_set)
30 {
31  // R/W race?
32  for(const auto &r_entry : code_rw_set.r_entries)
33  {
34  if(isr_rw_set.has_w_entry(r_entry.first))
35  return true;
36  }
37 
38  return false;
39 }
40 
42  const rw_set_baset &code_rw_set,
43  const rw_set_baset &isr_rw_set)
44 {
45  // W/R or W/W?
46  for(const auto &w_entry : code_rw_set.w_entries)
47  {
48  if(isr_rw_set.has_r_entry(w_entry.first))
49  return true;
50 
51  if(isr_rw_set.has_w_entry(w_entry.first))
52  return true;
53  }
54 
55  return false;
56 }
57 
58 static void interrupt(
59  value_setst &value_sets,
60  const symbol_tablet &symbol_table,
61  const irep_idt &function_id,
62 #ifdef LOCAL_MAY
63  const goto_functionst::goto_functiont &goto_function,
64 #endif
65  goto_programt &goto_program,
66  const symbol_exprt &interrupt_handler,
67  const rw_set_baset &isr_rw_set)
68 {
69  namespacet ns(symbol_table);
70 
71  Forall_goto_program_instructions(i_it, goto_program)
72  {
73  goto_programt::instructiont &instruction=*i_it;
74 
75 #ifdef LOCAL_MAY
76  local_may_aliast local_may(goto_function);
77 #endif
78  rw_set_loct rw_set(
79  ns,
80  value_sets,
81  function_id,
82  i_it
83 #ifdef LOCAL_MAY
84  ,
85  local_may
86 #endif
87  ); // NOLINT(whitespace/parens)
88 
89  // potential race?
90  bool race_on_read=potential_race_on_read(rw_set, isr_rw_set);
91  bool race_on_write=potential_race_on_write(rw_set, isr_rw_set);
92 
93  if(!race_on_read && !race_on_write)
94  continue;
95 
96  // Insert the call to the ISR.
97  // We do before for races on Read, and before and after
98  // for races on Write.
99 
100  if(race_on_read || race_on_write)
101  {
102  goto_programt::instructiont original_instruction;
103  original_instruction.swap(instruction);
104 
105  const source_locationt &source_location =
106  original_instruction.source_location();
107 
108  code_function_callt isr_call(interrupt_handler);
109  isr_call.add_source_location()=source_location;
110 
111  goto_programt::targett t_goto=i_it;
112  goto_programt::targett t_call=goto_program.insert_after(t_goto);
113  goto_programt::targett t_orig=goto_program.insert_after(t_call);
114 
115  *t_goto = goto_programt::make_goto(
116  t_orig,
117  side_effect_expr_nondett(bool_typet(), source_location),
118  source_location);
119 
120  *t_call = goto_programt::make_function_call(isr_call, source_location);
121 
122  t_orig->swap(original_instruction);
123 
124  i_it=t_orig; // the for loop already counts us up
125  }
126 
127  if(race_on_write)
128  {
129  // insert _after_ the instruction with race
130  goto_programt::targett t_orig=i_it;
131  t_orig++;
132 
133  const source_locationt &source_location = i_it->source_location();
134 
135  code_function_callt isr_call(interrupt_handler);
136  isr_call.add_source_location()=source_location;
137 
138  goto_programt::targett t_goto = goto_program.insert_after(
139  i_it,
141  t_orig,
142  side_effect_expr_nondett(bool_typet(), source_location),
143  source_location));
144 
145  goto_programt::targett t_call = goto_program.insert_after(
146  t_goto, goto_programt::make_function_call(isr_call, source_location));
147 
148  i_it=t_call; // the for loop already counts us up
149  }
150  }
151 }
152 
153 static symbol_exprt
154 get_isr(const symbol_tablet &symbol_table, const irep_idt &interrupt_handler)
155 {
156  std::list<symbol_exprt> matches;
157 
158  for(const auto &symbol_name_entry :
159  equal_range(symbol_table.symbol_base_map, interrupt_handler))
160  {
161  // look it up
162  symbol_tablet::symbolst::const_iterator s_it =
163  symbol_table.symbols.find(symbol_name_entry.second);
164 
165  if(s_it==symbol_table.symbols.end())
166  continue;
167 
168  if(s_it->second.type.id() == ID_code && !s_it->second.is_property)
169  matches.push_back(s_it->second.symbol_expr());
170  }
171 
172  if(matches.empty())
173  throw "interrupt handler '" + id2string(interrupt_handler) + "' not found";
174 
175  if(matches.size()>=2)
176  throw "interrupt handler '" + id2string(interrupt_handler) +
177  "' is ambiguous";
178 
179  symbol_exprt isr=matches.front();
180 
181  if(!to_code_type(isr.type()).parameters().empty())
182  throw "interrupt handler '" + id2string(interrupt_handler) +
183  "' must not have parameters";
184 
185  return isr;
186 }
187 
189  value_setst &value_sets,
190  goto_modelt &goto_model,
191  const irep_idt &interrupt_handler)
192 {
193  // look up the ISR
194  symbol_exprt isr=
195  get_isr(goto_model.symbol_table, interrupt_handler);
196 
197  // we first figure out which objects are read/written by the ISR
198  rw_set_functiont isr_rw_set(
199  value_sets, goto_model, isr);
200 
201  // now instrument
202 
203  for(auto &gf_entry : goto_model.goto_functions.function_map)
204  {
205  if(
206  gf_entry.first != INITIALIZE_FUNCTION &&
207  gf_entry.first != goto_functionst::entry_point() &&
208  gf_entry.first != isr.get_identifier())
209  {
210  interrupt(
211  value_sets,
212  goto_model.symbol_table,
213  gf_entry.first,
214 #ifdef LOCAL_MAY
215  gf_entry.second,
216 #endif
217  gf_entry.second.body,
218  isr,
219  isr_rw_set);
220  }
221  }
222 
223  goto_model.goto_functions.update();
224 }
Forall_goto_program_instructions
#define Forall_goto_program_instructions(it, program)
Definition: goto_program.h:1234
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
symbol_tablet
The symbol table.
Definition: symbol_table.h:13
get_isr
static symbol_exprt get_isr(const symbol_tablet &symbol_table, const irep_idt &interrupt_handler)
Definition: interrupt.cpp:154
symbol_table_baset::symbol_base_map
const symbol_base_mapt & symbol_base_map
Read-only field, used to look up symbol names given their base names.
Definition: symbol_table_base.h:33
goto_programt::instructiont::swap
void swap(instructiont &instruction)
Swap two instructions.
Definition: goto_program.h:513
goto_modelt
Definition: goto_model.h:25
bool_typet
The Boolean type.
Definition: std_types.h:35
goto_functionst::function_map
function_mapt function_map
Definition: goto_functions.h:29
symbol_exprt
Expression to hold a symbol (variable)
Definition: std_expr.h:112
rw_set_baset::r_entries
entriest r_entries
Definition: rw_set.h:59
local_may_aliast
Definition: local_may_alias.h:25
goto_programt::make_goto
static instructiont make_goto(targett _target, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:1030
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
goto_programt::make_function_call
static instructiont make_function_call(const code_function_callt &_code, const source_locationt &l=source_locationt::nil())
Create a function call instruction.
Definition: goto_program.h:1081
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
code_function_callt
goto_instruction_codet representation of a function call statement.
Definition: goto_instruction_code.h:271
to_code_type
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:744
interrupt.h
local_may_alias.h
id2string
const std::string & id2string(const irep_idt &d)
Definition: irep.h:47
goto_programt::instructiont::source_location
const source_locationt & source_location() const
Definition: goto_program.h:340
symbol_exprt::get_identifier
const irep_idt & get_identifier() const
Definition: std_expr.h:142
interrupt
static void interrupt(value_setst &value_sets, const symbol_tablet &symbol_table, const irep_idt &function_id, goto_programt &goto_program, const symbol_exprt &interrupt_handler, const rw_set_baset &isr_rw_set)
Definition: interrupt.cpp:58
INITIALIZE_FUNCTION
#define INITIALIZE_FUNCTION
Definition: static_lifetime_init.h:22
range.h
rw_set_baset::w_entries
entriest w_entries
Definition: rw_set.h:59
code_typet::parameters
const parameterst & parameters() const
Definition: std_types.h:655
std_code.h
potential_race_on_read
static bool potential_race_on_read(const rw_set_baset &code_rw_set, const rw_set_baset &isr_rw_set)
Definition: interrupt.cpp:27
source_locationt
Definition: source_location.h:18
side_effect_expr_nondett
A side_effect_exprt that returns a non-deterministically chosen value.
Definition: std_code.h:1519
goto_functionst::goto_functiont
::goto_functiont goto_functiont
Definition: goto_functions.h:27
rw_set_baset::has_w_entry
bool has_w_entry(irep_idt object) const
Definition: rw_set.h:79
value_setst
Definition: value_sets.h:21
goto_modelt::goto_functions
goto_functionst goto_functions
GOTO functions.
Definition: goto_model.h:33
rw_set_loct
Definition: rw_set.h:176
rw_set.h
rw_set_baset
Definition: rw_set.h:33
symbol_table_baset::symbols
const symbolst & symbols
Read-only field, used to look up symbols given their names.
Definition: symbol_table_base.h:30
goto_functionst::update
void update()
Definition: goto_functions.h:83
goto_programt
A generic container class for the GOTO intermediate representation of one function.
Definition: goto_program.h:72
rw_set_baset::has_r_entry
bool has_r_entry(irep_idt object) const
Definition: rw_set.h:84
goto_functionst::entry_point
static irep_idt entry_point()
Get the identifier of the entry point to a goto model.
Definition: goto_functions.h:92
static_lifetime_init.h
exprt::add_source_location
source_locationt & add_source_location()
Definition: expr.h:216
goto_programt::instructiont
This class represents an instruction in the GOTO intermediate representation.
Definition: goto_program.h:180
potential_race_on_write
static bool potential_race_on_write(const rw_set_baset &code_rw_set, const rw_set_baset &isr_rw_set)
Definition: interrupt.cpp:41
goto_modelt::symbol_table
symbol_tablet symbol_table
Symbol table.
Definition: goto_model.h:30
rw_set_functiont
Definition: rw_set.h:202
goto_programt::targett
instructionst::iterator targett
Definition: goto_program.h:586
equal_range
ranget< typename multimapt::const_iterator > equal_range(const multimapt &multimap, const typename multimapt::key_type &key)
Utility function to make equal_range method of multimap easier to use by returning a ranget object.
Definition: range.h:541