Struct member access for storage and memory.

This commit is contained in:
chriseth 2020-05-28 21:11:06 +02:00
parent 37e8d78cff
commit e7f3c042b6
4 changed files with 60 additions and 2 deletions

View File

@ -1467,7 +1467,43 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
break;
case Type::Category::Struct:
{
solUnimplementedAssert(false, "");
auto const& structType = dynamic_cast<StructType const&>(*_memberAccess.expression().annotation().type);
IRVariable expression(_memberAccess.expression());
switch (structType.location())
{
case DataLocation::Storage:
{
pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member);
string slot = m_context.newYulVariable();
m_code << "let " << slot << " := " <<
("add(" + expression.name() + ", " + offsets.first.str() + ")\n");
setLValue(_memberAccess, IRLValue{
type(_memberAccess),
IRLValue::Storage{slot, offsets.second}
});
break;
}
case DataLocation::Memory:
{
string pos = m_context.newYulVariable();
m_code << "let " << pos << " := " <<
("add(" + expression.part("mpos").name() + ", " + structType.memoryOffsetOfMember(member).str() + ")\n");
setLValue(_memberAccess, IRLValue{
type(_memberAccess),
IRLValue::Memory{pos}
});
break;
}
case DataLocation::CallData:
{
solUnimplementedAssert(false, "");
break;
}
default:
solAssert(false, "Illegal data location for struct.");
}
break;
}
case Type::Category::Enum:
{

View File

@ -0,0 +1,20 @@
contract C {
struct S {
uint8 a;
uint16 b;
uint128 c;
uint d;
}
mapping(uint => mapping(uint => S)) public x;
constructor() public {
x[1][2].a = 3;
x[1][2].b = 4;
x[1][2].c = 5;
x[1][2].d = 6;
}
}
// ====
// compileViaYul: also
// ----
// x(uint256,uint256): 1, 2 -> 3, 4, 5, 6
// x(uint256,uint256): 0, 0 -> 0x00, 0x00, 0x00, 0x00

View File

@ -12,6 +12,6 @@ contract test {
// compileViaYul: also
// ----
// data(uint256,uint256): 2, 2 -> 8
// data(uint256,uint256): 2, 8 -> FAILURE # NB: the original code contained a bug here #
// data(uint256,uint256): 2, 8 -> FAILURE # NB: the original code contained a bug here #
// dynamicData(uint256,uint256): 2, 2 -> 8
// dynamicData(uint256,uint256): 2, 8 -> FAILURE

View File

@ -8,5 +8,7 @@ contract test {
data[7].d = true;
}
}
// ====
// compileViaYul: also
// ----
// data(uint256): 7 -> 1, 2, true