Implement signed subtraction for sol->yul code generation.

This commit is contained in:
Daniel Kirchner
2019-06-20 12:16:56 +02:00
committed by chriseth
parent 88988af561
commit 5f6af8b374
5 changed files with 74 additions and 6 deletions
+13 -3
View File
@@ -464,18 +464,28 @@ string YulUtilFunctions::overflowCheckedIntDivFunction(IntegerType const& _type)
});
}
string YulUtilFunctions::overflowCheckedUIntSubFunction()
string YulUtilFunctions::overflowCheckedIntSubFunction(IntegerType const& _type)
{
string functionName = "checked_sub_uint";
string functionName = "checked_sub_" + _type.identifier();
return m_functionCollector->createFunction(functionName, [&] {
return
Whiskers(R"(
function <functionName>(x, y) -> diff {
if lt(x, y) { revert(0, 0) }
<?signed>
// underflow, if y >= 0 and x < (minValue + y)
if and(iszero(slt(y, 0)), slt(x, add(<minValue>, y))) { revert(0, 0) }
// overflow, if y < 0 and x > (maxValue + y)
if and(slt(y, 0), sgt(x, add(<maxValue>, y))) { revert(0, 0) }
<!signed>
if lt(x, y) { revert(0, 0) }
</signed>
diff := sub(x, y)
}
)")
("functionName", functionName)
("signed", _type.isSigned())
("maxValue", toCompactHexWithPrefix(u256(_type.maxValue())))
("minValue", toCompactHexWithPrefix(u256(_type.minValue())))
.render();
});
}
+1 -1
View File
@@ -106,7 +106,7 @@ public:
/// @returns computes the difference between two values.
/// Assumes the input to be in range for the type.
/// signature: (x, y) -> diff
std::string overflowCheckedUIntSubFunction();
std::string overflowCheckedIntSubFunction(IntegerType const& _type);
/// @returns the name of a function that fetches the length of the given
/// array
@@ -1133,8 +1133,7 @@ string IRGeneratorForStatements::binaryOperation(
fun = m_utils.overflowCheckedIntAddFunction(*type);
break;
case Token::Sub:
if (!type->isSigned())
fun = m_utils.overflowCheckedUIntSubFunction();
fun = m_utils.overflowCheckedIntSubFunction(*type);
break;
case Token::Mul:
if (!type->isSigned())