mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[Sol -> Yul] Implement unary -
, +
This commit is contained in:
parent
7dbcb80523
commit
86000fdcce
@ -1088,6 +1088,28 @@ std::string YulUtilFunctions::incrementCheckedFunction(Type const& _type)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string YulUtilFunctions::negateNumberCheckedFunction(Type const& _type)
|
||||||
|
{
|
||||||
|
IntegerType const& type = dynamic_cast<IntegerType const&>(_type);
|
||||||
|
solAssert(type.isSigned(), "Expected signed type!");
|
||||||
|
|
||||||
|
string const functionName = "negate_" + _type.identifier();
|
||||||
|
|
||||||
|
u256 const minintval = 0 - (u256(1) << (type.numBits() - 1)) + 1;
|
||||||
|
|
||||||
|
return m_functionCollector->createFunction(functionName, [&]() {
|
||||||
|
return Whiskers(R"(
|
||||||
|
function <functionName>(_value) -> ret {
|
||||||
|
if slt(_value, <minval>) { revert(0,0) }
|
||||||
|
ret := sub(0, _value)
|
||||||
|
}
|
||||||
|
)")
|
||||||
|
("functionName", functionName)
|
||||||
|
("minval", toCompactHexWithPrefix(minintval))
|
||||||
|
.render();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
string YulUtilFunctions::conversionFunctionSpecial(Type const& _from, Type const& _to)
|
string YulUtilFunctions::conversionFunctionSpecial(Type const& _from, Type const& _to)
|
||||||
{
|
{
|
||||||
string functionName =
|
string functionName =
|
||||||
|
@ -179,6 +179,8 @@ public:
|
|||||||
std::string incrementCheckedFunction(Type const& _type);
|
std::string incrementCheckedFunction(Type const& _type);
|
||||||
std::string decrementCheckedFunction(Type const& _type);
|
std::string decrementCheckedFunction(Type const& _type);
|
||||||
|
|
||||||
|
std::string negateNumberCheckedFunction(Type const& _type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Special case of conversionFunction - handles everything that does not
|
/// Special case of conversionFunction - handles everything that does not
|
||||||
/// use exactly one variable to hold the value.
|
/// use exactly one variable to hold the value.
|
||||||
|
@ -265,23 +265,39 @@ void IRGeneratorForStatements::endVisit(UnaryOperation const& _unaryOperation)
|
|||||||
) <<
|
) <<
|
||||||
"(" <<
|
"(" <<
|
||||||
originalValue <<
|
originalValue <<
|
||||||
")\n" <<
|
")\n";
|
||||||
m_currentLValue->storeValue(modifiedValue, resultType);
|
m_code << m_currentLValue->storeValue(modifiedValue, resultType);
|
||||||
|
m_currentLValue.reset();
|
||||||
|
|
||||||
defineExpression(_unaryOperation) <<
|
defineExpression(_unaryOperation) <<
|
||||||
(_unaryOperation.isPrefixOperation() ? modifiedValue : originalValue) <<
|
(_unaryOperation.isPrefixOperation() ? modifiedValue : originalValue) <<
|
||||||
"\n";
|
"\n";
|
||||||
|
|
||||||
m_code << m_currentLValue->storeValue(modifiedValue, resultType);
|
|
||||||
m_currentLValue.reset();
|
|
||||||
}
|
}
|
||||||
else if (op == Token::BitNot)
|
else if (op == Token::BitNot)
|
||||||
appendSimpleUnaryOperation(_unaryOperation, _unaryOperation.subExpression());
|
appendSimpleUnaryOperation(_unaryOperation, _unaryOperation.subExpression());
|
||||||
|
else if (op == Token::Add)
|
||||||
|
// According to SyntaxChecker...
|
||||||
|
solAssert(false, "Use of unary + is disallowed.");
|
||||||
|
else if (op == Token::Sub)
|
||||||
|
{
|
||||||
|
IntegerType const& intType = *dynamic_cast<IntegerType const*>(&resultType);
|
||||||
|
|
||||||
|
defineExpression(_unaryOperation) <<
|
||||||
|
m_utils.negateNumberCheckedFunction(intType) <<
|
||||||
|
"(" <<
|
||||||
|
m_context.variable(_unaryOperation.subExpression()) <<
|
||||||
|
")\n";
|
||||||
|
}
|
||||||
else
|
else
|
||||||
solUnimplementedAssert(false, "Unary operator not yet implemented");
|
solUnimplementedAssert(false, "Unary operator not yet implemented");
|
||||||
}
|
}
|
||||||
else if (resultType.category() == Type::Category::Bool)
|
else if (resultType.category() == Type::Category::Bool)
|
||||||
{
|
{
|
||||||
|
solAssert(
|
||||||
|
_unaryOperation.getOperator() != Token::BitNot,
|
||||||
|
"Bitwise Negation can't be done on bool!"
|
||||||
|
);
|
||||||
|
|
||||||
appendSimpleUnaryOperation(_unaryOperation, _unaryOperation.subExpression());
|
appendSimpleUnaryOperation(_unaryOperation, _unaryOperation.subExpression());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -69,6 +69,18 @@ contract C {
|
|||||||
ret := a
|
ret := a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function negate(int256 a) public pure returns (int256)
|
||||||
|
{
|
||||||
|
return -a;
|
||||||
|
}
|
||||||
|
function negate_s8(int8 a) public pure returns (int8)
|
||||||
|
{
|
||||||
|
return -a;
|
||||||
|
}
|
||||||
|
function negate_s16(int16 a) public pure returns (int16)
|
||||||
|
{
|
||||||
|
return -a;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// compileViaYul: true
|
// compileViaYul: true
|
||||||
@ -111,3 +123,14 @@ contract C {
|
|||||||
// bitnot(int256): -100 -> 99
|
// bitnot(int256): -100 -> 99
|
||||||
// bitnot_u8(uint8): 100 -> 155
|
// bitnot_u8(uint8): 100 -> 155
|
||||||
// bitnot_s8() -> 99
|
// bitnot_s8() -> 99
|
||||||
|
// negate(int256): -57896044618658097711785492504343953926634992332820282019728792003956564819968 -> FAILURE
|
||||||
|
// negate(int256): -57896044618658097711785492504343953926634992332820282019728792003956564819967 -> 57896044618658097711785492504343953926634992332820282019728792003956564819967
|
||||||
|
// negate(int256): 0 -> 0
|
||||||
|
// negate(int256): 1 -> -1
|
||||||
|
// negate(int256): -1 -> 1
|
||||||
|
// negate_s8(int8): -128 -> FAILURE
|
||||||
|
// negate_s8(int8): -138 -> FAILURE
|
||||||
|
// negate_s8(int8): -127 -> 127
|
||||||
|
// negate_s8(int8): 127 -> -127
|
||||||
|
// negate_s16(int16): -32768 -> FAILURE
|
||||||
|
// negate_s16(int16): -32767 -> 32767
|
||||||
|
Loading…
Reference in New Issue
Block a user