mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #10314 from ethereum/fixararylvalue
Pull offset check into updateStorageValue
This commit is contained in:
commit
db264d9e65
@ -1274,7 +1274,6 @@ string YulUtilFunctions::storageArrayPushFunction(ArrayType const& _type)
|
|||||||
{
|
{
|
||||||
solAssert(_type.location() == DataLocation::Storage, "");
|
solAssert(_type.location() == DataLocation::Storage, "");
|
||||||
solAssert(_type.isDynamicallySized(), "");
|
solAssert(_type.isDynamicallySized(), "");
|
||||||
solUnimplementedAssert(_type.baseType()->storageBytes() <= 32, "Base type is not yet implemented.");
|
|
||||||
|
|
||||||
string functionName = "array_push_" + _type.identifier();
|
string functionName = "array_push_" + _type.identifier();
|
||||||
return m_functionCollector.createFunction(functionName, [&]() {
|
return m_functionCollector.createFunction(functionName, [&]() {
|
||||||
@ -1540,7 +1539,7 @@ string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromType,
|
|||||||
let <elementValues> := srcPtr
|
let <elementValues> := srcPtr
|
||||||
</fromStorage>
|
</fromStorage>
|
||||||
|
|
||||||
<updateStorageValue>(elementSlot<?isValueType>, elementOffset</isValueType>, <elementValues>)
|
<updateStorageValue>(elementSlot, elementOffset, <elementValues>)
|
||||||
|
|
||||||
srcPtr := add(srcPtr, <srcStride>)
|
srcPtr := add(srcPtr, <srcStride>)
|
||||||
|
|
||||||
@ -2317,11 +2316,14 @@ string YulUtilFunctions::updateStorageValueFunction(
|
|||||||
solAssert(_offset.value_or(0) == 0, "");
|
solAssert(_offset.value_or(0) == 0, "");
|
||||||
|
|
||||||
Whiskers templ(R"(
|
Whiskers templ(R"(
|
||||||
function <functionName>(slot, <value>) {
|
function <functionName>(slot, <?dynamicOffset>offset, </dynamicOffset><value>) {
|
||||||
|
<?dynamicOffset>if offset { <panic>() }</dynamicOffset>
|
||||||
<copyArrayToStorage>(slot, <value>)
|
<copyArrayToStorage>(slot, <value>)
|
||||||
}
|
}
|
||||||
)");
|
)");
|
||||||
templ("functionName", functionName);
|
templ("functionName", functionName);
|
||||||
|
templ("dynamicOffset", !_offset.has_value());
|
||||||
|
templ("panic", panicFunction());
|
||||||
templ("value", suffixedVariableNameList("value_", 0, _fromType.sizeOnStack()));
|
templ("value", suffixedVariableNameList("value_", 0, _fromType.sizeOnStack()));
|
||||||
templ("copyArrayToStorage", copyArrayToStorageFunction(
|
templ("copyArrayToStorage", copyArrayToStorageFunction(
|
||||||
dynamic_cast<ArrayType const&>(_fromType),
|
dynamic_cast<ArrayType const&>(_fromType),
|
||||||
@ -2340,7 +2342,8 @@ string YulUtilFunctions::updateStorageValueFunction(
|
|||||||
solAssert(_offset.value_or(0) == 0, "");
|
solAssert(_offset.value_or(0) == 0, "");
|
||||||
|
|
||||||
Whiskers templ(R"(
|
Whiskers templ(R"(
|
||||||
function <functionName>(slot, value) {
|
function <functionName>(slot, <?dynamicOffset>offset, </dynamicOffset>value) {
|
||||||
|
<?dynamicOffset>if offset { <panic>() }</dynamicOffset>
|
||||||
<?fromStorage> if eq(slot, value) { leave } </fromStorage>
|
<?fromStorage> if eq(slot, value) { leave } </fromStorage>
|
||||||
<#member>
|
<#member>
|
||||||
{
|
{
|
||||||
@ -2349,8 +2352,10 @@ string YulUtilFunctions::updateStorageValueFunction(
|
|||||||
</member>
|
</member>
|
||||||
}
|
}
|
||||||
)");
|
)");
|
||||||
templ("fromStorage", fromStructType.dataStoredIn(DataLocation::Storage));
|
|
||||||
templ("functionName", functionName);
|
templ("functionName", functionName);
|
||||||
|
templ("dynamicOffset", !_offset.has_value());
|
||||||
|
templ("panic", panicFunction());
|
||||||
|
templ("fromStorage", fromStructType.dataStoredIn(DataLocation::Storage));
|
||||||
|
|
||||||
MemberList::MemberMap structMembers = fromStructType.nativeMembers(nullptr);
|
MemberList::MemberMap structMembers = fromStructType.nativeMembers(nullptr);
|
||||||
MemberList::MemberMap toStructMembers = toStructType.nativeMembers(nullptr);
|
MemberList::MemberMap toStructMembers = toStructType.nativeMembers(nullptr);
|
||||||
@ -2428,10 +2433,11 @@ string YulUtilFunctions::updateStorageValueFunction(
|
|||||||
solAssert(srcOffset == 0, "");
|
solAssert(srcOffset == 0, "");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
t("memberStorageSlotOffset", to_string(offset));
|
||||||
t("updateStorageValue", updateStorageValueFunction(
|
t("updateStorageValue", updateStorageValueFunction(
|
||||||
memberType,
|
memberType,
|
||||||
*toStructMembers[i].type,
|
*toStructMembers[i].type,
|
||||||
memberType.isValueType() ? optional<unsigned>{offset} : std::nullopt
|
optional<unsigned>{offset}
|
||||||
));
|
));
|
||||||
memberParams[i]["updateMemberCall"] = t.render();
|
memberParams[i]["updateMemberCall"] = t.render();
|
||||||
}
|
}
|
||||||
|
@ -287,6 +287,7 @@ public:
|
|||||||
/// Returns the name of a function will write the given value to
|
/// Returns the name of a function will write the given value to
|
||||||
/// the specified slot and offset. If offset is not given, it is expected as
|
/// the specified slot and offset. If offset is not given, it is expected as
|
||||||
/// runtime parameter.
|
/// runtime parameter.
|
||||||
|
/// For reference types, offset is checked to be zero at runtime.
|
||||||
/// signature: (slot, [offset,] value)
|
/// signature: (slot, [offset,] value)
|
||||||
std::string updateStorageValueFunction(
|
std::string updateStorageValueFunction(
|
||||||
Type const& _fromType,
|
Type const& _fromType,
|
||||||
|
@ -2660,22 +2660,22 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable
|
|||||||
std::visit(
|
std::visit(
|
||||||
util::GenericVisitor{
|
util::GenericVisitor{
|
||||||
[&](IRLValue::Storage const& _storage) {
|
[&](IRLValue::Storage const& _storage) {
|
||||||
std::optional<unsigned> offset;
|
string offsetArgument;
|
||||||
|
optional<unsigned> offsetStatic;
|
||||||
|
|
||||||
if (std::holds_alternative<unsigned>(_storage.offset))
|
std::visit(GenericVisitor{
|
||||||
offset = std::get<unsigned>(_storage.offset);
|
[&](unsigned _offset) { offsetStatic = _offset; },
|
||||||
|
[&](string const& _offset) { offsetArgument = ", " + _offset; }
|
||||||
|
}, _storage.offset);
|
||||||
|
|
||||||
m_code <<
|
m_code <<
|
||||||
m_utils.updateStorageValueFunction(_value.type(), _lvalue.type, offset) <<
|
m_utils.updateStorageValueFunction(_value.type(), _lvalue.type, offsetStatic) <<
|
||||||
"(" <<
|
"(" <<
|
||||||
_storage.slot <<
|
_storage.slot <<
|
||||||
(
|
offsetArgument <<
|
||||||
std::holds_alternative<string>(_storage.offset) ?
|
|
||||||
(", " + std::get<string>(_storage.offset)) :
|
|
||||||
""
|
|
||||||
) <<
|
|
||||||
_value.commaSeparatedListPrefixed() <<
|
_value.commaSeparatedListPrefixed() <<
|
||||||
")\n";
|
")\n";
|
||||||
|
|
||||||
},
|
},
|
||||||
[&](IRLValue::Memory const& _memory) {
|
[&](IRLValue::Memory const& _memory) {
|
||||||
if (_lvalue.type.isValueType())
|
if (_lvalue.type.isValueType())
|
||||||
|
@ -33,6 +33,8 @@ contract c {
|
|||||||
return (small.length, large.length);
|
return (small.length, large.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// test() -> 0x02000202
|
// test() -> 0x02000202
|
||||||
// storage: empty
|
// storage: empty
|
||||||
|
@ -21,6 +21,8 @@ contract c {
|
|||||||
delete inner;
|
delete inner;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// test() -> 1, 2, 3
|
// test() -> 1, 2, 3
|
||||||
// storage: empty
|
// storage: empty
|
||||||
|
Loading…
Reference in New Issue
Block a user