mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #9177 from ethereum/fixYulStructMemberAccess
[Sol -> Yul] Fix struct member access for memory and implement for calldata.
This commit is contained in:
commit
d4e3491f35
@ -2457,6 +2457,21 @@ set<string> StructType::membersMissingInMemory() const
|
|||||||
return missing;
|
return missing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<tuple<string, TypePointer>> StructType::makeStackItems() const
|
||||||
|
{
|
||||||
|
switch (m_location)
|
||||||
|
{
|
||||||
|
case DataLocation::CallData:
|
||||||
|
return {std::make_tuple("offset", TypeProvider::uint256())};
|
||||||
|
case DataLocation::Memory:
|
||||||
|
return {std::make_tuple("mpos", TypeProvider::uint256())};
|
||||||
|
case DataLocation::Storage:
|
||||||
|
return {std::make_tuple("slot", TypeProvider::uint256())};
|
||||||
|
}
|
||||||
|
solAssert(false, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TypePointer EnumType::encodingType() const
|
TypePointer EnumType::encodingType() const
|
||||||
{
|
{
|
||||||
return TypeProvider::uint(8 * storageBytes());
|
return TypeProvider::uint(8 * storageBytes());
|
||||||
|
@ -980,6 +980,8 @@ public:
|
|||||||
|
|
||||||
void clearCache() const override;
|
void clearCache() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override;
|
||||||
private:
|
private:
|
||||||
StructDefinition const& m_struct;
|
StructDefinition const& m_struct;
|
||||||
// Caches for interfaceType(bool)
|
// Caches for interfaceType(bool)
|
||||||
|
@ -1477,7 +1477,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
|||||||
pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member);
|
pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member);
|
||||||
string slot = m_context.newYulVariable();
|
string slot = m_context.newYulVariable();
|
||||||
m_code << "let " << slot << " := " <<
|
m_code << "let " << slot << " := " <<
|
||||||
("add(" + expression.name() + ", " + offsets.first.str() + ")\n");
|
("add(" + expression.part("slot").name() + ", " + offsets.first.str() + ")\n");
|
||||||
setLValue(_memberAccess, IRLValue{
|
setLValue(_memberAccess, IRLValue{
|
||||||
type(_memberAccess),
|
type(_memberAccess),
|
||||||
IRLValue::Storage{slot, offsets.second}
|
IRLValue::Storage{slot, offsets.second}
|
||||||
@ -1497,7 +1497,25 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
|||||||
}
|
}
|
||||||
case DataLocation::CallData:
|
case DataLocation::CallData:
|
||||||
{
|
{
|
||||||
solUnimplementedAssert(false, "");
|
string baseRef = expression.part("offset").name();
|
||||||
|
string offset = m_context.newYulVariable();
|
||||||
|
m_code << "let " << offset << " := " << "add(" << baseRef << ", " << to_string(structType.calldataOffsetOfMember(member)) << ")\n";
|
||||||
|
if (_memberAccess.annotation().type->isDynamicallyEncoded())
|
||||||
|
define(_memberAccess) <<
|
||||||
|
m_utils.accessCalldataTailFunction(*_memberAccess.annotation().type) <<
|
||||||
|
"(" <<
|
||||||
|
baseRef <<
|
||||||
|
", " <<
|
||||||
|
offset <<
|
||||||
|
")" <<
|
||||||
|
std::endl;
|
||||||
|
else
|
||||||
|
define(_memberAccess) <<
|
||||||
|
m_utils.readFromCalldata(*_memberAccess.annotation().type) <<
|
||||||
|
"(" <<
|
||||||
|
offset <<
|
||||||
|
")" <<
|
||||||
|
std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
contract C {
|
||||||
|
struct S {
|
||||||
|
uint a;
|
||||||
|
uint[] b;
|
||||||
|
uint c;
|
||||||
|
}
|
||||||
|
|
||||||
|
S s;
|
||||||
|
constructor() public {
|
||||||
|
s.a = 42;
|
||||||
|
s.b.push(1);
|
||||||
|
s.b.push(2);
|
||||||
|
s.b.push(3);
|
||||||
|
s.c = 21;
|
||||||
|
}
|
||||||
|
|
||||||
|
function f(S memory m) public pure returns (uint, uint[] memory, uint) {
|
||||||
|
return (m.a, m.b, m.c);
|
||||||
|
}
|
||||||
|
function g(S calldata c) external pure returns (uint, uint, uint, uint, uint, uint) {
|
||||||
|
return (c.a, c.b.length, c.c, c.b[0], c.b[1], c.b[2]);
|
||||||
|
}
|
||||||
|
function g2(S calldata c1, S calldata c2) external pure returns (uint, uint, uint, uint, uint, uint) {
|
||||||
|
return (c1.a, c1.c, c2.a, c2.b.length, c2.c, c2.b[0]);
|
||||||
|
}
|
||||||
|
function h() external view returns (uint, uint, uint, uint, uint, uint) {
|
||||||
|
return (s.a, s.b.length, s.c, s.b[0], s.b[1], s.b[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >homestead
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f((uint256,uint256[],uint256)): 0x20, 42, 0x60, 21, 3, 1, 2, 3 -> 42, 0x60, 21, 3, 1, 2, 3
|
||||||
|
// g((uint256,uint256[],uint256)): 0x20, 42, 0x60, 21, 3, 1, 2, 3 -> 42, 3, 21, 1, 2, 3
|
||||||
|
// g2((uint256,uint256[],uint256),(uint256,uint256[],uint256)): 0x40, 0x0120, 42, 0x60, 21, 2, 1, 2, 3, 7, 0x80, 9, 0, 1, 17 -> 42, 21, 7, 1, 9, 17
|
||||||
|
// h() -> 42, 3, 21, 1, 2, 3
|
Loading…
Reference in New Issue
Block a user