/src/solidity/libsolidity/codegen/LValue.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 | | * @author Christian <c@ethdev.com> |
20 | | * @date 2015 |
21 | | * LValues for use in the expression compiler. |
22 | | */ |
23 | | |
24 | | #pragma once |
25 | | |
26 | | #include <libsolidity/codegen/ArrayUtils.h> |
27 | | #include <libsolutil/Common.h> |
28 | | #include <liblangutil/SourceLocation.h> |
29 | | #include <libevmasm/Instruction.h> |
30 | | #include <memory> |
31 | | #include <vector> |
32 | | |
33 | | namespace solidity::frontend |
34 | | { |
35 | | |
36 | | class Declaration; |
37 | | class Type; |
38 | | class TupleType; |
39 | | class ArrayType; |
40 | | class CompilerContext; |
41 | | class VariableDeclaration; |
42 | | |
43 | | /** |
44 | | * Abstract class used to retrieve, delete and store data in lvalues/variables. |
45 | | */ |
46 | | class LValue |
47 | | { |
48 | | protected: |
49 | | explicit LValue(CompilerContext& _compilerContext, Type const* _dataType = nullptr): |
50 | 340k | m_context(_compilerContext), m_dataType(_dataType) {} |
51 | | |
52 | | public: |
53 | 340k | virtual ~LValue() = default; |
54 | | /// @returns the number of stack slots occupied by the lvalue reference |
55 | 0 | virtual unsigned sizeOnStack() const { return 1; } |
56 | | /// Copies the value of the current lvalue to the top of the stack and, if @a _remove is true, |
57 | | /// also removes the reference from the stack. |
58 | | /// @a _location source location of the current expression, used for error reporting. |
59 | | virtual void retrieveValue(langutil::SourceLocation const& _location, bool _remove = false) const = 0; |
60 | | /// Moves a value from the stack to the lvalue. Removes the value if @a _move is true. |
61 | | /// @a _location is the source location of the expression that caused this operation. |
62 | | /// Stack pre: value [lvalue_ref] |
63 | | /// Stack post: if !_move: value_of(lvalue_ref) |
64 | | virtual void storeValue(Type const& _sourceType, |
65 | | langutil::SourceLocation const& _location = {}, bool _move = false) const = 0; |
66 | | /// Stores zero in the lvalue. Removes the reference from the stack if @a _removeReference is true. |
67 | | /// @a _location is the source location of the requested operation |
68 | | virtual void setToZero( |
69 | | langutil::SourceLocation const& _location = {}, |
70 | | bool _removeReference = true |
71 | | ) const = 0; |
72 | | |
73 | | protected: |
74 | | CompilerContext& m_context; |
75 | | Type const* m_dataType; |
76 | | }; |
77 | | |
78 | | /** |
79 | | * Local variable that is completely stored on the stack. |
80 | | */ |
81 | | class StackVariable: public LValue |
82 | | { |
83 | | public: |
84 | | StackVariable(CompilerContext& _compilerContext, VariableDeclaration const& _declaration); |
85 | | |
86 | 6.72k | unsigned sizeOnStack() const override { return 0; } |
87 | | void retrieveValue(langutil::SourceLocation const& _location, bool _remove = false) const override; |
88 | | void storeValue( |
89 | | Type const& _sourceType, |
90 | | langutil::SourceLocation const& _location = {}, |
91 | | bool _move = false |
92 | | ) const override; |
93 | | void setToZero( |
94 | | langutil::SourceLocation const& _location = {}, |
95 | | bool _removeReference = true |
96 | | ) const override; |
97 | | |
98 | | private: |
99 | | /// Base stack offset (@see CompilerContext::baseStackOffsetOfVariable) of the local variable. |
100 | | unsigned m_baseStackOffset; |
101 | | /// Number of stack elements occupied by the value (not the reference). |
102 | | unsigned m_size; |
103 | | }; |
104 | | |
105 | | /** |
106 | | * Reference to some item in memory. |
107 | | */ |
108 | | class MemoryItem: public LValue |
109 | | { |
110 | | public: |
111 | | MemoryItem(CompilerContext& _compilerContext, Type const& _type, bool _padded = true); |
112 | 56 | unsigned sizeOnStack() const override { return 1; } |
113 | | void retrieveValue(langutil::SourceLocation const& _location, bool _remove = false) const override; |
114 | | void storeValue( |
115 | | Type const& _sourceType, |
116 | | langutil::SourceLocation const& _location = {}, |
117 | | bool _move = false |
118 | | ) const override; |
119 | | void setToZero( |
120 | | langutil::SourceLocation const& _location = {}, |
121 | | bool _removeReference = true |
122 | | ) const override; |
123 | | private: |
124 | | /// Special flag to deal with byte array elements. |
125 | | bool m_padded = false; |
126 | | }; |
127 | | |
128 | | /** |
129 | | * Reference to an immutable variable. During contract creation this refers to a location in memory. At the |
130 | | * end of contract creation the values from these memory locations are copied into all occurrences of the immutable |
131 | | * variable in the runtime code. |
132 | | */ |
133 | | class ImmutableItem: public LValue |
134 | | { |
135 | | public: |
136 | | ImmutableItem(CompilerContext& _compilerContext, VariableDeclaration const& _variable); |
137 | 102 | unsigned sizeOnStack() const override { return 0; } |
138 | | void retrieveValue(langutil::SourceLocation const& _location, bool _remove = false) const override; |
139 | | void storeValue( |
140 | | Type const& _sourceType, |
141 | | langutil::SourceLocation const& _location = {}, |
142 | | bool _move = false |
143 | | ) const override; |
144 | | void setToZero( |
145 | | langutil::SourceLocation const& _location = {}, |
146 | | bool _removeReference = true |
147 | | ) const override; |
148 | | private: |
149 | | VariableDeclaration const& m_variable; |
150 | | }; |
151 | | |
152 | | /** |
153 | | * Reference to some item in storage/transient storage. On the stack this is <storage key> <offset_inside_value>, |
154 | | * where 0 <= offset_inside_value < 32 and an offset of i means that the value is multiplied |
155 | | * by 2**i before storing it. |
156 | | */ |
157 | | template<bool IsTransient> |
158 | | class GenericStorageItem : public LValue |
159 | | { |
160 | | public: |
161 | | /// Constructs the LValue and pushes the location of @a _declaration onto the stack. |
162 | | GenericStorageItem(CompilerContext& _compilerContext, VariableDeclaration const& _declaration); |
163 | | /// Constructs the LValue and assumes that the storage reference is already on the stack. |
164 | | GenericStorageItem(CompilerContext& _compilerContext, Type const& _type); |
165 | 1.05k | unsigned sizeOnStack() const override { return 2; }solidity::frontend::GenericStorageItem<false>::sizeOnStack() const Line | Count | Source | 165 | 1.05k | unsigned sizeOnStack() const override { return 2; } |
Unexecuted instantiation: solidity::frontend::GenericStorageItem<true>::sizeOnStack() const |
166 | | void retrieveValue(langutil::SourceLocation const& _location, bool _remove = false) const override; |
167 | | void storeValue( |
168 | | Type const& _sourceType, |
169 | | langutil::SourceLocation const& _location = {}, |
170 | | bool _move = false |
171 | | ) const override; |
172 | | void setToZero( |
173 | | langutil::SourceLocation const& _location = {}, |
174 | | bool _removeReference = true |
175 | | ) const override; |
176 | | private: |
177 | | static constexpr evmasm::Instruction s_storeInstruction = IsTransient ? evmasm::Instruction::TSTORE : evmasm::Instruction::SSTORE; |
178 | | static constexpr evmasm::Instruction s_loadInstruction = IsTransient ? evmasm::Instruction::TLOAD : evmasm::Instruction::SLOAD; |
179 | | }; |
180 | | extern template class GenericStorageItem<false>; |
181 | | extern template class GenericStorageItem<true>; |
182 | | using StorageItem = GenericStorageItem<false>; |
183 | | using TransientStorageItem = GenericStorageItem<true>; |
184 | | |
185 | | /** |
186 | | * Reference to a single byte inside a storage byte array. |
187 | | * Stack: <storage_ref> <byte_number> |
188 | | */ |
189 | | class StorageByteArrayElement: public LValue |
190 | | { |
191 | | public: |
192 | | /// Constructs the LValue and assumes that the storage reference is already on the stack. |
193 | | StorageByteArrayElement(CompilerContext& _compilerContext); |
194 | 170 | unsigned sizeOnStack() const override { return 2; } |
195 | | void retrieveValue(langutil::SourceLocation const& _location, bool _remove = false) const override; |
196 | | void storeValue( |
197 | | Type const& _sourceType, |
198 | | langutil::SourceLocation const& _location = {}, |
199 | | bool _move = false |
200 | | ) const override; |
201 | | void setToZero( |
202 | | langutil::SourceLocation const& _location = {}, |
203 | | bool _removeReference = true |
204 | | ) const override; |
205 | | }; |
206 | | |
207 | | /** |
208 | | * Tuple object that can itself hold several LValues. |
209 | | */ |
210 | | class TupleObject: public LValue |
211 | | { |
212 | | public: |
213 | | /// Constructs the LValue assuming that the other LValues are present on the stack. |
214 | | /// Empty unique_ptrs are possible if e.g. some values should be ignored during assignment. |
215 | | TupleObject(CompilerContext& _compilerContext, std::vector<std::unique_ptr<LValue>>&& _lvalues); |
216 | | unsigned sizeOnStack() const override; |
217 | | void retrieveValue(langutil::SourceLocation const& _location, bool _remove = false) const override; |
218 | | void storeValue( |
219 | | Type const& _sourceType, |
220 | | langutil::SourceLocation const& _location = {}, |
221 | | bool _move = false |
222 | | ) const override; |
223 | | void setToZero( |
224 | | langutil::SourceLocation const& _location = {}, |
225 | | bool _removeReference = true |
226 | | ) const override; |
227 | | |
228 | | private: |
229 | | std::vector<std::unique_ptr<LValue>> m_lvalues; |
230 | | }; |
231 | | |
232 | | } |