mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Move storage access functions to utils.
This commit is contained in:
parent
dc13469593
commit
31b7037749
@ -255,39 +255,6 @@ string ABIFunctions::EncodingOptions::toFunctionNameSuffix() const
|
|||||||
return suffix;
|
return suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
string ABIFunctions::cleanupFromStorageFunction(Type const& _type, bool _splitFunctionTypes)
|
|
||||||
{
|
|
||||||
solAssert(_type.isValueType(), "");
|
|
||||||
solUnimplementedAssert(!_splitFunctionTypes, "");
|
|
||||||
|
|
||||||
string functionName = string("cleanup_from_storage_") + (_splitFunctionTypes ? "split_" : "") + _type.identifier();
|
|
||||||
return createFunction(functionName, [&] {
|
|
||||||
Whiskers templ(R"(
|
|
||||||
function <functionName>(value) -> cleaned {
|
|
||||||
<body>
|
|
||||||
}
|
|
||||||
)");
|
|
||||||
templ("functionName", functionName);
|
|
||||||
|
|
||||||
unsigned storageBytes = _type.storageBytes();
|
|
||||||
if (IntegerType const* type = dynamic_cast<IntegerType const*>(&_type))
|
|
||||||
if (type->isSigned() && storageBytes != 32)
|
|
||||||
{
|
|
||||||
templ("body", "cleaned := signextend(" + to_string(storageBytes - 1) + ", value)");
|
|
||||||
return templ.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (storageBytes == 32)
|
|
||||||
templ("body", "cleaned := value");
|
|
||||||
else if (_type.leftAligned())
|
|
||||||
templ("body", "cleaned := " + m_utils.shiftLeftFunction(256 - 8 * storageBytes) + "(value)");
|
|
||||||
else
|
|
||||||
templ("body", "cleaned := and(value, " + toCompactHexWithPrefix((u256(1) << (8 * storageBytes)) - 1) + ")");
|
|
||||||
|
|
||||||
return templ.render();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
string ABIFunctions::abiEncodingFunction(
|
string ABIFunctions::abiEncodingFunction(
|
||||||
Type const& _from,
|
Type const& _from,
|
||||||
Type const& _to,
|
Type const& _to,
|
||||||
@ -609,7 +576,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray(
|
|||||||
break;
|
break;
|
||||||
case DataLocation::Storage:
|
case DataLocation::Storage:
|
||||||
if (_from.baseType()->isValueType())
|
if (_from.baseType()->isValueType())
|
||||||
templ("arrayElementAccess", readFromStorage(*_from.baseType(), 0, false) + "(srcPtr)");
|
templ("arrayElementAccess", m_utils.readFromStorage(*_from.baseType(), 0, false) + "(srcPtr)");
|
||||||
else
|
else
|
||||||
templ("arrayElementAccess", "srcPtr");
|
templ("arrayElementAccess", "srcPtr");
|
||||||
break;
|
break;
|
||||||
@ -806,7 +773,7 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray(
|
|||||||
items[i]["inRange"] = "1";
|
items[i]["inRange"] = "1";
|
||||||
else
|
else
|
||||||
items[i]["inRange"] = "0";
|
items[i]["inRange"] = "0";
|
||||||
items[i]["extractFromSlot"] = extractFromStorageValue(*_from.baseType(), i * storageBytes, false);
|
items[i]["extractFromSlot"] = m_utils.extractFromStorageValue(*_from.baseType(), i * storageBytes, false);
|
||||||
}
|
}
|
||||||
templ("items", items);
|
templ("items", items);
|
||||||
return templ.render();
|
return templ.render();
|
||||||
@ -893,7 +860,7 @@ string ABIFunctions::abiEncodingFunctionStruct(
|
|||||||
members.back()["preprocess"] = "slotValue := sload(add(value, " + toCompactHexWithPrefix(storageSlotOffset) + "))";
|
members.back()["preprocess"] = "slotValue := sload(add(value, " + toCompactHexWithPrefix(storageSlotOffset) + "))";
|
||||||
previousSlotOffset = storageSlotOffset;
|
previousSlotOffset = storageSlotOffset;
|
||||||
}
|
}
|
||||||
members.back()["retrieveValue"] = extractFromStorageValue(*memberTypeFrom, intraSlotOffset, false) + "(slotValue)";
|
members.back()["retrieveValue"] = m_utils.extractFromStorageValue(*memberTypeFrom, intraSlotOffset, false) + "(slotValue)";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1400,51 +1367,6 @@ string ABIFunctions::abiDecodingFunctionFunctionType(FunctionType const& _type,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
string ABIFunctions::readFromStorage(Type const& _type, size_t _offset, bool _splitFunctionTypes)
|
|
||||||
{
|
|
||||||
solUnimplementedAssert(!_splitFunctionTypes, "");
|
|
||||||
string functionName =
|
|
||||||
"read_from_storage_" +
|
|
||||||
string(_splitFunctionTypes ? "split_" : "") +
|
|
||||||
"offset_" +
|
|
||||||
to_string(_offset) +
|
|
||||||
_type.identifier();
|
|
||||||
return m_functionCollector->createFunction(functionName, [&] {
|
|
||||||
solAssert(_type.sizeOnStack() == 1, "");
|
|
||||||
return Whiskers(R"(
|
|
||||||
function <functionName>(slot) -> value {
|
|
||||||
value := <extract>(sload(slot))
|
|
||||||
}
|
|
||||||
)")
|
|
||||||
("functionName", functionName)
|
|
||||||
("extract", extractFromStorageValue(_type, _offset, false))
|
|
||||||
.render();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
string ABIFunctions::extractFromStorageValue(Type const& _type, size_t _offset, bool _splitFunctionTypes)
|
|
||||||
{
|
|
||||||
solUnimplementedAssert(!_splitFunctionTypes, "");
|
|
||||||
|
|
||||||
string functionName =
|
|
||||||
"extract_from_storage_value_" +
|
|
||||||
string(_splitFunctionTypes ? "split_" : "") +
|
|
||||||
"offset_" +
|
|
||||||
to_string(_offset) +
|
|
||||||
_type.identifier();
|
|
||||||
return m_functionCollector->createFunction(functionName, [&] {
|
|
||||||
return Whiskers(R"(
|
|
||||||
function <functionName>(slot_value) -> value {
|
|
||||||
value := <cleanupStorage>(<shr>(slot_value))
|
|
||||||
}
|
|
||||||
)")
|
|
||||||
("functionName", functionName)
|
|
||||||
("shr", m_utils.shiftRightFunction(_offset * 8))
|
|
||||||
("cleanupStorage", cleanupFromStorageFunction(_type, false))
|
|
||||||
.render();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
string ABIFunctions::calldataAccessFunction(Type const& _type)
|
string ABIFunctions::calldataAccessFunction(Type const& _type)
|
||||||
{
|
{
|
||||||
solAssert(_type.isValueType() || _type.dataStoredIn(DataLocation::CallData), "");
|
solAssert(_type.isValueType() || _type.dataStoredIn(DataLocation::CallData), "");
|
||||||
|
@ -128,15 +128,6 @@ private:
|
|||||||
std::string toFunctionNameSuffix() const;
|
std::string toFunctionNameSuffix() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Performs cleanup after reading from a potentially compressed storage slot.
|
|
||||||
/// The function does not perform any validation, it just masks or sign-extends
|
|
||||||
/// higher order bytes or left-aligns (in case of bytesNN).
|
|
||||||
/// The storage cleanup expects the value to be right-aligned with potentially
|
|
||||||
/// dirty higher order bytes.
|
|
||||||
/// @param _splitFunctionTypes if false, returns the address and function signature in a
|
|
||||||
/// single variable.
|
|
||||||
std::string cleanupFromStorageFunction(Type const& _type, bool _splitFunctionTypes);
|
|
||||||
|
|
||||||
/// @returns the name of the ABI encoding function with the given type
|
/// @returns the name of the ABI encoding function with the given type
|
||||||
/// and queues the generation of the function to the requested functions.
|
/// and queues the generation of the function to the requested functions.
|
||||||
/// @param _fromStack if false, the input value was just loaded from storage
|
/// @param _fromStack if false, the input value was just loaded from storage
|
||||||
@ -231,19 +222,6 @@ private:
|
|||||||
/// Part of @a abiDecodingFunction for array types.
|
/// Part of @a abiDecodingFunction for array types.
|
||||||
std::string abiDecodingFunctionFunctionType(FunctionType const& _type, bool _fromMemory, bool _forUseOnStack);
|
std::string abiDecodingFunctionFunctionType(FunctionType const& _type, bool _fromMemory, bool _forUseOnStack);
|
||||||
|
|
||||||
/// @returns a function that reads a value type from storage.
|
|
||||||
/// Performs bit mask/sign extend cleanup and appropriate left / right shift, but not validation.
|
|
||||||
/// @param _splitFunctionTypes if false, returns the address and function signature in a
|
|
||||||
/// single variable.
|
|
||||||
std::string readFromStorage(Type const& _type, size_t _offset, bool _splitFunctionTypes);
|
|
||||||
|
|
||||||
/// @returns a function that extracts a value type from storage slot that has been
|
|
||||||
/// retrieved already.
|
|
||||||
/// Performs bit mask/sign extend cleanup and appropriate left / right shift, but not validation.
|
|
||||||
/// @param _splitFunctionTypes if false, returns the address and function signature in a
|
|
||||||
/// single variable.
|
|
||||||
std::string extractFromStorageValue(Type const& _type, size_t _offset, bool _splitFunctionTypes);
|
|
||||||
|
|
||||||
/// @returns the name of a function that retrieves an element from calldata.
|
/// @returns the name of a function that retrieves an element from calldata.
|
||||||
std::string calldataAccessFunction(Type const& _type);
|
std::string calldataAccessFunction(Type const& _type);
|
||||||
|
|
||||||
|
@ -461,6 +461,86 @@ string YulUtilFunctions::nextArrayElementFunction(ArrayType const& _type)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string YulUtilFunctions::readFromStorage(Type const& _type, size_t _offset, bool _splitFunctionTypes)
|
||||||
|
{
|
||||||
|
solUnimplementedAssert(!_splitFunctionTypes, "");
|
||||||
|
string functionName =
|
||||||
|
"read_from_storage_" +
|
||||||
|
string(_splitFunctionTypes ? "split_" : "") +
|
||||||
|
"offset_" +
|
||||||
|
to_string(_offset) +
|
||||||
|
"_" +
|
||||||
|
_type.identifier();
|
||||||
|
return m_functionCollector->createFunction(functionName, [&] {
|
||||||
|
solAssert(_type.sizeOnStack() == 1, "");
|
||||||
|
return Whiskers(R"(
|
||||||
|
function <functionName>(slot) -> value {
|
||||||
|
value := <extract>(sload(slot))
|
||||||
|
}
|
||||||
|
)")
|
||||||
|
("functionName", functionName)
|
||||||
|
("extract", extractFromStorageValue(_type, _offset, false))
|
||||||
|
.render();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
string YulUtilFunctions::extractFromStorageValue(Type const& _type, size_t _offset, bool _splitFunctionTypes)
|
||||||
|
{
|
||||||
|
solUnimplementedAssert(!_splitFunctionTypes, "");
|
||||||
|
|
||||||
|
string functionName =
|
||||||
|
"extract_from_storage_value_" +
|
||||||
|
string(_splitFunctionTypes ? "split_" : "") +
|
||||||
|
"offset_" +
|
||||||
|
to_string(_offset) +
|
||||||
|
_type.identifier();
|
||||||
|
return m_functionCollector->createFunction(functionName, [&] {
|
||||||
|
return Whiskers(R"(
|
||||||
|
function <functionName>(slot_value) -> value {
|
||||||
|
value := <cleanupStorage>(<shr>(slot_value))
|
||||||
|
}
|
||||||
|
)")
|
||||||
|
("functionName", functionName)
|
||||||
|
("shr", shiftRightFunction(_offset * 8))
|
||||||
|
("cleanupStorage", cleanupFromStorageFunction(_type, false))
|
||||||
|
.render();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
string YulUtilFunctions::cleanupFromStorageFunction(Type const& _type, bool _splitFunctionTypes)
|
||||||
|
{
|
||||||
|
solAssert(_type.isValueType(), "");
|
||||||
|
solUnimplementedAssert(!_splitFunctionTypes, "");
|
||||||
|
|
||||||
|
string functionName = string("cleanup_from_storage_") + (_splitFunctionTypes ? "split_" : "") + _type.identifier();
|
||||||
|
return m_functionCollector->createFunction(functionName, [&] {
|
||||||
|
Whiskers templ(R"(
|
||||||
|
function <functionName>(value) -> cleaned {
|
||||||
|
<body>
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
templ("functionName", functionName);
|
||||||
|
|
||||||
|
unsigned storageBytes = _type.storageBytes();
|
||||||
|
if (IntegerType const* type = dynamic_cast<IntegerType const*>(&_type))
|
||||||
|
if (type->isSigned() && storageBytes != 32)
|
||||||
|
{
|
||||||
|
templ("body", "cleaned := signextend(" + to_string(storageBytes - 1) + ", value)");
|
||||||
|
return templ.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (storageBytes == 32)
|
||||||
|
templ("body", "cleaned := value");
|
||||||
|
else if (_type.leftAligned())
|
||||||
|
templ("body", "cleaned := " + shiftLeftFunction(256 - 8 * storageBytes) + "(value)");
|
||||||
|
else
|
||||||
|
templ("body", "cleaned := and(value, " + toCompactHexWithPrefix((u256(1) << (8 * storageBytes)) - 1) + ")");
|
||||||
|
|
||||||
|
return templ.render();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
string YulUtilFunctions::allocationFunction()
|
string YulUtilFunctions::allocationFunction()
|
||||||
{
|
{
|
||||||
string functionName = "allocateMemory";
|
string functionName = "allocateMemory";
|
||||||
|
@ -88,6 +88,28 @@ public:
|
|||||||
/// Only works for memory arrays, calldata arrays and storage arrays that store one item per slot.
|
/// Only works for memory arrays, calldata arrays and storage arrays that store one item per slot.
|
||||||
std::string nextArrayElementFunction(ArrayType const& _type);
|
std::string nextArrayElementFunction(ArrayType const& _type);
|
||||||
|
|
||||||
|
/// @returns a function that reads a value type from storage.
|
||||||
|
/// Performs bit mask/sign extend cleanup and appropriate left / right shift, but not validation.
|
||||||
|
/// @param _splitFunctionTypes if false, returns the address and function signature in a
|
||||||
|
/// single variable.
|
||||||
|
std::string readFromStorage(Type const& _type, size_t _offset, bool _splitFunctionTypes);
|
||||||
|
|
||||||
|
/// @returns a function that extracts a value type from storage slot that has been
|
||||||
|
/// retrieved already.
|
||||||
|
/// Performs bit mask/sign extend cleanup and appropriate left / right shift, but not validation.
|
||||||
|
/// @param _splitFunctionTypes if false, returns the address and function signature in a
|
||||||
|
/// single variable.
|
||||||
|
std::string extractFromStorageValue(Type const& _type, size_t _offset, bool _splitFunctionTypes);
|
||||||
|
|
||||||
|
/// Performs cleanup after reading from a potentially compressed storage slot.
|
||||||
|
/// The function does not perform any validation, it just masks or sign-extends
|
||||||
|
/// higher order bytes or left-aligns (in case of bytesNN).
|
||||||
|
/// The storage cleanup expects the value to be right-aligned with potentially
|
||||||
|
/// dirty higher order bytes.
|
||||||
|
/// @param _splitFunctionTypes if false, returns the address and function signature in a
|
||||||
|
/// single variable.
|
||||||
|
std::string cleanupFromStorageFunction(Type const& _type, bool _splitFunctionTypes);
|
||||||
|
|
||||||
/// @returns the name of a function that allocates memory.
|
/// @returns the name of a function that allocates memory.
|
||||||
/// Modifies the "free memory pointer"
|
/// Modifies the "free memory pointer"
|
||||||
/// Arguments: size
|
/// Arguments: size
|
||||||
|
Loading…
Reference in New Issue
Block a user