ProgramStateRef SimpleConstraintManager::assumeInclusiveRange( ProgramStateRef State, NonLoc Value, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange) { assert(From.isUnsigned() == To.isUnsigned() && From.getBitWidth() == To.getBitWidth() && "Values should have same types!"); if (!canReasonAbout(Value)) { // Just add the constraint to the expression without trying to simplify. SymbolRef Sym = Value.getAsSymExpr(); assert(Sym); return assumeSymWithinInclusiveRange(State, Sym, From, To, InRange); } switch (Value.getSubKind()) { default: llvm_unreachable("'assumeInclusiveRange' is not implemented" "for this NonLoc"); case nonloc::LocAsIntegerKind: case nonloc::SymbolValKind: { if (SymbolRef Sym = Value.getAsSymbol()) return assumeSymWithinInclusiveRange(State, Sym, From, To, InRange); return State; } // end switch case nonloc::ConcreteIntKind: { const llvm::APSInt &IntVal = Value.castAs<nonloc::ConcreteInt>().getValue(); bool IsInRange = IntVal >= From && IntVal <= To; bool isFeasible = (IsInRange == InRange); return isFeasible ? State : nullptr; } } // end switch }
DWARFExpression lldb_private::npdb::MakeConstantLocationExpression( TypeIndex underlying_ti, TpiStream &tpi, const llvm::APSInt &constant, ModuleSP module) { const ArchSpec &architecture = module->GetArchitecture(); uint32_t address_size = architecture.GetAddressByteSize(); size_t size = 0; bool is_signed = false; std::tie(size, is_signed) = GetIntegralTypeInfo(underlying_ti, tpi); union { llvm::support::little64_t I; llvm::support::ulittle64_t U; } Value; std::shared_ptr<DataBufferHeap> buffer = std::make_shared<DataBufferHeap>(); buffer->SetByteSize(size); llvm::ArrayRef<uint8_t> bytes; if (is_signed) { Value.I = constant.getSExtValue(); } else { Value.U = constant.getZExtValue(); } bytes = llvm::makeArrayRef(reinterpret_cast<const uint8_t *>(&Value), 8) .take_front(size); buffer->CopyData(bytes.data(), size); DataExtractor extractor(buffer, lldb::eByteOrderLittle, address_size); DWARFExpression result(nullptr, extractor, nullptr, 0, size); return result; }
APSIntType::RangeTestResultKind APSIntType::testInRange(const llvm::APSInt &Value, bool AllowSignConversions) const { // Negative numbers cannot be losslessly converted to unsigned type. if (IsUnsigned && !AllowSignConversions && Value.isSigned() && Value.isNegative()) return RTR_Below; unsigned MinBits; if (AllowSignConversions) { if (Value.isSigned() && !IsUnsigned) MinBits = Value.getMinSignedBits(); else MinBits = Value.getActiveBits(); } else { // Signed integers can be converted to signed integers of the same width // or (if positive) unsigned integers with one fewer bit. // Unsigned integers can be converted to unsigned integers of the same width // or signed integers with one more bit. if (Value.isSigned()) MinBits = Value.getMinSignedBits() - IsUnsigned; else MinBits = Value.getActiveBits() + !IsUnsigned; } if (MinBits <= BitWidth) return RTR_Within; if (Value.isSigned() && Value.isNegative()) return RTR_Below; else return RTR_Above; }
ProgramStateRef BasicConstraintManager::assumeSymLE(ProgramStateRef state, SymbolRef sym, const llvm::APSInt &V, const llvm::APSInt &Adjustment) { // Reject a path if the value of sym is a constant X and !(X+Adj <= V). if (const llvm::APSInt* X = getSymVal(state, sym)) { bool isFeasible = (*X <= V-Adjustment); return isFeasible ? state : NULL; } // Sym is not a constant, but it is worth looking to see if V is the // minimum integer value. if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) { llvm::APSInt Adjusted = V-Adjustment; // If we know that sym != V (after adjustment), then this condition // is infeasible since there is no other value less than V. bool isFeasible = !isNotEqual(state, sym, Adjusted); // If the path is still feasible then as a consequence we know that // 'sym+Adjustment == V' because there are no smaller values. // Add this constraint. return isFeasible ? AddEQ(state, sym, Adjusted) : NULL; } return state; }
ProgramStateRef BasicConstraintManager::assumeSymGT(ProgramStateRef state, SymbolRef sym, const llvm::APSInt &V, const llvm::APSInt &Adjustment) { // Is 'V' the largest possible value? if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) { // sym cannot be any value greater than 'V'. This path is infeasible. return NULL; } // FIXME: For now have assuming x > y be the same as assuming sym != V; return assumeSymNE(state, sym, V, Adjustment); }
bool LiteralAnalyser::checkRange(QualType TLeft, const Expr* Right, clang::SourceLocation Loc, llvm::APSInt Result) { // TODO refactor with check() const QualType QT = TLeft.getCanonicalType(); int availableWidth = 0; if (QT.isBuiltinType()) { const BuiltinType* TL = cast<BuiltinType>(QT); if (!TL->isInteger()) { // TODO floats return false; } availableWidth = TL->getIntegerWidth(); } else { QT.dump(); assert(0 && "todo"); } const Limit* L = getLimit(availableWidth); assert(Result.isSigned() && "TEMP FOR NOW"); int64_t value = Result.getSExtValue(); bool overflow = false; if (Result.isNegative()) { const int64_t limit = L->minVal; if (value < limit) overflow = true; } else { const int64_t limit = (int64_t)L->maxVal; if (value > limit) overflow = true; } //fprintf(stderr, "VAL=%lld width=%d signed=%d\n", value, availableWidth, Result.isSigned()); if (overflow) { SmallString<20> ss; Result.toString(ss, 10, true); StringBuilder buf1; TLeft->DiagName(buf1); if (Right) { Diags.Report(Right->getLocStart(), diag::err_literal_outofbounds) << buf1 << L->minStr << L->maxStr << ss << Right->getSourceRange(); } else { Diags.Report(Loc, diag::err_literal_outofbounds) << buf1 << L->minStr << L->maxStr << ss; } return false; } return true; }
TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type) { Integer.Kind = Integral; // Copy the APSInt value into our decomposed form. Integer.BitWidth = Value.getBitWidth(); Integer.IsUnsigned = Value.isUnsigned(); // If the value is large, we have to get additional memory from the ASTContext unsigned NumWords = Value.getNumWords(); if (NumWords > 1) { void *Mem = Ctx.Allocate(NumWords * sizeof(uint64_t)); std::memcpy(Mem, Value.getRawData(), NumWords * sizeof(uint64_t)); Integer.pVal = static_cast<uint64_t *>(Mem); } else { Integer.VAL = Value.getZExtValue(); } Integer.Type = Type.getAsOpaquePtr(); }
SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS, BinaryOperator::Opcode op, const llvm::APSInt &RHS, QualType resultTy) { bool isIdempotent = false; // Check for a few special cases with known reductions first. switch (op) { default: // We can't reduce this case; just treat it normally. break; case BO_Mul: // a*0 and a*1 if (RHS == 0) return makeIntVal(0, resultTy); else if (RHS == 1) isIdempotent = true; break; case BO_Div: // a/0 and a/1 if (RHS == 0) // This is also handled elsewhere. return UndefinedVal(); else if (RHS == 1) isIdempotent = true; break; case BO_Rem: // a%0 and a%1 if (RHS == 0) // This is also handled elsewhere. return UndefinedVal(); else if (RHS == 1) return makeIntVal(0, resultTy); break; case BO_Add: case BO_Sub: case BO_Shl: case BO_Shr: case BO_Xor: // a+0, a-0, a<<0, a>>0, a^0 if (RHS == 0) isIdempotent = true; break; case BO_And: // a&0 and a&(~0) if (RHS == 0) return makeIntVal(0, resultTy); else if (RHS.isAllOnesValue()) isIdempotent = true; break; case BO_Or: // a|0 and a|(~0) if (RHS == 0) isIdempotent = true; else if (RHS.isAllOnesValue()) { const llvm::APSInt &Result = BasicVals.Convert(resultTy, RHS); return nonloc::ConcreteInt(Result); } break; } // Idempotent ops (like a*1) can still change the type of an expression. // Wrap the LHS up in a NonLoc again and let evalCastFromNonLoc do the // dirty work. if (isIdempotent) return evalCastFromNonLoc(nonloc::SymbolVal(LHS), resultTy); // If we reach this point, the expression cannot be simplified. // Make a SymbolVal for the entire expression, after converting the RHS. const llvm::APSInt *ConvertedRHS = &RHS; if (BinaryOperator::isComparisonOp(op)) { // We're looking for a type big enough to compare the symbolic value // with the given constant. // FIXME: This is an approximation of Sema::UsualArithmeticConversions. ASTContext &Ctx = getContext(); QualType SymbolType = LHS->getType(); uint64_t ValWidth = RHS.getBitWidth(); uint64_t TypeWidth = Ctx.getTypeSize(SymbolType); if (ValWidth < TypeWidth) { // If the value is too small, extend it. ConvertedRHS = &BasicVals.Convert(SymbolType, RHS); } else if (ValWidth == TypeWidth) { // If the value is signed but the symbol is unsigned, do the comparison // in unsigned space. [C99 6.3.1.8] // (For the opposite case, the value is already unsigned.) if (RHS.isSigned() && !SymbolType->isSignedIntegerOrEnumerationType()) ConvertedRHS = &BasicVals.Convert(SymbolType, RHS); } } else ConvertedRHS = &BasicVals.Convert(resultTy, RHS); return makeNonLoc(LHS, op, *ConvertedRHS, resultTy); }
bool isUnsigned() const { return Val.isUnsigned(); }
unsigned getBitWidth() const { return Val.getBitWidth(); }
/// \brief Determine if two APSInts have the same value, zero- or sign-extending /// as needed. static bool IsSameValue(const llvm::APSInt &I1, const llvm::APSInt &I2) { if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) return I1 == I2; // Check for a bit-width mismatch. if (I1.getBitWidth() > I2.getBitWidth()) return IsSameValue(I1, I2.extend(I1.getBitWidth())); else if (I2.getBitWidth() > I1.getBitWidth()) return IsSameValue(I1.extend(I2.getBitWidth()), I2); // We have a signedness mismatch. Turn the signed value into an unsigned // value. if (I1.isSigned()) { if (I1.isNegative()) return false; return llvm::APSInt(I1, true) == I2; } if (I2.isNegative()) return false; return I1 == llvm::APSInt(I2, true); }
SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS, BinaryOperator::Opcode op, const llvm::APSInt &RHS, QualType resultTy) { bool isIdempotent = false; // Check for a few special cases with known reductions first. switch (op) { default: // We can't reduce this case; just treat it normally. break; case BO_Mul: // a*0 and a*1 if (RHS == 0) return makeIntVal(0, resultTy); else if (RHS == 1) isIdempotent = true; break; case BO_Div: // a/0 and a/1 if (RHS == 0) // This is also handled elsewhere. return UndefinedVal(); else if (RHS == 1) isIdempotent = true; break; case BO_Rem: // a%0 and a%1 if (RHS == 0) // This is also handled elsewhere. return UndefinedVal(); else if (RHS == 1) return makeIntVal(0, resultTy); break; case BO_Add: case BO_Sub: case BO_Shl: case BO_Shr: case BO_Xor: // a+0, a-0, a<<0, a>>0, a^0 if (RHS == 0) isIdempotent = true; break; case BO_And: // a&0 and a&(~0) if (RHS == 0) return makeIntVal(0, resultTy); else if (RHS.isAllOnesValue()) isIdempotent = true; break; case BO_Or: // a|0 and a|(~0) if (RHS == 0) isIdempotent = true; else if (RHS.isAllOnesValue()) { const llvm::APSInt &Result = BasicVals.Convert(resultTy, RHS); return nonloc::ConcreteInt(Result); } break; } // Idempotent ops (like a*1) can still change the type of an expression. // Wrap the LHS up in a NonLoc again and let evalCastFromNonLoc do the // dirty work. if (isIdempotent) { if (SymbolRef LHSSym = dyn_cast<SymbolData>(LHS)) return evalCastFromNonLoc(nonloc::SymbolVal(LHSSym), resultTy); return evalCastFromNonLoc(nonloc::SymExprVal(LHS), resultTy); } // If we reach this point, the expression cannot be simplified. // Make a SymExprVal for the entire thing. return makeNonLoc(LHS, op, RHS, resultTy); }