mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #12584 from nishant-sachdeva/indexed_log_topic_differs_between_legacy_and_ir_if_explicitly_downcast
Code generators needed fixing of the cleanup process during typecasting
This commit is contained in:
commit
22116dfd0a
@ -16,6 +16,8 @@ Bugfixes:
|
|||||||
* Code Generator: Fix ICE when doing an explicit conversion from ``string calldata`` to ``bytes``.
|
* Code Generator: Fix ICE when doing an explicit conversion from ``string calldata`` to ``bytes``.
|
||||||
* Control Flow Graph: Perform proper virtual lookup for modifiers for uninitialized variable and unreachable code analysis.
|
* Control Flow Graph: Perform proper virtual lookup for modifiers for uninitialized variable and unreachable code analysis.
|
||||||
* Immutables: Fix wrong error when the constructor of a base contract uses ``return`` and the parent contract contains immutable variables.
|
* Immutables: Fix wrong error when the constructor of a base contract uses ``return`` and the parent contract contains immutable variables.
|
||||||
|
* IR Generator: Add missing cleanup during the conversion of fixed bytes types to smaller fixed bytes types.
|
||||||
|
* IR Generator: Add missing cleanup for indexed event arguments of value type.
|
||||||
* IR Generator: Fix IR syntax error when copying storage arrays of structs containing functions.
|
* IR Generator: Fix IR syntax error when copying storage arrays of structs containing functions.
|
||||||
* Natspec: Fix ICE when overriding a struct getter with a Natspec-documented return value and the name in the struct is different.
|
* Natspec: Fix ICE when overriding a struct getter with a Natspec-documented return value and the name in the struct is different.
|
||||||
* TypeChecker: Fix ICE when a constant variable declaration forward references a struct.
|
* TypeChecker: Fix ICE when a constant variable declaration forward references a struct.
|
||||||
|
@ -3400,11 +3400,11 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
|
|||||||
.render();
|
.render();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// clear for conversion to longer bytes
|
|
||||||
solAssert(toCategory == Type::Category::FixedBytes, "Invalid type conversion requested.");
|
solAssert(toCategory == Type::Category::FixedBytes, "Invalid type conversion requested.");
|
||||||
|
FixedBytesType const& to = dynamic_cast<FixedBytesType const&>(_to);
|
||||||
body =
|
body =
|
||||||
Whiskers("converted := <clean>(value)")
|
Whiskers("converted := <clean>(value)")
|
||||||
("clean", cleanupFunction(from))
|
("clean", cleanupFunction((to.numBytes() <= from.numBytes()) ? to : from))
|
||||||
.render();
|
.render();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1035,7 +1035,10 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
")\n";
|
")\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
indexedArgs.emplace_back(convert(arg, *paramTypes[i]));
|
{
|
||||||
|
solAssert(parameterTypes[i]->sizeOnStack() == 1, "");
|
||||||
|
indexedArgs.emplace_back(convert(arg, *paramTypes[i], true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2724,14 +2727,14 @@ void IRGeneratorForStatements::assignInternalFunctionIDIfNotCalledDirectly(
|
|||||||
m_context.addToInternalDispatch(_referencedFunction);
|
m_context.addToInternalDispatch(_referencedFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
IRVariable IRGeneratorForStatements::convert(IRVariable const& _from, Type const& _to)
|
IRVariable IRGeneratorForStatements::convert(IRVariable const& _from, Type const& _to, bool _forceCleanup)
|
||||||
{
|
{
|
||||||
if (_from.type() == _to)
|
if (_from.type() == _to && !_forceCleanup)
|
||||||
return _from;
|
return _from;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
IRVariable converted(m_context.newYulVariable(), _to);
|
IRVariable converted(m_context.newYulVariable(), _to);
|
||||||
define(converted, _from);
|
define(converted, _from, _forceCleanup);
|
||||||
return converted;
|
return converted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2763,10 +2766,10 @@ void IRGeneratorForStatements::declare(IRVariable const& _var)
|
|||||||
appendCode() << "let " << _var.commaSeparatedList() << "\n";
|
appendCode() << "let " << _var.commaSeparatedList() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRGeneratorForStatements::declareAssign(IRVariable const& _lhs, IRVariable const& _rhs, bool _declare)
|
void IRGeneratorForStatements::declareAssign(IRVariable const& _lhs, IRVariable const& _rhs, bool _declare, bool _forceCleanup)
|
||||||
{
|
{
|
||||||
string output;
|
string output;
|
||||||
if (_lhs.type() == _rhs.type())
|
if (_lhs.type() == _rhs.type() && !_forceCleanup)
|
||||||
for (auto const& [stackItemName, stackItemType]: _lhs.type().stackItems())
|
for (auto const& [stackItemName, stackItemType]: _lhs.type().stackItems())
|
||||||
if (stackItemType)
|
if (stackItemType)
|
||||||
declareAssign(_lhs.part(stackItemName), _rhs.part(stackItemName), _declare);
|
declareAssign(_lhs.part(stackItemName), _rhs.part(stackItemName), _declare);
|
||||||
|
@ -86,7 +86,11 @@ public:
|
|||||||
IRVariable evaluateExpression(Expression const& _expression, Type const& _to);
|
IRVariable evaluateExpression(Expression const& _expression, Type const& _to);
|
||||||
|
|
||||||
/// Defines @a _var using the value of @a _value while performing type conversions, if required.
|
/// Defines @a _var using the value of @a _value while performing type conversions, if required.
|
||||||
void define(IRVariable const& _var, IRVariable const& _value) { declareAssign(_var, _value, true); }
|
/// If @a _forceCleanup is set to true, it also cleans the value of the variable after the conversion.
|
||||||
|
void define(IRVariable const& _var, IRVariable const& _value, bool _forceCleanup = false)
|
||||||
|
{
|
||||||
|
declareAssign(_var, _value, true, _forceCleanup);
|
||||||
|
}
|
||||||
|
|
||||||
/// @returns the name of a function that computes the value of the given constant
|
/// @returns the name of a function that computes the value of the given constant
|
||||||
/// and also generates the function.
|
/// and also generates the function.
|
||||||
@ -162,8 +166,8 @@ private:
|
|||||||
);
|
);
|
||||||
|
|
||||||
/// Generates the required conversion code and @returns an IRVariable referring to the value of @a _variable
|
/// Generates the required conversion code and @returns an IRVariable referring to the value of @a _variable
|
||||||
/// converted to type @a _to.
|
/// If @a _forceCleanup is set to true, it also cleans the value of the variable after the conversion.
|
||||||
IRVariable convert(IRVariable const& _variable, Type const& _to);
|
IRVariable convert(IRVariable const& _variable, Type const& _to, bool _forceCleanup = false);
|
||||||
|
|
||||||
/// @returns a Yul expression representing the current value of @a _expression,
|
/// @returns a Yul expression representing the current value of @a _expression,
|
||||||
/// converted to type @a _to if it does not yet have that type.
|
/// converted to type @a _to if it does not yet have that type.
|
||||||
@ -179,7 +183,7 @@ private:
|
|||||||
/// Declares variable @a _var.
|
/// Declares variable @a _var.
|
||||||
void declare(IRVariable const& _var);
|
void declare(IRVariable const& _var);
|
||||||
|
|
||||||
void declareAssign(IRVariable const& _var, IRVariable const& _value, bool _define);
|
void declareAssign(IRVariable const& _var, IRVariable const& _value, bool _define, bool _forceCleanup = false);
|
||||||
|
|
||||||
/// @returns an IRVariable with the zero
|
/// @returns an IRVariable with the zero
|
||||||
/// value of @a _type.
|
/// value of @a _type.
|
||||||
|
@ -11,7 +11,6 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// compileToEwasm: also
|
// compileViaYul: false
|
||||||
// compileViaYul: also
|
|
||||||
// ----
|
// ----
|
||||||
// f() -> "\xff\xff\xff\xff"
|
// f() -> 0xffffffff00000000000000000000000000000000000000000000000000000000
|
@ -0,0 +1,14 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public pure returns (bytes32 r) {
|
||||||
|
bytes4 x = 0xffffffff;
|
||||||
|
bytes2 y = bytes2(x);
|
||||||
|
assembly {
|
||||||
|
r := y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileToEwasm: also
|
||||||
|
// compileViaYul: true
|
||||||
|
// ----
|
||||||
|
// f() -> 0xffff000000000000000000000000000000000000000000000000000000000000
|
@ -0,0 +1,23 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public pure returns (uint32 y) {
|
||||||
|
uint8 x = uint8(uint256(0x31313131313131313131313131313131));
|
||||||
|
assembly { y := x }
|
||||||
|
}
|
||||||
|
|
||||||
|
function g() public pure returns (bytes32 y) {
|
||||||
|
bytes1 x = bytes1(bytes16(0x31313131313131313131313131313131));
|
||||||
|
assembly { y := x }
|
||||||
|
}
|
||||||
|
|
||||||
|
function h() external returns (bytes32 y) {
|
||||||
|
bytes1 x;
|
||||||
|
assembly { x := sub(0,1) }
|
||||||
|
y = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: true
|
||||||
|
// ----
|
||||||
|
// f() -> 0x31
|
||||||
|
// g() -> 0x3100000000000000000000000000000000000000000000000000000000000000
|
||||||
|
// h() -> 0xff00000000000000000000000000000000000000000000000000000000000000
|
@ -0,0 +1,19 @@
|
|||||||
|
contract C {
|
||||||
|
event ev0(bytes1 indexed);
|
||||||
|
constructor() {
|
||||||
|
emit ev0(bytes1(bytes16(0x31313131313131313131313131313131)));
|
||||||
|
}
|
||||||
|
function j() external {
|
||||||
|
bytes1 x;
|
||||||
|
assembly { x := 0x3131313131313131313131313131313131313131313131313131313131313131 }
|
||||||
|
emit ev0(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// constructor() ->
|
||||||
|
// ~ emit ev0(bytes1): #"1"
|
||||||
|
// gas legacy: 168735
|
||||||
|
// j() ->
|
||||||
|
// ~ emit ev0(bytes1): #"1"
|
@ -115,7 +115,7 @@ contract ERC20 {
|
|||||||
// ----
|
// ----
|
||||||
// constructor()
|
// constructor()
|
||||||
// ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14
|
// ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14
|
||||||
// gas irOptimized: 442239
|
// gas irOptimized: 447831
|
||||||
// gas legacy: 861559
|
// gas legacy: 861559
|
||||||
// gas legacyOptimized: 420959
|
// gas legacyOptimized: 420959
|
||||||
// totalSupply() -> 20
|
// totalSupply() -> 20
|
||||||
|
@ -98,7 +98,7 @@ contract ERC20 {
|
|||||||
// ----
|
// ----
|
||||||
// constructor()
|
// constructor()
|
||||||
// ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14
|
// ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14
|
||||||
// gas irOptimized: 437697
|
// gas irOptimized: 443295
|
||||||
// gas legacy: 833310
|
// gas legacy: 833310
|
||||||
// gas legacyOptimized: 416135
|
// gas legacyOptimized: 416135
|
||||||
// totalSupply() -> 20
|
// totalSupply() -> 20
|
||||||
|
Loading…
Reference in New Issue
Block a user