Skip to content

Commit df91531

Browse files
authored
Merge pull request #15560 from ethereum/yul_ast_contains_dialect
Yul AST contains dialect
2 parents 20d84a9 + 96e63ab commit df91531

37 files changed

+127
-109
lines changed

libsolidity/ast/ASTJsonImporter.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ ASTPointer<InlineAssembly> ASTJsonImporter::createInlineAssembly(Json const& _no
742742
flags->emplace_back(std::make_shared<ASTString>(flag.get<std::string>()));
743743
}
744744
}
745-
std::shared_ptr<yul::AST> operations = std::make_shared<yul::AST>(yul::AsmJsonImporter(m_sourceNames).createAST(member(_node, "AST")));
745+
std::shared_ptr<yul::AST> operations = std::make_shared<yul::AST>(yul::AsmJsonImporter(dialect, m_sourceNames).createAST(member(_node, "AST")));
746746
return createASTNode<InlineAssembly>(
747747
_node,
748748
nullOrASTString(_node, "documentation"),

libsolidity/codegen/CompilerContext.cpp

+15-14
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ void CompilerContext::appendInlineAssembly(
444444
yul::Parser(errorReporter, dialect, std::move(locationOverride))
445445
.parse(charStream);
446446
#ifdef SOL_OUTPUT_ASM
447-
cout << yul::AsmPrinter(&dialect)(*parserResult) << endl;
447+
std::cout << yul::AsmPrinter::format(*parserResult) << std::endl;
448448
#endif
449449

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

487487
solAssert(!dialect.providesObjectAccess());
488-
optimizeYul(obj, dialect, _optimiserSettings, externallyUsedIdentifiers);
488+
optimizeYul(obj, _optimiserSettings, externallyUsedIdentifiers);
489489

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

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

504503
#ifdef SOL_OUTPUT_ASM
505-
cout << "After optimizer:" << endl;
506-
cout << yul::AsmPrinter(&dialect)(*parserResult) << endl;
504+
std::cout << "After optimizer:" << std::endl;
505+
std::cout << yul::AsmPrinter::format(*parserResult) << std::endl;
507506
#endif
508507
}
509508
else if (_system)
@@ -533,16 +532,18 @@ void CompilerContext::appendInlineAssembly(
533532
}
534533

535534

536-
void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, OptimiserSettings const& _optimiserSettings, std::set<yul::YulName> const& _externalIdentifiers)
535+
void CompilerContext::optimizeYul(yul::Object& _object, OptimiserSettings const& _optimiserSettings, std::set<yul::YulName> const& _externalIdentifiers)
537536
{
537+
yulAssert(_object.dialect());
538+
auto const* evmDialect = dynamic_cast<yul::EVMDialect const*>(_object.dialect());
539+
yulAssert(evmDialect);
538540
#ifdef SOL_OUTPUT_ASM
539-
cout << yul::AsmPrinter(*dialect)(*_object.code) << endl;
541+
std::cout << yul::AsmPrinter::format(*_object.code()) << std::endl;
540542
#endif
541543

542544
bool const isCreation = runtimeContext() != nullptr;
543-
yul::GasMeter meter(_dialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment);
545+
yul::GasMeter meter(*evmDialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment);
544546
yul::OptimiserSuite::run(
545-
_dialect,
546547
&meter,
547548
_object,
548549
_optimiserSettings.optimizeStackAllocation,
@@ -553,8 +554,8 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _
553554
);
554555

555556
#ifdef SOL_OUTPUT_ASM
556-
cout << "After optimizer:" << endl;
557-
cout << yul::AsmPrinter(*dialect)(*object.code) << endl;
557+
std::cout << "After optimizer:" << std::endl;
558+
std::cout << yul::AsmPrinter::format(*_object.code()) << std::endl;
558559
#endif
559560
}
560561

libsolidity/codegen/CompilerContext.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ class CompilerContext
277277
/// Otherwise returns "revert(0, 0)".
278278
std::string revertReasonIfDebug(std::string const& _message = "");
279279

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

282282
/// Appends arbitrary data to the end of the bytecode.
283283
void appendToAuxiliaryData(bytes const& _data) { m_asm->appendToAuxiliaryData(_data); }

libsolidity/codegen/ContractCompiler.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
932932

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

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

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

950-
m_context.optimizeYul(object, *dialect, m_optimiserSettings);
950+
m_context.optimizeYul(object, m_optimiserSettings);
951951

952952
code = object.code().get();
953953
analysisInfo = object.analysisInfo.get();

libyul/AST.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
namespace solidity::yul
3737
{
3838

39+
struct Dialect;
40+
3941
struct NameWithDebugData { langutil::DebugData::ConstPtr debugData; YulName name; };
4042
using NameWithDebugDataList = std::vector<NameWithDebugData>;
4143

@@ -103,10 +105,12 @@ struct Leave { langutil::DebugData::ConstPtr debugData; };
103105
class AST
104106
{
105107
public:
106-
explicit AST(Block _root): m_root(std::move(_root)) {}
108+
AST(Dialect const& _dialect, Block _root): m_dialect(_dialect), m_root(std::move(_root)) {}
107109

108-
[[nodiscard]] Block const& root() const { return m_root; }
110+
Dialect const& dialect() const { return m_dialect; }
111+
Block const& root() const { return m_root; }
109112
private:
113+
Dialect const& m_dialect;
110114
Block m_root;
111115
};
112116

libyul/AsmAnalysis.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,10 @@ bool AsmAnalyzer::analyze(Block const& _block)
8686
return watcher.ok();
8787
}
8888

89-
AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object)
89+
AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Object const& _object)
9090
{
91-
return analyzeStrictAssertCorrect(_dialect, _object.code()->root(), _object.summarizeStructure());
91+
yulAssert(_object.dialect());
92+
return analyzeStrictAssertCorrect(*_object.dialect(), _object.code()->root(), _object.summarizeStructure());
9293
}
9394

9495
AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(

libyul/AsmAnalysis.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class AsmAnalyzer
8181

8282
/// Performs analysis on the outermost code of the given object and returns the analysis info.
8383
/// Asserts on failure.
84-
static AsmAnalysisInfo analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object);
84+
static AsmAnalysisInfo analyzeStrictAssertCorrect(Object const& _object);
8585
static AsmAnalysisInfo analyzeStrictAssertCorrect(
8686
Dialect const& _dialect,
8787
Block const& _astRoot,

libyul/AsmJsonImporter.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ SourceLocation const AsmJsonImporter::createSourceLocation(Json const& _node)
5151

5252
AST AsmJsonImporter::createAST(solidity::Json const& _node)
5353
{
54-
return AST(createBlock(_node));
54+
return {m_dialect, createBlock(_node)};
5555
}
5656

5757
template <class T>

libyul/AsmJsonImporter.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,16 @@
3232
namespace solidity::yul
3333
{
3434

35+
struct Dialect;
36+
3537
/**
3638
* Component that imports an AST from json format to the internal format
3739
*/
3840
class AsmJsonImporter
3941
{
4042
public:
41-
explicit AsmJsonImporter(std::vector<std::shared_ptr<std::string const>> const& _sourceNames):
43+
explicit AsmJsonImporter(Dialect const& _dialect, std::vector<std::shared_ptr<std::string const>> const& _sourceNames):
44+
m_dialect(_dialect),
4245
m_sourceNames(_sourceNames)
4346
{}
4447

@@ -73,6 +76,7 @@ class AsmJsonImporter
7376
yul::Break createBreak(Json const& _node);
7477
yul::Continue createContinue(Json const& _node);
7578

79+
Dialect const& m_dialect;
7680
std::vector<std::shared_ptr<std::string const>> const& m_sourceNames;
7781
};
7882

libyul/AsmParser.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ std::unique_ptr<AST> Parser::parseInline(std::shared_ptr<Scanner> const& _scanne
125125
m_scanner = _scanner;
126126
if (m_useSourceLocationFrom == UseSourceLocationFrom::Comments)
127127
fetchDebugDataFromComment();
128-
return std::make_unique<AST>(parseBlock());
128+
return std::make_unique<AST>(m_dialect, parseBlock());
129129
}
130130
catch (FatalError const& error)
131131
{

libyul/AsmPrinter.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ using namespace solidity::langutil;
4242
using namespace solidity::util;
4343
using namespace solidity::yul;
4444

45+
std::string AsmPrinter::format(
46+
AST const& _ast,
47+
std::optional<std::map<unsigned, std::shared_ptr<std::string const>>> const& _sourceIndexToName,
48+
DebugInfoSelection const& _debugInfoSelection,
49+
CharStreamProvider const* _soliditySourceProvider)
50+
{
51+
return AsmPrinter{_ast.dialect(), _sourceIndexToName, _debugInfoSelection, _soliditySourceProvider}(_ast.root());
52+
}
53+
54+
4555
std::string AsmPrinter::operator()(Literal const& _literal)
4656
{
4757
yulAssert(validLiteral(_literal));

libyul/AsmPrinter.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,16 @@ struct Dialect;
4646
class AsmPrinter
4747
{
4848
public:
49+
static std::string format(
50+
AST const& _ast,
51+
std::optional<std::map<unsigned, std::shared_ptr<std::string const>>> const& _sourceIndexToName = {},
52+
langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(),
53+
langutil::CharStreamProvider const* _soliditySourceProvider = nullptr
54+
);
55+
4956
explicit AsmPrinter(
5057
Dialect const&,
51-
std::optional<std::map<unsigned, std::shared_ptr<std::string const>>> _sourceIndexToName = {},
58+
std::optional<std::map<unsigned, std::shared_ptr<std::string const>>> const& _sourceIndexToName = {},
5259
langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(),
5360
langutil::CharStreamProvider const* _soliditySourceProvider = nullptr
5461
):

libyul/CompilabilityChecker.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,12 @@ using namespace solidity::yul;
3131
using namespace solidity::util;
3232

3333
CompilabilityChecker::CompilabilityChecker(
34-
Dialect const& _dialect,
3534
Object const& _object,
3635
bool _optimizeStackAllocation
3736
)
3837
{
3938
yulAssert(_object.hasCode());
40-
if (auto const* evmDialect = dynamic_cast<EVMDialect const*>(&_dialect))
39+
if (auto const* evmDialect = dynamic_cast<EVMDialect const*>(_object.dialect()))
4140
{
4241
NoOutputEVMDialect noOutputDialect(*evmDialect);
4342

libyul/CompilabilityChecker.h

-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ namespace solidity::yul
4545
struct CompilabilityChecker
4646
{
4747
CompilabilityChecker(
48-
Dialect const& _dialect,
4948
Object const& _object,
5049
bool _optimizeStackAllocation
5150
);

libyul/Object.cpp

+13-4
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,15 @@ std::string Object::toString(
4949
) const
5050
{
5151
yulAssert(hasCode(), "No code");
52+
yulAssert(dialect(), "No dialect");
5253
yulAssert(debugData, "No debug data");
5354

54-
std::string inner = "code " + AsmPrinter(
55-
m_dialect,
55+
std::string inner = "code " + AsmPrinter::format(
56+
*code(),
5657
debugData->sourceNames,
5758
_debugInfoSelection,
5859
_soliditySourceProvider
59-
)(code()->root());
60+
);
6061

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

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

102104
Json subObjectsJson = Json::array();
103105
for (std::shared_ptr<ObjectNode> const& subObject: subObjects)
@@ -240,3 +242,10 @@ bool Object::hasContiguousSourceIndices() const
240242
solAssert(maxSourceIndex + 1 >= indices.size());
241243
return indices.size() == 0 || indices.size() == maxSourceIndex + 1;
242244
}
245+
246+
Dialect const* Object::dialect() const
247+
{
248+
if (!m_code)
249+
return nullptr;
250+
return &m_code->dialect();
251+
}

libyul/Object.h

+2-4
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121

2222
#pragma once
2323

24-
#include <libyul/AsmPrinter.h>
2524
#include <libyul/ASTForward.h>
25+
#include <libyul/AsmPrinter.h>
2626

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

165-
Dialect const& dialect() const { return m_dialect; }
164+
Dialect const* dialect() const;
166165

167166
private:
168-
Dialect const& m_dialect;
169167
std::shared_ptr<AST const> m_code;
170168
};
171169

libyul/ObjectOptimizer.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ void ObjectOptimizer::optimize(Object& _object, Settings const& _settings, bool
9090
}
9191

9292
OptimiserSuite::run(
93-
dialect,
9493
meter.get(),
9594
_object,
9695
_settings.optimizeStackAllocation,
@@ -118,15 +117,15 @@ void ObjectOptimizer::overwriteWithOptimizedObject(util::h256 _cacheKey, Object&
118117
CachedObject const& cachedObject = m_cachedObjects.at(_cacheKey);
119118

120119
yulAssert(cachedObject.optimizedAST);
121-
_object.setCode(std::make_shared<AST>(ASTCopier{}.translate(*cachedObject.optimizedAST)));
120+
yulAssert(cachedObject.dialect);
121+
_object.setCode(std::make_shared<AST>(*cachedObject.dialect, ASTCopier{}.translate(*cachedObject.optimizedAST)));
122122
yulAssert(_object.code());
123+
yulAssert(_object.dialect());
123124

124125
// There's no point in caching AnalysisInfo because it references AST nodes. It can't be shared
125126
// by multiple ASTs and it's easier to recalculate it than properly clone it.
126-
yulAssert(cachedObject.dialect);
127127
_object.analysisInfo = std::make_shared<AsmAnalysisInfo>(
128128
AsmAnalyzer::analyzeStrictAssertCorrect(
129-
*cachedObject.dialect,
130129
_object
131130
)
132131
);

libyul/ObjectParser.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ std::shared_ptr<Object> ObjectParser::parse(std::shared_ptr<Scanner> const& _sca
4949
if (currentToken() == Token::LBrace)
5050
{
5151
// Special case: Code-only form.
52-
object = std::make_shared<Object>(m_dialect);
52+
object = std::make_shared<Object>();
5353
object->name = "object";
5454
auto sourceNameMapping = tryParseSourceNameMapping();
5555
object->debugData = std::make_shared<ObjectDebugData>(ObjectDebugData{sourceNameMapping});
@@ -74,7 +74,7 @@ std::shared_ptr<Object> ObjectParser::parseObject(Object* _containingObject)
7474
{
7575
RecursionGuard guard(*this);
7676

77-
std::shared_ptr<Object> ret = std::make_shared<Object>(m_dialect);
77+
std::shared_ptr<Object> ret = std::make_shared<Object>();
7878

7979
auto sourceNameMapping = tryParseSourceNameMapping();
8080
ret->debugData = std::make_shared<ObjectDebugData>(ObjectDebugData{sourceNameMapping});

0 commit comments

Comments
 (0)