SMTAPI.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. //===- SMTAPI.h -------------------------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file defines a SMT generic Solver API, which will be the base class
  10. // for every SMT solver specific class.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_SUPPORT_SMTAPI_H
  14. #define LLVM_SUPPORT_SMTAPI_H
  15. #include "llvm/ADT/APFloat.h"
  16. #include "llvm/ADT/APSInt.h"
  17. #include "llvm/ADT/FoldingSet.h"
  18. #include "llvm/Support/raw_ostream.h"
  19. #include <memory>
  20. namespace llvm {
  21. /// Generic base class for SMT sorts
  22. class SMTSort {
  23. public:
  24. SMTSort() = default;
  25. virtual ~SMTSort() = default;
  26. /// Returns true if the sort is a bitvector, calls isBitvectorSortImpl().
  27. virtual bool isBitvectorSort() const { return isBitvectorSortImpl(); }
  28. /// Returns true if the sort is a floating-point, calls isFloatSortImpl().
  29. virtual bool isFloatSort() const { return isFloatSortImpl(); }
  30. /// Returns true if the sort is a boolean, calls isBooleanSortImpl().
  31. virtual bool isBooleanSort() const { return isBooleanSortImpl(); }
  32. /// Returns the bitvector size, fails if the sort is not a bitvector
  33. /// Calls getBitvectorSortSizeImpl().
  34. virtual unsigned getBitvectorSortSize() const {
  35. assert(isBitvectorSort() && "Not a bitvector sort!");
  36. unsigned Size = getBitvectorSortSizeImpl();
  37. assert(Size && "Size is zero!");
  38. return Size;
  39. };
  40. /// Returns the floating-point size, fails if the sort is not a floating-point
  41. /// Calls getFloatSortSizeImpl().
  42. virtual unsigned getFloatSortSize() const {
  43. assert(isFloatSort() && "Not a floating-point sort!");
  44. unsigned Size = getFloatSortSizeImpl();
  45. assert(Size && "Size is zero!");
  46. return Size;
  47. };
  48. virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
  49. bool operator<(const SMTSort &Other) const {
  50. llvm::FoldingSetNodeID ID1, ID2;
  51. Profile(ID1);
  52. Other.Profile(ID2);
  53. return ID1 < ID2;
  54. }
  55. friend bool operator==(SMTSort const &LHS, SMTSort const &RHS) {
  56. return LHS.equal_to(RHS);
  57. }
  58. virtual void print(raw_ostream &OS) const = 0;
  59. LLVM_DUMP_METHOD void dump() const;
  60. protected:
  61. /// Query the SMT solver and returns true if two sorts are equal (same kind
  62. /// and bit width). This does not check if the two sorts are the same objects.
  63. virtual bool equal_to(SMTSort const &other) const = 0;
  64. /// Query the SMT solver and checks if a sort is bitvector.
  65. virtual bool isBitvectorSortImpl() const = 0;
  66. /// Query the SMT solver and checks if a sort is floating-point.
  67. virtual bool isFloatSortImpl() const = 0;
  68. /// Query the SMT solver and checks if a sort is boolean.
  69. virtual bool isBooleanSortImpl() const = 0;
  70. /// Query the SMT solver and returns the sort bit width.
  71. virtual unsigned getBitvectorSortSizeImpl() const = 0;
  72. /// Query the SMT solver and returns the sort bit width.
  73. virtual unsigned getFloatSortSizeImpl() const = 0;
  74. };
  75. /// Shared pointer for SMTSorts, used by SMTSolver API.
  76. using SMTSortRef = const SMTSort *;
  77. /// Generic base class for SMT exprs
  78. class SMTExpr {
  79. public:
  80. SMTExpr() = default;
  81. virtual ~SMTExpr() = default;
  82. bool operator<(const SMTExpr &Other) const {
  83. llvm::FoldingSetNodeID ID1, ID2;
  84. Profile(ID1);
  85. Other.Profile(ID2);
  86. return ID1 < ID2;
  87. }
  88. virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
  89. friend bool operator==(SMTExpr const &LHS, SMTExpr const &RHS) {
  90. return LHS.equal_to(RHS);
  91. }
  92. virtual void print(raw_ostream &OS) const = 0;
  93. LLVM_DUMP_METHOD void dump() const;
  94. protected:
  95. /// Query the SMT solver and returns true if two sorts are equal (same kind
  96. /// and bit width). This does not check if the two sorts are the same objects.
  97. virtual bool equal_to(SMTExpr const &other) const = 0;
  98. };
  99. /// Shared pointer for SMTExprs, used by SMTSolver API.
  100. using SMTExprRef = const SMTExpr *;
  101. /// Generic base class for SMT Solvers
  102. ///
  103. /// This class is responsible for wrapping all sorts and expression generation,
  104. /// through the mk* methods. It also provides methods to create SMT expressions
  105. /// straight from clang's AST, through the from* methods.
  106. class SMTSolver {
  107. public:
  108. SMTSolver() = default;
  109. virtual ~SMTSolver() = default;
  110. LLVM_DUMP_METHOD void dump() const;
  111. // Returns an appropriate floating-point sort for the given bitwidth.
  112. SMTSortRef getFloatSort(unsigned BitWidth) {
  113. switch (BitWidth) {
  114. case 16:
  115. return getFloat16Sort();
  116. case 32:
  117. return getFloat32Sort();
  118. case 64:
  119. return getFloat64Sort();
  120. case 128:
  121. return getFloat128Sort();
  122. default:;
  123. }
  124. llvm_unreachable("Unsupported floating-point bitwidth!");
  125. }
  126. // Returns a boolean sort.
  127. virtual SMTSortRef getBoolSort() = 0;
  128. // Returns an appropriate bitvector sort for the given bitwidth.
  129. virtual SMTSortRef getBitvectorSort(const unsigned BitWidth) = 0;
  130. // Returns a floating-point sort of width 16
  131. virtual SMTSortRef getFloat16Sort() = 0;
  132. // Returns a floating-point sort of width 32
  133. virtual SMTSortRef getFloat32Sort() = 0;
  134. // Returns a floating-point sort of width 64
  135. virtual SMTSortRef getFloat64Sort() = 0;
  136. // Returns a floating-point sort of width 128
  137. virtual SMTSortRef getFloat128Sort() = 0;
  138. // Returns an appropriate sort for the given AST.
  139. virtual SMTSortRef getSort(const SMTExprRef &AST) = 0;
  140. /// Given a constraint, adds it to the solver
  141. virtual void addConstraint(const SMTExprRef &Exp) const = 0;
  142. /// Creates a bitvector addition operation
  143. virtual SMTExprRef mkBVAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  144. /// Creates a bitvector subtraction operation
  145. virtual SMTExprRef mkBVSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  146. /// Creates a bitvector multiplication operation
  147. virtual SMTExprRef mkBVMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  148. /// Creates a bitvector signed modulus operation
  149. virtual SMTExprRef mkBVSRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  150. /// Creates a bitvector unsigned modulus operation
  151. virtual SMTExprRef mkBVURem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  152. /// Creates a bitvector signed division operation
  153. virtual SMTExprRef mkBVSDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  154. /// Creates a bitvector unsigned division operation
  155. virtual SMTExprRef mkBVUDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  156. /// Creates a bitvector logical shift left operation
  157. virtual SMTExprRef mkBVShl(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  158. /// Creates a bitvector arithmetic shift right operation
  159. virtual SMTExprRef mkBVAshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  160. /// Creates a bitvector logical shift right operation
  161. virtual SMTExprRef mkBVLshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  162. /// Creates a bitvector negation operation
  163. virtual SMTExprRef mkBVNeg(const SMTExprRef &Exp) = 0;
  164. /// Creates a bitvector not operation
  165. virtual SMTExprRef mkBVNot(const SMTExprRef &Exp) = 0;
  166. /// Creates a bitvector xor operation
  167. virtual SMTExprRef mkBVXor(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  168. /// Creates a bitvector or operation
  169. virtual SMTExprRef mkBVOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  170. /// Creates a bitvector and operation
  171. virtual SMTExprRef mkBVAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  172. /// Creates a bitvector unsigned less-than operation
  173. virtual SMTExprRef mkBVUlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  174. /// Creates a bitvector signed less-than operation
  175. virtual SMTExprRef mkBVSlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  176. /// Creates a bitvector unsigned greater-than operation
  177. virtual SMTExprRef mkBVUgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  178. /// Creates a bitvector signed greater-than operation
  179. virtual SMTExprRef mkBVSgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  180. /// Creates a bitvector unsigned less-equal-than operation
  181. virtual SMTExprRef mkBVUle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  182. /// Creates a bitvector signed less-equal-than operation
  183. virtual SMTExprRef mkBVSle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  184. /// Creates a bitvector unsigned greater-equal-than operation
  185. virtual SMTExprRef mkBVUge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  186. /// Creates a bitvector signed greater-equal-than operation
  187. virtual SMTExprRef mkBVSge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  188. /// Creates a boolean not operation
  189. virtual SMTExprRef mkNot(const SMTExprRef &Exp) = 0;
  190. /// Creates a boolean equality operation
  191. virtual SMTExprRef mkEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  192. /// Creates a boolean and operation
  193. virtual SMTExprRef mkAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  194. /// Creates a boolean or operation
  195. virtual SMTExprRef mkOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  196. /// Creates a boolean ite operation
  197. virtual SMTExprRef mkIte(const SMTExprRef &Cond, const SMTExprRef &T,
  198. const SMTExprRef &F) = 0;
  199. /// Creates a bitvector sign extension operation
  200. virtual SMTExprRef mkBVSignExt(unsigned i, const SMTExprRef &Exp) = 0;
  201. /// Creates a bitvector zero extension operation
  202. virtual SMTExprRef mkBVZeroExt(unsigned i, const SMTExprRef &Exp) = 0;
  203. /// Creates a bitvector extract operation
  204. virtual SMTExprRef mkBVExtract(unsigned High, unsigned Low,
  205. const SMTExprRef &Exp) = 0;
  206. /// Creates a bitvector concat operation
  207. virtual SMTExprRef mkBVConcat(const SMTExprRef &LHS,
  208. const SMTExprRef &RHS) = 0;
  209. /// Creates a predicate that checks for overflow in a bitvector addition
  210. /// operation
  211. virtual SMTExprRef mkBVAddNoOverflow(const SMTExprRef &LHS,
  212. const SMTExprRef &RHS,
  213. bool isSigned) = 0;
  214. /// Creates a predicate that checks for underflow in a signed bitvector
  215. /// addition operation
  216. virtual SMTExprRef mkBVAddNoUnderflow(const SMTExprRef &LHS,
  217. const SMTExprRef &RHS) = 0;
  218. /// Creates a predicate that checks for overflow in a signed bitvector
  219. /// subtraction operation
  220. virtual SMTExprRef mkBVSubNoOverflow(const SMTExprRef &LHS,
  221. const SMTExprRef &RHS) = 0;
  222. /// Creates a predicate that checks for underflow in a bitvector subtraction
  223. /// operation
  224. virtual SMTExprRef mkBVSubNoUnderflow(const SMTExprRef &LHS,
  225. const SMTExprRef &RHS,
  226. bool isSigned) = 0;
  227. /// Creates a predicate that checks for overflow in a signed bitvector
  228. /// division/modulus operation
  229. virtual SMTExprRef mkBVSDivNoOverflow(const SMTExprRef &LHS,
  230. const SMTExprRef &RHS) = 0;
  231. /// Creates a predicate that checks for overflow in a bitvector negation
  232. /// operation
  233. virtual SMTExprRef mkBVNegNoOverflow(const SMTExprRef &Exp) = 0;
  234. /// Creates a predicate that checks for overflow in a bitvector multiplication
  235. /// operation
  236. virtual SMTExprRef mkBVMulNoOverflow(const SMTExprRef &LHS,
  237. const SMTExprRef &RHS,
  238. bool isSigned) = 0;
  239. /// Creates a predicate that checks for underflow in a signed bitvector
  240. /// multiplication operation
  241. virtual SMTExprRef mkBVMulNoUnderflow(const SMTExprRef &LHS,
  242. const SMTExprRef &RHS) = 0;
  243. /// Creates a floating-point negation operation
  244. virtual SMTExprRef mkFPNeg(const SMTExprRef &Exp) = 0;
  245. /// Creates a floating-point isInfinite operation
  246. virtual SMTExprRef mkFPIsInfinite(const SMTExprRef &Exp) = 0;
  247. /// Creates a floating-point isNaN operation
  248. virtual SMTExprRef mkFPIsNaN(const SMTExprRef &Exp) = 0;
  249. /// Creates a floating-point isNormal operation
  250. virtual SMTExprRef mkFPIsNormal(const SMTExprRef &Exp) = 0;
  251. /// Creates a floating-point isZero operation
  252. virtual SMTExprRef mkFPIsZero(const SMTExprRef &Exp) = 0;
  253. /// Creates a floating-point multiplication operation
  254. virtual SMTExprRef mkFPMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  255. /// Creates a floating-point division operation
  256. virtual SMTExprRef mkFPDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  257. /// Creates a floating-point remainder operation
  258. virtual SMTExprRef mkFPRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  259. /// Creates a floating-point addition operation
  260. virtual SMTExprRef mkFPAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  261. /// Creates a floating-point subtraction operation
  262. virtual SMTExprRef mkFPSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  263. /// Creates a floating-point less-than operation
  264. virtual SMTExprRef mkFPLt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  265. /// Creates a floating-point greater-than operation
  266. virtual SMTExprRef mkFPGt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  267. /// Creates a floating-point less-than-or-equal operation
  268. virtual SMTExprRef mkFPLe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  269. /// Creates a floating-point greater-than-or-equal operation
  270. virtual SMTExprRef mkFPGe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
  271. /// Creates a floating-point equality operation
  272. virtual SMTExprRef mkFPEqual(const SMTExprRef &LHS,
  273. const SMTExprRef &RHS) = 0;
  274. /// Creates a floating-point conversion from floatint-point to floating-point
  275. /// operation
  276. virtual SMTExprRef mkFPtoFP(const SMTExprRef &From, const SMTSortRef &To) = 0;
  277. /// Creates a floating-point conversion from signed bitvector to
  278. /// floatint-point operation
  279. virtual SMTExprRef mkSBVtoFP(const SMTExprRef &From,
  280. const SMTSortRef &To) = 0;
  281. /// Creates a floating-point conversion from unsigned bitvector to
  282. /// floatint-point operation
  283. virtual SMTExprRef mkUBVtoFP(const SMTExprRef &From,
  284. const SMTSortRef &To) = 0;
  285. /// Creates a floating-point conversion from floatint-point to signed
  286. /// bitvector operation
  287. virtual SMTExprRef mkFPtoSBV(const SMTExprRef &From, unsigned ToWidth) = 0;
  288. /// Creates a floating-point conversion from floatint-point to unsigned
  289. /// bitvector operation
  290. virtual SMTExprRef mkFPtoUBV(const SMTExprRef &From, unsigned ToWidth) = 0;
  291. /// Creates a new symbol, given a name and a sort
  292. virtual SMTExprRef mkSymbol(const char *Name, SMTSortRef Sort) = 0;
  293. // Returns an appropriate floating-point rounding mode.
  294. virtual SMTExprRef getFloatRoundingMode() = 0;
  295. // If the a model is available, returns the value of a given bitvector symbol
  296. virtual llvm::APSInt getBitvector(const SMTExprRef &Exp, unsigned BitWidth,
  297. bool isUnsigned) = 0;
  298. // If the a model is available, returns the value of a given boolean symbol
  299. virtual bool getBoolean(const SMTExprRef &Exp) = 0;
  300. /// Constructs an SMTExprRef from a boolean.
  301. virtual SMTExprRef mkBoolean(const bool b) = 0;
  302. /// Constructs an SMTExprRef from a finite APFloat.
  303. virtual SMTExprRef mkFloat(const llvm::APFloat Float) = 0;
  304. /// Constructs an SMTExprRef from an APSInt and its bit width
  305. virtual SMTExprRef mkBitvector(const llvm::APSInt Int, unsigned BitWidth) = 0;
  306. /// Given an expression, extract the value of this operand in the model.
  307. virtual bool getInterpretation(const SMTExprRef &Exp, llvm::APSInt &Int) = 0;
  308. /// Given an expression extract the value of this operand in the model.
  309. virtual bool getInterpretation(const SMTExprRef &Exp,
  310. llvm::APFloat &Float) = 0;
  311. /// Check if the constraints are satisfiable
  312. virtual Optional<bool> check() const = 0;
  313. /// Push the current solver state
  314. virtual void push() = 0;
  315. /// Pop the previous solver state
  316. virtual void pop(unsigned NumStates = 1) = 0;
  317. /// Reset the solver and remove all constraints.
  318. virtual void reset() = 0;
  319. /// Checks if the solver supports floating-points.
  320. virtual bool isFPSupported() = 0;
  321. virtual void print(raw_ostream &OS) const = 0;
  322. };
  323. /// Shared pointer for SMTSolvers.
  324. using SMTSolverRef = std::shared_ptr<SMTSolver>;
  325. /// Convenience method to create and Z3Solver object
  326. SMTSolverRef CreateZ3Solver();
  327. } // namespace llvm
  328. #endif