Skip to content

Commit

Permalink
[ethdebug] Enable ethdebug debug info selection.
Browse files Browse the repository at this point in the history
  • Loading branch information
aarlt committed Jul 24, 2024
1 parent b4c395b commit ec729b3
Show file tree
Hide file tree
Showing 43 changed files with 553 additions and 16 deletions.
12 changes: 10 additions & 2 deletions liblangutil/DebugInfoSelection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,22 @@ DebugInfoSelection const DebugInfoSelection::Only(bool DebugInfoSelection::* _me
return result;
}

DebugInfoSelection const DebugInfoSelection::Except(std::vector<bool DebugInfoSelection::*> const& _members) noexcept
{
DebugInfoSelection result = All();
for (bool DebugInfoSelection::* member: _members)
result.*member = false;
return result;
}

std::optional<DebugInfoSelection> DebugInfoSelection::fromString(std::string_view _input)
{
// TODO: Make more stuff constexpr and make it a static_assert().
solAssert(componentMap().count("all") == 0, "");
solAssert(componentMap().count("none") == 0, "");

if (_input == "all")
return All();
return ExceptExperimental();
if (_input == "none")
return None();

Expand All @@ -74,7 +82,7 @@ std::optional<DebugInfoSelection> 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;
Expand Down
6 changes: 5 additions & 1 deletion liblangutil/DebugInfoSelection.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<bool DebugInfoSelection::*> const& _members) noexcept;
static DebugInfoSelection const ExceptExperimental() noexcept { return Except({&DebugInfoSelection::ethdebug}); }

static std::optional<DebugInfoSelection> fromString(std::string_view _input);
static std::optional<DebugInfoSelection> fromComponents(
Expand Down Expand Up @@ -72,13 +74,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
10 changes: 9 additions & 1 deletion libsolidity/interface/StandardCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion libyul/YulStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,8 @@ std::string YulStack::print(
yulAssert(m_stackState >= Parsed);
yulAssert(m_parserResult, "");
yulAssert(m_parserResult->code, "");
return m_parserResult->toString(&languageToDialect(m_language, m_evmVersion), m_debugInfoSelection, _soliditySourceProvider) + "\n";
return (m_debugInfoSelection.ethdebug ? "/// ethdebug: enabled\n" : "") +
m_parserResult->toString(&languageToDialect(m_language, m_evmVersion), m_debugInfoSelection, _soliditySourceProvider) + "\n";
}

Json YulStack::astJson() const
Expand Down
15 changes: 14 additions & 1 deletion 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 @@ -1439,6 +1444,14 @@ 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) + "."
);
}

void CommandLineParser::parseCombinedJsonOption()
Expand Down
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_ethdebug_via_ir/args
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--via-ir --debug-info ethdebug --bin
6 changes: 6 additions & 0 deletions test/cmdlineTests/debug_info_ethdebug_via_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 {}
}
4 changes: 4 additions & 0 deletions test/cmdlineTests/debug_info_ethdebug_via_ir/output
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

======= debug_info_ethdebug_via_ir/input.sol:C =======
Binary:
<BYTECODE REMOVED>
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_ethdebug_no_ir/in.sol"]}
},
"settings": {
"debug": {"debugInfo": ["ethdebug"]},
"outputSelection": {
"*": {"*": ["evm.bytecode"]}
}
}
}
32 changes: 32 additions & 0 deletions test/cmdlineTests/standard_debug_info_ethdebug_no_ir/output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"contracts": {
"C": {
"C": {
"evm": {
"bytecode": {
"functionDebugData": {},
"generatedSources": [],
"linkReferences": {},
"object": "<BYTECODE REMOVED>",
"opcodes":"<OPCODES REMOVED>",
"sourceMap":"<SOURCEMAP REMOVED>"
}
}
}
}
},
"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
}
}
}
1 change: 1 addition & 0 deletions test/cmdlineTests/standard_debug_info_ethdebug_via_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_via_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 {}
}
Loading

0 comments on commit ec729b3

Please sign in to comment.