ROSE  0.11.101.0
SValue.h
1 #ifndef ROSE_BinaryAnalysis_InstructionSemantics_BaseSemantics_SValue_H
2 #define ROSE_BinaryAnalysis_InstructionSemantics_BaseSemantics_SValue_H
3 #include <featureTests.h>
4 #ifdef ROSE_ENABLE_BINARY_ANALYSIS
5 
6 #include <Rose/BinaryAnalysis/InstructionSemantics/BaseSemantics/Types.h>
7 #include <Rose/BinaryAnalysis/SmtSolver.h>
8 
9 #include <boost/serialization/access.hpp>
10 #include <boost/serialization/export.hpp>
11 #include <boost/serialization/nvp.hpp>
12 #include <Sawyer/SharedPointer.h>
13 
14 namespace Rose {
15 namespace BinaryAnalysis {
16 namespace InstructionSemantics {
17 namespace BaseSemantics {
18 
20 // Semantic Values
22 
23 // This is leftover for compatibility with an older API. The old API had code like this:
24 // User::SValue user_svalue = BaseSemantics::dynamic_pointer_cast<User::SValue>(base_svalue);
25 // Which can be replaced now with
26 // User::SValue user_svalue = base_svalue.dynamicCast<User::SValue>();
27 template<class To, class From>
28 Sawyer::SharedPointer<To> dynamic_pointer_cast(const Sawyer::SharedPointer<From> &from) {
29  return from.template dynamicCast<To>();
30 }
31 
47 public:
49  using Ptr = SValuePtr;
50 
51 protected:
52  size_t width;
54  // Serialization
56 #ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
57 private:
58  friend class boost::serialization::access;
59 
60  template<class S>
61  void serialize(S &s, const unsigned /*version*/) {
62  s & BOOST_SERIALIZATION_NVP(width);
63  }
64 #endif
65 
67  // Normal, protected, C++ constructors
68 protected:
69  SValue(): width(0) {} // needed for serialization
70  explicit SValue(size_t nbits): width(nbits) {} // hot
71  SValue(const SValue &other): Sawyer::SharedObject(other), width(other.width) {}
72 
73 public:
74  virtual ~SValue() {}
75 
77  // Allocating static constructor. None are needed--this class is abstract.
78 
80  // Allocating virtual constructors. undefined_() needs underscores, so we do so consistently for all
81  // these allocating virtual c'tors. However, we use copy() rather than copy_() because this one is fundamentally
82  // different: the object (this) is use for more than just selecting which virtual method to invoke.
83  //
84  // The naming scheme we use here is a bit different than for most other objects for historical reasons. Most other classes
85  // use "create" and "clone" as the virtual constructor names, but SValue uses names ending in undercore, and "copy". The
86  // other difference (at least in this base class) is that we don't define any real constructors or static allocating
87  // constructors (usually named "instance")--it's because this is an abstract class.
88 public:
94  virtual SValuePtr undefined_(size_t nbits) const = 0; // hot
95 
104  virtual SValuePtr unspecified_(size_t nbits) const = 0;
105 
111  virtual SValuePtr bottom_(size_t nBits) const = 0;
112 
116  virtual SValuePtr number_(size_t nbits, uint64_t number) const = 0; // hot
117 
121  virtual SValuePtr boolean_(bool value) const { return number_(1, value?1:0); }
122 
126  virtual SValuePtr copy(size_t new_width=0) const = 0;
127 
155  createOptionalMerge(const SValuePtr &other, const MergerPtr &merger, const SmtSolverPtr &solver) const = 0;
156 
163  SValuePtr createMerged(const SValuePtr &other, const MergerPtr &merger, const SmtSolverPtr &solver) const /*final*/ {
164  return createOptionalMerge(other, merger, solver).orElse(copy());
165  }
166 
168  // Dynamic pointer casts. No-ops since this is the base class
169 public:
170  static SValuePtr promote(const SValuePtr &x) {
171  ASSERT_not_null(x);
172  return x;
173  }
174 
176  // The rest of the API...
177 public:
183  size_t nBits() const /*final*/;
184 
190  virtual bool isBottom() const = 0;
191 
199  bool isConcrete() const /*final*/;
200 
207  Sawyer::Optional<uint64_t> toUnsigned() const /*final*/;
208 
215  Sawyer::Optional<int64_t> toSigned() const /*final*/;
216 
222  bool mustEqual(const SValuePtr &other, const SmtSolverPtr &solver = SmtSolverPtr()) const /*final*/;
223 
229  bool mayEqual(const SValuePtr &other, const SmtSolverPtr &solver = SmtSolverPtr()) const /*final*/;
230 
234  bool isTrue() const /*final*/;
235 
239  bool isFalse() const /*final*/;
240 
251  std::string comment() const /*final*/;
252  void comment(const std::string&) const /*final*/; // const is intentional (see documentation)
258  virtual void hash(Combinatorics::Hasher&) const = 0;
259 
263  void print(std::ostream&) const;
264  virtual void print(std::ostream&, Formatter&) const = 0;
271  std::string toString() const;
272 
275  SValuePtr obj;
276  Formatter &fmt;
277  public:
278  WithFormatter(const SValuePtr &svalue, Formatter &fmt): obj(svalue), fmt(fmt) {}
279  void print(std::ostream &stream) const { obj->print(stream, fmt); }
280  };
281 
291  WithFormatter operator+(const std::string &linePrefix);
294  // This is the virtual interface that uses names that are not consistent with most of the rest of binary analysis. Calling
296  // these directly is deprecated and we may make them protected at some time. [Robb Matzke 2021-03-18].
298 public: // for backward compatibility for now, but assume protected
300  virtual bool is_number() const = 0;
301 
303  virtual uint64_t get_number() const = 0;
304 
308  virtual size_t get_width() const { return width; }
309  virtual void set_width(size_t nbits) { width = nbits; }
313  virtual bool must_equal(const SValuePtr &other, const SmtSolverPtr &solver = SmtSolverPtr()) const = 0;
314 
316  virtual bool may_equal(const SValuePtr &other, const SmtSolverPtr &solver = SmtSolverPtr()) const = 0;
317 
323  virtual std::string get_comment() const { return ""; }
324  virtual void set_comment(const std::string&) const {} // const is intended; cf. doxygen comment
326 };
327 
328 std::ostream& operator<<(std::ostream&, const SValue&);
329 std::ostream& operator<<(std::ostream&, const SValue::WithFormatter&);
330 
331 } // namespace
332 } // namespace
333 } // namespace
334 } // namespace
335 
337 
338 #endif
339 #endif
Base classes for instruction semantics.
Definition: Dispatcher.h:18
virtual void set_width(size_t nbits)
Virtual API.
Definition: SValue.h:309
virtual SValuePtr boolean_(bool value) const
Create a new, Boolean value.
Definition: SValue.h:121
SharedObject()
Default constructor.
Definition: SharedObject.h:70
virtual bool may_equal(const SValuePtr &other, const SmtSolverPtr &solver=SmtSolverPtr()) const =0
Virtual API.
virtual std::string get_comment() const
Some subclasses support the ability to add comments to values.
Definition: SValue.h:323
WithFormatter with_format(Formatter &fmt)
Used for printing values with formatting.
Definition: SValue.h:289
WithFormatter operator+(Formatter &fmt)
Used for printing values with formatting.
Definition: SValue.h:290
virtual SValuePtr copy(size_t new_width=0) const =0
Create a new value from an existing value, changing the width if new_width is non-zero.
virtual void set_comment(const std::string &) const
Some subclasses support the ability to add comments to values.
Definition: SValue.h:324
STL namespace.
Holds a value or nothing.
Definition: Optional.h:49
Small object support.
Definition: SmallObject.h:19
SValuePtr createMerged(const SValuePtr &other, const MergerPtr &merger, const SmtSolverPtr &solver) const
Create a new value by merging two existing values.
Definition: SValue.h:163
Main namespace for the ROSE library.
virtual void hash(Combinatorics::Hasher &) const =0
Hash this semantic value.
Sawyer::Optional< int64_t > toSigned() const
Converts a concrete value to a native signed integer.
virtual SValuePtr undefined_(size_t nbits) const =0
Create a new undefined semantic value.
Reference-counting intrusive smart pointer.
Definition: SharedPointer.h:68
Name space for the entire library.
Definition: FeasiblePath.h:773
bool isFalse() const
Returns true if concrete zero.
bool isConcrete() const
Determines if the value is a concrete number.
virtual bool must_equal(const SValuePtr &other, const SmtSolverPtr &solver=SmtSolverPtr()) const =0
Virtual API.
Creates SharedPointer from this.
virtual SValuePtr bottom_(size_t nBits) const =0
Data-flow bottom value.
bool isTrue() const
Returns true if concrete non-zero.
void print(std::ostream &) const
Print a value to a stream using default format.
Binary analysis.
Sawyer::SharedPointer< SValue > SValuePtr
Shared-ownership pointer to a semantic value in any domain.
virtual bool isBottom() const =0
Determines whether a value is a data-flow bottom.
Base class for reference counted objects.
Definition: SharedObject.h:64
virtual SValuePtr unspecified_(size_t nbits) const =0
Create a new unspecified semantic value.
virtual Sawyer::Optional< SValuePtr > createOptionalMerge(const SValuePtr &other, const MergerPtr &merger, const SmtSolverPtr &solver) const =0
Possibly create a new value by merging two existing values.
bool mayEqual(const SValuePtr &other, const SmtSolverPtr &solver=SmtSolverPtr()) const
Tests two values for possible equality.
bool mustEqual(const SValuePtr &other, const SmtSolverPtr &solver=SmtSolverPtr()) const
Tests two values for equality.
std::string toString() const
Render this symbolic expression as a string.
virtual SValuePtr number_(size_t nbits, uint64_t number) const =0
Create a new concrete semantic value.
Sawyer::Optional< uint64_t > toUnsigned() const
Converts a concrete value to a native unsigned integer.