Home | History | Annotate | Download | only in ssa
      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.ssa;
     18 
     19 import com.android.dx.rop.code.RegisterSpec;
     20 import com.android.dx.util.IntList;
     21 
     22 /**
     23  * This class maps one register space into another, with
     24  * each mapping built up individually and added via addMapping()
     25  */
     26 public class BasicRegisterMapper extends RegisterMapper {
     27     /** indexed by old register, containing new name */
     28     private final IntList oldToNew;
     29 
     30     /** running count of used registers in new namespace */
     31     private int runningCountNewRegisters;
     32 
     33     /**
     34      * Creates a new OneToOneRegisterMapper.
     35      *
     36      * @param countOldRegisters the number of registers in the old name space
     37      */
     38     public BasicRegisterMapper(int countOldRegisters) {
     39         oldToNew = new IntList(countOldRegisters);
     40     }
     41 
     42     /** {@inheritDoc} */
     43     @Override
     44     public int getNewRegisterCount() {
     45         return runningCountNewRegisters;
     46     }
     47 
     48     /** {@inheritDoc} */
     49     @Override
     50     public RegisterSpec map(RegisterSpec registerSpec) {
     51         if (registerSpec == null) {
     52             return null;
     53         }
     54 
     55         int newReg;
     56         try {
     57             newReg = oldToNew.get(registerSpec.getReg());
     58         } catch (IndexOutOfBoundsException ex) {
     59             newReg = -1;
     60         }
     61 
     62         if (newReg < 0) {
     63             throw new RuntimeException("no mapping specified for register");
     64         }
     65 
     66         return registerSpec.withReg(newReg);
     67     }
     68 
     69     /**
     70      * Returns the new-namespace mapping for the specified
     71      * old-namespace register, or -1 if one exists.
     72      *
     73      * @param oldReg {@code >= 0;} old-namespace register
     74      * @return new-namespace register or -1 if none
     75      */
     76     public int oldToNew(int oldReg) {
     77         if (oldReg >= oldToNew.size()) {
     78             return -1;
     79         }
     80 
     81         return oldToNew.get(oldReg);
     82     }
     83 
     84     /** {@inheritDoc} */
     85     public String toHuman() {
     86         StringBuilder sb = new StringBuilder();
     87 
     88         sb.append("Old\tNew\n");
     89         int sz = oldToNew.size();
     90 
     91         for (int i = 0; i < sz; i++) {
     92             sb.append(i);
     93             sb.append('\t');
     94             sb.append(oldToNew.get(i));
     95             sb.append('\n');
     96         }
     97 
     98         sb.append("new reg count:");
     99 
    100         sb.append(runningCountNewRegisters);
    101         sb.append('\n');
    102 
    103         return sb.toString();
    104     }
    105 
    106     /**
    107      * Adds a mapping to the mapper. If oldReg has already been mapped,
    108      * overwrites previous mapping with new mapping.
    109      *
    110      * @param oldReg {@code >= 0;} old register
    111      * @param newReg {@code >= 0;} new register
    112      * @param category {@code 1..2;} width of reg
    113      */
    114     public void addMapping(int oldReg, int newReg, int category) {
    115         if (oldReg >= oldToNew.size()) {
    116             // expand the array as necessary
    117             for (int i = oldReg - oldToNew.size(); i >= 0; i--) {
    118                 oldToNew.add(-1);
    119             }
    120         }
    121 
    122         oldToNew.set(oldReg, newReg);
    123 
    124         if (runningCountNewRegisters < (newReg + category)) {
    125             runningCountNewRegisters = newReg + category;
    126         }
    127     }
    128 }
    129