mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[SMTChecker] Support to bitwise
This commit is contained in:
@@ -701,7 +701,7 @@ vector<smtutil::SortPointer> CHC::stateSorts(ContractDefinition const& _contract
|
||||
smtutil::SortPointer CHC::constructorSort()
|
||||
{
|
||||
return make_shared<smtutil::FunctionSort>(
|
||||
vector<smtutil::SortPointer>{smtutil::SortProvider::intSort} + m_stateSorts,
|
||||
vector<smtutil::SortPointer>{smtutil::SortProvider::uintSort} + m_stateSorts,
|
||||
smtutil::SortProvider::boolSort
|
||||
);
|
||||
}
|
||||
@@ -747,7 +747,7 @@ smtutil::SortPointer CHC::sort(FunctionDefinition const& _function)
|
||||
auto inputSorts = applyMap(_function.parameters(), smtSort);
|
||||
auto outputSorts = applyMap(_function.returnParameters(), smtSort);
|
||||
return make_shared<smtutil::FunctionSort>(
|
||||
vector<smtutil::SortPointer>{smtutil::SortProvider::intSort} + m_stateSorts + inputSorts + m_stateSorts + inputSorts + outputSorts,
|
||||
vector<smtutil::SortPointer>{smtutil::SortProvider::uintSort} + m_stateSorts + inputSorts + m_stateSorts + inputSorts + outputSorts,
|
||||
smtutil::SortProvider::boolSort
|
||||
);
|
||||
}
|
||||
@@ -776,7 +776,7 @@ smtutil::SortPointer CHC::summarySort(FunctionDefinition const& _function, Contr
|
||||
auto inputSorts = applyMap(_function.parameters(), smtSort);
|
||||
auto outputSorts = applyMap(_function.returnParameters(), smtSort);
|
||||
return make_shared<smtutil::FunctionSort>(
|
||||
vector<smtutil::SortPointer>{smtutil::SortProvider::intSort} + sorts + inputSorts + sorts + outputSorts,
|
||||
vector<smtutil::SortPointer>{smtutil::SortProvider::uintSort} + sorts + inputSorts + sorts + outputSorts,
|
||||
smtutil::SortProvider::boolSort
|
||||
);
|
||||
}
|
||||
|
||||
@@ -574,6 +574,8 @@ void SMTEncoder::endVisit(BinaryOperation const& _op)
|
||||
arithmeticOperation(_op);
|
||||
else if (TokenTraits::isCompareOp(_op.getOperator()))
|
||||
compareOperation(_op);
|
||||
else if (TokenTraits::isBitOp(_op.getOperator()))
|
||||
bitwiseOperation(_op);
|
||||
else
|
||||
m_errorReporter.warning(
|
||||
3876_error,
|
||||
@@ -1346,6 +1348,43 @@ void SMTEncoder::booleanOperation(BinaryOperation const& _op)
|
||||
);
|
||||
}
|
||||
|
||||
void SMTEncoder::bitwiseOperation(BinaryOperation const& _op)
|
||||
{
|
||||
solAssert(TokenTraits::isBitOp(_op.getOperator()), "");
|
||||
auto commonType = _op.annotation().commonType;
|
||||
solAssert(commonType, "");
|
||||
|
||||
unsigned bvSize = 256;
|
||||
bool isSigned = false;
|
||||
if (auto const* intType = dynamic_cast<IntegerType const*>(commonType))
|
||||
{
|
||||
bvSize = intType->numBits();
|
||||
isSigned = intType->isSigned();
|
||||
}
|
||||
else if (auto const* fixedType = dynamic_cast<FixedPointType const*>(commonType))
|
||||
{
|
||||
bvSize = fixedType->numBits();
|
||||
isSigned = fixedType->isSigned();
|
||||
}
|
||||
|
||||
auto bvLeft = smtutil::Expression::int2bv(expr(_op.leftExpression()), bvSize);
|
||||
auto bvRight = smtutil::Expression::int2bv(expr(_op.rightExpression()), bvSize);
|
||||
|
||||
optional<smtutil::Expression> result;
|
||||
if (_op.getOperator() == Token::BitAnd)
|
||||
result = bvLeft & bvRight;
|
||||
// TODO implement the other operators
|
||||
else
|
||||
m_errorReporter.warning(
|
||||
1093_error,
|
||||
_op.location(),
|
||||
"Assertion checker does not yet implement this bitwise operator."
|
||||
);
|
||||
|
||||
if (result)
|
||||
defineExpr(_op, smtutil::Expression::bv2int(*result, isSigned));
|
||||
}
|
||||
|
||||
smtutil::Expression SMTEncoder::division(smtutil::Expression _left, smtutil::Expression _right, IntegerType const& _type)
|
||||
{
|
||||
// Signed division in SMTLIB2 rounds differently for negative division.
|
||||
|
||||
@@ -108,6 +108,7 @@ protected:
|
||||
);
|
||||
void compareOperation(BinaryOperation const& _op);
|
||||
void booleanOperation(BinaryOperation const& _op);
|
||||
void bitwiseOperation(BinaryOperation const& _op);
|
||||
|
||||
void initContract(ContractDefinition const& _contract);
|
||||
void initFunction(FunctionDefinition const& _function);
|
||||
|
||||
@@ -63,7 +63,7 @@ private:
|
||||
|
||||
/// Symbolic balances.
|
||||
SymbolicArrayVariable m_balances{
|
||||
std::make_shared<smtutil::ArraySort>(smtutil::SortProvider::intSort, smtutil::SortProvider::intSort),
|
||||
std::make_shared<smtutil::ArraySort>(smtutil::SortProvider::uintSort, smtutil::SortProvider::uintSort),
|
||||
"balances",
|
||||
m_context
|
||||
};
|
||||
|
||||
@@ -34,7 +34,11 @@ SortPointer smtSort(frontend::Type const& _type)
|
||||
switch (smtKind(_type.category()))
|
||||
{
|
||||
case Kind::Int:
|
||||
return SortProvider::intSort;
|
||||
if (auto const* intType = dynamic_cast<IntegerType const*>(&_type))
|
||||
return SortProvider::intSort(intType->isSigned());
|
||||
if (auto const* fixedType = dynamic_cast<FixedPointType const*>(&_type))
|
||||
return SortProvider::intSort(fixedType->isSigned());
|
||||
return SortProvider::uintSort;
|
||||
case Kind::Bool:
|
||||
return SortProvider::boolSort;
|
||||
case Kind::Function:
|
||||
@@ -50,7 +54,7 @@ SortPointer smtSort(frontend::Type const& _type)
|
||||
returnSort = SortProvider::boolSort;
|
||||
else if (returnTypes.size() > 1)
|
||||
// Abstract sort.
|
||||
returnSort = SortProvider::intSort;
|
||||
returnSort = SortProvider::uintSort;
|
||||
else
|
||||
returnSort = smtSort(*returnTypes.front());
|
||||
return make_shared<FunctionSort>(parameterSorts, returnSort);
|
||||
@@ -68,7 +72,7 @@ SortPointer smtSort(frontend::Type const& _type)
|
||||
{
|
||||
auto stringLitType = dynamic_cast<frontend::StringLiteralType const*>(&_type);
|
||||
solAssert(stringLitType, "");
|
||||
array = make_shared<ArraySort>(SortProvider::intSort, SortProvider::intSort);
|
||||
array = make_shared<ArraySort>(SortProvider::uintSort, SortProvider::uintSort);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -81,7 +85,7 @@ SortPointer smtSort(frontend::Type const& _type)
|
||||
solAssert(false, "");
|
||||
|
||||
solAssert(arrayType, "");
|
||||
array = make_shared<ArraySort>(SortProvider::intSort, smtSortAbstractFunction(*arrayType->baseType()));
|
||||
array = make_shared<ArraySort>(SortProvider::uintSort, smtSortAbstractFunction(*arrayType->baseType()));
|
||||
}
|
||||
|
||||
string tupleName;
|
||||
@@ -98,7 +102,7 @@ SortPointer smtSort(frontend::Type const& _type)
|
||||
return make_shared<TupleSort>(
|
||||
tupleName,
|
||||
vector<string>{tupleName + "_accessor_array", tupleName + "_accessor_length"},
|
||||
vector<SortPointer>{array, SortProvider::intSort}
|
||||
vector<SortPointer>{array, SortProvider::uintSort}
|
||||
);
|
||||
}
|
||||
case Kind::Tuple:
|
||||
@@ -118,7 +122,7 @@ SortPointer smtSort(frontend::Type const& _type)
|
||||
}
|
||||
default:
|
||||
// Abstract case.
|
||||
return SortProvider::intSort;
|
||||
return SortProvider::uintSort;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +137,7 @@ vector<SortPointer> smtSort(vector<frontend::TypePointer> const& _types)
|
||||
SortPointer smtSortAbstractFunction(frontend::Type const& _type)
|
||||
{
|
||||
if (isFunction(_type.category()))
|
||||
return SortProvider::intSort;
|
||||
return SortProvider::uintSort;
|
||||
return smtSort(_type);
|
||||
}
|
||||
|
||||
@@ -144,7 +148,7 @@ vector<SortPointer> smtSortAbstractFunction(vector<frontend::TypePointer> const&
|
||||
if (type)
|
||||
sorts.push_back(smtSortAbstractFunction(*type));
|
||||
else
|
||||
sorts.push_back(SortProvider::intSort);
|
||||
sorts.push_back(SortProvider::uintSort);
|
||||
return sorts;
|
||||
}
|
||||
|
||||
|
||||
@@ -286,7 +286,7 @@ SymbolicArrayVariable::SymbolicArrayVariable(
|
||||
std::make_shared<TupleSort>(
|
||||
"array_length_pair",
|
||||
std::vector<std::string>{"array", "length"},
|
||||
std::vector<SortPointer>{m_sort, SortProvider::intSort}
|
||||
std::vector<SortPointer>{m_sort, SortProvider::uintSort}
|
||||
),
|
||||
m_uniqueName + "_array_length_pair",
|
||||
m_context
|
||||
|
||||
Reference in New Issue
Block a user