Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eof: Pass eofVersion flag to EVMDialect #15467

Merged
merged 1 commit into from
Oct 1, 2024
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
26 changes: 22 additions & 4 deletions liblangutil/EVMVersion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,26 @@ using namespace solidity;
using namespace solidity::evmasm;
using namespace solidity::langutil;

bool EVMVersion::hasOpcode(Instruction _opcode) const
bool EVMVersion::hasOpcode(Instruction _opcode, std::optional<uint8_t> _eofVersion) const
{
// EOF version can be only defined since prague
assert(!_eofVersion.has_value() || this->m_version >= prague());

switch (_opcode)
{
case Instruction::RETURNDATACOPY:
case Instruction::RETURNDATASIZE:
return supportsReturndata();
case Instruction::STATICCALL:
return hasStaticCall();
return !_eofVersion.has_value() && hasStaticCall();
case Instruction::SHL:
case Instruction::SHR:
case Instruction::SAR:
return hasBitwiseShifting();
case Instruction::CREATE2:
return hasCreate2();
return !_eofVersion.has_value() && hasCreate2();
case Instruction::EXTCODEHASH:
return hasExtCodeHash();
return !_eofVersion.has_value() && hasExtCodeHash();
cameel marked this conversation as resolved.
Show resolved Hide resolved
Comment on lines 39 to +48
Copy link
Member

Choose a reason for hiding this comment

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

We should make the EOF version a parameter in hasStaticCall(), hasCreate2() and hasExtCodeHash(). I wasn't sure about it back when I reviewed this PR, but now I saw this bit again in #15456 and I think it is necessary after all.

I actually just tried to do this myself as a quick tweak, but looks like it requires the EOF version to be passed into a few more places. And in some of those places it actually needs to be handled since they make assumptions based on the availability of these instructions. For example there are fallback to call when staticcall is not available, but on EOF they should result in extstaticcall instead.

case Instruction::CHAINID:
return hasChainID();
case Instruction::SELFBALANCE:
Expand All @@ -58,6 +61,21 @@ bool EVMVersion::hasOpcode(Instruction _opcode) const
case Instruction::TSTORE:
case Instruction::TLOAD:
return supportsTransientStorage();
// Instructions below are deprecated in EOF
case Instruction::CALL:
case Instruction::CALLCODE:
case Instruction::DELEGATECALL:
case Instruction::SELFDESTRUCT:
case Instruction::JUMP:
case Instruction::JUMPI:
case Instruction::PC:
case Instruction::CREATE:
case Instruction::CODESIZE:
case Instruction::CODECOPY:
case Instruction::EXTCODESIZE:
case Instruction::EXTCODECOPY:
case Instruction::GAS:
return !_eofVersion.has_value();
default:
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion liblangutil/EVMVersion.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class EVMVersion:
bool hasMcopy() const { return *this >= cancun(); }
bool supportsTransientStorage() const { return *this >= cancun(); }

bool hasOpcode(evmasm::Instruction _opcode) const;
bool hasOpcode(evmasm::Instruction _opcode, std::optional<uint8_t> _eofVersion) const;

/// Whether we have to retain the costs for the call opcode itself (false),
/// or whether we can just forward easily all remaining gas (true).
Expand Down
11 changes: 10 additions & 1 deletion libsolidity/ast/ASTJsonExporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,12 +664,21 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node)
for (Json& it: externalReferences | ranges::views::values)
externalReferencesJson.emplace_back(std::move(it));

auto const& evmDialect = dynamic_cast<solidity::yul::EVMDialect const&>(_node.dialect());

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

// TODO: Add test in test/linsolidity/ASTJSON/assembly. This requires adding support for eofVersion in ASTJSONTest
if (evmDialect.eofVersion())
{
solAssert(*evmDialect.eofVersion() > 0);
attributes.push_back(std::make_pair("eofVersion", *evmDialect.eofVersion()));
}

if (_node.flags())
{
Json flags = Json::array();
Expand Down
11 changes: 10 additions & 1 deletion libsolidity/ast/ASTJsonImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,16 @@ ASTPointer<InlineAssembly> ASTJsonImporter::createInlineAssembly(Json const& _no
astAssert(evmVersion.has_value(), "Invalid EVM version!");
astAssert(m_evmVersion == evmVersion, "Imported tree evm version differs from configured evm version!");

yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(evmVersion.value());
// TODO: Add test in test/linsolidity/ASTJSON/assembly. This requires adding support for eofVersion in ASTJSONTest
std::optional<uint8_t> eofVersion;
if (auto const it = _node.find("eofVersion"); it != _node.end())
{
eofVersion = it->get<uint8_t>();
astAssert(eofVersion > 0);
}
astAssert(m_eofVersion == eofVersion, "Imported tree EOF version differs from configured EOF version!");

yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(evmVersion.value(), eofVersion);
ASTPointer<std::vector<ASTPointer<ASTString>>> flags;
if (_node.contains("flags"))
{
Expand Down
6 changes: 4 additions & 2 deletions libsolidity/ast/ASTJsonImporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ namespace solidity::frontend
class ASTJsonImporter
{
public:
ASTJsonImporter(langutil::EVMVersion _evmVersion)
:m_evmVersion(_evmVersion)
ASTJsonImporter(langutil::EVMVersion _evmVersion, std::optional<uint8_t> _eofVersion)
:m_evmVersion(_evmVersion), m_eofVersion(_eofVersion)
{}

/// Converts the AST from JSON-format to ASTPointer
Expand Down Expand Up @@ -166,6 +166,8 @@ class ASTJsonImporter
std::set<int64_t> m_usedIDs;
/// Configured EVM version
langutil::EVMVersion m_evmVersion;
/// Configured EOF version. Equals std::nullopt if non-EOF
std::optional<uint8_t> m_eofVersion;
};

}
3 changes: 2 additions & 1 deletion libsolidity/codegen/CompilerContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ void CompilerContext::appendInlineAssembly(
ErrorList errors;
ErrorReporter errorReporter(errors);
langutil::CharStream charStream(_assembly, _sourceName);
yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion);
yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion, std::nullopt);
std::optional<langutil::SourceLocation> locationOverride;
if (!_system)
locationOverride = m_asm->currentSourceLocation();
Expand Down Expand Up @@ -522,6 +522,7 @@ void CompilerContext::appendInlineAssembly(
analysisInfo,
*m_asm,
m_evmVersion,
std::nullopt,
identifierAccess.generateCode,
_system,
_optimiserSettings.optimizeStackAllocation
Expand Down
1 change: 1 addition & 0 deletions libsolidity/codegen/ContractCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
*analysisInfo,
*m_context.assemblyPtr(),
m_context.evmVersion(),
std::nullopt,
identifierAccessCodeGen,
false,
m_optimiserSettings.optimizeStackAllocation
Expand Down
7 changes: 4 additions & 3 deletions libsolidity/interface/CompilerStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ bool CompilerStack::parse()

try
{
Parser parser{m_errorReporter, m_evmVersion};
Parser parser{m_errorReporter, m_evmVersion, m_eofVersion};

std::vector<std::string> sourcesToParse;
for (auto const& s: m_sources)
Expand Down Expand Up @@ -427,7 +427,8 @@ bool CompilerStack::parse()
void CompilerStack::importASTs(std::map<std::string, Json> const& _sources)
{
solAssert(m_stackState == Empty, "Must call importASTs only before the SourcesSet state.");
std::map<std::string, ASTPointer<SourceUnit>> reconstructedSources = ASTJsonImporter(m_evmVersion).jsonToSourceUnit(_sources);
std::map<std::string, ASTPointer<SourceUnit>> reconstructedSources =
ASTJsonImporter(m_evmVersion, m_eofVersion).jsonToSourceUnit(_sources);
for (auto& src: reconstructedSources)
{
solUnimplementedAssert(!src.second->experimentalSolidity());
Expand Down Expand Up @@ -896,7 +897,7 @@ Json CompilerStack::generatedSources(std::string const& _contractName, bool _run
ErrorList errors;
ErrorReporter errorReporter(errors);
CharStream charStream(source, sourceName);
yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion);
yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion, m_eofVersion);
std::shared_ptr<yul::AST> parserResult = yul::Parser{errorReporter, dialect}.parse(charStream);
solAssert(parserResult);
sources[0]["ast"] = yul::AsmJsonConverter{sourceIndex}(parserResult->root());
Expand Down
2 changes: 1 addition & 1 deletion libsolidity/parsing/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1448,7 +1448,7 @@ ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> con
SourceLocation location = currentLocation();

expectToken(Token::Assembly);
yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion);
yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion, m_eofVersion);
if (m_scanner->currentToken() == Token::StringLiteral)
{
if (m_scanner->currentLiteral() != "evmasm")
Expand Down
7 changes: 5 additions & 2 deletions libsolidity/parsing/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@ class Parser: public langutil::ParserBase
public:
explicit Parser(
langutil::ErrorReporter& _errorReporter,
langutil::EVMVersion _evmVersion
langutil::EVMVersion _evmVersion,
std::optional<uint8_t> _eofVersion
):
ParserBase(_errorReporter),
m_evmVersion(_evmVersion)
m_evmVersion(_evmVersion),
m_eofVersion(_eofVersion)
{}

ASTPointer<SourceUnit> parse(langutil::CharStream& _charStream);
Expand Down Expand Up @@ -247,6 +249,7 @@ class Parser: public langutil::ParserBase
/// Flag that signifies whether '_' is parsed as a PlaceholderStatement or a regular identifier.
bool m_insideModifier = false;
langutil::EVMVersion m_evmVersion;
std::optional<uint8_t> m_eofVersion;
/// Counter for the next AST node ID
int64_t m_currentNodeID = 0;
/// Flag that indicates whether experimental mode is enabled in the current source unit
Expand Down
3 changes: 2 additions & 1 deletion libyul/AsmAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,8 @@ void AsmAnalyzer::expectValidIdentifier(YulName _identifier, SourceLocation cons
bool AsmAnalyzer::validateInstructions(std::string const& _instructionIdentifier, langutil::SourceLocation const& _location)
{
// NOTE: This function uses the default EVM version instead of the currently selected one.
auto const builtin = EVMDialect::strictAssemblyForEVM(EVMVersion{}).builtin(YulName(_instructionIdentifier));
// TODO: Add EOF support
auto const builtin = EVMDialect::strictAssemblyForEVM(EVMVersion{}, std::nullopt).builtin(YulName(_instructionIdentifier));
if (builtin && builtin->instruction.has_value())
return validateInstructions(builtin->instruction.value(), _location);
Comment on lines 627 to 631
Copy link
Member

Choose a reason for hiding this comment

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

The reason we use hard-coded EVM version here is that historically this was always the one that had all possible builtins. With EOF this changes so I guess we'll have to use a different strategy for checking if the thing is a builtin - we should check both EOF and non-EOF dialect here and call validateInstruction() for whichever has the instruction (or maybe even for both).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Let me know if you want this to be added in this PR

Copy link
Member

@cameel cameel Oct 1, 2024

Choose a reason for hiding this comment

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

It would probably be best to still do it here. I wouldn't be against doing it later in another PR in principle, but we have so many of these TODOs now that I'm a bit afraid that things like this will just get forgotten and lost, only to surface as bugs much later :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. But we need test for this. Current SyntaxTest does not support compileToEOF flag. I would add it to EVMVersionRestrictedTestCase constructor to have it available in all derived TaseCase classes. WDYT? If so here on additional PR? :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It has to be done in this PR because CI requires to cover all possible error codes

Copy link
Member

Choose a reason for hiding this comment

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

Either way sounds fine, but it's related so having it here is probably a good idea. And yeah, the error code - we have a whitelist for unused codes in scripts/error_codes.py so you could temporarily add it there if necessary, but that's always a last resort :)

Copy link
Member

@cameel cameel Oct 1, 2024

Choose a reason for hiding this comment

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

Though one thing to consider here - we have two different approaches to these settings, and you need to choose one:

  1. EVMVersion setting: you set a supported range of versions in the test, but a single isoltest run always executes only for one specific version (selected via --evm-version). If that matches the range, the test runs. Otherwise it's skipped. To get full coverage we run soltest with all relevant EVM versions in CI (via soltest_all.sh).
  2. compileViaYul setting in semantic tests: you select compilation via Yul or not or both. And each run does exactly that, running it twice if necessary. There's no CLI option.

The downside of (1) is that you'll have to run tests twice locally to test both EOF and legacy. It also adds another dimension to our test matrix. Currently we have two dimensions: optimizer on/off and EVM version. EOF version will be the third one, so you'll basically have to multiply the number of runs by two (though fortunately we can exclude older EVM versions from that, which lowers that number significantly).

Also, with (1) we end up unnecessarily running tests that are not affected by the flag multiple times, so it's only good for things that affect almost every part of the compiler.

The upside is that you get it supported almost for free in all test cases just by inheriting from EVMVersionRestrictedTestCase, while compiling things multiple times for (2) requires adding special support for it in each case. This matters especially for the smaller test cases (i.e. the ones where you used the flag from CommonOptions), where we definitely won't be going out of our way to make them use EOF, but it would be nice to have for more comprehensive coverage.

Since we already have that --eof-version flag in soltest and the option is closely related to EVM version, I think it still makes the most sense to go with (1). And we'll need to add that additional run with EOF enabled anyway, because otherwise the tests using EOF versions from CommonOptions now would still only be tested with legacy.

Copy link
Member

Choose a reason for hiding this comment

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

So, in short, my suggestion would be to extend EVMVersionRestrictedTestCase to make it support a setting like EOFVersion, which takes a list of comma-separated values: for now only legacy and >=1. The values should really be ranges, like for EVM, but since we only have one version, I'd not bother with that - I'd just make it support >=1 as a single, hard-coded value. If we ever get EOF v2, it will be easy to extend it by just changing how the value is parsed, without having to update it in all the tests.

Copy link
Contributor Author

@rodiazet rodiazet Oct 1, 2024

Choose a reason for hiding this comment

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

We agreed on addind EOF support for AsmAnalysis in a separated PR #15471

else
Expand Down
8 changes: 5 additions & 3 deletions libyul/ObjectOptimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ using namespace solidity::util;
using namespace solidity::yul;


Dialect const& yul::languageToDialect(Language _language, EVMVersion _version)
Dialect const& yul::languageToDialect(Language _language, EVMVersion _version, std::optional<uint8_t> _eofVersion)
{
switch (_language)
{
case Language::Assembly:
case Language::StrictAssembly:
return EVMDialect::strictAssemblyForEVMObjects(_version);
return EVMDialect::strictAssemblyForEVMObjects(_version, _eofVersion);
}
util::unreachable();
}
Expand Down Expand Up @@ -77,7 +77,7 @@ void ObjectOptimizer::optimize(Object& _object, Settings const& _settings, bool
);
}

Dialect const& dialect = languageToDialect(_settings.language, _settings.evmVersion);
Dialect const& dialect = languageToDialect(_settings.language, _settings.evmVersion, _settings.eofVersion);
std::unique_ptr<GasMeter> meter;
if (EVMDialect const* evmDialect = dynamic_cast<EVMDialect const*>(&dialect))
meter = std::make_unique<GasMeter>(*evmDialect, _isCreation, _settings.expectedExecutionsPerDeployment);
Expand Down Expand Up @@ -158,6 +158,8 @@ std::optional<h256> ObjectOptimizer::calculateCacheKey(
rawKey += h256(u256(_settings.expectedExecutionsPerDeployment)).asBytes();
rawKey += FixedHash<1>(uint8_t(_isCreation ? 0 : 1)).asBytes();
rawKey += keccak256(_settings.evmVersion.name()).asBytes();
yulAssert(!_settings.eofVersion.has_value() || *_settings.eofVersion > 0);
rawKey += FixedHash<1>(uint8_t(_settings.eofVersion ? 0 : *_settings.eofVersion)).asBytes();
cameel marked this conversation as resolved.
Show resolved Hide resolved
rawKey += keccak256(_settings.yulOptimiserSteps).asBytes();
rawKey += keccak256(_settings.yulOptimiserCleanupSteps).asBytes();

Expand Down
3 changes: 2 additions & 1 deletion libyul/ObjectOptimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ enum class Language
StrictAssembly,
};

Dialect const& languageToDialect(Language _language, langutil::EVMVersion _version);
Dialect const& languageToDialect(Language _language, langutil::EVMVersion _version, std::optional<uint8_t> _eofVersion);

/// Encapsulates logic for applying @a yul::OptimiserSuite to a whole hierarchy of Yul objects.
/// Also, acts as a transparent cache for optimized objects.
Expand All @@ -58,6 +58,7 @@ class ObjectOptimizer
{
Language language;
langutil::EVMVersion evmVersion;
std::optional<uint8_t> eofVersion;
cameel marked this conversation as resolved.
Show resolved Hide resolved
bool optimizeStackAllocation;
std::string yulOptimiserSteps;
std::string yulOptimiserCleanupSteps;
Expand Down
13 changes: 7 additions & 6 deletions libyul/YulStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ bool YulStack::parse(std::string const& _sourceName, std::string const& _source)
{
m_charStream = std::make_unique<CharStream>(_source, _sourceName);
std::shared_ptr<Scanner> scanner = std::make_shared<Scanner>(*m_charStream);
m_parserResult = ObjectParser(m_errorReporter, languageToDialect(m_language, m_evmVersion)).parse(scanner, false);
m_parserResult = ObjectParser(m_errorReporter, languageToDialect(m_language, m_evmVersion, m_eofVersion)).parse(scanner, false);
}
catch (UnimplementedFeatureError const& _error)
{
Expand Down Expand Up @@ -94,7 +94,7 @@ void YulStack::optimize()
{
if (
!m_optimiserSettings.runYulOptimiser &&
yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion), *m_parserResult)
yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion, m_eofVersion), *m_parserResult)
)
return;

Expand Down Expand Up @@ -130,6 +130,7 @@ void YulStack::optimize()
ObjectOptimizer::Settings{
m_language,
m_evmVersion,
m_eofVersion,
optimizeStackAllocation,
yulOptimiserSteps,
yulOptimiserCleanupSteps,
Expand Down Expand Up @@ -163,7 +164,7 @@ bool YulStack::analyzeParsed(Object& _object)
AsmAnalyzer analyzer(
*_object.analysisInfo,
m_errorReporter,
languageToDialect(m_language, m_evmVersion),
languageToDialect(m_language, m_evmVersion, m_eofVersion),
{},
_object.qualifiedDataNames()
);
Expand Down Expand Up @@ -196,7 +197,7 @@ void YulStack::compileEVM(AbstractAssembly& _assembly, bool _optimize) const
{
case Language::Assembly:
case Language::StrictAssembly:
dialect = &EVMDialect::strictAssemblyForEVMObjects(m_evmVersion);
dialect = &EVMDialect::strictAssemblyForEVMObjects(m_evmVersion, m_eofVersion);
break;
default:
yulAssert(false, "Invalid language.");
Expand Down Expand Up @@ -316,7 +317,7 @@ YulStack::assembleEVMWithDeployed(std::optional<std::string_view> _deployName)
// it with the minimal steps required to avoid "stack too deep".
bool optimize = m_optimiserSettings.optimizeStackAllocation || (
!m_optimiserSettings.runYulOptimiser &&
!yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion), *m_parserResult)
!yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion, m_eofVersion), *m_parserResult)
);
try
{
Expand Down Expand Up @@ -385,7 +386,7 @@ Json YulStack::cfgJson() const
// NOTE: The block Ids are reset for each object
std::unique_ptr<ControlFlow> controlFlow = SSAControlFlowGraphBuilder::build(
*_object.analysisInfo.get(),
languageToDialect(m_language, m_evmVersion),
languageToDialect(m_language, m_evmVersion, m_eofVersion),
_object.code()->root()
);
YulControlFlowGraphExporter exporter(*controlFlow);
Expand Down
3 changes: 2 additions & 1 deletion libyul/backends/evm/AsmCodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ void CodeGenerator::assemble(
AsmAnalysisInfo& _analysisInfo,
evmasm::Assembly& _assembly,
langutil::EVMVersion _evmVersion,
std::optional<uint8_t> _eofVersion,
ExternalIdentifierAccess::CodeGenerator _identifierAccessCodeGen,
bool _useNamedLabelsForFunctions,
bool _optimizeStackAllocation
Expand All @@ -49,7 +50,7 @@ void CodeGenerator::assemble(
assemblyAdapter,
_analysisInfo,
_parsedData,
EVMDialect::strictAssemblyForEVM(_evmVersion),
EVMDialect::strictAssemblyForEVM(_evmVersion, _eofVersion),
builtinContext,
_optimizeStackAllocation,
_identifierAccessCodeGen,
Expand Down
1 change: 1 addition & 0 deletions libyul/backends/evm/AsmCodeGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class CodeGenerator
AsmAnalysisInfo& _analysisInfo,
evmasm::Assembly& _assembly,
langutil::EVMVersion _evmVersion,
std::optional<uint8_t> _eofVersion,
ExternalIdentifierAccess::CodeGenerator _identifierAccess = {},
bool _useNamedLabelsForFunctions = false,
bool _optimizeStackAllocation = false
Expand Down
Loading