mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge remote-tracking branch 'origin/develop' into HEAD
This commit is contained in:
@@ -2153,58 +2153,47 @@ string YulUtilFunctions::readFromStorage(Type const& _type, size_t _offset, bool
|
||||
string YulUtilFunctions::readFromStorageDynamic(Type const& _type, bool _splitFunctionTypes)
|
||||
{
|
||||
solAssert(_type.isValueType(), "");
|
||||
return readFromStorageValueTypeDynamic(_type, _splitFunctionTypes);
|
||||
return readFromStorageValueType(_type, {}, _splitFunctionTypes);
|
||||
}
|
||||
|
||||
string YulUtilFunctions::readFromStorageValueType(Type const& _type, size_t _offset, bool _splitFunctionTypes)
|
||||
string YulUtilFunctions::readFromStorageValueType(Type const& _type, optional<size_t> _offset, bool _splitFunctionTypes)
|
||||
{
|
||||
solAssert(_type.isValueType(), "");
|
||||
|
||||
if (_type.category() == Type::Category::Function)
|
||||
solUnimplementedAssert(!_splitFunctionTypes, "");
|
||||
string functionName =
|
||||
"read_from_storage_" +
|
||||
string(_splitFunctionTypes ? "split_" : "") +
|
||||
"offset_" +
|
||||
to_string(_offset) +
|
||||
string(_splitFunctionTypes ? "split_" : "") + (
|
||||
_offset.has_value() ?
|
||||
"offset_" + to_string(*_offset) :
|
||||
"dynamic"
|
||||
) +
|
||||
"_" +
|
||||
_type.identifier();
|
||||
|
||||
return m_functionCollector.createFunction(functionName, [&] {
|
||||
solAssert(_type.sizeOnStack() == 1, "");
|
||||
return Whiskers(R"(
|
||||
function <functionName>(slot) -> value {
|
||||
value := <extract>(sload(slot))
|
||||
Whiskers templ(R"(
|
||||
function <functionName>(slot<?dynamic>, offset</dynamic>) -> <?split>addr, selector<!split>value</split> {
|
||||
<?split>let</split> value := <extract>(sload(slot)<?dynamic>, offset</dynamic>)
|
||||
<?split>
|
||||
addr, selector := <splitFunction>(value)
|
||||
</split>
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("extract", extractFromStorageValue(_type, _offset, false))
|
||||
.render();
|
||||
)");
|
||||
templ("functionName", functionName);
|
||||
templ("dynamic", !_offset.has_value());
|
||||
if (_offset.has_value())
|
||||
templ("extract", extractFromStorageValue(_type, *_offset));
|
||||
else
|
||||
templ("extract", extractFromStorageValueDynamic(_type));
|
||||
auto const* funType = dynamic_cast<FunctionType const*>(&_type);
|
||||
bool split = _splitFunctionTypes && funType && funType->kind() == FunctionType::Kind::External;
|
||||
templ("split", split);
|
||||
if (split)
|
||||
templ("splitFunction", splitExternalFunctionIdFunction());
|
||||
return templ.render();
|
||||
});
|
||||
}
|
||||
string YulUtilFunctions::readFromStorageValueTypeDynamic(Type const& _type, bool _splitFunctionTypes)
|
||||
{
|
||||
solAssert(_type.isValueType(), "");
|
||||
if (_type.category() == Type::Category::Function)
|
||||
solUnimplementedAssert(!_splitFunctionTypes, "");
|
||||
|
||||
string functionName =
|
||||
"read_from_storage_value_type_dynamic" +
|
||||
string(_splitFunctionTypes ? "split_" : "") +
|
||||
"_" +
|
||||
_type.identifier();
|
||||
return m_functionCollector.createFunction(functionName, [&] {
|
||||
solAssert(_type.sizeOnStack() == 1, "");
|
||||
return Whiskers(R"(
|
||||
function <functionName>(slot, offset) -> value {
|
||||
value := <extract>(sload(slot), offset)
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("extract", extractFromStorageValueDynamic(_type, _splitFunctionTypes))
|
||||
.render();
|
||||
});
|
||||
}
|
||||
string YulUtilFunctions::readFromStorageReferenceType(Type const& _type)
|
||||
{
|
||||
solUnimplementedAssert(_type.category() == Type::Category::Struct, "");
|
||||
@@ -2437,9 +2426,7 @@ string YulUtilFunctions::updateStorageValueFunction(
|
||||
|
||||
string YulUtilFunctions::writeToMemoryFunction(Type const& _type)
|
||||
{
|
||||
string const functionName =
|
||||
string("write_to_memory_") +
|
||||
_type.identifier();
|
||||
string const functionName = "write_to_memory_" + _type.identifier();
|
||||
|
||||
return m_functionCollector.createFunction(functionName, [&] {
|
||||
solAssert(!dynamic_cast<StringLiteralType const*>(&_type), "");
|
||||
@@ -2493,14 +2480,10 @@ string YulUtilFunctions::writeToMemoryFunction(Type const& _type)
|
||||
});
|
||||
}
|
||||
|
||||
string YulUtilFunctions::extractFromStorageValueDynamic(Type const& _type, bool _splitFunctionTypes)
|
||||
string YulUtilFunctions::extractFromStorageValueDynamic(Type const& _type)
|
||||
{
|
||||
if (_type.category() == Type::Category::Function)
|
||||
solUnimplementedAssert(!_splitFunctionTypes, "");
|
||||
|
||||
string functionName =
|
||||
"extract_from_storage_value_dynamic" +
|
||||
string(_splitFunctionTypes ? "split_" : "") +
|
||||
_type.identifier();
|
||||
return m_functionCollector.createFunction(functionName, [&] {
|
||||
return Whiskers(R"(
|
||||
@@ -2510,21 +2493,14 @@ string YulUtilFunctions::extractFromStorageValueDynamic(Type const& _type, bool
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("shr", shiftRightFunctionDynamic())
|
||||
("cleanupStorage", cleanupFromStorageFunction(_type, _splitFunctionTypes))
|
||||
("cleanupStorage", cleanupFromStorageFunction(_type))
|
||||
.render();
|
||||
});
|
||||
}
|
||||
|
||||
string YulUtilFunctions::extractFromStorageValue(Type const& _type, size_t _offset, bool _splitFunctionTypes)
|
||||
string YulUtilFunctions::extractFromStorageValue(Type const& _type, size_t _offset)
|
||||
{
|
||||
solUnimplementedAssert(!_splitFunctionTypes, "");
|
||||
|
||||
string functionName =
|
||||
"extract_from_storage_value_" +
|
||||
string(_splitFunctionTypes ? "split_" : "") +
|
||||
"offset_" +
|
||||
to_string(_offset) +
|
||||
_type.identifier();
|
||||
string functionName = "extract_from_storage_value_offset_" + to_string(_offset) + _type.identifier();
|
||||
return m_functionCollector.createFunction(functionName, [&] {
|
||||
return Whiskers(R"(
|
||||
function <functionName>(slot_value) -> value {
|
||||
@@ -2533,18 +2509,16 @@ string YulUtilFunctions::extractFromStorageValue(Type const& _type, size_t _offs
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("shr", shiftRightFunction(_offset * 8))
|
||||
("cleanupStorage", cleanupFromStorageFunction(_type, _splitFunctionTypes))
|
||||
("cleanupStorage", cleanupFromStorageFunction(_type))
|
||||
.render();
|
||||
});
|
||||
}
|
||||
|
||||
string YulUtilFunctions::cleanupFromStorageFunction(Type const& _type, bool _splitFunctionTypes)
|
||||
string YulUtilFunctions::cleanupFromStorageFunction(Type const& _type)
|
||||
{
|
||||
solAssert(_type.isValueType(), "");
|
||||
if (_type.category() == Type::Category::Function)
|
||||
solUnimplementedAssert(!_splitFunctionTypes, "");
|
||||
|
||||
string functionName = string("cleanup_from_storage_") + (_splitFunctionTypes ? "split_" : "") + _type.identifier();
|
||||
string functionName = string("cleanup_from_storage_") + _type.identifier();
|
||||
return m_functionCollector.createFunction(functionName, [&] {
|
||||
Whiskers templ(R"(
|
||||
function <functionName>(value) -> cleaned {
|
||||
@@ -2581,22 +2555,37 @@ string YulUtilFunctions::cleanupFromStorageFunction(Type const& _type, bool _spl
|
||||
|
||||
string YulUtilFunctions::prepareStoreFunction(Type const& _type)
|
||||
{
|
||||
if (_type.category() == Type::Category::Function)
|
||||
solUnimplementedAssert(dynamic_cast<FunctionType const&>(_type).kind() == FunctionType::Kind::Internal, "");
|
||||
|
||||
string functionName = "prepare_store_" + _type.identifier();
|
||||
return m_functionCollector.createFunction(functionName, [&]() {
|
||||
Whiskers templ(R"(
|
||||
function <functionName>(value) -> ret {
|
||||
ret := <actualPrepare>
|
||||
}
|
||||
)");
|
||||
templ("functionName", functionName);
|
||||
if (_type.category() == Type::Category::FixedBytes)
|
||||
templ("actualPrepare", shiftRightFunction(256 - 8 * _type.storageBytes()) + "(value)");
|
||||
solAssert(_type.isValueType(), "");
|
||||
auto const* funType = dynamic_cast<FunctionType const*>(&_type);
|
||||
if (funType && funType->kind() == FunctionType::Kind::External)
|
||||
{
|
||||
Whiskers templ(R"(
|
||||
function <functionName>(addr, selector) -> ret {
|
||||
ret := <prepareBytes>(<combine>(addr, selector))
|
||||
}
|
||||
)");
|
||||
templ("functionName", functionName);
|
||||
templ("prepareBytes", prepareStoreFunction(*TypeProvider::fixedBytes(24)));
|
||||
templ("combine", combineExternalFunctionIdFunction());
|
||||
return templ.render();
|
||||
}
|
||||
else
|
||||
templ("actualPrepare", "value");
|
||||
return templ.render();
|
||||
{
|
||||
solAssert(_type.sizeOnStack() == 1, "");
|
||||
Whiskers templ(R"(
|
||||
function <functionName>(value) -> ret {
|
||||
ret := <actualPrepare>
|
||||
}
|
||||
)");
|
||||
templ("functionName", functionName);
|
||||
if (_type.category() == Type::Category::FixedBytes)
|
||||
templ("actualPrepare", shiftRightFunction(256 - 8 * _type.storageBytes()) + "(value)");
|
||||
else
|
||||
templ("actualPrepare", "value");
|
||||
return templ.render();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3683,37 +3672,44 @@ string YulUtilFunctions::readFromMemoryOrCalldata(Type const& _type, bool _fromC
|
||||
}
|
||||
|
||||
solAssert(_type.isValueType(), "");
|
||||
if (auto const* funType = dynamic_cast<FunctionType const*>(&_type))
|
||||
if (funType->kind() == FunctionType::Kind::External)
|
||||
return Whiskers(R"(
|
||||
function <functionName>(memPtr) -> addr, selector {
|
||||
let combined := <load>(memPtr)
|
||||
addr, selector := <splitFunction>(combined)
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("load", _fromCalldata ? "calldataload" : "mload")
|
||||
("splitFunction", splitExternalFunctionIdFunction())
|
||||
.render();
|
||||
|
||||
|
||||
return Whiskers(R"(
|
||||
function <functionName>(ptr) -> value {
|
||||
Whiskers templ(R"(
|
||||
function <functionName>(ptr) -> <returnVariables> {
|
||||
<?fromCalldata>
|
||||
value := calldataload(ptr)
|
||||
let value := calldataload(ptr)
|
||||
<validate>(value)
|
||||
<!fromCalldata>
|
||||
value := <cleanup>(mload(ptr))
|
||||
let value := <cleanup>(mload(ptr))
|
||||
</fromCalldata>
|
||||
|
||||
<returnVariables> :=
|
||||
<?externalFunction>
|
||||
<splitFunction>(value)
|
||||
<!externalFunction>
|
||||
value
|
||||
</externalFunction>
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("fromCalldata", _fromCalldata)
|
||||
("validate", validatorFunction(_type, true))
|
||||
)");
|
||||
templ("functionName", functionName);
|
||||
templ("fromCalldata", _fromCalldata);
|
||||
if (_fromCalldata)
|
||||
templ("validate", validatorFunction(_type, true));
|
||||
auto const* funType = dynamic_cast<FunctionType const*>(&_type);
|
||||
if (funType && funType->kind() == FunctionType::Kind::External)
|
||||
{
|
||||
templ("externalFunction", true);
|
||||
templ("splitFunction", splitExternalFunctionIdFunction());
|
||||
templ("returnVariables", "addr, selector");
|
||||
}
|
||||
else
|
||||
{
|
||||
templ("externalFunction", false);
|
||||
templ("returnVariables", "returnValue");
|
||||
}
|
||||
|
||||
// Byte array elements generally need cleanup.
|
||||
// Other types are cleaned as well to account for dirty memory e.g. due to inline assembly.
|
||||
("cleanup", cleanupFunction(_type))
|
||||
.render();
|
||||
templ("cleanup", cleanupFunction(_type));
|
||||
return templ.render();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user