aboutsummaryrefslogtreecommitdiffstats
path: root/LValue.h
blob: 1ed0ae01197686b9da33d005d5562bd848910de6 (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
133
134
135
136
137
138
/*
    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 2015
 * LValues for use in the expresison compiler.
 */

#pragma once

#include <memory>
#include <libevmcore/SourceLocation.h>
#include <libsolidity/ArrayUtils.h>

namespace dev
{
namespace solidity
{

class Declaration;
class Type;
class ArrayType;
class CompilerContext;

/**
 * Abstract class used to retrieve, delete and store data in lvalues/variables.
 */
class LValue
{
protected:
    LValue(CompilerContext& _compilerContext, Type const& _dataType):
        m_context(_compilerContext), m_dataType(_dataType) {}

public:
    /// @returns true if this lvalue reference type occupies a slot on the stack.
    virtual bool storesReferenceOnStack() const = 0;
    /// Copies the value of the current lvalue to the top of the stack and, if @a _remove is true,
    /// also removes the reference from the stack.
    /// @a _location source location of the current expression, used for error reporting.
    virtual void retrieveValue(SourceLocation const& _location, bool _remove = false) const = 0;
    /// Moves a value from the stack to the lvalue. Removes the value if @a _move is true.
    /// @a _location is the source location of the expression that caused this operation.
    /// Stack pre: value [lvalue_ref]
    /// Stack post: if !_move: value_of(lvalue_ref)
    virtual void storeValue(Type const& _sourceType,
        SourceLocation const& _location = SourceLocation(), bool _move = false) const = 0;
    /// Stores zero in the lvalue. Removes the reference from the stack if @a _removeReference is true.
    /// @a _location is the source location of the requested operation
    virtual void setToZero(
        SourceLocation const& _location = SourceLocation(), bool _removeReference = true) const = 0;

protected:
    CompilerContext& m_context;
    Type const& m_dataType;
};

/**
 * Local variable that is completely stored on the stack.
 */
class StackVariable: public LValue
{
public:
    StackVariable(CompilerContext& _compilerContext, Declaration const& _declaration);

    virtual bool storesReferenceOnStack() const { return false; }
    virtual void retrieveValue(SourceLocation const& _location, bool _remove = false) const override;
    virtual void storeValue(Type const& _sourceType,
        SourceLocation const& _location = SourceLocation(), bool _move = false) const override;
    virtual void setToZero(
        SourceLocation const& _location = SourceLocation(), bool _removeReference = true) const override;

private:
    /// Base stack offset (@see CompilerContext::getBaseStackOffsetOfVariable) of the local variable.
    unsigned m_baseStackOffset;
    /// Number of stack elements occupied by the value (not the reference).
    unsigned m_size;
};

/**
 * Reference to some item in storage. The (starting) position of the item is stored on the stack.
 */
class StorageItem: public LValue
{
public:
    /// Constructs the LValue and pushes the location of @a _declaration onto the stack.
    StorageItem(CompilerContext& _compilerContext, Declaration const& _declaration);
    /// Constructs the LValue and assumes that the storage reference is already on the stack.
    StorageItem(CompilerContext& _compilerContext, Type const& _type);
    virtual bool storesReferenceOnStack() const { return true; }
    virtual void retrieveValue(SourceLocation const& _location, bool _remove = false) const override;
    virtual void storeValue(Type const& _sourceType,
        SourceLocation const& _location = SourceLocation(), bool _move = false) const override;
    virtual void setToZero(
        SourceLocation const& _location = SourceLocation(), bool _removeReference = true) const override;

private:
    /// Number of stack elements occupied by the value (not the reference).
    /// Only used for value types.
    unsigned m_size;
};

/**
 * Reference to the "length" member of a dynamically-sized array. This is an LValue with special
 * semantics since assignments to it might reduce its length and thus arrays members have to be
 * deleted.
 */
class StorageArrayLength: public LValue
{
public:
    /// Constructs the LValue, assumes that the reference to the array head is already on the stack.
    StorageArrayLength(CompilerContext& _compilerContext, ArrayType const& _arrayType);
    virtual bool storesReferenceOnStack() const { return true; }
    virtual void retrieveValue(SourceLocation const& _location, bool _remove = false) const override;
    virtual void storeValue(Type const& _sourceType,
        SourceLocation const& _location = SourceLocation(), bool _move = false) const override;
    virtual void setToZero(
        SourceLocation const& _location = SourceLocation(), bool _removeReference = true) const override;

private:
    ArrayType const& m_arrayType;
};

}
}