| 327 | } |
| 328 | |
| 329 | std::string YulUtilFunctions::requireWithErrorFunction(FunctionCall const& errorConstructorCall) |
| 330 | { |
| 331 | ErrorDefinition const* errorDefinition = dynamic_cast<ErrorDefinition const*>(ASTNode::referencedDeclaration(errorConstructorCall.expression())); |
| 332 | solAssert(errorDefinition); |
| 333 | |
| 334 | std::string const errorSignature = errorDefinition->functionType(true)->externalSignature(); |
| 335 | // Note that in most cases we'll always generate one function per error definition, |
| 336 | // because types in the constructor call will match the ones in the definition. The only |
| 337 | // exception are calls with types, where each instance has its own type (e.g. literals). |
| 338 | std::string functionName = "require_helper_t_error_" + std::to_string(errorDefinition->id()) + "_" + errorDefinition->name(); |
| 339 | for (ASTPointer<Expression const> const& argument: errorConstructorCall.sortedArguments()) |
| 340 | { |
| 341 | solAssert(argument->annotation().type); |
| 342 | functionName += ("_" + argument->annotation().type->identifier()); |
| 343 | } |
| 344 | |
| 345 | std::vector<std::string> functionParameterNames; |
| 346 | for (ASTPointer<Expression const> const& arg: errorConstructorCall.sortedArguments()) |
| 347 | { |
| 348 | solAssert(arg->annotation().type); |
| 349 | if (arg->annotation().type->sizeOnStack() > 0) |
| 350 | functionParameterNames += IRVariable(*arg).stackSlots(); |
| 351 | } |
| 352 | |
| 353 | return m_functionCollector.createFunction(functionName, [&]() { |
| 354 | return Whiskers(R"( |
| 355 | function <functionName>(condition <functionParameterNames>) { |
| 356 | if iszero(condition) |
| 357 | <revertWithError> |
| 358 | } |
| 359 | )") |
| 360 | ("functionName", functionName) |
| 361 | ("functionParameterNames", joinHumanReadablePrefixed(functionParameterNames)) |
| 362 | // We're creating parameter names from the expressions passed into the constructor call, |
| 363 | // which will result in odd names like `expr_29` that would normally be used for locals. |
| 364 | // Note that this is the naming expected by `revertWithError()`. |
| 365 | ("revertWithError", revertWithError(errorSignature, errorDefinition->functionType(true)->parameterTypes(), errorConstructorCall.sortedArguments())) |
| 366 | .render(); |
| 367 | }); |
| 368 | } |
| 369 | |
| 370 | std::string YulUtilFunctions::leftAlignFunction(Type const& _type) |
| 371 | { |
no test coverage detected