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 
17 package com.android.dx.cf.code;
18 
19 import com.android.dex.util.ExceptionWithContext;
20 import com.android.dx.rop.code.RegisterSpec;
21 import com.android.dx.rop.type.Type;
22 import com.android.dx.rop.type.TypeBearer;
23 import com.android.dx.util.MutabilityControl;
24 import 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  */
33 public 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      */
LocalsArray(boolean mutable)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      */
copy()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      */
annotate(ExceptionWithContext ex)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      */
makeInitialized(Type type)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      */
getMaxLocals()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      */
set(int idx, TypeBearer type)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      */
set(RegisterSpec spec)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      */
invalidate(int idx)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      */
getOrNull(int idx)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      */
get(int idx)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      */
getCategory1(int idx)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      */
getCategory2(int idx)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      */
merge(LocalsArray other)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      */
mergeWithSubroutineCaller(LocalsArray other, int predLabel)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      */
getPrimary()179     protected abstract OneLocalsArray getPrimary();
180 
181 }
182