Skip to content

Commit eb2f874

Browse files
authored
Merge pull request #13733 from ethereum/eofSetting
Add experimental EOF options for CLI and Standard JSON.
2 parents 33f2709 + bf26d3b commit eb2f874

38 files changed

+198
-22
lines changed

libsolidity/codegen/ir/IRGenerator.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ pair<string, string> IRGenerator::run(
9797

9898
yul::YulStack asmStack(
9999
m_evmVersion,
100+
m_eofVersion,
100101
yul::YulStack::Language::StrictAssembly,
101102
m_optimiserSettings,
102103
m_context.debugInfoSelection()

libsolidity/codegen/ir/IRGenerator.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,15 @@ class IRGenerator
4646

4747
IRGenerator(
4848
langutil::EVMVersion _evmVersion,
49+
std::optional<uint8_t> _eofVersion,
4950
RevertStrings _revertStrings,
5051
OptimiserSettings _optimiserSettings,
5152
std::map<std::string, unsigned> _sourceIndices,
5253
langutil::DebugInfoSelection const& _debugInfoSelection,
5354
langutil::CharStreamProvider const* _soliditySourceProvider
5455
):
5556
m_evmVersion(_evmVersion),
57+
m_eofVersion(_eofVersion),
5658
m_optimiserSettings(_optimiserSettings),
5759
m_context(
5860
_evmVersion,
@@ -138,6 +140,7 @@ class IRGenerator
138140
std::string dispenseLocationComment(ASTNode const& _node);
139141

140142
langutil::EVMVersion const m_evmVersion;
143+
std::optional<uint8_t> const m_eofVersion;
141144
OptimiserSettings const m_optimiserSettings;
142145

143146
IRGenerationContext m_context;

libsolidity/interface/CompilerStack.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,15 @@ void CompilerStack::setEVMVersion(langutil::EVMVersion _version)
225225
m_evmVersion = _version;
226226
}
227227

228+
void CompilerStack::setEOFVersion(std::optional<uint8_t> _version)
229+
{
230+
if (m_stackState >= CompilationSuccessful)
231+
solThrow(CompilerError, "Must set EOF version before compiling.");
232+
if (_version && _version != 1)
233+
solThrow(CompilerError, "Invalid EOF version.");
234+
m_eofVersion = _version;
235+
}
236+
228237
void CompilerStack::setModelCheckerSettings(ModelCheckerSettings _settings)
229238
{
230239
if (m_stackState >= ParsedAndImported)
@@ -1308,6 +1317,7 @@ void CompilerStack::compileContract(
13081317
)
13091318
{
13101319
solAssert(!m_viaIR, "");
1320+
solUnimplementedAssert(!m_eofVersion.has_value(), "Experimental EOF support is only available for via-IR compilation.");
13111321
solAssert(m_stackState >= AnalysisPerformed, "");
13121322
if (m_hasError)
13131323
solThrow(CompilerError, "Called compile with errors.");
@@ -1373,7 +1383,15 @@ void CompilerStack::generateIR(ContractDefinition const& _contract)
13731383
for (auto const& pair: m_contracts)
13741384
otherYulSources.emplace(pair.second.contract, pair.second.yulIR);
13751385

1376-
IRGenerator generator(m_evmVersion, m_revertStrings, m_optimiserSettings, sourceIndices(), m_debugInfoSelection, this);
1386+
IRGenerator generator(
1387+
m_evmVersion,
1388+
m_eofVersion,
1389+
m_revertStrings,
1390+
m_optimiserSettings,
1391+
sourceIndices(),
1392+
m_debugInfoSelection,
1393+
this
1394+
);
13771395
tie(compiledContract.yulIR, compiledContract.yulIROptimized) = generator.run(
13781396
_contract,
13791397
createCBORMetadata(compiledContract, /* _forIR */ true),
@@ -1398,6 +1416,7 @@ void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract)
13981416
// Re-parse the Yul IR in EVM dialect
13991417
yul::YulStack stack(
14001418
m_evmVersion,
1419+
m_eofVersion,
14011420
yul::YulStack::Language::StrictAssembly,
14021421
m_optimiserSettings,
14031422
m_debugInfoSelection
@@ -1430,6 +1449,7 @@ void CompilerStack::generateEwasm(ContractDefinition const& _contract)
14301449
// Re-parse the Yul IR in EVM dialect
14311450
yul::YulStack stack(
14321451
m_evmVersion,
1452+
m_eofVersion,
14331453
yul::YulStack::Language::StrictAssembly,
14341454
m_optimiserSettings,
14351455
m_debugInfoSelection
@@ -1580,6 +1600,8 @@ string CompilerStack::createMetadata(Contract const& _contract, bool _forIR) con
15801600
if (_forIR)
15811601
meta["settings"]["viaIR"] = _forIR;
15821602
meta["settings"]["evmVersion"] = m_evmVersion.name();
1603+
if (m_eofVersion.has_value())
1604+
meta["settings"]["eofVersion"] = *m_eofVersion;
15831605
meta["settings"]["compilationTarget"][_contract.contract->sourceUnitName()] =
15841606
*_contract.contract->annotation().canonicalName;
15851607

@@ -1704,7 +1726,7 @@ bytes CompilerStack::createCBORMetadata(Contract const& _contract, bool _forIR)
17041726
else
17051727
solAssert(m_metadataHash == MetadataHash::None, "Invalid metadata hash");
17061728

1707-
if (experimentalMode)
1729+
if (experimentalMode || m_eofVersion.has_value())
17081730
encoder.pushBool("experimental", true);
17091731
if (m_metadataFormat == MetadataFormat::WithReleaseVersionTag)
17101732
encoder.pushBytes("solc", VersionCompactBytes);

libsolidity/interface/CompilerStack.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@ class CompilerStack: public langutil::CharStreamProvider
181181
/// Must be set before parsing.
182182
void setEVMVersion(langutil::EVMVersion _version = langutil::EVMVersion{});
183183

184+
/// Set the EOF version used before running compile.
185+
/// If set to std::nullopt (the default), legacy non-EOF bytecode is generated.
186+
void setEOFVersion(std::optional<uint8_t> version);
187+
184188
/// Set model checker settings.
185189
void setModelCheckerSettings(ModelCheckerSettings _settings);
186190

@@ -498,6 +502,7 @@ class CompilerStack: public langutil::CharStreamProvider
498502
State m_stopAfter = State::CompilationSuccessful;
499503
bool m_viaIR = false;
500504
langutil::EVMVersion m_evmVersion;
505+
std::optional<uint8_t> m_eofVersion;
501506
ModelCheckerSettings m_modelCheckerSettings;
502507
std::map<std::string, std::set<std::string>> m_requestedContractNames;
503508
bool m_generateEvmBytecode = true;

libsolidity/interface/StandardCompiler.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,16 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
800800
ret.evmVersion = *version;
801801
}
802802

803+
if (settings.isMember("eofVersion"))
804+
{
805+
if (!settings["eofVersion"].isUInt())
806+
return formatFatalError(Error::Type::JSONError, "eofVersion must be an unsigned integer.");
807+
auto eofVersion = settings["evmVersion"].asUInt();
808+
if (eofVersion != 1)
809+
return formatFatalError(Error::Type::JSONError, "Invalid EOF version requested.");
810+
ret.eofVersion = 1;
811+
}
812+
803813
if (settings.isMember("debug"))
804814
{
805815
if (auto result = checkKeys(settings["debug"], {"revertStrings", "debugInfo"}, "settings.debug"))
@@ -1413,6 +1423,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
14131423

14141424
YulStack stack(
14151425
_inputsAndSettings.evmVersion,
1426+
_inputsAndSettings.eofVersion,
14161427
YulStack::Language::StrictAssembly,
14171428
_inputsAndSettings.optimiserSettings,
14181429
_inputsAndSettings.debugInfoSelection.has_value() ?

libsolidity/interface/StandardCompiler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class StandardCompiler
7777
std::map<std::string, std::string> sources;
7878
std::map<util::h256, std::string> smtLib2Responses;
7979
langutil::EVMVersion evmVersion;
80+
std::optional<uint8_t> eofVersion;
8081
std::vector<ImportRemapper::Remapping> remappings;
8182
RevertStrings revertStrings = RevertStrings::Default;
8283
OptimiserSettings optimiserSettings = OptimiserSettings::minimal();

libyul/YulStack.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ void YulStack::compileEVM(AbstractAssembly& _assembly, bool _optimize) const
164164
break;
165165
}
166166

167-
EVMObjectCompiler::compile(*m_parserResult, _assembly, *dialect, _optimize);
167+
EVMObjectCompiler::compile(*m_parserResult, _assembly, *dialect, _optimize, m_eofVersion);
168168
}
169169

170170
void YulStack::optimize(Object& _object, bool _isCreation)

libyul/YulStack.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class YulStack: public langutil::CharStreamProvider
7272
YulStack():
7373
YulStack(
7474
langutil::EVMVersion{},
75+
std::nullopt,
7576
Language::Assembly,
7677
solidity::frontend::OptimiserSettings::none(),
7778
langutil::DebugInfoSelection::Default()
@@ -80,12 +81,14 @@ class YulStack: public langutil::CharStreamProvider
8081

8182
YulStack(
8283
langutil::EVMVersion _evmVersion,
84+
std::optional<uint8_t> _eofVersion,
8385
Language _language,
8486
solidity::frontend::OptimiserSettings _optimiserSettings,
8587
langutil::DebugInfoSelection const& _debugInfoSelection
8688
):
8789
m_language(_language),
8890
m_evmVersion(_evmVersion),
91+
m_eofVersion(_eofVersion),
8992
m_optimiserSettings(std::move(_optimiserSettings)),
9093
m_debugInfoSelection(_debugInfoSelection),
9194
m_errorReporter(m_errors)
@@ -146,6 +149,7 @@ class YulStack: public langutil::CharStreamProvider
146149

147150
Language m_language = Language::Assembly;
148151
langutil::EVMVersion m_evmVersion;
152+
std::optional<uint8_t> m_eofVersion;
149153
solidity::frontend::OptimiserSettings m_optimiserSettings;
150154
langutil::DebugInfoSelection m_debugInfoSelection{};
151155

libyul/backends/evm/EVMObjectCompiler.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,15 @@
3535
using namespace solidity::yul;
3636
using namespace std;
3737

38-
void EVMObjectCompiler::compile(Object& _object, AbstractAssembly& _assembly, EVMDialect const& _dialect, bool _optimize)
38+
void EVMObjectCompiler::compile(
39+
Object& _object,
40+
AbstractAssembly& _assembly,
41+
EVMDialect const& _dialect,
42+
bool _optimize,
43+
std::optional<uint8_t> _eofVersion
44+
)
3945
{
40-
EVMObjectCompiler compiler(_assembly, _dialect);
46+
EVMObjectCompiler compiler(_assembly, _dialect, _eofVersion);
4147
compiler.run(_object, _optimize);
4248
}
4349

@@ -54,7 +60,7 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize)
5460
auto subAssemblyAndID = m_assembly.createSubAssembly(isCreation, subObject->name.str());
5561
context.subIDs[subObject->name] = subAssemblyAndID.second;
5662
subObject->subId = subAssemblyAndID.second;
57-
compile(*subObject, *subAssemblyAndID.first, m_dialect, _optimize);
63+
compile(*subObject, *subAssemblyAndID.first, m_dialect, _optimize, m_eofVersion);
5864
}
5965
else
6066
{
@@ -68,6 +74,11 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize)
6874

6975
yulAssert(_object.analysisInfo, "No analysis info.");
7076
yulAssert(_object.code, "No code.");
77+
if (m_eofVersion.has_value())
78+
yulAssert(
79+
_optimize && (m_dialect.evmVersion() == langutil::EVMVersion()),
80+
"Experimental EOF support is only available for optimized via-IR compilation and the most recent EVM version."
81+
);
7182
if (_optimize && m_dialect.evmVersion().canOverchargeGasForCall())
7283
{
7384
auto stackErrors = OptimizedEVMCodeTransform::run(

libyul/backends/evm/EVMObjectCompiler.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121

2222
#pragma once
2323

24+
#include <optional>
25+
#include <cstdint>
26+
2427
namespace solidity::yul
2528
{
2629
struct Object;
@@ -30,16 +33,23 @@ struct EVMDialect;
3033
class EVMObjectCompiler
3134
{
3235
public:
33-
static void compile(Object& _object, AbstractAssembly& _assembly, EVMDialect const& _dialect, bool _optimize);
36+
static void compile(
37+
Object& _object,
38+
AbstractAssembly& _assembly,
39+
EVMDialect const& _dialect,
40+
bool _optimize,
41+
std::optional<uint8_t> _eofVersion
42+
);
3443
private:
35-
EVMObjectCompiler(AbstractAssembly& _assembly, EVMDialect const& _dialect):
36-
m_assembly(_assembly), m_dialect(_dialect)
44+
EVMObjectCompiler(AbstractAssembly& _assembly, EVMDialect const& _dialect, std::optional<uint8_t> _eofVersion):
45+
m_assembly(_assembly), m_dialect(_dialect), m_eofVersion(_eofVersion)
3746
{}
3847

3948
void run(Object& _object, bool _optimize);
4049

4150
AbstractAssembly& m_assembly;
4251
EVMDialect const& m_dialect;
52+
std::optional<uint8_t> m_eofVersion;
4353
};
4454

4555
}

0 commit comments

Comments
 (0)