/src/solidity/libsolidity/codegen/ArrayUtils.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 | | * Code generation utils that handle arrays. |
22 | | */ |
23 | | |
24 | | #pragma once |
25 | | |
26 | | #include <memory> |
27 | | |
28 | | namespace solidity::frontend |
29 | | { |
30 | | |
31 | | class CompilerContext; |
32 | | class Type; |
33 | | class ArrayType; |
34 | | |
35 | | /** |
36 | | * Class that provides code generation for handling arrays. |
37 | | */ |
38 | | class ArrayUtils |
39 | | { |
40 | | public: |
41 | 172k | explicit ArrayUtils(CompilerContext& _context): m_context(_context) {} |
42 | | |
43 | | /// Copies an array to an array in storage. The arrays can be of different types only if |
44 | | /// their storage representation is the same. |
45 | | /// Stack pre: source_reference [source_length] target_reference |
46 | | /// Stack post: target_reference |
47 | | void copyArrayToStorage(ArrayType const& _targetType, ArrayType const& _sourceType) const; |
48 | | /// Copies the data part of an array (which cannot be dynamically nested) from anywhere |
49 | | /// to a given position in memory. |
50 | | /// This always copies contained data as is (i.e. structs and fixed-size arrays are copied in |
51 | | /// place as required by the ABI encoding). Use CompilerUtils::convertType if you want real |
52 | | /// memory copies of nested arrays. |
53 | | /// Stack pre: memory_offset source_item |
54 | | /// Stack post: memory_offset + length(padded) |
55 | | void copyArrayToMemory(ArrayType const& _sourceType, bool _padToWordBoundaries = true) const; |
56 | | /// Clears the given dynamic or static array. |
57 | | /// Stack pre: storage_ref storage_byte_offset |
58 | | /// Stack post: |
59 | | void clearArray(ArrayType const& _type) const; |
60 | | /// Clears the length and data elements of the array referenced on the stack. |
61 | | /// Stack pre: reference (excludes byte offset) |
62 | | /// Stack post: |
63 | | void clearDynamicArray(ArrayType const& _type) const; |
64 | | /// Changes the size of a dynamic array and clears the tail if it is shortened. |
65 | | /// Stack pre: reference (excludes byte offset) new_length |
66 | | /// Stack post: |
67 | | void resizeDynamicArray(ArrayType const& _type) const; |
68 | | /// Increments the size of a dynamic array by one. |
69 | | /// Does not touch the new data element. In case of a byte array, this might move the |
70 | | /// data. |
71 | | /// Stack pre: reference (excludes byte offset) |
72 | | /// Stack post: new_length |
73 | | void incrementDynamicArraySize(ArrayType const& _type) const; |
74 | | /// Decrements the size of a dynamic array by one if length is nonzero. Causes a Panic otherwise. |
75 | | /// Clears the removed data element. In case of a byte array, this might move the data. |
76 | | /// Stack pre: reference |
77 | | /// Stack post: |
78 | | void popStorageArrayElement(ArrayType const& _type) const; |
79 | | /// Appends a loop that clears a sequence of storage slots of the given type (excluding end). |
80 | | /// Stack pre: end_ref start_ref |
81 | | /// Stack post: end_ref |
82 | | void clearStorageLoop(Type const* _type) const; |
83 | | /// Converts length to size (number of storage slots or calldata/memory bytes). |
84 | | /// if @a _pad then add padding to multiples of 32 bytes for calldata/memory. |
85 | | /// Stack pre: length |
86 | | /// Stack post: size |
87 | | void convertLengthToSize(ArrayType const& _arrayType, bool _pad = false) const; |
88 | | /// Retrieves the length (number of elements) of the array ref on the stack. This also |
89 | | /// works for statically-sized arrays. |
90 | | /// @param _stackDepth number of stack elements between top of stack and top (!) of reference |
91 | | /// Stack pre: reference (excludes byte offset for dynamic storage arrays) |
92 | | /// Stack post: reference length |
93 | | void retrieveLength(ArrayType const& _arrayType, unsigned _stackDepth = 0) const; |
94 | | /// Stores the length of an array of type @a _arrayType in storage. The length itself is stored |
95 | | /// on the stack at position @a _stackDepthLength and the storage reference at @a _stackDepthRef. |
96 | | /// If @a _arrayType is a byte array, takes tight coding into account. |
97 | | void storeLength(ArrayType const& _arrayType, unsigned _stackDepthLength = 0, unsigned _stackDepthRef = 1) const; |
98 | | /// Checks whether the index is out of range and returns the absolute offset of the element reference[index] |
99 | | /// (i.e. reference + index * size_of_base_type). |
100 | | /// If @a _keepReference is true, the base reference to the beginning of the array is kept on the stack. |
101 | | /// Stack pre: reference [length] index |
102 | | /// Stack post (storage): [reference] storage_slot byte_offset |
103 | | /// Stack post: [reference] memory/calldata_offset |
104 | | void accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck = true, bool _keepReference = false) const; |
105 | | /// Access calldata array's element and put it on stack. |
106 | | /// Stack pre: reference [length] index |
107 | | /// Stack post: value |
108 | | void accessCallDataArrayElement(ArrayType const& _arrayType, bool _doBoundsCheck = true) const; |
109 | | |
110 | | private: |
111 | | /// Adds the given number of bytes to a storage byte offset counter and also increments |
112 | | /// the storage offset if adding this number again would increase the counter over 32. |
113 | | /// @param byteOffsetPosition the stack offset of the storage byte offset |
114 | | /// @param storageOffsetPosition the stack offset of the storage slot offset |
115 | | void incrementByteOffset(unsigned _byteSize, unsigned _byteOffsetPosition, unsigned _storageOffsetPosition) const; |
116 | | |
117 | | CompilerContext& m_context; |
118 | | }; |
119 | | |
120 | | } |