/*
* Copyright (C) 2011 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.google.dexmaker;
import com.android.dx.rop.code.BasicBlockList;
import com.android.dx.rop.code.Insn;
import com.android.dx.rop.code.PlainCstInsn;
import com.android.dx.rop.code.PlainInsn;
import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.rop.code.Rop;
import static com.android.dx.rop.code.Rop.BRANCH_GOTO;
import static com.android.dx.rop.code.Rop.BRANCH_NONE;
import static com.android.dx.rop.code.Rop.BRANCH_RETURN;
import com.android.dx.rop.code.Rops;
import com.android.dx.rop.code.SourcePosition;
import com.android.dx.rop.code.ThrowingCstInsn;
import com.android.dx.rop.code.ThrowingInsn;
import com.android.dx.rop.cst.CstInteger;
import com.android.dx.rop.type.StdTypeList;
import static com.android.dx.rop.type.Type.BT_BYTE;
import static com.android.dx.rop.type.Type.BT_CHAR;
import static com.android.dx.rop.type.Type.BT_INT;
import static com.android.dx.rop.type.Type.BT_SHORT;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* Builds a sequence of instructions.
*
*
Locals
* All data manipulation takes place in local variables. Each parameter gets its
* own local by default; access these using {@link #getParameter
* getParameter()}. Non-static methods and constructors also have a {@code this}
* parameter; it's available as {@link #getThis getThis()}. Allocate a new local
* variable using {@link #newLocal newLocal()}, and assign a default value to it
* with {@link #loadConstant loadConstant()}. Copy a value from one local to
* another with {@link #move move()}.
*
*
Every local variable has a fixed type. This is either a primitive type (of
* any size) or a reference type. This class emits instructions appropriate to
* the types they operate on. Not all operations are local on all types;
* attempting to emit such an operation will fail with an unchecked exception.
*
*
Math and Bit Operations
* Transform a single value into another related value using {@link
* #op(UnaryOp,Local,Local) op(UnaryOp, Local, Local)}. Transform two values
* into a third value using {@link #op(BinaryOp,Local,Local,Local) op(BinaryOp,
* Local, Local, Local)}. In either overload the first {@code Local} parameter
* is where the result will be sent; the other {@code Local} parameters are the
* inputs.
*
*
Comparisons
* There are three different comparison operations each with different
* constraints:
*
*
{@link #compareLongs compareLongs()} compares two locals each
* containing a {@code long} primitive. This is the only operation that
* can compare longs. The result of the comparison is written to another
* {@code int} local.
*
{@link #compareFloatingPoint compareFloatingPoint()} compares two
* locals; both {@code float} primitives or both {@code double}
* primitives. This is the only operation that can compare floating
* point values. This comparison takes an extra parameter that sets
* the desired result if either parameter is {@code NaN}. The result of
* the comparison is wrtten to another {@code int} local.
*
{@link #compare compare()} compares two locals. The {@link
* Comparison#EQ} and {@link Comparison#NE} options compare either
* {@code int} primitives or references. The other options compare only
* {@code int} primitives. This comparison takes a {@link Label} that
* will be jumped to if the comparison is true. If the comparison is
* false the next instruction in sequence will be executed.
*
* There's no single operation to compare longs and jump, or to compare ints and
* store the result in a local. Accomplish these goals by chaining multiple
* operations together.
*
*
Branches, Labels and Returns
* Basic control flow is expressed using jumps and labels. Each label must be
* marked exactly once and may be jumped to any number of times. Create a label
* using its constructor: {@code new Label()}, and mark it using {@link #mark
* mark(Label)}. All jumps to a label will execute instructions starting from
* that label. You can jump to a label that hasn't yet been marked (jumping
* forward) or to a label that has already been marked (jumping backward). Jump
* unconditionally with {@link #jump jump(Label)} or conditionally based on a
* comparison using {@link #compare compare()}.
*
*
Most methods should contain either a return instruction. Void methods
* should use {@link #returnVoid()}; non-void methods should use {@link
* #returnValue returnValue()} with a local whose return type matches the
* method's return type. Constructors are considered void methods and should
* call {@link #returnVoid()}. Methods may make multiple returns. Methods
* containing no return statements must either loop infinitely or throw
* unconditionally; it is not legal to end a sequence of instructions without a
* jump, return or throw.
*
*
Throwing and Catching
* This API uses labels to handle thrown exceptions, errors and throwables. Call
* {@link #addCatchClause addCatchClause()} to register the target label and
* throwable class. All statements that follow will jump to that catch clause if
* they throw a {@link Throwable} assignable to that type. Use {@link
* #removeCatchClause removeCatchClause()} to unregister the throwable class.
*
*
Throw an throwable by first assigning it to a local and then calling
* {@link #throwValue throwValue()}. Control flow will jump to the nearest label
* assigned to a type assignable to the thrown type. In this context, "nearest"
* means the label requiring the fewest stack frames to be popped.
*
*
Calling methods
* A method's caller must know its return type, name, parameters, and invoke
* kind. Lookup a method on a type using {@link TypeId#getMethod
* TypeId.getMethod()}. This is more onerous than Java language invokes, which
* can infer the target method using the target object and parameters. There are
* four invoke kinds:
*
*
{@link #invokeStatic invokeStatic()} is used for static methods.
*
{@link #invokeDirect invokeDirect()} is used for private instance
* methods and for constructors to call their superclass's
* constructor.
*
{@link #invokeInterface invokeInterface()} is used to invoke a method
* whose declaring type is an interface.
*
{@link #invokeVirtual invokeVirtual()} is used to invoke any other
* method. The target must not be static, private, a constructor, or an
* interface method.
*
{@link #invokeSuper invokeSuper()} is used to invoke the closest
* superclass's virtual method. The target must not be static, private,
* a constructor method, or an interface method.
*
{@link #newInstance newInstance()} is used to invoke a
* constructor.
*
* All invoke methods take a local for the return value. For void methods this
* local is unused and may be null.
*
*
Field Access
* Read static fields using {@link #sget sget()}; write them using {@link
* #sput sput()}. For instance values you'll need to specify the declaring
* instance; use {@link #getThis getThis()} in an instance method to use {@code
* this}. Read instance values using {@link #iget iget()} and write them with
* {@link #iput iput()}.
*
*
Array Access
* Allocate an array using {@link #newArray newArray()}. Read an array's length
* with {@link #arrayLength arrayLength()} and its elements with {@link #aget
* aget()}. Write an array's elements with {@link #aput aput()}.
*
*
Types
* Use {@link #cast cast()} to perform either a numeric cast or
* a type cast. Interrogate the type of a value in a local
* using {@link #instanceOfType instanceOfType()}.
*
*
Synchronization
* Acquire a monitor using {@link #monitorEnter monitorEnter()}; release it with
* {@link #monitorExit monitorExit()}. It is the caller's responsibility to
* guarantee that enter and exit calls are balanced, even in the presence of
* exceptions thrown.
*
* Warning: Even if a method has the {@code synchronized} flag,
* dex requires instructions to acquire and release monitors manually. A method
* declared with {@link java.lang.reflect.Modifier#SYNCHRONIZED SYNCHRONIZED}
* but without manual calls to {@code monitorEnter()} and {@code monitorExit()}
* will not be synchronized when executed.
*/
public final class Code {
private final MethodId, ?> method;
/**
* All allocated labels. Although the order of the labels in this list
* shouldn't impact behavior, it is used to determine basic block indices.
*/
private final List