diff options
Diffstat (limited to 'dx/src/com/android/dx/ssa/BasicRegisterMapper.java')
-rw-r--r-- | dx/src/com/android/dx/ssa/BasicRegisterMapper.java | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/dx/src/com/android/dx/ssa/BasicRegisterMapper.java b/dx/src/com/android/dx/ssa/BasicRegisterMapper.java new file mode 100644 index 0000000..83045b2 --- /dev/null +++ b/dx/src/com/android/dx/ssa/BasicRegisterMapper.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.dx.ssa; + +import com.android.dx.rop.code.RegisterSpec; +import com.android.dx.rop.code.RegisterSpecList; +import com.android.dx.util.IntList; + +/** + * This class maps one register space into another, with + * each mapping built up individually and added via addMapping() + */ +public class BasicRegisterMapper extends RegisterMapper { + /** indexed by old register, containing new name */ + private IntList oldToNew; + + /** running count of used registers in new namespace */ + private int runningCountNewRegisters; + + /** + * Creates a new OneToOneRegisterMapper. + * + * @param countOldRegisters the number of registers in the old name space + */ + public BasicRegisterMapper(int countOldRegisters) { + oldToNew = new IntList(countOldRegisters); + } + + /** {@inheritDoc} */ + @Override + public int getNewRegisterCount() { + return runningCountNewRegisters; + } + + /** {@inheritDoc} */ + @Override + public RegisterSpec map(RegisterSpec registerSpec) { + if (registerSpec == null) { + return null; + } + + int newReg; + try { + newReg = oldToNew.get(registerSpec.getReg()); + } catch (IndexOutOfBoundsException ex) { + newReg = -1; + } + + if (newReg < 0) { + throw new RuntimeException("no mapping specified for register"); + } + + return registerSpec.withReg(newReg); + } + + /** + * Returns the new-namespace mapping for the specified + * old-namespace register, or -1 if one exists. + * + * @param oldReg {@code >= 0;} old-namespace register + * @return new-namespace register or -1 if none + */ + public int oldToNew(int oldReg) { + if (oldReg >= oldToNew.size()) { + return -1; + } + + return oldToNew.get(oldReg); + } + + /** {@inheritDoc} */ + public String toHuman() { + StringBuilder sb = new StringBuilder(); + + sb.append("Old\tNew\n"); + int sz = oldToNew.size(); + + for (int i = 0; i < sz; i++) { + sb.append(i); + sb.append('\t'); + sb.append(oldToNew.get(i)); + sb.append('\n'); + } + + sb.append("new reg count:"); + + sb.append(runningCountNewRegisters); + sb.append('\n'); + + return sb.toString(); + } + + /** + * Adds a mapping to the mapper. If oldReg has already been mapped, + * overwrites previous mapping with new mapping. + * + * @param oldReg {@code >= 0;} old register + * @param newReg {@code >= 0;} new register + * @param category {@code 1..2;} width of reg + */ + public void addMapping(int oldReg, int newReg, int category) { + if (oldReg >= oldToNew.size()) { + // expand the array as necessary + for (int i = oldReg - oldToNew.size(); i >= 0; i--) { + oldToNew.add(-1); + } + } + + oldToNew.set(oldReg, newReg); + + if (runningCountNewRegisters < (newReg + category)) { + runningCountNewRegisters = newReg + category; + } + } +} |