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.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 */ 26public class BasicRegisterMapper extends RegisterMapper { 27 /** indexed by old register, containing new name */ 28 private 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