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 bf0f6d5c0f25..55fe0f936490 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -118,7 +118,7 @@ std::string IRGenerator::generate( ); }; - Whiskers t(R"( + Whiskers t(R"(/// ethdebug: enabled /// @use-src object "" { code { @@ -155,6 +155,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 f2c37fa68523..76808cac0cfe 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1076,6 +1076,14 @@ Json CompilerStack::interfaceSymbols(std::string const& _contractName) const return interfaceSymbols; } +Json CompilerStack::ethdebug(std::string const& _contractName) const +{ + (void)_contractName; + + Json ethdebug = Json::object(); + return ethdebug; +} + 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 2c5ecb132b94..6225f0725b72 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -349,6 +349,10 @@ 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) const; + /// @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)); } diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index e4b9f9f7ae17..15e4a2e44f3f 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1321,10 +1321,18 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu compilerStack.setModelCheckerSettings(_inputsAndSettings.modelCheckerSettings); compilerStack.enableEvmBytecodeGeneration(isEvmBytecodeRequested(_inputsAndSettings.outputSelection)); - compilerStack.requestIROutputs(irOutputSelection(_inputsAndSettings.outputSelection)); + CompilerStack::IROutputSelection selectedIrOutput = irOutputSelection(_inputsAndSettings.outputSelection); + compilerStack.requestIROutputs(selectedIrOutput); Json errors = std::move(_inputsAndSettings.errors); + if ( + _inputsAndSettings.debugInfoSelection.has_value() && + _inputsAndSettings.debugInfoSelection->ethdebug && + (selectedIrOutput == CompilerStack::IROutputSelection::None && !_inputsAndSettings.viaIR) + ) + errors.emplace_back(formatError(Error::Type::FatalError, "general", "'ethdebug' can only be selected in 'settings.debug.debugInfo' when at least one of the IR outputs is selected or 'viaIR' was set.")); + bool const binariesRequested = isBinaryRequested(_inputsAndSettings.outputSelection); try diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index b9fc6388c6bd..e3ac252a80bd 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -360,12 +360,13 @@ std::string YulStack::print( yulAssert(m_stackState >= Parsed); yulAssert(m_parserResult, ""); yulAssert(m_parserResult->code, ""); - return m_parserResult->toString( - languageToDialect(m_language, m_evmVersion), - AsmPrinter::TypePrinting::OmitDefault, - m_debugInfoSelection, - _soliditySourceProvider - ) + "\n"; + return (m_debugInfoSelection.ethdebug ? "/// ethdebug: enabled\n" : "") + + m_parserResult->toString( + languageToDialect(m_language, m_evmVersion), + AsmPrinter::TypePrinting::OmitDefault, + m_debugInfoSelection, + _soliditySourceProvider + ) + "\n"; } Json YulStack::astJson() const diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 1351858405a1..7f821959a489 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -154,7 +154,8 @@ static bool needsHumanTargetedStdout(CommandLineOptions const& _options) _options.compiler.outputs.natspecDev || _options.compiler.outputs.opcodes || _options.compiler.outputs.signatureHashes || - _options.compiler.outputs.storageLayout; + _options.compiler.outputs.storageLayout || + _options.compiler.outputs.ethdebug; } static bool coloredOutput(CommandLineOptions const& _options) @@ -505,6 +506,20 @@ void CommandLineInterface::handleGasEstimation(std::string const& _contract) } } +void CommandLineInterface::handleEthdebug(std::string const& _contract) +{ + solAssert(CompilerInputModes.count(m_options.input.mode) == 1); + + if (!m_options.compiler.outputs.ethdebug) + return; + + std::string data = jsonPrint(removeNullMembers(m_compiler->ethdebug(_contract)), m_options.formatting.json); + if (!m_options.output.dir.empty()) + createFile(m_compiler->filesystemFriendlyName(_contract) + "_ethdebug.json", data); + else + sout() << "Debug Data (ethdebug):" << std::endl << data << std::endl; +} + void CommandLineInterface::readInputFiles() { solAssert(!m_standardJsonInput.has_value()); @@ -1324,6 +1339,7 @@ void CommandLineInterface::outputCompilationResults() handleStorageLayout(contract); handleNatspec(true, contract); handleNatspec(false, contract); + handleEthdebug(contract); } // end of contracts iteration } diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index bcebcbcfd3be..b4a8a89348ec 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -115,6 +115,7 @@ class CommandLineInterface void handleNatspec(bool _natspecDev, std::string const& _contract); void handleGasEstimation(std::string const& _contract); void handleStorageLayout(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 881c656dad9b..10bbaf1566fc 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -473,6 +473,7 @@ void CommandLineParser::parseOutputSelection() CompilerOutputs::componentName(&CompilerOutputs::irOptimized), CompilerOutputs::componentName(&CompilerOutputs::astCompactJson), CompilerOutputs::componentName(&CompilerOutputs::asmJson), + CompilerOutputs::componentName(&CompilerOutputs::ethdebug), }; static std::set const evmAssemblyJsonImportModeOutputs = { CompilerOutputs::componentName(&CompilerOutputs::asm_), @@ -638,7 +639,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 +769,13 @@ General Information)").c_str(), (CompilerOutputs::componentName(&CompilerOutputs::metadata).c_str(), "Combined Metadata JSON whose IPFS hash is stored on-chain.") (CompilerOutputs::componentName(&CompilerOutputs::storageLayout).c_str(), "Slots, offsets and types of the contract's state variables.") ; + if (!_forHelp) // Note: We intentionally keep this undocumented for now. + outputComponents.add_options() + ( + CompilerOutputs::componentName(&CompilerOutputs::ethdebug).c_str(), + "Ethdebug output of all contracts." + ) + ; desc.add(outputComponents); po::options_description extraOutput("Extra Output"); @@ -1440,6 +1454,29 @@ void CommandLineParser::processArgs() m_options.input.mode == InputMode::CompilerWithASTImport || m_options.input.mode == InputMode::EVMAssemblerJSON ); + + if (m_options.compiler.outputs.ethdebug) + { + m_options.output.viaIR = true; + if (m_options.output.debugInfoSelection.has_value()) + m_options.output.debugInfoSelection->ethdebug = true; + else + { + m_options.output.debugInfoSelection = DebugInfoSelection::Default(); + m_options.output.debugInfoSelection->enable("ethdebug"); + } + } + + 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) + ) + solThrow( + CommandLineValidationError, + "--debug-info ethdebug can only be used with --" + CompilerOutputs::componentName(&CompilerOutputs::ir) + + ", --" + CompilerOutputs::componentName(&CompilerOutputs::irOptimized) + + " and/or --" + CompilerOutputs::componentName(&CompilerOutputs::ethdebug) + "." + ); } void CommandLineParser::parseCombinedJsonOption() diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index b95973562e51..f7d92950e427 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -86,6 +86,7 @@ struct CompilerOutputs {"devdoc", &CompilerOutputs::natspecDev}, {"metadata", &CompilerOutputs::metadata}, {"storage-layout", &CompilerOutputs::storageLayout}, + {"ethdebug", &CompilerOutputs::ethdebug}, }; return components; } @@ -106,6 +107,7 @@ struct CompilerOutputs bool natspecDev = false; bool metadata = false; bool storageLayout = false; + bool ethdebug = false; }; struct CombinedJsonRequests diff --git a/test/cmdlineTests/debug_info_ethdebug_no_ir/args b/test/cmdlineTests/debug_info_ethdebug_no_ir/args new file mode 100644 index 000000000000..7b4e521b02b8 --- /dev/null +++ b/test/cmdlineTests/debug_info_ethdebug_no_ir/args @@ -0,0 +1 @@ +--debug-info ethdebug diff --git a/test/cmdlineTests/debug_info_ethdebug_no_ir/err b/test/cmdlineTests/debug_info_ethdebug_no_ir/err new file mode 100644 index 000000000000..7cc3e08b8855 --- /dev/null +++ b/test/cmdlineTests/debug_info_ethdebug_no_ir/err @@ -0,0 +1 @@ +Error: --debug-info ethdebug can only be used with --ir, --ir-optimized and/or --ethdebug. diff --git a/test/cmdlineTests/debug_info_ethdebug_no_ir/exit b/test/cmdlineTests/debug_info_ethdebug_no_ir/exit new file mode 100644 index 000000000000..d00491fd7e5b --- /dev/null +++ b/test/cmdlineTests/debug_info_ethdebug_no_ir/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/debug_info_ethdebug_no_ir/input.sol b/test/cmdlineTests/debug_info_ethdebug_no_ir/input.sol new file mode 100644 index 000000000000..415509ef9aef --- /dev/null +++ b/test/cmdlineTests/debug_info_ethdebug_no_ir/input.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/debug_info_in_yul_ethdebug/args b/test/cmdlineTests/debug_info_in_yul_ethdebug/args new file mode 100644 index 000000000000..af87a8c5aa81 --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_ethdebug/args @@ -0,0 +1 @@ +--ir --debug-info ethdebug diff --git a/test/cmdlineTests/debug_info_in_yul_ethdebug/input.sol b/test/cmdlineTests/debug_info_in_yul_ethdebug/input.sol new file mode 100644 index 000000000000..415509ef9aef --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_ethdebug/input.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/debug_info_in_yul_ethdebug/output b/test/cmdlineTests/debug_info_in_yul_ethdebug/output new file mode 100644 index 000000000000..601fe824288b --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_ethdebug/output @@ -0,0 +1,112 @@ +IR: +/// ethdebug: enabled +/// @use-src 0:"debug_info_in_yul_ethdebug/input.sol" +object "C_6" { + code { + /// @src 0:60:101 + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_6() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) + + return(_1, datasize("C_6_deployed")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:60:101 + function constructor_C_6() { + + /// @src 0:60:101 + + } + /// @src 0:60:101 + + } + /// @use-src 0:"debug_info_in_yul_ethdebug/input.sol" + object "C_6_deployed" { + code { + /// @src 0:60:101 + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x26121ff0 + { + // f() + + external_fun_f_5() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function abi_decode_tuple_(headStart, dataEnd) { + if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_f_5() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + /// @src 0:77:99 + function fun_f_5() { + + } + /// @src 0:60:101 + + } + + data ".metadata" hex"" + } + +} diff --git a/test/cmdlineTests/debug_info_in_yul_ethdebug_optimized/args b/test/cmdlineTests/debug_info_in_yul_ethdebug_optimized/args new file mode 100644 index 000000000000..7d714eba9a13 --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_ethdebug_optimized/args @@ -0,0 +1 @@ +--ir-optimized --optimize --debug-info ethdebug diff --git a/test/cmdlineTests/debug_info_in_yul_ethdebug_optimized/input.sol b/test/cmdlineTests/debug_info_in_yul_ethdebug_optimized/input.sol new file mode 100644 index 000000000000..415509ef9aef --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_ethdebug_optimized/input.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/debug_info_in_yul_ethdebug_optimized/output b/test/cmdlineTests/debug_info_in_yul_ethdebug_optimized/output new file mode 100644 index 000000000000..dd7d13d0d600 --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_ethdebug_optimized/output @@ -0,0 +1,35 @@ +Optimized IR: +/// ethdebug: enabled +/// @use-src 0:"debug_info_in_yul_ethdebug_optimized/input.sol" +object "C_6" { + code { + { + /// @src 0:60:101 + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize("C_6_deployed") + codecopy(_1, dataoffset("C_6_deployed"), _2) + return(_1, _2) + } + } + /// @use-src 0:"debug_info_in_yul_ethdebug_optimized/input.sol" + object "C_6_deployed" { + code { + { + /// @src 0:60:101 + if iszero(lt(calldatasize(), 4)) + { + if eq(0x26121ff0, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + return(0, 0) + } + } + revert(0, 0) + } + } + data ".metadata" hex"" + } +} diff --git a/test/cmdlineTests/ethdebug_enables_via_ir/args b/test/cmdlineTests/ethdebug_enables_via_ir/args new file mode 100644 index 000000000000..44742686d155 --- /dev/null +++ b/test/cmdlineTests/ethdebug_enables_via_ir/args @@ -0,0 +1 @@ +--ethdebug --metadata diff --git a/test/cmdlineTests/ethdebug_enables_via_ir/input.sol b/test/cmdlineTests/ethdebug_enables_via_ir/input.sol new file mode 100644 index 000000000000..415509ef9aef --- /dev/null +++ b/test/cmdlineTests/ethdebug_enables_via_ir/input.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/ethdebug_enables_via_ir/output b/test/cmdlineTests/ethdebug_enables_via_ir/output new file mode 100644 index 000000000000..21ad80b2e7f9 --- /dev/null +++ b/test/cmdlineTests/ethdebug_enables_via_ir/output @@ -0,0 +1,6 @@ + +======= ethdebug_enables_via_ir/input.sol:C ======= +Metadata: +{"compiler":{"version": ""},"language":"Solidity","output":{"abi":[{"inputs":[],"name":"f","outputs":[],"stateMutability":"nonpayable","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"ethdebug_enables_via_ir/input.sol":"C"},"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[],"viaIR":true},"sources":{"ethdebug_enables_via_ir/input.sol":{"keccak256":"0xd664727da2d62b6156845f13be0ecb2d8d8223c0f736d39575a3bdfbb062c320","license":"GPL-2.0","urls":["bzz-raw://470d51a492c4368fac9c29ebb491b0eaa1bc8a660445a014276dc686531742b8","dweb:/ipfs/QmVVnjC3Z35AXGo3GUNPMuKBD2MdFcZxhVg1qHi4fmHzKo"]}},"version":1} +Debug Data (ethdebug): +{} diff --git a/test/cmdlineTests/standard_debug_info_ethdebug_no_ir/args b/test/cmdlineTests/standard_debug_info_ethdebug_no_ir/args new file mode 100644 index 000000000000..18532c5a6d3f --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_ethdebug_no_ir/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_debug_info_ethdebug_no_ir/in.sol b/test/cmdlineTests/standard_debug_info_ethdebug_no_ir/in.sol new file mode 100644 index 000000000000..415509ef9aef --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_ethdebug_no_ir/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/standard_debug_info_ethdebug_no_ir/input.json b/test/cmdlineTests/standard_debug_info_ethdebug_no_ir/input.json new file mode 100644 index 000000000000..9fdf2232ac08 --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_ethdebug_no_ir/input.json @@ -0,0 +1,12 @@ +{ + "language": "Solidity", + "sources": { + "C": {"urls": ["standard_debug_info_ethdebug_no_ir/in.sol"]} + }, + "settings": { + "debug": {"debugInfo": ["ethdebug"]}, + "outputSelection": { + "*": {"*": ["evm.bytecode"]} + } + } +} diff --git a/test/cmdlineTests/standard_debug_info_ethdebug_no_ir/output.json b/test/cmdlineTests/standard_debug_info_ethdebug_no_ir/output.json new file mode 100644 index 000000000000..54515ba25040 --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_ethdebug_no_ir/output.json @@ -0,0 +1,32 @@ +{ + "contracts": { + "C": { + "C": { + "evm": { + "bytecode": { + "functionDebugData": {}, + "generatedSources": [], + "linkReferences": {}, + "object": "", + "opcodes":"", + "sourceMap":"" + } + } + } + } + }, + "errors": [ + { + "component": "general", + "formattedMessage": "'ethdebug' can only be selected in 'settings.debug.debugInfo' when at least one of the IR outputs is selected or 'viaIR' was set.", + "message": "'ethdebug' can only be selected in 'settings.debug.debugInfo' when at least one of the IR outputs is selected or 'viaIR' was set.", + "severity": "error", + "type": "FatalError" + } + ], + "sources": { + "C": { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_ethdebug/args b/test/cmdlineTests/standard_debug_info_in_yul_ethdebug/args new file mode 100644 index 000000000000..18532c5a6d3f --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_ethdebug/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_debug_info_in_yul_ethdebug/in.sol b/test/cmdlineTests/standard_debug_info_in_yul_ethdebug/in.sol new file mode 100644 index 000000000000..415509ef9aef --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_ethdebug/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_ethdebug/input.json b/test/cmdlineTests/standard_debug_info_in_yul_ethdebug/input.json new file mode 100644 index 000000000000..eca9b2d92f66 --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_ethdebug/input.json @@ -0,0 +1,13 @@ +{ + "language": "Solidity", + "sources": { + "C": {"urls": ["standard_debug_info_in_yul_ethdebug/in.sol"]} + }, + "settings": { + "debug": {"debugInfo": ["ethdebug"]}, + "optimizer": {"enabled": false}, + "outputSelection": { + "*": {"*": ["ir"]} + } + } +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_ethdebug/output.json b/test/cmdlineTests/standard_debug_info_in_yul_ethdebug/output.json new file mode 100644 index 000000000000..1d46ed584a8a --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_ethdebug/output.json @@ -0,0 +1,126 @@ +{ + "contracts": { + "C": { + "C": { + "ir": "/// ethdebug: enabled +/// @use-src 0:\"C\" +object \"C_6\" { + code { + /// @src 0:60:101 + mstore(64, memoryguard(128)) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_6() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"C_6_deployed\"), datasize(\"C_6_deployed\")) + + return(_1, datasize(\"C_6_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:60:101 + function constructor_C_6() { + + /// @src 0:60:101 + + } + /// @src 0:60:101 + + } + /// @use-src 0:\"C\" + object \"C_6_deployed\" { + code { + /// @src 0:60:101 + mstore(64, memoryguard(128)) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x26121ff0 + { + // f() + + external_fun_f_5() + } + + default {} + } + + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function abi_decode_tuple_(headStart, dataEnd) { + if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function external_fun_f_5() { + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + /// @src 0:77:99 + function fun_f_5() { + + } + /// @src 0:60:101 + + } + + data \".metadata\" hex\"\" + } + +} + +" + } + } + }, + "sources": { + "C": { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_ethdebug_optimized/args b/test/cmdlineTests/standard_debug_info_in_yul_ethdebug_optimized/args new file mode 100644 index 000000000000..18532c5a6d3f --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_ethdebug_optimized/args @@ -0,0 +1 @@ +--allow-paths . diff --git a/test/cmdlineTests/standard_debug_info_in_yul_ethdebug_optimized/in.sol b/test/cmdlineTests/standard_debug_info_in_yul_ethdebug_optimized/in.sol new file mode 100644 index 000000000000..415509ef9aef --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_ethdebug_optimized/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_ethdebug_optimized/input.json b/test/cmdlineTests/standard_debug_info_in_yul_ethdebug_optimized/input.json new file mode 100644 index 000000000000..410c03bd1a7e --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_ethdebug_optimized/input.json @@ -0,0 +1,13 @@ +{ + "language": "Solidity", + "sources": { + "C": {"urls": ["standard_debug_info_in_yul_ethdebug_optimized/in.sol"]} + }, + "settings": { + "debug": {"debugInfo": ["ethdebug"]}, + "optimizer": {"enabled": true}, + "outputSelection": { + "*": {"*": ["irOptimized"]} + } + } +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_ethdebug_optimized/output.json b/test/cmdlineTests/standard_debug_info_in_yul_ethdebug_optimized/output.json new file mode 100644 index 000000000000..af2fbde3dadd --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_ethdebug_optimized/output.json @@ -0,0 +1,48 @@ +{ + "contracts": { + "C": { + "C": { + "irOptimized": "/// ethdebug: enabled +/// @use-src 0:\"C\" +object \"C_6\" { + code { + { + /// @src 0:60:101 + let _1 := memoryguard(0x80) + mstore(64, _1) + if callvalue() { revert(0, 0) } + let _2 := datasize(\"C_6_deployed\") + codecopy(_1, dataoffset(\"C_6_deployed\"), _2) + return(_1, _2) + } + } + /// @use-src 0:\"C\" + object \"C_6_deployed\" { + code { + { + /// @src 0:60:101 + if iszero(lt(calldatasize(), 4)) + { + if eq(0x26121ff0, shr(224, calldataload(0))) + { + if callvalue() { revert(0, 0) } + if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } + return(0, 0) + } + } + revert(0, 0) + } + } + data \".metadata\" hex\"\" + } +} +" + } + } + }, + "sources": { + "C": { + "id": 0 + } + } +} diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index dece0d82b10e..b00bfc457635 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -59,7 +59,7 @@ std::pair, std::shared_ptr> yul::te 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 eb6a447d1273..92f71b4d9171 100644 --- a/test/libyul/YulInterpreterTest.cpp +++ b/test/libyul/YulInterpreterTest.cpp @@ -70,7 +70,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/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 e31391b0e15b..6a8730095f6e 100644 --- a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp @@ -64,7 +64,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))