aboutsummaryrefslogtreecommitdiffstats
path: root/CompilerUtils.h
blob: 27c46ba11040982a2e6917b9ccb95959d1ea680d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
    This file is part of cpp-ethereum.

    cpp-ethereum is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    cpp-ethereum is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * @author Christian <c@ethdev.com>
 * @date 2014
 * Routines used by both the compiler and the expression compiler.
 */

#pragma once

#include <libsolidity/CompilerContext.h>
#include <libsolidity/ASTForward.h>

namespace dev {
namespace solidity {

class Type; // forward

class CompilerUtils
{
public:
    CompilerUtils(CompilerContext& _context): m_context(_context) {}

    /// Stores the initial value of the free-memory-pointer at its position;
    void initialiseFreeMemoryPointer();
    /// Copies the free memory pointer to the stack.
    void fetchFreeMemoryPointer();
    /// Stores the free memory pointer from the stack.
    void storeFreeMemoryPointer();
    /// Appends code that transforms memptr to (memptr - free_memptr) memptr
    void toSizeAfterFreeMemoryPointer();

    /// Loads data from memory to the stack.
    /// @param _offset offset in memory (or calldata)
    /// @param _type data type to load
    /// @param _fromCalldata if true, load from calldata, not from memory
    /// @param _padToWordBoundaries if true, assume the data is padded to word (32 byte) boundaries
    /// @returns the number of bytes consumed in memory.
    unsigned loadFromMemory(
        unsigned _offset,
        Type const& _type = IntegerType(256),
        bool _fromCalldata = false,
        bool _padToWordBoundaries = false
    );
    /// Dynamic version of @see loadFromMemory, expects the memory offset on the stack.
    /// Stack pre: memory_offset
    /// Stack post: value... (memory_offset+length)
    void loadFromMemoryDynamic(
        Type const& _type,
        bool _fromCalldata = false,
        bool _padToWordBoundaries = true,
        bool _keepUpdatedMemoryOffset = true
    );
    /// Stores data from stack in memory.
    /// @param _offset offset in memory
    /// @param _type type of the data on the stack
    /// @param _padToWordBoundaries if true, pad the data to word (32 byte) boundaries
    /// @returns the number of bytes written to memory (can be different from _bytes if
    ///          _padToWordBoundaries is true)
    unsigned storeInMemory(unsigned _offset,
        Type const& _type = IntegerType(256),
        bool _padToWordBoundaries = false
    );
    /// Dynamic version of @see storeInMemory, expects the memory offset below the value on the stack
    /// and also updates that. For arrays, only copies the data part.
    /// Stack pre: memory_offset value...
    /// Stack post: (memory_offset+length)
    void storeInMemoryDynamic(Type const& _type, bool _padToWordBoundaries = true);

    /// Moves the value that is at the top of the stack to a stack variable.
    void moveToStackVariable(VariableDeclaration const& _variable);
    /// Copies an item that occupies @a _itemSize stack slots from a stack depth of @a _stackDepth
    /// to the top of the stack.
    void copyToStackTop(unsigned _stackDepth, unsigned _itemSize);
    /// Moves a single stack element (with _stackDepth items on top of it) to the top of the stack.
    void moveToStackTop(unsigned _stackDepth);
    /// Removes the current value from the top of the stack.
    void popStackElement(Type const& _type);
    /// Removes element from the top of the stack _amount times.
    void popStackSlots(size_t _amount);

    template <class T>
    static unsigned getSizeOnStack(std::vector<T> const& _variables);
    static unsigned getSizeOnStack(std::vector<std::shared_ptr<Type const>> const& _variableTypes);

    /// Appends code that computes tha SHA3 hash of the topmost stack element of type @a _type.
    /// If @a _pad is set, padds the type to muliples of 32 bytes.
    /// @note Only works for types of fixed size.
    void computeHashStatic(Type const& _type = IntegerType(256), bool _padToWordBoundaries = false);

    /// Bytes we need to the start of call data.
    ///  - The size in bytes of the function (hash) identifier.
    static const unsigned dataStartOffset;

    /// Position of the free-memory-pointer in memory;
    static const size_t freeMemoryPointer;

private:
    /// Prepares the given type for storing in memory by shifting it if necessary.
    unsigned prepareMemoryStore(Type const& _type, bool _padToWordBoundaries) const;
    /// Loads type from memory assuming memory offset is on stack top.
    unsigned loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWordBoundaries);

    CompilerContext& m_context;
};


template <class T>
unsigned CompilerUtils::getSizeOnStack(std::vector<T> const& _variables)
{
    unsigned size = 0;
    for (T const& variable: _variables)
        size += variable->getType()->getSizeOnStack();
    return size;
}

}
}