Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:34

0001 //===- SMTAPI.h -------------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  This file defines a SMT generic Solver API, which will be the base class
0010 //  for every SMT solver specific class.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_SUPPORT_SMTAPI_H
0015 #define LLVM_SUPPORT_SMTAPI_H
0016 
0017 #include "llvm/ADT/APFloat.h"
0018 #include "llvm/ADT/APSInt.h"
0019 #include "llvm/ADT/FoldingSet.h"
0020 #include "llvm/Support/raw_ostream.h"
0021 #include <memory>
0022 
0023 namespace llvm {
0024 
0025 /// Generic base class for SMT sorts
0026 class SMTSort {
0027 public:
0028   SMTSort() = default;
0029   virtual ~SMTSort() = default;
0030 
0031   /// Returns true if the sort is a bitvector, calls isBitvectorSortImpl().
0032   virtual bool isBitvectorSort() const { return isBitvectorSortImpl(); }
0033 
0034   /// Returns true if the sort is a floating-point, calls isFloatSortImpl().
0035   virtual bool isFloatSort() const { return isFloatSortImpl(); }
0036 
0037   /// Returns true if the sort is a boolean, calls isBooleanSortImpl().
0038   virtual bool isBooleanSort() const { return isBooleanSortImpl(); }
0039 
0040   /// Returns the bitvector size, fails if the sort is not a bitvector
0041   /// Calls getBitvectorSortSizeImpl().
0042   virtual unsigned getBitvectorSortSize() const {
0043     assert(isBitvectorSort() && "Not a bitvector sort!");
0044     unsigned Size = getBitvectorSortSizeImpl();
0045     assert(Size && "Size is zero!");
0046     return Size;
0047   };
0048 
0049   /// Returns the floating-point size, fails if the sort is not a floating-point
0050   /// Calls getFloatSortSizeImpl().
0051   virtual unsigned getFloatSortSize() const {
0052     assert(isFloatSort() && "Not a floating-point sort!");
0053     unsigned Size = getFloatSortSizeImpl();
0054     assert(Size && "Size is zero!");
0055     return Size;
0056   };
0057 
0058   virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
0059 
0060   bool operator<(const SMTSort &Other) const {
0061     llvm::FoldingSetNodeID ID1, ID2;
0062     Profile(ID1);
0063     Other.Profile(ID2);
0064     return ID1 < ID2;
0065   }
0066 
0067   friend bool operator==(SMTSort const &LHS, SMTSort const &RHS) {
0068     return LHS.equal_to(RHS);
0069   }
0070 
0071   virtual void print(raw_ostream &OS) const = 0;
0072 
0073   LLVM_DUMP_METHOD void dump() const;
0074 
0075 protected:
0076   /// Query the SMT solver and returns true if two sorts are equal (same kind
0077   /// and bit width). This does not check if the two sorts are the same objects.
0078   virtual bool equal_to(SMTSort const &other) const = 0;
0079 
0080   /// Query the SMT solver and checks if a sort is bitvector.
0081   virtual bool isBitvectorSortImpl() const = 0;
0082 
0083   /// Query the SMT solver and checks if a sort is floating-point.
0084   virtual bool isFloatSortImpl() const = 0;
0085 
0086   /// Query the SMT solver and checks if a sort is boolean.
0087   virtual bool isBooleanSortImpl() const = 0;
0088 
0089   /// Query the SMT solver and returns the sort bit width.
0090   virtual unsigned getBitvectorSortSizeImpl() const = 0;
0091 
0092   /// Query the SMT solver and returns the sort bit width.
0093   virtual unsigned getFloatSortSizeImpl() const = 0;
0094 };
0095 
0096 /// Shared pointer for SMTSorts, used by SMTSolver API.
0097 using SMTSortRef = const SMTSort *;
0098 
0099 /// Generic base class for SMT exprs
0100 class SMTExpr {
0101 public:
0102   SMTExpr() = default;
0103   virtual ~SMTExpr() = default;
0104 
0105   bool operator<(const SMTExpr &Other) const {
0106     llvm::FoldingSetNodeID ID1, ID2;
0107     Profile(ID1);
0108     Other.Profile(ID2);
0109     return ID1 < ID2;
0110   }
0111 
0112   virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
0113 
0114   friend bool operator==(SMTExpr const &LHS, SMTExpr const &RHS) {
0115     return LHS.equal_to(RHS);
0116   }
0117 
0118   virtual void print(raw_ostream &OS) const = 0;
0119 
0120   LLVM_DUMP_METHOD void dump() const;
0121 
0122 protected:
0123   /// Query the SMT solver and returns true if two sorts are equal (same kind
0124   /// and bit width). This does not check if the two sorts are the same objects.
0125   virtual bool equal_to(SMTExpr const &other) const = 0;
0126 };
0127 
0128 class SMTSolverStatistics {
0129 public:
0130   SMTSolverStatistics() = default;
0131   virtual ~SMTSolverStatistics() = default;
0132 
0133   virtual double getDouble(llvm::StringRef) const = 0;
0134   virtual unsigned getUnsigned(llvm::StringRef) const = 0;
0135 
0136   virtual void print(raw_ostream &OS) const = 0;
0137 
0138   LLVM_DUMP_METHOD void dump() const;
0139 };
0140 
0141 /// Shared pointer for SMTExprs, used by SMTSolver API.
0142 using SMTExprRef = const SMTExpr *;
0143 
0144 /// Generic base class for SMT Solvers
0145 ///
0146 /// This class is responsible for wrapping all sorts and expression generation,
0147 /// through the mk* methods. It also provides methods to create SMT expressions
0148 /// straight from clang's AST, through the from* methods.
0149 class SMTSolver {
0150 public:
0151   SMTSolver() = default;
0152   virtual ~SMTSolver() = default;
0153 
0154   LLVM_DUMP_METHOD void dump() const;
0155 
0156   // Returns an appropriate floating-point sort for the given bitwidth.
0157   SMTSortRef getFloatSort(unsigned BitWidth) {
0158     switch (BitWidth) {
0159     case 16:
0160       return getFloat16Sort();
0161     case 32:
0162       return getFloat32Sort();
0163     case 64:
0164       return getFloat64Sort();
0165     case 128:
0166       return getFloat128Sort();
0167     default:;
0168     }
0169     llvm_unreachable("Unsupported floating-point bitwidth!");
0170   }
0171 
0172   // Returns a boolean sort.
0173   virtual SMTSortRef getBoolSort() = 0;
0174 
0175   // Returns an appropriate bitvector sort for the given bitwidth.
0176   virtual SMTSortRef getBitvectorSort(const unsigned BitWidth) = 0;
0177 
0178   // Returns a floating-point sort of width 16
0179   virtual SMTSortRef getFloat16Sort() = 0;
0180 
0181   // Returns a floating-point sort of width 32
0182   virtual SMTSortRef getFloat32Sort() = 0;
0183 
0184   // Returns a floating-point sort of width 64
0185   virtual SMTSortRef getFloat64Sort() = 0;
0186 
0187   // Returns a floating-point sort of width 128
0188   virtual SMTSortRef getFloat128Sort() = 0;
0189 
0190   // Returns an appropriate sort for the given AST.
0191   virtual SMTSortRef getSort(const SMTExprRef &AST) = 0;
0192 
0193   /// Given a constraint, adds it to the solver
0194   virtual void addConstraint(const SMTExprRef &Exp) const = 0;
0195 
0196   /// Creates a bitvector addition operation
0197   virtual SMTExprRef mkBVAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0198 
0199   /// Creates a bitvector subtraction operation
0200   virtual SMTExprRef mkBVSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0201 
0202   /// Creates a bitvector multiplication operation
0203   virtual SMTExprRef mkBVMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0204 
0205   /// Creates a bitvector signed modulus operation
0206   virtual SMTExprRef mkBVSRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0207 
0208   /// Creates a bitvector unsigned modulus operation
0209   virtual SMTExprRef mkBVURem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0210 
0211   /// Creates a bitvector signed division operation
0212   virtual SMTExprRef mkBVSDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0213 
0214   /// Creates a bitvector unsigned division operation
0215   virtual SMTExprRef mkBVUDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0216 
0217   /// Creates a bitvector logical shift left operation
0218   virtual SMTExprRef mkBVShl(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0219 
0220   /// Creates a bitvector arithmetic shift right operation
0221   virtual SMTExprRef mkBVAshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0222 
0223   /// Creates a bitvector logical shift right operation
0224   virtual SMTExprRef mkBVLshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0225 
0226   /// Creates a bitvector negation operation
0227   virtual SMTExprRef mkBVNeg(const SMTExprRef &Exp) = 0;
0228 
0229   /// Creates a bitvector not operation
0230   virtual SMTExprRef mkBVNot(const SMTExprRef &Exp) = 0;
0231 
0232   /// Creates a bitvector xor operation
0233   virtual SMTExprRef mkBVXor(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0234 
0235   /// Creates a bitvector or operation
0236   virtual SMTExprRef mkBVOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0237 
0238   /// Creates a bitvector and operation
0239   virtual SMTExprRef mkBVAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0240 
0241   /// Creates a bitvector unsigned less-than operation
0242   virtual SMTExprRef mkBVUlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0243 
0244   /// Creates a bitvector signed less-than operation
0245   virtual SMTExprRef mkBVSlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0246 
0247   /// Creates a bitvector unsigned greater-than operation
0248   virtual SMTExprRef mkBVUgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0249 
0250   /// Creates a bitvector signed greater-than operation
0251   virtual SMTExprRef mkBVSgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0252 
0253   /// Creates a bitvector unsigned less-equal-than operation
0254   virtual SMTExprRef mkBVUle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0255 
0256   /// Creates a bitvector signed less-equal-than operation
0257   virtual SMTExprRef mkBVSle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0258 
0259   /// Creates a bitvector unsigned greater-equal-than operation
0260   virtual SMTExprRef mkBVUge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0261 
0262   /// Creates a bitvector signed greater-equal-than operation
0263   virtual SMTExprRef mkBVSge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0264 
0265   /// Creates a boolean not operation
0266   virtual SMTExprRef mkNot(const SMTExprRef &Exp) = 0;
0267 
0268   /// Creates a boolean equality operation
0269   virtual SMTExprRef mkEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0270 
0271   /// Creates a boolean and operation
0272   virtual SMTExprRef mkAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0273 
0274   /// Creates a boolean or operation
0275   virtual SMTExprRef mkOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0276 
0277   /// Creates a boolean ite operation
0278   virtual SMTExprRef mkIte(const SMTExprRef &Cond, const SMTExprRef &T,
0279                            const SMTExprRef &F) = 0;
0280 
0281   /// Creates a bitvector sign extension operation
0282   virtual SMTExprRef mkBVSignExt(unsigned i, const SMTExprRef &Exp) = 0;
0283 
0284   /// Creates a bitvector zero extension operation
0285   virtual SMTExprRef mkBVZeroExt(unsigned i, const SMTExprRef &Exp) = 0;
0286 
0287   /// Creates a bitvector extract operation
0288   virtual SMTExprRef mkBVExtract(unsigned High, unsigned Low,
0289                                  const SMTExprRef &Exp) = 0;
0290 
0291   /// Creates a bitvector concat operation
0292   virtual SMTExprRef mkBVConcat(const SMTExprRef &LHS,
0293                                 const SMTExprRef &RHS) = 0;
0294 
0295   /// Creates a predicate that checks for overflow in a bitvector addition
0296   /// operation
0297   virtual SMTExprRef mkBVAddNoOverflow(const SMTExprRef &LHS,
0298                                        const SMTExprRef &RHS,
0299                                        bool isSigned) = 0;
0300 
0301   /// Creates a predicate that checks for underflow in a signed bitvector
0302   /// addition operation
0303   virtual SMTExprRef mkBVAddNoUnderflow(const SMTExprRef &LHS,
0304                                         const SMTExprRef &RHS) = 0;
0305 
0306   /// Creates a predicate that checks for overflow in a signed bitvector
0307   /// subtraction operation
0308   virtual SMTExprRef mkBVSubNoOverflow(const SMTExprRef &LHS,
0309                                        const SMTExprRef &RHS) = 0;
0310 
0311   /// Creates a predicate that checks for underflow in a bitvector subtraction
0312   /// operation
0313   virtual SMTExprRef mkBVSubNoUnderflow(const SMTExprRef &LHS,
0314                                         const SMTExprRef &RHS,
0315                                         bool isSigned) = 0;
0316 
0317   /// Creates a predicate that checks for overflow in a signed bitvector
0318   /// division/modulus operation
0319   virtual SMTExprRef mkBVSDivNoOverflow(const SMTExprRef &LHS,
0320                                         const SMTExprRef &RHS) = 0;
0321 
0322   /// Creates a predicate that checks for overflow in a bitvector negation
0323   /// operation
0324   virtual SMTExprRef mkBVNegNoOverflow(const SMTExprRef &Exp) = 0;
0325 
0326   /// Creates a predicate that checks for overflow in a bitvector multiplication
0327   /// operation
0328   virtual SMTExprRef mkBVMulNoOverflow(const SMTExprRef &LHS,
0329                                        const SMTExprRef &RHS,
0330                                        bool isSigned) = 0;
0331 
0332   /// Creates a predicate that checks for underflow in a signed bitvector
0333   /// multiplication operation
0334   virtual SMTExprRef mkBVMulNoUnderflow(const SMTExprRef &LHS,
0335                                         const SMTExprRef &RHS) = 0;
0336 
0337   /// Creates a floating-point negation operation
0338   virtual SMTExprRef mkFPNeg(const SMTExprRef &Exp) = 0;
0339 
0340   /// Creates a floating-point isInfinite operation
0341   virtual SMTExprRef mkFPIsInfinite(const SMTExprRef &Exp) = 0;
0342 
0343   /// Creates a floating-point isNaN operation
0344   virtual SMTExprRef mkFPIsNaN(const SMTExprRef &Exp) = 0;
0345 
0346   /// Creates a floating-point isNormal operation
0347   virtual SMTExprRef mkFPIsNormal(const SMTExprRef &Exp) = 0;
0348 
0349   /// Creates a floating-point isZero operation
0350   virtual SMTExprRef mkFPIsZero(const SMTExprRef &Exp) = 0;
0351 
0352   /// Creates a floating-point multiplication operation
0353   virtual SMTExprRef mkFPMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0354 
0355   /// Creates a floating-point division operation
0356   virtual SMTExprRef mkFPDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0357 
0358   /// Creates a floating-point remainder operation
0359   virtual SMTExprRef mkFPRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0360 
0361   /// Creates a floating-point addition operation
0362   virtual SMTExprRef mkFPAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0363 
0364   /// Creates a floating-point subtraction operation
0365   virtual SMTExprRef mkFPSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0366 
0367   /// Creates a floating-point less-than operation
0368   virtual SMTExprRef mkFPLt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0369 
0370   /// Creates a floating-point greater-than operation
0371   virtual SMTExprRef mkFPGt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0372 
0373   /// Creates a floating-point less-than-or-equal operation
0374   virtual SMTExprRef mkFPLe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0375 
0376   /// Creates a floating-point greater-than-or-equal operation
0377   virtual SMTExprRef mkFPGe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
0378 
0379   /// Creates a floating-point equality operation
0380   virtual SMTExprRef mkFPEqual(const SMTExprRef &LHS,
0381                                const SMTExprRef &RHS) = 0;
0382 
0383   /// Creates a floating-point conversion from floatint-point to floating-point
0384   /// operation
0385   virtual SMTExprRef mkFPtoFP(const SMTExprRef &From, const SMTSortRef &To) = 0;
0386 
0387   /// Creates a floating-point conversion from signed bitvector to
0388   /// floatint-point operation
0389   virtual SMTExprRef mkSBVtoFP(const SMTExprRef &From,
0390                                const SMTSortRef &To) = 0;
0391 
0392   /// Creates a floating-point conversion from unsigned bitvector to
0393   /// floatint-point operation
0394   virtual SMTExprRef mkUBVtoFP(const SMTExprRef &From,
0395                                const SMTSortRef &To) = 0;
0396 
0397   /// Creates a floating-point conversion from floatint-point to signed
0398   /// bitvector operation
0399   virtual SMTExprRef mkFPtoSBV(const SMTExprRef &From, unsigned ToWidth) = 0;
0400 
0401   /// Creates a floating-point conversion from floatint-point to unsigned
0402   /// bitvector operation
0403   virtual SMTExprRef mkFPtoUBV(const SMTExprRef &From, unsigned ToWidth) = 0;
0404 
0405   /// Creates a new symbol, given a name and a sort
0406   virtual SMTExprRef mkSymbol(const char *Name, SMTSortRef Sort) = 0;
0407 
0408   // Returns an appropriate floating-point rounding mode.
0409   virtual SMTExprRef getFloatRoundingMode() = 0;
0410 
0411   // If the a model is available, returns the value of a given bitvector symbol
0412   virtual llvm::APSInt getBitvector(const SMTExprRef &Exp, unsigned BitWidth,
0413                                     bool isUnsigned) = 0;
0414 
0415   // If the a model is available, returns the value of a given boolean symbol
0416   virtual bool getBoolean(const SMTExprRef &Exp) = 0;
0417 
0418   /// Constructs an SMTExprRef from a boolean.
0419   virtual SMTExprRef mkBoolean(const bool b) = 0;
0420 
0421   /// Constructs an SMTExprRef from a finite APFloat.
0422   virtual SMTExprRef mkFloat(const llvm::APFloat Float) = 0;
0423 
0424   /// Constructs an SMTExprRef from an APSInt and its bit width
0425   virtual SMTExprRef mkBitvector(const llvm::APSInt Int, unsigned BitWidth) = 0;
0426 
0427   /// Given an expression, extract the value of this operand in the model.
0428   virtual bool getInterpretation(const SMTExprRef &Exp, llvm::APSInt &Int) = 0;
0429 
0430   /// Given an expression extract the value of this operand in the model.
0431   virtual bool getInterpretation(const SMTExprRef &Exp,
0432                                  llvm::APFloat &Float) = 0;
0433 
0434   /// Check if the constraints are satisfiable
0435   virtual std::optional<bool> check() const = 0;
0436 
0437   /// Push the current solver state
0438   virtual void push() = 0;
0439 
0440   /// Pop the previous solver state
0441   virtual void pop(unsigned NumStates = 1) = 0;
0442 
0443   /// Reset the solver and remove all constraints.
0444   virtual void reset() = 0;
0445 
0446   /// Checks if the solver supports floating-points.
0447   virtual bool isFPSupported() = 0;
0448 
0449   virtual void print(raw_ostream &OS) const = 0;
0450 
0451   /// Sets the requested option.
0452   virtual void setBoolParam(StringRef Key, bool Value) = 0;
0453   virtual void setUnsignedParam(StringRef Key, unsigned Value) = 0;
0454 
0455   virtual std::unique_ptr<SMTSolverStatistics> getStatistics() const = 0;
0456 };
0457 
0458 /// Shared pointer for SMTSolvers.
0459 using SMTSolverRef = std::shared_ptr<SMTSolver>;
0460 
0461 /// Convenience method to create and Z3Solver object
0462 SMTSolverRef CreateZ3Solver();
0463 
0464 } // namespace llvm
0465 
0466 #endif