Merge pull request #5842 from ethereum/refactorStructEncoding

[Yul] Refactor struct encoder.
This commit is contained in:
chriseth 2019-01-22 18:24:03 +01:00 committed by GitHub
commit a010e45166
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -904,6 +904,8 @@ string ABIFunctions::abiEncodingFunctionStruct(
<#members> <#members>
{ {
// <memberName> // <memberName>
<preprocess>
let memberValue := <retrieveValue>
<encode> <encode>
} }
</members> </members>
@ -932,20 +934,10 @@ string ABIFunctions::abiEncodingFunctionStruct(
bool dynamicMember = memberTypeTo->isDynamicallyEncoded(); bool dynamicMember = memberTypeTo->isDynamicallyEncoded();
if (dynamicMember) if (dynamicMember)
solAssert(dynamic, ""); solAssert(dynamic, "");
Whiskers memberTempl(R"(
<preprocess> members.push_back({});
let memberValue := <retrieveValue> members.back()["preprocess"] = "";
)" + (
dynamicMember ?
string(R"(
mstore(add(pos, <encodingOffset>), sub(tail, pos))
tail := <abiEncode>(memberValue, tail)
)") :
string(R"(
<abiEncode>(memberValue, add(pos, <encodingOffset>))
)")
)
);
if (fromStorage) if (fromStorage)
{ {
solAssert(memberTypeFrom->isValueType() == memberTypeTo->isValueType(), ""); solAssert(memberTypeFrom->isValueType() == memberTypeTo->isValueType(), "");
@ -956,36 +948,42 @@ string ABIFunctions::abiEncodingFunctionStruct(
{ {
if (storageSlotOffset != previousSlotOffset) if (storageSlotOffset != previousSlotOffset)
{ {
memberTempl("preprocess", "slotValue := sload(add(value, " + toCompactHexWithPrefix(storageSlotOffset) + "))"); members.back()["preprocess"] = "slotValue := sload(add(value, " + toCompactHexWithPrefix(storageSlotOffset) + "))";
previousSlotOffset = storageSlotOffset; previousSlotOffset = storageSlotOffset;
} }
else members.back()["retrieveValue"] = shiftRightFunction(intraSlotOffset * 8) + "(slotValue)";
memberTempl("preprocess", "");
memberTempl("retrieveValue", shiftRightFunction(intraSlotOffset * 8) + "(slotValue)");
} }
else else
{ {
solAssert(memberTypeFrom->dataStoredIn(DataLocation::Storage), ""); solAssert(memberTypeFrom->dataStoredIn(DataLocation::Storage), "");
solAssert(intraSlotOffset == 0, ""); solAssert(intraSlotOffset == 0, "");
memberTempl("preprocess", ""); members.back()["retrieveValue"] = "add(value, " + toCompactHexWithPrefix(storageSlotOffset) + ")";
memberTempl("retrieveValue", "add(value, " + toCompactHexWithPrefix(storageSlotOffset) + ")");
} }
} }
else else
{ {
memberTempl("preprocess", "");
string sourceOffset = toCompactHexWithPrefix(_from.memoryOffsetOfMember(member.name)); string sourceOffset = toCompactHexWithPrefix(_from.memoryOffsetOfMember(member.name));
memberTempl("retrieveValue", "mload(add(value, " + sourceOffset + "))"); members.back()["retrieveValue"] = "mload(add(value, " + sourceOffset + "))";
} }
memberTempl("encodingOffset", toCompactHexWithPrefix(encodingOffset));
Whiskers encodeTempl(
dynamicMember ?
string(R"(
mstore(add(pos, <encodingOffset>), sub(tail, pos))
tail := <abiEncode>(memberValue, tail)
)") :
string(R"(
<abiEncode>(memberValue, add(pos, <encodingOffset>))
)")
);
encodeTempl("encodingOffset", toCompactHexWithPrefix(encodingOffset));
encodingOffset += dynamicMember ? 0x20 : memberTypeTo->calldataEncodedSize(); encodingOffset += dynamicMember ? 0x20 : memberTypeTo->calldataEncodedSize();
EncodingOptions subOptions(_options); EncodingOptions subOptions(_options);
subOptions.encodeFunctionFromStack = false; subOptions.encodeFunctionFromStack = false;
memberTempl("abiEncode", abiEncodingFunction(*memberTypeFrom, *memberTypeTo, subOptions)); encodeTempl("abiEncode", abiEncodingFunction(*memberTypeFrom, *memberTypeTo, subOptions));
members.push_back({}); members.back()["encode"] = encodeTempl.render();
members.back()["encode"] = memberTempl.render();
members.back()["memberName"] = member.name; members.back()["memberName"] = member.name;
} }
templ("members", members); templ("members", members);