blob: 75af04752d656bf8ada1078df78ea3ac6ba02d93 [file] [log] [blame]
/*
* 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();
}