/* This file is part of solidity. solidity is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. solidity is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with solidity. If not, see . */ /** * Class that contains contextual information during IR generation. */ #pragma once #include #include #include #include #include #include #include #include #include #include #include namespace solidity::frontend { class YulUtilFunctions; class ABIFunctions; /** * Class that contains contextual information during IR generation. */ class IRGenerationContext { public: IRGenerationContext( langutil::EVMVersion _evmVersion, RevertStrings _revertStrings, OptimiserSettings _optimiserSettings ): m_evmVersion(_evmVersion), m_revertStrings(_revertStrings), m_optimiserSettings(std::move(_optimiserSettings)) {} MultiUseYulFunctionCollector& functionCollector() { return m_functions; } /// Adds a Solidity function to the function generation queue and returns the name of the /// corresponding Yul function. std::string enqueueFunctionForCodeGeneration(FunctionDefinition const& _function); /// Pops one item from the function generation queue. Must not be called if the queue is empty. FunctionDefinition const* dequeueFunctionForCodeGeneration(); bool functionGenerationQueueEmpty() { return m_functionGenerationQueue.empty(); } /// Sets the most derived contract (the one currently being compiled)> 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); /// Registers an immutable variable of the contract. /// Should only be called at construction time. void registerImmutableVariable(VariableDeclaration const& _varDecl); /// @returns the reserved memory for storing the value of the /// immutable @a _variable during contract creation. size_t immutableMemoryOffset(VariableDeclaration const& _variable) const; /// @returns the reserved memory and resets it to mark it as used. /// Intended to be used only once for initializing the free memory pointer /// to after the area used for immutables. 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 storageLocationOfVariable(VariableDeclaration const& _varDecl) const { return m_stateVariables.at(&_varDecl); } std::string functionName(FunctionDefinition const& _function); std::string functionName(VariableDeclaration const& _varDecl); std::string creationObjectName(ContractDefinition const& _contract) const; std::string runtimeObjectName(ContractDefinition const& _contract) const; std::string newYulVariable(); std::string internalDispatch(size_t _in, size_t _out); /// @returns a new copy of the utility function generator (but using the same function set). YulUtilFunctions utils(); langutil::EVMVersion evmVersion() const { return m_evmVersion; }; ABIFunctions abiFunctions(); /// @returns code that stores @param _message for revert reason /// if m_revertStrings is debug. std::string revertReasonIfDebug(std::string const& _message = ""); RevertStrings revertStrings() const { return m_revertStrings; } /// @returns the variable name that can be used to inspect the success or failure of an external /// function call that was invoked as part of the try statement. std::string trySuccessConditionVariable(Expression const& _expression) const; std::set& subObjectsCreated() { return m_subObjects; } private: langutil::EVMVersion m_evmVersion; RevertStrings m_revertStrings; OptimiserSettings m_optimiserSettings; ContractDefinition const* m_mostDerivedContract = nullptr; std::map m_localVariables; /// Memory offsets reserved for the values of immutable variables during contract creation. /// This map is empty in the runtime context. std::map m_immutableVariables; /// Total amount of reserved memory. Reserved memory is used to store /// immutable variables during contract creation. std::optional m_reservedMemory = {0}; /// Storage offsets of state variables std::map> m_stateVariables; MultiUseYulFunctionCollector m_functions; size_t m_varCounter = 0; /// Function definitions queued for code generation. They're the Solidity functions whose calls /// were discovered by the IR generator during AST traversal. /// Note that the queue gets filled in a lazy way - new definitions can be added while the /// collected ones get removed and traversed. /// The order and duplicates are irrelevant here (hence std::set rather than std::queue) as /// long as the order of Yul functions in the generated code is deterministic and the same on /// all platforms - which is a property guaranteed by MultiUseYulFunctionCollector. std::set m_functionGenerationQueue; std::set m_subObjects; }; }