Skip to content

Commit

Permalink
yul ast class
Browse files Browse the repository at this point in the history
  • Loading branch information
clonker committed Jul 9, 2024
1 parent 40f8435 commit e8c587e
Show file tree
Hide file tree
Showing 84 changed files with 882 additions and 931 deletions.
4 changes: 2 additions & 2 deletions libsolidity/analysis/ControlFlowBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ bool ControlFlowBuilder::visit(InlineAssembly const& _inlineAssembly)
solAssert(!!m_currentNode && !m_inlineAssembly, "");

m_inlineAssembly = &_inlineAssembly;
(*this)(_inlineAssembly.operations());
(*this)(_inlineAssembly.operations().block());
m_inlineAssembly = nullptr;

return false;
Expand Down Expand Up @@ -582,7 +582,7 @@ void ControlFlowBuilder::operator()(yul::FunctionCall const& _functionCall)
solAssert(m_currentNode && m_inlineAssembly, "");
yul::ASTWalker::operator()(_functionCall);

if (auto const *builtinFunction = m_inlineAssembly->nameRepository().builtin(_functionCall.functionName.name))
if (auto const *builtinFunction = m_inlineAssembly->operations().nameRepository().builtin(_functionCall.functionName.name))
{
if (builtinFunction->data->controlFlowSideEffects.canTerminate)
connect(m_currentNode, m_transactionReturnNode);
Expand Down
4 changes: 2 additions & 2 deletions libsolidity/analysis/PostTypeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -507,8 +507,8 @@ class LValueChecker: public ASTConstVisitor
if (m_willBeWrittenTo)
return;

YulLValueChecker yulChecker{m_declaration->name(), _inlineAssembly.nameRepository()};
yulChecker(_inlineAssembly.operations());
YulLValueChecker yulChecker{m_declaration->name(), _inlineAssembly.operations().nameRepository()};
yulChecker(_inlineAssembly.operations().block());
m_willBeWrittenTo = yulChecker.willBeWrittenTo();
}
private:
Expand Down
4 changes: 2 additions & 2 deletions libsolidity/analysis/ReferencesResolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,8 @@ bool ReferencesResolver::visit(UsingForDirective const& _usingFor)
bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly)
{
m_yulAnnotation = &_inlineAssembly.annotation();
m_yulNameRepository = &_inlineAssembly.nameRepository();
(*this)(_inlineAssembly.operations());
m_yulNameRepository = &_inlineAssembly.operations().nameRepository();
(*this)(_inlineAssembly.operations().block());
m_yulNameRepository = nullptr;
m_yulAnnotation = nullptr;

Expand Down
2 changes: 1 addition & 1 deletion libsolidity/analysis/SyntaxChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ bool SyntaxChecker::visit(InlineAssembly const& _inlineAssembly)
if (!m_useYulOptimizer)
return false;

if (yul::MSizeFinder::containsMSize(_inlineAssembly.nameRepository(), _inlineAssembly.operations()))
if (yul::MSizeFinder::containsMSize(_inlineAssembly.operations()))
m_errorReporter.syntaxError(
6553_error,
_inlineAssembly.location(),
Expand Down
4 changes: 2 additions & 2 deletions libsolidity/analysis/TypeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -944,10 +944,10 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
yul::AsmAnalyzer analyzer(
*_inlineAssembly.annotation().analysisInfo,
m_errorReporter,
_inlineAssembly.nameRepository(),
_inlineAssembly.operations().nameRepository(),
identifierAccess
);
if (!analyzer.analyze(_inlineAssembly.operations()))
if (!analyzer.analyze(_inlineAssembly.operations().block()))
solAssert(m_errorReporter.hasErrors());
_inlineAssembly.annotation().hasMemoryEffects =
lvalueAccessToMemoryVariable ||
Expand Down
4 changes: 2 additions & 2 deletions libsolidity/analysis/ViewPureChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,9 @@ void ViewPureChecker::endVisit(Identifier const& _identifier)
void ViewPureChecker::endVisit(InlineAssembly const& _inlineAssembly)
{
AssemblyViewPureChecker{
_inlineAssembly.nameRepository(),
_inlineAssembly.operations().nameRepository(),
[&](StateMutability _mutability, SourceLocation const& _location) { reportMutability(_mutability, _location); }
}(_inlineAssembly.operations());
}(_inlineAssembly.operations().block());
}

void ViewPureChecker::reportMutability(
Expand Down
8 changes: 2 additions & 6 deletions libsolidity/ast/AST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1066,17 +1066,13 @@ InlineAssembly::InlineAssembly(
int64_t _id,
SourceLocation const& _location,
ASTPointer<ASTString> const& _docString,
std::unique_ptr<yul::YulNameRepository> _yulNameRepository,
ASTPointer<std::vector<ASTPointer<ASTString>>> _flags,
std::shared_ptr<yul::Block> _operations
std::shared_ptr<yul::AST> _operations
):
Statement(_id, _location, _docString),
m_yulNameRepository(std::move(_yulNameRepository)),
m_flags(std::move(_flags)),
m_operations(std::move(_operations))
{
solAssert(m_yulNameRepository != nullptr);
}
{}

InlineAssembly::~InlineAssembly() = default;

Expand Down
11 changes: 4 additions & 7 deletions libsolidity/ast/AST.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
namespace solidity::yul
{
// Forward-declaration to <yul/AST.h>
struct Block;
class AST;
class YulNameRepository;
}

Expand Down Expand Up @@ -1567,24 +1567,21 @@ class InlineAssembly: public Statement
int64_t _id,
SourceLocation const& _location,
ASTPointer<ASTString> const& _docString,
std::unique_ptr<yul::YulNameRepository> _yulNameRepository,
ASTPointer<std::vector<ASTPointer<ASTString>>> _flags,
std::shared_ptr<yul::Block> _operations
std::shared_ptr<yul::AST> _operations
);
~InlineAssembly() override;
void accept(ASTVisitor& _visitor) override;
void accept(ASTConstVisitor& _visitor) const override;

yul::YulNameRepository& nameRepository() const { return *m_yulNameRepository; }
yul::Block const& operations() const { return *m_operations; }
yul::AST const& operations() const { return *m_operations; }
ASTPointer<std::vector<ASTPointer<ASTString>>> const& flags() const { return m_flags; }

InlineAssemblyAnnotation& annotation() const override;

private:
std::unique_ptr<yul::YulNameRepository> mutable m_yulNameRepository;
ASTPointer<std::vector<ASTPointer<ASTString>>> m_flags;
std::shared_ptr<yul::Block> m_operations;
std::shared_ptr<yul::AST> m_operations;
};

/**
Expand Down
6 changes: 3 additions & 3 deletions libsolidity/ast/ASTJsonExporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,7 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node)
for (auto const& it: _node.annotation().externalReferences)
if (it.first)
externalReferences.emplace_back(std::make_pair(
_node.nameRepository().labelOf(it.first->name),
_node.operations().nameRepository().labelOf(it.first->name),
inlineAssemblyIdentifierToJson(it)
));

Expand All @@ -665,9 +665,9 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node)
externalReferencesJson.emplace_back(std::move(it));

std::vector<std::pair<std::string, Json>> attributes = {
std::make_pair("AST", Json(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()), _node.nameRepository())(_node.operations()))),
std::make_pair("AST", Json(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()), _node.operations().nameRepository())(_node.operations().block()))),
std::make_pair("externalReferences", std::move(externalReferencesJson)),
std::make_pair("evmVersion", dynamic_cast<solidity::yul::EVMDialect const&>(_node.nameRepository().dialect()).evmVersion().name())
std::make_pair("evmVersion", dynamic_cast<solidity::yul::EVMDialect const&>(_node.operations().nameRepository().dialect()).evmVersion().name())
};

if (_node.flags())
Expand Down
4 changes: 1 addition & 3 deletions libsolidity/ast/ASTJsonImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -733,12 +733,10 @@ ASTPointer<InlineAssembly> ASTJsonImporter::createInlineAssembly(Json const& _no
flags->emplace_back(std::make_shared<ASTString>(flag.get<std::string>()));
}
}
auto repository = std::make_unique<yul::YulNameRepository>(dialect);
std::shared_ptr<yul::Block> operations = std::make_shared<yul::Block>(yul::AsmJsonImporter(m_sourceNames, *repository).createBlock(member(_node, "AST")));
auto operations = std::make_shared<yul::AST>(yul::AsmJsonImporter(m_sourceNames, dialect).createAST(member(_node, "AST")));
return createASTNode<InlineAssembly>(
_node,
nullOrASTString(_node, "documentation"),
std::move(repository),
std::move(flags),
operations
);
Expand Down
53 changes: 28 additions & 25 deletions libsolidity/codegen/CompilerContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
#include <liblangutil/Scanner.h>
#include <liblangutil/SourceReferenceFormatter.h>

#include <range/v3/view.hpp>

#include <utility>

// Change to "define" to output all intermediate code
Expand Down Expand Up @@ -387,24 +389,27 @@ void CompilerContext::appendInlineAssembly(
{
unsigned startStackHeight = stackHeight();
yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion);
yul::YulNameRepository nameRepository (dialect);

auto nameRepository = std::make_unique<yul::YulNameRepository>(dialect);

std::vector<yul::YulName> externallyUsedFunctionNames = _externallyUsedFunctions
| ranges::views::transform([&nameRepository](auto const& label) { return nameRepository->defineName(label); })
| ranges::to_vector;
std::vector<yul::YulName> localVariableNames = _localVariables
| ranges::views::transform([&nameRepository](auto const& label) { return nameRepository->defineName(label); })
| ranges::to_vector;
std::set<yul::YulName> externallyUsedIdentifiers;
for (auto const& fun: _externallyUsedFunctions)
externallyUsedIdentifiers.insert(nameRepository.defineName(fun));
for (auto const& var: _localVariables)
externallyUsedIdentifiers.insert(nameRepository.defineName(var));
externallyUsedIdentifiers += externallyUsedFunctionNames + localVariableNames;

yul::ExternalIdentifierAccess identifierAccess;
identifierAccess.resolve = [&](
identifierAccess.resolve = [&localVariableNames](
yul::Identifier const& _identifier,
yul::IdentifierContext,
bool _insideFunction
) -> bool
{
if (_insideFunction)
return false;
return util::contains(_localVariables, nameRepository.labelOf(_identifier.name));
return util::contains(localVariableNames, _identifier.name);
};
identifierAccess.generateCode = [&](
yul::Identifier const& _identifier,
Expand All @@ -413,9 +418,9 @@ void CompilerContext::appendInlineAssembly(
)
{
solAssert(_context == yul::IdentifierContext::RValue || _context == yul::IdentifierContext::LValue, "");
auto it = std::find(_localVariables.begin(), _localVariables.end(), nameRepository.labelOf(_identifier.name));
solAssert(it != _localVariables.end(), "");
auto stackDepth = static_cast<size_t>(distance(it, _localVariables.end()));
auto it = std::find(localVariableNames.begin(), localVariableNames.end(), _identifier.name);
solAssert(it != localVariableNames.end(), "");
auto stackDepth = static_cast<size_t>(distance(it, localVariableNames.end()));
size_t stackDiff = static_cast<size_t>(_assembly.stackHeight()) - startStackHeight + stackDepth;
if (_context == yul::IdentifierContext::LValue)
stackDiff -= 1;
Expand All @@ -440,9 +445,9 @@ void CompilerContext::appendInlineAssembly(
std::optional<langutil::SourceLocation> locationOverride;
if (!_system)
locationOverride = m_asm->currentSourceLocation();
std::shared_ptr<yul::Block> parserResult =
yul::Parser(errorReporter, nameRepository, std::move(locationOverride))
.parse(charStream);
std::shared_ptr<yul::AST> parserResult =
yul::Parser(errorReporter, dialect, std::move(locationOverride))
.parse(charStream, std::move(nameRepository));
#ifdef SOL_OUTPUT_ASM
cout << yul::AsmPrinter(&dialect)(*parserResult) << endl;
#endif
Expand Down Expand Up @@ -470,9 +475,9 @@ void CompilerContext::appendInlineAssembly(
analyzerResult = yul::AsmAnalyzer(
analysisInfo,
errorReporter,
nameRepository,
parserResult->nameRepository(),
identifierAccess.resolve
).analyze(*parserResult);
).analyze(parserResult->block());
if (!parserResult || !errorReporter.errors().empty() || !analyzerResult)
reportError("Invalid assembly generated by code generator.");

Expand All @@ -485,17 +490,17 @@ void CompilerContext::appendInlineAssembly(
obj.analysisInfo = std::make_shared<yul::AsmAnalysisInfo>(analysisInfo);

solAssert(!dialect.providesObjectAccess());
optimizeYul(obj, dialect, nameRepository, _optimiserSettings, externallyUsedIdentifiers);
optimizeYul(obj, dialect, _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(nameRepository)(*obj.code);
std::string code = yul::AsmPrinter(nameRepository)(*obj.code);
std::string code = yul::AsmPrinter(parserResult->nameRepository())(obj.code->block());
m_generatedYulUtilityCode = code;
langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName);
obj.code = yul::Parser(errorReporter, nameRepository).parse(charStream);
*obj.analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(nameRepository, obj);
obj.code = yul::Parser(errorReporter, dialect).parse(charStream);
*obj.analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(obj);
}

analysisInfo = std::move(*obj.analysisInfo);
Expand All @@ -522,7 +527,6 @@ void CompilerContext::appendInlineAssembly(
analysisInfo,
*m_asm,
m_evmVersion,
nameRepository,
identifierAccess.generateCode,
_system,
_optimiserSettings.optimizeStackAllocation
Expand All @@ -533,16 +537,15 @@ void CompilerContext::appendInlineAssembly(
}


void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, yul::YulNameRepository& _yulNameRepository, OptimiserSettings const& _optimiserSettings, std::set<yul::YulName> const& _externalIdentifiers)
void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, OptimiserSettings const& _optimiserSettings, std::set<yul::YulName> const& _externalIdentifiers)
{
#ifdef SOL_OUTPUT_ASM
cout << yul::AsmPrinter(_yulNameRepository)(*_object.code) << endl;
#endif

bool const isCreation = runtimeContext() != nullptr;
yul::GasMeter meter(_yulNameRepository, _dialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment);
yul::GasMeter meter(_object.code->nameRepository(), _dialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment);
yul::OptimiserSuite::run(
_yulNameRepository,
&meter,
_object,
_optimiserSettings.optimizeStackAllocation,
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, yul::YulNameRepository& _yulNameRepository, OptimiserSettings const& _optimiserSetting, std::set<yul::YulName> const& _externalIdentifiers = {});
void optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, 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
11 changes: 5 additions & 6 deletions libsolidity/codegen/ContractCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -926,7 +926,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
}
};

yul::Block const* code = &_inlineAssembly.operations();
yul::AST const* code = &_inlineAssembly.operations();
yul::AsmAnalysisInfo* analysisInfo = _inlineAssembly.annotation().analysisInfo.get();

// Only used in the scope below, but required to live outside to keep the
Expand All @@ -939,14 +939,14 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
_inlineAssembly.annotation().externalReferences.empty()
)
{
yul::EVMDialect const* dialect = dynamic_cast<decltype(dialect)>(&_inlineAssembly.nameRepository().dialect());
yul::EVMDialect const* dialect = dynamic_cast<decltype(dialect)>(&code->nameRepository().dialect());
solAssert(dialect, "");

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

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

code = object.code.get();
analysisInfo = object.analysisInfo.get();
Expand All @@ -957,7 +957,6 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
*analysisInfo,
*m_context.assemblyPtr(),
m_context.evmVersion(),
_inlineAssembly.nameRepository(),
identifierAccessCodeGen,
false,
m_optimiserSettings.optimizeStackAllocation
Expand Down
8 changes: 5 additions & 3 deletions libsolidity/codegen/ir/IRGeneratorForStatements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2250,14 +2250,16 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm)
setLocation(_inlineAsm);
if (*_inlineAsm.annotation().hasMemoryEffects && !_inlineAsm.annotation().markedMemorySafe)
m_context.setMemoryUnsafeInlineAssemblySeen();
CopyTranslate bodyCopier{_inlineAsm.nameRepository(), m_context, _inlineAsm.annotation().externalReferences};
// make a copy of the name repository so that the "usr$" prefixed names can be defined on it
yul::YulNameRepository nameRepository = _inlineAsm.operations().nameRepository();
CopyTranslate bodyCopier{nameRepository, m_context, _inlineAsm.annotation().externalReferences};

yul::Statement modified = bodyCopier(_inlineAsm.operations());
yul::Statement modified = bodyCopier(_inlineAsm.operations().block());

solAssert(std::holds_alternative<yul::Block>(modified));

// Do not provide dialect so that we get the full type information.
appendCode() << yul::AsmPrinter(_inlineAsm.nameRepository())(std::get<yul::Block>(modified)) << "\n";
appendCode() << yul::AsmPrinter(nameRepository)(std::get<yul::Block>(modified)) << "\n";
return false;
}

Expand Down
4 changes: 2 additions & 2 deletions libsolidity/experimental/analysis/TypeInference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,10 @@ bool TypeInference::visit(InlineAssembly const& _inlineAssembly)
yul::AsmAnalyzer analyzer(
*_inlineAssembly.annotation().analysisInfo,
m_errorReporter,
_inlineAssembly.nameRepository(),
_inlineAssembly.operations().nameRepository(),
identifierAccess
);
if (!analyzer.analyze(_inlineAssembly.operations()))
if (!analyzer.analyze(_inlineAssembly.operations().block()))
solAssert(m_errorReporter.hasErrors());
return false;
}
Expand Down
7 changes: 4 additions & 3 deletions libsolidity/experimental/codegen/IRGeneratorForStatements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,11 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tupleExpression)

bool IRGeneratorForStatements::visit(InlineAssembly const& _assembly)
{
CopyTranslate bodyCopier{m_context, _assembly.nameRepository(), _assembly.annotation().externalReferences};
yul::Statement modified = bodyCopier(_assembly.operations());
yul::YulNameRepository nameRepository(_assembly.operations().nameRepository());
CopyTranslate bodyCopier{m_context, nameRepository, _assembly.annotation().externalReferences};
yul::Statement modified = bodyCopier(_assembly.operations().block());
solAssert(std::holds_alternative<yul::Block>(modified));
m_code << yul::AsmPrinter(_assembly.nameRepository())(std::get<yul::Block>(modified)) << "\n";
m_code << yul::AsmPrinter(nameRepository)(std::get<yul::Block>(modified)) << "\n";
return false;
}

Expand Down
Loading

0 comments on commit e8c587e

Please sign in to comment.