Initial still broken version.

This commit is contained in:
Daniel Kirchner
2023-01-05 20:05:11 +01:00
parent 9453edcbc0
commit ed74f3d2a0
39 changed files with 398 additions and 66 deletions
+2 -1
View File
@@ -33,6 +33,7 @@ using namespace solidity::util;
CompilabilityChecker::CompilabilityChecker(
Dialect const& _dialect,
std::optional<uint8_t> _eofVersion,
Object const& _object,
bool _optimizeStackAllocation
)
@@ -50,7 +51,7 @@ CompilabilityChecker::CompilabilityChecker(
builtinContext.subIDs[_object.name] = 1;
for (auto const& subNode: _object.subObjects)
builtinContext.subIDs[subNode->name] = 1;
NoOutputAssembly assembly;
NoOutputAssembly assembly(_eofVersion.has_value());
CodeTransform transform(
assembly,
analysisInfo,
+6 -1
View File
@@ -44,7 +44,12 @@ namespace solidity::yul
*/
struct CompilabilityChecker
{
CompilabilityChecker(Dialect const& _dialect, Object const& _object, bool _optimizeStackAllocation);
CompilabilityChecker(
Dialect const& _dialect,
std::optional<uint8_t> _eofVersion,
Object const& _object,
bool _optimizeStackAllocation
);
std::map<YulString, std::set<YulString>> unreachableVariables;
std::map<YulString, int> stackDeficit;
};
+1
View File
@@ -184,6 +184,7 @@ void YulStack::optimize(Object& _object, bool _isCreation)
meter = make_unique<GasMeter>(*evmDialect, _isCreation, m_optimiserSettings.expectedExecutionsPerDeployment);
OptimiserSuite::run(
dialect,
m_eofVersion,
meter.get(),
_object,
m_optimiserSettings.optimizeStackAllocation,
+10
View File
@@ -55,10 +55,12 @@ class AbstractAssembly
public:
using LabelID = size_t;
using SubID = size_t;
using FunctionID = uint16_t;
enum class JumpType { Ordinary, IntoFunction, OutOfFunction };
virtual ~AbstractAssembly() = default;
virtual bool supportsFunctions() const = 0;
/// Set a new source location valid starting from the next instruction.
virtual void setSourceLocation(langutil::SourceLocation const& _location) = 0;
/// Retrieve the current height of the stack. This does not have to be zero
@@ -99,6 +101,14 @@ public:
virtual void appendAssemblySize() = 0;
/// Creates a new sub-assembly, which can be referenced using dataSize and dataOffset.
virtual std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly(bool _creation, std::optional<uint8_t> _eofVersion, std::string _name = "") = 0;
virtual FunctionID createFunction(uint8_t _args, uint8_t _rets) = 0;
virtual void beginFunction(FunctionID _functionID) = 0;
virtual void endFunction() = 0;
virtual void appendFunctionCall(FunctionID _functionID) = 0;
virtual void appendFunctionReturn() = 0;
/// Appends the offset of the given sub-assembly or data.
virtual void appendDataOffset(std::vector<SubID> const& _subPath) = 0;
/// Appends the size of the given sub-assembly or data.
+2 -1
View File
@@ -123,7 +123,7 @@ inline bool canBeFreelyGenerated(StackSlot const& _slot)
/// Control flow graph consisting of ``CFG::BasicBlock``s connected by control flow.
struct CFG
{
explicit CFG() {}
explicit CFG(bool _useFunctions): useFunctions(_useFunctions) {}
CFG(CFG const&) = delete;
CFG(CFG&&) = delete;
CFG& operator=(CFG const&) = delete;
@@ -220,6 +220,7 @@ struct CFG
bool canContinue = true;
};
bool useFunctions = false;
/// The main entry point, i.e. the start of the outermost Yul block.
BasicBlock* entry = nullptr;
/// Subgraphs for functions.
@@ -209,10 +209,11 @@ void markNeedsCleanStack(CFG& _cfg)
std::unique_ptr<CFG> ControlFlowGraphBuilder::build(
AsmAnalysisInfo const& _analysisInfo,
Dialect const& _dialect,
std::optional<uint8_t> _eofVersion,
Block const& _block
)
{
auto result = std::make_unique<CFG>();
auto result = std::make_unique<CFG>(_eofVersion.has_value());
result->entry = &result->makeBlock(debugDataOf(_block));
ControlFlowSideEffectsCollector sideEffects(_dialect, _block);
@@ -541,7 +542,7 @@ Stack const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _cal
Scope::Function const& function = lookupFunction(_call.functionName.name);
canContinue = m_graph.functionInfo.at(&function).canContinue;
Stack inputs;
if (canContinue)
if (!m_graph.useFunctions && canContinue)
inputs.emplace_back(FunctionCallReturnLabelSlot{_call});
for (auto const& arg: _call.arguments | ranges::views::reverse)
inputs.emplace_back(std::visit(*this, arg));
@@ -31,7 +31,12 @@ class ControlFlowGraphBuilder
public:
ControlFlowGraphBuilder(ControlFlowGraphBuilder const&) = delete;
ControlFlowGraphBuilder& operator=(ControlFlowGraphBuilder const&) = delete;
static std::unique_ptr<CFG> build(AsmAnalysisInfo const& _analysisInfo, Dialect const& _dialect, Block const& _block);
static std::unique_ptr<CFG> build(
AsmAnalysisInfo const& _analysisInfo,
Dialect const& _dialect,
std::optional<uint8_t> _eofVersion,
Block const& _block
);
StackSlot operator()(Expression const& _literal);
StackSlot operator()(Literal const& _literal);
@@ -81,6 +86,7 @@ private:
AsmAnalysisInfo const& m_info;
std::map<FunctionDefinition const*, ControlFlowSideEffects> const& m_functionSideEffects;
Dialect const& m_dialect;
std::optional<uint8_t> m_eofVersion;
CFG::BasicBlock* m_currentBlock = nullptr;
Scope* m_scope = nullptr;
struct ForLoopInfo
+3
View File
@@ -22,6 +22,7 @@
#pragma once
#include <libyul/Dialect.h>
#include <libyul/Scope.h>
#include <libyul/backends/evm/AbstractAssembly.h>
#include <libyul/ASTForward.h>
@@ -46,6 +47,8 @@ struct BuiltinContext
Object const* currentObject = nullptr;
/// Mapping from named objects to abstract assembly sub IDs.
std::map<YulString, AbstractAssembly::SubID> subIDs;
std::map<Scope::Function const*, AbstractAssembly::FunctionID> functionIDs;
};
struct BuiltinFunctionForEVM: public BuiltinFunction
@@ -86,6 +86,7 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize)
*_object.analysisInfo,
*_object.code,
m_dialect,
m_eofVersion,
context,
OptimizedEVMCodeTransform::UseNamedLabels::ForFirstFunctionOfEachName
);
@@ -44,6 +44,11 @@ EthAssemblyAdapter::EthAssemblyAdapter(evmasm::Assembly& _assembly):
{
}
bool EthAssemblyAdapter::supportsFunctions() const
{
return m_assembly.supportsFunctions();
}
void EthAssemblyAdapter::setSourceLocation(SourceLocation const& _location)
{
m_assembly.setSourceLocation(_location);
@@ -129,6 +134,31 @@ pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> EthAssemblyAdapter::
return {make_shared<EthAssemblyAdapter>(*assembly), static_cast<size_t>(sub.data())};
}
AbstractAssembly::FunctionID EthAssemblyAdapter::createFunction(uint8_t _args, uint8_t _rets)
{
return m_assembly.createFunction(_args, _rets);
}
void EthAssemblyAdapter::beginFunction(AbstractAssembly::FunctionID _functionID)
{
m_assembly.beginFunction(_functionID);
}
void EthAssemblyAdapter::endFunction()
{
m_assembly.endFunction();
}
void EthAssemblyAdapter::appendFunctionReturn()
{
m_assembly.appendFunctionReturn();
}
void EthAssemblyAdapter::appendFunctionCall(FunctionID _functionID)
{
m_assembly.appendFunctionCall(_functionID);
}
void EthAssemblyAdapter::appendDataOffset(vector<AbstractAssembly::SubID> const& _subPath)
{
if (auto it = m_dataHashBySubId.find(_subPath[0]); it != m_dataHashBySubId.end())
+6
View File
@@ -40,6 +40,7 @@ class EthAssemblyAdapter: public AbstractAssembly
{
public:
explicit EthAssemblyAdapter(evmasm::Assembly& _assembly);
bool supportsFunctions() const override;
void setSourceLocation(langutil::SourceLocation const& _location) override;
int stackHeight() const override;
void setStackHeight(int height) override;
@@ -56,6 +57,11 @@ public:
void appendJumpToIf(LabelID _labelId, JumpType _jumpType) override;
void appendAssemblySize() override;
std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly(bool _creation, std::optional<uint8_t> _eofVersion, std::string _name = {}) override;
AbstractAssembly::FunctionID createFunction(uint8_t _args, uint8_t _rets) override;
void beginFunction(AbstractAssembly::FunctionID _functionID) override;
void endFunction() override;
void appendFunctionCall(FunctionID _functionID) override;
void appendFunctionReturn() override;
void appendDataOffset(std::vector<SubID> const& _subPath) override;
void appendDataSize(std::vector<SubID> const& _subPath) override;
SubID appendData(bytes const& _data) override;
+27
View File
@@ -104,6 +104,33 @@ pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> NoOutputAssembly::cr
return {};
}
AbstractAssembly::FunctionID NoOutputAssembly::createFunction(uint8_t _args, uint8_t _rets)
{
yulAssert(m_context->numFunctions <= std::numeric_limits<AbstractAssembly::FunctionID>::max());
AbstractAssembly::FunctionID id = static_cast<AbstractAssembly::FunctionID>(m_context->numFunctions++);
m_context->functionSignatures[id] = std::make_pair(_args, _rets);
return id;
}
void NoOutputAssembly::beginFunction(FunctionID)
{
}
void NoOutputAssembly::endFunction()
{
}
void NoOutputAssembly::appendFunctionCall(FunctionID _functionID)
{
auto [args, rets] = m_context->functionSignatures.at(_functionID);
m_stackHeight += static_cast<int>(rets) - static_cast<int>(args);
}
void NoOutputAssembly::appendFunctionReturn()
{
m_stackHeight = 0;
}
void NoOutputAssembly::appendDataOffset(std::vector<AbstractAssembly::SubID> const&)
{
appendInstruction(evmasm::Instruction::PUSH1);
+19 -1
View File
@@ -37,6 +37,13 @@ struct SourceLocation;
namespace solidity::yul
{
class NoOutputAssembly;
struct NoOutputAssemblyContext
{
size_t numFunctions = 0;
std::map<uint16_t, std::pair<uint8_t, uint8_t>> functionSignatures;
};
/**
* Assembly class that just ignores everything and only performs stack counting.
@@ -45,9 +52,13 @@ namespace solidity::yul
class NoOutputAssembly: public AbstractAssembly
{
public:
explicit NoOutputAssembly() { }
explicit NoOutputAssembly(bool _hasFunctions): m_hasFunctions(_hasFunctions), m_context(std::make_shared<NoOutputAssemblyContext>()) { }
NoOutputAssembly(bool _hasFunctions, std::shared_ptr<NoOutputAssemblyContext> _context): m_hasFunctions(_hasFunctions), m_context(_context) {}
~NoOutputAssembly() override = default;
bool supportsFunctions() const override { return m_hasFunctions; }
void setSourceLocation(langutil::SourceLocation const&) override {}
int stackHeight() const override { return m_stackHeight; }
void setStackHeight(int height) override { m_stackHeight = height; }
@@ -66,6 +77,11 @@ public:
void appendAssemblySize() override;
std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly(bool _creation, std::optional<uint8_t> _eofVersion, std::string _name = "") override;
FunctionID createFunction(uint8_t _args, uint8_t rets) override;
void beginFunction(FunctionID) override;
void endFunction() override;
void appendFunctionCall(FunctionID _functionID) override;
void appendFunctionReturn() override;
void appendDataOffset(std::vector<SubID> const& _subPath) override;
void appendDataSize(std::vector<SubID> const& _subPath) override;
SubID appendData(bytes const& _data) override;
@@ -78,6 +94,8 @@ public:
void markAsInvalid() override {}
private:
bool m_hasFunctions = false;
std::shared_ptr<NoOutputAssemblyContext> m_context;
int m_stackHeight = 0;
};
@@ -45,12 +45,28 @@ vector<StackTooDeepError> OptimizedEVMCodeTransform::run(
AsmAnalysisInfo& _analysisInfo,
Block const& _block,
EVMDialect const& _dialect,
std::optional<uint8_t> _eofVersion,
BuiltinContext& _builtinContext,
UseNamedLabels _useNamedLabelsForFunctions
)
{
std::unique_ptr<CFG> dfg = ControlFlowGraphBuilder::build(_analysisInfo, _dialect, _block);
std::unique_ptr<CFG> dfg = ControlFlowGraphBuilder::build(_analysisInfo, _dialect, _eofVersion, _block);
yulAssert(_eofVersion.has_value() == dfg->useFunctions);
StackLayout stackLayout = StackLayoutGenerator::run(*dfg);
if (dfg->useFunctions)
for (Scope::Function const* function: dfg->functions)
{
auto const& info = dfg->functionInfo.at(function);
yulAssert(info.parameters.size() <= 0xFF);
yulAssert(info.returnVariables.size() <= 0xFF);
auto functionID = _assembly.createFunction(
static_cast<uint8_t>(info.parameters.size()),
static_cast<uint8_t>(info.returnVariables.size())
);
_builtinContext.functionIDs[function] = functionID;
}
OptimizedEVMCodeTransform optimizedCodeTransform(
_assembly,
_builtinContext,
@@ -68,10 +84,11 @@ vector<StackTooDeepError> OptimizedEVMCodeTransform::run(
void OptimizedEVMCodeTransform::operator()(CFG::FunctionCall const& _call)
{
bool useReturnLabel = !m_dfg.useFunctions && _call.canContinue;
// Validate stack.
{
yulAssert(m_assembly.stackHeight() == static_cast<int>(m_stack.size()), "");
yulAssert(m_stack.size() >= _call.function.get().arguments.size() + (_call.canContinue ? 1 : 0), "");
yulAssert(m_stack.size() >= _call.function.get().arguments.size() + (useReturnLabel ? 1 : 0), "");
// Assert that we got the correct arguments on stack for the call.
for (auto&& [arg, slot]: ranges::zip_view(
_call.functionCall.get().arguments | ranges::views::reverse,
@@ -79,7 +96,7 @@ void OptimizedEVMCodeTransform::operator()(CFG::FunctionCall const& _call)
))
validateSlot(slot, arg);
// Assert that we got the correct return label on stack.
if (_call.canContinue)
if (useReturnLabel)
{
auto const* returnLabelSlot = get_if<FunctionCallReturnLabelSlot>(
&m_stack.at(m_stack.size() - _call.functionCall.get().arguments.size() - 1)
@@ -91,19 +108,22 @@ void OptimizedEVMCodeTransform::operator()(CFG::FunctionCall const& _call)
// Emit code.
{
m_assembly.setSourceLocation(originLocationOf(_call));
m_assembly.appendJumpTo(
getFunctionLabel(_call.function),
static_cast<int>(_call.function.get().returns.size() - _call.function.get().arguments.size()) - (_call.canContinue ? 1 : 0),
AbstractAssembly::JumpType::IntoFunction
);
if (_call.canContinue)
if (m_dfg.useFunctions)
m_assembly.appendFunctionCall(m_builtinContext.functionIDs.at(&_call.function.get()));
else
m_assembly.appendJumpTo(
getFunctionLabel(_call.function),
static_cast<int>(_call.function.get().returns.size() - _call.function.get().arguments.size()) - (_call.canContinue ? 1 : 0),
AbstractAssembly::JumpType::IntoFunction
);
if (useReturnLabel)
m_assembly.appendLabel(m_returnLabels.at(&_call.functionCall.get()));
}
// Update stack.
{
// Remove arguments and return label from m_stack.
for (size_t i = 0; i < _call.function.get().arguments.size() + (_call.canContinue ? 1 : 0); ++i)
for (size_t i = 0; i < _call.function.get().arguments.size() + (useReturnLabel ? 1 : 0); ++i)
m_stack.pop_back();
// Push return values to m_stack.
for (size_t index: ranges::views::iota(0u, _call.function.get().returns.size()))
@@ -184,7 +204,7 @@ OptimizedEVMCodeTransform::OptimizedEVMCodeTransform(
m_builtinContext(_builtinContext),
m_dfg(_dfg),
m_stackLayout(_stackLayout),
m_functionLabels([&](){
m_functionLabels(_dfg.useFunctions ? decltype(m_functionLabels)() : [&](){
map<CFG::FunctionInfo const*, AbstractAssembly::LabelID> functionLabels;
set<YulString> assignedFunctionNames;
for (Scope::Function const* function: m_dfg.functions)
@@ -217,6 +237,7 @@ void OptimizedEVMCodeTransform::assertLayoutCompatibility(Stack const& _currentS
AbstractAssembly::LabelID OptimizedEVMCodeTransform::getFunctionLabel(Scope::Function const& _function)
{
yulAssert(!m_dfg.useFunctions);
return m_functionLabels.at(&m_dfg.functionInfo.at(&_function));
}
@@ -491,11 +512,15 @@ void OptimizedEVMCodeTransform::operator()(CFG::BasicBlock const& _block)
Stack exitStack = m_currentFunctionInfo->returnVariables | ranges::views::transform([](auto const& _varSlot){
return StackSlot{_varSlot};
}) | ranges::to<Stack>;
exitStack.emplace_back(FunctionReturnLabelSlot{_functionReturn.info->function});
if (!m_dfg.useFunctions)
exitStack.emplace_back(FunctionReturnLabelSlot{_functionReturn.info->function});
// Create the function return layout and jump.
createStackLayout(debugDataOf(_functionReturn), exitStack);
m_assembly.appendJump(0, AbstractAssembly::JumpType::OutOfFunction);
if (m_dfg.useFunctions)
m_assembly.appendFunctionReturn();
else
m_assembly.appendJump(0, AbstractAssembly::JumpType::OutOfFunction);
},
[&](CFG::BasicBlock::Terminated const&)
{
@@ -516,25 +541,31 @@ void OptimizedEVMCodeTransform::operator()(CFG::BasicBlock const& _block)
void OptimizedEVMCodeTransform::operator()(CFG::FunctionInfo const& _functionInfo)
{
bool useReturnLabel = !m_dfg.useFunctions && _functionInfo.canContinue;
yulAssert(!m_currentFunctionInfo, "");
ScopedSaveAndRestore currentFunctionInfoRestore(m_currentFunctionInfo, &_functionInfo);
yulAssert(m_stack.empty() && m_assembly.stackHeight() == 0, "");
// Create function entry layout in m_stack.
if (_functionInfo.canContinue)
if (useReturnLabel)
m_stack.emplace_back(FunctionReturnLabelSlot{_functionInfo.function});
for (auto const& param: _functionInfo.parameters | ranges::views::reverse)
m_stack.emplace_back(param);
if (m_dfg.useFunctions)
m_assembly.beginFunction(m_builtinContext.functionIDs[&_functionInfo.function]);
m_assembly.setStackHeight(static_cast<int>(m_stack.size()));
m_assembly.setSourceLocation(originLocationOf(_functionInfo));
m_assembly.appendLabel(getFunctionLabel(_functionInfo.function));
if (!m_dfg.useFunctions)
m_assembly.appendLabel(getFunctionLabel(_functionInfo.function));
// Create the entry layout of the function body block and visit.
createStackLayout(debugDataOf(_functionInfo), m_stackLayout.blockInfos.at(_functionInfo.entry).entryLayout);
(*this)(*_functionInfo.entry);
m_stack.clear();
if (m_dfg.useFunctions)
m_assembly.endFunction();
m_assembly.setStackHeight(0);
}
@@ -52,6 +52,7 @@ public:
AsmAnalysisInfo& _analysisInfo,
Block const& _block,
EVMDialect const& _dialect,
std::optional<uint8_t> _eofVersion,
BuiltinContext& _builtinContext,
UseNamedLabels _useNamedLabelsForFunctions
);
+5 -3
View File
@@ -50,7 +50,7 @@ using namespace std;
StackLayout StackLayoutGenerator::run(CFG const& _cfg)
{
StackLayout stackLayout;
StackLayout stackLayout{_cfg.useFunctions, {}, {}};
StackLayoutGenerator{stackLayout}.processEntryPoint(*_cfg.entry);
for (auto& functionInfo: _cfg.functionInfo | ranges::views::values)
@@ -71,7 +71,7 @@ map<YulString, vector<StackLayoutGenerator::StackTooDeep>> StackLayoutGenerator:
vector<StackLayoutGenerator::StackTooDeep> StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg, YulString _functionName)
{
StackLayout stackLayout;
StackLayout stackLayout{_cfg.useFunctions, {}, {}};
CFG::FunctionInfo const* functionInfo = nullptr;
if (!_functionName.empty())
{
@@ -463,7 +463,9 @@ optional<Stack> StackLayoutGenerator::getExitLayoutOrStageDependencies(
Stack stack = _functionReturn.info->returnVariables | ranges::views::transform([](auto const& _varSlot){
return StackSlot{_varSlot};
}) | ranges::to<Stack>;
stack.emplace_back(FunctionReturnLabelSlot{_functionReturn.info->function});
if (!m_layout.useFunctions)
stack.emplace_back(FunctionReturnLabelSlot{_functionReturn.info->function});
return stack;
},
[&](CFG::BasicBlock::Terminated const&) -> std::optional<Stack>
@@ -37,6 +37,7 @@ struct StackLayout
/// The resulting stack layout after executing the block.
Stack exitLayout;
};
bool useFunctions = false;
std::map<CFG::BasicBlock const*, BlockInfo> blockInfos;
/// For each operation the complete stack layout that:
/// - has the slots required for the operation at the stack top.
@@ -74,6 +74,7 @@ Object EVMToEwasmTranslator::run(Object const& _object)
// expectedExecutionsPerDeployment is currently unused.
OptimiserStepContext context{
m_dialect,
nullopt,
nameDispenser,
reservedIdentifiers,
frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment
+1
View File
@@ -35,6 +35,7 @@ class NameDispenser;
struct OptimiserStepContext
{
Dialect const& dialect;
std::optional<uint8_t> eofVersion;
NameDispenser& dispenser;
std::set<YulString> const& reservedIdentifiers;
/// The value nullopt represents creation code
+3 -2
View File
@@ -238,6 +238,7 @@ void eliminateVariablesOptimizedCodegen(
bool StackCompressor::run(
Dialect const& _dialect,
std::optional<uint8_t> _eofVersion,
Object& _object,
bool _optimizeStackAllocation,
size_t _maxIterations
@@ -258,7 +259,7 @@ bool StackCompressor::run(
if (usesOptimizedCodeGenerator)
{
yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object);
unique_ptr<CFG> cfg = ControlFlowGraphBuilder::build(analysisInfo, _dialect, *_object.code);
unique_ptr<CFG> cfg = ControlFlowGraphBuilder::build(analysisInfo, _dialect, _eofVersion, *_object.code);
eliminateVariablesOptimizedCodegen(
_dialect,
*_object.code,
@@ -269,7 +270,7 @@ bool StackCompressor::run(
else
for (size_t iterations = 0; iterations < _maxIterations; iterations++)
{
map<YulString, int> stackSurplus = CompilabilityChecker(_dialect, _object, _optimizeStackAllocation).stackDeficit;
map<YulString, int> stackSurplus = CompilabilityChecker(_dialect, _eofVersion, _object, _optimizeStackAllocation).stackDeficit;
if (stackSurplus.empty())
return true;
eliminateVariables(
+1
View File
@@ -48,6 +48,7 @@ public:
/// @returns true if it was successful.
static bool run(
Dialect const& _dialect,
std::optional<uint8_t> _eofVersion,
Object& _object,
bool _optimizeStackAllocation,
size_t _maxIterations
+2 -1
View File
@@ -131,12 +131,13 @@ void StackLimitEvader::run(
if (evmDialect && evmDialect->evmVersion().canOverchargeGasForCall())
{
yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(*evmDialect, _object);
unique_ptr<CFG> cfg = ControlFlowGraphBuilder::build(analysisInfo, *evmDialect, *_object.code);
unique_ptr<CFG> cfg = ControlFlowGraphBuilder::build(analysisInfo, *evmDialect, _context.eofVersion, *_object.code);
run(_context, _object, StackLayoutGenerator::reportStackTooDeep(*cfg));
}
else
run(_context, _object, CompilabilityChecker{
_context.dialect,
_context.eofVersion,
_object,
true
}.unreachableVariables);
+4 -1
View File
@@ -135,6 +135,7 @@ void outputPerformanceMetrics(map<string, int64_t> const& _metrics)
void OptimiserSuite::run(
Dialect const& _dialect,
std::optional<uint8_t> _eofVersion,
GasMeter const* _meter,
Object& _object,
bool _optimizeStackAllocation,
@@ -161,7 +162,7 @@ void OptimiserSuite::run(
Block& ast = *_object.code;
NameDispenser dispenser{_dialect, ast, reservedIdentifiers};
OptimiserStepContext context{_dialect, dispenser, reservedIdentifiers, _expectedExecutionsPerDeployment};
OptimiserStepContext context{_dialect, _eofVersion, dispenser, reservedIdentifiers, _expectedExecutionsPerDeployment};
OptimiserSuite suite(context, Debug::None);
@@ -182,6 +183,7 @@ void OptimiserSuite::run(
if (!usesOptimizedCodeGenerator)
StackCompressor::run(
_dialect,
_eofVersion,
_object,
_optimizeStackAllocation,
stackCompressorMaxIterations
@@ -202,6 +204,7 @@ void OptimiserSuite::run(
{
StackCompressor::run(
_dialect,
_eofVersion,
_object,
_optimizeStackAllocation,
stackCompressorMaxIterations
+1
View File
@@ -64,6 +64,7 @@ public:
/// The value nullopt for `_expectedExecutionsPerDeployment` represents creation code.
static void run(
Dialect const& _dialect,
std::optional<uint8_t> _eofVersion,
GasMeter const* _meter,
Object& _object,
bool _optimizeStackAllocation,