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"(
|
Whiskers templ(R"(
|
||||||
function <functionName>(pos) -> end {
|
function <functionName>(pos) -> end {
|
||||||
pos := <storeLength>(pos, <length>)
|
pos := <storeLength>(pos, <length>)
|
||||||
<#word>
|
<storeLiteralInMemory>(pos)
|
||||||
mstore(add(pos, <offset>), <wordValue>)
|
|
||||||
</word>
|
|
||||||
end := add(pos, <overallSize>)
|
end := add(pos, <overallSize>)
|
||||||
}
|
}
|
||||||
)");
|
)");
|
||||||
templ("functionName", functionName);
|
templ("functionName", functionName);
|
||||||
|
|
||||||
// TODO this can make use of CODECOPY for large strings once we have that in Yul
|
// 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("length", to_string(value.size()));
|
||||||
templ("storeLength", arrayStoreLengthForEncodingFunction(dynamic_cast<ArrayType const&>(_to), _options));
|
templ("storeLength", arrayStoreLengthForEncodingFunction(dynamic_cast<ArrayType const&>(_to), _options));
|
||||||
if (_options.padded)
|
if (_options.padded)
|
||||||
templ("overallSize", to_string(words * 32));
|
templ("overallSize", to_string(((value.size() + 31) / 32) * 32));
|
||||||
else
|
else
|
||||||
templ("overallSize", to_string(value.size()));
|
templ("overallSize", to_string(value.size()));
|
||||||
|
templ("storeLiteralInMemory", m_utils.storeLiteralInMemoryFunction(value));
|
||||||
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);
|
|
||||||
return templ.render();
|
return templ.render();
|
||||||
}
|
}
|
||||||
else
|
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_" + util::toHex(util::keccak256(_literal).asBytes());
|
||||||
string functionName = "copy_literal_to_memory_" + h256(_literal, h256::AlignLeft).hex();
|
|
||||||
|
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, [&]() {
|
return m_functionCollector.createFunction(functionName, [&]() {
|
||||||
size_t words = (_literal.length() + 31) / 32;
|
size_t words = (_literal.length() + 31) / 32;
|
||||||
@ -122,18 +140,13 @@ string YulUtilFunctions::copyToMemoryLiteralFunction(string const& _literal)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Whiskers(R"(
|
return Whiskers(R"(
|
||||||
function <functionName>() -> memPtr {
|
function <functionName>(memPtr) {
|
||||||
memPtr := <allocationFunction>(add(<size>, 32))
|
|
||||||
mstore(memPtr, <size>)
|
|
||||||
let dataPos := add(memPtr, 32)
|
|
||||||
<#word>
|
<#word>
|
||||||
mstore(add(dataPos, <offset>), <wordValue>)
|
mstore(add(memPtr, <offset>), <wordValue>)
|
||||||
</word>
|
</word>
|
||||||
}
|
}
|
||||||
)")
|
)")
|
||||||
("functionName", functionName)
|
("functionName", functionName)
|
||||||
("allocationFunction", allocationFunction())
|
|
||||||
("size", to_string(_literal.size()))
|
|
||||||
("word", wordParams)
|
("word", wordParams)
|
||||||
.render();
|
.render();
|
||||||
});
|
});
|
||||||
@ -3933,31 +3946,14 @@ string YulUtilFunctions::conversionFunctionSpecial(Type const& _from, Type const
|
|||||||
}
|
}
|
||||||
else if (_to.category() == Type::Category::Array)
|
else if (_to.category() == Type::Category::Array)
|
||||||
{
|
{
|
||||||
auto const& arrayType = dynamic_cast<ArrayType const&>(_to);
|
solAssert(dynamic_cast<ArrayType const&>(_to).isByteArray(), "");
|
||||||
solAssert(arrayType.isByteArray(), "");
|
|
||||||
size_t words = (data.size() + 31) / 32;
|
|
||||||
size_t storageSize = 32 + words * 32;
|
|
||||||
|
|
||||||
Whiskers templ(R"(
|
Whiskers templ(R"(
|
||||||
function <functionName>() -> converted {
|
function <functionName>() -> converted {
|
||||||
converted := <allocate>(<storageSize>)
|
converted := <copyLiteralToMemory>()
|
||||||
mstore(converted, <size>)
|
|
||||||
<#word>
|
|
||||||
mstore(add(converted, <offset>), <wordValue>)
|
|
||||||
</word>
|
|
||||||
}
|
}
|
||||||
)");
|
)");
|
||||||
templ("functionName", functionName);
|
templ("functionName", functionName);
|
||||||
templ("allocate", allocationFunction());
|
templ("copyLiteralToMemory", copyLiteralToMemoryFunction(data));
|
||||||
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);
|
|
||||||
return templ.render();
|
return templ.render();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -72,10 +72,14 @@ public:
|
|||||||
/// Pads with zeros and might write more than exactly length.
|
/// Pads with zeros and might write more than exactly length.
|
||||||
std::string copyToMemoryFunction(bool _fromCalldata);
|
std::string copyToMemoryFunction(bool _fromCalldata);
|
||||||
|
|
||||||
/// @returns a function name that copies string literal to memory
|
/// @returns the name of a function that copies a string literal to memory
|
||||||
/// and returns pointer to memory array containing it
|
/// and returns a pointer to the memory area containing the string literal.
|
||||||
/// signature: () -> memPtr
|
/// 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
|
// @returns the name of a function that has the equivalent logic of an
|
||||||
// `assert` or `require` call.
|
// `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();
|
TypePointer arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
|
||||||
ContractDefinition const& contract = dynamic_cast<ContractType const&>(*arg).contractDefinition();
|
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")
|
else if (member == "interfaceId")
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user