mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Corresponding code in the .cpp file has been commented instead of begin removed pending preliminary reviews
Code generators needed fixing of the cleanup process during typecasting of bytes and integers
This commit is contained in:
parent
b897d5d7c4
commit
dec511aad8
@ -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