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 YulUtilFunctions::arrayLengthFunction(ArrayType const& _type)
{ {
string functionName = "array_length_" + _type.identifier(); string functionName = "array_length_" + _type.identifier();

View File

@ -86,6 +86,10 @@ public:
std::string overflowCheckedUIntAddFunction(size_t _bits); 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); std::string arrayLengthFunction(ArrayType const& _type);
/// @returns the name of a function that computes the number of bytes required /// @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). /// 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 else
{ {
solUnimplementedAssert(_binOp.getOperator() == Token::Add, "");
if (IntegerType const* type = dynamic_cast<IntegerType const*>(commonType)) if (IntegerType const* type = dynamic_cast<IntegerType const*>(commonType))
{ {
solUnimplementedAssert(!type->isSigned(), ""); solUnimplementedAssert(!type->isSigned(), "");
defineExpression(_binOp) << string left = expressionAsType(_binOp.leftExpression(), *commonType);
m_utils.overflowCheckedUIntAddFunction(type->numBits()) << string right = expressionAsType(_binOp.rightExpression(), *commonType);
"(" << string fun;
expressionAsType(_binOp.leftExpression(), *commonType) << if (_binOp.getOperator() == Token::Add)
", " << fun = m_utils.overflowCheckedUIntAddFunction(type->numBits());
expressionAsType(_binOp.rightExpression(), *commonType) << else if (_binOp.getOperator() == Token::Sub)
")\n"; fun = m_utils.overflowCheckedUIntSubFunction();
else
solUnimplementedAssert(false, "");
defineExpression(_binOp) << fun << "(" << left << ", " << right << ")\n";
} }
else else
solUnimplementedAssert(false, ""); solUnimplementedAssert(false, "");