Skip to content

Commit

Permalink
eof: Pass eofVersion flag to EVMDialect
Browse files Browse the repository at this point in the history
  • Loading branch information
rodiazet committed Sep 30, 2024
1 parent bc9342a commit 60bfab0
Show file tree
Hide file tree
Showing 41 changed files with 226 additions and 108 deletions.
1 change: 1 addition & 0 deletions libevmasm/Assembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1380,6 +1380,7 @@ LinkerObject const& Assembly::assembleEOF() const
switch (item.type())
{
case Operation:
solAssert(!(item.instruction() >= Instruction::PUSH0 && item.instruction() <= Instruction::PUSH32));
ret.bytecode += assembleOperation(item);
break;
case Push:
Expand Down
24 changes: 21 additions & 3 deletions liblangutil/EVMVersion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@ 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:
Expand All @@ -40,9 +43,9 @@ bool EVMVersion::hasOpcode(Instruction _opcode) const
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();
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
7 changes: 6 additions & 1 deletion libsolidity/ast/ASTJsonImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,12 @@ 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());
std::optional<uint8_t> eofVersion;
if (auto const it = _node.find("eofVersion"); it != _node.end())
eofVersion = it->get<uint8_t>();
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;
};

}
6 changes: 3 additions & 3 deletions libsolidity/codegen/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ namespace solidity::frontend
class Compiler
{
public:
Compiler(langutil::EVMVersion _evmVersion, RevertStrings _revertStrings, OptimiserSettings _optimiserSettings):
Compiler(langutil::EVMVersion _evmVersion, std::optional<uint8_t> _eofVersion, RevertStrings _revertStrings, OptimiserSettings _optimiserSettings):
m_optimiserSettings(std::move(_optimiserSettings)),
m_runtimeContext(_evmVersion, _revertStrings),
m_context(_evmVersion, _revertStrings, &m_runtimeContext)
m_runtimeContext(_evmVersion, _eofVersion, _revertStrings),
m_context(_evmVersion, _eofVersion, _revertStrings, &m_runtimeContext)
{ }

/// Compiles a contract.
Expand Down
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, m_eofVersion);
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,
m_eofVersion,
identifierAccess.generateCode,
_system,
_optimiserSettings.optimizeStackAllocation
Expand Down
4 changes: 4 additions & 0 deletions libsolidity/codegen/CompilerContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,13 @@ class CompilerContext
public:
explicit CompilerContext(
langutil::EVMVersion _evmVersion,
std::optional<uint8_t> _eofVersion,
RevertStrings _revertStrings,
CompilerContext* _runtimeContext = nullptr
):
m_asm(std::make_shared<evmasm::Assembly>(_evmVersion, _runtimeContext != nullptr, std::nullopt, std::string{})),
m_evmVersion(_evmVersion),
m_eofVersion(_eofVersion),
m_revertStrings(_revertStrings),
m_reservedMemory{0},
m_runtimeContext(_runtimeContext),
Expand All @@ -78,6 +80,7 @@ class CompilerContext
}

langutil::EVMVersion const& evmVersion() const { return m_evmVersion; }
std::optional<uint8_t> eofVersion() const { return m_eofVersion; }

void setUseABICoderV2(bool _value) { m_useABICoderV2 = _value; }
bool useABICoderV2() const { return m_useABICoderV2; }
Expand Down Expand Up @@ -349,6 +352,7 @@ class CompilerContext
evmasm::AssemblyPointer m_asm;
/// Version of the EVM to compile against.
langutil::EVMVersion m_evmVersion;
std::optional<uint8_t> m_eofVersion;
RevertStrings const m_revertStrings;
bool m_useABICoderV2 = false;
/// Other already compiled contracts to be used in contract creation calls.
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(),
m_context.eofVersion(),
identifierAccessCodeGen,
false,
m_optimiserSettings.optimizeStackAllocation
Expand Down
9 changes: 5 additions & 4 deletions libsolidity/interface/CompilerStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,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 @@ -419,7 +419,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 @@ -873,7 +874,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 Expand Up @@ -1463,7 +1464,7 @@ void CompilerStack::compileContract(

Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName());

std::shared_ptr<Compiler> compiler = std::make_shared<Compiler>(m_evmVersion, m_revertStrings, m_optimiserSettings);
std::shared_ptr<Compiler> compiler = std::make_shared<Compiler>(m_evmVersion, m_eofVersion, m_revertStrings, m_optimiserSettings);

solAssert(!m_viaIR, "");
bytes cborEncodedMetadata = createCBORMetadata(compiledContract, /* _forIR */ false);
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);
else
Expand Down
6 changes: 3 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
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;
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

0 comments on commit 60bfab0

Please sign in to comment.