Skip to content

Commit

Permalink
CompilerStack: Yul AST generation only on demand
Browse files Browse the repository at this point in the history
- The JSON artifacts take a lot of memory so always generating them is very wasteful.
- Even when requested, they are only relevant while the current contract is being copmiled. We only really want to store the serialized JSON that will be returned to the user.
- This actually also speeds up compilation quite a bit.
  • Loading branch information
cameel committed Sep 25, 2024
1 parent 6d289e6 commit c23cac8
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 18 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Language Features:

Compiler Features:
* Code Generator: Transient storage value type state variables are now supported by the legacy pipeline.
* CompilerStack: Generate Yul ASTs only on demand to reduce memory usage.


Bugfixes:
Expand Down
27 changes: 15 additions & 12 deletions libsolidity/interface/CompilerStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -956,21 +956,24 @@ std::string const& CompilerStack::yulIR(std::string const& _contractName) const
return contract(_contractName).yulIR;
}

Json const& CompilerStack::yulIRAst(std::string const& _contractName) const
Json CompilerStack::yulIRAst(std::string const& _contractName) const
{
solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful.");
solUnimplementedAssert(!isExperimentalSolidity());
return contract(_contractName).yulIRAst;

// NOTE: Intentionally not using LazyInit. The artifact can get very large and we don't want to
// keep it around when compiling a large project containing many contracts.
return loadGeneratedIR(contract(_contractName).yulIR).astJson();
}

Json const& CompilerStack::yulCFGJson(std::string const& _contractName) const
Json CompilerStack::yulCFGJson(std::string const& _contractName) const
{
if (m_stackState != CompilationSuccessful)
solThrow(CompilerError, "Compilation was not successful.");

solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful.");
solUnimplementedAssert(!isExperimentalSolidity());

return contract(_contractName).yulCFGJson;
// NOTE: Intentionally not using LazyInit. The artifact can get very large and we don't want to
// keep it around when compiling a large project containing many contracts.
return loadGeneratedIR(contract(_contractName).yulIR).cfgJson();
}

std::string const& CompilerStack::yulIROptimized(std::string const& _contractName) const
Expand All @@ -979,11 +982,14 @@ std::string const& CompilerStack::yulIROptimized(std::string const& _contractNam
return contract(_contractName).yulIROptimized;
}

Json const& CompilerStack::yulIROptimizedAst(std::string const& _contractName) const
Json CompilerStack::yulIROptimizedAst(std::string const& _contractName) const
{
solAssert(m_stackState == CompilationSuccessful, "Compilation was not successful.");
solUnimplementedAssert(!isExperimentalSolidity());
return contract(_contractName).yulIROptimizedAst;

// NOTE: Intentionally not using LazyInit. The artifact can get very large and we don't want to
// keep it around when compiling a large project containing many contracts.
return loadGeneratedIR(contract(_contractName).yulIROptimized).astJson();
}

evmasm::LinkerObject const& CompilerStack::object(std::string const& _contractName) const
Expand Down Expand Up @@ -1539,13 +1545,10 @@ void CompilerStack::generateIR(ContractDefinition const& _contract, bool _unopti
}

YulStack stack = loadGeneratedIR(compiledContract.yulIR);
compiledContract.yulIRAst = stack.astJson();
compiledContract.yulCFGJson = stack.cfgJson();
if (!_unoptimizedOnly)
{
stack.optimize();
compiledContract.yulIROptimized = stack.print();
compiledContract.yulIROptimizedAst = stack.astJson();
}
}

Expand Down
9 changes: 3 additions & 6 deletions libsolidity/interface/CompilerStack.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,15 +295,15 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac
std::string const& yulIR(std::string const& _contractName) const;

/// @returns the IR representation of a contract AST in format.
Json const& yulIRAst(std::string const& _contractName) const;
Json yulIRAst(std::string const& _contractName) const;

/// @returns the optimized IR representation of a contract.
std::string const& yulIROptimized(std::string const& _contractName) const;

/// @returns the optimized IR representation of a contract AST in JSON format.
Json const& yulIROptimizedAst(std::string const& _contractName) const;
Json yulIROptimizedAst(std::string const& _contractName) const;

Json const& yulCFGJson(std::string const& _contractName) const;
Json yulCFGJson(std::string const& _contractName) const;

/// @returns the assembled object for a contract.
virtual evmasm::LinkerObject const& object(std::string const& _contractName) const override;
Expand Down Expand Up @@ -416,9 +416,6 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac
evmasm::LinkerObject runtimeObject; ///< Runtime object.
std::string yulIR; ///< Yul IR code straight from the code generator.
std::string yulIROptimized; ///< Reparsed and possibly optimized Yul IR code.
Json yulIRAst; ///< JSON AST of Yul IR code.
Json yulIROptimizedAst; ///< JSON AST of optimized Yul IR code.
Json yulCFGJson; ///< JSON CFG of Yul IR code.
util::LazyInit<std::string const> metadata; ///< The metadata json that will be hashed into the chain.
util::LazyInit<Json const> abi;
util::LazyInit<Json const> storageLayout;
Expand Down

0 comments on commit c23cac8

Please sign in to comment.