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.dexgen.rop.code;
     18 
     19 import com.android.dexgen.rop.cst.Constant;
     20 import com.android.dexgen.rop.type.StdTypeList;
     21 import com.android.dexgen.rop.type.Type;
     22 import com.android.dexgen.rop.type.TypeBearer;
     23 import com.android.dexgen.rop.type.TypeList;
     24 
     25 /**
     26  * Plain instruction, which has no embedded data and which cannot possibly
     27  * throw an exception.
     28  */
     29 public final class PlainInsn
     30         extends Insn {
     31     /**
     32      * Constructs an instance.
     33      *
     34      * @param opcode {@code non-null;} the opcode
     35      * @param position {@code non-null;} source position
     36      * @param result {@code null-ok;} spec for the result, if any
     37      * @param sources {@code non-null;} specs for all the sources
     38      */
     39     public PlainInsn(Rop opcode, SourcePosition position,
     40                      RegisterSpec result, RegisterSpecList sources) {
     41         super(opcode, position, result, sources);
     42 
     43         switch (opcode.getBranchingness()) {
     44             case Rop.BRANCH_SWITCH:
     45             case Rop.BRANCH_THROW: {
     46                 throw new IllegalArgumentException("bogus branchingness");
     47             }
     48         }
     49 
     50         if (result != null && opcode.getBranchingness() != Rop.BRANCH_NONE) {
     51             // move-result-pseudo is required here
     52             throw new IllegalArgumentException
     53                     ("can't mix branchingness with result");
     54         }
     55     }
     56 
     57     /**
     58      * Constructs a single-source instance.
     59      *
     60      * @param opcode {@code non-null;} the opcode
     61      * @param position {@code non-null;} source position
     62      * @param result {@code null-ok;} spec for the result, if any
     63      * @param source {@code non-null;} spec for the source
     64      */
     65     public PlainInsn(Rop opcode, SourcePosition position, RegisterSpec result,
     66                      RegisterSpec source) {
     67         this(opcode, position, result, RegisterSpecList.make(source));
     68     }
     69 
     70     /** {@inheritDoc} */
     71     @Override
     72     public TypeList getCatches() {
     73         return StdTypeList.EMPTY;
     74     }
     75 
     76     /** {@inheritDoc} */
     77     @Override
     78     public void accept(Visitor visitor) {
     79         visitor.visitPlainInsn(this);
     80     }
     81 
     82     /** {@inheritDoc} */
     83     @Override
     84     public Insn withAddedCatch(Type type) {
     85         throw new UnsupportedOperationException("unsupported");
     86     }
     87 
     88     /** {@inheritDoc} */
     89     @Override
     90     public Insn withRegisterOffset(int delta) {
     91         return new PlainInsn(getOpcode(), getPosition(),
     92                              getResult().withOffset(delta),
     93                              getSources().withOffset(delta));
     94     }
     95 
     96     /** {@inheritDoc} */
     97     @Override
     98     public Insn withLastSourceLiteral() {
     99         RegisterSpecList sources = getSources();
    100         int szSources = sources.size();
    101 
    102         if (szSources == 0) {
    103             return this;
    104         }
    105 
    106         TypeBearer lastType = sources.get(szSources - 1).getTypeBearer();
    107 
    108         if (!lastType.isConstant()) {
    109             return this;
    110         }
    111 
    112         Constant cst = (Constant) lastType;
    113 
    114         RegisterSpecList newSources = sources.withoutLast();
    115 
    116         Rop newRop;
    117         try {
    118             newRop = Rops.ropFor(getOpcode().getOpcode(),
    119                     getResult(), newSources, (Constant)lastType);
    120         } catch (IllegalArgumentException ex) {
    121             // There's no rop for this case
    122             return this;
    123         }
    124 
    125         return new PlainCstInsn(newRop, getPosition(),
    126                 getResult(), newSources, cst);
    127     }
    128 
    129 
    130     /** {@inheritDoc} */
    131     @Override
    132     public Insn withNewRegisters(RegisterSpec result,
    133             RegisterSpecList sources) {
    134 
    135         return new PlainInsn(getOpcode(), getPosition(),
    136                              result,
    137                              sources);
    138 
    139     }
    140 }
    141