13 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONV_H 14 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONV_H 19 #include "llvm/Support/SMTAPI.h" 27 static inline llvm::SMTSortRef
mkSort(llvm::SMTSolverRef &Solver,
28 const QualType &Ty,
unsigned BitWidth) {
30 return Solver->getBoolSort();
33 return Solver->getFloatSort(BitWidth);
35 return Solver->getBitvectorSort(BitWidth);
39 static inline llvm::SMTExprRef
fromUnOp(llvm::SMTSolverRef &Solver,
41 const llvm::SMTExprRef &Exp) {
44 return Solver->mkBVNeg(Exp);
47 return Solver->mkBVNot(Exp);
50 return Solver->mkNot(Exp);
54 llvm_unreachable(
"Unimplemented opcode");
58 static inline llvm::SMTExprRef
fromFloatUnOp(llvm::SMTSolverRef &Solver,
60 const llvm::SMTExprRef &Exp) {
63 return Solver->mkFPNeg(Exp);
70 llvm_unreachable(
"Unimplemented opcode");
74 static inline llvm::SMTExprRef
76 const std::vector<llvm::SMTExprRef> &ASTs) {
77 assert(!ASTs.empty());
79 if (Op != BO_LAnd && Op != BO_LOr)
80 llvm_unreachable(
"Unimplemented opcode");
82 llvm::SMTExprRef res = ASTs.front();
84 res = (Op == BO_LAnd) ? Solver->mkAnd(res, ASTs[i])
85 : Solver->mkOr(res, ASTs[i]);
90 static inline llvm::SMTExprRef
fromBinOp(llvm::SMTSolverRef &Solver,
91 const llvm::SMTExprRef &LHS,
93 const llvm::SMTExprRef &RHS,
95 assert(*Solver->getSort(LHS) == *Solver->getSort(RHS) &&
96 "AST's must have the same sort!");
101 return Solver->mkBVMul(LHS, RHS);
104 return isSigned ? Solver->mkBVSDiv(LHS, RHS) : Solver->mkBVUDiv(LHS, RHS);
107 return isSigned ? Solver->mkBVSRem(LHS, RHS) : Solver->mkBVURem(LHS, RHS);
111 return Solver->mkBVAdd(LHS, RHS);
114 return Solver->mkBVSub(LHS, RHS);
118 return Solver->mkBVShl(LHS, RHS);
121 return isSigned ? Solver->mkBVAshr(LHS, RHS) : Solver->mkBVLshr(LHS, RHS);
125 return isSigned ? Solver->mkBVSlt(LHS, RHS) : Solver->mkBVUlt(LHS, RHS);
128 return isSigned ? Solver->mkBVSgt(LHS, RHS) : Solver->mkBVUgt(LHS, RHS);
131 return isSigned ? Solver->mkBVSle(LHS, RHS) : Solver->mkBVUle(LHS, RHS);
134 return isSigned ? Solver->mkBVSge(LHS, RHS) : Solver->mkBVUge(LHS, RHS);
138 return Solver->mkEqual(LHS, RHS);
142 fromBinOp(Solver, LHS, BO_EQ, RHS, isSigned));
146 return Solver->mkBVAnd(LHS, RHS);
149 return Solver->mkBVXor(LHS, RHS);
152 return Solver->mkBVOr(LHS, RHS);
156 return Solver->mkAnd(LHS, RHS);
159 return Solver->mkOr(LHS, RHS);
163 llvm_unreachable(
"Unimplemented opcode");
168 static inline llvm::SMTExprRef
171 const llvm::APFloat::fltCategory &RHS) {
176 case llvm::APFloat::fcInfinity:
177 return Solver->mkFPIsInfinite(LHS);
179 case llvm::APFloat::fcNaN:
180 return Solver->mkFPIsNaN(LHS);
182 case llvm::APFloat::fcNormal:
183 return Solver->mkFPIsNormal(LHS);
185 case llvm::APFloat::fcZero:
186 return Solver->mkFPIsZero(LHS);
197 llvm_unreachable(
"Unimplemented opcode");
202 const llvm::SMTExprRef &LHS,
204 const llvm::SMTExprRef &RHS) {
205 assert(*Solver->getSort(LHS) == *Solver->getSort(RHS) &&
206 "AST's must have the same sort!");
211 return Solver->mkFPMul(LHS, RHS);
214 return Solver->mkFPDiv(LHS, RHS);
217 return Solver->mkFPRem(LHS, RHS);
221 return Solver->mkFPAdd(LHS, RHS);
224 return Solver->mkFPSub(LHS, RHS);
228 return Solver->mkFPLt(LHS, RHS);
231 return Solver->mkFPGt(LHS, RHS);
234 return Solver->mkFPLe(LHS, RHS);
237 return Solver->mkFPGe(LHS, RHS);
241 return Solver->mkFPEqual(LHS, RHS);
250 return fromBinOp(Solver, LHS, Op, RHS,
false);
255 llvm_unreachable(
"Unimplemented opcode");
260 static inline llvm::SMTExprRef
fromCast(llvm::SMTSolverRef &Solver,
261 const llvm::SMTExprRef &Exp,
264 uint64_t FromBitWidth) {
272 assert(ToBitWidth > 0 &&
"BitWidth must be positive!");
273 return Solver->mkIte(
274 Exp, Solver->mkBitvector(
llvm::APSInt(
"1"), ToBitWidth),
278 if (ToBitWidth > FromBitWidth)
280 ? Solver->mkBVSignExt(ToBitWidth - FromBitWidth, Exp)
281 : Solver->mkBVZeroExt(ToBitWidth - FromBitWidth, Exp);
283 if (ToBitWidth < FromBitWidth)
284 return Solver->mkBVExtract(ToBitWidth - 1, 0, Exp);
291 if (ToBitWidth != FromBitWidth)
292 return Solver->mkFPtoFP(Exp, Solver->getFloatSort(ToBitWidth));
298 llvm::SMTSortRef Sort = Solver->getFloatSort(ToBitWidth);
300 ? Solver->mkSBVtoFP(Exp, Sort)
301 : Solver->mkUBVtoFP(Exp, Sort);
306 ? Solver->mkFPtoSBV(Exp, ToBitWidth)
307 : Solver->mkFPtoUBV(Exp, ToBitWidth);
309 llvm_unreachable(
"Unsupported explicit type cast!");
316 uint64_t FromWidth) {
322 static inline llvm::SMTExprRef
fromData(llvm::SMTSolverRef &Solver,
325 llvm::Twine Name =
"$" + llvm::Twine(ID);
326 return Solver->mkSymbol(Name.str().c_str(),
mkSort(Solver, Ty, BitWidth));
330 static inline llvm::SMTExprRef
getCastExpr(llvm::SMTSolverRef &Solver,
332 const llvm::SMTExprRef &Exp,
340 static inline llvm::SMTExprRef
342 const llvm::SMTExprRef &LHS,
QualType LTy,
345 llvm::SMTExprRef NewLHS = LHS;
346 llvm::SMTExprRef NewRHS = RHS;
384 if (
const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) {
385 llvm::SMTExprRef LHS =
386 getSymExpr(Solver, Ctx, SIE->getLHS(), <y, hasComparison);
388 std::tie(NewRInt, RTy) =
fixAPSInt(Ctx, SIE->getRHS());
389 llvm::SMTExprRef RHS =
390 Solver->mkBitvector(NewRInt, NewRInt.getBitWidth());
391 return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
394 if (
const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
396 std::tie(NewLInt, LTy) =
fixAPSInt(Ctx, ISE->getLHS());
397 llvm::SMTExprRef LHS =
398 Solver->mkBitvector(NewLInt, NewLInt.getBitWidth());
399 llvm::SMTExprRef RHS =
400 getSymExpr(Solver, Ctx, ISE->getRHS(), &RTy, hasComparison);
401 return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
404 if (
const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) {
405 llvm::SMTExprRef LHS =
406 getSymExpr(Solver, Ctx, SSM->getLHS(), <y, hasComparison);
407 llvm::SMTExprRef RHS =
408 getSymExpr(Solver, Ctx, SSM->getRHS(), &RTy, hasComparison);
409 return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
412 llvm_unreachable(
"Unsupported BinarySymExpr type!");
417 static inline llvm::SMTExprRef
getSymExpr(llvm::SMTSolverRef &Solver,
420 bool *hasComparison) {
421 if (
const SymbolData *SD = dyn_cast<SymbolData>(Sym)) {
429 if (
const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
434 llvm::SMTExprRef Exp =
435 getSymExpr(Solver, Ctx, SC->getOperand(), &FromTy, hasComparison);
441 *hasComparison =
false;
445 if (
const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
446 llvm::SMTExprRef Exp =
454 llvm_unreachable(
"Unsupported SymbolRef type!");
461 static inline llvm::SMTExprRef
getExpr(llvm::SMTSolverRef &Solver,
464 bool *hasComparison =
nullptr) {
466 *hasComparison =
false;
469 return getSymExpr(Solver, Ctx, Sym, RetTy, hasComparison);
473 static inline llvm::SMTExprRef
getZeroExpr(llvm::SMTSolverRef &Solver,
475 const llvm::SMTExprRef &Exp,
481 Solver->mkFloat(Zero));
490 return Assumption ?
fromUnOp(Solver, UO_LNot, Exp) : Exp;
493 Solver, Exp, Assumption ? BO_EQ : BO_NE,
498 llvm_unreachable(
"Unsupported type for zero value!");
503 static inline llvm::SMTExprRef
509 std::tie(NewFromInt, FromTy) =
fixAPSInt(Ctx, From);
510 llvm::SMTExprRef FromExp =
511 Solver->mkBitvector(NewFromInt, NewFromInt.getBitWidth());
515 llvm::SMTExprRef Exp =
getExpr(Solver, Ctx, Sym, &SymTy);
519 return getBinExpr(Solver, Ctx, Exp, SymTy, InRange ? BO_EQ : BO_NE,
520 FromExp, FromTy,
nullptr);
524 std::tie(NewToInt, ToTy) =
fixAPSInt(Ctx, To);
525 llvm::SMTExprRef ToExp =
526 Solver->mkBitvector(NewToInt, NewToInt.getBitWidth());
527 assert(FromTy == ToTy &&
"Range values have different types!");
530 llvm::SMTExprRef LHS =
531 getBinExpr(Solver, Ctx, Exp, SymTy, InRange ? BO_GE : BO_LT, FromExp,
533 llvm::SMTExprRef RHS =
getBinExpr(Solver, Ctx, Exp, SymTy,
534 InRange ? BO_LE : BO_GT, ToExp, ToTy,
537 return fromBinOp(Solver, LHS, InRange ? BO_LAnd : BO_LOr, RHS,
549 static inline std::pair<llvm::APSInt, QualType>
569 llvm::SMTExprRef &RHS,
QualType <y,
571 assert(!LTy.
isNull() && !RTy.
isNull() &&
"Input type is null!");
577 SMTConv::doIntTypeConversion<llvm::SMTExprRef, &fromCast>(
578 Solver, Ctx, LHS, LTy, RHS, RTy);
583 SMTConv::doFloatTypeConversion<llvm::SMTExprRef, &fromCast>(
584 Solver, Ctx, LHS, LTy, RHS, RTy);
604 LHS =
fromCast(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
607 RHS =
fromCast(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
618 "Pointer types have different bitwidths!");
642 template <
typename T, T (*doCast)(llvm::SMTSolverRef &Solver,
const T &,
643 QualType, uint64_t, QualType, uint64_t)>
646 T &RHS, QualType &RTy) {
650 assert(!LTy.
isNull() && !RTy.
isNull() &&
"Input type is null!");
656 LHS = (*doCast)(Solver, LHS, NewTy, NewBitWidth, LTy, LBitWidth);
658 LBitWidth = NewBitWidth;
663 RHS = (*doCast)(Solver, RHS, NewTy, NewBitWidth, RTy, RBitWidth);
665 RBitWidth = NewBitWidth;
677 if (isLSignedTy == isRSignedTy) {
680 RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
683 LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
686 }
else if (order != (isLSignedTy ? 1 : -1)) {
690 RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
693 LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
696 }
else if (LBitWidth != RBitWidth) {
701 RHS = (doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
704 LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
714 RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
716 LHS = (doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
724 template <
typename T, T (*doCast)(llvm::SMTSolverRef &Solver,
const T &,
725 QualType, uint64_t, QualType, uint64_t)>
728 QualType <y, T &RHS, QualType &RTy) {
734 LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
736 LBitWidth = RBitWidth;
739 RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
741 RBitWidth = LBitWidth;
752 RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
754 }
else if (order == 0) {
755 LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
758 llvm_unreachable(
"Unsupported floating-point type cast!");
static llvm::SMTExprRef fromUnOp(llvm::SMTSolverRef &Solver, const UnaryOperator::Opcode Op, const llvm::SMTExprRef &Exp)
Constructs an SMTSolverRef from an unary operator.
static QualType getAPSIntType(ASTContext &Ctx, const llvm::APSInt &Int)
A (possibly-)qualified type.
int getIntegerTypeOrder(QualType LHS, QualType RHS) const
Return the highest ranked integer type, see C99 6.3.1.8p1.
bool isBlockPointerType() const
static llvm::SMTExprRef getSymBinExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, const BinarySymExpr *BSE, bool *hasComparison, QualType *RetTy)
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
bool isArithmeticType() const
bool isRealFloatingType() const
Floating point categories.
QualType getCorrespondingUnsignedType(QualType T) const
static llvm::SMTExprRef fromFloatUnOp(llvm::SMTSolverRef &Solver, const UnaryOperator::Opcode Op, const llvm::SMTExprRef &Exp)
Constructs an SMTSolverRef from a floating-point unary operator.
static void doIntTypeConversion(llvm::SMTSolverRef &Solver, ASTContext &Ctx, T &LHS, QualType <y, T &RHS, QualType &RTy)
static std::pair< llvm::APSInt, QualType > fixAPSInt(ASTContext &Ctx, const llvm::APSInt &Int)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
static llvm::SMTSortRef mkSort(llvm::SMTSolverRef &Solver, const QualType &Ty, unsigned BitWidth)
bool Zero(InterpState &S, CodePtr OpPC)
bool isReferenceType() const
static llvm::SMTExprRef fromNBinOp(llvm::SMTSolverRef &Solver, const BinaryOperator::Opcode Op, const std::vector< llvm::SMTExprRef > &ASTs)
Construct an SMTSolverRef from a n-ary binary operator.
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
static void doFloatTypeConversion(llvm::SMTSolverRef &Solver, ASTContext &Ctx, T &LHS, QualType <y, T &RHS, QualType &RTy)
A record of the "type" of an APSInt, used for conversions.
Represents a symbolic expression like 'x' + 3.
virtual QualType getType() const =0
bool isPromotableIntegerType() const
More type predicates useful for type checking/promotion.
static llvm::SMTExprRef getCastExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, const llvm::SMTExprRef &Exp, QualType FromTy, QualType ToTy)
QualType getPromotedIntegerType(QualType PromotableType) const
Return the type that PromotableType will promote to: C99 6.3.1.1p2, assuming that PromotableType is a...
static llvm::SMTExprRef getZeroExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, const llvm::SMTExprRef &Exp, QualType Ty, bool Assumption)
bool isNullPtrType() const
Represents a cast expression.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
bool isVoidPointerType() const
bool isComparisonOp() const
QualType getCanonicalType() const
static llvm::SMTExprRef getExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, QualType *RetTy=nullptr, bool *hasComparison=nullptr)
bool InRange(InterpState &S, CodePtr OpPC)
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Represents a symbolic expression like 3 - 'x'.
bool isObjCObjectPointerType() const
bool isAnyPointerType() const
static llvm::SMTExprRef getBinExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, const llvm::SMTExprRef &LHS, QualType LTy, BinaryOperator::Opcode Op, const llvm::SMTExprRef &RHS, QualType RTy, QualType *RetTy)
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
llvm::APSInt convert(const llvm::APSInt &Value) const LLVM_READONLY
Convert and return a new APSInt with the given value, but this type's bit width and signedness...
Dataflow Directional Tag Classes.
int getFloatingTypeOrder(QualType LHS, QualType RHS) const
Compare the rank of the two specified floating point types, ignoring the domain of the type (i...
Represents a symbolic expression involving a binary operator.
static llvm::SMTExprRef fromBinOp(llvm::SMTSolverRef &Solver, const llvm::SMTExprRef &LHS, const BinaryOperator::Opcode Op, const llvm::SMTExprRef &RHS, bool isSigned)
Construct an SMTSolverRef from a binary operator.
bool isBooleanType() const
static void doTypeConversion(llvm::SMTSolverRef &Solver, ASTContext &Ctx, llvm::SMTExprRef &LHS, llvm::SMTExprRef &RHS, QualType <y, QualType &RTy)
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
static llvm::SMTExprRef fromData(llvm::SMTSolverRef &Solver, const SymbolID ID, const QualType &Ty, uint64_t BitWidth)
Construct an SMTSolverRef from a SymbolData.
static llvm::SMTExprRef getSymExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, QualType *RetTy, bool *hasComparison)
static llvm::SMTExprRef fromFloatBinOp(llvm::SMTSolverRef &Solver, const llvm::SMTExprRef &LHS, const BinaryOperator::Opcode Op, const llvm::SMTExprRef &RHS)
Construct an SMTSolverRef from a floating-point binary operator.
BinaryOperator::Opcode getOpcode() const
static llvm::SMTExprRef fromFloatSpecialBinOp(llvm::SMTSolverRef &Solver, const llvm::SMTExprRef &LHS, const BinaryOperator::Opcode Op, const llvm::APFloat::fltCategory &RHS)
Construct an SMTSolverRef from a special floating-point binary operator.
static llvm::APSInt castAPSInt(llvm::SMTSolverRef &Solver, const llvm::APSInt &V, QualType ToTy, uint64_t ToWidth, QualType FromTy, uint64_t FromWidth)
static llvm::SMTExprRef fromCast(llvm::SMTSolverRef &Solver, const llvm::SMTExprRef &Exp, QualType ToTy, uint64_t ToBitWidth, QualType FromTy, uint64_t FromBitWidth)
Construct an SMTSolverRef from a QualType FromTy to a QualType ToTy, and their bit widths...
Represents a symbolic expression like 'x' + 'y'.
A symbol representing data which can be stored in a memory location (region).
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth, signed/unsigned.
static llvm::SMTExprRef getRangeExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange)