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