1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.dx.cf.code;
18
19import com.android.dex.util.ExceptionWithContext;
20import com.android.dx.rop.code.RegisterSpec;
21import com.android.dx.rop.type.Type;
22import com.android.dx.rop.type.TypeBearer;
23import com.android.dx.util.MutabilityControl;
24import com.android.dx.util.ToHuman;
25
26/**
27 * Representation of an array of local variables, with Java semantics.
28 *
29 * <p><b>Note:</b> For the most part, the documentation for this class
30 * ignores the distinction between {@link Type} and {@link
31 * TypeBearer}.</p>
32 */
33public abstract class LocalsArray extends MutabilityControl implements ToHuman {
34
35    /**
36     * Constructs an instance, explicitly indicating the mutability.
37     *
38     * @param mutable {@code true} if this instance is mutable
39     */
40    protected LocalsArray(boolean mutable) {
41        super(mutable);
42    }
43
44    /**
45     * Makes and returns a mutable copy of this instance.
46     *
47     * @return {@code non-null;} the copy
48     */
49    public abstract LocalsArray copy();
50
51    /**
52     * Annotates (adds context to) the given exception with information
53     * about this instance.
54     *
55     * @param ex {@code non-null;} the exception to annotate
56     */
57    public abstract void annotate(ExceptionWithContext ex);
58
59    /**
60     * Replaces all the occurrences of the given uninitialized type in
61     * this array with its initialized equivalent.
62     *
63     * @param type {@code non-null;} type to replace
64     */
65    public abstract void makeInitialized(Type type);
66
67    /**
68     * Gets the maximum number of locals this instance can refer to.
69     *
70     * @return the max locals
71     */
72    public abstract int getMaxLocals();
73
74    /**
75     * Sets the type stored at the given local index. If the given type
76     * is category-2, then (a) the index must be at least two less than
77     * {@link #getMaxLocals} and (b) the next index gets invalidated
78     * by the operation. In case of either category, if the <i>previous</i>
79     * local contains a category-2 value, then it too is invalidated by
80     * this operation.
81     *
82     * @param idx {@code >= 0, < getMaxLocals();} which local
83     * @param type {@code non-null;} new type for the local at {@code idx}
84     */
85    public abstract void set(int idx, TypeBearer type);
86
87    /**
88     * Sets the type for the local indicated by the given register spec
89     * to that register spec (which includes type and optional name
90     * information). This is identical to calling
91     * {@code set(spec.getReg(), spec)}.
92     *
93     * @param spec {@code non-null;} register spec to use as the basis for the update
94     */
95    public abstract void set(RegisterSpec spec);
96
97    /**
98     * Invalidates the local at the given index.
99     *
100     * @param idx {@code >= 0, < getMaxLocals();} which local
101     */
102    public abstract void invalidate(int idx);
103
104    /**
105     * Gets the type stored at the given local index, or {@code null}
106     * if the given local is uninitialized / invalid.
107     *
108     * @param idx {@code >= 0, < getMaxLocals();} which local
109     * @return {@code null-ok;} the type of value stored in that local
110     */
111    public abstract TypeBearer getOrNull(int idx);
112
113    /**
114     * Gets the type stored at the given local index, only succeeding if
115     * the given local contains a valid type (though it is allowed to
116     * be an uninitialized instance).
117     *
118     * @param idx {@code >= 0, < getMaxLocals();} which local
119     * @return {@code non-null;} the type of value stored in that local
120     * @throws SimException thrown if {@code idx} is valid, but
121     * the contents are invalid
122     */
123    public abstract TypeBearer get(int idx);
124
125    /**
126     * Gets the type stored at the given local index, which is expected
127     * to be an initialized category-1 value.
128     *
129     * @param idx {@code >= 0, < getMaxLocals();} which local
130     * @return {@code non-null;} the type of value stored in that local
131     * @throws SimException thrown if {@code idx} is valid, but
132     * one of the following holds: (a) the local is invalid; (b) the local
133     * contains an uninitialized instance; (c) the local contains a
134     * category-2 value
135     */
136    public abstract TypeBearer getCategory1(int idx);
137
138    /**
139     * Gets the type stored at the given local index, which is expected
140     * to be a category-2 value.
141     *
142     * @param idx {@code >= 0, < getMaxLocals();} which local
143     * @return {@code non-null;} the type of value stored in that local
144     * @throws SimException thrown if {@code idx} is valid, but
145     * one of the following holds: (a) the local is invalid; (b) the local
146     * contains a category-1 value
147     */
148    public abstract TypeBearer getCategory2(int idx);
149
150    /**
151     * Merges this instance with {@code other}. If the merged result is
152     * the same as this instance, then this is returned (not a copy).
153     *
154     * @param other {@code non-null;} another LocalsArray
155     * @return {@code non-null;} the merge result, a new instance or this
156     */
157    public abstract LocalsArray merge(LocalsArray other);
158
159    /**
160     * Merges this instance with a {@code LocalsSet} from a subroutine
161     * caller. To be used when merging in the first block of a subroutine.
162     *
163     * @param other {@code other non-null;} another LocalsArray. The final locals
164     * state of a subroutine caller.
165     * @param predLabel the label of the subroutine caller block.
166     * @return {@code non-null;} the merge result, a new instance or this
167     */
168    public abstract LocalsArraySet mergeWithSubroutineCaller
169            (LocalsArray other, int predLabel);
170
171    /**
172     * Gets the locals set appropriate for the current execution context.
173     * That is, if this is a {@code OneLocalsArray} instance, then return
174     * {@code this}, otherwise return {@code LocalsArraySet}'s
175     * primary.
176     *
177     * @return locals for this execution context.
178     */
179    protected abstract OneLocalsArray getPrimary();
180
181}
182