Skip to content
Merged
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
2 changes: 2 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ Language Features:
Compiler Features:
* Commandline Interface: Disallow selecting the deprecated assembly input mode that was only accessible via `--assemble` instead of treating it as equivalent to `--strict-assembly`.
* Commandline Interface: Introduce `--experimental` flag required for enabling the experimental mode.
* Commandline Interface: Replace ``--ethdebug`` and ``--ethdebug-runtime`` with more granular ``--ethdebug-resources``, ``--ethdebug-compilation``, ``--ethdebug-program`` and ``--ethdebug-program-runtime`` flags. Per-contract program outputs no longer force full binary compilation.
* EVM: Introduce experimental EVM version `@future`.
* General: Introduce the SSA CFG codegen (experimental).
* General: Improve performance of sanity checks throughout the compiler implementation.
* General: Restrict the existing experimental features (`generic-solidity`, `lsp`, `ethdebug`, `eof`, `evm`, `ast-import`, `evmasm-import`, `ir-ast`, `ssa-cfg`) to experimental mode.
* Metadata: Store the state of the experimental mode in JSON and CBOR metadata. In CBOR this broadens the meaning of the existing `experimental` field, which used to indicate only the presence of certain experimental pragmas in the source.
* Standard JSON Interface: Introduce `settings.experimental` setting required for enabling the experimental mode.
* Standard JSON Interface: Replace the top-level ``ethdebug`` output with ``ethdebug.resources`` and ``ethdebug.compilation``. Decouple ethdebug outputs from binary compilation so that global ethdebug outputs can be produced without generating bytecode.
* Yul Optimizer: Improve performance of control flow side effects collector and function references resolver.

Bugfixes:
Expand Down
63 changes: 36 additions & 27 deletions docs/using-the-compiler.rst
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ Input Description
// The snippet is quoted and follows the corresponding `@src` annotation.
// - `ast-id`: Annotations of the form `@ast-id <id>` over elements that can be mapped back to a definition in the original Solidity file.
// `<id>` is a node ID in the Solidity AST ('ast' output).
// - `ethdebug`: Ethdebug annotations (experimental).
// - `ethdebug`: Ethdebug annotations (experimental). Automatically enabled when any ethdebug output is requested.
// - `*`: Wildcard value that can be used to request all non-experimental components.
"debugInfo": ["location", "snippet", "ast-id", "ethdebug"]
},
Expand Down Expand Up @@ -453,8 +453,8 @@ Input Description
// transientStorageLayout - Slots, offsets and types of the contract's state variables in transient storage
// evm.assembly - New assembly format
// evm.legacyAssembly - Old-style assembly format in JSON
// evm.bytecode.ethdebug - Debug information in ethdebug format (ethdebug/format/program schema). Can only be requested when compiling via IR. (experimental)
// evm.deployedBytecode.ethdebug - Like evm.bytecode.ethdebug, but for the runtime part of the contract (experimental)
// evm.bytecode.ethdebug - Debug information in ethdebug format (ethdebug/format/program schema for creation bytecode). Can only be requested when compiling via IR. (experimental)
// evm.deployedBytecode.ethdebug - Debug information in ethdebug format (ethdebug/format/program schema for deployed bytecode). Can only be requested when compiling via IR. (experimental)
// evm.bytecode.functionDebugData - Debugging information at function level
// evm.bytecode.object - Bytecode object
// evm.bytecode.opcodes - Opcodes list
Expand All @@ -467,6 +467,10 @@ Input Description
// evm.gasEstimates - Function gas estimates
// yulCFGJson - Control Flow Graph (CFG) of the Single Static Assignment (SSA) form of the contract (experimental)
//
// Global level (needs "*" as file name and "*" as contract name):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

not sure why it needs "*" for file and contract name, can this be solved differently? wouldn't it be better as flat top-level key if it's actually global?

// ethdebug.resources - Global ethdebug output (ethdebug/format/info/resources schema) containing source list and compiler info (experimental)
// ethdebug.compilation - Global ethdebug compilation output (the 'compilation' key from ethdebug/format/info/resources schema) (experimental)
//
// Note that using `evm`, `evm.bytecode`, etc. will select every
// target part of that output. Additionally, `*` can be used as a wildcard to request everything.
//
Expand Down Expand Up @@ -696,7 +700,12 @@ Output Description
}
},
// Global Ethdebug output (experimental)
"ethdebug": {/* ... */ }
"ethdebug": {
// Requested via ethdebug.resources output selection
"resources": {/* ... */},
// Requested via ethdebug.compilation output selection
"compilation": {/* ... */}
}
}


Expand Down Expand Up @@ -751,26 +760,26 @@ Note that the use of this mode is recorded in the metadata:

The table below details all currently available experimental features.

+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+
| Feature | ID | Affects bytecode | Flag/pragma |
+=======================+==========================+==================+===================================================================+
| AST import | ``ast-import`` | yes | ``--import-ast`` |
+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+
| LSP | ``lsp`` | no | ``--lsp`` |
+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+
| EVM Assembly import | ``evmasm-import`` | yes | ``--import-asm-json`` |
+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+
| Generic Solidity | ``generic-solidity`` | yes | ``pragma experimental solidity`` |
+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+
| IR AST | ``ir-ast`` | no | ``--ir-ast-json``, ``--ir-optimized-ast-json`` |
+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+
| EOF | ``eof`` | yes | ``--experimental-eof-version`` |
+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+
| Non-mainnet EVMs | ``evm`` | yes | ``--evm-version <version name>`` |
+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+
| Ethdebug | ``ethdebug`` | no | ``--ethdebug``, ``--ethdebug-runtime``, ``--debug-info ethdebug`` |
+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+
| | | no | ``--yul-cfg-json`` |
| SSA CFG + ``ssa-cfg`` +------------------+-------------------------------------------------------------------+
| | | yes | ``--via-ssa-cfg`` |
+-----------------------+--------------------------+------------------+-------------------------------------------------------------------+
+-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| Feature | ID | Affects bytecode | Flag/pragma |
+=======================+==========================+==================+=========================================================================================================================================+
| AST import | ``ast-import`` | yes | ``--import-ast`` |
+-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| LSP | ``lsp`` | no | ``--lsp`` |
+-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| EVM Assembly import | ``evmasm-import`` | yes | ``--import-asm-json`` |
+-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| Generic Solidity | ``generic-solidity`` | yes | ``pragma experimental solidity`` |
+-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| IR AST | ``ir-ast`` | no | ``--ir-ast-json``, ``--ir-optimized-ast-json`` |
+-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| EOF | ``eof`` | yes | ``--experimental-eof-version`` |
+-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| Non-mainnet EVMs | ``evm`` | yes | ``--evm-version <version name>`` |
+-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| Ethdebug | ``ethdebug`` | no | ``--ethdebug-resources``, ``--ethdebug-compilation``, ``--ethdebug-program``, ``--ethdebug-program-runtime``, ``--debug-info ethdebug`` |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

what's the default now, actually? is that somehow reflected in the docs?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Default in what way?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry I confused myself here. What I meant were the default settings for emitting debug info. Which, obviously, is to not emit anything unless debug info output is requested. So nothing to change or even discuss in that regard.

Tangentially (and where my confusion came from): I've always found it a bit funny that the default behavior of IR output is to attach source location info.

+-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| | | no | ``--yul-cfg-json`` |
| SSA CFG + ``ssa-cfg`` +------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
| | | yes | ``--via-ssa-cfg`` |
+-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
1 change: 1 addition & 0 deletions libevmasm/AbstractAssemblyStack.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class AbstractAssemblyStack
virtual Json ethdebug(std::string const& _contractName) const = 0;
virtual Json ethdebugRuntime(std::string const& _contractName) const = 0;
virtual Json ethdebug() const = 0;
virtual Json ethdebugCompilation() const = 0;

virtual Json assemblyJSON(std::string const& _contractName) const = 0;
virtual std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const = 0;
Expand Down
5 changes: 5 additions & 0 deletions libevmasm/EVMAssemblyStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ Json EVMAssemblyStack::ethdebug() const
return {};
}

Json EVMAssemblyStack::ethdebugCompilation() const
{
return {};
}

Json EVMAssemblyStack::assemblyJSON() const
{
solAssert(m_evmAssembly);
Expand Down
1 change: 1 addition & 0 deletions libevmasm/EVMAssemblyStack.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class EVMAssemblyStack: public AbstractAssemblyStack
Json ethdebug(std::string const& _contractName) const override;
Json ethdebugRuntime(std::string const& _contractName) const override;
Json ethdebug() const override;
Json ethdebugCompilation() const override;

Json assemblyJSON() const;
Json assemblyJSON(std::string const& _contractName) const override;
Expand Down
14 changes: 10 additions & 4 deletions libevmasm/Ethdebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,16 @@ Json ethdebug::resources(std::vector<std::string> const& _sources, std::string c
sources.push_back(source);
}
Json result = Json::object();
result["compilation"] = Json::object();
result["compilation"]["compiler"] = Json::object();
result["compilation"]["compiler"]["name"] = "solc";
result["compilation"]["compiler"]["version"] = _version;
result["compilation"] = compilation(_version);
result["compilation"]["sources"] = sources;
return result;
}

Json ethdebug::compilation(std::string_view _version)
{
Json result = Json::object();
result["compiler"] = Json::object();
result["compiler"]["name"] = "solc";
result["compiler"]["version"] = _version;
return result;
}
3 changes: 3 additions & 0 deletions libevmasm/Ethdebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,7 @@ Json program(std::string_view _name, unsigned _sourceID, Assembly const& _assemb
// returns ethdebug/format/info/resources
Json resources(std::vector<std::string> const& _sources, std::string const& _version);

// returns the 'compilation' object from ethdebug/format/info/resources
Json compilation(std::string_view _version);

} // namespace solidity::evmasm::ethdebug
15 changes: 13 additions & 2 deletions libsolidity/interface/CompilerStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,7 @@ bool CompilerStack::compile(State _stopAfter)

// Only compile contracts individually which have been requested.
std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> otherCompilers;
bool requiresFullCompilation = false;

for (Source const* source: m_sourceOrder)
for (ASTPointer<ASTNode> const& node: source->ast->nodes())
Expand All @@ -802,6 +803,11 @@ bool CompilerStack::compile(State _stopAfter)

try
{
// Skip if full compilation is not needed (i.e. no IR/bytecode requested)
if (!pipelineConfig.needsFullCompilation())
continue;
requiresFullCompilation = true;

if (pipelineConfig.needIR(m_viaIR))
generateIR(*contract, pipelineConfig.needIRCodegenOnly(m_viaIR));
if (pipelineConfig.needBytecode())
Expand Down Expand Up @@ -831,7 +837,8 @@ bool CompilerStack::compile(State _stopAfter)

solAssert(!m_errorReporter.hasErrors());
m_stackState = CompilationSuccessful;
this->link();
if (requiresFullCompilation)
this->link();
Comment on lines +840 to +841
Copy link
Copy Markdown
Member

@clonker clonker Apr 15, 2026

Choose a reason for hiding this comment

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

how is this (as well as the perf optimization above) related to ethdebug? isn't this orthogonal?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sure, I guess you could say so, although it was a requirement in the issue. E.g. requiresting ethdebug.compilation, which just gives the compiler details shouldn't really trigger full compilation.

return true;
}

Expand Down Expand Up @@ -1227,10 +1234,14 @@ Json CompilerStack::interfaceSymbols(std::string const& _contractName) const
Json CompilerStack::ethdebug() const
{
solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful.");
solAssert(!m_contracts.empty());
return evmasm::ethdebug::resources(sourceNames(), VersionString);
}

Json CompilerStack::ethdebugCompilation() const
{
return evmasm::ethdebug::compilation(VersionString);
}

Json CompilerStack::ethdebug(std::string const& _contractName) const
{
return ethdebug(contract(_contractName), /* runtime */ false);
Expand Down
8 changes: 8 additions & 0 deletions libsolidity/interface/CompilerStack.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,11 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac
return bytecode;
}

bool needsFullCompilation() const
{
return irCodegen || irOptimization || bytecode;
}

PipelineConfig operator|(PipelineConfig const& _other) const
{
return {
Expand Down Expand Up @@ -410,6 +415,9 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac
/// Prerequisite: Successful call to parse or compile.
Json ethdebug() const override;

/// @returns a JSON representing the ethdebug compilation data (compiler name and version).
Json ethdebugCompilation() 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)); }

Expand Down
Loading