/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/YulString.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 | | using YulType = YulString; |
39 | | |
40 | | struct Variable |
41 | | { |
42 | | YulType type; |
43 | | YulString name; |
44 | | }; |
45 | | struct Function |
46 | | { |
47 | | std::vector<YulType> arguments; |
48 | | std::vector<YulType> returns; |
49 | | YulString name; |
50 | | }; |
51 | | |
52 | | using Identifier = std::variant<Variable, Function>; |
53 | | |
54 | | bool registerVariable(YulString _name, YulType const& _type); |
55 | | bool registerFunction( |
56 | | YulString _name, |
57 | | std::vector<YulType> _arguments, |
58 | | std::vector<YulType> _returns |
59 | | ); |
60 | | |
61 | | /// Looks up the identifier in this or super scopes and returns a valid pointer if found |
62 | | /// or a nullptr if not found. Variable lookups up across function boundaries will fail, as |
63 | | /// will any lookups across assembly boundaries. |
64 | | /// The pointer will be invalidated if the scope is modified. |
65 | | /// @param _crossedFunction if true, we already crossed a function boundary during recursive lookup |
66 | | Identifier* lookup(YulString _name); |
67 | | /// Looks up the identifier in this and super scopes (will not find variables across function |
68 | | /// boundaries and generally stops at assembly boundaries) and calls the visitor, returns |
69 | | /// false if not found. |
70 | | template <class V> |
71 | | bool lookup(YulString _name, V const& _visitor) |
72 | 2.97M | { |
73 | 2.97M | if (Identifier* id = lookup(_name)) |
74 | 2.92M | { |
75 | 2.92M | std::visit(_visitor, *id); |
76 | 2.92M | return true; |
77 | 2.92M | } |
78 | 56.5k | else |
79 | 56.5k | return false; |
80 | 2.97M | } AsmAnalysis.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::AsmAnalyzer::operator()(solidity::yul::Identifier const&)::$_0, solidity::yul::AsmAnalyzer::operator()(solidity::yul::Identifier const&)::$_1> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::AsmAnalyzer::operator()(solidity::yul::Identifier const&)::$_0, solidity::yul::AsmAnalyzer::operator()(solidity::yul::Identifier const&)::$_1> const&) Line | Count | Source | 72 | 1.51M | { | 73 | 1.51M | if (Identifier* id = lookup(_name)) | 74 | 1.48M | { | 75 | 1.48M | std::visit(_visitor, *id); | 76 | 1.48M | return true; | 77 | 1.48M | } | 78 | 28.1k | else | 79 | 28.1k | return false; | 80 | 1.51M | } |
AsmAnalysis.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::AsmAnalyzer::operator()(solidity::yul::FunctionCall const&)::$_4, solidity::yul::AsmAnalyzer::operator()(solidity::yul::FunctionCall const&)::$_5> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::AsmAnalyzer::operator()(solidity::yul::FunctionCall const&)::$_4, solidity::yul::AsmAnalyzer::operator()(solidity::yul::FunctionCall const&)::$_5> const&) Line | Count | Source | 72 | 338k | { | 73 | 338k | if (Identifier* id = lookup(_name)) | 74 | 337k | { | 75 | 337k | std::visit(_visitor, *id); | 76 | 337k | return true; | 77 | 337k | } | 78 | 415 | else | 79 | 415 | return false; | 80 | 338k | } |
EVMCodeTransform.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::CodeTransform::operator()(solidity::yul::FunctionCall const&)::$_0, solidity::yul::CodeTransform::operator()(solidity::yul::FunctionCall const&)::$_1> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::CodeTransform::operator()(solidity::yul::FunctionCall const&)::$_0, solidity::yul::CodeTransform::operator()(solidity::yul::FunctionCall const&)::$_1> const&) Line | Count | Source | 72 | 84.7k | { | 73 | 84.7k | if (Identifier* id = lookup(_name)) | 74 | 84.7k | { | 75 | 84.7k | std::visit(_visitor, *id); | 76 | 84.7k | return true; | 77 | 84.7k | } | 78 | 0 | else | 79 | 0 | return false; | 80 | 84.7k | } |
EVMCodeTransform.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::CodeTransform::operator()(solidity::yul::Identifier const&)::$_2, solidity::yul::CodeTransform::operator()(solidity::yul::Identifier const&)::$_3> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::CodeTransform::operator()(solidity::yul::Identifier const&)::$_2, solidity::yul::CodeTransform::operator()(solidity::yul::Identifier const&)::$_3> const&) Line | Count | Source | 72 | 422k | { | 73 | 422k | if (Identifier* id = lookup(_name)) | 74 | 394k | { | 75 | 394k | std::visit(_visitor, *id); | 76 | 394k | return true; | 77 | 394k | } | 78 | 27.9k | else | 79 | 27.9k | return false; | 80 | 422k | } |
VariableReferenceCounter.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::VariableReferenceCounter::increaseRefIfFound(solidity::yul::YulString)::$_0, solidity::yul::VariableReferenceCounter::increaseRefIfFound(solidity::yul::YulString)::$_1> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::VariableReferenceCounter::increaseRefIfFound(solidity::yul::YulString)::$_0, solidity::yul::VariableReferenceCounter::increaseRefIfFound(solidity::yul::YulString)::$_1> const&) Line | Count | Source | 72 | 287k | { | 73 | 287k | if (Identifier* id = lookup(_name)) | 74 | 287k | { | 75 | 287k | std::visit(_visitor, *id); | 76 | 287k | return true; | 77 | 287k | } | 78 | 4 | else | 79 | 4 | return false; | 80 | 287k | } |
ControlFlowGraphBuilder.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::ControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_12, solidity::yul::ControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_13> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::ControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_12, solidity::yul::ControlFlowGraphBuilder::lookupFunction(solidity::yul::YulString) const::$_13> const&) Line | Count | Source | 72 | 11.8k | { | 73 | 11.8k | if (Identifier* id = lookup(_name)) | 74 | 11.8k | { | 75 | 11.8k | std::visit(_visitor, *id); | 76 | 11.8k | return true; | 77 | 11.8k | } | 78 | 0 | else | 79 | 0 | return false; | 80 | 11.8k | } |
ControlFlowGraphBuilder.cpp:bool solidity::yul::Scope::lookup<solidity::util::GenericVisitor<solidity::yul::ControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_14, solidity::yul::ControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_15> >(solidity::yul::YulString, solidity::util::GenericVisitor<solidity::yul::ControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_14, solidity::yul::ControlFlowGraphBuilder::lookupVariable(solidity::yul::YulString) const::$_15> const&) Line | Count | Source | 72 | 320k | { | 73 | 320k | if (Identifier* id = lookup(_name)) | 74 | 320k | { | 75 | 320k | std::visit(_visitor, *id); | 76 | 320k | return true; | 77 | 320k | } | 78 | 0 | else | 79 | 0 | return false; | 80 | 320k | } |
|
81 | | /// @returns true if the name exists in this scope or in super scopes (also searches |
82 | | /// across function and assembly boundaries). |
83 | | bool exists(YulString _name) const; |
84 | | |
85 | | /// @returns the number of variables directly registered inside the scope. |
86 | | size_t numberOfVariables() const; |
87 | | /// @returns true if this scope is inside a function. |
88 | | bool insideFunction() const; |
89 | | |
90 | | Scope* superScope = nullptr; |
91 | | /// If true, variables from the super scope are not visible here (other identifiers are), |
92 | | /// but they are still taken into account to prevent shadowing. |
93 | | bool functionScope = false; |
94 | | std::map<YulString, Identifier> identifiers; |
95 | | }; |
96 | | |
97 | | } |