Coverage Report

Created: 2022-08-24 06:28

/src/solidity/libyul/ControlFlowSideEffectsCollector.h
Line
Count
Source (jump to first uncovered line)
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
#pragma once
20
21
#include <libyul/optimiser/ASTWalker.h>
22
#include <libyul/ControlFlowSideEffects.h>
23
24
#include <set>
25
#include <stack>
26
#include <optional>
27
#include <list>
28
29
namespace solidity::yul
30
{
31
32
struct Dialect;
33
34
struct ControlFlowNode
35
{
36
  std::vector<ControlFlowNode const*> successors;
37
  /// Function call AST node, if present.
38
  FunctionCall const* functionCall = nullptr;
39
};
40
41
/**
42
 * The control flow of a function with entry and exit nodes.
43
 */
44
struct FunctionFlow
45
{
46
  ControlFlowNode const* entry;
47
  ControlFlowNode const* exit;
48
};
49
50
/**
51
 * Requires: Disambiguator, Function Hoister.
52
 */
53
class ControlFlowBuilder: private ASTWalker
54
{
55
public:
56
  /// Computes the control-flows of all function defined in the block.
57
  /// Assumes the functions are hoisted to the topmost block.
58
  explicit ControlFlowBuilder(Block const& _ast);
59
0
  std::map<FunctionDefinition const*, FunctionFlow> const& functionFlows() const { return m_functionFlows; }
60
61
private:
62
  using ASTWalker::operator();
63
  void operator()(FunctionCall const& _functionCall) override;
64
  void operator()(If const& _if) override;
65
  void operator()(Switch const& _switch) override;
66
  void operator()(FunctionDefinition const& _functionDefinition) override;
67
  void operator()(ForLoop const& _forLoop) override;
68
  void operator()(Break const& _break) override;
69
  void operator()(Continue const& _continue) override;
70
  void operator()(Leave const& _leaveStatement) override;
71
72
  void newConnectedNode();
73
  ControlFlowNode* newNode();
74
75
  std::vector<std::shared_ptr<ControlFlowNode>> m_nodes;
76
77
  ControlFlowNode* m_currentNode = nullptr;
78
  ControlFlowNode const* m_leave = nullptr;
79
  ControlFlowNode const* m_break = nullptr;
80
  ControlFlowNode const* m_continue = nullptr;
81
82
  std::map<FunctionDefinition const*, FunctionFlow> m_functionFlows;
83
};
84
85
86
/**
87
 * Computes control-flow side-effects for user-defined functions.
88
 * Source does not have to be disambiguated, unless you want the side-effects
89
 * based on function names.
90
 */
91
class ControlFlowSideEffectsCollector
92
{
93
public:
94
  explicit ControlFlowSideEffectsCollector(
95
    Dialect const& _dialect,
96
    Block const& _ast
97
  );
98
99
  std::map<FunctionDefinition const*, ControlFlowSideEffects> const& functionSideEffects() const
100
0
  {
101
0
    return m_functionSideEffects;
102
0
  }
103
  /// Returns the side effects by function name, requires unique function names.
104
  std::map<YulString, ControlFlowSideEffects> functionSideEffectsNamed() const;
105
private:
106
107
  /// @returns false if nothing could be processed.
108
  bool processFunction(FunctionDefinition const& _function);
109
110
  /// @returns the next pending node of the function that is not
111
  /// a function call to a function that might not continue.
112
  /// De-queues the node or returns nullptr if no such node is found.
113
  ControlFlowNode const* nextProcessableNode(FunctionDefinition const& _function);
114
115
  /// @returns the side-effects of either a builtin call or a user defined function
116
  /// call (as far as already computed).
117
  ControlFlowSideEffects const& sideEffects(FunctionCall const& _call) const;
118
119
  /// Queues the given node to be processed (if not already visited)
120
  /// and if it is a function call, records that `_functionName` calls
121
  /// `*_node->functionCall`.
122
  void recordReachabilityAndQueue(FunctionDefinition const& _function, ControlFlowNode const* _node);
123
124
  Dialect const& m_dialect;
125
  ControlFlowBuilder m_cfgBuilder;
126
  /// Function references, but only for calls to user-defined functions.
127
  std::map<FunctionCall const*, FunctionDefinition const*> m_functionReferences;
128
  /// Side effects of user-defined functions, is being constructod.
129
  std::map<FunctionDefinition const*, ControlFlowSideEffects> m_functionSideEffects;
130
  /// Control flow nodes still to process, per function.
131
  std::map<FunctionDefinition const*, std::list<ControlFlowNode const*>> m_pendingNodes;
132
  /// Control flow nodes already processed, per function.
133
  std::map<FunctionDefinition const*, std::set<ControlFlowNode const*>> m_processedNodes;
134
  /// Set of reachable function calls nodes in each function (including calls to builtins).
135
  std::map<FunctionDefinition const*, std::set<FunctionCall const*>> m_functionCalls;
136
};
137
138
139
}