| 236 | } |
| 237 | |
| 238 | std::string YulUtilFunctions::revertWithError( |
| 239 | std::string const& _signature, |
| 240 | std::vector<Type const*> const& _parameterTypes, |
| 241 | std::vector<ASTPointer<Expression const>> const& _errorArguments, |
| 242 | std::string const& _posVar, |
| 243 | std::string const& _endVar |
| 244 | ) |
| 245 | { |
| 246 | solAssert((!_posVar.empty() && !_endVar.empty()) || (_posVar.empty() && _endVar.empty())); |
| 247 | bool const needsNewVariable = !_posVar.empty() && !_endVar.empty(); |
| 248 | bool needsAllocation = true; |
| 249 | |
| 250 | if (std::optional<size_t> size = staticEncodingSize(_parameterTypes)) |
| 251 | if ( |
| 252 | ranges::all_of(_parameterTypes, [](auto const* type) { |
| 253 | solAssert(!dynamic_cast<InaccessibleDynamicType const*>(type)); |
| 254 | return type && type->isValueType(); |
| 255 | }) |
| 256 | ) |
| 257 | { |
| 258 | constexpr size_t errorSelectorSize = 4; |
| 259 | needsAllocation = *size + errorSelectorSize > CompilerUtils::generalPurposeMemoryStart; |
| 260 | } |
| 261 | |
| 262 | Whiskers templ(R"({ |
| 263 | <?needsAllocation> |
| 264 | let <pos> := <allocateUnbounded>() |
| 265 | <!needsAllocation> |
| 266 | let <pos> := 0 |
| 267 | </needsAllocation> |
| 268 | mstore(<pos>, <hash>) |
| 269 | let <end> := <encode>(add(<pos>, 4) <argumentVars>) |
| 270 | revert(<pos>, sub(<end>, <pos>)) |
| 271 | })"); |
| 272 | templ("pos", needsNewVariable ? _posVar : "memPtr"); |
| 273 | templ("end", needsNewVariable ? _endVar : "end"); |
| 274 | templ("hash", formatNumber(util::selectorFromSignatureU256(_signature))); |
| 275 | templ("needsAllocation", needsAllocation); |
| 276 | if (needsAllocation) |
| 277 | templ("allocateUnbounded", allocateUnboundedFunction()); |
| 278 | |
| 279 | std::vector<std::string> errorArgumentVars; |
| 280 | std::vector<Type const*> errorArgumentTypes; |
| 281 | for (ASTPointer<Expression const> const& arg: _errorArguments) |
| 282 | { |
| 283 | errorArgumentVars += IRVariable(*arg).stackSlots(); |
| 284 | solAssert(arg->annotation().type); |
| 285 | errorArgumentTypes.push_back(arg->annotation().type); |
| 286 | } |
| 287 | templ("argumentVars", joinHumanReadablePrefixed(errorArgumentVars)); |
| 288 | templ("encode", ABIFunctions(m_evmVersion, m_eofVersion, m_revertStrings, m_functionCollector).tupleEncoder(errorArgumentTypes, _parameterTypes)); |
| 289 | |
| 290 | return templ.render(); |
| 291 | } |
| 292 | |
| 293 | std::string YulUtilFunctions::requireOrAssertFunction(bool _assert, Type const* _messageType, ASTPointer<Expression const> _stringArgumentExpression) |
| 294 | { |
nothing calls this directly
no test coverage detected