1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/* 2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project 3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License"); 5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License. 6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at 7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * http://www.apache.org/licenses/LICENSE-2.0 9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software 11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS, 12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and 14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License. 15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.dex.code; 18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.ArrayList; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Destination for {@link DalvInsn} instances being output. This class 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * receives and collects instructions in two pieces — a primary 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * list and a suffix (generally consisting of adjunct data referred to 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * by the primary list, such as switch case tables) — which it 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * merges and emits back out in the form of a {@link DalvInsnList} 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance. 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class OutputCollector { 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code non-null;} the associated finisher (which holds the instruction 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * list in-progress) 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final OutputFinisher finisher; 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code null-ok;} suffix for the output, or {@code null} if the suffix 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * has been appended to the main output (by {@link #appendSuffixToOutput}) 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private ArrayList<DalvInsn> suffix; 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param initialCapacity {@code >= 0;} initial capacity of the output list 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param suffixInitialCapacity {@code >= 0;} initial capacity of the output 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * suffix 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param regCount {@code >= 0;} register count for the method 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public OutputCollector(int initialCapacity, int suffixInitialCapacity, 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int regCount) { 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.finisher = new OutputFinisher(initialCapacity, regCount); 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.suffix = new ArrayList<DalvInsn>(suffixInitialCapacity); 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Adds an instruction to the output. 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction to add 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void add(DalvInsn insn) { 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul finisher.add(insn); 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Reverses a branch which is buried a given number of instructions 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * backward in the output. It is illegal to call this unless the 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * indicated instruction really is a reversible branch. 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param which how many instructions back to find the branch; 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code 0} is the most recently added instruction, 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code 1} is the instruction before that, etc. 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param newTarget {@code non-null;} the new target for the reversed branch 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void reverseBranch(int which, CodeAddress newTarget) { 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul finisher.reverseBranch(which, newTarget); 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Adds an instruction to the output suffix. 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction to add 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void addSuffix(DalvInsn insn) { 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul suffix.add(insn); 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the results of all the calls on this instance, in the form of 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * an {@link OutputFinisher}. 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the output finisher 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws UnsupportedOperationException if this method has 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * already been called 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public OutputFinisher getFinisher() { 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (suffix == null) { 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new UnsupportedOperationException("already processed"); 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul appendSuffixToOutput(); 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return finisher; 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper for {@link #getFinisher}, which appends the suffix to 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the primary output. 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void appendSuffixToOutput() { 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int size = suffix.size(); 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < size; i++) { 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul finisher.add(suffix.get(i)); 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul suffix = null; 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 119