mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Refactoring copyLiteralToMemoryFunction and reusing it from other functions.
Co-authored-by: Leonardo <leo@ethereum.org> Co-authored-by: Alex Beregszaszi <alex@rtfs.hu>
This commit is contained in:
parent
b74c08143f
commit
047d693ac9
@ -976,30 +976,20 @@ string ABIFunctions::abiEncodingFunctionStringLiteral(
|
||||
Whiskers templ(R"(
|
||||
function <functionName>(pos) -> end {
|
||||
pos := <storeLength>(pos, <length>)
|
||||
<#word>
|
||||
mstore(add(pos, <offset>), <wordValue>)
|
||||
</word>
|
||||
<storeLiteralInMemory>(pos)
|
||||
end := add(pos, <overallSize>)
|
||||
}
|
||||
)");
|
||||
templ("functionName", functionName);
|
||||
|
||||
// TODO this can make use of CODECOPY for large strings once we have that in Yul
|
||||
size_t words = (value.size() + 31) / 32;
|
||||
templ("length", to_string(value.size()));
|
||||
templ("storeLength", arrayStoreLengthForEncodingFunction(dynamic_cast<ArrayType const&>(_to), _options));
|
||||
if (_options.padded)
|
||||
templ("overallSize", to_string(words * 32));
|
||||
templ("overallSize", to_string(((value.size() + 31) / 32) * 32));
|
||||
else
|
||||
templ("overallSize", to_string(value.size()));
|
||||
|
||||
vector<map<string, string>> wordParams(words);
|
||||
for (size_t i = 0; i < words; ++i)
|
||||
{
|
||||
wordParams[i]["offset"] = to_string(i * 32);
|
||||
wordParams[i]["wordValue"] = formatAsStringOrNumber(value.substr(32 * i, 32));
|
||||
}
|
||||
templ("word", wordParams);
|
||||
templ("storeLiteralInMemory", m_utils.storeLiteralInMemoryFunction(value));
|
||||
return templ.render();
|
||||
}
|
||||
else
|
||||
|
@ -107,10 +107,28 @@ string YulUtilFunctions::copyToMemoryFunction(bool _fromCalldata)
|
||||
});
|
||||
}
|
||||
|
||||
string YulUtilFunctions::copyToMemoryLiteralFunction(string const& _literal)
|
||||
string YulUtilFunctions::copyLiteralToMemoryFunction(string const& _literal)
|
||||
{
|
||||
solAssert(!_literal.empty(), "");
|
||||
string functionName = "copy_literal_to_memory_" + h256(_literal, h256::AlignLeft).hex();
|
||||
string functionName = "copy_literal_to_memory_" + util::toHex(util::keccak256(_literal).asBytes());
|
||||
|
||||
return m_functionCollector.createFunction(functionName, [&]() {
|
||||
return Whiskers(R"(
|
||||
function <functionName>() -> memPtr {
|
||||
memPtr := <arrayAllocationFunction>(<size>)
|
||||
<storeLiteralInMem>(add(memPtr, 32))
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("arrayAllocationFunction", allocateMemoryArrayFunction(*TypeProvider::array(DataLocation::Memory, true)))
|
||||
("size", to_string(_literal.size()))
|
||||
("storeLiteralInMem", storeLiteralInMemoryFunction(_literal))
|
||||
.render();
|
||||
});
|
||||
}
|
||||
|
||||
string YulUtilFunctions::storeLiteralInMemoryFunction(string const& _literal)
|
||||
{
|
||||
string functionName = "store_literal_in_memory_" + util::toHex(util::keccak256(_literal).asBytes());
|
||||
|
||||
return m_functionCollector.createFunction(functionName, [&]() {
|
||||
size_t words = (_literal.length() + 31) / 32;
|
||||
@ -122,18 +140,13 @@ string YulUtilFunctions::copyToMemoryLiteralFunction(string const& _literal)
|
||||
}
|
||||
|
||||
return Whiskers(R"(
|
||||
function <functionName>() -> memPtr {
|
||||
memPtr := <allocationFunction>(add(<size>, 32))
|
||||
mstore(memPtr, <size>)
|
||||
let dataPos := add(memPtr, 32)
|
||||
function <functionName>(memPtr) {
|
||||
<#word>
|
||||
mstore(add(dataPos, <offset>), <wordValue>)
|
||||
mstore(add(memPtr, <offset>), <wordValue>)
|
||||
</word>
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("allocationFunction", allocationFunction())
|
||||
("size", to_string(_literal.size()))
|
||||
("word", wordParams)
|
||||
.render();
|
||||
});
|
||||
@ -3933,31 +3946,14 @@ string YulUtilFunctions::conversionFunctionSpecial(Type const& _from, Type const
|
||||
}
|
||||
else if (_to.category() == Type::Category::Array)
|
||||
{
|
||||
auto const& arrayType = dynamic_cast<ArrayType const&>(_to);
|
||||
solAssert(arrayType.isByteArray(), "");
|
||||
size_t words = (data.size() + 31) / 32;
|
||||
size_t storageSize = 32 + words * 32;
|
||||
|
||||
solAssert(dynamic_cast<ArrayType const&>(_to).isByteArray(), "");
|
||||
Whiskers templ(R"(
|
||||
function <functionName>() -> converted {
|
||||
converted := <allocate>(<storageSize>)
|
||||
mstore(converted, <size>)
|
||||
<#word>
|
||||
mstore(add(converted, <offset>), <wordValue>)
|
||||
</word>
|
||||
converted := <copyLiteralToMemory>()
|
||||
}
|
||||
)");
|
||||
templ("functionName", functionName);
|
||||
templ("allocate", allocationFunction());
|
||||
templ("storageSize", to_string(storageSize));
|
||||
templ("size", to_string(data.size()));
|
||||
vector<map<string, string>> wordParams(words);
|
||||
for (size_t i = 0; i < words; ++i)
|
||||
{
|
||||
wordParams[i]["offset"] = to_string(32 + i * 32);
|
||||
wordParams[i]["wordValue"] = formatAsStringOrNumber(data.substr(32 * i, 32));
|
||||
}
|
||||
templ("word", wordParams);
|
||||
templ("copyLiteralToMemory", copyLiteralToMemoryFunction(data));
|
||||
return templ.render();
|
||||
}
|
||||
else
|
||||
|
@ -72,10 +72,14 @@ public:
|
||||
/// Pads with zeros and might write more than exactly length.
|
||||
std::string copyToMemoryFunction(bool _fromCalldata);
|
||||
|
||||
/// @returns a function name that copies string literal to memory
|
||||
/// and returns pointer to memory array containing it
|
||||
/// @returns the name of a function that copies a string literal to memory
|
||||
/// and returns a pointer to the memory area containing the string literal.
|
||||
/// signature: () -> memPtr
|
||||
std::string copyToMemoryLiteralFunction(std::string const& _literal);
|
||||
std::string copyLiteralToMemoryFunction(std::string const& _literal);
|
||||
|
||||
/// @returns the name of a function that stores a string literal at a specific location in memory
|
||||
/// signature: (memPtr) ->
|
||||
std::string storeLiteralInMemoryFunction(std::string const& _literal);
|
||||
|
||||
// @returns the name of a function that has the equivalent logic of an
|
||||
// `assert` or `require` call.
|
||||
|
@ -1739,7 +1739,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
{
|
||||
TypePointer arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
|
||||
ContractDefinition const& contract = dynamic_cast<ContractType const&>(*arg).contractDefinition();
|
||||
define(IRVariable(_memberAccess)) << m_utils.copyToMemoryLiteralFunction(contract.name()) << "()\n";
|
||||
define(IRVariable(_memberAccess)) << m_utils.copyLiteralToMemoryFunction(contract.name()) << "()\n";
|
||||
}
|
||||
else if (member == "interfaceId")
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user