1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.dex.code;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
193dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornsteinimport com.android.dx.dex.DexOptions;
203dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Destination for {@link DalvInsn} instances being output. This class
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * receives and collects instructions in two pieces — a primary
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * list and a suffix (generally consisting of adjunct data referred to
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by the primary list, such as switch case tables) — which it
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * merges and emits back out in the form of a {@link DalvInsnList}
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * instance.
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class OutputCollector {
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
3399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code non-null;} the associated finisher (which holds the instruction
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * list in-progress)
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final OutputFinisher finisher;
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
3999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code null-ok;} suffix for the output, or {@code null} if the suffix
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * has been appended to the main output (by {@link #appendSuffixToOutput})
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private ArrayList<DalvInsn> suffix;
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance.
46de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
473dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein     * @param dexOptions {@code non-null;} options for dex output
4899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param initialCapacity {@code >= 0;} initial capacity of the output list
4999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param suffixInitialCapacity {@code >= 0;} initial capacity of the output
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * suffix
5199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param regCount {@code >= 0;} register count for the method
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
533dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein    public OutputCollector(DexOptions dexOptions, int initialCapacity, int suffixInitialCapacity,
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int regCount) {
553dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein        this.finisher = new OutputFinisher(dexOptions, initialCapacity, regCount);
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.suffix = new ArrayList<DalvInsn>(suffixInitialCapacity);
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Adds an instruction to the output.
61de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
62de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * @param insn {@code non-null;} the instruction to add
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void add(DalvInsn insn) {
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        finisher.add(insn);
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Reverses a branch which is buried a given number of instructions
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * backward in the output. It is illegal to call this unless the
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * indicated instruction really is a reversible branch.
72de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param which how many instructions back to find the branch;
7499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code 0} is the most recently added instruction,
7599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code 1} is the instruction before that, etc.
7699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param newTarget {@code non-null;} the new target for the reversed branch
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void reverseBranch(int which, CodeAddress newTarget) {
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        finisher.reverseBranch(which, newTarget);
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Adds an instruction to the output suffix.
84de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
85de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * @param insn {@code non-null;} the instruction to add
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void addSuffix(DalvInsn insn) {
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        suffix.add(insn);
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the results of all the calls on this instance, in the form of
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * an {@link OutputFinisher}.
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
9599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the output finisher
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws UnsupportedOperationException if this method has
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * already been called
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public OutputFinisher getFinisher() {
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (suffix == null) {
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new UnsupportedOperationException("already processed");
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
103de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        appendSuffixToOutput();
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return finisher;
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper for {@link #getFinisher}, which appends the suffix to
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the primary output.
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void appendSuffixToOutput() {
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int size = suffix.size();
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < size; i++) {
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            finisher.add(suffix.get(i));
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        suffix = null;
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
122