Refactoring revertReasonIfDebug in YulUtilFunctions.

This commit is contained in:
Djordje Mijovic 2020-05-25 17:14:28 +02:00
parent 21a9d3dd21
commit fa69eaf11b
12 changed files with 83 additions and 31 deletions

View File

@ -1541,5 +1541,5 @@ size_t ABIFunctions::numVariablesForType(Type const& _type, EncodingOptions cons
std::string ABIFunctions::revertReasonIfDebug(std::string const& _message) std::string ABIFunctions::revertReasonIfDebug(std::string const& _message)
{ {
return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _message); return m_utils.revertReasonIfDebugAssembly(m_revertStrings, _message);
} }

View File

@ -529,7 +529,7 @@ LinkerObject const& CompilerContext::assembledObject() const
string CompilerContext::revertReasonIfDebug(string const& _message) string CompilerContext::revertReasonIfDebug(string const& _message)
{ {
return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _message); return m_yulUtilFunctions.revertReasonIfDebugAssembly(m_revertStrings, _message);
} }
void CompilerContext::updateSourceLocation() void CompilerContext::updateSourceLocation()

View File

@ -1159,8 +1159,8 @@ string YulUtilFunctions::calldataArrayIndexRangeAccess(ArrayType const& _type)
)") )")
("functionName", functionName) ("functionName", functionName)
("stride", to_string(_type.calldataStride())) ("stride", to_string(_type.calldataStride()))
("revertSliceStartAfterEnd", revertReasonIfDebug("Slice starts after end")) ("revertSliceStartAfterEnd", revertReasonIfDebugAssembly(m_revertStrings, "Slice starts after end"))
("revertSliceGreaterThanLength", revertReasonIfDebug("Slice is greater than length")) ("revertSliceGreaterThanLength", revertReasonIfDebugAssembly(m_revertStrings, "Slice is greater than length"))
.render(); .render();
}); });
} }
@ -1188,9 +1188,9 @@ string YulUtilFunctions::accessCalldataTailFunction(Type const& _type)
("dynamicallySized", _type.isDynamicallySized()) ("dynamicallySized", _type.isDynamicallySized())
("neededLength", toCompactHexWithPrefix(_type.calldataEncodedTailSize())) ("neededLength", toCompactHexWithPrefix(_type.calldataEncodedTailSize()))
("calldataStride", toCompactHexWithPrefix(_type.isDynamicallySized() ? dynamic_cast<ArrayType const&>(_type).calldataStride() : 0)) ("calldataStride", toCompactHexWithPrefix(_type.isDynamicallySized() ? dynamic_cast<ArrayType const&>(_type).calldataStride() : 0))
("invalidCalldataTailOffset", revertReasonIfDebug("Invalid calldata tail offset")) ("invalidCalldataTailOffset", revertReasonIfDebugAssembly(m_revertStrings, "Invalid calldata tail offset"))
("invalidCalldataTailLength", revertReasonIfDebug("Invalid calldata tail length")) ("invalidCalldataTailLength", revertReasonIfDebugAssembly(m_revertStrings, "Invalid calldata tail length"))
("shortCalldataTail", revertReasonIfDebug("Calldata tail too short")) ("shortCalldataTail", revertReasonIfDebugAssembly(m_revertStrings, "Calldata tail too short"))
.render(); .render();
}); });
} }
@ -2495,11 +2495,10 @@ string YulUtilFunctions::readFromMemoryOrCalldata(Type const& _type, bool _fromC
}); });
} }
string YulUtilFunctions::revertReasonIfDebug(RevertStrings revertStrings, string const& _message) string YulUtilFunctions::revertReasonIfDebugAssembly(RevertStrings _revertStrings, std::string const& _message)
{ {
if (revertStrings >= RevertStrings::Debug && !_message.empty()) Whiskers templ(R"({
{ <?debugAndMessage>
Whiskers templ(R"({
mstore(0, <sig>) mstore(0, <sig>)
mstore(4, 0x20) mstore(4, 0x20)
mstore(add(4, 0x20), <length>) mstore(add(4, 0x20), <length>)
@ -2508,29 +2507,56 @@ string YulUtilFunctions::revertReasonIfDebug(RevertStrings revertStrings, string
mstore(add(reasonPos, <offset>), <wordValue>) mstore(add(reasonPos, <offset>), <wordValue>)
</word> </word>
revert(0, add(reasonPos, <end>)) revert(0, add(reasonPos, <end>))
})"); <!debugAndMessage>
templ("sig", (u256(util::FixedHash<4>::Arith(util::FixedHash<4>(util::keccak256("Error(string)")))) << (256 - 32)).str()); revert(0, 0)
</debugAndMessage>
})");
bool debugAndMessage = _revertStrings >= RevertStrings::Debug && !_message.empty();
templ("debugAndMessage", debugAndMessage);
if (debugAndMessage)
{
templ("sig", (u256(util::FixedHash<4>::Arith(util::FixedHash<4>(util::keccak256("Error(string)"))))
<< (256 - 32)).str());
templ("length", to_string(_message.length())); templ("length", to_string(_message.length()));
size_t words = (_message.length() + 31) / 32; size_t words = (_message.length() + 31) / 32;
vector<map<string, string>> wordParams(words); vector<map<string, string>> wordParams(words);
for (size_t i = 0; i < words; ++i) for (size_t i = 0; i < words; ++i) {
{
wordParams[i]["offset"] = to_string(i * 32); wordParams[i]["offset"] = to_string(i * 32);
wordParams[i]["wordValue"] = formatAsStringOrNumber(_message.substr(32 * i, 32)); wordParams[i]["wordValue"] = formatAsStringOrNumber(_message.substr(32 * i, 32));
} }
templ("word", wordParams); templ("word", wordParams);
templ("end", to_string(words * 32)); templ("end", to_string(words * 32));
return templ.render();
} }
else
return "revert(0, 0)"; return templ.render();
} }
string YulUtilFunctions::revertReasonIfDebug(string const& _message) string YulUtilFunctions::revertReasonIfDebugFunction(RevertStrings _revertStrings, string const& _message)
{ {
return revertReasonIfDebug(m_revertStrings, _message); string functionName = "revert_reason_" + revertStringsToString(_revertStrings) + "_";
for (char c: _message)
if (isalnum(c))
functionName += tolower(c);
else if (isspace(c))
functionName += "_";
return m_functionCollector.createFunction(functionName, [&]() {
Whiskers templ(R"({
function <functionName>() {
<revertReasonAssembly>
}
})");
templ("functionName", functionName);
templ("revertReasonAssembly", revertReasonIfDebugAssembly(_revertStrings, _message));
return templ.render();
});
}
string YulUtilFunctions::revertReasonIfDebugFunction(string const& _message)
{
return revertReasonIfDebugFunction(m_revertStrings, _message);
} }
string YulUtilFunctions::tryDecodeErrorMessageFunction() string YulUtilFunctions::tryDecodeErrorMessageFunction()

View File

@ -335,9 +335,11 @@ public:
/// If revertStrings is debug, @returns inline assembly code that /// If revertStrings is debug, @returns inline assembly code that
/// stores @param _message in memory position 0 and reverts. /// stores @param _message in memory position 0 and reverts.
/// Otherwise returns "revert(0, 0)". /// Otherwise returns "revert(0, 0)".
static std::string revertReasonIfDebug(RevertStrings revertStrings, std::string const& _message = ""); std::string revertReasonIfDebugAssembly(RevertStrings revertStrings, std::string const& _message = "");
std::string revertReasonIfDebug(std::string const& _message = ""); std::string revertReasonIfDebugFunction(RevertStrings revertStrings, std::string const& _message = "");
std::string revertReasonIfDebugFunction(std::string const& _message = "");
/// Returns the name of a function that decodes an error message. /// Returns the name of a function that decodes an error message.
/// signature: () -> arrayPtr /// signature: () -> arrayPtr

View File

@ -186,5 +186,5 @@ ABIFunctions IRGenerationContext::abiFunctions()
std::string IRGenerationContext::revertReasonIfDebug(std::string const& _message) std::string IRGenerationContext::revertReasonIfDebug(std::string const& _message)
{ {
return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _message); return utils().revertReasonIfDebugFunction(m_revertStrings, _message) + "()";
} }

View File

@ -36,7 +36,7 @@ object \"C_6\" {
revert(0, 0) revert(0, 0)
function abi_decode_tuple_(headStart, dataEnd) function abi_decode_tuple_(headStart, dataEnd)
{ {
if slt(sub(dataEnd, headStart), 0) { revert(0, 0) } if slt(sub(dataEnd, headStart), 0) { { revert(0, 0) } }
} }
function abi_encode_tuple__to__fromStack(headStart) -> tail function abi_encode_tuple__to__fromStack(headStart) -> tail
{ tail := add(headStart, 0) } { tail := add(headStart, 0) }

View File

@ -48,7 +48,11 @@ object \"C_6\" {
revert(0, 0) revert(0, 0)
function abi_decode_tuple_(headStart, dataEnd) { function abi_decode_tuple_(headStart, dataEnd) {
if slt(sub(dataEnd, headStart), 0) { revert(0, 0) } if slt(sub(dataEnd, headStart), 0) { {
revert(0, 0)
} }
} }

View File

@ -48,7 +48,11 @@ object \"C_10\" {
revert(0, 0) revert(0, 0)
function abi_decode_tuple_(headStart, dataEnd) { function abi_decode_tuple_(headStart, dataEnd) {
if slt(sub(dataEnd, headStart), 0) { revert(0, 0) } if slt(sub(dataEnd, headStart), 0) { {
revert(0, 0)
} }
} }

View File

@ -48,7 +48,11 @@ object \"C_10\" {
revert(0, 0) revert(0, 0)
function abi_decode_tuple_(headStart, dataEnd) { function abi_decode_tuple_(headStart, dataEnd) {
if slt(sub(dataEnd, headStart), 0) { revert(0, 0) } if slt(sub(dataEnd, headStart), 0) { {
revert(0, 0)
} }
} }

View File

@ -48,7 +48,11 @@ object \"C_10\" {
revert(0, 0) revert(0, 0)
function abi_decode_tuple_(headStart, dataEnd) { function abi_decode_tuple_(headStart, dataEnd) {
if slt(sub(dataEnd, headStart), 0) { revert(0, 0) } if slt(sub(dataEnd, headStart), 0) { {
revert(0, 0)
} }
} }

View File

@ -48,7 +48,11 @@ object \"C_10\" {
revert(0, 0) revert(0, 0)
function abi_decode_tuple_(headStart, dataEnd) { function abi_decode_tuple_(headStart, dataEnd) {
if slt(sub(dataEnd, headStart), 0) { revert(0, 0) } if slt(sub(dataEnd, headStart), 0) { {
revert(0, 0)
} }
} }

View File

@ -48,7 +48,11 @@ object \"C_10\" {
revert(0, 0) revert(0, 0)
function abi_decode_tuple_(headStart, dataEnd) { function abi_decode_tuple_(headStart, dataEnd) {
if slt(sub(dataEnd, headStart), 0) { revert(0, 0) } if slt(sub(dataEnd, headStart), 0) { {
revert(0, 0)
} }
} }