summaryrefslogtreecommitdiffstats
path: root/dx/src/com/android/dx/cf/code/LocalsArray.java
blob: 75af04752d656bf8ada1078df78ea3ac6ba02d93 (plain)
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.dx.cf.code;

import com.android.dx.rop.code.RegisterSpec;
import com.android.dx.rop.type.Type;
import com.android.dx.rop.type.TypeBearer;
import com.android.dx.util.ExceptionWithContext;
import com.android.dx.util.Hex;
import com.android.dx.util.MutabilityControl;
import com.android.dx.util.ToHuman;

/**
 * Representation of an array of local variables, with Java semantics.
 *
 * <p><b>Note:</b> For the most part, the documentation for this class
 * ignores the distinction between {@link Type} and {@link
 * TypeBearer}.</p>
 */
public abstract class LocalsArray extends MutabilityControl implements ToHuman {

    /**
     * Constructs an instance, explicitly indicating the mutability.
     *
     * @param mutable {@code true} if this instance is mutable
     */
    protected LocalsArray(boolean mutable) {
        super(mutable);
    }

    /**
     * Makes and returns a mutable copy of this instance.
     *
     * @return {@code non-null;} the copy
     */
    public abstract LocalsArray copy();

    /**
     * Annotates (adds context to) the given exception with information
     * about this instance.
     *
     * @param ex {@code non-null;} the exception to annotate
     */
    public abstract void annotate(ExceptionWithContext ex);

    /**
     * Replaces all the occurrences of the given uninitialized type in
     * this array with its initialized equivalent.
     *
     * @param type {@code non-null;} type to replace
     */
    public abstract void makeInitialized(Type type);

    /**
     * Gets the maximum number of locals this instance can refer to.
     *
     * @return the max locals
     */
    public abstract int getMaxLocals();

    /**
     * Sets the type stored at the given local index. If the given type
     * is category-2, then (a) the index must be at least two less than
     * {@link #getMaxLocals} and (b) the next index gets invalidated
     * by the operation. In case of either category, if the <i>previous</i>
     * local contains a category-2 value, then it too is invalidated by
     * this operation.
     *
     * @param idx {@code >= 0, < getMaxLocals();} which local
     * @param type {@code non-null;} new type for the local at {@code idx}
     */
    public abstract void set(int idx, TypeBearer type);

    /**
     * Sets the type for the local indicated by the given register spec
     * to that register spec (which includes type and optional name
     * information). This is identical to calling
     * {@code set(spec.getReg(), spec)}.
     *
     * @param spec {@code non-null;} register spec to use as the basis for the update
     */
    public abstract void set(RegisterSpec spec);

    /**
     * Invalidates the local at the given index.
     *
     * @param idx {@code >= 0, < getMaxLocals();} which local
     */
    public abstract void invalidate(int idx);

    /**
     * Gets the type stored at the given local index, or {@code null}
     * if the given local is uninitialized / invalid.
     *
     * @param idx {@code >= 0, < getMaxLocals();} which local
     * @return {@code null-ok;} the type of value stored in that local
     */
    public abstract TypeBearer getOrNull(int idx);

    /**
     * Gets the type stored at the given local index, only succeeding if
     * the given local contains a valid type (though it is allowed to
     * be an uninitialized instance).
     *
     * @param idx {@code >= 0, < getMaxLocals();} which local
     * @return {@code non-null;} the type of value stored in that local
     * @throws SimException thrown if {@code idx} is valid, but
     * the contents are invalid
     */
    public abstract TypeBearer get(int idx);

    /**
     * Gets the type stored at the given local index, which is expected
     * to be an initialized category-1 value.
     *
     * @param idx {@code >= 0, < getMaxLocals();} which local
     * @return {@code non-null;} the type of value stored in that local
     * @throws SimException thrown if {@code idx} is valid, but
     * one of the following holds: (a) the local is invalid; (b) the local
     * contains an uninitialized instance; (c) the local contains a
     * category-2 value
     */
    public abstract TypeBearer getCategory1(int idx);

    /**
     * Gets the type stored at the given local index, which is expected
     * to be a category-2 value.
     *
     * @param idx {@code >= 0, < getMaxLocals();} which local
     * @return {@code non-null;} the type of value stored in that local
     * @throws SimException thrown if {@code idx} is valid, but
     * one of the following holds: (a) the local is invalid; (b) the local
     * contains a category-1 value
     */
    public abstract TypeBearer getCategory2(int idx);

    /**
     * Merges this instance with {@code other}. If the merged result is
     * the same as this instance, then this is returned (not a copy).
     *
     * @param other {@code non-null;} another LocalsArray
     * @return {@code non-null;} the merge result, a new instance or this
     */
    public abstract LocalsArray merge(LocalsArray other);

    /**
     * Merges this instance with a {@code LocalsSet} from a subroutine
     * caller. To be used when merging in the first block of a subroutine.
     *
     * @param other {@code other non-null;} another LocalsArray. The final locals
     * state of a subroutine caller.
     * @param predLabel the label of the subroutine caller block.
     * @return {@code non-null;} the merge result, a new instance or this
     */
    public abstract LocalsArraySet mergeWithSubroutineCaller
            (LocalsArray other, int predLabel);

    /**
     * Gets the locals set appropriate for the current execution context.
     * That is, if this is a {@code OneLocalsArray} instance, then return
     * {@code this}, otherwise return {@code LocalsArraySet}'s
     * primary.
     *
     * @return locals for this execution context.
     */
    protected abstract OneLocalsArray getPrimary();

}