Home | History | Annotate | Download | only in code
      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.dex.code;
     18 
     19 import com.android.dx.rop.code.RegisterSpecList;
     20 import com.android.dx.rop.code.SourcePosition;
     21 
     22 /**
     23  * Instruction which has a single branch target.
     24  */
     25 public final class TargetInsn extends FixedSizeInsn {
     26     /** {@code non-null;} the branch target */
     27     private CodeAddress target;
     28 
     29     /**
     30      * Constructs an instance. The output address of this instance is initially
     31      * unknown ({@code -1}), and the target is initially
     32      * {@code null}.
     33      *
     34      * @param opcode the opcode; one of the constants from {@link Dops}
     35      * @param position {@code non-null;} source position
     36      * @param registers {@code non-null;} register list, including a
     37      * result register if appropriate (that is, registers may be either
     38      * ins or outs)
     39      * @param target {@code non-null;} the branch target
     40      */
     41     public TargetInsn(Dop opcode, SourcePosition position,
     42                       RegisterSpecList registers, CodeAddress target) {
     43         super(opcode, position, registers);
     44 
     45         if (target == null) {
     46             throw new NullPointerException("target == null");
     47         }
     48 
     49         this.target = target;
     50     }
     51 
     52     /** {@inheritDoc} */
     53     @Override
     54     public DalvInsn withOpcode(Dop opcode) {
     55         return new TargetInsn(opcode, getPosition(), getRegisters(), target);
     56     }
     57 
     58     /** {@inheritDoc} */
     59     @Override
     60     public DalvInsn withRegisters(RegisterSpecList registers) {
     61         return new TargetInsn(getOpcode(), getPosition(), registers, target);
     62     }
     63 
     64     /**
     65      * Returns an instance that is just like this one, except that its
     66      * opcode has the opposite sense (as a test; e.g. a
     67      * {@code lt} test becomes a {@code ge}), and its branch
     68      * target is replaced by the one given, and all set-once values
     69      * associated with the class (such as its address) are reset.
     70      *
     71      * @param target {@code non-null;} the new branch target
     72      * @return {@code non-null;} an appropriately-constructed instance
     73      */
     74     public TargetInsn withNewTargetAndReversed(CodeAddress target) {
     75         Dop opcode = getOpcode().getOppositeTest();
     76 
     77         return new TargetInsn(opcode, getPosition(), getRegisters(), target);
     78     }
     79 
     80     /**
     81      * Gets the unique branch target of this instruction.
     82      *
     83      * @return {@code non-null;} the branch target
     84      */
     85     public CodeAddress getTarget() {
     86         return target;
     87     }
     88 
     89     /**
     90      * Gets the target address of this instruction. This is only valid
     91      * to call if the target instruction has been assigned an address,
     92      * and it is merely a convenient shorthand for
     93      * {@code getTarget().getAddress()}.
     94      *
     95      * @return {@code >= 0;} the target address
     96      */
     97     public int getTargetAddress() {
     98         return target.getAddress();
     99     }
    100 
    101     /**
    102      * Gets the branch offset of this instruction. This is only valid to
    103      * call if both this and the target instruction each has been assigned
    104      * an address, and it is merely a convenient shorthand for
    105      * {@code getTargetAddress() - getAddress()}.
    106      *
    107      * @return the branch offset
    108      */
    109     public int getTargetOffset() {
    110         return target.getAddress() - getAddress();
    111     }
    112 
    113     /**
    114      * Returns whether the target offset is known.
    115      *
    116      * @return {@code true} if the target offset is known or
    117      * {@code false} if not
    118      */
    119     public boolean hasTargetOffset() {
    120         return hasAddress() && target.hasAddress();
    121     }
    122 
    123     /** {@inheritDoc} */
    124     @Override
    125     protected String argString() {
    126         if (target == null) {
    127             return "????";
    128         }
    129 
    130         return target.identifierString();
    131     }
    132 }
    133