CBMC
mm_io.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Perform Memory-mapped I/O instrumentation
4 
5 Author: Daniel Kroening
6 
7 Date: April 2017
8 
9 \*******************************************************************/
10 
13 
14 #include "mm_io.h"
15 
16 #include <util/fresh_symbol.h>
17 #include <util/message.h>
18 #include <util/pointer_expr.h>
21 #include <util/replace_expr.h>
22 
23 #include "goto_model.h"
24 
25 #include <set>
26 
27 class mm_iot
28 {
29 public:
30  explicit mm_iot(symbol_table_baset &symbol_table);
31 
32  void mm_io(goto_functionst::goto_functiont &goto_function);
33 
34  std::size_t reads_replaced = 0;
35  std::size_t writes_replaced = 0;
36 
37 protected:
38  const irep_idt id_r = CPROVER_PREFIX "mm_io_r";
39  const irep_idt id_w = CPROVER_PREFIX "mm_io_w";
40 
41  const namespacet ns;
45 };
46 
48  : ns(symbol_table),
49  mm_io_r(nil_exprt{}),
50  mm_io_r_value(nil_exprt{}),
51  mm_io_w(nil_exprt{})
52 {
53  if(const auto mm_io_r_symbol = symbol_table.lookup(id_r))
54  {
55  mm_io_r = mm_io_r_symbol->symbol_expr();
56 
57  const auto &value_symbol = get_fresh_aux_symbol(
59  id2string(id_r) + "$value",
60  id2string(id_r) + "$value",
61  mm_io_r_symbol->location,
62  mm_io_r_symbol->mode,
63  symbol_table);
64 
65  mm_io_r_value = value_symbol.symbol_expr();
66  }
67 
68  if(const auto mm_io_w_symbol = symbol_table.lookup(id_w))
69  mm_io_w = mm_io_w_symbol->symbol_expr();
70 }
71 
72 static std::set<dereference_exprt> collect_deref_expr(const exprt &src)
73 {
74  std::set<dereference_exprt> collected;
75  src.visit_pre([&collected](const exprt &e) {
76  if(e.id() == ID_dereference)
77  collected.insert(to_dereference_expr(e));
78  });
79  return collected;
80 }
81 
83 {
84  // return early when there is nothing to be done
85  if(mm_io_r.is_nil() && mm_io_w.is_nil())
86  return;
87 
88  for(auto it = goto_function.body.instructions.begin();
89  it != goto_function.body.instructions.end();
90  it++)
91  {
92  if(!it->is_assign())
93  continue;
94 
95  auto &a_lhs = it->assign_lhs();
96  auto &a_rhs = it->assign_rhs_nonconst();
97  const auto deref_expr_r = collect_deref_expr(a_rhs);
98 
99  if(mm_io_r.is_not_nil())
100  {
101  if(deref_expr_r.size() == 1)
102  {
103  const dereference_exprt &d = *deref_expr_r.begin();
104  source_locationt source_location = it->source_location();
105  const code_typet &ct = to_code_type(mm_io_r.type());
106 
107  if_exprt if_expr(
110  d);
111  replace_expr(d, if_expr, a_rhs);
112 
113  const typet &pt = ct.parameters()[0].type();
114  const typet &st = ct.parameters()[1].type();
115  auto size_opt = size_of_expr(d.type(), ns);
116  CHECK_RETURN(size_opt.has_value());
119  mm_io_r,
120  {typecast_exprt(d.pointer(), pt),
121  typecast_exprt(size_opt.value(), st)},
122  source_location);
123  goto_function.body.insert_before_swap(it, call);
124  ++reads_replaced;
125  it++;
126  }
127  }
128 
129  if(mm_io_w.is_not_nil())
130  {
131  if(a_lhs.id() == ID_dereference)
132  {
133  const dereference_exprt &d = to_dereference_expr(a_lhs);
134  source_locationt source_location = it->source_location();
135  const code_typet &ct = to_code_type(mm_io_w.type());
136  const typet &pt = ct.parameters()[0].type();
137  const typet &st = ct.parameters()[1].type();
138  const typet &vt = ct.parameters()[2].type();
139  auto size_opt = size_of_expr(d.type(), ns);
140  CHECK_RETURN(size_opt.has_value());
141  const code_function_callt fc(
142  mm_io_w,
143  {typecast_exprt(d.pointer(), pt),
144  typecast_exprt(size_opt.value(), st),
145  typecast_exprt(a_rhs, vt)});
146  goto_function.body.insert_before_swap(it);
147  *it = goto_programt::make_function_call(fc, source_location);
148  ++writes_replaced;
149  it++;
150  }
151  }
152  }
153 }
154 
155 void mm_io(
156  symbol_tablet &symbol_table,
157  goto_functionst &goto_functions,
158  message_handlert &message_handler)
159 {
160  mm_iot rewrite{symbol_table};
161 
162  for(auto &f : goto_functions.function_map)
163  rewrite.mm_io(f.second);
164 
165  if(rewrite.reads_replaced || rewrite.writes_replaced)
166  {
167  messaget log{message_handler};
168  log.status() << "Replaced MMIO operations: " << rewrite.reads_replaced
169  << " read(s), " << rewrite.writes_replaced << " write(s)"
170  << messaget::eom;
171  }
172 }
173 
174 void mm_io(goto_modelt &model, message_handlert &message_handler)
175 {
176  mm_io(model.symbol_table, model.goto_functions, message_handler);
177 }
goto_instruction_codet representation of a function call statement.
Base type of functions.
Definition: std_types.h:583
const typet & return_type() const
Definition: std_types.h:689
const parameterst & parameters() const
Definition: std_types.h:699
Operator to dereference a pointer.
Definition: pointer_expr.h:834
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
Base class for all expressions.
Definition: expr.h:56
void visit_pre(std::function< void(exprt &)>)
Definition: expr.cpp:227
typet & type()
Return the type of the expression.
Definition: expr.h:84
A collection of goto functions.
function_mapt function_map
::goto_functiont goto_functiont
symbol_tablet symbol_table
Symbol table.
Definition: goto_model.h:31
goto_functionst goto_functions
GOTO functions.
Definition: goto_model.h:34
static instructiont make_function_call(const code_function_callt &_code, const source_locationt &l=source_locationt::nil())
Create a function call instruction.
The trinary if-then-else operator.
Definition: std_expr.h:2370
bool is_not_nil() const
Definition: irep.h:368
const irep_idt & id() const
Definition: irep.h:384
bool is_nil() const
Definition: irep.h:364
Class that provides messages with a built-in verbosity 'level'.
Definition: message.h:155
static eomt eom
Definition: message.h:297
Definition: mm_io.cpp:28
const irep_idt id_r
Definition: mm_io.cpp:38
const irep_idt id_w
Definition: mm_io.cpp:39
std::size_t reads_replaced
Definition: mm_io.cpp:34
exprt mm_io_r
Definition: mm_io.cpp:42
mm_iot(symbol_table_baset &symbol_table)
Definition: mm_io.cpp:47
std::size_t writes_replaced
Definition: mm_io.cpp:35
exprt mm_io_r_value
Definition: mm_io.cpp:43
void mm_io(goto_functionst::goto_functiont &goto_function)
Definition: mm_io.cpp:82
exprt mm_io_w
Definition: mm_io.cpp:44
const namespacet ns
Definition: mm_io.cpp:41
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
The NIL expression.
Definition: std_expr.h:3073
The symbol table base class interface.
const symbolt * lookup(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
The symbol table.
Definition: symbol_table.h:14
Semantic type conversion.
Definition: std_expr.h:2068
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2076
The type of an expression, extends irept.
Definition: type.h:29
#define CPROVER_PREFIX
symbolt & get_fresh_aux_symbol(const typet &type, const std::string &name_prefix, const std::string &basename_prefix, const source_locationt &source_location, const irep_idt &symbol_mode, const namespacet &ns, symbol_table_baset &symbol_table)
Installs a fresh-named symbol with respect to the given namespace ns with the requested name pattern ...
Fresh auxiliary symbol creation.
Symbol Table + CFG.
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
double log(double x)
Definition: math.c:2776
void mm_io(symbol_tablet &symbol_table, goto_functionst &goto_functions, message_handlert &message_handler)
Definition: mm_io.cpp:155
static std::set< dereference_exprt > collect_deref_expr(const exprt &src)
Definition: mm_io.cpp:72
Perform Memory-mapped I/O instrumentation.
API to expression classes for Pointers.
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
Definition: pointer_expr.h:890
std::optional< exprt > size_of_expr(const typet &type, const namespacet &ns)
Pointer Logic.
exprt integer_address(const exprt &pointer)
Various predicates over pointers in programs.
bool replace_expr(const exprt &what, const exprt &by, exprt &dest)
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:788