diff --git a/libsolidity/codegen/ir/Common.cpp b/libsolidity/codegen/ir/Common.cpp index 45ec60d1e..4f414cb99 100644 --- a/libsolidity/codegen/ir/Common.cpp +++ b/libsolidity/codegen/ir/Common.cpp @@ -16,8 +16,9 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include #include +#include +#include #include @@ -25,6 +26,9 @@ using namespace std; using namespace solidity::util; using namespace solidity::frontend; +namespace solidity::frontend +{ + YulArity YulArity::fromType(FunctionType const& _functionType) { return YulArity{ @@ -122,3 +126,20 @@ string IRNames::zeroValue(Type const& _type, string const& _variableName) { return "zero_" + _type.identifier() + _variableName; } + +string sourceLocationComment(langutil::SourceLocation const& _location, IRGenerationContext const& _context) +{ + return "/// @src " + + to_string(_context.sourceIndices().at(_location.source->name())) + + ":" + + to_string(_location.start) + + "," + + to_string(_location.end); +} + +string sourceLocationComment(ASTNode const& _node, IRGenerationContext const& _context) +{ + return sourceLocationComment(_node.location(), _context); +} + +} diff --git a/libsolidity/codegen/ir/Common.h b/libsolidity/codegen/ir/Common.h index 4625b91d9..67b0cffdc 100644 --- a/libsolidity/codegen/ir/Common.h +++ b/libsolidity/codegen/ir/Common.h @@ -29,6 +29,8 @@ namespace solidity::frontend { +class IRGenerationContext; + /** * Structure that describes arity and co-arity of a Yul function, i.e. the number of its inputs and outputs. */ @@ -66,6 +68,14 @@ struct IRNames static std::string zeroValue(Type const& _type, std::string const& _variableName); }; + +/** + * @returns a source location comment in the form of + * `/// @src ::`. + */ +std::string sourceLocationComment(langutil::SourceLocation const& _location, IRGenerationContext const& _context); +std::string sourceLocationComment(ASTNode const& _node, IRGenerationContext const& _context); + } // Overloading std::less() makes it possible to use YulArity as a map key. We could define operator< diff --git a/libsolidity/codegen/ir/IRGenerationContext.h b/libsolidity/codegen/ir/IRGenerationContext.h index 0f1e9ae1c..1b41bcb71 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.h +++ b/libsolidity/codegen/ir/IRGenerationContext.h @@ -68,11 +68,13 @@ public: IRGenerationContext( langutil::EVMVersion _evmVersion, RevertStrings _revertStrings, - OptimiserSettings _optimiserSettings + OptimiserSettings _optimiserSettings, + std::map _sourceIndices ): m_evmVersion(_evmVersion), m_revertStrings(_revertStrings), - m_optimiserSettings(std::move(_optimiserSettings)) + m_optimiserSettings(std::move(_optimiserSettings)), + m_sourceIndices(std::move(_sourceIndices)) {} MultiUseYulFunctionCollector& functionCollector() { return m_functions; } @@ -150,10 +152,13 @@ public: bool inlineAssemblySeen() const { return m_inlineAssemblySeen; } void setInlineAssemblySeen() { m_inlineAssemblySeen = true; } + std::map const& sourceIndices() const { return m_sourceIndices; } + private: langutil::EVMVersion m_evmVersion; RevertStrings m_revertStrings; OptimiserSettings m_optimiserSettings; + std::map m_sourceIndices; ContractDefinition const* m_mostDerivedContract = nullptr; std::map m_localVariables; /// Memory offsets reserved for the values of immutable variables during contract creation. diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index 0dee6a496..a7adc07eb 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -21,8 +21,8 @@ * Component that translates Solidity code into Yul. */ +#include #include - #include #include @@ -107,12 +107,12 @@ pair IRGenerator::run( asmStack.optimize(); string warning = - "/*******************************************************\n" + "/*=====================================================*\n" " * WARNING *\n" " * Solidity to Yul compilation is still EXPERIMENTAL *\n" " * It can result in LOSS OF FUNDS or worse *\n" " * !USE AT YOUR OWN RISK! *\n" - " *******************************************************/\n\n"; + " *=====================================================*/\n\n"; return {warning + ir, warning + asmStack.print()}; } @@ -134,6 +134,7 @@ string IRGenerator::generate( Whiskers t(R"( object "" { code { + @@ -146,6 +147,7 @@ string IRGenerator::generate( } object "" { code { + let called_via_delegatecall := iszero(eq(loadimmutable(""), address())) @@ -164,6 +166,8 @@ string IRGenerator::generate( for (VariableDeclaration const* var: ContractType(_contract).immutableVariables()) m_context.registerImmutableVariable(*var); + t("sourceLocationComment", sourceLocationComment(_contract, m_context)); + t("CreationObject", IRNames::creationObject(_contract)); t("library", _contract.isLibrary()); @@ -186,7 +190,7 @@ string IRGenerator::generate( t("deploy", deployCode(_contract)); generateConstructors(_contract); set creationFunctionList = generateQueuedFunctions(); - InternalDispatchMap internalDispatchMap = generateInternalDispatchFunctions(); + InternalDispatchMap internalDispatchMap = generateInternalDispatchFunctions(_contract); t("functions", m_context.functionCollector().requestedFunctions()); t("subObjects", subObjectSources(m_context.subObjectsCreated())); @@ -207,7 +211,7 @@ string IRGenerator::generate( t("library_address", IRNames::libraryAddressImmutable()); t("dispatch", dispatchRoutine(_contract)); set deployedFunctionList = generateQueuedFunctions(); - generateInternalDispatchFunctions(); + generateInternalDispatchFunctions(_contract); t("deployedFunctions", m_context.functionCollector().requestedFunctions()); t("deployedSubObjects", subObjectSources(m_context.subObjectsCreated())); t("metadataName", yul::Object::metadataName()); @@ -249,7 +253,7 @@ set IRGenerator::generateQueuedFunctions() return functions; } -InternalDispatchMap IRGenerator::generateInternalDispatchFunctions() +InternalDispatchMap IRGenerator::generateInternalDispatchFunctions(ContractDefinition const& _contract) { solAssert( m_context.functionGenerationQueueEmpty(), @@ -264,6 +268,7 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions() m_context.functionCollector().createFunction(funName, [&]() { Whiskers templ(R"( function (fun, ) -> { + switch fun <#cases> case @@ -274,6 +279,7 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions() default { () } } )"); + templ("sourceLocationComment", sourceLocationComment(_contract, m_context)); templ("functionName", funName); templ("panic", m_utils.panicFunction(PanicCode::InvalidInternalFunction)); templ("in", suffixedVariableNameList("in_", 0, arity.in)); @@ -319,10 +325,14 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function) m_context.resetLocalVariables(); Whiskers t(R"( function () -> { + } )"); + + t("sourceLocationComment", sourceLocationComment(_function, m_context)); + t("functionName", functionName); vector params; for (auto const& varDecl: _function.parameters()) @@ -377,6 +387,7 @@ string IRGenerator::generateModifier( m_context.resetLocalVariables(); Whiskers t(R"( function () -> { + @@ -404,6 +415,7 @@ string IRGenerator::generateModifier( _modifierInvocation.name().annotation().referencedDeclaration ); solAssert(modifier, ""); + t("sourceLocationComment", sourceLocationComment(*modifier, m_context)); switch (*_modifierInvocation.name().annotation().requiredLookup) { case VirtualLookup::Virtual: @@ -455,10 +467,12 @@ string IRGenerator::generateFunctionWithModifierInner(FunctionDefinition const& m_context.resetLocalVariables(); Whiskers t(R"( function () -> { + } )"); + t("sourceLocationComment", sourceLocationComment(_function, m_context)); t("functionName", functionName); vector retParams; vector retParamsIn; @@ -497,9 +511,11 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) solUnimplementedAssert(type->sizeOnStack() == 1, ""); return Whiskers(R"( function () -> rval { + rval := loadimmutable("") } )") + ("sourceLocationComment", sourceLocationComment(_varDecl, m_context)) ("functionName", functionName) ("id", to_string(_varDecl.id())) .render(); @@ -509,9 +525,11 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) solAssert(paramTypes.empty(), ""); return Whiskers(R"( function () -> { + := () } )") + ("sourceLocationComment", sourceLocationComment(_varDecl, m_context)) ("functionName", functionName) ("constantValueFunction", IRGeneratorForStatements(m_context, m_utils).constantValueFunction(_varDecl)) ("ret", suffixedVariableNameList("ret_", 0, _varDecl.type()->sizeOnStack())) @@ -624,6 +642,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) return Whiskers(R"( function () -> { + } )") @@ -631,6 +650,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) ("params", joinHumanReadable(parameters)) ("retVariables", joinHumanReadable(returnVariables)) ("code", std::move(code)) + ("sourceLocationComment", sourceLocationComment(_varDecl, m_context)) .render(); }); } @@ -739,6 +759,7 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract) Whiskers t(R"( function () { + () @@ -748,6 +769,14 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract) if (contract->constructor()) for (ASTPointer const& varDecl: contract->constructor()->parameters()) params += m_context.addLocalVariable(*varDecl).stackSlots(); + + t("sourceLocationComment", sourceLocationComment( + contract->constructor() ? + contract->constructor()->location() : + contract->location(), + m_context + )); + t("params", joinHumanReadable(params)); vector baseParams = listAllParams(baseConstructorParams); t("baseParams", joinHumanReadable(baseParams)); @@ -984,7 +1013,7 @@ void IRGenerator::resetContext(ContractDefinition const& _contract) m_context.internalDispatchClean(), "Reset internal dispatch map without consuming it." ); - m_context = IRGenerationContext(m_evmVersion, m_context.revertStrings(), m_optimiserSettings); + m_context = IRGenerationContext(m_evmVersion, m_context.revertStrings(), m_optimiserSettings, m_context.sourceIndices()); m_context.setMostDerivedContract(_contract); for (auto const& var: ContractType(_contract).stateVariables()) diff --git a/libsolidity/codegen/ir/IRGenerator.h b/libsolidity/codegen/ir/IRGenerator.h index fb7dde788..528fc3c7b 100644 --- a/libsolidity/codegen/ir/IRGenerator.h +++ b/libsolidity/codegen/ir/IRGenerator.h @@ -42,11 +42,12 @@ public: IRGenerator( langutil::EVMVersion _evmVersion, RevertStrings _revertStrings, - OptimiserSettings _optimiserSettings + OptimiserSettings _optimiserSettings, + std::map _sourceIndices ): m_evmVersion(_evmVersion), m_optimiserSettings(_optimiserSettings), - m_context(_evmVersion, _revertStrings, std::move(_optimiserSettings)), + m_context(_evmVersion, _revertStrings, std::move(_optimiserSettings), std::move(_sourceIndices)), m_utils(_evmVersion, m_context.revertStrings(), m_context.functionCollector()) {} @@ -74,7 +75,7 @@ private: /// possibly be called via a pointer. /// @return The content of the dispatch for reuse in runtime code. Reuse is necessary because /// pointers to functions can be passed from the creation code in storage variables. - InternalDispatchMap generateInternalDispatchFunctions(); + InternalDispatchMap generateInternalDispatchFunctions(ContractDefinition const& _contract); /// Generates code for and returns the name of the function. std::string generateFunction(FunctionDefinition const& _function); std::string generateModifier( diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index b4d2e5db0..2d4f9e724 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -205,10 +205,34 @@ private: } +string IRGeneratorForStatementsBase::code() const +{ + return m_code.str(); +} + +std::ostringstream& IRGeneratorForStatementsBase::appendCode(bool _addLocationComment) +{ + if ( + _addLocationComment && + m_currentLocation.isValid() && + m_lastLocation != m_currentLocation + ) + m_code << sourceLocationComment(m_currentLocation, m_context) << "\n"; + + m_lastLocation = m_currentLocation; + + return m_code; +} + +void IRGeneratorForStatementsBase::setLocation(ASTNode const& _node) +{ + m_currentLocation = _node.location(); +} + string IRGeneratorForStatements::code() const { solAssert(!m_currentLValue, "LValue not reset!"); - return m_code.str(); + return IRGeneratorForStatementsBase::code(); } void IRGeneratorForStatements::generate(Block const& _block) @@ -289,6 +313,8 @@ IRVariable IRGeneratorForStatements::evaluateExpression(Expression const& _expre setLocation(_expression); _expression.accept(*this); + + setLocation(_expression); IRVariable variable{m_context.newYulVariable(), _targetType}; define(variable, _expression); return variable; @@ -305,16 +331,16 @@ string IRGeneratorForStatements::constantValueFunction(VariableDeclaration const { try { - setLocation(_constant); - string functionName = IRNames::constantValueFunction(_constant); return m_context.functionCollector().createFunction(functionName, [&] { Whiskers templ(R"( + function () -> { := } )"); + templ("sourceLocationComment", sourceLocationComment(_constant, m_context)); templ("functionName", functionName); IRGeneratorForStatements generator(m_context, m_utils); solAssert(_constant.value(), ""); @@ -376,19 +402,19 @@ bool IRGeneratorForStatements::visit(Conditional const& _conditional) string condition = expressionAsType(_conditional.condition(), *TypeProvider::boolean()); declare(_conditional); - m_code << "switch " << condition << "\n" "case 0 {\n"; + appendCode() << "switch " << condition << "\n" "case 0 {\n"; _conditional.falseExpression().accept(*this); setLocation(_conditional); assign(_conditional, _conditional.falseExpression()); - m_code << "}\n" "default {\n"; + appendCode() << "}\n" "default {\n"; _conditional.trueExpression().accept(*this); setLocation(_conditional); assign(_conditional, _conditional.trueExpression()); - m_code << "}\n"; + appendCode() << "}\n"; return false; } @@ -472,7 +498,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple) component.accept(*this); setLocation(_tuple); IRVariable converted = convert(component, baseType); - m_code << + appendCode() << m_utils.writeToMemoryFunction(baseType) << "(" << ("add(" + mpos + ", " + to_string(i * arrayType.memoryStride()) + ")") << @@ -553,24 +579,25 @@ bool IRGeneratorForStatements::visit(IfStatement const& _ifStatement) if (_ifStatement.falseStatement()) { - m_code << "switch " << condition << "\n" "case 0 {\n"; + appendCode() << "switch " << condition << "\n" "case 0 {\n"; _ifStatement.falseStatement()->accept(*this); setLocation(_ifStatement); - m_code << "}\n" "default {\n"; + appendCode() << "}\n" "default {\n"; } else - m_code << "if " << condition << " {\n"; + appendCode() << "if " << condition << " {\n"; _ifStatement.trueStatement().accept(*this); setLocation(_ifStatement); - m_code << "}\n"; + appendCode() << "}\n"; return false; } -void IRGeneratorForStatements::endVisit(PlaceholderStatement const&) +void IRGeneratorForStatements::endVisit(PlaceholderStatement const& _placeholder) { solAssert(m_placeholderCallback, ""); - m_code << m_placeholderCallback(); + setLocation(_placeholder); + appendCode() << m_placeholderCallback(); } bool IRGeneratorForStatements::visit(ForStatement const& _forStatement) @@ -603,14 +630,14 @@ bool IRGeneratorForStatements::visit(WhileStatement const& _whileStatement) bool IRGeneratorForStatements::visit(Continue const& _continue) { setLocation(_continue); - m_code << "continue\n"; + appendCode() << "continue\n"; return false; } bool IRGeneratorForStatements::visit(Break const& _break) { setLocation(_break); - m_code << "break\n"; + appendCode() << "break\n"; return false; } @@ -628,7 +655,7 @@ void IRGeneratorForStatements::endVisit(Return const& _return) else if (returnParameters.size() == 1) assign(m_context.localVariable(*returnParameters.front()), *value); } - m_code << "leave\n"; + appendCode() << "leave\n"; } void IRGeneratorForStatements::endVisit(UnaryOperation const& _unaryOperation) @@ -643,7 +670,7 @@ void IRGeneratorForStatements::endVisit(UnaryOperation const& _unaryOperation) std::visit( util::GenericVisitor{ [&](IRLValue::Storage const& _storage) { - m_code << + appendCode() << m_utils.storageSetToZeroFunction(m_currentLValue->type) << "(" << _storage.slot << @@ -870,7 +897,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) for (size_t i = 0; i < arguments.size(); i++) { IRVariable converted = convert(*arguments[i], *parameterTypes[i]); - m_code << + appendCode() << m_utils.writeToMemoryFunction(*functionType->parameterTypes()[i]) << "(add(" << IRVariable(_functionCall).part("mpos").name() << @@ -1001,7 +1028,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) templ("indexedArgs", joinHumanReadablePrefixed(indexedArgs | ranges::views::transform([&](auto const& _arg) { return _arg.commaSeparatedList(); }))); - m_code << templ.render(); + appendCode() << templ.render(); break; } case FunctionType::Kind::Error: @@ -1030,10 +1057,10 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) messageArgumentType ); - m_code << move(requireOrAssertFunction) << "(" << IRVariable(*arguments[0]).name(); + appendCode() << move(requireOrAssertFunction) << "(" << IRVariable(*arguments[0]).name(); if (messageArgumentType && messageArgumentType->sizeOnStack() > 0) - m_code << ", " << IRVariable(*arguments[1]).commaSeparatedList(); - m_code << ")\n"; + appendCode() << ", " << IRVariable(*arguments[1]).commaSeparatedList(); + appendCode() << ")\n"; break; } @@ -1075,7 +1102,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) // We might want to introduce a new set of memory handling functions here // a la "setMemoryCheckPoint" and "freeUntilCheckPoint". string freeMemoryPre = m_context.newYulVariable(); - m_code << "let " << freeMemoryPre << " := " << m_utils.allocateUnboundedFunction() << "()\n"; + appendCode() << "let " << freeMemoryPre << " := " << m_utils.allocateUnboundedFunction() << "()\n"; IRVariable array = convert(*arguments[0], *TypeProvider::bytesMemory()); IRVariable hashVariable(m_context.newYulVariable(), *TypeProvider::fixedBytes(32)); @@ -1092,7 +1119,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) IRVariable selectorVariable(m_context.newYulVariable(), *TypeProvider::fixedBytes(4)); define(selectorVariable, hashVariable); selector = selectorVariable.name(); - m_code << m_utils.finalizeAllocationFunction() << "(" << freeMemoryPre << ", 0)\n"; + appendCode() << m_utils.finalizeAllocationFunction() << "(" << freeMemoryPre << ", 0)\n"; } } else if (functionType->kind() == FunctionType::Kind::ABIEncodeWithSelector) @@ -1122,7 +1149,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) templ("arguments", joinHumanReadablePrefixed(argumentVars)); templ("finalizeAllocation", m_utils.finalizeAllocationFunction()); - m_code << templ.render(); + appendCode() << templ.render(); break; } case FunctionType::Kind::ABIDecode: @@ -1161,7 +1188,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) } templ("retVars", IRVariable(_functionCall).commaSeparatedList()); - m_code << templ.render(); + appendCode() << templ.render(); break; } case FunctionType::Kind::Revert: @@ -1173,7 +1200,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) arguments.front()->annotation().type->isImplicitlyConvertibleTo(*TypeProvider::stringMemory()), ""); if (m_context.revertStrings() == RevertStrings::Strip || arguments.empty()) - m_code << "revert(0, 0)\n"; + appendCode() << "revert(0, 0)\n"; else revertWithError( "Error(string)", @@ -1248,7 +1275,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) { auto slotName = m_context.newYulVariable(); auto offsetName = m_context.newYulVariable(); - m_code << "let " << slotName << ", " << offsetName << " := " << + appendCode() << "let " << slotName << ", " << offsetName << " := " << m_utils.storageArrayPushZeroFunction(*arrayType) << "(" << IRVariable(_functionCall.expression()).commaSeparatedList() << ")\n"; setLValue(_functionCall, IRLValue{ @@ -1266,7 +1293,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) convert(*arguments.front(), *arrayType->baseType()) : *arguments.front(); - m_code << + appendCode() << m_utils.storageArrayPushFunction(*arrayType, &argument.type()) << "(" << IRVariable(_functionCall.expression()).commaSeparatedList() << @@ -1311,7 +1338,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) Whiskers templ("if iszero() { () }\n"); templ("modulus", modulus.name()); templ("panic", m_utils.panicFunction(PanicCode::DivisionByZero)); - m_code << templ.render(); + appendCode() << templ.render(); string args; for (size_t i = 0; i < 2; ++i) @@ -1357,8 +1384,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) &dynamic_cast(*functionType->returnParameterTypes().front()).contractDefinition(); m_context.subObjectsCreated().insert(contract); - Whiskers t(R"( - let := () + Whiskers t(R"(let := () let := add(, datasize("")) if or(gt(, 0xffffffffffffffff), lt(, )) { () } datacopy(, dataoffset(""), datasize("")) @@ -1394,7 +1420,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) t("success", IRNames::trySuccessConditionVariable(_functionCall)); else t("forwardingRevert", m_utils.forwardingRevertFunction()); - m_code << t.render(); + appendCode() << t.render(); break; } @@ -1422,7 +1448,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) templ("success", IRVariable(_functionCall).commaSeparatedList()); templ("isTransfer", functionType->kind() == FunctionType::Kind::Transfer); templ("forwardingRevert", m_utils.forwardingRevertFunction()); - m_code << templ.render(); + appendCode() << templ.render(); break; } @@ -1485,7 +1511,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) templ("gas", "sub(gas(), " + formatNumber(gasNeededByCaller) + ")"); } - m_code << templ.render(); + appendCode() << templ.render(); break; } @@ -1722,7 +1748,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) solAssert(!contractType.isSuper(), ""); ContractDefinition const& contract = contractType.contractDefinition(); m_context.subObjectsCreated().insert(&contract); - m_code << Whiskers(R"( + appendCode() << Whiskers(R"( let := datasize("") let := (add(, 32)) mstore(, ) @@ -1775,7 +1801,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) { pair const& offsets = structType.storageOffsetsOfMember(member); string slot = m_context.newYulVariable(); - m_code << "let " << slot << " := " << + appendCode() << "let " << slot << " := " << ("add(" + expression.part("slot").name() + ", " + offsets.first.str() + ")\n"); setLValue(_memberAccess, IRLValue{ type(_memberAccess), @@ -1786,7 +1812,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) case DataLocation::Memory: { string pos = m_context.newYulVariable(); - m_code << "let " << pos << " := " << + appendCode() << "let " << pos << " := " << ("add(" + expression.part("mpos").name() + ", " + structType.memoryOffsetOfMember(member).str() + ")\n"); setLValue(_memberAccess, IRLValue{ type(_memberAccess), @@ -1798,7 +1824,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) { string baseRef = expression.part("offset").name(); string offset = m_context.newYulVariable(); - m_code << "let " << offset << " := " << "add(" << baseRef << ", " << to_string(structType.calldataOffsetOfMember(member)) << ")\n"; + appendCode() << "let " << offset << " := " << "add(" << baseRef << ", " << to_string(structType.calldataOffsetOfMember(member)) << ")\n"; if (_memberAccess.annotation().type->isDynamicallyEncoded()) define(_memberAccess) << m_utils.accessCalldataTailFunction(*_memberAccess.annotation().type) << @@ -2023,7 +2049,7 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm) solAssert(holds_alternative(modified), ""); // Do not provide dialect so that we get the full type information. - m_code << yul::AsmPrinter()(std::get(modified)) << "\n"; + appendCode() << yul::AsmPrinter()(std::get(modified)) << "\n"; return false; } @@ -2046,7 +2072,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess) templ("indexAccess", m_utils.mappingIndexAccessFunction(mappingType, keyType)); templ("base", IRVariable(_indexAccess.baseExpression()).commaSeparatedList()); templ("key", IRVariable(*_indexAccess.indexExpression()).commaSeparatedList()); - m_code << templ.render(); + appendCode() << templ.render(); setLValue(_indexAccess, IRLValue{ *_indexAccess.annotation().type, IRLValue::Storage{ @@ -2074,7 +2100,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess) string slot = m_context.newYulVariable(); string offset = m_context.newYulVariable(); - m_code << Whiskers(R"( + appendCode() << Whiskers(R"( let , := (, ) )") ("slot", slot) @@ -2141,7 +2167,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess) IRVariable index{m_context.newYulVariable(), *TypeProvider::uint256()}; define(index, *_indexAccess.indexExpression()); - m_code << Whiskers(R"( + appendCode() << Whiskers(R"( if iszero(lt(, )) { () } let := (byte(, )) )") @@ -2307,7 +2333,6 @@ void IRGeneratorForStatements::handleVariableReference( Expression const& _referencingExpression ) { - setLocation(_referencingExpression); if ((_variable.isStateVariable() || _variable.isFileLevelVariable()) && _variable.isConstant()) define(_referencingExpression) << constantValueFunction(_variable) << "()\n"; else if (_variable.isStateVariable() && _variable.immutable()) @@ -2377,11 +2402,10 @@ void IRGeneratorForStatements::appendExternalFunctionCall( // We could also just use MLOAD; POP right before the gas calculation, but the optimizer // would remove that, so we use MSTORE here. if (!funType.gasSet() && returnInfo.estimatedReturnSize > 0) - m_code << "mstore(add(" << m_utils.allocateUnboundedFunction() << "() , " << to_string(returnInfo.estimatedReturnSize) << "), 0)\n"; + appendCode() << "mstore(add(" << m_utils.allocateUnboundedFunction() << "() , " << to_string(returnInfo.estimatedReturnSize) << "), 0)\n"; } - Whiskers templ(R"( - if iszero(extcodesize(
)) { () } + Whiskers templ(R"(if iszero(extcodesize(
)) { () } // storage for arguments and returned data let := () @@ -2474,7 +2498,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall( templ("forwardingRevert", m_utils.forwardingRevertFunction()); - m_code << templ.render(); + appendCode() << templ.render(); } void IRGeneratorForStatements::appendBareCall( @@ -2565,7 +2589,7 @@ void IRGeneratorForStatements::appendBareCall( templ("gas", "sub(gas(), " + formatNumber(gasNeededByCaller) + ")"); } - m_code << templ.render(); + appendCode() << templ.render(); } IRVariable IRGeneratorForStatements::convert(IRVariable const& _from, Type const& _to) @@ -2597,14 +2621,14 @@ std::string IRGeneratorForStatements::expressionAsType(Expression const& _expres std::ostream& IRGeneratorForStatements::define(IRVariable const& _var) { if (_var.type().sizeOnStack() > 0) - m_code << "let " << _var.commaSeparatedList() << " := "; - return m_code; + appendCode() << "let " << _var.commaSeparatedList() << " := "; + return appendCode(false); } void IRGeneratorForStatements::declare(IRVariable const& _var) { if (_var.type().sizeOnStack() > 0) - m_code << "let " << _var.commaSeparatedList() << "\n"; + appendCode() << "let " << _var.commaSeparatedList() << "\n"; } void IRGeneratorForStatements::declareAssign(IRVariable const& _lhs, IRVariable const& _rhs, bool _declare) @@ -2615,15 +2639,15 @@ void IRGeneratorForStatements::declareAssign(IRVariable const& _lhs, IRVariable if (stackItemType) declareAssign(_lhs.part(stackItemName), _rhs.part(stackItemName), _declare); else - m_code << (_declare ? "let ": "") << _lhs.part(stackItemName).name() << " := " << _rhs.part(stackItemName).name() << "\n"; + appendCode() << (_declare ? "let ": "") << _lhs.part(stackItemName).name() << " := " << _rhs.part(stackItemName).name() << "\n"; else { if (_lhs.type().sizeOnStack() > 0) - m_code << + appendCode() << (_declare ? "let ": "") << _lhs.commaSeparatedList() << " := "; - m_code << m_context.utils().conversionFunction(_rhs.type(), _lhs.type()) << + appendCode() << m_context.utils().conversionFunction(_rhs.type(), _lhs.type()) << "(" << _rhs.commaSeparatedList() << ")\n"; @@ -2761,13 +2785,13 @@ void IRGeneratorForStatements::appendAndOrOperatorCode(BinaryOperation const& _b IRVariable value(_binOp); define(value, _binOp.leftExpression()); if (op == Token::Or) - m_code << "if iszero(" << value.name() << ") {\n"; + appendCode() << "if iszero(" << value.name() << ") {\n"; else - m_code << "if " << value.name() << " {\n"; + appendCode() << "if " << value.name() << " {\n"; _binOp.rightExpression().accept(*this); setLocation(_binOp); assign(value, _binOp.rightExpression()); - m_code << "}\n"; + appendCode() << "}\n"; } void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable const& _value) @@ -2783,7 +2807,7 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable [&](string const& _offset) { offsetArgument = ", " + _offset; } }, _storage.offset); - m_code << + appendCode() << m_utils.updateStorageValueFunction(_value.type(), _lvalue.type, offsetStatic) << "(" << _storage.slot << @@ -2801,10 +2825,10 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable if (_memory.byteArrayElement) { solAssert(_lvalue.type == *TypeProvider::byte(), ""); - m_code << "mstore8(" + _memory.address + ", byte(0, " + prepared.commaSeparatedList() + "))\n"; + appendCode() << "mstore8(" + _memory.address + ", byte(0, " + prepared.commaSeparatedList() + "))\n"; } else - m_code << m_utils.writeToMemoryFunction(_lvalue.type) << + appendCode() << m_utils.writeToMemoryFunction(_lvalue.type) << "(" << _memory.address << ", " << @@ -2812,7 +2836,7 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable ")\n"; } else if (auto const* literalType = dynamic_cast(&_value.type())) - m_code << + appendCode() << m_utils.writeToMemoryFunction(*TypeProvider::uint256()) << "(" << _memory.address << @@ -2824,7 +2848,7 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable solAssert(_lvalue.type.sizeOnStack() == 1, ""); auto const* valueReferenceType = dynamic_cast(&_value.type()); solAssert(valueReferenceType && valueReferenceType->dataStoredIn(DataLocation::Memory), ""); - m_code << "mstore(" + _memory.address + ", " + _value.part("mpos").name() + ")\n"; + appendCode() << "mstore(" + _memory.address + ", " + _value.part("mpos").name() + ")\n"; } }, [&](IRLValue::Stack const& _stack) { assign(_stack.variable, _value); }, @@ -2838,7 +2862,7 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable IRVariable prepared(m_context.newYulVariable(), _lvalue.type); define(prepared, _value); - m_code << "mstore(" << to_string(memOffset) << ", " << prepared.commaSeparatedList() << ")\n"; + appendCode() << "mstore(" << to_string(memOffset) << ", " << prepared.commaSeparatedList() << ")\n"; }, [&](IRLValue::Tuple const& _tuple) { auto components = std::move(_tuple.components); @@ -2931,36 +2955,36 @@ void IRGeneratorForStatements::generateLoop( { solAssert(_conditionExpression, "Expected condition for doWhile"); firstRun = m_context.newYulVariable(); - m_code << "let " << firstRun << " := 1\n"; + appendCode() << "let " << firstRun << " := 1\n"; } - m_code << "for {\n"; + appendCode() << "for {\n"; if (_initExpression) _initExpression->accept(*this); - m_code << "} 1 {\n"; + appendCode() << "} 1 {\n"; if (_loopExpression) _loopExpression->accept(*this); - m_code << "}\n"; - m_code << "{\n"; + appendCode() << "}\n"; + appendCode() << "{\n"; if (_conditionExpression) { if (_isDoWhile) - m_code << "if iszero(" << firstRun << ") {\n"; + appendCode() << "if iszero(" << firstRun << ") {\n"; _conditionExpression->accept(*this); - m_code << + appendCode() << "if iszero(" << expressionAsType(*_conditionExpression, *TypeProvider::boolean()) << ") { break }\n"; if (_isDoWhile) - m_code << "}\n" << firstRun << " := 0\n"; + appendCode() << "}\n" << firstRun << " := 0\n"; } _body.accept(*this); - m_code << "}\n"; + appendCode() << "}\n"; } Type const& IRGeneratorForStatements::type(Expression const& _expression) @@ -2975,9 +2999,9 @@ bool IRGeneratorForStatements::visit(TryStatement const& _tryStatement) externalCall.accept(*this); setLocation(_tryStatement); - m_code << "switch iszero(" << IRNames::trySuccessConditionVariable(externalCall) << ")\n"; + appendCode() << "switch iszero(" << IRNames::trySuccessConditionVariable(externalCall) << ")\n"; - m_code << "case 0 { // success case\n"; + appendCode() << "case 0 { // success case\n"; TryCatchClause const& successClause = *_tryStatement.clauses().front(); if (successClause.parameters()) { @@ -2995,32 +3019,34 @@ bool IRGeneratorForStatements::visit(TryStatement const& _tryStatement) successClause.block().accept(*this); setLocation(_tryStatement); - m_code << "}\n"; + appendCode() << "}\n"; - m_code << "default { // failure case\n"; + appendCode() << "default { // failure case\n"; handleCatch(_tryStatement); - m_code << "}\n"; + appendCode() << "}\n"; return false; } void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement) { + setLocation(_tryStatement); string const runFallback = m_context.newYulVariable(); - m_code << "let " << runFallback << " := 1\n"; + appendCode() << "let " << runFallback << " := 1\n"; // This function returns zero on "short returndata". We have to add a success flag // once we implement custom error codes. if (_tryStatement.errorClause() || _tryStatement.panicClause()) - m_code << "switch " << m_utils.returnDataSelectorFunction() << "()\n"; + appendCode() << "switch " << m_utils.returnDataSelectorFunction() << "()\n"; if (TryCatchClause const* errorClause = _tryStatement.errorClause()) { - m_code << "case " << selectorFromSignature32("Error(string)") << " {\n"; + appendCode() << "case " << selectorFromSignature32("Error(string)") << " {\n"; + setLocation(*errorClause); string const dataVariable = m_context.newYulVariable(); - m_code << "let " << dataVariable << " := " << m_utils.tryDecodeErrorMessageFunction() << "()\n"; - m_code << "if " << dataVariable << " {\n"; - m_code << runFallback << " := 0\n"; + appendCode() << "let " << dataVariable << " := " << m_utils.tryDecodeErrorMessageFunction() << "()\n"; + appendCode() << "if " << dataVariable << " {\n"; + appendCode() << runFallback << " := 0\n"; if (errorClause->parameters()) { solAssert(errorClause->parameters()->parameters().size() == 1, ""); @@ -3028,17 +3054,20 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement) define(var) << dataVariable << "\n"; } errorClause->accept(*this); - m_code << "}\n"; - m_code << "}\n"; + setLocation(*errorClause); + appendCode() << "}\n"; + setLocation(_tryStatement); + appendCode() << "}\n"; } if (TryCatchClause const* panicClause = _tryStatement.panicClause()) { - m_code << "case " << selectorFromSignature32("Panic(uint256)") << " {\n"; + appendCode() << "case " << selectorFromSignature32("Panic(uint256)") << " {\n"; + setLocation(*panicClause); string const success = m_context.newYulVariable(); string const code = m_context.newYulVariable(); - m_code << "let " << success << ", " << code << " := " << m_utils.tryDecodePanicDataFunction() << "()\n"; - m_code << "if " << success << " {\n"; - m_code << runFallback << " := 0\n"; + appendCode() << "let " << success << ", " << code << " := " << m_utils.tryDecodePanicDataFunction() << "()\n"; + appendCode() << "if " << success << " {\n"; + appendCode() << runFallback << " := 0\n"; if (panicClause->parameters()) { solAssert(panicClause->parameters()->parameters().size() == 1, ""); @@ -3046,20 +3075,25 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement) define(var) << code << "\n"; } panicClause->accept(*this); - m_code << "}\n"; - m_code << "}\n"; + setLocation(*panicClause); + appendCode() << "}\n"; + setLocation(_tryStatement); + appendCode() << "}\n"; } - m_code << "if " << runFallback << " {\n"; + setLocation(_tryStatement); + appendCode() << "if " << runFallback << " {\n"; if (_tryStatement.fallbackClause()) handleCatchFallback(*_tryStatement.fallbackClause()); else - m_code << m_utils.forwardingRevertFunction() << "()\n"; - m_code << "}\n"; + appendCode() << m_utils.forwardingRevertFunction() << "()\n"; + setLocation(_tryStatement); + appendCode() << "}\n"; } void IRGeneratorForStatements::handleCatchFallback(TryCatchClause const& _fallback) { + setLocation(_fallback); if (_fallback.parameters()) { solAssert(m_context.evmVersion().supportsReturndata(), ""); @@ -3104,7 +3138,7 @@ void IRGeneratorForStatements::revertWithError( templ("argumentVars", joinHumanReadablePrefixed(errorArgumentVars)); templ("encode", m_context.abiFunctions().tupleEncoder(errorArgumentTypes, _parameterTypes)); - m_code << templ.render(); + appendCode() << templ.render(); } @@ -3114,11 +3148,6 @@ bool IRGeneratorForStatements::visit(TryCatchClause const& _clause) return false; } -void IRGeneratorForStatements::setLocation(ASTNode const& _node) -{ - m_currentLocation = _node.location(); -} - string IRGeneratorForStatements::linkerSymbol(ContractDefinition const& _library) const { solAssert(_library.isLibrary(), ""); diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.h b/libsolidity/codegen/ir/IRGeneratorForStatements.h index f8a581b5f..75baaaf4f 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.h +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.h @@ -33,11 +33,33 @@ namespace solidity::frontend class IRGenerationContext; class YulUtilFunctions; +/** + * Base class for the statement generator. + * Encapsulates access to the yul code stream and handles source code locations. + */ +class IRGeneratorForStatementsBase: public ASTConstVisitor +{ +public: + IRGeneratorForStatementsBase(IRGenerationContext& _context): + m_context(_context) + {} + + virtual std::string code() const; + std::ostringstream& appendCode(bool _addLocationComment = true); +protected: + void setLocation(ASTNode const& _node); + langutil::SourceLocation m_currentLocation = {}; + langutil::SourceLocation m_lastLocation = {}; + IRGenerationContext& m_context; +private: + std::ostringstream m_code; +}; + /** * Component that translates Solidity's AST into Yul at statement level and below. * It is an AST visitor that appends to an internal string buffer. */ -class IRGeneratorForStatements: public ASTConstVisitor +class IRGeneratorForStatements: public IRGeneratorForStatementsBase { public: IRGeneratorForStatements( @@ -45,12 +67,12 @@ public: YulUtilFunctions& _utils, std::function _placeholderCallback = {} ): - m_context(_context), + IRGeneratorForStatementsBase(_context), m_placeholderCallback(std::move(_placeholderCallback)), m_utils(_utils) {} - std::string code() const; + std::string code() const override; /// Generate the code for the statements in the block; void generate(Block const& _block); @@ -190,16 +212,11 @@ private: static Type const& type(Expression const& _expression); - void setLocation(ASTNode const& _node); - std::string linkerSymbol(ContractDefinition const& _library) const; - std::ostringstream m_code; - IRGenerationContext& m_context; std::function m_placeholderCallback; YulUtilFunctions& m_utils; std::optional m_currentLValue; - langutil::SourceLocation m_currentLocation; }; } diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index ab7e6e501..dcc07e1f5 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1350,7 +1350,7 @@ void CompilerStack::generateIR(ContractDefinition const& _contract) for (auto const& pair: m_contracts) otherYulSources.emplace(pair.second.contract, pair.second.yulIR); - IRGenerator generator(m_evmVersion, m_revertStrings, m_optimiserSettings); + IRGenerator generator(m_evmVersion, m_revertStrings, m_optimiserSettings, sourceIndices()); tie(compiledContract.yulIR, compiledContract.yulIROptimized) = generator.run( _contract, createCBORMetadata(compiledContract), diff --git a/test/cmdlineTests/constant_optimizer_yul/output b/test/cmdlineTests/constant_optimizer_yul/output index 05ff4bea3..9ef151e3b 100644 --- a/test/cmdlineTests/constant_optimizer_yul/output +++ b/test/cmdlineTests/constant_optimizer_yul/output @@ -1,10 +1,10 @@ Optimized IR: -/******************************************************* +/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object "C_12" { code { diff --git a/test/cmdlineTests/exp_base_literal/output b/test/cmdlineTests/exp_base_literal/output index 17f3670ef..93fd7488d 100644 --- a/test/cmdlineTests/exp_base_literal/output +++ b/test/cmdlineTests/exp_base_literal/output @@ -1,14 +1,15 @@ IR: -/******************************************************* +/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object "C_81" { code { + /// @src 0:82,370 mstore(64, 128) if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } @@ -25,6 +26,8 @@ object "C_81" { function constructor_C_81() { + /// @src 0:82,370 + } function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { @@ -34,6 +37,7 @@ object "C_81" { } object "C_81_deployed" { code { + /// @src 0:82,370 mstore(64, 128) if iszero(lt(calldatasize(), 4)) @@ -208,78 +212,126 @@ object "C_81" { } function fun_f_80(var_a_4, var_b_6, var_c_8, var_d_10) -> var__13, var__15, var__17, var__19 { + /// @src 0:96,368 + /// @src 0:160,164 let zero_t_uint256_1 := zero_value_for_split_t_uint256() var__13 := zero_t_uint256_1 + /// @src 0:166,169 let zero_t_int256_2 := zero_value_for_split_t_int256() var__15 := zero_t_int256_2 + /// @src 0:171,175 let zero_t_uint256_3 := zero_value_for_split_t_uint256() var__17 := zero_t_uint256_3 + /// @src 0:177,181 let zero_t_uint256_4 := zero_value_for_split_t_uint256() var__19 := zero_t_uint256_4 + /// @src 0:196,197 let expr_23 := 0x02 + /// @src 0:199,200 let _5 := var_a_4 let expr_24 := _5 + /// @src 0:196,200 let _6 := convert_t_rational_2_by_1_to_t_uint256(expr_23) let expr_25 := checked_exp_t_rational_2_by_1_t_uint256(expr_24) + /// @src 0:187,200 let var_w_22 := expr_25 + /// @src 0:214,215 let expr_29 := 0x02 + /// @src 0:213,215 let expr_30 := 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe + /// @src 0:212,216 let expr_31 := expr_30 + /// @src 0:218,219 let _7 := var_b_6 let expr_32 := _7 + /// @src 0:212,219 let _8 := convert_t_rational_minus_2_by_1_to_t_int256(expr_31) let expr_33 := checked_exp_t_rational_minus_2_by_1_t_uint256(expr_32) + /// @src 0:204,219 let var_x_28 := expr_33 + /// @src 0:232,234 let expr_37 := 0x0a + /// @src 0:236,237 let _9 := var_c_8 let expr_38 := _9 + /// @src 0:232,237 let _10 := convert_t_rational_10_by_1_to_t_uint256(expr_37) let expr_39 := checked_exp_t_rational_10_by_1_t_uint256(expr_38) + /// @src 0:223,237 let var_y_36 := expr_39 + /// @src 0:251,260 let expr_47 := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + /// @src 0:250,262 let expr_48 := expr_47 + /// @src 0:264,265 let _11 := var_d_10 let expr_49 := _11 + /// @src 0:250,265 let _12 := convert_t_rational_115792089237316195423570985008687907853269984665640564039457584007913129639935_by_1_to_t_uint256(expr_48) let expr_50 := checked_exp_t_rational_115792089237316195423570985008687907853269984665640564039457584007913129639935_by_1_t_uint256(expr_49) + /// @src 0:241,265 let var_z_42 := expr_50 + /// @src 0:308,309 let expr_53 := 0x00 + /// @src 0:307,310 let expr_54 := expr_53 + /// @src 0:312,313 let _13 := var_a_4 let expr_55 := _13 + /// @src 0:307,313 let _14 := convert_t_rational_0_by_1_to_t_uint256(expr_54) let expr_56 := checked_exp_t_rational_0_by_1_t_uint256(expr_55) + /// @src 0:303,313 var_w_22 := expr_56 let expr_57 := expr_56 + /// @src 0:323,324 let expr_60 := 0x01 + /// @src 0:322,324 let expr_61 := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + /// @src 0:321,325 let expr_62 := expr_61 + /// @src 0:327,328 let _15 := var_b_6 let expr_63 := _15 + /// @src 0:321,328 let _16 := convert_t_rational_minus_1_by_1_to_t_int256(expr_62) let expr_64 := checked_exp_t_rational_minus_1_by_1_t_uint256(expr_63) + /// @src 0:317,328 var_x_28 := expr_64 let expr_65 := expr_64 + /// @src 0:336,337 let expr_68 := 0x01 + /// @src 0:339,340 let _17 := var_c_8 let expr_69 := _17 + /// @src 0:336,340 let _18 := convert_t_rational_1_by_1_to_t_uint256(expr_68) let expr_70 := checked_exp_t_rational_1_by_1_t_uint256(expr_69) + /// @src 0:332,340 var_y_36 := expr_70 let expr_71 := expr_70 + /// @src 0:353,354 let _19 := var_w_22 let expr_73 := _19 + /// @src 0:352,364 let expr_77_component_1 := expr_73 + /// @src 0:356,357 let _20 := var_x_28 let expr_74 := _20 + /// @src 0:352,364 let expr_77_component_2 := expr_74 + /// @src 0:359,360 let _21 := var_y_36 let expr_75 := _21 + /// @src 0:352,364 let expr_77_component_3 := expr_75 + /// @src 0:362,363 let _22 := var_z_42 let expr_76 := _22 + /// @src 0:352,364 let expr_77_component_4 := expr_76 + /// @src 0:345,364 var__13 := expr_77_component_1 var__15 := expr_77_component_2 var__17 := expr_77_component_3 diff --git a/test/cmdlineTests/ir_compiler_inheritance_nosubobjects/output b/test/cmdlineTests/ir_compiler_inheritance_nosubobjects/output index 496e9de16..ad951774e 100644 --- a/test/cmdlineTests/ir_compiler_inheritance_nosubobjects/output +++ b/test/cmdlineTests/ir_compiler_inheritance_nosubobjects/output @@ -1,10 +1,10 @@ Optimized IR: -/******************************************************* +/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object "C_7" { code { @@ -28,12 +28,12 @@ object "C_7" { } Optimized IR: -/******************************************************* +/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object "D_10" { code { diff --git a/test/cmdlineTests/ir_compiler_subobjects/output b/test/cmdlineTests/ir_compiler_subobjects/output index 2cbfee997..c10198bbb 100644 --- a/test/cmdlineTests/ir_compiler_subobjects/output +++ b/test/cmdlineTests/ir_compiler_subobjects/output @@ -1,10 +1,10 @@ Optimized IR: -/******************************************************* +/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object "C_3" { code { @@ -28,12 +28,12 @@ object "C_3" { } Optimized IR: -/******************************************************* +/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object "D_16" { code { diff --git a/test/cmdlineTests/ir_with_assembly_no_memoryguard_creation/output b/test/cmdlineTests/ir_with_assembly_no_memoryguard_creation/output index 254b355e3..4efea77ce 100644 --- a/test/cmdlineTests/ir_with_assembly_no_memoryguard_creation/output +++ b/test/cmdlineTests/ir_with_assembly_no_memoryguard_creation/output @@ -1,10 +1,10 @@ Optimized IR: -/******************************************************* +/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object "D_12" { code { diff --git a/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/output b/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/output index 7ce79e765..9b39c93e6 100644 --- a/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/output +++ b/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/output @@ -1,10 +1,10 @@ Optimized IR: -/******************************************************* +/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object "D_8" { code { diff --git a/test/cmdlineTests/keccak_optimization_deploy_code/output b/test/cmdlineTests/keccak_optimization_deploy_code/output index 99eac4c53..907b08b70 100644 --- a/test/cmdlineTests/keccak_optimization_deploy_code/output +++ b/test/cmdlineTests/keccak_optimization_deploy_code/output @@ -1,10 +1,10 @@ Optimized IR: -/******************************************************* +/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object "C_12" { code { diff --git a/test/cmdlineTests/keccak_optimization_low_runs/output b/test/cmdlineTests/keccak_optimization_low_runs/output index 5644a1388..99af8c821 100644 --- a/test/cmdlineTests/keccak_optimization_low_runs/output +++ b/test/cmdlineTests/keccak_optimization_low_runs/output @@ -1,10 +1,10 @@ Optimized IR: -/******************************************************* +/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object "C_7" { code { diff --git a/test/cmdlineTests/name_simplifier/output b/test/cmdlineTests/name_simplifier/output index 255f781b0..d8e7d4f7c 100644 --- a/test/cmdlineTests/name_simplifier/output +++ b/test/cmdlineTests/name_simplifier/output @@ -1,10 +1,10 @@ Optimized IR: -/******************************************************* +/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object "C_59" { code { diff --git a/test/cmdlineTests/optimizer_array_sload/output b/test/cmdlineTests/optimizer_array_sload/output index 5cfd79d9e..c80e9df87 100644 --- a/test/cmdlineTests/optimizer_array_sload/output +++ b/test/cmdlineTests/optimizer_array_sload/output @@ -1,10 +1,10 @@ Optimized IR: -/******************************************************* +/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object "Arraysum_34" { code { diff --git a/test/cmdlineTests/revert_strings/output b/test/cmdlineTests/revert_strings/output index 8a80f1d56..5ce644d53 100644 --- a/test/cmdlineTests/revert_strings/output +++ b/test/cmdlineTests/revert_strings/output @@ -1,14 +1,15 @@ IR: -/******************************************************* +/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object "C_15" { code { + /// @src 0:59,147 mstore(64, 128) if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } @@ -25,6 +26,8 @@ object "C_15" { function constructor_C_15() { + /// @src 0:59,147 + } function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { @@ -49,6 +52,7 @@ object "C_15" { } object "C_15_deployed" { code { + /// @src 0:59,147 mstore(64, 128) if iszero(lt(calldatasize(), 4)) @@ -213,6 +217,7 @@ object "C_15" { } function fun_f_14(var__7_mpos, var_e_10) { + /// @src 0:93,145 } diff --git a/test/cmdlineTests/standard_irOptimized_requested/output.json b/test/cmdlineTests/standard_irOptimized_requested/output.json index 438793053..73e9653d2 100644 --- a/test/cmdlineTests/standard_irOptimized_requested/output.json +++ b/test/cmdlineTests/standard_irOptimized_requested/output.json @@ -1,9 +1,9 @@ -{"contracts":{"A":{"C":{"irOptimized":"/******************************************************* +{"contracts":{"A":{"C":{"irOptimized":"/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object \"C_7\" { code { diff --git a/test/cmdlineTests/standard_ir_requested/output.json b/test/cmdlineTests/standard_ir_requested/output.json index bc5afb411..0d61f8cca 100644 --- a/test/cmdlineTests/standard_ir_requested/output.json +++ b/test/cmdlineTests/standard_ir_requested/output.json @@ -1,13 +1,14 @@ -{"contracts":{"A":{"C":{"ir":"/******************************************************* +{"contracts":{"A":{"C":{"ir":"/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object \"C_7\" { code { + /// @src 0:79,121 mstore(64, 128) if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } @@ -24,6 +25,8 @@ object \"C_7\" { function constructor_C_7() { + /// @src 0:79,121 + } function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { @@ -33,6 +36,7 @@ object \"C_7\" { } object \"C_7_deployed\" { code { + /// @src 0:79,121 mstore(64, 128) if iszero(lt(calldatasize(), 4)) @@ -72,6 +76,7 @@ object \"C_7\" { } function fun_f_6() { + /// @src 0:92,119 } diff --git a/test/cmdlineTests/standard_viair_requested/output.json b/test/cmdlineTests/standard_viair_requested/output.json index ca317a29b..4f2399134 100644 --- a/test/cmdlineTests/standard_viair_requested/output.json +++ b/test/cmdlineTests/standard_viair_requested/output.json @@ -1,13 +1,14 @@ -{"contracts":{"A":{"C":{"evm":{"bytecode":{"generatedSources":[],"object":""},"deployedBytecode":{"object":""}},"ir":"/******************************************************* +{"contracts":{"A":{"C":{"evm":{"bytecode":{"generatedSources":[],"object":""},"deployedBytecode":{"object":""}},"ir":"/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object \"C_3\" { code { + /// @src 0:79,92 mstore(64, 128) if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } @@ -24,6 +25,8 @@ object \"C_3\" { function constructor_C_3() { + /// @src 0:79,92 + } function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { @@ -33,6 +36,7 @@ object \"C_3\" { } object \"C_3_deployed\" { code { + /// @src 0:79,92 mstore(64, 128) if iszero(lt(calldatasize(), 4)) @@ -67,16 +71,17 @@ object \"C_3\" { } -"},"D":{"evm":{"bytecode":{"generatedSources":[],"object":""},"deployedBytecode":{"object":""}},"ir":"/******************************************************* +"},"D":{"evm":{"bytecode":{"generatedSources":[],"object":""},"deployedBytecode":{"object":""}},"ir":"/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object \"D_16\" { code { + /// @src 0:93,146 mstore(64, 128) if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } @@ -93,6 +98,8 @@ object \"D_16\" { function constructor_D_16() { + /// @src 0:93,146 + } function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { @@ -102,6 +109,7 @@ object \"D_16\" { } object \"D_16_deployed\" { code { + /// @src 0:93,146 mstore(64, 128) if iszero(lt(calldatasize(), 4)) @@ -141,7 +149,9 @@ object \"D_16\" { } function fun_f_15() { + /// @src 0:106,144 + /// @src 0:134,141 let _1 := allocate_unbounded() let _2 := add(_1, datasize(\"C_3\")) if or(gt(_2, 0xffffffffffffffff), lt(_2, _1)) { panic_error_0x41() } @@ -152,6 +162,7 @@ object \"D_16\" { if iszero(expr_12_address) { revert_forward_1() } + /// @src 0:128,141 let var_c_8_address := expr_12_address } @@ -188,15 +199,16 @@ object \"D_16\" { } } - /******************************************************* + /*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object \"C_3\" { code { + /// @src 0:79,92 mstore(64, 128) if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } @@ -213,6 +225,8 @@ object \"D_16\" { function constructor_C_3() { + /// @src 0:79,92 + } function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { @@ -222,6 +236,7 @@ object \"D_16\" { } object \"C_3_deployed\" { code { + /// @src 0:79,92 mstore(64, 128) if iszero(lt(calldatasize(), 4)) diff --git a/test/cmdlineTests/viair_abicoder_v1/output b/test/cmdlineTests/viair_abicoder_v1/output index c001c8bfe..d16d77f2d 100644 --- a/test/cmdlineTests/viair_abicoder_v1/output +++ b/test/cmdlineTests/viair_abicoder_v1/output @@ -1,14 +1,15 @@ IR: -/******************************************************* +/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object "test_11" { code { + /// @src 0:79,169 mstore(64, 128) if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } @@ -25,6 +26,8 @@ object "test_11" { function constructor_test_11() { + /// @src 0:79,169 + } function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { @@ -34,6 +37,7 @@ object "test_11" { } object "test_11_deployed" { code { + /// @src 0:79,169 mstore(64, 128) if iszero(lt(calldatasize(), 4)) @@ -83,10 +87,14 @@ object "test_11" { } function fun_f_10() -> var__5 { + /// @src 0:99,167 + /// @src 0:133,137 let zero_t_bool_1 := zero_value_for_split_t_bool() var__5 := zero_t_bool_1 + /// @src 0:156,160 let expr_7 := 0x01 + /// @src 0:149,160 var__5 := expr_7 leave diff --git a/test/cmdlineTests/viair_subobjects/output b/test/cmdlineTests/viair_subobjects/output index e025a6a83..cf52c5e97 100644 --- a/test/cmdlineTests/viair_subobjects/output +++ b/test/cmdlineTests/viair_subobjects/output @@ -5,12 +5,12 @@ Binary: Binary of the runtime part: Optimized IR: -/******************************************************* +/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object "C_3" { code { @@ -40,12 +40,12 @@ Binary: Binary of the runtime part: Optimized IR: -/******************************************************* +/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object "D_16" { code { diff --git a/test/cmdlineTests/yul_optimizer_steps/output b/test/cmdlineTests/yul_optimizer_steps/output index 10981782f..6f42b4761 100644 --- a/test/cmdlineTests/yul_optimizer_steps/output +++ b/test/cmdlineTests/yul_optimizer_steps/output @@ -1,10 +1,10 @@ Optimized IR: -/******************************************************* +/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object "C_7" { code { diff --git a/test/cmdlineTests/yul_source_locations/input.json b/test/cmdlineTests/yul_source_locations/input.json new file mode 100644 index 000000000..ce5c4b626 --- /dev/null +++ b/test/cmdlineTests/yul_source_locations/input.json @@ -0,0 +1,21 @@ +{ + "language": "Solidity", + "sources": + { + "C": + { + "content": "//SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\npragma abicoder v2;\n\ncontract C\n{\n int constant constVar = 41;\n int immutable immutVar = 42;\n int public stateVar;\n\n constructor(int _init)\n {\n stateVar = _init;\n }\n\n function f() external pure returns (int)\n {\n return constVar + immutVar;\n }\n modifier m()\n {\n stateVar++;\n _;\n }\n function f2() m public returns (int)\n {\n return stateVar + this.f() + immutVar;\n }\n}\n" + }, + "D": + { + "content": "//SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\npragma abicoder v2;\nimport \"C\";\n\ncontract D is C(3)\n{\n constructor(int _init2)\n {\n stateVar += _init2;\n }\n}\n" + } + }, + "settings": + { + "outputSelection": + { + "*": { "*": ["ir"] } + } + } +} diff --git a/test/cmdlineTests/yul_source_locations/output.json b/test/cmdlineTests/yul_source_locations/output.json new file mode 100644 index 000000000..19f8b3714 --- /dev/null +++ b/test/cmdlineTests/yul_source_locations/output.json @@ -0,0 +1,1120 @@ +{"contracts":{"C":{"C":{"ir":"/*=====================================================* + * WARNING * + * Solidity to Yul compilation is still EXPERIMENTAL * + * It can result in LOSS OF FUNDS or worse * + * !USE AT YOUR OWN RISK! * + *=====================================================*/ + + +object \"C_54\" { + code { + /// @src 0:79,428 + mstore(64, 160) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + let _1 := copy_arguments_for_constructor_20_object_C_54() + constructor_C_54(_1) + + let _2 := allocate_unbounded() + codecopy(_2, dataoffset(\"C_54_deployed\"), datasize(\"C_54_deployed\")) + + setimmutable(_2, \"8\", mload(128)) + + return(_2, datasize(\"C_54_deployed\")) + + function abi_decode_t_int256_fromMemory(offset, end) -> value { + value := mload(offset) + validator_revert_t_int256(value) + } + + function abi_decode_tuple_t_int256_fromMemory(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_int256_fromMemory(add(headStart, offset), dataEnd) + } + + } + + function allocate_memory(size) -> memPtr { + memPtr := allocate_unbounded() + finalize_allocation(memPtr, size) + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function cleanup_t_int256(value) -> cleaned { + cleaned := value + } + + function constructor_C_54(var__init_12) { + + /// @src 0:175,223 + + /// @src 0:147,149 + let expr_7 := 0x2a + let _3 := convert_t_rational_42_by_1_to_t_int256(expr_7) + mstore(128, _3) + + /// @src 0:214,219 + let _4 := var__init_12 + let expr_16 := _4 + /// @src 0:203,219 + update_storage_value_offset_0t_int256_to_t_int256(0x00, expr_16) + let expr_17 := expr_16 + + } + + function convert_t_int256_to_t_int256(value) -> converted { + converted := cleanup_t_int256(value) + } + + function convert_t_rational_42_by_1_to_t_int256(value) -> converted { + converted := cleanup_t_int256(value) + } + + function copy_arguments_for_constructor_20_object_C_54() -> ret_param_0 { + let programSize := datasize(\"C_54\") + let argSize := sub(codesize(), programSize) + + let memoryDataOffset := allocate_memory(argSize) + codecopy(memoryDataOffset, programSize, argSize) + + ret_param_0 := abi_decode_tuple_t_int256_fromMemory(memoryDataOffset, add(memoryDataOffset, argSize)) + } + + function finalize_allocation(memPtr, size) { + let newFreePtr := add(memPtr, round_up_to_mul_of_32(size)) + // protect against overflow + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() } + mstore(64, newFreePtr) + } + + function panic_error_0x41() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x41) + revert(0, 0x24) + } + + function prepare_store_t_int256(value) -> ret { + ret := value + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function round_up_to_mul_of_32(value) -> result { + result := and(add(value, 31), not(31)) + } + + function shift_left_0(value) -> newValue { + newValue := + + shl(0, value) + + } + + function update_byte_slice_32_shift_0(value, toInsert) -> result { + let mask := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + toInsert := shift_left_0(toInsert) + value := and(value, not(mask)) + result := or(value, and(toInsert, mask)) + } + + function update_storage_value_offset_0t_int256_to_t_int256(slot, value_0) { + let convertedValue_0 := convert_t_int256_to_t_int256(value_0) + sstore(slot, update_byte_slice_32_shift_0(sload(slot), prepare_store_t_int256(convertedValue_0))) + } + + function validator_revert_t_int256(value) { + if iszero(eq(value, cleanup_t_int256(value))) { revert(0, 0) } + } + + } + object \"C_54_deployed\" { + code { + /// @src 0:79,428 + mstore(64, 128) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x26121ff0 + { + // f() + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := fun_f_30() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + } + + case 0x793816ec + { + // stateVar() + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := getter_fun_stateVar_10() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + } + + case 0x9942ec6f + { + // f2() + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := fun_f2_53() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + } + + default {} + } + if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function abi_decode_t_int256_fromMemory(offset, end) -> value { + value := mload(offset) + validator_revert_t_int256(value) + } + + function abi_decode_tuple_(headStart, dataEnd) { + if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + } + + function abi_decode_tuple_t_int256_fromMemory(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_int256_fromMemory(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_t_int256_to_t_int256_fromStack(value, pos) { + mstore(pos, cleanup_t_int256(value)) + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function abi_encode_tuple_t_int256__to_t_int256__fromStack(headStart , value0) -> tail { + tail := add(headStart, 32) + + abi_encode_t_int256_to_t_int256_fromStack(value0, add(headStart, 0)) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function checked_add_t_int256(x, y) -> sum { + x := cleanup_t_int256(x) + y := cleanup_t_int256(y) + + // overflow, if x >= 0 and y > (maxValue - x) + if and(iszero(slt(x, 0)), sgt(y, sub(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, x))) { panic_error_0x11() } + // underflow, if x < 0 and y < (minValue - x) + if and(slt(x, 0), slt(y, sub(0x8000000000000000000000000000000000000000000000000000000000000000, x))) { panic_error_0x11() } + + sum := add(x, y) + } + + function cleanup_from_storage_t_int256(value) -> cleaned { + cleaned := value + } + + function cleanup_t_int256(value) -> cleaned { + cleaned := value + } + + function cleanup_t_uint160(value) -> cleaned { + cleaned := and(value, 0xffffffffffffffffffffffffffffffffffffffff) + } + + /// @src 0:93,119 + function constant_constVar_5() -> ret { + /// @src 0:117,119 + let expr_4 := 0x29 + let _2 := convert_t_rational_41_by_1_to_t_int256(expr_4) + + ret := _2 + } + + function convert_t_contract$_C_$54_to_t_address(value) -> converted { + converted := convert_t_contract$_C_$54_to_t_uint160(value) + } + + function convert_t_contract$_C_$54_to_t_uint160(value) -> converted { + converted := cleanup_t_uint160(value) + } + + function convert_t_int256_to_t_int256(value) -> converted { + converted := cleanup_t_int256(value) + } + + function convert_t_rational_41_by_1_to_t_int256(value) -> converted { + converted := cleanup_t_int256(value) + } + + function extract_from_storage_value_dynamict_int256(slot_value, offset) -> value { + value := cleanup_from_storage_t_int256(shift_right_unsigned_dynamic(mul(offset, 8), slot_value)) + } + + function extract_from_storage_value_offset_0t_int256(slot_value) -> value { + value := cleanup_from_storage_t_int256(shift_right_0_unsigned(slot_value)) + } + + function finalize_allocation(memPtr, size) { + let newFreePtr := add(memPtr, round_up_to_mul_of_32(size)) + // protect against overflow + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() } + mstore(64, newFreePtr) + } + + function fun_f2_53() -> var__42 { + /// @src 0:343,426 + /// @src 0:375,378 + let zero_t_int256_4 := zero_value_for_split_t_int256() + var__42 := zero_t_int256_4 + + var__42 := modifier_m_40(var__42) + } + + function fun_f2_53_inner(_8) -> var__42 { + /// @src 0:343,426 + var__42 := _8 + + /// @src 0:392,400 + let _9 := read_from_storage_split_offset_0_t_int256(0x00) + let expr_44 := _9 + /// @src 0:403,407 + let expr_45_address := address() + /// @src 0:403,409 + let expr_46_address := convert_t_contract$_C_$54_to_t_address(expr_45_address) + let expr_46_functionSelector := 0x26121ff0 + /// @src 0:403,411 + if iszero(extcodesize(expr_46_address)) { revert_error_0cc013b6b3b6beabea4e3a74a6d380f0df81852ca99887912475e1f66b2a2c20() } + + // storage for arguments and returned data + let _10 := allocate_unbounded() + mstore(_10, shift_left_224(expr_46_functionSelector)) + let _11 := abi_encode_tuple__to__fromStack(add(_10, 4) ) + + let _12 := staticcall(gas(), expr_46_address, _10, sub(_11, _10), _10, 32) + + if iszero(_12) { revert_forward_1() } + + let expr_47 + if _12 { + + // update freeMemoryPointer according to dynamic return size + finalize_allocation(_10, returndatasize()) + + // decode return parameters from external try-call into retVars + expr_47 := abi_decode_tuple_t_int256_fromMemory(_10, add(_10, returndatasize())) + } + /// @src 0:392,411 + let expr_48 := checked_add_t_int256(expr_44, expr_47) + + /// @src 0:414,422 + let _13 := loadimmutable(\"8\") + let expr_49 := _13 + /// @src 0:392,422 + let expr_50 := checked_add_t_int256(expr_48, expr_49) + + /// @src 0:385,422 + var__42 := expr_50 + leave + + } + + function fun_f_30() -> var__23 { + /// @src 0:226,302 + /// @src 0:262,265 + let zero_t_int256_1 := zero_value_for_split_t_int256() + var__23 := zero_t_int256_1 + + /// @src 0:279,287 + let expr_25 := constant_constVar_5() + /// @src 0:290,298 + let _3 := loadimmutable(\"8\") + let expr_26 := _3 + /// @src 0:279,298 + let expr_27 := checked_add_t_int256(expr_25, expr_26) + + /// @src 0:272,298 + var__23 := expr_27 + leave + + } + + function getter_fun_stateVar_10() -> ret { + /// @src 0:152,171 + + let slot := 0 + let offset := 0 + + ret := read_from_storage_split_dynamic_t_int256(slot, offset) + + } + + function increment_t_int256(value) -> ret { + value := cleanup_t_int256(value) + if eq(value, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) { panic_error_0x11() } + ret := add(value, 1) + } + + function modifier_m_40(var__42) -> _5 { + /// @src 0:304,341 + _5 := var__42 + + /// @src 0:322,332 + let _7 := read_from_storage_split_offset_0_t_int256(0x00) + let _6 := increment_t_int256(_7) + update_storage_value_offset_0t_int256_to_t_int256(0x00, _6) + let expr_33 := _7 + /// @src 0:336,337 + _5 := fun_f2_53_inner(var__42) + + } + + function panic_error_0x11() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x11) + revert(0, 0x24) + } + + function panic_error_0x41() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x41) + revert(0, 0x24) + } + + function prepare_store_t_int256(value) -> ret { + ret := value + } + + function read_from_storage_split_dynamic_t_int256(slot, offset) -> value { + value := extract_from_storage_value_dynamict_int256(sload(slot), offset) + + } + + function read_from_storage_split_offset_0_t_int256(slot) -> value { + value := extract_from_storage_value_offset_0t_int256(sload(slot)) + + } + + function revert_error_0cc013b6b3b6beabea4e3a74a6d380f0df81852ca99887912475e1f66b2a2c20() { + revert(0, 0) + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_forward_1() { + let pos := allocate_unbounded() + returndatacopy(pos, 0, returndatasize()) + revert(pos, returndatasize()) + } + + function round_up_to_mul_of_32(value) -> result { + result := and(add(value, 31), not(31)) + } + + function shift_left_0(value) -> newValue { + newValue := + + shl(0, value) + + } + + function shift_left_224(value) -> newValue { + newValue := + + shl(224, value) + + } + + function shift_right_0_unsigned(value) -> newValue { + newValue := + + shr(0, value) + + } + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function shift_right_unsigned_dynamic(bits, value) -> newValue { + newValue := + + shr(bits, value) + + } + + function update_byte_slice_32_shift_0(value, toInsert) -> result { + let mask := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + toInsert := shift_left_0(toInsert) + value := and(value, not(mask)) + result := or(value, and(toInsert, mask)) + } + + function update_storage_value_offset_0t_int256_to_t_int256(slot, value_0) { + let convertedValue_0 := convert_t_int256_to_t_int256(value_0) + sstore(slot, update_byte_slice_32_shift_0(sload(slot), prepare_store_t_int256(convertedValue_0))) + } + + function validator_revert_t_int256(value) { + if iszero(eq(value, cleanup_t_int256(value))) { revert(0, 0) } + } + + function zero_value_for_split_t_int256() -> ret { + ret := 0 + } + + } + + data \".metadata\" hex\"\" + } + +} + +"}},"D":{"D":{"ir":"/*=====================================================* + * WARNING * + * Solidity to Yul compilation is still EXPERIMENTAL * + * It can result in LOSS OF FUNDS or worse * + * !USE AT YOUR OWN RISK! * + *=====================================================*/ + + +object \"D_72\" { + code { + /// @src 1:91,166 + mstore(64, 160) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + let _1 := copy_arguments_for_constructor_71_object_D_72() + constructor_D_72(_1) + + let _2 := allocate_unbounded() + codecopy(_2, dataoffset(\"D_72_deployed\"), datasize(\"D_72_deployed\")) + + setimmutable(_2, \"8\", mload(128)) + + return(_2, datasize(\"D_72_deployed\")) + + function abi_decode_t_int256_fromMemory(offset, end) -> value { + value := mload(offset) + validator_revert_t_int256(value) + } + + function abi_decode_tuple_t_int256_fromMemory(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_int256_fromMemory(add(headStart, offset), dataEnd) + } + + } + + function allocate_memory(size) -> memPtr { + memPtr := allocate_unbounded() + finalize_allocation(memPtr, size) + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function checked_add_t_int256(x, y) -> sum { + x := cleanup_t_int256(x) + y := cleanup_t_int256(y) + + // overflow, if x >= 0 and y > (maxValue - x) + if and(iszero(slt(x, 0)), sgt(y, sub(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, x))) { panic_error_0x11() } + // underflow, if x < 0 and y < (minValue - x) + if and(slt(x, 0), slt(y, sub(0x8000000000000000000000000000000000000000000000000000000000000000, x))) { panic_error_0x11() } + + sum := add(x, y) + } + + function cleanup_from_storage_t_int256(value) -> cleaned { + cleaned := value + } + + function cleanup_t_int256(value) -> cleaned { + cleaned := value + } + + function constructor_C_54(var__init_12) { + + /// @src 0:175,223 + + /// @src 0:147,149 + let expr_7 := 0x2a + let _6 := convert_t_rational_42_by_1_to_t_int256(expr_7) + mstore(128, _6) + + /// @src 0:214,219 + let _7 := var__init_12 + let expr_16 := _7 + /// @src 0:203,219 + update_storage_value_offset_0t_int256_to_t_int256(0x00, expr_16) + let expr_17 := expr_16 + + } + + function constructor_D_72(var__init2_63) { + /// @src 1:107,108 + let expr_60 := 0x03 + let _3 := convert_t_rational_3_by_1_to_t_int256(expr_60) + + /// @src 1:113,164 + constructor_C_54(_3) + + /// @src 1:154,160 + let _4 := var__init2_63 + let expr_67 := _4 + /// @src 1:142,160 + let _5 := read_from_storage_split_offset_0_t_int256(0x00) + let expr_68 := checked_add_t_int256(_5, expr_67) + + update_storage_value_offset_0t_int256_to_t_int256(0x00, expr_68) + + } + + function convert_t_int256_to_t_int256(value) -> converted { + converted := cleanup_t_int256(value) + } + + function convert_t_rational_3_by_1_to_t_int256(value) -> converted { + converted := cleanup_t_int256(value) + } + + function convert_t_rational_42_by_1_to_t_int256(value) -> converted { + converted := cleanup_t_int256(value) + } + + function copy_arguments_for_constructor_71_object_D_72() -> ret_param_0 { + let programSize := datasize(\"D_72\") + let argSize := sub(codesize(), programSize) + + let memoryDataOffset := allocate_memory(argSize) + codecopy(memoryDataOffset, programSize, argSize) + + ret_param_0 := abi_decode_tuple_t_int256_fromMemory(memoryDataOffset, add(memoryDataOffset, argSize)) + } + + function extract_from_storage_value_offset_0t_int256(slot_value) -> value { + value := cleanup_from_storage_t_int256(shift_right_0_unsigned(slot_value)) + } + + function finalize_allocation(memPtr, size) { + let newFreePtr := add(memPtr, round_up_to_mul_of_32(size)) + // protect against overflow + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() } + mstore(64, newFreePtr) + } + + function panic_error_0x11() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x11) + revert(0, 0x24) + } + + function panic_error_0x41() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x41) + revert(0, 0x24) + } + + function prepare_store_t_int256(value) -> ret { + ret := value + } + + function read_from_storage_split_offset_0_t_int256(slot) -> value { + value := extract_from_storage_value_offset_0t_int256(sload(slot)) + + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function round_up_to_mul_of_32(value) -> result { + result := and(add(value, 31), not(31)) + } + + function shift_left_0(value) -> newValue { + newValue := + + shl(0, value) + + } + + function shift_right_0_unsigned(value) -> newValue { + newValue := + + shr(0, value) + + } + + function update_byte_slice_32_shift_0(value, toInsert) -> result { + let mask := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + toInsert := shift_left_0(toInsert) + value := and(value, not(mask)) + result := or(value, and(toInsert, mask)) + } + + function update_storage_value_offset_0t_int256_to_t_int256(slot, value_0) { + let convertedValue_0 := convert_t_int256_to_t_int256(value_0) + sstore(slot, update_byte_slice_32_shift_0(sload(slot), prepare_store_t_int256(convertedValue_0))) + } + + function validator_revert_t_int256(value) { + if iszero(eq(value, cleanup_t_int256(value))) { revert(0, 0) } + } + + } + object \"D_72_deployed\" { + code { + /// @src 1:91,166 + mstore(64, 128) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x26121ff0 + { + // f() + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := fun_f_30() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + } + + case 0x793816ec + { + // stateVar() + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := getter_fun_stateVar_10() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + } + + case 0x9942ec6f + { + // f2() + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + let ret_0 := fun_f2_53() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple_t_int256__to_t_int256__fromStack(memPos , ret_0) + return(memPos, sub(memEnd, memPos)) + } + + default {} + } + if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function abi_decode_t_int256_fromMemory(offset, end) -> value { + value := mload(offset) + validator_revert_t_int256(value) + } + + function abi_decode_tuple_(headStart, dataEnd) { + if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + } + + function abi_decode_tuple_t_int256_fromMemory(headStart, dataEnd) -> value0 { + if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + { + + let offset := 0 + + value0 := abi_decode_t_int256_fromMemory(add(headStart, offset), dataEnd) + } + + } + + function abi_encode_t_int256_to_t_int256_fromStack(value, pos) { + mstore(pos, cleanup_t_int256(value)) + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function abi_encode_tuple_t_int256__to_t_int256__fromStack(headStart , value0) -> tail { + tail := add(headStart, 32) + + abi_encode_t_int256_to_t_int256_fromStack(value0, add(headStart, 0)) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function checked_add_t_int256(x, y) -> sum { + x := cleanup_t_int256(x) + y := cleanup_t_int256(y) + + // overflow, if x >= 0 and y > (maxValue - x) + if and(iszero(slt(x, 0)), sgt(y, sub(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, x))) { panic_error_0x11() } + // underflow, if x < 0 and y < (minValue - x) + if and(slt(x, 0), slt(y, sub(0x8000000000000000000000000000000000000000000000000000000000000000, x))) { panic_error_0x11() } + + sum := add(x, y) + } + + function cleanup_from_storage_t_int256(value) -> cleaned { + cleaned := value + } + + function cleanup_t_int256(value) -> cleaned { + cleaned := value + } + + function cleanup_t_uint160(value) -> cleaned { + cleaned := and(value, 0xffffffffffffffffffffffffffffffffffffffff) + } + + /// @src 0:93,119 + function constant_constVar_5() -> ret { + /// @src 0:117,119 + let expr_4 := 0x29 + let _2 := convert_t_rational_41_by_1_to_t_int256(expr_4) + + ret := _2 + } + + function convert_t_contract$_C_$54_to_t_address(value) -> converted { + converted := convert_t_contract$_C_$54_to_t_uint160(value) + } + + function convert_t_contract$_C_$54_to_t_uint160(value) -> converted { + converted := cleanup_t_uint160(value) + } + + function convert_t_int256_to_t_int256(value) -> converted { + converted := cleanup_t_int256(value) + } + + function convert_t_rational_41_by_1_to_t_int256(value) -> converted { + converted := cleanup_t_int256(value) + } + + function extract_from_storage_value_dynamict_int256(slot_value, offset) -> value { + value := cleanup_from_storage_t_int256(shift_right_unsigned_dynamic(mul(offset, 8), slot_value)) + } + + function extract_from_storage_value_offset_0t_int256(slot_value) -> value { + value := cleanup_from_storage_t_int256(shift_right_0_unsigned(slot_value)) + } + + function finalize_allocation(memPtr, size) { + let newFreePtr := add(memPtr, round_up_to_mul_of_32(size)) + // protect against overflow + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() } + mstore(64, newFreePtr) + } + + function fun_f2_53() -> var__42 { + /// @src 0:343,426 + /// @src 0:375,378 + let zero_t_int256_4 := zero_value_for_split_t_int256() + var__42 := zero_t_int256_4 + + var__42 := modifier_m_40(var__42) + } + + function fun_f2_53_inner(_8) -> var__42 { + /// @src 0:343,426 + var__42 := _8 + + /// @src 0:392,400 + let _9 := read_from_storage_split_offset_0_t_int256(0x00) + let expr_44 := _9 + /// @src 0:403,407 + let expr_45_address := address() + /// @src 0:403,409 + let expr_46_address := convert_t_contract$_C_$54_to_t_address(expr_45_address) + let expr_46_functionSelector := 0x26121ff0 + /// @src 0:403,411 + if iszero(extcodesize(expr_46_address)) { revert_error_0cc013b6b3b6beabea4e3a74a6d380f0df81852ca99887912475e1f66b2a2c20() } + + // storage for arguments and returned data + let _10 := allocate_unbounded() + mstore(_10, shift_left_224(expr_46_functionSelector)) + let _11 := abi_encode_tuple__to__fromStack(add(_10, 4) ) + + let _12 := staticcall(gas(), expr_46_address, _10, sub(_11, _10), _10, 32) + + if iszero(_12) { revert_forward_1() } + + let expr_47 + if _12 { + + // update freeMemoryPointer according to dynamic return size + finalize_allocation(_10, returndatasize()) + + // decode return parameters from external try-call into retVars + expr_47 := abi_decode_tuple_t_int256_fromMemory(_10, add(_10, returndatasize())) + } + /// @src 0:392,411 + let expr_48 := checked_add_t_int256(expr_44, expr_47) + + /// @src 0:414,422 + let _13 := loadimmutable(\"8\") + let expr_49 := _13 + /// @src 0:392,422 + let expr_50 := checked_add_t_int256(expr_48, expr_49) + + /// @src 0:385,422 + var__42 := expr_50 + leave + + } + + function fun_f_30() -> var__23 { + /// @src 0:226,302 + /// @src 0:262,265 + let zero_t_int256_1 := zero_value_for_split_t_int256() + var__23 := zero_t_int256_1 + + /// @src 0:279,287 + let expr_25 := constant_constVar_5() + /// @src 0:290,298 + let _3 := loadimmutable(\"8\") + let expr_26 := _3 + /// @src 0:279,298 + let expr_27 := checked_add_t_int256(expr_25, expr_26) + + /// @src 0:272,298 + var__23 := expr_27 + leave + + } + + function getter_fun_stateVar_10() -> ret { + /// @src 0:152,171 + + let slot := 0 + let offset := 0 + + ret := read_from_storage_split_dynamic_t_int256(slot, offset) + + } + + function increment_t_int256(value) -> ret { + value := cleanup_t_int256(value) + if eq(value, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) { panic_error_0x11() } + ret := add(value, 1) + } + + function modifier_m_40(var__42) -> _5 { + /// @src 0:304,341 + _5 := var__42 + + /// @src 0:322,332 + let _7 := read_from_storage_split_offset_0_t_int256(0x00) + let _6 := increment_t_int256(_7) + update_storage_value_offset_0t_int256_to_t_int256(0x00, _6) + let expr_33 := _7 + /// @src 0:336,337 + _5 := fun_f2_53_inner(var__42) + + } + + function panic_error_0x11() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x11) + revert(0, 0x24) + } + + function panic_error_0x41() { + mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856) + mstore(4, 0x41) + revert(0, 0x24) + } + + function prepare_store_t_int256(value) -> ret { + ret := value + } + + function read_from_storage_split_dynamic_t_int256(slot, offset) -> value { + value := extract_from_storage_value_dynamict_int256(sload(slot), offset) + + } + + function read_from_storage_split_offset_0_t_int256(slot) -> value { + value := extract_from_storage_value_offset_0t_int256(sload(slot)) + + } + + function revert_error_0cc013b6b3b6beabea4e3a74a6d380f0df81852ca99887912475e1f66b2a2c20() { + revert(0, 0) + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() { + revert(0, 0) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function revert_forward_1() { + let pos := allocate_unbounded() + returndatacopy(pos, 0, returndatasize()) + revert(pos, returndatasize()) + } + + function round_up_to_mul_of_32(value) -> result { + result := and(add(value, 31), not(31)) + } + + function shift_left_0(value) -> newValue { + newValue := + + shl(0, value) + + } + + function shift_left_224(value) -> newValue { + newValue := + + shl(224, value) + + } + + function shift_right_0_unsigned(value) -> newValue { + newValue := + + shr(0, value) + + } + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function shift_right_unsigned_dynamic(bits, value) -> newValue { + newValue := + + shr(bits, value) + + } + + function update_byte_slice_32_shift_0(value, toInsert) -> result { + let mask := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + toInsert := shift_left_0(toInsert) + value := and(value, not(mask)) + result := or(value, and(toInsert, mask)) + } + + function update_storage_value_offset_0t_int256_to_t_int256(slot, value_0) { + let convertedValue_0 := convert_t_int256_to_t_int256(value_0) + sstore(slot, update_byte_slice_32_shift_0(sload(slot), prepare_store_t_int256(convertedValue_0))) + } + + function validator_revert_t_int256(value) { + if iszero(eq(value, cleanup_t_int256(value))) { revert(0, 0) } + } + + function zero_value_for_split_t_int256() -> ret { + ret := 0 + } + + } + + data \".metadata\" hex\"\" + } + +} + +"}}},"sources":{"C":{"id":0},"D":{"id":1}}} diff --git a/test/cmdlineTests/yul_string_format_ascii/output.json b/test/cmdlineTests/yul_string_format_ascii/output.json index 8e7ef86b0..df96ed791 100644 --- a/test/cmdlineTests/yul_string_format_ascii/output.json +++ b/test/cmdlineTests/yul_string_format_ascii/output.json @@ -1,13 +1,14 @@ -{"contracts":{"A":{"C":{"ir":"/******************************************************* +{"contracts":{"A":{"C":{"ir":"/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object \"C_11\" { code { + /// @src 0:78,164 mstore(64, 128) if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } @@ -24,6 +25,8 @@ object \"C_11\" { function constructor_C_11() { + /// @src 0:78,164 + } function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { @@ -33,6 +36,7 @@ object \"C_11\" { } object \"C_11_deployed\" { code { + /// @src 0:78,164 mstore(64, 128) if iszero(lt(calldatasize(), 4)) @@ -146,9 +150,12 @@ object \"C_11\" { } function fun_f_10() -> var__5_mpos { + /// @src 0:91,162 + /// @src 0:127,140 let zero_t_string_memory_ptr_1_mpos := zero_value_for_split_t_string_memory_ptr() var__5_mpos := zero_t_string_memory_ptr_1_mpos + /// @src 0:144,159 var__5_mpos := convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_string_memory_ptr() leave diff --git a/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json b/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json index c6de505db..9e47d6e1e 100644 --- a/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json @@ -1,13 +1,14 @@ -{"contracts":{"A":{"C":{"ir":"/******************************************************* +{"contracts":{"A":{"C":{"ir":"/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object \"C_11\" { code { + /// @src 0:78,158 mstore(64, 128) if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } @@ -24,6 +25,8 @@ object \"C_11\" { function constructor_C_11() { + /// @src 0:78,158 + } function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { @@ -33,6 +36,7 @@ object \"C_11\" { } object \"C_11_deployed\" { code { + /// @src 0:78,158 mstore(64, 128) if iszero(lt(calldatasize(), 4)) @@ -86,9 +90,12 @@ object \"C_11\" { } function fun_f_10() -> var__5 { + /// @src 0:91,156 + /// @src 0:127,134 let zero_t_bytes32_1 := zero_value_for_split_t_bytes32() var__5 := zero_t_bytes32_1 + /// @src 0:138,153 var__5 := convert_t_stringliteral_9f0adad0a59b05d2e04a1373342b10b9eb16c57c164c8a3bfcbf46dccee39a21_to_t_bytes32() leave diff --git a/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json b/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json index c4b747f3d..8c5df7044 100644 --- a/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json @@ -1,13 +1,14 @@ -{"contracts":{"A":{"C":{"ir":"/******************************************************* +{"contracts":{"A":{"C":{"ir":"/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object \"C_11\" { code { + /// @src 0:78,159 mstore(64, 128) if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } @@ -24,6 +25,8 @@ object \"C_11\" { function constructor_C_11() { + /// @src 0:78,159 + } function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { @@ -33,6 +36,7 @@ object \"C_11\" { } object \"C_11_deployed\" { code { + /// @src 0:78,159 mstore(64, 128) if iszero(lt(calldatasize(), 4)) @@ -90,10 +94,14 @@ object \"C_11\" { } function fun_f_10() -> var__5 { + /// @src 0:91,157 + /// @src 0:127,133 let zero_t_bytes4_1 := zero_value_for_split_t_bytes4() var__5 := zero_t_bytes4_1 + /// @src 0:144,154 let expr_7 := 0x61626364 + /// @src 0:137,154 var__5 := convert_t_rational_1633837924_by_1_to_t_bytes4(expr_7) leave diff --git a/test/cmdlineTests/yul_string_format_ascii_long/output.json b/test/cmdlineTests/yul_string_format_ascii_long/output.json index fe60dc52f..ad2197252 100644 --- a/test/cmdlineTests/yul_string_format_ascii_long/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_long/output.json @@ -1,13 +1,14 @@ -{"contracts":{"A":{"C":{"ir":"/******************************************************* +{"contracts":{"A":{"C":{"ir":"/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object \"C_11\" { code { + /// @src 0:78,243 mstore(64, 128) if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } @@ -24,6 +25,8 @@ object \"C_11\" { function constructor_C_11() { + /// @src 0:78,243 + } function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { @@ -33,6 +36,7 @@ object \"C_11\" { } object \"C_11_deployed\" { code { + /// @src 0:78,243 mstore(64, 128) if iszero(lt(calldatasize(), 4)) @@ -146,9 +150,12 @@ object \"C_11\" { } function fun_f_10() -> var__5_mpos { + /// @src 0:91,241 + /// @src 0:127,140 let zero_t_string_memory_ptr_1_mpos := zero_value_for_split_t_string_memory_ptr() var__5_mpos := zero_t_string_memory_ptr_1_mpos + /// @src 0:144,238 var__5_mpos := convert_t_stringliteral_d6604f85ac07e2b33103a620b3d3d75b0473c7214912beded67b9b624d41c571_to_t_string_memory_ptr() leave diff --git a/test/cmdlineTests/yul_string_format_hex/output.json b/test/cmdlineTests/yul_string_format_hex/output.json index 0e2851bad..86eb7ed62 100644 --- a/test/cmdlineTests/yul_string_format_hex/output.json +++ b/test/cmdlineTests/yul_string_format_hex/output.json @@ -1,13 +1,14 @@ -{"contracts":{"A":{"C":{"ir":"/******************************************************* +{"contracts":{"A":{"C":{"ir":"/*=====================================================* * WARNING * * Solidity to Yul compilation is still EXPERIMENTAL * * It can result in LOSS OF FUNDS or worse * * !USE AT YOUR OWN RISK! * - *******************************************************/ + *=====================================================*/ object \"C_11\" { code { + /// @src 0:78,159 mstore(64, 128) if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } @@ -24,6 +25,8 @@ object \"C_11\" { function constructor_C_11() { + /// @src 0:78,159 + } function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { @@ -33,6 +36,7 @@ object \"C_11\" { } object \"C_11_deployed\" { code { + /// @src 0:78,159 mstore(64, 128) if iszero(lt(calldatasize(), 4)) @@ -90,10 +94,14 @@ object \"C_11\" { } function fun_f_10() -> var__5 { + /// @src 0:91,157 + /// @src 0:127,133 let zero_t_bytes4_1 := zero_value_for_split_t_bytes4() var__5 := zero_t_bytes4_1 + /// @src 0:144,154 let expr_7 := 0xaabbccdd + /// @src 0:137,154 var__5 := convert_t_rational_2864434397_by_1_to_t_bytes4(expr_7) leave