Skip to content

Commit bf26d3b

Browse files
ekpyroncameel
andcommitted
Add experimental EOF options for CLI and Standard JSON.
Co-authored-by: Kamil Śliwak <[email protected]>
1 parent 3109ce2 commit bf26d3b

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)
@@ -1299,6 +1308,7 @@ void CompilerStack::compileContract(
12991308
)
13001309
{
13011310
solAssert(!m_viaIR, "");
1311+
solUnimplementedAssert(!m_eofVersion.has_value(), "Experimental EOF support is only available for via-IR compilation.");
13021312
solAssert(m_stackState >= AnalysisPerformed, "");
13031313
if (m_hasError)
13041314
solThrow(CompilerError, "Called compile with errors.");
@@ -1364,7 +1374,15 @@ void CompilerStack::generateIR(ContractDefinition const& _contract)
13641374
for (auto const& pair: m_contracts)
13651375
otherYulSources.emplace(pair.second.contract, pair.second.yulIR);
13661376

1367-
IRGenerator generator(m_evmVersion, m_revertStrings, m_optimiserSettings, sourceIndices(), m_debugInfoSelection, this);
1377+
IRGenerator generator(
1378+
m_evmVersion,
1379+
m_eofVersion,
1380+
m_revertStrings,
1381+
m_optimiserSettings,
1382+
sourceIndices(),
1383+
m_debugInfoSelection,
1384+
this
1385+
);
13681386
tie(compiledContract.yulIR, compiledContract.yulIROptimized) = generator.run(
13691387
_contract,
13701388
createCBORMetadata(compiledContract, /* _forIR */ true),
@@ -1389,6 +1407,7 @@ void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract)
13891407
// Re-parse the Yul IR in EVM dialect
13901408
yul::YulStack stack(
13911409
m_evmVersion,
1410+
m_eofVersion,
13921411
yul::YulStack::Language::StrictAssembly,
13931412
m_optimiserSettings,
13941413
m_debugInfoSelection
@@ -1421,6 +1440,7 @@ void CompilerStack::generateEwasm(ContractDefinition const& _contract)
14211440
// Re-parse the Yul IR in EVM dialect
14221441
yul::YulStack stack(
14231442
m_evmVersion,
1443+
m_eofVersion,
14241444
yul::YulStack::Language::StrictAssembly,
14251445
m_optimiserSettings,
14261446
m_debugInfoSelection
@@ -1571,6 +1591,8 @@ string CompilerStack::createMetadata(Contract const& _contract, bool _forIR) con
15711591
if (_forIR)
15721592
meta["settings"]["viaIR"] = _forIR;
15731593
meta["settings"]["evmVersion"] = m_evmVersion.name();
1594+
if (m_eofVersion.has_value())
1595+
meta["settings"]["eofVersion"] = *m_eofVersion;
15741596
meta["settings"]["compilationTarget"][_contract.contract->sourceUnitName()] =
15751597
*_contract.contract->annotation().canonicalName;
15761598

@@ -1695,7 +1717,7 @@ bytes CompilerStack::createCBORMetadata(Contract const& _contract, bool _forIR)
16951717
else
16961718
solAssert(m_metadataHash == MetadataHash::None, "Invalid metadata hash");
16971719

1698-
if (experimentalMode)
1720+
if (experimentalMode || m_eofVersion.has_value())
16991721
encoder.pushBool("experimental", true);
17001722
if (m_metadataFormat == MetadataFormat::WithReleaseVersionTag)
17011723
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)