From 0dd51e53c2eea31de4f395ca0b5b96ede6324d65 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Mon, 22 Jul 2024 19:15:14 +0200 Subject: [PATCH 1/3] Enable ethdebug debug info and output selection. --- libevmasm/AbstractAssemblyStack.h | 4 + libevmasm/Assembly.cpp | 2 +- libevmasm/EVMAssemblyStack.cpp | 11 + libevmasm/EVMAssemblyStack.h | 5 + liblangutil/DebugInfoSelection.cpp | 12 +- liblangutil/DebugInfoSelection.h | 6 +- libsolidity/codegen/ir/IRGenerator.cpp | 3 +- libsolidity/interface/CompilerStack.cpp | 39 +++ libsolidity/interface/CompilerStack.h | 16 ++ libsolidity/interface/StandardCompiler.cpp | 76 +++++- libyul/YulStack.cpp | 11 +- libyul/YulStack.h | 1 + solc/CommandLineInterface.cpp | 52 ++++ solc/CommandLineInterface.h | 2 + solc/CommandLineParser.cpp | 79 +++++- solc/CommandLineParser.h | 4 + test/libsolidity/StandardCompiler.cpp | 239 ++++++++++++++++++ test/libyul/Common.cpp | 2 +- test/libyul/EVMCodeTransformTest.cpp | 2 +- test/libyul/ObjectCompilerTest.cpp | 2 +- test/libyul/ObjectParser.cpp | 4 +- test/libyul/YulInterpreterTest.cpp | 2 +- test/solc/CommandLineInterface.cpp | 142 +++++++++++ .../ossfuzz/strictasm_assembly_ossfuzz.cpp | 2 +- test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp | 2 +- test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp | 2 +- 26 files changed, 699 insertions(+), 23 deletions(-) diff --git a/libevmasm/AbstractAssemblyStack.h b/libevmasm/AbstractAssemblyStack.h index 278edf5c273b..c38e2aaa27c1 100644 --- a/libevmasm/AbstractAssemblyStack.h +++ b/libevmasm/AbstractAssemblyStack.h @@ -40,6 +40,10 @@ class AbstractAssemblyStack virtual std::string const* sourceMapping(std::string const& _contractName) const = 0; virtual std::string const* runtimeSourceMapping(std::string const& _contractName) const = 0; + virtual Json ethdebug(std::string const& _contractName, bool _runtime) const = 0; + + virtual Json ethdebug() const = 0; + virtual Json assemblyJSON(std::string const& _contractName) const = 0; virtual std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const = 0; diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index ab3879da48c8..433c53b81484 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -426,7 +426,7 @@ std::string Assembly::assemblyString( { std::ostringstream tmp; assemblyStream(tmp, _debugInfoSelection, "", _sourceCodes); - return tmp.str(); + return (_debugInfoSelection.ethdebug ? "/// ethdebug: enabled\n" : "") + tmp.str(); } Json Assembly::assemblyJSON(std::map const& _sourceIndices, bool _includeSourceList) const diff --git a/libevmasm/EVMAssemblyStack.cpp b/libevmasm/EVMAssemblyStack.cpp index 20605ee354a0..f6a4cd8de117 100644 --- a/libevmasm/EVMAssemblyStack.cpp +++ b/libevmasm/EVMAssemblyStack.cpp @@ -99,6 +99,17 @@ std::string const* EVMAssemblyStack::runtimeSourceMapping(std::string const& _co return &m_runtimeSourceMapping; } +Json EVMAssemblyStack::ethdebug(std::string const& _contractName, bool _runtime) const +{ + solAssert(_contractName == m_name); + return _runtime ? m_runtimeEthdebug : m_ethdebug; +} + +Json EVMAssemblyStack::ethdebug() const +{ + return {}; +} + Json EVMAssemblyStack::assemblyJSON(std::string const& _contractName) const { solAssert(_contractName == m_name); diff --git a/libevmasm/EVMAssemblyStack.h b/libevmasm/EVMAssemblyStack.h index f2516c0b8a0a..cadff677122a 100644 --- a/libevmasm/EVMAssemblyStack.h +++ b/libevmasm/EVMAssemblyStack.h @@ -58,6 +58,9 @@ class EVMAssemblyStack: public AbstractAssemblyStack virtual std::string const* sourceMapping(std::string const& _contractName) const override; virtual std::string const* runtimeSourceMapping(std::string const& _contractName) const override; + virtual Json ethdebug(std::string const& _contractName, bool _runtime) const override; + virtual Json ethdebug() const override; + virtual Json assemblyJSON(std::string const& _contractName) const override; virtual std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const override; @@ -85,6 +88,8 @@ class EVMAssemblyStack: public AbstractAssemblyStack langutil::DebugInfoSelection m_debugInfoSelection = langutil::DebugInfoSelection::Default(); std::string m_sourceMapping; std::string m_runtimeSourceMapping; + Json m_ethdebug; + Json m_runtimeEthdebug; }; } // namespace solidity::evmasm diff --git a/liblangutil/DebugInfoSelection.cpp b/liblangutil/DebugInfoSelection.cpp index ad0b615c1c1e..57e4d17650b7 100644 --- a/liblangutil/DebugInfoSelection.cpp +++ b/liblangutil/DebugInfoSelection.cpp @@ -49,6 +49,14 @@ DebugInfoSelection const DebugInfoSelection::Only(bool DebugInfoSelection::* _me return result; } +DebugInfoSelection const DebugInfoSelection::Except(std::vector const& _members) noexcept +{ + DebugInfoSelection result = All(); + for (bool DebugInfoSelection::* member: _members) + result.*member = false; + return result; +} + std::optional DebugInfoSelection::fromString(std::string_view _input) { // TODO: Make more stuff constexpr and make it a static_assert(). @@ -56,7 +64,7 @@ std::optional DebugInfoSelection::fromString(std::string_vie solAssert(componentMap().count("none") == 0, ""); if (_input == "all") - return All(); + return ExceptExperimental(); if (_input == "none") return None(); @@ -74,7 +82,7 @@ std::optional DebugInfoSelection::fromComponents( for (auto const& component: _componentNames) { if (component == "*") - return (_acceptWildcards ? std::make_optional(DebugInfoSelection::All()) : std::nullopt); + return (_acceptWildcards ? std::make_optional(ExceptExperimental()) : std::nullopt); if (!selection.enable(component)) return std::nullopt; diff --git a/liblangutil/DebugInfoSelection.h b/liblangutil/DebugInfoSelection.h index 3a9432de6d02..cdaf75cc8045 100644 --- a/liblangutil/DebugInfoSelection.h +++ b/liblangutil/DebugInfoSelection.h @@ -42,7 +42,9 @@ struct DebugInfoSelection static DebugInfoSelection const All(bool _value = true) noexcept; static DebugInfoSelection const None() noexcept { return All(false); } static DebugInfoSelection const Only(bool DebugInfoSelection::* _member) noexcept; - static DebugInfoSelection const Default() noexcept { return All(); } + static DebugInfoSelection const Default() noexcept { return ExceptExperimental(); } + static DebugInfoSelection const Except(std::vector const& _members) noexcept; + static DebugInfoSelection const ExceptExperimental() noexcept { return Except({&DebugInfoSelection::ethdebug}); } static std::optional fromString(std::string_view _input); static std::optional fromComponents( @@ -72,6 +74,7 @@ struct DebugInfoSelection {"location", &DebugInfoSelection::location}, {"snippet", &DebugInfoSelection::snippet}, {"ast-id", &DebugInfoSelection::astID}, + {"ethdebug", &DebugInfoSelection::ethdebug}, }; return components; } @@ -79,6 +82,7 @@ struct DebugInfoSelection bool location = false; ///< Include source location. E.g. `@src 3:50:100` bool snippet = false; ///< Include source code snippet next to location. E.g. `@src 3:50:100 "contract C {..."` bool astID = false; ///< Include ID of the Solidity AST node. E.g. `@ast-id 15` + bool ethdebug = false; ///< Include ethdebug related debug information. }; std::ostream& operator<<(std::ostream& _stream, DebugInfoSelection const& _selection); diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index 00c9fa196bd8..738638d2097f 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -130,7 +130,7 @@ std::string IRGenerator::generate( ); }; - Whiskers t(R"( + Whiskers t(R"(/// ethdebug: enabled /// @use-src object "" { code { @@ -167,6 +167,7 @@ std::string IRGenerator::generate( for (VariableDeclaration const* var: ContractType(_contract).immutableVariables()) m_context.registerImmutableVariable(*var); + t("isEthdebugEnabled", m_context.debugInfoSelection().ethdebug); t("CreationObject", IRNames::creationObject(_contract)); t("sourceLocationCommentCreation", dispenseLocationComment(_contract)); t("library", _contract.isLibrary()); diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 1f432db40fca..82ce0a0bc37f 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1092,6 +1092,45 @@ Json CompilerStack::interfaceSymbols(std::string const& _contractName) const return interfaceSymbols; } +Json CompilerStack::ethdebug() const +{ + return m_ethdebug.init( + [&] + { + Json result = Json::object(); + result["sources"] = sourceNames(); + return result; + }); +} + +Json CompilerStack::ethdebug(std::string const& _contractName, bool _runtime) const +{ + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); + return ethdebug(contract(_contractName), _runtime); +} + +Json CompilerStack::ethdebug(Contract const& _contract, bool _runtime) const +{ + solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); + solAssert(_contract.contract); + solUnimplementedAssert(!isExperimentalSolidity()); + if (_runtime) + return _contract.ethdebugRuntime.init( + [&] + { + Json result = Json::object(); + result["ethdebug-runtime-data"] = true; + return result; + }); + return _contract.ethdebug.init( + [&] + { + Json result = Json::object(); + result["ethdebug-data"] = true; + return result; + }); +} + bytes CompilerStack::cborMetadata(std::string const& _contractName, bool _forIR) const { solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful."); diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 25863b6d0690..27ecc8f02b43 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -355,6 +355,14 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// @returns a JSON object with the three members ``methods``, ``events``, ``errors``. Each is a map, mapping identifiers (hashes) to function names. Json interfaceSymbols(std::string const& _contractName) const; + /// @returns a JSON representing the ethdebug data of the specified contract. + /// Prerequisite: Successful call to parse or compile. + Json ethdebug(std::string const& _contractName, bool _runtime) const override; + + /// @returns a JSON representing the top-level ethdebug data (types, etc.). + /// Prerequisite: Successful call to parse or compile. + Json ethdebug() const override; + /// @returns the Contract Metadata matching the pipeline selected using the viaIR setting. std::string const& metadata(std::string const& _contractName) const { return metadata(contract(_contractName)); } @@ -419,6 +427,8 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac util::LazyInit devDocumentation; util::LazyInit generatedSources; util::LazyInit runtimeGeneratedSources; + util::LazyInit ethdebug; + util::LazyInit ethdebugRuntime; mutable std::optional sourceMapping; mutable std::optional runtimeSourceMapping; }; @@ -527,6 +537,10 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac /// This will generate the metadata and store it in the Contract object if it is not present yet. std::string const& metadata(Contract const& _contract) const; + /// @returns the Contract ethdebug data. + /// This will generate the JSON object and store it in the Contract object if it is not present yet. + Json ethdebug(Contract const& _contract, bool _runtime) const; + /// @returns the offset of the entry point of the given function into the list of assembly items /// or zero if it is not found or does not exist. size_t functionEntryPoint( @@ -567,6 +581,8 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac State m_stackState = Empty; CompilationSourceType m_compilationSourceType = CompilationSourceType::Solidity; MetadataFormat m_metadataFormat = defaultMetadataFormat(); + // top-level ethdebug object containing top-level information (types, sources, etc.) + util::LazyInit m_ethdebug; }; } diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 0c1ccb6b7653..8aa6de21f5c0 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -180,7 +180,7 @@ bool hashMatchesContent(std::string const& _hash, std::string const& _content) bool isArtifactRequested(Json const& _outputSelection, std::string const& _artifact, bool _wildcardMatchesExperimental) { - static std::set experimental{"ir", "irAst", "irOptimized", "irOptimizedAst"}; + static std::set experimental{"ir", "irAst", "irOptimized", "irOptimizedAst", "evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug"}; for (auto const& selectedArtifactJson: _outputSelection) { std::string const& selectedArtifact = selectedArtifactJson.get(); @@ -188,10 +188,17 @@ bool isArtifactRequested(Json const& _outputSelection, std::string const& _artif _artifact == selectedArtifact || boost::algorithm::starts_with(_artifact, selectedArtifact + ".") ) + { + if (_artifact.find("ethdebug") != std::string::npos) + // only accept exact matches for ethdebug, e.g. evm.bytecode.ethdebug + return selectedArtifact == _artifact; return true; + } else if (selectedArtifact == "*") { // "ir", "irOptimized" can only be matched by "*" if activated. + if (_artifact.find("ethdebug") != std::string::npos) + return false; if (experimental.count(_artifact) == 0 || _wildcardMatchesExperimental) return true; } @@ -249,7 +256,7 @@ bool isArtifactRequested(Json const& _outputSelection, std::string const& _file, std::vector evmObjectComponents(std::string const& _objectKind) { solAssert(_objectKind == "bytecode" || _objectKind == "deployedBytecode", ""); - std::vector components{"", ".object", ".opcodes", ".sourceMap", ".functionDebugData", ".generatedSources", ".linkReferences"}; + std::vector components{"", ".object", ".opcodes", ".sourceMap", ".functionDebugData", ".generatedSources", ".linkReferences", ".ethdebug"}; if (_objectKind == "deployedBytecode") components.push_back(".immutableReferences"); return util::applyMap(components, [&](auto const& _s) { return "evm." + _objectKind + _s; }); @@ -295,6 +302,21 @@ bool isEvmBytecodeRequested(Json const& _outputSelection) return false; } +/// @returns true if ethdebug was requested. +bool isEthdebugRequested(Json const& _outputSelection) +{ + if (!_outputSelection.is_object()) + return false; + + for (auto const& fileRequests: _outputSelection) + for (auto const& requests: fileRequests) + for (auto const& request: requests) + if (request == "evm.bytecode.ethdebug" || request == "evm.deployedBytecode.ethdebug") + return true; + + return false; +} + /// @returns The IR output selection for CompilerStack, based on outputs requested in the JSON. /// Note that as an exception, '*' does not yet match "ir", "irAst", "irOptimized" or "irOptimizedAst". CompilerStack::IROutputSelection irOutputSelection(Json const& _outputSelection) @@ -371,6 +393,7 @@ Json collectEVMObject( langutil::EVMVersion _evmVersion, evmasm::LinkerObject const& _object, std::string const* _sourceMap, + Json _ethdebug, Json _generatedSources, bool _runtimeObject, std::function const& _artifactRequested @@ -391,6 +414,9 @@ Json collectEVMObject( output["immutableReferences"] = formatImmutableReferences(_object.immutableReferences); if (_artifactRequested("generatedSources")) output["generatedSources"] = std::move(_generatedSources); + if (_artifactRequested("ethdebug")) + output["ethdebug"] = std::move(_ethdebug); + return output; } @@ -1172,6 +1198,36 @@ std::variant StandardCompiler::parseI ret.modelCheckerSettings.timeout = modelCheckerSettings["timeout"].get(); } + if ((ret.debugInfoSelection.has_value() && ret.debugInfoSelection->ethdebug) || isEthdebugRequested(ret.outputSelection)) + { + if (ret.language != "Solidity" && ret.language != "Yul") + return formatFatalError(Error::Type::FatalError, "'ethdebug' is only supported for languages 'Solidity' and 'Yul'."); + } + + if (isEthdebugRequested(ret.outputSelection)) + { + if (ret.language == "Solidity" && !ret.viaIR) + return formatFatalError(Error::Type::FatalError, "'ethdebug' can only be selected as output, if 'viaIR' was set."); + + if (!ret.debugInfoSelection.has_value()) + { + ret.debugInfoSelection = DebugInfoSelection::Default(); + ret.debugInfoSelection->enable("ethdebug"); + } + else + { + if (!ret.debugInfoSelection->ethdebug && ret.language == "Solidity") + return formatFatalError(Error::Type::FatalError, "'ethdebug' needs to be enabled in 'settings.debug.debugInfo', if 'ethdebug' was selected as output."); + } + } + + if ( + ret.debugInfoSelection.has_value() && ret.debugInfoSelection->ethdebug && ret.language == "Solidity" && + irOutputSelection(ret.outputSelection) == CompilerStack::IROutputSelection::None && + !isEthdebugRequested(ret.outputSelection) + ) + return formatFatalError(Error::Type::FatalError, "'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized' and/or 'ethdebug' was selected."); + return {std::move(ret)}; } @@ -1247,6 +1303,7 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in _inputsAndSettings.evmVersion, stack.object(sourceName), stack.sourceMapping(sourceName), + stack.ethdebug(sourceName, false), {}, false, // _runtimeObject [&](std::string const& _element) { @@ -1271,6 +1328,7 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in _inputsAndSettings.evmVersion, stack.runtimeObject(sourceName), stack.runtimeSourceMapping(sourceName), + stack.ethdebug(sourceName, true), {}, true, // _runtimeObject [&](std::string const& _element) { @@ -1292,6 +1350,7 @@ Json StandardCompiler::importEVMAssembly(StandardCompiler::InputsAndSettings _in contractsOutput[sourceName][""] = contractData; Json output; output["contracts"] = contractsOutput; + return util::removeNullMembers(output); } @@ -1430,8 +1489,8 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu Json output; - if (errors.size() > 0) - output["errors"] = std::move(errors); + if (!errors.empty()) + output["errors"] = std::move(errors); if (!compilerStack.unhandledSMTLib2Queries().empty()) for (std::string const& query: compilerStack.unhandledSMTLib2Queries()) @@ -1508,6 +1567,7 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu _inputsAndSettings.evmVersion, compilerStack.object(contractName), compilerStack.sourceMapping(contractName), + compilerStack.ethdebug(contractName, false), compilerStack.generatedSources(contractName), false, [&](std::string const& _element) { return isArtifactRequested( @@ -1530,6 +1590,7 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu _inputsAndSettings.evmVersion, compilerStack.runtimeObject(contractName), compilerStack.runtimeSourceMapping(contractName), + compilerStack.ethdebug(contractName, true), compilerStack.generatedSources(contractName, true), true, [&](std::string const& _element) { return isArtifactRequested( @@ -1554,6 +1615,9 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu if (!contractsOutput.empty()) output["contracts"] = contractsOutput; + if (isEthdebugRequested(_inputsAndSettings.outputSelection)) + output["ethdebug"] = compilerStack.ethdebug(); + return output; } @@ -1682,6 +1746,7 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) _inputsAndSettings.evmVersion, *o.bytecode, o.sourceMappings.get(), + o.ethdebug, Json::array(), isDeployed, [&, kind = kind](std::string const& _element) { return isArtifactRequested( @@ -1699,6 +1764,9 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "evm.assembly", wildcardMatchesExperimental)) output["contracts"][sourceName][contractName]["evm"]["assembly"] = object.assembly->assemblyString(stack.debugInfoSelection()); + if (isEthdebugRequested(_inputsAndSettings.outputSelection)) + output["ethdebug"] = {}; + return output; } diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 1f57eda48cb3..68da91d988aa 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -266,6 +266,7 @@ YulStack::assembleWithDeployed(std::optional _deployName) {{m_charStream->name(), 0}} ) ); + creationObject.ethdebug["not yet implemented @ MachineAssemblyObject::ethdebug"] = true; if (deployedAssembly) { @@ -277,6 +278,7 @@ YulStack::assembleWithDeployed(std::optional _deployName) {{m_charStream->name(), 0}} ) ); + deployedObject.ethdebug["not yet implemented @ MachineAssemblyObject::ethdebug"] = true; } } catch (UnimplementedFeatureError const& _error) @@ -350,10 +352,11 @@ std::string YulStack::print( yulAssert(m_stackState >= Parsed); yulAssert(m_parserResult, ""); yulAssert(m_parserResult->hasCode(), ""); - return m_parserResult->toString( - m_debugInfoSelection, - _soliditySourceProvider - ) + "\n"; + return (m_debugInfoSelection.ethdebug ? "/// ethdebug: enabled\n" : "") + + m_parserResult->toString( + m_debugInfoSelection, + _soliditySourceProvider + ) + "\n"; } Json YulStack::astJson() const diff --git a/libyul/YulStack.h b/libyul/YulStack.h index 69c0f01656f9..f0487ffe52cb 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -58,6 +58,7 @@ struct MachineAssemblyObject std::shared_ptr bytecode; std::shared_ptr assembly; std::unique_ptr sourceMappings; + Json ethdebug = Json::object(); }; /* diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 02b6dcade295..3a421a9d7cfb 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -150,6 +150,7 @@ static bool needsHumanTargetedStdout(CommandLineOptions const& _options) _options.compiler.outputs.asmJson || _options.compiler.outputs.binary || _options.compiler.outputs.binaryRuntime || + _options.compiler.outputs.ethdebug || _options.compiler.outputs.metadata || _options.compiler.outputs.natspecUser || _options.compiler.outputs.natspecDev || @@ -520,6 +521,44 @@ void CommandLineInterface::handleGasEstimation(std::string const& _contract) } } +void CommandLineInterface::handleEthdebug() +{ + if (m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) + { + std::string ethdebug{jsonPrint(removeNullMembers(m_compiler->ethdebug()), m_options.formatting.json)}; + if (!m_options.output.dir.empty()) + createFile("ethdebug.json", ethdebug); + else + sout() << "Debug Data Definitions:" << std::endl << ethdebug << std::endl; + } +} + +void CommandLineInterface::handleEthdebug(std::string const& _contract) +{ + solAssert(CompilerInputModes.count(m_options.input.mode) == 1); + + if (!(m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime)) + return; + + if (m_options.compiler.outputs.ethdebug) + { + std::string ethdebug{jsonPrint(removeNullMembers(m_compiler->ethdebug(_contract, false)), m_options.formatting.json)}; + if (!m_options.output.dir.empty()) + createFile(m_compiler->filesystemFriendlyName(_contract) + "_ethdebug.json", ethdebug); + else + sout() << "Debug Data:" << std::endl << ethdebug << std::endl; + } + + if (m_options.compiler.outputs.ethdebugRuntime) + { + std::string ethdebugRuntime{jsonPrint(removeNullMembers(m_compiler->ethdebug(_contract, true)), m_options.formatting.json)}; + if (!m_options.output.dir.empty()) + createFile(m_compiler->filesystemFriendlyName(_contract) + "_ethdebug.json", ethdebugRuntime); + else + sout() << "Debug Data of the runtime part:" << std::endl << ethdebugRuntime << std::endl; + } +} + void CommandLineInterface::readInputFiles() { solAssert(!m_standardJsonInput.has_value()); @@ -879,6 +918,8 @@ void CommandLineInterface::compile() m_options.compiler.outputs.opcodes || m_options.compiler.outputs.binary || m_options.compiler.outputs.binaryRuntime || + m_options.compiler.outputs.ethdebug || + m_options.compiler.outputs.ethdebugRuntime || (m_options.compiler.combinedJsonRequests && ( m_options.compiler.combinedJsonRequests->binary || m_options.compiler.combinedJsonRequests->binaryRuntime || @@ -1300,6 +1341,14 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y m_options.formatting.json ) << std::endl; } + if (m_options.compiler.outputs.ethdebug) + { + sout() << std::endl << "Debug Data (ethdebug):" << std::endl; + sout() << util::jsonPrint( + object.ethdebug, + m_options.formatting.json + ) << std::endl; + } } } @@ -1312,6 +1361,8 @@ void CommandLineInterface::outputCompilationResults() // do we need AST output? handleAst(); + handleEthdebug(); + CompilerOutputs astOutputSelection; astOutputSelection.astCompactJson = true; if (m_options.compiler.outputs != CompilerOutputs() && m_options.compiler.outputs != astOutputSelection) @@ -1342,6 +1393,7 @@ void CommandLineInterface::outputCompilationResults() handleTransientStorageLayout(contract); handleNatspec(true, contract); handleNatspec(false, contract); + handleEthdebug(contract); } // end of contracts iteration } diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index c23fd9e17b1f..21edc4c34120 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -101,6 +101,7 @@ class CommandLineInterface void handleCombinedJSON(); void handleAst(); + void handleEthdebug(); void handleEVMAssembly(std::string const& _contract); void handleBinary(std::string const& _contract); void handleOpcode(std::string const& _contract); @@ -116,6 +117,7 @@ class CommandLineInterface void handleGasEstimation(std::string const& _contract); void handleStorageLayout(std::string const& _contract); void handleTransientStorageLayout(std::string const& _contract); + void handleEthdebug(std::string const& _contract); /// Tries to read @ m_sourceCodes as a JSONs holding ASTs /// such that they can be imported into the compiler (importASTs()) diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 19089d885ae8..3d71f321f39f 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -473,6 +473,8 @@ void CommandLineParser::parseOutputSelection() CompilerOutputs::componentName(&CompilerOutputs::irOptimized), CompilerOutputs::componentName(&CompilerOutputs::astCompactJson), CompilerOutputs::componentName(&CompilerOutputs::asmJson), + CompilerOutputs::componentName(&CompilerOutputs::ethdebug), + CompilerOutputs::componentName(&CompilerOutputs::ethdebugRuntime), }; static std::set const evmAssemblyJsonImportModeOutputs = { CompilerOutputs::componentName(&CompilerOutputs::asm_), @@ -641,7 +643,13 @@ General Information)").c_str(), po::value()->default_value(util::toString(DebugInfoSelection::Default())), ("Debug info components to be included in the produced EVM assembly and Yul code. " "Value can be all, none or a comma-separated list containing one or more of the " - "following components: " + util::joinHumanReadable(DebugInfoSelection::componentMap() | ranges::views::keys) + ".").c_str() + "following components: " + + util::joinHumanReadable( + DebugInfoSelection::componentMap() | ranges::views::keys | + // Note: We intentionally keep ethdebug undocumented for now. + ranges::views::filter([](std::string const& key) { return key != "ethdebug"; }) | + ranges::to() + ) + ".").c_str() ) ( g_strStopAfter.c_str(), @@ -762,6 +770,19 @@ General Information)").c_str(), (CompilerOutputs::componentName(&CompilerOutputs::storageLayout).c_str(), "Slots, offsets and types of the contract's state variables located in storage.") (CompilerOutputs::componentName(&CompilerOutputs::transientStorageLayout).c_str(), "Slots, offsets and types of the contract's state variables located in transient storage.") ; + if (!_forHelp) // Note: We intentionally keep this undocumented for now. + { + outputComponents.add_options() + ( + CompilerOutputs::componentName(&CompilerOutputs::ethdebug).c_str(), + "Ethdebug output of all contracts." + ); + outputComponents.add_options() + ( + CompilerOutputs::componentName(&CompilerOutputs::ethdebugRuntime).c_str(), + "Ethdebug output of the runtime part of all contracts." + ); + } desc.add(outputComponents); po::options_description extraOutput("Extra Output"); @@ -1446,6 +1467,62 @@ void CommandLineParser::processArgs() m_options.input.mode == InputMode::CompilerWithASTImport || m_options.input.mode == InputMode::EVMAssemblerJSON ); + + std::string ethdebugOutputSelection = + "--" + CompilerOutputs::componentName(&CompilerOutputs::ethdebug) + " / --" + CompilerOutputs::componentName(&CompilerOutputs::ethdebugRuntime); + + bool incompatibleEthdebugOutputs = + m_options.compiler.outputs.asmJson || m_options.compiler.outputs.irAstJson || m_options.compiler.outputs.irOptimizedAstJson; + + bool incompatibleEthdebugInputs = m_options.input.mode != InputMode::Compiler; + + if (m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) + { + if (!m_options.output.viaIR) + solThrow( + CommandLineValidationError, + "--" + CompilerOutputs::componentName(&CompilerOutputs::ethdebug) + " / --" + CompilerOutputs::componentName(&CompilerOutputs::ethdebugRuntime) + " output can only be selected, if --via-ir was specified." + ); + + if (incompatibleEthdebugOutputs) + solThrow( + CommandLineValidationError, + "--" + CompilerOutputs::componentName(&CompilerOutputs::ethdebug) + " output can only be used with --" + CompilerOutputs::componentName(&CompilerOutputs::ir) + + ", --" + CompilerOutputs::componentName(&CompilerOutputs::irOptimized) + + " and/or " + ethdebugOutputSelection + "." + ); + + if (!m_options.output.debugInfoSelection.has_value()) + { + m_options.output.debugInfoSelection = DebugInfoSelection::Default(); + m_options.output.debugInfoSelection->enable("ethdebug"); + } + else + { + if (!m_options.output.debugInfoSelection->ethdebug) + solThrow( + CommandLineValidationError, + "--debug-info must contain ethdebug, when compiling with " + ethdebugOutputSelection + "." + ); + } + } + + if ( + m_options.output.debugInfoSelection.has_value() && m_options.output.debugInfoSelection->ethdebug && + (!(m_options.compiler.outputs.ir || m_options.compiler.outputs.irOptimized || m_options.compiler.outputs.ethdebug || m_options.compiler.outputs.ethdebugRuntime) || incompatibleEthdebugOutputs) + ) + solThrow( + CommandLineValidationError, + "--debug-info ethdebug can only be used with --" + CompilerOutputs::componentName(&CompilerOutputs::ir) + + ", --" + CompilerOutputs::componentName(&CompilerOutputs::irOptimized) + + " and/or " + ethdebugOutputSelection + "." + ); + + if (m_options.output.debugInfoSelection.has_value() && m_options.output.debugInfoSelection->ethdebug && incompatibleEthdebugInputs) + solThrow( + CommandLineValidationError, + "Invalid input mode for --debug-info ethdebug and/or --ethdebug." + ); } void CommandLineParser::parseCombinedJsonOption() diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index 5d941f662c99..46c9d17e121f 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -87,6 +87,8 @@ struct CompilerOutputs {"metadata", &CompilerOutputs::metadata}, {"storage-layout", &CompilerOutputs::storageLayout}, {"transient-storage-layout", &CompilerOutputs::transientStorageLayout}, + {"ethdebug", &CompilerOutputs::ethdebug}, + {"ethdebug-runtime", &CompilerOutputs::ethdebugRuntime}, }; return components; } @@ -108,6 +110,8 @@ struct CompilerOutputs bool metadata = false; bool storageLayout = false; bool transientStorageLayout = false; + bool ethdebug = false; + bool ethdebugRuntime = false; }; struct CombinedJsonRequests diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 4cb0b3c93068..0d5b23e54865 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -33,6 +33,7 @@ #include #include +#include using namespace solidity::evmasm; using namespace std::string_literals; @@ -152,6 +153,132 @@ Json compile(std::string _input) return ret; } +Json createLanguageAndSourcesSection(std::string const& _language, std::string const& _file, Json const& _content) +{ + Json result = Json::object(); + result["language"] = _language; + result["sources"] = Json::object(); + result["sources"][_file] = Json::object(); + result["sources"][_file]["content"] = _content; + return result; +} + +class Code +{ +public: + virtual ~Code() = default; + explicit Code(std::string _code = {}) : m_code(std::move(_code)) {} + [[nodiscard]] virtual Json json() const = 0; +protected: + std::string m_code; +}; + +class SolidityCode: public Code +{ +public: + explicit SolidityCode(std::string const& _code = {}) : Code(_code) {} + [[nodiscard]] Json json() const override + { + static std::string defaultCode = "pragma solidity >=0.0; contract C { function f() public pure {} }"; + return createLanguageAndSourcesSection("Solidity", "fileA", m_code.empty() ? defaultCode : m_code); + } +}; + +class YulCode: public Code +{ +public: + explicit YulCode(std::string const& _code = {}) : Code(_code) {} + [[nodiscard]] Json json() const override + { + static std::string defaultCode = "{}"; + return createLanguageAndSourcesSection("Yul", "fileA", m_code.empty() ? defaultCode : m_code); + } +}; + +class EvmAssemblyCode: public Code +{ +public: + explicit EvmAssemblyCode(std::string const& _code = {}) : Code(_code) {} + [[nodiscard]] Json json() const override + { + static std::string defaultCode = R"( + { + "assemblyJson": { + ".code": [ + { + "begin": 36, + "end": 51, + "name": "PUSH", + "source": 0, + "value": "0" + } + ], + "sourceList": [ + "" + ] + } + })"; + return createLanguageAndSourcesSection("EVMAssembly", "fileA", m_code.empty() ? Json::parse(defaultCode) : Json::parse(m_code)); + } +}; + +class SolidityAstCode: public Code +{ +public: + explicit SolidityAstCode(std::string const& _code = {}) : Code(_code) {} + [[nodiscard]] Json json() const override + { + static std::string defaultCode = R"( + { + "ast": { + "absolutePath": "empty_contract.sol", + "exportedSymbols": { + "test": [ + 1 + ] + }, + "id": 2, + "nodeType": "SourceUnit", + "nodes": [ + { + "abstract": false, + "baseContracts": [], + "canonicalName": "test", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 1, + "linearizedBaseContracts": [ + 1 + ], + "name": "test", + "nameLocation": "9:4:0", + "nodeType": "ContractDefinition", + "nodes": [], + "scope": 2, + "src": "0:17:0", + "usedErrors": [] + } + ], + "src": "0:124:0" + }, + "id": 0 + })"; + return createLanguageAndSourcesSection("SolidityAST", "fileA", m_code.empty() ? Json::parse(defaultCode) : Json::parse(m_code)); + } +}; + +Json generateStandardJson(bool _viaIr, std::optional const& _debugInfoSelection, Json const& _outputSelection, Code const& _code = SolidityCode()) +{ + Json result = _code.json(); + result["settings"] = Json::object(); + result["settings"]["viaIR"] = _viaIr; + if (_debugInfoSelection.has_value()) + result["settings"]["debug"]["debugInfo"] = _debugInfoSelection.value(); + result["settings"]["outputSelection"]["*"]["*"] = _outputSelection; + return result; +} + } // end anonymous namespace BOOST_AUTO_TEST_SUITE(StandardCompiler) @@ -1782,6 +1909,118 @@ BOOST_AUTO_TEST_CASE(source_location_of_bare_block) BOOST_REQUIRE(sourceMap.find(sourceRef) != std::string::npos); } +BOOST_AUTO_TEST_CASE(ethdebug_excluded_from_wildcards) +{ + frontend::StandardCompiler compiler; + // excluded from output selection wildcard + Json result = compiler.compile(generateStandardJson(true, {}, Json::array({"*"}))); + BOOST_REQUIRE(result.dump().find("ethdebug") == std::string::npos); + // excluded from debug info selection wildcard + result = compiler.compile(generateStandardJson(true, {"*"}, Json::array({"ir"}))); + BOOST_REQUIRE(result.dump().find("ethdebug") == std::string::npos); + // excluded from both - just in case ;) + result = compiler.compile(generateStandardJson(true, {"*"}, Json::array({"*"}))); + BOOST_REQUIRE(result.dump().find("ethdebug") == std::string::npos); + // "evm.bytecode.ethdebug" / "evm.deployedBytecode.ethdebug" is excluded from "evm.bytecode" / "evm.deployedBytecode" + result = compiler.compile(generateStandardJson(true, {"*"}, Json::array({"evm.bytecode"}))); + BOOST_REQUIRE(result.dump().find("ethdebug") == std::string::npos); + result = compiler.compile(generateStandardJson(true, {"*"}, Json::array({"evm.deployedBytecode"}))); + BOOST_REQUIRE(result.dump().find("ethdebug") == std::string::npos); +} + +BOOST_AUTO_TEST_CASE(ethdebug_debug_info_ethdebug) +{ + frontend::StandardCompiler compiler; + // it will only work if ir, irOptimized and / or ethdebug was selected as output + // - debug-info selection "ethdebug" will not work on output selection wildcard. + Json result = compiler.compile(generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"*"}))); + BOOST_REQUIRE(result["errors"].size() == 1); + result = compiler.compile(generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"*"}))); + BOOST_REQUIRE(result["errors"].size() == 1); + // debug-info selection "ethdebug" only works with via-ir, if "ethdebug" was selected as output. + // - this one will not work, because via-ir is disabled: + result = compiler.compile(generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"}))); + BOOST_REQUIRE(result["errors"].size() == 1); + // - via-ir enabled, everything is fine: + result = compiler.compile(generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"}))); + BOOST_REQUIRE(result.contains("ethdebug")); + BOOST_REQUIRE(result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug")); + result = compiler.compile(generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"}))); + BOOST_REQUIRE(result.contains("ethdebug")); + BOOST_REQUIRE(result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug")); + // 'settings.debug.debugInfo' can only include 'ethdebug', if output 'ir', 'irOptimized' and/or 'ethdebug' was selected. + result = compiler.compile(generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"bin"}))); + BOOST_REQUIRE(result["errors"].size() == 1); + result = compiler.compile(generateStandardJson(true, Json::array({"ethdebug"}), Json::array({ "bin"}))); + BOOST_REQUIRE(result["errors"].size() == 1); + // debug-info selection "ethdebug" works with ir, irOptimized. + result = compiler.compile(generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"ir"}))); + BOOST_REQUIRE(result.contains("contracts")); + BOOST_REQUIRE(result.dump().find("/// ethdebug: enabled") != std::string::npos); + result = compiler.compile(generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"irOptimized"}))); + BOOST_REQUIRE(result.contains("contracts")); + BOOST_REQUIRE(result.dump().find("/// ethdebug: enabled") != std::string::npos); + // ir and irOptimized works if selected at the same time, of course. + result = compiler.compile(generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"ir", "irOptimized"}))); + BOOST_REQUIRE(result.contains("contracts")); + BOOST_REQUIRE(result.dump().find("/// ethdebug: enabled") != std::string::npos); + // output selection "ethdebug" only works with via-ir, even if "ir" and "irOptimized" was selected. + result = compiler.compile(generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"ir", "irOptimized", "evm.bytecode.ethdebug"}))); + BOOST_REQUIRE(result["errors"].size() == 1); + result = compiler.compile(generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"ir", "irOptimized", "evm.bytecode.ethdebug"}))); + BOOST_REQUIRE(result.contains("contracts")); + BOOST_REQUIRE(result.dump().find("/// ethdebug: enabled") != std::string::npos); + BOOST_REQUIRE(result.contains("ethdebug")); + BOOST_REQUIRE(result["contracts"]["fileA"]["C"]["evm"]["bytecode"].contains("ethdebug")); + result = compiler.compile(generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"ir", "irOptimized", "evm.deployedBytecode.ethdebug"}))); + BOOST_REQUIRE(result["errors"].size() == 1); + result = compiler.compile(generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"ir", "irOptimized", "evm.deployedBytecode.ethdebug"}))); + BOOST_REQUIRE(result.contains("contracts")); + BOOST_REQUIRE(result.dump().find("/// ethdebug: enabled") != std::string::npos); + BOOST_REQUIRE(result.contains("ethdebug")); + BOOST_REQUIRE(result["contracts"]["fileA"]["C"]["evm"]["deployedBytecode"].contains("ethdebug")); + // debug-info ethdebug always works with yul + result = compiler.compile(generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"*"}), YulCode())); + BOOST_REQUIRE(result.contains("contracts")); + BOOST_REQUIRE(result.dump().find("/// ethdebug: enabled") != std::string::npos); + // debug-info ethdebug only supported for languages Solidity and Yul. + result = compiler.compile(generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"*"}), EvmAssemblyCode())); + BOOST_REQUIRE(result["errors"].size() == 1); + result = compiler.compile(generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"*"}), SolidityAstCode())); + BOOST_REQUIRE(result["errors"].size() == 1); +} + +BOOST_AUTO_TEST_CASE(ethdebug_ethdebug_output) +{ + frontend::StandardCompiler compiler; + // if no debug-info was selected, it implicitly set debug-info to ethdebug. + Json result = compiler.compile(generateStandardJson(true, std::nullopt, Json::array({"evm.deployedBytecode.ethdebug", "ir"}))); + BOOST_REQUIRE(result.contains("contracts")); + BOOST_REQUIRE(result.dump().find("/// ethdebug: enabled") != std::string::npos); + result = compiler.compile(generateStandardJson(true, std::nullopt, Json::array({"evm.bytecode.ethdebug", "ir"}))); + BOOST_REQUIRE(result.contains("contracts")); + BOOST_REQUIRE(result.dump().find("/// ethdebug: enabled") != std::string::npos); + // if via-ir was not specified, it will error with a message stating that ethdebug can only be selected as output, if via-ir was defined. solc --ethdebug only works with --via-ir + result = compiler.compile(generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"}))); + BOOST_REQUIRE(result["errors"].size() == 1); + result = compiler.compile(generateStandardJson(false, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"}))); + BOOST_REQUIRE(result["errors"].size() == 1); + // via-ir enabled, everything is fine: + result = compiler.compile(generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.bytecode.ethdebug"}))); + BOOST_REQUIRE(result.contains("contracts")); + result = compiler.compile(generateStandardJson(true, Json::array({"ethdebug"}), Json::array({"evm.deployedBytecode.ethdebug"}))); + BOOST_REQUIRE(result.contains("contracts")); + // if debug-info was selected and did not contain ethdebug, an error will be generated stating that ethdebug need to be set in debug-info solc --ethdebug --debug-info location + result = compiler.compile(generateStandardJson(false, Json::array({"all"}), Json::array({"evm.bytecode.ethdebug"}))); + BOOST_REQUIRE(result["errors"].size() == 1); + result = compiler.compile(generateStandardJson(false, Json::array({"all"}), Json::array({"evm.deployedBytecode.ethdebug"}))); + BOOST_REQUIRE(result["errors"].size() == 1); + // strict-assembly will always work e.g. solc --strict-assembly --ethdebug + result = compiler.compile(generateStandardJson(false, std::nullopt, Json::array({"evm.bytecode.ethdebug"}), YulCode())); + BOOST_REQUIRE(result.contains("contracts")); + BOOST_REQUIRE(result.dump().find("ethdebug") != std::string::npos); +} + BOOST_AUTO_TEST_SUITE_END() } // end namespaces diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 8980adcb1821..d365280b84fd 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -59,7 +59,7 @@ std::pair, std::shared_ptr> yul solidity::test::CommonOptions::get().optimize ? solidity::frontend::OptimiserSettings::standard() : solidity::frontend::OptimiserSettings::minimal(), - DebugInfoSelection::All() + DebugInfoSelection::ExceptExperimental() ); if (!stack.parseAndAnalyze("", _source) || !stack.errors().empty()) BOOST_FAIL("Invalid source."); diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index 4c2eecab05fe..685187b07699 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -57,7 +57,7 @@ TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::strin std::nullopt, YulStack::Language::StrictAssembly, settings, - DebugInfoSelection::All() + DebugInfoSelection::ExceptExperimental() ); if (!stack.parseAndAnalyze("", m_source)) { diff --git a/test/libyul/ObjectCompilerTest.cpp b/test/libyul/ObjectCompilerTest.cpp index 5d6dd1b23dea..215f26b934e9 100644 --- a/test/libyul/ObjectCompilerTest.cpp +++ b/test/libyul/ObjectCompilerTest.cpp @@ -69,7 +69,7 @@ TestCase::TestResult ObjectCompilerTest::run(std::ostream& _stream, std::string std::nullopt, YulStack::Language::StrictAssembly, OptimiserSettings::preset(m_optimisationPreset), - DebugInfoSelection::All() + DebugInfoSelection::ExceptExperimental() ); if (!stack.parseAndAnalyze("source", m_source)) { diff --git a/test/libyul/ObjectParser.cpp b/test/libyul/ObjectParser.cpp index b23e530601da..f08e23489618 100644 --- a/test/libyul/ObjectParser.cpp +++ b/test/libyul/ObjectParser.cpp @@ -60,7 +60,7 @@ std::pair parse(std::string const& _source) solidity::test::CommonOptions::get().eofVersion(), YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::none(), - DebugInfoSelection::All() + DebugInfoSelection::ExceptExperimental() ); bool success = asmStack.parseAndAnalyze("source", _source); return {success, asmStack.errors()}; @@ -177,7 +177,7 @@ BOOST_AUTO_TEST_CASE(to_string) solidity::test::CommonOptions::get().eofVersion(), YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::none(), - DebugInfoSelection::All() + DebugInfoSelection::ExceptExperimental() ); BOOST_REQUIRE(asmStack.parseAndAnalyze("source", code)); BOOST_CHECK_EQUAL(asmStack.print(), expectation); diff --git a/test/libyul/YulInterpreterTest.cpp b/test/libyul/YulInterpreterTest.cpp index 9d4ccd81ba49..84c559e91f60 100644 --- a/test/libyul/YulInterpreterTest.cpp +++ b/test/libyul/YulInterpreterTest.cpp @@ -71,7 +71,7 @@ bool YulInterpreterTest::parse(std::ostream& _stream, std::string const& _linePr solidity::test::CommonOptions::get().eofVersion(), YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::none(), - DebugInfoSelection::All() + DebugInfoSelection::ExceptExperimental() ); if (stack.parseAndAnalyze("", m_source)) { diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index 6d19df01b3f8..14c1bc93c146 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -1412,6 +1412,148 @@ BOOST_AUTO_TEST_CASE(cli_include_paths_ambiguous_import) BOOST_REQUIRE(!result.success); } +BOOST_AUTO_TEST_CASE(cli_ethdebug_no_ethdebug_in_help) +{ + OptionsReaderAndMessages result = runCLI({"solc", "--help"}); + BOOST_REQUIRE(result.stdoutContent.find("ethdebug") == std::string::npos); +} + +BOOST_AUTO_TEST_CASE(cli_ethdebug_incompatible_outputs) +{ + TemporaryDirectory tempDir(TEST_CASE_NAME); + createFilesWithParentDirs({tempDir.path() / "input.sol"}); + // output selection "asm-json" not working with debug-info "ethdebug" or "ethdebug" output selection. + OptionsReaderAndMessages result = runCLI({"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", "--debug-info", "ethdebug", "--ir-ast-json", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", "--debug-info", "ethdebug", "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", "--debug-info", "ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", "--debug-info", "ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", "--debug-info", "ethdebug", "--asm-json", tempDir.path().string() + "/input.json"}, ""); + BOOST_REQUIRE(!result.success); + for (char const* ethdebug : {"--ethdebug", "--ethdebug-runtime"}) + { + result = runCLI({"solc", ethdebug, "--asm-json", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", "--via-ir", ethdebug, "--asm-json", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", "--via-ir", ethdebug, "--ir-ast-json", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", "--via-ir", ethdebug, "--ir-optimized-ast-json", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", ethdebug, "--import-asm-json", tempDir.path().string() + "/input.json"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", "--via-ir", ethdebug, "--asm-json", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(!result.success); + } +} + +BOOST_AUTO_TEST_CASE(cli_ethdebug_incompatible_input_modes) +{ + TemporaryDirectory tempDir(TEST_CASE_NAME); + createFilesWithParentDirs({tempDir.path() / "input.json"}); + OptionsReaderAndMessages result = runCLI({"solc", "--debug-info", "ethdebug", "--import-asm-json", tempDir.path().string() + "/input.json"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", "--debug-info", "ethdebug", "--ir", "--import-ast", tempDir.path().string() + "/input.json"}, ""); + BOOST_REQUIRE(!result.success); + for (char const* ethdebug : {"--ethdebug", "--ethdebug-runtime"}) + { + result = runCLI({"solc", ethdebug, "--via-ir", "--import-asm-json", tempDir.path().string() + "/input.json"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", ethdebug, "--via-ir", "--import-ast", tempDir.path().string() + "/input.json"}, ""); + BOOST_REQUIRE(!result.success); + } +} + +BOOST_AUTO_TEST_CASE(cli_ethdebug_debug_info_ethdebug) +{ + TemporaryDirectory tempDir(TEST_CASE_NAME); + createFilesWithParentDirs({tempDir.path() / "input.sol"}, "pragma solidity >=0.0; contract C { function f() public pure {} }"); + createFilesWithParentDirs({tempDir.path() / "input.yul"}, "{}"); + // --debug-info ethdebug only works with --ir, --ir-optimized and --ethdebug (--ethdebug always need --via-ir) + OptionsReaderAndMessages result = runCLI({"solc", "--debug-info", "ethdebug", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(!result.success); + // debug-info selection "ethdebug" only works, if "ir" and "irOptimized" was selected. + result = runCLI({"solc", "--debug-info", "ethdebug", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", "--debug-info", "ethdebug", "--ir", tempDir.path().string() + "/input.sol"}, ""); + // if --debug-info ethdebug was set, we will output a comment on top of the ir output, indicating that ethdebug was enabled, + // so we use this to check whether --debug-info ethdebug was implicitly enabled. + BOOST_REQUIRE(result.success); + BOOST_REQUIRE(result.stdoutContent.find("/// ethdebug: enabled") != std::string::npos); + result = runCLI({"solc", "--debug-info", "ethdebug", "--ir-optimized", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(result.success); + BOOST_REQUIRE(result.stdoutContent.find("/// ethdebug: enabled") != std::string::npos); + // --ethdebug only works, if --via-ir was defined + for (char const* ethdebug : {"--ethdebug", "--ethdebug-runtime"}) + { + result = runCLI({"solc", "--debug-info", "ethdebug", ethdebug, tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", "--debug-info", "ethdebug", ethdebug, "--via-ir", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(result.success); + if (strcmp(ethdebug, "--ethdebug") == 0) + BOOST_REQUIRE(result.stdoutContent.find("Debug Data:") != std::string::npos); + if (strcmp(ethdebug, "--ethdebug-runtime") == 0) + BOOST_REQUIRE(result.stdoutContent.find("Debug Data of the runtime part:") != std::string::npos); + } + // --debug-info ethdebug always works with --strict-assembly + result = runCLI({"solc", "--debug-info", "ethdebug", "--strict-assembly", tempDir.path().string() + "/input.yul"}, ""); + BOOST_REQUIRE(result.success); + BOOST_REQUIRE(result.stdoutContent.find("/// ethdebug: enabled") != std::string::npos); + // --debug-info ethdebug is excluded from --debug-info all + result = runCLI({"solc", "--debug-info", "all", "--strict-assembly", tempDir.path().string() + "/input.yul"}, ""); + BOOST_REQUIRE(result.success); + BOOST_REQUIRE(result.stdoutContent.find("/// ethdebug: enabled") == std::string::npos); +} + +BOOST_AUTO_TEST_CASE(cli_ethdebug_ethdebug_output) +{ + TemporaryDirectory tempDir(TEST_CASE_NAME); + createFilesWithParentDirs({tempDir.path() / "input.sol"}, "pragma solidity >=0.0; contract C { function f() public pure {} }"); + for (char const* ethdebug : {"--ethdebug", "--ethdebug-runtime"}) + { + // --ethdebug only works with --via-ir + OptionsReaderAndMessages result = runCLI({"solc", ethdebug, tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", ethdebug, "--via-ir", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(result.success); + if (strcmp(ethdebug, "--ethdebug") == 0) + BOOST_REQUIRE(result.stdoutContent.find("Debug Data:") != std::string::npos); + if (strcmp(ethdebug, "--ethdebug-runtime") == 0) + BOOST_REQUIRE(result.stdoutContent.find("Debug Data of the runtime part:") != std::string::npos); + result = runCLI({"solc", ethdebug, "--via-ir", "--ir", tempDir.path().string() + "/input.sol"}, ""); + // --ethdebug will implicitly set --debug-info ethdebug, if no --debug-info was set. + // right now, if --debug-info ethdebug was set, we will output a comment on top of the ir output, indicating that ethdebug was enabled, + // so we use this to check whether --debug-info ethdebug was implicitly enabled. + BOOST_REQUIRE(result.success); + BOOST_REQUIRE(result.stdoutContent.find("/// ethdebug: enabled") != std::string::npos); + // let's just do the same for --ir-optimized + result = runCLI({"solc", ethdebug, "--via-ir", "--ir-optimized", "--optimize", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(result.success); + BOOST_REQUIRE(result.stdoutContent.find("/// ethdebug: enabled") != std::string::npos); + // --ethdebug only works with --via-ir. + result = runCLI({"solc", "--debug-info", "ethdebug", ethdebug, tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", "--debug-info", "ethdebug", ethdebug, "--via-ir", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(result.success); + // --ethdebug only works, if --debug-info was not set to something else as "ethdebug". + result = runCLI({"solc", "--debug-info", "location", ethdebug, "--via-ir", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", "--debug-info", "all", ethdebug, "--via-ir", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(!result.success); + result = runCLI({"solc", "--debug-info", "ethdebug", ethdebug, "--via-ir", tempDir.path().string() + "/input.sol"}, ""); + BOOST_REQUIRE(result.success); + } +} + BOOST_AUTO_TEST_SUITE_END() } // namespace solidity::frontend::test diff --git a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp index 595aecdca3f4..5df804388cd8 100644 --- a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp @@ -41,7 +41,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) std::nullopt, YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::minimal(), - langutil::DebugInfoSelection::All() + langutil::DebugInfoSelection::ExceptExperimental() ); if (!stack.parseAndAnalyze("source", input)) diff --git a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp index f685aa90da4b..d477f0736e70 100644 --- a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp @@ -65,7 +65,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) std::nullopt, YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::full(), - DebugInfoSelection::All() + DebugInfoSelection::ExceptExperimental() ); try { diff --git a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp index 7553c81c0f44..42bb78d49894 100644 --- a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp @@ -42,7 +42,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) std::nullopt, YulStack::Language::StrictAssembly, solidity::frontend::OptimiserSettings::full(), - DebugInfoSelection::All() + DebugInfoSelection::ExceptExperimental() ); if (!stack.parseAndAnalyze("source", input)) From 94f97169ab9a288d0ea4d8e49e0798855a20a3e7 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Thu, 15 Feb 2024 21:47:11 +0100 Subject: [PATCH 2/3] [yul] Add support for parsing debug data attributes. --- liblangutil/DebugData.h | 16 +- libsolutil/CMakeLists.txt | 1 + libsolutil/Cache.h | 126 +++++++++++++ libyul/AsmParser.cpp | 148 ++++++++++++++-- libyul/AsmParser.h | 32 +++- test/CMakeLists.txt | 1 + .../ethdebug_large_debug_attributes/args | 1 + .../ethdebug_large_debug_attributes/input.yul | 16 ++ .../ethdebug_large_debug_attributes/output | 26 +++ test/libsolutil/Cache.cpp | 166 ++++++++++++++++++ test/libyul/Parser.cpp | 66 ++++++- .../invalid/invalid_debug_merge.yul | 7 + .../invalid/invalid_debug_patch.yul | 7 + .../invalid_debug_patch_patch_object.yul | 7 + .../invalid/invalid_debug_set.yul | 7 + 15 files changed, 599 insertions(+), 28 deletions(-) create mode 100644 libsolutil/Cache.h create mode 100644 test/cmdlineTests/ethdebug_large_debug_attributes/args create mode 100644 test/cmdlineTests/ethdebug_large_debug_attributes/input.yul create mode 100644 test/cmdlineTests/ethdebug_large_debug_attributes/output create mode 100644 test/libsolutil/Cache.cpp create mode 100644 test/libyul/yulSyntaxTests/invalid/invalid_debug_merge.yul create mode 100644 test/libyul/yulSyntaxTests/invalid/invalid_debug_patch.yul create mode 100644 test/libyul/yulSyntaxTests/invalid/invalid_debug_patch_patch_object.yul create mode 100644 test/libyul/yulSyntaxTests/invalid/invalid_debug_set.yul diff --git a/liblangutil/DebugData.h b/liblangutil/DebugData.h index 70259bd039f3..9e58d9f37794 100644 --- a/liblangutil/DebugData.h +++ b/liblangutil/DebugData.h @@ -19,6 +19,7 @@ #pragma once #include +#include #include #include @@ -28,27 +29,32 @@ namespace solidity::langutil struct DebugData { typedef typename std::shared_ptr ConstPtr; + typedef std::optional>> Attributes; explicit DebugData( langutil::SourceLocation _nativeLocation = {}, langutil::SourceLocation _originLocation = {}, - std::optional _astID = {} + std::optional _astID = {}, + Attributes _attributes = {} ): nativeLocation(std::move(_nativeLocation)), originLocation(std::move(_originLocation)), - astID(_astID) + astID(_astID), + attributes(std::move(_attributes)) {} static DebugData::ConstPtr create( langutil::SourceLocation _nativeLocation, langutil::SourceLocation _originLocation = {}, - std::optional _astID = {} + std::optional _astID = {}, + Attributes _attributes = {} ) { return std::make_shared( std::move(_nativeLocation), std::move(_originLocation), - _astID + _astID, + std::move(_attributes) ); } @@ -65,6 +71,8 @@ struct DebugData langutil::SourceLocation originLocation; /// ID in the (Solidity) source AST. std::optional astID; + /// Additional debug data attributes. + Attributes attributes; }; } // namespace solidity::langutil diff --git a/libsolutil/CMakeLists.txt b/libsolutil/CMakeLists.txt index a1e9559edef0..7382cbbc3b61 100644 --- a/libsolutil/CMakeLists.txt +++ b/libsolutil/CMakeLists.txt @@ -2,6 +2,7 @@ set(sources Algorithms.h AnsiColorized.h Assertions.h + Cache.h Common.h CommonData.cpp CommonData.h diff --git a/libsolutil/Cache.h b/libsolutil/Cache.h new file mode 100644 index 000000000000..4ec1e2e0aa95 --- /dev/null +++ b/libsolutil/Cache.h @@ -0,0 +1,126 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 +/** @file Cache.h + * @date 2024 + * + * Simple cache. + */ + +#pragma once + +#include + +#include +#include +#include + +#include + +#include + +namespace solidity::util +{ + +namespace detail +{ + +template typename TCache ,typename THash, typename TValue> +class CacheBase +{ +public: + typedef THash Hash; + typedef TValue Value; + typedef TCache Cache; + typedef std::shared_ptr Entry; + typedef std::shared_ptr Ptr; + + Entry set(Hash const& hash, Value const& value) + { + Entry result; + if (m_cache.find(hash) == m_cache.end()) + { + result = std::make_shared(value); + auto [_, inserted] = m_cache.emplace(std::make_pair(hash, result)); + solAssert(inserted); + } + else + result = m_cache[hash]; + return result; + } + + Entry set(Value const& value) { return set(Cache::hash(value), value); } + + std::map const& cache() { return m_cache; } + + typename std::map::iterator get(Hash const& hash) { return m_cache.find(hash); } + + typename std::map::iterator begin() { return m_cache.begin(); } + + typename std::map::iterator end() { return m_cache.end(); } + +private: + std::map m_cache; +}; + +} // namespace detail + +template +class Cache; + +template +class Cache: public detail::CacheBase +{ +public: + static size_t hash(TValue const& value) + { + boost::hash hasher; + return hasher(value); + } +}; + +template +class Cache: public detail::CacheBase +{ +public: + static h256 hash(TValue const& value) + { + std::stringstream stream; + stream << value; + return keccak256(stream.str()); + } +}; + +template<> +class Cache: public detail::CacheBase +{ +public: + static size_t hash(Json const& value) + { + boost::hash hasher; + return hasher(value.dump(0)); + } +}; + +template<> +class Cache: public detail::CacheBase +{ +public: + static h256 hash(Json const& value) { return keccak256(value.dump(0)); } +}; + +} // namespace solidity::util diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index d41b41a36a42..f6df876dd3da 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -62,14 +62,36 @@ std::optional toInt(std::string const& _value) langutil::DebugData::ConstPtr Parser::createDebugData() const { + solAssert(m_debugAttributeCache); switch (m_useSourceLocationFrom) { - case UseSourceLocationFrom::Scanner: - return DebugData::create(ParserBase::currentLocation(), ParserBase::currentLocation()); - case UseSourceLocationFrom::LocationOverride: - return DebugData::create(m_locationOverride, m_locationOverride); - case UseSourceLocationFrom::Comments: - return DebugData::create(ParserBase::currentLocation(), m_locationFromComment, m_astIDFromComment); + case UseSourceLocationFrom::Scanner: + return DebugData::create( + ParserBase::currentLocation(), + ParserBase::currentLocation(), + {}, + m_currentDebugAttributes.has_value() + ? DebugData::Attributes({m_debugAttributeCache->set(*m_currentDebugAttributes)}) + : DebugData::Attributes({}) + ); + case UseSourceLocationFrom::LocationOverride: + return DebugData::create( + m_locationOverride, + m_locationOverride, + {}, + m_currentDebugAttributes.has_value() + ? DebugData::Attributes({m_debugAttributeCache->set(*m_currentDebugAttributes)}) + : DebugData::Attributes({}) + ); + case UseSourceLocationFrom::Comments: + return DebugData::create( + ParserBase::currentLocation(), + m_locationFromComment, + m_astIDFromComment, + m_currentDebugAttributes.has_value() + ? DebugData::Attributes({m_debugAttributeCache->set(*m_currentDebugAttributes)}) + : DebugData::Attributes({}) + ); } solAssert(false, ""); } @@ -138,24 +160,20 @@ std::unique_ptr Parser::parseInline(std::shared_ptr const& _scanne langutil::Token Parser::advance() { auto const token = ParserBase::advance(); - if (m_useSourceLocationFrom == UseSourceLocationFrom::Comments) - fetchDebugDataFromComment(); + fetchDebugDataFromComment(); return token; } void Parser::fetchDebugDataFromComment() { - solAssert(m_sourceNames.has_value(), ""); - static std::regex const tagRegex = std::regex( - R"~~((?:^|\s+)(@[a-zA-Z0-9\-_]+)(?:\s+|$))~~", // tag, e.g: @src + R"~~((?:^|\s+)(@[a-zA-Z0-9\-\._]+)(?:\s+|$))~~", // tag, e.g: @src std::regex_constants::ECMAScript | std::regex_constants::optimize ); std::string_view commentLiteral = m_scanner->currentCommentLiteral(); std::match_results match; - langutil::SourceLocation originLocation = m_locationFromComment; // Empty for each new node. std::optional astID; @@ -166,10 +184,14 @@ void Parser::fetchDebugDataFromComment() if (match[1] == "@src") { - if (auto parseResult = parseSrcComment(commentLiteral, m_scanner->currentCommentLocation())) - tie(commentLiteral, originLocation) = *parseResult; - else - break; + if (m_useSourceLocationFrom == UseSourceLocationFrom::Comments) + { + solAssert(m_sourceNames.has_value(), ""); + if (auto parseResult = parseSrcComment(commentLiteral, m_scanner->currentCommentLocation())) + tie(commentLiteral, m_locationFromComment) = *parseResult; + else + break; + } } else if (match[1] == "@ast-id") { @@ -178,15 +200,107 @@ void Parser::fetchDebugDataFromComment() else break; } + else if (match[1] == "@debug.set") + { + if (auto parseResult = parseDebugDataAttributeOperationComment(match[1], commentLiteral, m_scanner->currentCommentLocation())) + { + commentLiteral = parseResult->first; + if (parseResult->second.has_value()) + m_currentDebugAttributes = parseResult->second.value(); + } + else + break; + } + else if (match[1] == "@debug.merge") + { + if (auto parseResult = parseDebugDataAttributeOperationComment(match[1], commentLiteral, m_scanner->currentCommentLocation())) + { + commentLiteral = parseResult->first; + if (parseResult->second.has_value()) + { + if (!m_currentDebugAttributes.has_value()) + m_currentDebugAttributes = Json::object(); + m_currentDebugAttributes->merge_patch(parseResult->second.value()); + } + } + else + break; + } + else if (match[1] == "@debug.patch") + { + if (auto parseResult = parseDebugDataAttributeOperationComment(match[1], commentLiteral, m_scanner->currentCommentLocation())) + { + commentLiteral = parseResult->first; + if (parseResult->second.has_value()) + applyDebugDataAttributePatch(parseResult->second.value(), m_scanner->currentCommentLocation()); + } + else + break; + } else // Ignore unrecognized tags. continue; } - m_locationFromComment = originLocation; m_astIDFromComment = astID; } +std::optional>> Parser::parseDebugDataAttributeOperationComment( + std::string const& _command, + std::string_view _arguments, + langutil::SourceLocation const& _location +) +{ + std::optional jsonData; + try + { + jsonData = Json::parse(_arguments.begin(), _arguments.end(), nullptr, true); + } + catch (nlohmann::json::parse_error& e) + { + try + { + jsonData = Json::parse(_arguments.substr(0, e.byte - 1), nullptr, true); + } + catch(nlohmann::json::parse_error& ee) + { + m_errorReporter.syntaxError( + 5721_error, + _location, + _command + ": Could not parse debug data: " + removeNlohmannInternalErrorIdentifier(ee.what()) + ); + jsonData.reset(); + } + _arguments = _arguments.substr(e.byte - 1); + } + return {{_arguments, jsonData}}; +} + +void Parser::applyDebugDataAttributePatch(Json const& _jsonPatch, langutil::SourceLocation const& _location) +{ + try + { + if (!m_currentDebugAttributes.has_value()) + m_currentDebugAttributes = Json::object(); + if (_jsonPatch.is_object()) + { + Json array = Json::array(); + array.push_back(_jsonPatch); + m_currentDebugAttributes = m_currentDebugAttributes->patch(array); + } + else + m_currentDebugAttributes = m_currentDebugAttributes->patch(_jsonPatch); + } + catch(nlohmann::json::parse_error& ee) + { + m_errorReporter.syntaxError( + 9426_error, + _location, + "@debug.patch: Could not patch debug data: " + removeNlohmannInternalErrorIdentifier(ee.what()) + ); + } +} + std::optional> Parser::parseSrcComment( std::string_view const _arguments, langutil::SourceLocation const& _commentLocation diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index d4616a2a9508..e4a6b51bd9fe 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -31,10 +31,11 @@ #include #include +#include + #include #include #include -#include #include namespace solidity::yul @@ -43,6 +44,8 @@ namespace solidity::yul class Parser: public langutil::ParserBase { public: + typedef util::Cache DebugAttributeCache; + enum class ForLoopComponent { None, ForLoopPre, ForLoopPost, ForLoopBody @@ -56,7 +59,8 @@ class Parser: public langutil::ParserBase explicit Parser( langutil::ErrorReporter& _errorReporter, Dialect const& _dialect, - std::optional _locationOverride = {} + std::optional _locationOverride = {}, + DebugAttributeCache::Ptr debugAttributesCache = {} ): ParserBase(_errorReporter), m_dialect(_dialect), @@ -65,7 +69,8 @@ class Parser: public langutil::ParserBase _locationOverride ? UseSourceLocationFrom::LocationOverride : UseSourceLocationFrom::Scanner - } + }, + m_debugAttributeCache(debugAttributesCache == nullptr ? std::make_shared() : debugAttributesCache) {} /// Constructs a Yul parser that is using the debug data @@ -73,7 +78,8 @@ class Parser: public langutil::ParserBase explicit Parser( langutil::ErrorReporter& _errorReporter, Dialect const& _dialect, - std::optional>> _sourceNames + std::optional>> _sourceNames, + DebugAttributeCache::Ptr debugAttributesCache = {} ): ParserBase(_errorReporter), m_dialect(_dialect), @@ -82,7 +88,8 @@ class Parser: public langutil::ParserBase m_sourceNames.has_value() ? UseSourceLocationFrom::Comments : UseSourceLocationFrom::Scanner - } + }, + m_debugAttributeCache(debugAttributesCache == nullptr ? std::make_shared() : debugAttributesCache) {} /// Parses an inline assembly block starting with `{` and ending with `}`. @@ -117,6 +124,14 @@ class Parser: public langutil::ParserBase langutil::SourceLocation const& _commentLocation ); + std::optional>> parseDebugDataAttributeOperationComment( + std::string const& _command, + std::string_view _arguments, + langutil::SourceLocation const& _commentLocation + ); + + void applyDebugDataAttributePatch(Json const& _jsonPatch, langutil::SourceLocation const& _location); + /// Creates a DebugData object with the correct source location set. langutil::DebugData::ConstPtr createDebugData() const; @@ -154,6 +169,11 @@ class Parser: public langutil::ParserBase static bool isValidNumberLiteral(std::string const& _literal); + DebugAttributeCache::Ptr debugAttributeCache() const + { + return m_debugAttributeCache; + } + private: Dialect const& m_dialect; @@ -164,6 +184,8 @@ class Parser: public langutil::ParserBase UseSourceLocationFrom m_useSourceLocationFrom = UseSourceLocationFrom::Scanner; ForLoopComponent m_currentForLoopComponent = ForLoopComponent::None; bool m_insideFunction = false; + std::optional m_currentDebugAttributes; + mutable DebugAttributeCache::Ptr m_debugAttributeCache; }; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5308a55f7826..1a3cb4950257 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -28,6 +28,7 @@ set(contracts_sources detect_stray_source_files("${contracts_sources}" "contracts/") set(libsolutil_sources + libsolutil/Cache.cpp libsolutil/Checksum.cpp libsolutil/CommonData.cpp libsolutil/CommonIO.cpp diff --git a/test/cmdlineTests/ethdebug_large_debug_attributes/args b/test/cmdlineTests/ethdebug_large_debug_attributes/args new file mode 100644 index 000000000000..2c89c24e0a35 --- /dev/null +++ b/test/cmdlineTests/ethdebug_large_debug_attributes/args @@ -0,0 +1 @@ +--strict-assembly diff --git a/test/cmdlineTests/ethdebug_large_debug_attributes/input.yul b/test/cmdlineTests/ethdebug_large_debug_attributes/input.yul new file mode 100644 index 000000000000..42b90b56d3ba --- /dev/null +++ b/test/cmdlineTests/ethdebug_large_debug_attributes/input.yul @@ -0,0 +1,16 @@ +object "a" { + code { + /// @debug.set { + /// "A": "B", + /// "C": "........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", + /// "D": "........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................" + /// } + let addr := linkersymbol("contract/test.sol:L") + /// @debug.merge { + /// "E": "........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", + /// "F": "G", + /// "H": "........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................" + /// } + sstore(0, addr) + } +} diff --git a/test/cmdlineTests/ethdebug_large_debug_attributes/output b/test/cmdlineTests/ethdebug_large_debug_attributes/output new file mode 100644 index 000000000000..ad74f2ebeede --- /dev/null +++ b/test/cmdlineTests/ethdebug_large_debug_attributes/output @@ -0,0 +1,26 @@ + +======= ethdebug_large_debug_attributes/input.yul (EVM) ======= + +Pretty printed source: +object "a" { + code { + { + let addr := linkersymbol("contract/test.sol:L") + sstore(0, addr) + } + } +} + + +Binary representation: +73__$f919ba91ac99f96129544b80b9516b27a8$__5f5500 + +Text representation: + /* "ethdebug_large_debug_attributes/input.yul":54152:54187 */ + linkerSymbol("f919ba91ac99f96129544b80b9516b27a80e376b9dc693819d0b18b7e0395612") + /* "ethdebug_large_debug_attributes/input.yul":108313:108314 */ + 0x00 + /* "ethdebug_large_debug_attributes/input.yul":108306:108321 */ + sstore + /* "ethdebug_large_debug_attributes/input.yul":22:108327 */ + stop diff --git a/test/libsolutil/Cache.cpp b/test/libsolutil/Cache.cpp new file mode 100644 index 000000000000..eba1f62f887b --- /dev/null +++ b/test/libsolutil/Cache.cpp @@ -0,0 +1,166 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 +/** + * @date 2024 + * Unit tests for libsolutil/Cache.h. + */ + +#include +#include + +#include + +#include + + +namespace solidity::util::test +{ + +BOOST_AUTO_TEST_SUITE(CacheTest, *boost::unit_test::label("nooptions")) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + Cache::Entry cached_int; + Cache int_cache; + cached_int = int_cache.set(45); + BOOST_CHECK(int_cache.set(45) == cached_int); + BOOST_CHECK(int_cache.set(46) == int_cache.set(46)); + + Cache h256_int_cache; + cached_int = h256_int_cache.set(45); + BOOST_CHECK(h256_int_cache.set(45) == cached_int); + BOOST_CHECK(h256_int_cache.set(46) == h256_int_cache.set(46)); + + Cache string_cache; + std::shared_ptr cached_string = string_cache.set(""); + BOOST_CHECK(string_cache.set("") == cached_string); + BOOST_CHECK(string_cache.set("hello") == string_cache.set("hello")); + + Cache h256_string_cache; + cached_string = h256_string_cache.set(""); + BOOST_CHECK(h256_string_cache.set("") == cached_string); + BOOST_CHECK(h256_string_cache.set("hello") == h256_string_cache.set("hello")); + + Cache h256_json_cache; + Cache::Entry cached_json = h256_json_cache.set({}); + BOOST_CHECK(h256_json_cache.set({}) == cached_json); + BOOST_CHECK(h256_json_cache.set({{"a", "b"}}) == h256_json_cache.set({{"a", "b"}})); + + Cache json_cache; + cached_json = json_cache.set({}); + BOOST_CHECK(json_cache.set({}) == cached_json); + BOOST_CHECK(json_cache.set({{"a", "b"}}) == json_cache.set({{"a", "b"}})); + + Cache::Ptr json_cache_ptr = std::make_shared>(); + cached_json = json_cache_ptr->set({}); + BOOST_CHECK(json_cache_ptr->set({}) == cached_json); + BOOST_CHECK(json_cache_ptr->set({{"a", "b"}}) == json_cache_ptr->set({{"a", "b"}})); + + Cache::Ptr h256_json_cache_ptr = std::make_shared>(); + cached_json = h256_json_cache_ptr->set({}); + BOOST_CHECK(h256_json_cache_ptr->set({}) == cached_json); + BOOST_CHECK(h256_json_cache_ptr->set({{"a", "b"}}) == h256_json_cache_ptr->set({{"a", "b"}})); +} + +BOOST_AUTO_TEST_CASE(cache_hash_get) +{ + auto test = [](auto _value0, auto _hash0, auto _value1, auto _hash1) -> void + { + typedef decltype(_hash0) Hash; + typedef decltype(_value0) Value; + static_assert( + std::is_same_v, "types of _hash0 and _hash1 need to be the same" + ); + static_assert( + std::is_same_v, + "types of _value0 and _value1 need to be the same" + ); + typename Cache::Ptr cache = std::make_shared>(); + Hash hash0 = cache->hash(_value0); + Hash hash1 = cache->hash(_value1); + BOOST_CHECK_EQUAL(hash0, _hash0); + BOOST_CHECK_EQUAL(hash1, _hash1); + BOOST_CHECK(cache->get(_hash0) == cache->end()); + BOOST_CHECK(cache->get(_hash1) == cache->end()); + cache->set(_value0); + BOOST_CHECK(cache->get(_hash0) != cache->end()); + BOOST_CHECK(*(cache->get(_hash0)->second) == _value0); + BOOST_CHECK(cache->get(hash1) == cache->end()); + cache->set(_value1); + BOOST_CHECK(cache->get(hash1) != cache->end()); + BOOST_CHECK(*(cache->get(hash1)->second) == _value1); + }; + test(0, static_cast(0), 1, static_cast(1)); + test(0.1f, static_cast(1036831949), 0.2f, static_cast(1045220557)); + test(0.1, static_cast(4591870180066957722), 0.2, static_cast(4596373779694328218)); + test( + "", + // different boost versions seem to return different hashes for strings, so we just calculate the correct hashes here. + Cache::hash(""), + "HELLO WORLD", + Cache::hash("HELLO WORLD") + ); + test( + std::string(), + // different boost versions seem to return different hashes for strings, so we just calculate the correct hashes here. + Cache::hash(std::string()), + std::string("HELLO WORLD"), + Cache::hash("HELLO WORLD") + ); + test( + Json{}, + // different boost versions seem to return different hashes for strings, so we just calculate the correct hashes here. + Cache::hash(Json{}), + Json{{"HELLO", "WORLD"}}, + Cache::hash(Json{{"HELLO", "WORLD"}}) + ); + test( + 0, + static_cast("044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d"), + 1, + static_cast("c89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6") + ); + test( + 0.1f, + static_cast("8cd160c72d102a6747abd189ac21d4a1f802e3fcc1bb8fc78cc4d558df0c7c21"), + 0.2f, + static_cast("c1907d585d0b0e66920f6383717e2e9e7c44e42ba86ef49b0e19983ffd702288") + ); + test( + 0.1, + static_cast("8cd160c72d102a6747abd189ac21d4a1f802e3fcc1bb8fc78cc4d558df0c7c21"), + 0.2, + static_cast("c1907d585d0b0e66920f6383717e2e9e7c44e42ba86ef49b0e19983ffd702288") + ); + test( + "", + static_cast("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"), + "HELLO WORLD", + static_cast("6c1223964c4674e3797678a0af4dee8b46a8ac1471d97cf37c136ce0937fa0df") + ); + test( + Json{}, + static_cast("efbde2c3aee204a69b7696d4b10ff31137fe78e3946306284f806e2dfc68b805"), + Json{{"HELLO", "WORLD"}}, + static_cast("90e22a3e1e4d820d1a76c04d130c08dd1cabb2c1d22ad7d582a0b5415d797bde") + ); +} + +BOOST_AUTO_TEST_SUITE_END() + +} diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 9b8ce42921b6..5636047dc3c7 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -54,7 +54,7 @@ namespace solidity::yul::test namespace { -std::shared_ptr parse(std::string const& _source, Dialect const& _dialect, ErrorReporter& errorReporter) +std::shared_ptr parse(std::string const& _source, Dialect const& _dialect, ErrorReporter& errorReporter, Parser::DebugAttributeCache::Ptr debugAttributesCache = {}) { auto stream = CharStream(_source, ""); std::map> indicesToSourceNames; @@ -64,7 +64,8 @@ std::shared_ptr parse(std::string const& _source, Dialect const& _dialect, auto parserResult = yul::Parser( errorReporter, _dialect, - std::move(indicesToSourceNames) + std::move(indicesToSourceNames), + std::move(debugAttributesCache) ).parse(stream); if (parserResult) { @@ -998,6 +999,67 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_multiple_src_tags_on_one_line) CHECK_LOCATION(varX.debugData->originLocation, "source1", 4, 5); } +BOOST_AUTO_TEST_CASE(ethdebug_debug_attributes_empty) +{ + Parser::DebugAttributeCache::Ptr cache = std::make_shared(); + ErrorList errorList; + ErrorReporter reporter(errorList); + auto const sourceText = R"( + {} + )"; + EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + std::shared_ptr result = parse(sourceText, dialect, reporter, cache); + BOOST_REQUIRE(cache->cache().size() == 0); +} + +BOOST_AUTO_TEST_CASE(ethdebug_debug_attributes_set_empty) +{ + Parser::DebugAttributeCache::Ptr cache = std::make_shared(); + ErrorList errorList; + ErrorReporter reporter(errorList); + auto const sourceText = R"( + /// @debug.set {} + {} + )"; + EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + std::shared_ptr result = parse(sourceText, dialect, reporter, cache); + BOOST_REQUIRE(cache->cache().size() == 1); +} + + +BOOST_AUTO_TEST_CASE(ethdebug_debug_attributes_set) +{ + Parser::DebugAttributeCache::Ptr cache = std::make_shared(); + ErrorList errorList; + ErrorReporter reporter(errorList); + auto const sourceText = R"( + /// @debug.set {"hello": "world"} + {} + )"; + EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + std::shared_ptr result = parse(sourceText, dialect, reporter, cache); + BOOST_REQUIRE(cache->cache().size() == 1); +} + +BOOST_AUTO_TEST_CASE(ethdebug_debug_attributes_multiple_set) +{ + Parser::DebugAttributeCache::Ptr cache = std::make_shared(); + ErrorList errorList; + ErrorReporter reporter(errorList); + auto const sourceText = R"( + /// @debug.set {"hello": "world"} + { + /// @debug.set {"hello": "world!"} + {} + /// @debug.set {"hello": "world"} + {} + } + )"; + EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + std::shared_ptr result = parse(sourceText, dialect, reporter, cache); + BOOST_REQUIRE(cache->cache().size() == 2); +} + BOOST_AUTO_TEST_SUITE_END() } // end namespaces diff --git a/test/libyul/yulSyntaxTests/invalid/invalid_debug_merge.yul b/test/libyul/yulSyntaxTests/invalid/invalid_debug_merge.yul new file mode 100644 index 000000000000..13200b008cb8 --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/invalid_debug_merge.yul @@ -0,0 +1,7 @@ +object "object" { + code { + /// @debug.merge {"HELLO": 2 + } +} +// ---- +// SyntaxError 5721: (37-65): @debug.merge: Could not parse debug data: parse error at line 1, column 12: syntax error while parsing object - unexpected end of input; expected '}' diff --git a/test/libyul/yulSyntaxTests/invalid/invalid_debug_patch.yul b/test/libyul/yulSyntaxTests/invalid/invalid_debug_patch.yul new file mode 100644 index 000000000000..3f1d15e962da --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/invalid_debug_patch.yul @@ -0,0 +1,7 @@ +object "object" { + code { + /// @debug.patch {"HELLO": invalid + } +} +// ---- +// SyntaxError 5721: (37-71): @debug.patch: Could not parse debug data: parse error at line 1, column 11: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal diff --git a/test/libyul/yulSyntaxTests/invalid/invalid_debug_patch_patch_object.yul b/test/libyul/yulSyntaxTests/invalid/invalid_debug_patch_patch_object.yul new file mode 100644 index 000000000000..a5c02823f27c --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/invalid_debug_patch_patch_object.yul @@ -0,0 +1,7 @@ +object "object" { + code { + /// @debug.patch { "op": "unknown_operation", "path": "/variable_a", "value": ["test"] } + } +} +// ---- +// SyntaxError 9426: (37-125): @debug.patch: Could not patch debug data: parse error: operation value 'unknown_operation' is invalid diff --git a/test/libyul/yulSyntaxTests/invalid/invalid_debug_set.yul b/test/libyul/yulSyntaxTests/invalid/invalid_debug_set.yul new file mode 100644 index 000000000000..3c99b7cb52bd --- /dev/null +++ b/test/libyul/yulSyntaxTests/invalid/invalid_debug_set.yul @@ -0,0 +1,7 @@ +object "object" { + code { + /// @debug.set {"HELLO": "WORLD + } +} +// ---- +// SyntaxError 5721: (37-68): @debug.set: Could not parse debug data: parse error at line 1, column 17: syntax error while parsing value - invalid string: missing closing quote; last read: '"WORLD' From 2bd86662a39592bb95878e99b77af14be89a23b4 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Wed, 4 Sep 2024 16:56:43 +0200 Subject: [PATCH 3/3] Debug attributes get only parsed, if debug attribute cache was set. --- libyul/AsmParser.cpp | 27 ++++++++++--------- libyul/AsmParser.h | 7 ++--- libyul/ObjectParser.cpp | 2 +- libyul/ObjectParser.h | 8 +++--- libyul/YulStack.cpp | 2 +- libyul/YulStack.h | 8 ++++-- test/libyul/Common.cpp | 15 ++++++++--- test/libyul/Common.h | 6 +++-- test/libyul/Parser.cpp | 9 ++++--- test/libyul/SyntaxTest.cpp | 5 +++- test/libyul/SyntaxTest.h | 8 +++++- .../invalid/invalid_debug_merge.yul | 2 ++ .../invalid/invalid_debug_patch.yul | 2 ++ .../invalid_debug_patch_patch_object.yul | 2 ++ .../invalid/invalid_debug_set.yul | 2 ++ 15 files changed, 70 insertions(+), 35 deletions(-) diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index f6df876dd3da..4eec48085779 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -62,7 +62,6 @@ std::optional toInt(std::string const& _value) langutil::DebugData::ConstPtr Parser::createDebugData() const { - solAssert(m_debugAttributeCache); switch (m_useSourceLocationFrom) { case UseSourceLocationFrom::Scanner: @@ -70,27 +69,27 @@ langutil::DebugData::ConstPtr Parser::createDebugData() const ParserBase::currentLocation(), ParserBase::currentLocation(), {}, - m_currentDebugAttributes.has_value() - ? DebugData::Attributes({m_debugAttributeCache->set(*m_currentDebugAttributes)}) - : DebugData::Attributes({}) + m_debugAttributeCache + ? m_currentDebugAttributes.has_value() ? DebugData::Attributes({m_debugAttributeCache->set(*m_currentDebugAttributes)}) : DebugData::Attributes({}) + : std::nullopt ); case UseSourceLocationFrom::LocationOverride: return DebugData::create( m_locationOverride, m_locationOverride, {}, - m_currentDebugAttributes.has_value() - ? DebugData::Attributes({m_debugAttributeCache->set(*m_currentDebugAttributes)}) - : DebugData::Attributes({}) + m_debugAttributeCache + ? m_currentDebugAttributes.has_value() ? DebugData::Attributes({m_debugAttributeCache->set(*m_currentDebugAttributes)}) : DebugData::Attributes({}) + : std::nullopt ); case UseSourceLocationFrom::Comments: return DebugData::create( ParserBase::currentLocation(), m_locationFromComment, m_astIDFromComment, - m_currentDebugAttributes.has_value() - ? DebugData::Attributes({m_debugAttributeCache->set(*m_currentDebugAttributes)}) - : DebugData::Attributes({}) + m_debugAttributeCache + ? m_currentDebugAttributes.has_value() ? DebugData::Attributes({m_debugAttributeCache->set(*m_currentDebugAttributes)}) : DebugData::Attributes({}) + : std::nullopt ); } solAssert(false, ""); @@ -200,7 +199,7 @@ void Parser::fetchDebugDataFromComment() else break; } - else if (match[1] == "@debug.set") + else if (match[1] == "@debug.set" && m_debugAttributeCache) { if (auto parseResult = parseDebugDataAttributeOperationComment(match[1], commentLiteral, m_scanner->currentCommentLocation())) { @@ -211,7 +210,7 @@ void Parser::fetchDebugDataFromComment() else break; } - else if (match[1] == "@debug.merge") + else if (match[1] == "@debug.merge" && m_debugAttributeCache) { if (auto parseResult = parseDebugDataAttributeOperationComment(match[1], commentLiteral, m_scanner->currentCommentLocation())) { @@ -226,7 +225,7 @@ void Parser::fetchDebugDataFromComment() else break; } - else if (match[1] == "@debug.patch") + else if (match[1] == "@debug.patch" && m_debugAttributeCache) { if (auto parseResult = parseDebugDataAttributeOperationComment(match[1], commentLiteral, m_scanner->currentCommentLocation())) { @@ -251,6 +250,7 @@ std::optional>> Parser::parseDeb langutil::SourceLocation const& _location ) { + solAssert(m_debugAttributeCache, "debug attributes can only be used with valid debug attribute cache"); std::optional jsonData; try { @@ -278,6 +278,7 @@ std::optional>> Parser::parseDeb void Parser::applyDebugDataAttributePatch(Json const& _jsonPatch, langutil::SourceLocation const& _location) { + solAssert(m_debugAttributeCache, "debug attributes can only be used with valid debug attribute cache"); try { if (!m_currentDebugAttributes.has_value()) diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index e4a6b51bd9fe..85aae3641806 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -60,7 +61,7 @@ class Parser: public langutil::ParserBase langutil::ErrorReporter& _errorReporter, Dialect const& _dialect, std::optional _locationOverride = {}, - DebugAttributeCache::Ptr debugAttributesCache = {} + DebugAttributeCache::Ptr _debugAttributesCache = {} ): ParserBase(_errorReporter), m_dialect(_dialect), @@ -70,7 +71,7 @@ class Parser: public langutil::ParserBase UseSourceLocationFrom::LocationOverride : UseSourceLocationFrom::Scanner }, - m_debugAttributeCache(debugAttributesCache == nullptr ? std::make_shared() : debugAttributesCache) + m_debugAttributeCache(std::move(_debugAttributesCache)) {} /// Constructs a Yul parser that is using the debug data @@ -89,7 +90,7 @@ class Parser: public langutil::ParserBase UseSourceLocationFrom::Comments : UseSourceLocationFrom::Scanner }, - m_debugAttributeCache(debugAttributesCache == nullptr ? std::make_shared() : debugAttributesCache) + m_debugAttributeCache(std::move(debugAttributesCache)) {} /// Parses an inline assembly block starting with `{` and ending with `}`. diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp index 123dedcb483d..5e648737603d 100644 --- a/libyul/ObjectParser.cpp +++ b/libyul/ObjectParser.cpp @@ -171,7 +171,7 @@ std::optional ObjectParser::tryParseSourceNameMapping() const std::shared_ptr ObjectParser::parseBlock(std::optional _sourceNames) { - Parser parser(m_errorReporter, m_dialect, std::move(_sourceNames)); + Parser parser(m_errorReporter, m_dialect, std::move(_sourceNames), m_cache); auto ast = parser.parseInline(m_scanner); yulAssert(ast || m_errorReporter.hasErrors(), "Invalid block but no error!"); return ast; diff --git a/libyul/ObjectParser.h b/libyul/ObjectParser.h index 1d7756f5ae71..833a21967534 100644 --- a/libyul/ObjectParser.h +++ b/libyul/ObjectParser.h @@ -21,8 +21,9 @@ #pragma once -#include #include +#include +#include #include #include @@ -45,8 +46,8 @@ namespace solidity::yul class ObjectParser: public langutil::ParserBase { public: - explicit ObjectParser(langutil::ErrorReporter& _errorReporter, Dialect const& _dialect): - ParserBase(_errorReporter), m_dialect(_dialect) {} + explicit ObjectParser(langutil::ErrorReporter& _errorReporter, Dialect const& _dialect, Parser::DebugAttributeCache::Ptr _cache = {}): + ParserBase(_errorReporter), m_dialect(_dialect), m_cache(std::move(_cache)) {} /// Parses a Yul object. /// Falls back to code-only parsing if the source starts with `{`. @@ -66,6 +67,7 @@ class ObjectParser: public langutil::ParserBase void addNamedSubObject(Object& _container, std::string_view _name, std::shared_ptr _subObject); Dialect const& m_dialect; + Parser::DebugAttributeCache::Ptr m_cache; }; } diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 68da91d988aa..6418e713ea1c 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -55,7 +55,7 @@ bool YulStack::parse(std::string const& _sourceName, std::string const& _source) { m_charStream = std::make_unique(_source, _sourceName); std::shared_ptr scanner = std::make_shared(*m_charStream); - m_parserResult = ObjectParser(m_errorReporter, languageToDialect(m_language, m_evmVersion)).parse(scanner, false); + m_parserResult = ObjectParser(m_errorReporter, languageToDialect(m_language, m_evmVersion), m_cache).parse(scanner, false); } catch (UnimplementedFeatureError const& _error) { diff --git a/libyul/YulStack.h b/libyul/YulStack.h index f0487ffe52cb..e9caae1b42c5 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -37,6 +37,7 @@ #include #include +#include namespace solidity::evmasm { @@ -91,7 +92,8 @@ class YulStack: public langutil::CharStreamProvider Language _language, solidity::frontend::OptimiserSettings _optimiserSettings, langutil::DebugInfoSelection const& _debugInfoSelection, - std::shared_ptr _objectOptimizer = nullptr + std::shared_ptr _objectOptimizer = nullptr, + Parser::DebugAttributeCache::Ptr _cache = {} ): m_language(_language), m_evmVersion(_evmVersion), @@ -99,7 +101,8 @@ class YulStack: public langutil::CharStreamProvider m_optimiserSettings(std::move(_optimiserSettings)), m_debugInfoSelection(_debugInfoSelection), m_errorReporter(m_errors), - m_objectOptimizer(_objectOptimizer ? std::move(_objectOptimizer) : std::make_shared()) + m_objectOptimizer(_objectOptimizer ? std::move(_objectOptimizer) : std::make_shared()), + m_cache(std::move(_cache)) {} /// @returns the char stream used during parsing @@ -177,6 +180,7 @@ class YulStack: public langutil::CharStreamProvider langutil::ErrorReporter m_errorReporter; std::shared_ptr m_objectOptimizer; + Parser::DebugAttributeCache::Ptr m_cache; }; } diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index d365280b84fd..57dc3387b880 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -19,6 +19,9 @@ * Common functions the Yul tests. */ +#include "libyul/AsmParser.h" + + #include #include @@ -36,6 +39,7 @@ #include +#include #include using namespace solidity; @@ -50,7 +54,7 @@ Dialect const& defaultDialect() } } -std::pair, std::shared_ptr> yul::test::parse(std::string const& _source) +std::pair, std::shared_ptr> yul::test::parse(std::string const& _source, Parser::DebugAttributeCache::Ptr _cache) { YulStack stack( solidity::test::CommonOptions::get().evmVersion(), @@ -59,7 +63,9 @@ std::pair, std::shared_ptr> yul solidity::test::CommonOptions::get().optimize ? solidity::frontend::OptimiserSettings::standard() : solidity::frontend::OptimiserSettings::minimal(), - DebugInfoSelection::ExceptExperimental() + DebugInfoSelection::ExceptExperimental(), + nullptr, + std::move(_cache) ); if (!stack.parseAndAnalyze("", _source) || !stack.errors().empty()) BOOST_FAIL("Invalid source."); @@ -69,13 +75,14 @@ std::pair, std::shared_ptr> yul std::pair, std::shared_ptr> yul::test::parse( std::string const& _source, Dialect const& _dialect, - ErrorList& _errors + ErrorList& _errors, + Parser::DebugAttributeCache::Ptr _cache ) { ErrorReporter errorReporter(_errors); CharStream stream(_source, ""); std::shared_ptr scanner = std::make_shared(stream); - std::shared_ptr parserResult = yul::ObjectParser(errorReporter, _dialect).parse(scanner, false); + std::shared_ptr parserResult = yul::ObjectParser(errorReporter, _dialect, std::move(_cache)).parse(scanner, false); if (!parserResult) return {}; if (!parserResult->hasCode() || errorReporter.hasErrors()) diff --git a/test/libyul/Common.h b/test/libyul/Common.h index c87f1c68be17..35504c45afe9 100644 --- a/test/libyul/Common.h +++ b/test/libyul/Common.h @@ -23,6 +23,8 @@ #include +#include + #include #include #include @@ -46,10 +48,10 @@ namespace solidity::yul::test { std::pair, std::shared_ptr> -parse(std::string const& _source); +parse(std::string const& _source, Parser::DebugAttributeCache::Ptr _cache = {}); std::pair, std::shared_ptr> -parse(std::string const& _source, Dialect const& _dialect, langutil::ErrorList& _errors); +parse(std::string const& _source, Dialect const& _dialect, langutil::ErrorList& _errors, Parser::DebugAttributeCache::Ptr _cache = {}); Block disambiguate(std::string const& _source); std::string format(std::string const& _source); diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 5636047dc3c7..85e5e582fac8 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -1007,7 +1007,8 @@ BOOST_AUTO_TEST_CASE(ethdebug_debug_attributes_empty) auto const sourceText = R"( {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + BOOST_REQUIRE(cache->cache().size() == 0); std::shared_ptr result = parse(sourceText, dialect, reporter, cache); BOOST_REQUIRE(cache->cache().size() == 0); } @@ -1021,7 +1022,7 @@ BOOST_AUTO_TEST_CASE(ethdebug_debug_attributes_set_empty) /// @debug.set {} {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter, cache); BOOST_REQUIRE(cache->cache().size() == 1); } @@ -1036,7 +1037,7 @@ BOOST_AUTO_TEST_CASE(ethdebug_debug_attributes_set) /// @debug.set {"hello": "world"} {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter, cache); BOOST_REQUIRE(cache->cache().size() == 1); } @@ -1055,7 +1056,7 @@ BOOST_AUTO_TEST_CASE(ethdebug_debug_attributes_multiple_set) {} } )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); + auto const& dialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); std::shared_ptr result = parse(sourceText, dialect, reporter, cache); BOOST_REQUIRE(cache->cache().size() == 2); } diff --git a/test/libyul/SyntaxTest.cpp b/test/libyul/SyntaxTest.cpp index 7ed87bee450a..52cda2d2a07c 100644 --- a/test/libyul/SyntaxTest.cpp +++ b/test/libyul/SyntaxTest.cpp @@ -46,8 +46,10 @@ void SyntaxTest::parseAndAnalyze() ErrorList errorList{}; soltestAssert(m_dialect, ""); + if (m_debugAttributesEnabled && m_debugAttributesCache == nullptr) + m_debugAttributesCache = std::make_shared(); // Silently ignoring the results. - yul::test::parse(source, *m_dialect, errorList); + yul::test::parse(source, *m_dialect, errorList, m_debugAttributesCache); for (auto const& error: errorList) { int locationStart = -1; @@ -75,5 +77,6 @@ SyntaxTest::SyntaxTest(std::string const& _filename, langutil::EVMVersion _evmVe CommonSyntaxTest(_filename, _evmVersion) { std::string dialectName = m_reader.stringSetting("dialect", "evm"); + m_debugAttributesEnabled = m_reader.boolSetting("enableDebugAttributes", false); m_dialect = &dialect(dialectName, solidity::test::CommonOptions::get().evmVersion()); } diff --git a/test/libyul/SyntaxTest.h b/test/libyul/SyntaxTest.h index 27e59ee61439..6591140f6f29 100644 --- a/test/libyul/SyntaxTest.h +++ b/test/libyul/SyntaxTest.h @@ -18,8 +18,12 @@ #pragma once -#include +#include "libyul/AsmParser.h" +#include "libyul/optimiser/SimplificationRules.h" + + #include +#include namespace solidity::yul::test { @@ -40,6 +44,8 @@ class SyntaxTest: public solidity::test::CommonSyntaxTest private: Dialect const* m_dialect = nullptr; + bool m_debugAttributesEnabled = false; + Parser::DebugAttributeCache::Ptr m_debugAttributesCache; }; } diff --git a/test/libyul/yulSyntaxTests/invalid/invalid_debug_merge.yul b/test/libyul/yulSyntaxTests/invalid/invalid_debug_merge.yul index 13200b008cb8..f492d990d7a1 100644 --- a/test/libyul/yulSyntaxTests/invalid/invalid_debug_merge.yul +++ b/test/libyul/yulSyntaxTests/invalid/invalid_debug_merge.yul @@ -3,5 +3,7 @@ object "object" { /// @debug.merge {"HELLO": 2 } } +// ==== +// enableDebugAttributes: true // ---- // SyntaxError 5721: (37-65): @debug.merge: Could not parse debug data: parse error at line 1, column 12: syntax error while parsing object - unexpected end of input; expected '}' diff --git a/test/libyul/yulSyntaxTests/invalid/invalid_debug_patch.yul b/test/libyul/yulSyntaxTests/invalid/invalid_debug_patch.yul index 3f1d15e962da..ade80e757c22 100644 --- a/test/libyul/yulSyntaxTests/invalid/invalid_debug_patch.yul +++ b/test/libyul/yulSyntaxTests/invalid/invalid_debug_patch.yul @@ -3,5 +3,7 @@ object "object" { /// @debug.patch {"HELLO": invalid } } +// ==== +// enableDebugAttributes: true // ---- // SyntaxError 5721: (37-71): @debug.patch: Could not parse debug data: parse error at line 1, column 11: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal diff --git a/test/libyul/yulSyntaxTests/invalid/invalid_debug_patch_patch_object.yul b/test/libyul/yulSyntaxTests/invalid/invalid_debug_patch_patch_object.yul index a5c02823f27c..bf3abccea470 100644 --- a/test/libyul/yulSyntaxTests/invalid/invalid_debug_patch_patch_object.yul +++ b/test/libyul/yulSyntaxTests/invalid/invalid_debug_patch_patch_object.yul @@ -3,5 +3,7 @@ object "object" { /// @debug.patch { "op": "unknown_operation", "path": "/variable_a", "value": ["test"] } } } +// ==== +// enableDebugAttributes: true // ---- // SyntaxError 9426: (37-125): @debug.patch: Could not patch debug data: parse error: operation value 'unknown_operation' is invalid diff --git a/test/libyul/yulSyntaxTests/invalid/invalid_debug_set.yul b/test/libyul/yulSyntaxTests/invalid/invalid_debug_set.yul index 3c99b7cb52bd..f81ec22fc2de 100644 --- a/test/libyul/yulSyntaxTests/invalid/invalid_debug_set.yul +++ b/test/libyul/yulSyntaxTests/invalid/invalid_debug_set.yul @@ -3,5 +3,7 @@ object "object" { /// @debug.set {"HELLO": "WORLD } } +// ==== +// enableDebugAttributes: true // ---- // SyntaxError 5721: (37-68): @debug.set: Could not parse debug data: parse error at line 1, column 17: syntax error while parsing value - invalid string: missing closing quote; last read: '"WORLD'