Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add output selection support for ethdebug #15293

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions liblangutil/DebugInfoSelection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ DebugInfoSelection const DebugInfoSelection::All(bool _value) noexcept
DebugInfoSelection result;
for (bool DebugInfoSelection::* member: componentMap() | ranges::views::values)
result.*member = _value;
result.ethdebug = false;
return result;
}

Expand Down
2 changes: 2 additions & 0 deletions liblangutil/DebugInfoSelection.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,15 @@ struct DebugInfoSelection
{"location", &DebugInfoSelection::location},
{"snippet", &DebugInfoSelection::snippet},
{"ast-id", &DebugInfoSelection::astID},
{"ethdebug", &DebugInfoSelection::ethdebug},
};
return components;
}

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);
Expand Down
3 changes: 2 additions & 1 deletion libsolidity/codegen/ir/IRGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ std::string IRGenerator::generate(
);
};

Whiskers t(R"(
Whiskers t(R"(<?isEthdebugEnabled>/// ethdebug: enabled</isEthdebugEnabled>
/// @use-src <useSrcMapCreation>
object "<CreationObject>" {
code {
Expand Down Expand Up @@ -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());
Expand Down
3 changes: 2 additions & 1 deletion libsolidity/interface/CompilerStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1486,7 +1486,8 @@ void CompilerStack::generateIR(ContractDefinition const& _contract)
YulStack stack = parseYul(compiledContract.yulIR);
compiledContract.yulIRAst = stack.astJson();
stack.optimize();
compiledContract.yulIROptimized = stack.print(this);
compiledContract.yulIROptimized = m_debugInfoSelection.ethdebug ? "/// ethdebug: enabled\n" : "";
compiledContract.yulIROptimized += stack.print(this);
}
{
// Optimizer does not maintain correct native source locations in the AST.
Expand Down
13 changes: 12 additions & 1 deletion libsolidity/interface/StandardCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1324,6 +1324,13 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu

Json errors = std::move(_inputsAndSettings.errors);

if (_inputsAndSettings.debugInfoSelection.has_value() &&
_inputsAndSettings.debugInfoSelection->ethdebug &&
!(isIRRequested(_inputsAndSettings.outputSelection) || _inputsAndSettings.viaIR)
)
errors.emplace_back(formatError(Error::Type::FatalError, "general", "debug.debugInfo setting for ethdebug only valid, if 'ir', 'irAst', 'irOptimized' or 'irOptimizedAst' where requested."));


bool const binariesRequested = isBinaryRequested(_inputsAndSettings.outputSelection);

try
Expand Down Expand Up @@ -1429,7 +1436,7 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu
Json output;

if (errors.size() > 0)
output["errors"] = std::move(errors);
output["errors"] = std::move(errors);

if (!compilerStack.unhandledSMTLib2Queries().empty())
for (std::string const& query: compilerStack.unhandledSMTLib2Queries())
Expand Down Expand Up @@ -1482,6 +1489,10 @@ Json StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inpu
if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "irOptimizedAst", wildcardMatchesExperimental))
contractData["irOptimizedAst"] = compilerStack.yulIROptimizedAst(contractName);

// ethdebug
if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "ethdebug", wildcardMatchesExperimental))
contractData["ethdebug"] = Json::object();

// EVM
Json evmData;
if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.assembly", wildcardMatchesExperimental))
Expand Down
3 changes: 3 additions & 0 deletions solc/CommandLineInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ static std::string const g_strSignatureHashes = "hashes";
static std::string const g_strSourceList = "sourceList";
static std::string const g_strSources = "sources";
static std::string const g_strSrcMap = "srcmap";
static std::string const g_strEthdebug = "ethdebug";
static std::string const g_strSrcMapRuntime = "srcmap-runtime";
static std::string const g_strStorageLayout = "storage-layout";
static std::string const g_strVersion = "version";
Expand Down Expand Up @@ -995,6 +996,8 @@ void CommandLineInterface::handleCombinedJSON()
contractData[g_strFunDebugRuntime] = StandardCompiler::formatFunctionDebugData(
m_assemblyStack->runtimeObject(contractName).functionDebugData
);
if (m_options.compiler.combinedJsonRequests->ethdebug)
contractData[g_strEthdebug] = Json::object();
Copy link
Member

@cameel cameel Jul 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Combined JSON has been deprecated for ages now (#10278) and we're likely to drop it in the next breaking release. It does not make sense add more things to it at this point.

This should be standalone compiler output instead.

}
}

Expand Down
28 changes: 26 additions & 2 deletions solc/CommandLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,12 @@ General Information)").c_str(),
po::value<std::string>()->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 |
ranges::views::filter([](std::string const& key) { return key != "ethdebug"; }) |
ranges::to<std::vector>()
) + ".").c_str()
)
(
g_strStopAfter.c_str(),
Expand Down Expand Up @@ -771,7 +776,13 @@ General Information)").c_str(),
)
(
g_strCombinedJson.c_str(),
po::value<std::string>()->value_name(util::joinHumanReadable(CombinedJsonRequests::componentMap() | ranges::views::keys, ",")),
po::value<std::string>()->value_name(
util::joinHumanReadable(
CombinedJsonRequests::componentMap() | ranges::views::keys |
ranges::views::filter([](std::string const& key) { return key != "ethdebug"; }) |
ranges::to<std::vector>(), ","
)
),
"Output a single json document containing the specified information."
)
;
Expand Down Expand Up @@ -1439,6 +1450,19 @@ void CommandLineParser::processArgs()
m_options.input.mode == InputMode::CompilerWithASTImport ||
m_options.input.mode == InputMode::EVMAssemblerJSON
);

if (m_options.output.debugInfoSelection.has_value() && m_options.output.debugInfoSelection->ethdebug &&
!(m_options.output.viaIR || m_options.compiler.outputs.ir || m_options.compiler.outputs.irOptimized)
)
solThrow(CommandLineValidationError,
"--debug-info ethdebug can only be used with --" + g_strViaIR + ", --" + CompilerOutputs::componentName(&CompilerOutputs::ir) +
" and/or --" + CompilerOutputs::componentName(&CompilerOutputs::irOptimized) + "."
);

if (m_options.compiler.combinedJsonRequests.has_value() && m_options.compiler.combinedJsonRequests->ethdebug &&
!(m_options.output.debugInfoSelection.has_value() && m_options.output.debugInfoSelection->ethdebug)
)
solThrow(CommandLineValidationError, "--combined-json ethdebug can only be used together with --debug-info ethdebug.");
}

void CommandLineParser::parseCombinedJsonOption()
Expand Down
2 changes: 2 additions & 0 deletions solc/CommandLineParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ struct CombinedJsonRequests
{"devdoc", &CombinedJsonRequests::natspecDev},
{"userdoc", &CombinedJsonRequests::natspecUser},
{"ast", &CombinedJsonRequests::ast},
{"ethdebug", &CombinedJsonRequests::ethdebug},
};
return components;
}
Expand All @@ -156,6 +157,7 @@ struct CombinedJsonRequests
bool natspecDev = false;
bool natspecUser = false;
bool ast = false;
bool ethdebug = false;
};

struct CommandLineOptions
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--combined-json ethdebug --pretty-json --json-indent 3
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Error: --combined-json ethdebug can only be used together with --debug-info ethdebug.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract C {}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--via-ir --debug-info ethdebug --combined-json ethdebug --pretty-json --json-indent 3
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract C {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"contracts": {
"combined_json_ethdebug_without_ethdebug_debug_info/input.sol:C": {
"ethdebug": {}
}
},
"version": "<VERSION REMOVED>"
}
1 change: 1 addition & 0 deletions test/cmdlineTests/debug_info_ethdebug_no_ir/args
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--debug-info ethdebug
1 change: 1 addition & 0 deletions test/cmdlineTests/debug_info_ethdebug_no_ir/err
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Error: --debug-info ethdebug can only be used with --via-ir, --ir and/or --ir-optimized.
1 change: 1 addition & 0 deletions test/cmdlineTests/debug_info_ethdebug_no_ir/exit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1
6 changes: 6 additions & 0 deletions test/cmdlineTests/debug_info_ethdebug_no_ir/input.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
pragma solidity >=0.0;

contract C {
function f() public {}
}
1 change: 1 addition & 0 deletions test/cmdlineTests/debug_info_in_yul_ethdebug/args
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--ir --debug-info ethdebug
6 changes: 6 additions & 0 deletions test/cmdlineTests/debug_info_in_yul_ethdebug/input.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
pragma solidity >=0.0;

contract C {
function f() public {}
}
112 changes: 112 additions & 0 deletions test/cmdlineTests/debug_info_in_yul_ethdebug/output
Original file line number Diff line number Diff line change
@@ -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"<BYTECODE REMOVED>"
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--ir-optimized --optimize --debug-info ethdebug
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
pragma solidity >=0.0;

contract C {
function f() public {}
}
35 changes: 35 additions & 0 deletions test/cmdlineTests/debug_info_in_yul_ethdebug_optimized/output
Original file line number Diff line number Diff line change
@@ -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"<BYTECODE REMOVED>"
}
}
1 change: 1 addition & 0 deletions test/cmdlineTests/standard_debug_info_ethdebug_no_ir/args
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--allow-paths .
6 changes: 6 additions & 0 deletions test/cmdlineTests/standard_debug_info_ethdebug_no_ir/in.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
pragma solidity >=0.0;

contract C {
function f() public {}
}
12 changes: 12 additions & 0 deletions test/cmdlineTests/standard_debug_info_ethdebug_no_ir/input.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"language": "Solidity",
"sources": {
"C": {"urls": ["standard_debug_info_in_yul_ethdebug_optimized/in.sol"]}
},
"settings": {
"debug": {"debugInfo": ["ethdebug"]},
"outputSelection": {
"*": {"*": ["asm"]}
}
}
}
Loading