Merge pull request #11066 from ethereum/functionCollectorrefactor

Adding additional interface to yul function collector.
This commit is contained in:
chriseth 2021-03-15 21:42:34 +01:00 committed by GitHub
commit ae1b321a2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 12 deletions

View File

@ -23,11 +23,13 @@
#include <libsolidity/codegen/MultiUseYulFunctionCollector.h>
#include <liblangutil/Exceptions.h>
#include <libsolutil/Whiskers.h>
#include <libsolutil/StringUtils.h>
using namespace std;
using namespace solidity;
using namespace solidity::frontend;
using namespace solidity::util;
string MultiUseYulFunctionCollector::requestedFunctions()
{
@ -54,3 +56,31 @@ string MultiUseYulFunctionCollector::createFunction(string const& _name, functio
}
return _name;
}
string MultiUseYulFunctionCollector::createFunction(
string const& _name,
function<string(vector<string>&, vector<string>&)> const& _creator
)
{
solAssert(!_name.empty(), "");
if (!m_requestedFunctions.count(_name))
{
m_requestedFunctions[_name] = "<<STUB<<";
vector<string> arguments;
vector<string> returnParameters;
string body = _creator(arguments, returnParameters);
solAssert(!body.empty(), "");
m_requestedFunctions[_name] = Whiskers(R"(
function <functionName>(<args>)<?+retParams> -> <retParams></+retParams> {
<body>
}
)")
("functionName", _name)
("args", joinHumanReadable(arguments))
("retParams", joinHumanReadable(returnParameters))
("body", body)
.render();;
}
return _name;
}

View File

@ -41,6 +41,11 @@ public:
/// cases.
std::string createFunction(std::string const& _name, std::function<std::string()> const& _creator);
std::string createFunction(
std::string const& _name,
std::function<std::string(std::vector<std::string>&, std::vector<std::string>&)> const& _creator
);
/// @returns concatenation of all generated functions.
/// Guarantees that the order of functions in the generated code is deterministic and
/// platform-independent.

View File

@ -3285,19 +3285,17 @@ string YulUtilFunctions::copyStructToStorageFunction(StructType const& _from, St
"_to_" +
_to.identifier();
return m_functionCollector.createFunction(functionName, [&]() {
return m_functionCollector.createFunction(functionName, [&](auto& _arguments, auto&) {
_arguments = {"slot", "value"};
Whiskers templ(R"(
function <functionName>(slot, value) {
<?fromStorage> if iszero(eq(slot, value)) { </fromStorage>
<#member>
{
<updateMemberCall>
}
</member>
<?fromStorage> } </fromStorage>
<?fromStorage> if iszero(eq(slot, value)) { </fromStorage>
<#member>
{
<updateMemberCall>
}
</member>
<?fromStorage> } </fromStorage>
)");
templ("functionName", functionName);
templ("fromStorage", _from.dataStoredIn(DataLocation::Storage));
MemberList::MemberMap structMembers = _from.nativeMembers(nullptr);
@ -3368,7 +3366,7 @@ string YulUtilFunctions::copyStructToStorageFunction(StructType const& _from, St
}
else if (fromStorage)
{
auto[srcSlotOffset, srcOffset] = _from.storageOffsetsOfMember(structMembers[i].name);
auto const& [srcSlotOffset, srcOffset] = _from.storageOffsetsOfMember(structMembers[i].name);
t("memberOffset", formatNumber(srcSlotOffset));
if (memberType.isValueType())
t("read", readFromStorageValueType(memberType, srcOffset, false));