/src/solidity/libyul/Scope.h
Line | Count | Source |
1 | | /* |
2 | | This file is part of solidity. |
3 | | |
4 | | solidity is free software: you can redistribute it and/or modify |
5 | | it under the terms of the GNU General Public License as published by |
6 | | the Free Software Foundation, either version 3 of the License, or |
7 | | (at your option) any later version. |
8 | | |
9 | | solidity is distributed in the hope that it will be useful, |
10 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | GNU General Public License for more details. |
13 | | |
14 | | You should have received a copy of the GNU General Public License |
15 | | along with solidity. If not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | // SPDX-License-Identifier: GPL-3.0 |
18 | | /** |
19 | | * Scopes for identifiers. |
20 | | */ |
21 | | |
22 | | #pragma once |
23 | | |
24 | | #include <liblangutil/Exceptions.h> |
25 | | |
26 | | #include <libyul/YulName.h> |
27 | | |
28 | | #include <functional> |
29 | | #include <memory> |
30 | | #include <optional> |
31 | | #include <variant> |
32 | | |
33 | | namespace solidity::yul |
34 | | { |
35 | | |
36 | | struct Scope |
37 | | { |
38 | | struct Variable |
39 | | { |
40 | | YulName name; |
41 | | }; |
42 | | struct Function |
43 | | { |
44 | | size_t numArguments; |
45 | | size_t numReturns; |
46 | | YulName name; |
47 | | }; |
48 | | |
49 | | using Identifier = std::variant<Variable, Function>; |
50 | | |
51 | | bool registerVariable(YulName _name); |
52 | | bool registerFunction( |
53 | | YulName _name, |
54 | | size_t _numArguments, |
55 | | size_t _numReturns |
56 | | ); |
57 | | |
58 | | /// Looks up the identifier in this or super scopes and returns a valid pointer if found |
59 | | /// or a nullptr if not found. Variable lookups up across function boundaries will fail, as |
60 | | /// will any lookups across assembly boundaries. |
61 | | /// The pointer will be invalidated if the scope is modified. |
62 | | /// @param _crossedFunction if true, we already crossed a function boundary during recursive lookup |
63 | | Identifier* lookup(YulName _name); |
64 | | /// Looks up the identifier in this and super scopes (will not find variables across function |
65 | | /// boundaries and generally stops at assembly boundaries) and calls the visitor, returns |
66 | | /// false if not found. |
67 | | template <class V> |
68 | | bool lookup(YulName _name, V const& _visitor) |
69 | 18.4M | { |
70 | 18.4M | if (Identifier* id = lookup(_name)) |
71 | 18.2M | { |
72 | 18.2M | std::visit(_visitor, *id); |
73 | 18.2M | return true; |
74 | 18.2M | } |
75 | 133k | else |
76 | 133k | return false; |
77 | 18.4M | } AsmAnalysis.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::AsmAnalyzer::operator()(solidity::yul::FunctionCall const&)::$_7::operator()(solidity::yul::Identifier const&) const::{lambda(solidity::yul::Scope::Variable const&)#1}, solidity::yul::AsmAnalyzer::operator()(solidity::yul::FunctionCall const&)::$_7::operator()(solidity::yul::Identifier const&) const::{lambda(solidity::yul::Scope::Function const&)#1}> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::AsmAnalyzer::operator()(solidity::yul::FunctionCall const&)::$_7::operator()(solidity::yul::Identifier const&) const::{lambda(solidity::yul::Scope::Variable const&)#1}, solidity::yul::AsmAnalyzer::operator()(solidity::yul::FunctionCall const&)::$_7::operator()(solidity::yul::Identifier const&) const::{lambda(solidity::yul::Scope::Function const&)#1}> const&) Line | Count | Source | 69 | 2.81M | { | 70 | 2.81M | if (Identifier* id = lookup(_name)) | 71 | 2.80M | { | 72 | 2.80M | std::visit(_visitor, *id); | 73 | 2.80M | return true; | 74 | 2.80M | } | 75 | 11.5k | else | 76 | 11.5k | return false; | 77 | 2.81M | } |
AsmAnalysis.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::AsmAnalyzer::operator()(solidity::yul::Identifier const&)::$_2, solidity::yul::AsmAnalyzer::operator()(solidity::yul::Identifier const&)::$_3> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::AsmAnalyzer::operator()(solidity::yul::Identifier const&)::$_2, solidity::yul::AsmAnalyzer::operator()(solidity::yul::Identifier const&)::$_3> const&) Line | Count | Source | 69 | 6.97M | { | 70 | 6.97M | if (Identifier* id = lookup(_name)) | 71 | 6.90M | { | 72 | 6.90M | std::visit(_visitor, *id); | 73 | 6.90M | return true; | 74 | 6.90M | } | 75 | 64.8k | else | 76 | 64.8k | return false; | 77 | 6.97M | } |
EVMCodeTransform.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::CodeTransform::operator()(solidity::yul::FunctionCall const&)::$_1, solidity::yul::CodeTransform::operator()(solidity::yul::FunctionCall const&)::$_2> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::CodeTransform::operator()(solidity::yul::FunctionCall const&)::$_1, solidity::yul::CodeTransform::operator()(solidity::yul::FunctionCall const&)::$_2> const&) Line | Count | Source | 69 | 458k | { | 70 | 458k | if (Identifier* id = lookup(_name)) | 71 | 458k | { | 72 | 458k | std::visit(_visitor, *id); | 73 | 458k | return true; | 74 | 458k | } | 75 | 0 | else | 76 | 0 | return false; | 77 | 458k | } |
EVMCodeTransform.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::CodeTransform::operator()(solidity::yul::Identifier const&)::$_3, solidity::yul::CodeTransform::operator()(solidity::yul::Identifier const&)::$_4> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::CodeTransform::operator()(solidity::yul::Identifier const&)::$_3, solidity::yul::CodeTransform::operator()(solidity::yul::Identifier const&)::$_4> const&) Line | Count | Source | 69 | 1.37M | { | 70 | 1.37M | if (Identifier* id = lookup(_name)) | 71 | 1.31M | { | 72 | 1.31M | std::visit(_visitor, *id); | 73 | 1.31M | return true; | 74 | 1.31M | } | 75 | 57.1k | else | 76 | 57.1k | return false; | 77 | 1.37M | } |
Unexecuted instantiation: SSAControlFlowGraphBuilder.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::SSAControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_21, solidity::yul::SSAControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_22> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::SSAControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_21, solidity::yul::SSAControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_22> const&) Unexecuted instantiation: SSAControlFlowGraphBuilder.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::SSAControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_23, solidity::yul::SSAControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_24> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::SSAControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_23, solidity::yul::SSAControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_24> const&) VariableReferenceCounter.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::VariableReferenceCounter::increaseRefIfFound(solidity::yul::YulString)::$_1, solidity::yul::VariableReferenceCounter::increaseRefIfFound(solidity::yul::YulString)::$_2> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::VariableReferenceCounter::increaseRefIfFound(solidity::yul::YulString)::$_1, solidity::yul::VariableReferenceCounter::increaseRefIfFound(solidity::yul::YulString)::$_2> const&) Line | Count | Source | 69 | 887k | { | 70 | 887k | if (Identifier* id = lookup(_name)) | 71 | 887k | { | 72 | 887k | std::visit(_visitor, *id); | 73 | 887k | return true; | 74 | 887k | } | 75 | 0 | else | 76 | 0 | return false; | 77 | 887k | } |
ControlFlowGraphBuilder.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::ControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_13, solidity::yul::ControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_14> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::ControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_13, solidity::yul::ControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_14> const&) Line | Count | Source | 69 | 933k | { | 70 | 933k | if (Identifier* id = lookup(_name)) | 71 | 933k | { | 72 | 933k | std::visit(_visitor, *id); | 73 | 933k | return true; | 74 | 933k | } | 75 | 0 | else | 76 | 0 | return false; | 77 | 933k | } |
ControlFlowGraphBuilder.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::ControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_15, solidity::yul::ControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_16> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::ControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_15, solidity::yul::ControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_16> const&) Line | Count | Source | 69 | 4.97M | { | 70 | 4.97M | if (Identifier* id = lookup(_name)) | 71 | 4.97M | { | 72 | 4.97M | std::visit(_visitor, *id); | 73 | 4.97M | return true; | 74 | 4.97M | } | 75 | 0 | else | 76 | 0 | return false; | 77 | 4.97M | } |
|
78 | | /// @returns true if the name exists in this scope or in super scopes (also searches |
79 | | /// across function and assembly boundaries). |
80 | | bool exists(YulName _name) const; |
81 | | |
82 | | /// @returns the number of variables directly registered inside the scope. |
83 | | size_t numberOfVariables() const; |
84 | | /// @returns true if this scope is inside a function. |
85 | | bool insideFunction() const; |
86 | | |
87 | | Scope* superScope = nullptr; |
88 | | /// If true, variables from the super scope are not visible here (other identifiers are), |
89 | | /// but they are still taken into account to prevent shadowing. |
90 | | bool functionScope = false; |
91 | | std::map<YulName, Identifier> identifiers; |
92 | | }; |
93 | | |
94 | | } |