Subtraction for unsigned integers.

This commit is contained in:
chriseth 2019-05-08 21:25:47 +02:00
parent 5e5138869b
commit 45ee3fc007
3 changed files with 30 additions and 8 deletions

View File

@ -360,6 +360,22 @@ string YulUtilFunctions::overflowCheckedUIntAddFunction(size_t _bits)
});
}
string YulUtilFunctions::overflowCheckedUIntSubFunction()
{
string functionName = "checked_sub_uint";
return m_functionCollector->createFunction(functionName, [&] {
return
Whiskers(R"(
function <functionName>(x, y) -> diff {
if lt(x, y) { revert(0, 0) }
diff := sub(x, y)
}
)")
("functionName", functionName)
.render();
});
}
string YulUtilFunctions::arrayLengthFunction(ArrayType const& _type)
{
string functionName = "array_length_" + _type.identifier();

View File

@ -86,6 +86,10 @@ public:
std::string overflowCheckedUIntAddFunction(size_t _bits);
/// @returns computes the difference between two values.
/// Assumes the input to be in range for the type.
std::string overflowCheckedUIntSubFunction();
std::string arrayLengthFunction(ArrayType const& _type);
/// @returns the name of a function that computes the number of bytes required
/// to store an array in memory given its length (internally encoded, not ABI encoded).

View File

@ -292,17 +292,19 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
}
else
{
solUnimplementedAssert(_binOp.getOperator() == Token::Add, "");
if (IntegerType const* type = dynamic_cast<IntegerType const*>(commonType))
{
solUnimplementedAssert(!type->isSigned(), "");
defineExpression(_binOp) <<
m_utils.overflowCheckedUIntAddFunction(type->numBits()) <<
"(" <<
expressionAsType(_binOp.leftExpression(), *commonType) <<
", " <<
expressionAsType(_binOp.rightExpression(), *commonType) <<
")\n";
string left = expressionAsType(_binOp.leftExpression(), *commonType);
string right = expressionAsType(_binOp.rightExpression(), *commonType);
string fun;
if (_binOp.getOperator() == Token::Add)
fun = m_utils.overflowCheckedUIntAddFunction(type->numBits());
else if (_binOp.getOperator() == Token::Sub)
fun = m_utils.overflowCheckedUIntSubFunction();
else
solUnimplementedAssert(false, "");
defineExpression(_binOp) << fun << "(" << left << ", " << right << ")\n";
}
else
solUnimplementedAssert(false, "");