#pragma once
#include <libsolidity/ast/AST.h>
#include <libsolidity/codegen/ir/IRVariable.h>
#include <libsolidity/interface/OptimiserSettings.h>
#include <libsolidity/interface/DebugSettings.h>
#include <libsolidity/codegen/MultiUseYulFunctionCollector.h>
#include <libsolidity/codegen/ir/Common.h>
#include <liblangutil/CharStreamProvider.h>
#include <liblangutil/DebugInfoSelection.h>
#include <liblangutil/EVMVersion.h>
#include <libsolutil/Common.h>
#include <set>
#include <string>
#include <memory>
#include <vector>
namespace solidity::frontend
{
class YulUtilFunctions;
class ABIFunctions;
struct AscendingFunctionIDCompare
{
bool operator()(FunctionDefinition const* _f1, FunctionDefinition const* _f2) const
{
if (_f1 != nullptr && _f2 != nullptr)
return _f1->id() < _f2->id();
else
return _f1 == nullptr;
}
};
using DispatchSet = std::set<FunctionDefinition const*, AscendingFunctionIDCompare>;
using InternalDispatchMap = std::map<YulArity, DispatchSet>;
class IRGenerationContext
{
public:
enum class ExecutionContext { Creation, Deployed };
IRGenerationContext(
langutil::EVMVersion _evmVersion,
ExecutionContext _executionContext,
RevertStrings _revertStrings,
OptimiserSettings _optimiserSettings,
std::map<std::string, unsigned> _sourceIndices,
langutil::DebugInfoSelection const& _debugInfoSelection,
langutil::CharStreamProvider const* _soliditySourceProvider
):
m_evmVersion(_evmVersion),
m_executionContext(_executionContext),
m_revertStrings(_revertStrings),
m_optimiserSettings(std::move(_optimiserSettings)),
m_sourceIndices(std::move(_sourceIndices)),
m_debugInfoSelection(_debugInfoSelection),
m_soliditySourceProvider(_soliditySourceProvider)
{}
MultiUseYulFunctionCollector& functionCollector() { return m_functions; }
std::string enqueueFunctionForCodeGeneration(FunctionDefinition const& _function);
FunctionDefinition const* dequeueFunctionForCodeGeneration();
bool functionGenerationQueueEmpty() { return m_functionGenerationQueue.empty(); }
void setMostDerivedContract(ContractDefinition const& _mostDerivedContract)
{
m_mostDerivedContract = &_mostDerivedContract;
}
ContractDefinition const& mostDerivedContract() const;
IRVariable const& addLocalVariable(VariableDeclaration const& _varDecl);
bool isLocalVariable(VariableDeclaration const& _varDecl) const { return m_localVariables.count(&_varDecl); }
IRVariable const& localVariable(VariableDeclaration const& _varDecl);
void resetLocalVariables();
void registerImmutableVariable(VariableDeclaration const& _varDecl);
size_t immutableMemoryOffset(VariableDeclaration const& _variable) const;
size_t reservedMemory();
void addStateVariable(VariableDeclaration const& _varDecl, u256 _storageOffset, unsigned _byteOffset);
bool isStateVariable(VariableDeclaration const& _varDecl) const { return m_stateVariables.count(&_varDecl); }
std::pair<u256, unsigned> storageLocationOfStateVariable(VariableDeclaration const& _varDecl) const
{
solAssert(isStateVariable(_varDecl), "");
return m_stateVariables.at(&_varDecl);
}
std::string newYulVariable();
void initializeInternalDispatch(InternalDispatchMap _internalDispatchMap);
InternalDispatchMap consumeInternalDispatchMap();
bool internalDispatchClean() const { return m_internalDispatchMap.empty(); }
void internalFunctionCalledThroughDispatch(YulArity const& _arity);
void addToInternalDispatch(FunctionDefinition const& _function);
YulUtilFunctions utils();
langutil::EVMVersion evmVersion() const { return m_evmVersion; }
ExecutionContext executionContext() const { return m_executionContext; }
void setArithmetic(Arithmetic _value) { m_arithmetic = _value; }
Arithmetic arithmetic() const { return m_arithmetic; }
ABIFunctions abiFunctions();
RevertStrings revertStrings() const { return m_revertStrings; }
std::set<ContractDefinition const*, ASTNode::CompareByID>& subObjectsCreated() { return m_subObjects; }
bool memoryUnsafeInlineAssemblySeen() const { return m_memoryUnsafeInlineAssemblySeen; }
void setMemoryUnsafeInlineAssemblySeen() { m_memoryUnsafeInlineAssemblySeen = true; }
uint64_t internalFunctionID(FunctionDefinition const& _function, bool _requirePresent);
void copyFunctionIDsFrom(IRGenerationContext const& _other);
std::map<std::string, unsigned> const& sourceIndices() const { return m_sourceIndices; }
void markSourceUsed(std::string const& _name) { m_usedSourceNames.insert(_name); }
std::set<std::string> const& usedSourceNames() const { return m_usedSourceNames; }
bool immutableRegistered(VariableDeclaration const& _varDecl) const { return m_immutableVariables.count(&_varDecl); }
langutil::DebugInfoSelection debugInfoSelection() const { return m_debugInfoSelection; }
langutil::CharStreamProvider const* soliditySourceProvider() const { return m_soliditySourceProvider; }
private:
langutil::EVMVersion m_evmVersion;
ExecutionContext m_executionContext;
RevertStrings m_revertStrings;
OptimiserSettings m_optimiserSettings;
std::map<std::string, unsigned> m_sourceIndices;
std::set<std::string> m_usedSourceNames;
ContractDefinition const* m_mostDerivedContract = nullptr;
std::map<VariableDeclaration const*, IRVariable> m_localVariables;
std::map<VariableDeclaration const*, size_t> m_immutableVariables;
std::optional<size_t> m_reservedMemory = {0};
std::map<VariableDeclaration const*, std::pair<u256, unsigned>> m_stateVariables;
MultiUseYulFunctionCollector m_functions;
size_t m_varCounter = 0;
Arithmetic m_arithmetic = Arithmetic::Checked;
bool m_memoryUnsafeInlineAssemblySeen = false;
DispatchSet m_functionGenerationQueue;
InternalDispatchMap m_internalDispatchMap;
std::map<int64_t, uint64_t> m_functionIDs;
std::set<ContractDefinition const*, ASTNode::CompareByID> m_subObjects;
langutil::DebugInfoSelection m_debugInfoSelection = {};
langutil::CharStreamProvider const* m_soliditySourceProvider = nullptr;
};
}