Refactoring signature for updateStorageValueFunction

This commit is contained in:
Djordje Mijovic 2020-09-01 14:43:40 +02:00
parent 15163b2270
commit 1fab5b79fb
4 changed files with 28 additions and 15 deletions

View File

@ -362,7 +362,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
solAssert(sourceType.sizeOnStack() == 1, ""); solAssert(sourceType.sizeOnStack() == 1, "");
solAssert(structType.sizeOnStack() == 1, ""); solAssert(structType.sizeOnStack() == 1, "");
m_context << Instruction::DUP2 << Instruction::DUP2; m_context << Instruction::DUP2 << Instruction::DUP2;
m_context.callYulFunction(m_context.utilFunctions().updateStorageValueFunction(structType, &sourceType, 0), 2, 0); m_context.callYulFunction(m_context.utilFunctions().updateStorageValueFunction(sourceType, structType, 0), 2, 0);
} }
else else
{ {

View File

@ -964,7 +964,7 @@ string YulUtilFunctions::storageArrayPushFunction(ArrayType const& _type)
("dataAreaFunction", arrayDataAreaFunction(_type)) ("dataAreaFunction", arrayDataAreaFunction(_type))
("isByteArray", _type.isByteArray()) ("isByteArray", _type.isByteArray())
("indexAccess", storageArrayIndexAccessFunction(_type)) ("indexAccess", storageArrayIndexAccessFunction(_type))
("storeValue", updateStorageValueFunction(*_type.baseType())) ("storeValue", updateStorageValueFunction(*_type.baseType(), *_type.baseType()))
("maxArrayLength", (u256(1) << 64).str()) ("maxArrayLength", (u256(1) << 64).str())
("shl", shiftLeftFunctionDynamic()) ("shl", shiftLeftFunctionDynamic())
("shr", shiftRightFunction(248)) ("shr", shiftRightFunction(248))
@ -994,7 +994,7 @@ string YulUtilFunctions::storageArrayPushZeroFunction(ArrayType const& _type)
("functionName", functionName) ("functionName", functionName)
("fetchLength", arrayLengthFunction(_type)) ("fetchLength", arrayLengthFunction(_type))
("indexAccess", storageArrayIndexAccessFunction(_type)) ("indexAccess", storageArrayIndexAccessFunction(_type))
("storeValue", updateStorageValueFunction(*_type.baseType())) ("storeValue", updateStorageValueFunction(*_type.baseType(), *_type.baseType()))
("maxArrayLength", (u256(1) << 64).str()) ("maxArrayLength", (u256(1) << 64).str())
("zeroValueFunction", zeroValueFunction(*_type.baseType())) ("zeroValueFunction", zeroValueFunction(*_type.baseType()))
.render(); .render();
@ -1529,21 +1529,22 @@ string YulUtilFunctions::readFromCalldata(Type const& _type)
} }
string YulUtilFunctions::updateStorageValueFunction( string YulUtilFunctions::updateStorageValueFunction(
Type const& _fromType,
Type const& _toType, Type const& _toType,
Type const* _fromType,
std::optional<unsigned> const& _offset std::optional<unsigned> const& _offset
) )
{ {
string const functionName = string const functionName =
"update_storage_value_" + "update_storage_value_" +
(_offset.has_value() ? ("offset_" + to_string(*_offset)) : "") + (_offset.has_value() ? ("offset_" + to_string(*_offset)) : "") +
(_fromType ? "_from_" + _fromType->identifier() : "") + _fromType.identifier() +
"_to_" + "_to_" +
_toType.identifier(); _toType.identifier();
return m_functionCollector.createFunction(functionName, [&] { return m_functionCollector.createFunction(functionName, [&] {
if (_toType.isValueType()) if (_toType.isValueType())
{ {
solAssert(_fromType.isImplicitlyConvertibleTo(_toType), "");
solAssert(_toType.storageBytes() <= 32, "Invalid storage bytes size."); solAssert(_toType.storageBytes() <= 32, "Invalid storage bytes size.");
solAssert(_toType.storageBytes() > 0, "Invalid storage bytes size."); solAssert(_toType.storageBytes() > 0, "Invalid storage bytes size.");
@ -1565,13 +1566,20 @@ string YulUtilFunctions::updateStorageValueFunction(
} }
else else
{ {
auto const* toReferenceType = dynamic_cast<ReferenceType const*>(&_toType);
auto const* fromReferenceType = dynamic_cast<ReferenceType const*>(&_toType);
solAssert(fromReferenceType && toReferenceType, "");
solAssert(*toReferenceType->copyForLocation(
fromReferenceType->location(),
fromReferenceType->isPointer()
).get() == *fromReferenceType, "");
if (_toType.category() == Type::Category::Array) if (_toType.category() == Type::Category::Array)
solUnimplementedAssert(false, ""); solUnimplementedAssert(false, "");
else if (_toType.category() == Type::Category::Struct) else if (_toType.category() == Type::Category::Struct)
{ {
solAssert(_fromType, ""); solAssert(_fromType.category() == Type::Category::Struct, "");
solAssert(_fromType->category() == Type::Category::Struct, ""); auto const& fromStructType = dynamic_cast<StructType const&>(_fromType);
auto const& fromStructType = dynamic_cast<StructType const&>(*_fromType);
auto const& toStructType = dynamic_cast<StructType const&>(_toType); auto const& toStructType = dynamic_cast<StructType const&>(_toType);
solAssert(fromStructType.structDefinition() == toStructType.structDefinition(), ""); solAssert(fromStructType.structDefinition() == toStructType.structDefinition(), "");
solAssert(fromStructType.location() != DataLocation::Storage, ""); solAssert(fromStructType.location() != DataLocation::Storage, "");
@ -1597,15 +1605,20 @@ string YulUtilFunctions::updateStorageValueFunction(
bool fromCalldata = fromStructType.location() == DataLocation::CallData; bool fromCalldata = fromStructType.location() == DataLocation::CallData;
auto const& [slotDiff, offset] = toStructType.storageOffsetsOfMember(structMembers[i].name); auto const& [slotDiff, offset] = toStructType.storageOffsetsOfMember(structMembers[i].name);
memberParams[i]["updateMemberCall"] = Whiskers(R"( memberParams[i]["updateMemberCall"] = Whiskers(R"(
let memberValue := <loadFromMemoryOrCalldata>(add(value, <memberOffset>)) let <memberValues> := <loadFromMemoryOrCalldata>(add(value, <memberOffset>))
<updateMember>(add(slot, <memberStorageSlotDiff>), <?hasOffset><memberStorageOffset>,</hasOffset> memberValue) <updateMember>(add(slot, <memberStorageSlotDiff>), <?hasOffset><memberStorageOffset>,</hasOffset> <memberValues>)
)") )")
("memberValues", suffixedVariableNameList(
"memberValue_",
0,
structMembers[i].type->stackItems().size()
))
("hasOffset", structMembers[i].type->isValueType()) ("hasOffset", structMembers[i].type->isValueType())
( (
"updateMember", "updateMember",
structMembers[i].type->isValueType() ? structMembers[i].type->isValueType() ?
updateStorageValueFunction(*structMembers[i].type, structMembers[i].type) : updateStorageValueFunction(*structMembers[i].type, *structMembers[i].type) :
updateStorageValueFunction(*structMembers[i].type, structMembers[i].type, offset) updateStorageValueFunction(*structMembers[i].type, *structMembers[i].type, offset)
) )
("memberStorageSlotDiff", slotDiff.str()) ("memberStorageSlotDiff", slotDiff.str())
("memberStorageOffset", to_string(offset)) ("memberStorageOffset", to_string(offset))
@ -2632,7 +2645,7 @@ string YulUtilFunctions::storageSetToZeroFunction(Type const& _type)
} }
)") )")
("functionName", functionName) ("functionName", functionName)
("store", updateStorageValueFunction(_type)) ("store", updateStorageValueFunction(_type, _type))
("zeroValue", zeroValueFunction(_type)) ("zeroValue", zeroValueFunction(_type))
.render(); .render();
else if (_type.category() == Type::Category::Array) else if (_type.category() == Type::Category::Array)

View File

@ -248,8 +248,8 @@ public:
/// runtime parameter. /// runtime parameter.
/// signature: (slot, [offset,] value) /// signature: (slot, [offset,] value)
std::string updateStorageValueFunction( std::string updateStorageValueFunction(
Type const& _fromType,
Type const& _toType, Type const& _toType,
Type const* _fromType = nullptr,
std::optional<unsigned> const& _offset = std::optional<unsigned>() std::optional<unsigned> const& _offset = std::optional<unsigned>()
); );

View File

@ -2486,7 +2486,7 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable
offset = std::get<unsigned>(_storage.offset); offset = std::get<unsigned>(_storage.offset);
m_code << m_code <<
m_utils.updateStorageValueFunction(_lvalue.type, &_value.type(), offset) << m_utils.updateStorageValueFunction(_value.type(), _lvalue.type, offset) <<
"(" << "(" <<
_storage.slot << _storage.slot <<
( (