Skip to content

Commit

Permalink
Merge pull request #15560 from ethereum/yul_ast_contains_dialect
Browse files Browse the repository at this point in the history
Yul AST contains dialect
  • Loading branch information
clonker authored Dec 3, 2024
2 parents 20d84a9 + 96e63ab commit df91531
Show file tree
Hide file tree
Showing 37 changed files with 127 additions and 109 deletions.
2 changes: 1 addition & 1 deletion libsolidity/ast/ASTJsonImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,7 @@ ASTPointer<InlineAssembly> ASTJsonImporter::createInlineAssembly(Json const& _no
flags->emplace_back(std::make_shared<ASTString>(flag.get<std::string>()));
}
}
std::shared_ptr<yul::AST> operations = std::make_shared<yul::AST>(yul::AsmJsonImporter(m_sourceNames).createAST(member(_node, "AST")));
std::shared_ptr<yul::AST> operations = std::make_shared<yul::AST>(yul::AsmJsonImporter(dialect, m_sourceNames).createAST(member(_node, "AST")));
return createASTNode<InlineAssembly>(
_node,
nullOrASTString(_node, "documentation"),
Expand Down
29 changes: 15 additions & 14 deletions libsolidity/codegen/CompilerContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ void CompilerContext::appendInlineAssembly(
yul::Parser(errorReporter, dialect, std::move(locationOverride))
.parse(charStream);
#ifdef SOL_OUTPUT_ASM
cout << yul::AsmPrinter(&dialect)(*parserResult) << endl;
std::cout << yul::AsmPrinter::format(*parserResult) << std::endl;
#endif

auto reportError = [&](std::string const& _context)
Expand Down Expand Up @@ -481,29 +481,28 @@ void CompilerContext::appendInlineAssembly(
// so we essentially only optimize the ABI functions.
if (_optimiserSettings.runYulOptimiser && _localVariables.empty())
{
yul::Object obj{dialect};
yul::Object obj;
obj.setCode(parserResult, std::make_shared<yul::AsmAnalysisInfo>(analysisInfo));

solAssert(!dialect.providesObjectAccess());
optimizeYul(obj, dialect, _optimiserSettings, externallyUsedIdentifiers);
optimizeYul(obj, _optimiserSettings, externallyUsedIdentifiers);

if (_system)
{
// Store as generated sources, but first re-parse to update the source references.
solAssert(m_generatedYulUtilityCode.empty(), "");
m_generatedYulUtilityCode = yul::AsmPrinter(obj.dialect())(obj.code()->root());
std::string code = yul::AsmPrinter{obj.dialect()}(obj.code()->root());
m_generatedYulUtilityCode = yul::AsmPrinter::format(*obj.code());
langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName);
obj.setCode(yul::Parser(errorReporter, dialect).parse(charStream));
obj.analysisInfo = std::make_shared<yul::AsmAnalysisInfo>(yul::AsmAnalyzer::analyzeStrictAssertCorrect(dialect, obj));
obj.analysisInfo = std::make_shared<yul::AsmAnalysisInfo>(yul::AsmAnalyzer::analyzeStrictAssertCorrect(obj));
}

analysisInfo = std::move(*obj.analysisInfo);
toBeAssembledAST = obj.code();

#ifdef SOL_OUTPUT_ASM
cout << "After optimizer:" << endl;
cout << yul::AsmPrinter(&dialect)(*parserResult) << endl;
std::cout << "After optimizer:" << std::endl;
std::cout << yul::AsmPrinter::format(*parserResult) << std::endl;
#endif
}
else if (_system)
Expand Down Expand Up @@ -533,16 +532,18 @@ void CompilerContext::appendInlineAssembly(
}


void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, OptimiserSettings const& _optimiserSettings, std::set<yul::YulName> const& _externalIdentifiers)
void CompilerContext::optimizeYul(yul::Object& _object, OptimiserSettings const& _optimiserSettings, std::set<yul::YulName> const& _externalIdentifiers)
{
yulAssert(_object.dialect());
auto const* evmDialect = dynamic_cast<yul::EVMDialect const*>(_object.dialect());
yulAssert(evmDialect);
#ifdef SOL_OUTPUT_ASM
cout << yul::AsmPrinter(*dialect)(*_object.code) << endl;
std::cout << yul::AsmPrinter::format(*_object.code()) << std::endl;
#endif

bool const isCreation = runtimeContext() != nullptr;
yul::GasMeter meter(_dialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment);
yul::GasMeter meter(*evmDialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment);
yul::OptimiserSuite::run(
_dialect,
&meter,
_object,
_optimiserSettings.optimizeStackAllocation,
Expand All @@ -553,8 +554,8 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _
);

#ifdef SOL_OUTPUT_ASM
cout << "After optimizer:" << endl;
cout << yul::AsmPrinter(*dialect)(*object.code) << endl;
std::cout << "After optimizer:" << std::endl;
std::cout << yul::AsmPrinter::format(*_object.code()) << std::endl;
#endif
}

Expand Down
2 changes: 1 addition & 1 deletion libsolidity/codegen/CompilerContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ class CompilerContext
/// Otherwise returns "revert(0, 0)".
std::string revertReasonIfDebug(std::string const& _message = "");

void optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, OptimiserSettings const& _optimiserSetting, std::set<yul::YulName> const& _externalIdentifiers = {});
void optimizeYul(yul::Object& _object, OptimiserSettings const& _optimiserSetting, std::set<yul::YulName> const& _externalIdentifiers = {});

/// Appends arbitrary data to the end of the bytecode.
void appendToAuxiliaryData(bytes const& _data) { m_asm->appendToAuxiliaryData(_data); }
Expand Down
8 changes: 4 additions & 4 deletions libsolidity/codegen/ContractCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)

// Only used in the scope below, but required to live outside to keep the
// std::shared_ptr's alive
yul::Object object{_inlineAssembly.dialect()};
yul::Object object;

// The optimiser cannot handle external references
if (
Expand All @@ -944,10 +944,10 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
solAssert(dialect, "");

// Create a modifiable copy of the code and analysis
object.setCode(std::make_shared<yul::AST>(yul::ASTCopier().translate(code->root())));
object.analysisInfo = std::make_shared<yul::AsmAnalysisInfo>(yul::AsmAnalyzer::analyzeStrictAssertCorrect(*dialect, object));
object.setCode(std::make_shared<yul::AST>(_inlineAssembly.dialect(), yul::ASTCopier().translate(code->root())));
object.analysisInfo = std::make_shared<yul::AsmAnalysisInfo>(yul::AsmAnalyzer::analyzeStrictAssertCorrect(object));

m_context.optimizeYul(object, *dialect, m_optimiserSettings);
m_context.optimizeYul(object, m_optimiserSettings);

code = object.code().get();
analysisInfo = object.analysisInfo.get();
Expand Down
8 changes: 6 additions & 2 deletions libyul/AST.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
namespace solidity::yul
{

struct Dialect;

struct NameWithDebugData { langutil::DebugData::ConstPtr debugData; YulName name; };
using NameWithDebugDataList = std::vector<NameWithDebugData>;

Expand Down Expand Up @@ -103,10 +105,12 @@ struct Leave { langutil::DebugData::ConstPtr debugData; };
class AST
{
public:
explicit AST(Block _root): m_root(std::move(_root)) {}
AST(Dialect const& _dialect, Block _root): m_dialect(_dialect), m_root(std::move(_root)) {}

[[nodiscard]] Block const& root() const { return m_root; }
Dialect const& dialect() const { return m_dialect; }
Block const& root() const { return m_root; }
private:
Dialect const& m_dialect;
Block m_root;
};

Expand Down
5 changes: 3 additions & 2 deletions libyul/AsmAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ bool AsmAnalyzer::analyze(Block const& _block)
return watcher.ok();
}

AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object)
AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Object const& _object)
{
return analyzeStrictAssertCorrect(_dialect, _object.code()->root(), _object.summarizeStructure());
yulAssert(_object.dialect());
return analyzeStrictAssertCorrect(*_object.dialect(), _object.code()->root(), _object.summarizeStructure());
}

AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(
Expand Down
2 changes: 1 addition & 1 deletion libyul/AsmAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class AsmAnalyzer

/// Performs analysis on the outermost code of the given object and returns the analysis info.
/// Asserts on failure.
static AsmAnalysisInfo analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object);
static AsmAnalysisInfo analyzeStrictAssertCorrect(Object const& _object);
static AsmAnalysisInfo analyzeStrictAssertCorrect(
Dialect const& _dialect,
Block const& _astRoot,
Expand Down
2 changes: 1 addition & 1 deletion libyul/AsmJsonImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ SourceLocation const AsmJsonImporter::createSourceLocation(Json const& _node)

AST AsmJsonImporter::createAST(solidity::Json const& _node)
{
return AST(createBlock(_node));
return {m_dialect, createBlock(_node)};
}

template <class T>
Expand Down
6 changes: 5 additions & 1 deletion libyul/AsmJsonImporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@
namespace solidity::yul
{

struct Dialect;

/**
* Component that imports an AST from json format to the internal format
*/
class AsmJsonImporter
{
public:
explicit AsmJsonImporter(std::vector<std::shared_ptr<std::string const>> const& _sourceNames):
explicit AsmJsonImporter(Dialect const& _dialect, std::vector<std::shared_ptr<std::string const>> const& _sourceNames):
m_dialect(_dialect),
m_sourceNames(_sourceNames)
{}

Expand Down Expand Up @@ -73,6 +76,7 @@ class AsmJsonImporter
yul::Break createBreak(Json const& _node);
yul::Continue createContinue(Json const& _node);

Dialect const& m_dialect;
std::vector<std::shared_ptr<std::string const>> const& m_sourceNames;
};

Expand Down
2 changes: 1 addition & 1 deletion libyul/AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ std::unique_ptr<AST> Parser::parseInline(std::shared_ptr<Scanner> const& _scanne
m_scanner = _scanner;
if (m_useSourceLocationFrom == UseSourceLocationFrom::Comments)
fetchDebugDataFromComment();
return std::make_unique<AST>(parseBlock());
return std::make_unique<AST>(m_dialect, parseBlock());
}
catch (FatalError const& error)
{
Expand Down
10 changes: 10 additions & 0 deletions libyul/AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ using namespace solidity::langutil;
using namespace solidity::util;
using namespace solidity::yul;

std::string AsmPrinter::format(
AST const& _ast,
std::optional<std::map<unsigned, std::shared_ptr<std::string const>>> const& _sourceIndexToName,
DebugInfoSelection const& _debugInfoSelection,
CharStreamProvider const* _soliditySourceProvider)
{
return AsmPrinter{_ast.dialect(), _sourceIndexToName, _debugInfoSelection, _soliditySourceProvider}(_ast.root());
}


std::string AsmPrinter::operator()(Literal const& _literal)
{
yulAssert(validLiteral(_literal));
Expand Down
9 changes: 8 additions & 1 deletion libyul/AsmPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,16 @@ struct Dialect;
class AsmPrinter
{
public:
static std::string format(
AST const& _ast,
std::optional<std::map<unsigned, std::shared_ptr<std::string const>>> const& _sourceIndexToName = {},
langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(),
langutil::CharStreamProvider const* _soliditySourceProvider = nullptr
);

explicit AsmPrinter(
Dialect const&,
std::optional<std::map<unsigned, std::shared_ptr<std::string const>>> _sourceIndexToName = {},
std::optional<std::map<unsigned, std::shared_ptr<std::string const>>> const& _sourceIndexToName = {},
langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(),
langutil::CharStreamProvider const* _soliditySourceProvider = nullptr
):
Expand Down
3 changes: 1 addition & 2 deletions libyul/CompilabilityChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,12 @@ using namespace solidity::yul;
using namespace solidity::util;

CompilabilityChecker::CompilabilityChecker(
Dialect const& _dialect,
Object const& _object,
bool _optimizeStackAllocation
)
{
yulAssert(_object.hasCode());
if (auto const* evmDialect = dynamic_cast<EVMDialect const*>(&_dialect))
if (auto const* evmDialect = dynamic_cast<EVMDialect const*>(_object.dialect()))
{
NoOutputEVMDialect noOutputDialect(*evmDialect);

Expand Down
1 change: 0 additions & 1 deletion libyul/CompilabilityChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ namespace solidity::yul
struct CompilabilityChecker
{
CompilabilityChecker(
Dialect const& _dialect,
Object const& _object,
bool _optimizeStackAllocation
);
Expand Down
17 changes: 13 additions & 4 deletions libyul/Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@ std::string Object::toString(
) const
{
yulAssert(hasCode(), "No code");
yulAssert(dialect(), "No dialect");
yulAssert(debugData, "No debug data");

std::string inner = "code " + AsmPrinter(
m_dialect,
std::string inner = "code " + AsmPrinter::format(
*code(),
debugData->sourceNames,
_debugInfoSelection,
_soliditySourceProvider
)(code()->root());
);

for (auto const& obj: subObjects)
inner += "\n" + obj->toString(_debugInfoSelection, _soliditySourceProvider);
Expand Down Expand Up @@ -94,10 +95,11 @@ std::string ObjectDebugData::formatUseSrcComment() const
Json Object::toJson() const
{
yulAssert(hasCode(), "No code");
yulAssert(dialect(), "No dialect");

Json codeJson;
codeJson["nodeType"] = "YulCode";
codeJson["block"] = AsmJsonConverter(m_dialect, 0 /* sourceIndex */)(code()->root());
codeJson["block"] = AsmJsonConverter(*dialect(), 0 /* sourceIndex */)(code()->root());

Json subObjectsJson = Json::array();
for (std::shared_ptr<ObjectNode> const& subObject: subObjects)
Expand Down Expand Up @@ -240,3 +242,10 @@ bool Object::hasContiguousSourceIndices() const
solAssert(maxSourceIndex + 1 >= indices.size());
return indices.size() == 0 || indices.size() == maxSourceIndex + 1;
}

Dialect const* Object::dialect() const
{
if (!m_code)
return nullptr;
return &m_code->dialect();
}
6 changes: 2 additions & 4 deletions libyul/Object.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@

#pragma once

#include <libyul/AsmPrinter.h>
#include <libyul/ASTForward.h>
#include <libyul/AsmPrinter.h>

#include <liblangutil/CharStreamProvider.h>
#include <liblangutil/DebugInfoSelection.h>
Expand Down Expand Up @@ -91,7 +91,6 @@ struct ObjectDebugData
class Object: public ObjectNode
{
public:
explicit Object(Dialect const& _dialect): m_dialect(_dialect) {}
/// @returns a (parseable) string representation.
std::string toString(
langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(),
Expand Down Expand Up @@ -162,10 +161,9 @@ class Object: public ObjectNode
/// @returns the name of the special metadata data object.
static std::string metadataName() { return ".metadata"; }

Dialect const& dialect() const { return m_dialect; }
Dialect const* dialect() const;

private:
Dialect const& m_dialect;
std::shared_ptr<AST const> m_code;
};

Expand Down
7 changes: 3 additions & 4 deletions libyul/ObjectOptimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ void ObjectOptimizer::optimize(Object& _object, Settings const& _settings, bool
}

OptimiserSuite::run(
dialect,
meter.get(),
_object,
_settings.optimizeStackAllocation,
Expand Down Expand Up @@ -118,15 +117,15 @@ void ObjectOptimizer::overwriteWithOptimizedObject(util::h256 _cacheKey, Object&
CachedObject const& cachedObject = m_cachedObjects.at(_cacheKey);

yulAssert(cachedObject.optimizedAST);
_object.setCode(std::make_shared<AST>(ASTCopier{}.translate(*cachedObject.optimizedAST)));
yulAssert(cachedObject.dialect);
_object.setCode(std::make_shared<AST>(*cachedObject.dialect, ASTCopier{}.translate(*cachedObject.optimizedAST)));
yulAssert(_object.code());
yulAssert(_object.dialect());

// There's no point in caching AnalysisInfo because it references AST nodes. It can't be shared
// by multiple ASTs and it's easier to recalculate it than properly clone it.
yulAssert(cachedObject.dialect);
_object.analysisInfo = std::make_shared<AsmAnalysisInfo>(
AsmAnalyzer::analyzeStrictAssertCorrect(
*cachedObject.dialect,
_object
)
);
Expand Down
4 changes: 2 additions & 2 deletions libyul/ObjectParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ std::shared_ptr<Object> ObjectParser::parse(std::shared_ptr<Scanner> const& _sca
if (currentToken() == Token::LBrace)
{
// Special case: Code-only form.
object = std::make_shared<Object>(m_dialect);
object = std::make_shared<Object>();
object->name = "object";
auto sourceNameMapping = tryParseSourceNameMapping();
object->debugData = std::make_shared<ObjectDebugData>(ObjectDebugData{sourceNameMapping});
Expand All @@ -74,7 +74,7 @@ std::shared_ptr<Object> ObjectParser::parseObject(Object* _containingObject)
{
RecursionGuard guard(*this);

std::shared_ptr<Object> ret = std::make_shared<Object>(m_dialect);
std::shared_ptr<Object> ret = std::make_shared<Object>();

auto sourceNameMapping = tryParseSourceNameMapping();
ret->debugData = std::make_shared<ObjectDebugData>(ObjectDebugData{sourceNameMapping});
Expand Down
Loading

0 comments on commit df91531

Please sign in to comment.