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.file;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dex.util.ExceptionWithContext;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.dex.code.LocalList;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.dex.code.PositionList;
22fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport static com.android.dx.dex.file.DebugInfoConstants.DBG_ADVANCE_LINE;
23fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport static com.android.dx.dex.file.DebugInfoConstants.DBG_ADVANCE_PC;
24fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport static com.android.dx.dex.file.DebugInfoConstants.DBG_END_LOCAL;
25fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport static com.android.dx.dex.file.DebugInfoConstants.DBG_END_SEQUENCE;
26fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport static com.android.dx.dex.file.DebugInfoConstants.DBG_FIRST_SPECIAL;
27fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport static com.android.dx.dex.file.DebugInfoConstants.DBG_LINE_BASE;
28fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport static com.android.dx.dex.file.DebugInfoConstants.DBG_LINE_RANGE;
29fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport static com.android.dx.dex.file.DebugInfoConstants.DBG_RESTART_LOCAL;
30fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport static com.android.dx.dex.file.DebugInfoConstants.DBG_SET_PROLOGUE_END;
31fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport static com.android.dx.dex.file.DebugInfoConstants.DBG_START_LOCAL;
32fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport static com.android.dx.dex.file.DebugInfoConstants.DBG_START_LOCAL_EXTENDED;
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.RegisterSpec;
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.SourcePosition;
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstMethodRef;
36333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport com.android.dx.rop.cst.CstString;
37fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dx.rop.cst.CstType;
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Prototype;
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.StdTypeList;
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type;
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.AnnotatedOutput;
42fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dx.util.ByteArrayAnnotatedOutput;
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException;
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.PrintWriter;
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList;
46fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport java.util.BitSet;
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Collections;
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Comparator;
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * An encoder for the dex debug info state machine format. The format
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for each method enrty is as follows:
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <ol>
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li> signed LEB128: initial value for line register.
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li> n instances of signed LEB128: string indicies (offset by 1)
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for each method argument in left-to-right order
5799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * with {@code this} excluded. A value of '0' indicates "no name"
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li> A sequence of special or normal opcodes as defined in
5999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code DebugInfoConstants}.
6099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * <li> A single terminating {@code OP_END_SEQUENCE}
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </ol>
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class DebugInfoEncoder {
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final boolean DEBUG = false;
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code null-ok;} positions (line numbers) to encode */
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final PositionList positions;
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code null-ok;} local variables to encode */
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final LocalList locals;
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final ByteArrayAnnotatedOutput output;
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final DexFile file;
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int codeSize;
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int regSize;
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final Prototype desc;
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final boolean isStatic;
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** current encoding state: bytecode address */
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int address = 0;
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** current encoding state: line number */
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int line = 1;
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * if non-null: the output to write annotations to. No normal
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * output is written to this.
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private AnnotatedOutput annotateTo;
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** if non-null: another possible output for annotations */
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private PrintWriter debugPrint;
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** if non-null: the prefix for each annotation or debugPrint line */
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private String prefix;
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** true if output should be consumed during annotation */
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private boolean shouldConsume;
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** indexed by register; last local alive in register */
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final LocalList.Entry[] lastEntryForReg;
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Creates an instance.
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
107f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein     * @param positions {@code null-ok;} positions (line numbers) to encode
108f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein     * @param locals {@code null-ok;} local variables to encode
10999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param file {@code null-ok;} may only be {@code null} if simply using
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this class to do a debug print
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param codeSize
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param regSize
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param isStatic
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param ref
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
116f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein    public DebugInfoEncoder(PositionList positions, LocalList locals,
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DexFile file, int codeSize, int regSize,
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            boolean isStatic, CstMethodRef ref) {
119f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein        this.positions = positions;
120f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein        this.locals = locals;
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.file = file;
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.desc = ref.getPrototype();
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.isStatic = isStatic;
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.codeSize = codeSize;
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.regSize = regSize;
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
127f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein        output = new ByteArrayAnnotatedOutput();
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        lastEntryForReg = new LocalList.Entry[regSize];
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
13299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Annotates or writes a message to the {@code debugPrint} writer
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * if applicable.
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param length the number of bytes associated with this message
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param message the message itself
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void annotate(int length, String message) {
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (prefix != null) {
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            message = prefix + message;
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotateTo != null) {
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            annotateTo.annotate(shouldConsume ? length : 0, message);
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (debugPrint != null) {
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            debugPrint.println(message);
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Converts this (PositionList, LocalList) pair into a state machine
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * sequence.
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
15699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} encoded byte sequence without padding and
15799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * terminated with a {@code 0x00} byte
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public byte[] convert() {
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            byte[] ret;
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ret = convert0();
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (DEBUG) {
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                for (int i = 0 ; i < ret.length; i++) {
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    System.err.printf("byte %02x\n", (0xff & ret[i]));
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return ret;
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (IOException ex) {
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw ExceptionWithContext
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    .withContext(ex, "...while encoding debug info");
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Converts and produces annotations on a stream. Does not write
17999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * actual bits to the {@code AnnotatedOutput}.
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
18199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param prefix {@code null-ok;} prefix to attach to each line of output
18299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param debugPrint {@code null-ok;} if specified, an alternate output for
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * annotations
18499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param out {@code null-ok;} if specified, where annotations should go
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param consume whether to claim to have consumed output for
18699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code out}
18799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} encoded output
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public byte[] convertAndAnnotate(String prefix, PrintWriter debugPrint,
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            AnnotatedOutput out, boolean consume) {
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.prefix = prefix;
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.debugPrint = debugPrint;
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        annotateTo = out;
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        shouldConsume = consume;
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[] result = convert();
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
200f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private byte[] convert0() throws IOException {
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ArrayList<PositionList.Entry> sortedPositions = buildSortedPositions();
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ArrayList<LocalList.Entry> methodArgs = extractMethodArguments();
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        emitHeader(sortedPositions, methodArgs);
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // TODO: Make this mark be the actual prologue end.
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        output.writeByte(DBG_SET_PROLOGUE_END);
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotateTo != null || debugPrint != null) {
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            annotate(1, String.format("%04x: prologue end",address));
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
214f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein        int positionsSz = sortedPositions.size();
215f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein        int localsSz = locals.size();
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Current index in sortedPositions
218f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein        int curPositionIdx = 0;
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Current index in locals
220f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein        int curLocalIdx = 0;
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (;;) {
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Emit any information for the current address.
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
227f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            curLocalIdx = emitLocalsAtAddress(curLocalIdx);
228f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            curPositionIdx =
229f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                emitPositionsAtAddress(curPositionIdx, sortedPositions);
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Figure out what the next important address is.
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int nextAddrL = Integer.MAX_VALUE; // local variable
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int nextAddrP = Integer.MAX_VALUE; // position (line number)
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
238f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            if (curLocalIdx < localsSz) {
239f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                nextAddrL = locals.get(curLocalIdx).getAddress();
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
242f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            if (curPositionIdx < positionsSz) {
243f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                nextAddrP = sortedPositions.get(curPositionIdx).getAddress();
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int next = Math.min(nextAddrP, nextAddrL);
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // No next important address == done.
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (next == Integer.MAX_VALUE) {
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * If the only work remaining are local ends at the end of the
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * block, stop here. Those are implied anyway.
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (next == codeSize
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    && nextAddrL == Integer.MAX_VALUE
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    && nextAddrP == Integer.MAX_VALUE) {
260f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                break;
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (next == nextAddrP) {
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // Combined advance PC + position entry
265f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                emitPosition(sortedPositions.get(curPositionIdx++));
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                emitAdvancePc(next - address);
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        emitEndSequence();
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return output.toByteArray();
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Emits all local variable activity that occurs at the current
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@link #address} starting at the given index into {@code
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * locals} and including all subsequent activity at the same
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * address.
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
282f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein     * @param curLocalIdx Current index in locals
283f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein     * @return new value for {@code curLocalIdx}
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
286f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein    private int emitLocalsAtAddress(int curLocalIdx)
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws IOException {
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int sz = locals.size();
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // TODO: Don't emit ends implied by starts.
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
292f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein        while ((curLocalIdx < sz)
293f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                && (locals.get(curLocalIdx).getAddress() == address)) {
294f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            LocalList.Entry entry = locals.get(curLocalIdx++);
295f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            int reg = entry.getRegister();
296f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            LocalList.Entry prevEntry = lastEntryForReg[reg];
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
298f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            if (entry == prevEntry) {
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * Here we ignore locals entries for parameters,
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * which have already been represented and placed in the
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * lastEntryForReg array.
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                continue;
305f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            }
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // At this point we have a new entry one way or another.
308f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            lastEntryForReg[reg] = entry;
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
310f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            if (entry.isStart()) {
311f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                if ((prevEntry != null) && entry.matches(prevEntry)) {
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /*
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * The previous local in this register has the same
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * name and type as the one being introduced now, so
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * use the more efficient "restart" form.
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
317f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                    if (prevEntry.isStart()) {
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        /*
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * We should never be handed a start when a
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * a matching local is already active.
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         */
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        throw new RuntimeException("shouldn't happen");
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
324f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                    emitLocalRestart(entry);
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
326f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                    emitLocalStart(entry);
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * Only emit a local end if it is *not* due to a direct
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * replacement. Direct replacements imply an end of the
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * previous local in the same register.
333f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                 *
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * TODO: Make sure the runtime can deal with implied
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * local ends from category-2 interactions, and when so,
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * also stop emitting local ends for those cases.
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
338f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                if (entry.getDisposition()
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        != LocalList.Disposition.END_REPLACED) {
340f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                    emitLocalEnd(entry);
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
345f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein        return curLocalIdx;
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
34999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Emits all positions that occur at the current {@code address}
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
351f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein     * @param curPositionIdx Current index in sortedPositions
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param sortedPositions positions, sorted by ascending address
353f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein     * @return new value for {@code curPositionIdx}
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
356f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein    private int emitPositionsAtAddress(int curPositionIdx,
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ArrayList<PositionList.Entry> sortedPositions)
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws IOException {
359f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein        int positionsSz = sortedPositions.size();
360f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein        while ((curPositionIdx < positionsSz)
361f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                && (sortedPositions.get(curPositionIdx).getAddress()
362f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                        == address)) {
363f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            emitPosition(sortedPositions.get(curPositionIdx++));
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
365f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein        return curPositionIdx;
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Emits the header sequence, which consists of LEB128-encoded initial
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * line number and string indicies for names of all non-"this" arguments.
371f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein     *
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param sortedPositions positions, sorted by ascending address
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param methodArgs local list entries for method argumens arguments,
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in left-to-right order omitting "this"
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void emitHeader(ArrayList<PositionList.Entry> sortedPositions,
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ArrayList<LocalList.Entry> methodArgs) throws IOException {
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean annotate = (annotateTo != null) || (debugPrint != null);
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int mark = output.getCursor();
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Start by initializing the line number register.
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (sortedPositions.size() > 0) {
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            PositionList.Entry entry = sortedPositions.get(0);
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            line = entry.getPosition().getLine();
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
387dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson        output.writeUleb128(line);
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotate) {
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            annotate(output.getCursor() - mark, "line_start: " + line);
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int curParam = getParamBase();
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // paramTypes will not include 'this'
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StdTypeList paramTypes = desc.getParameterTypes();
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int szParamTypes = paramTypes.size();
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Initialize lastEntryForReg to have an initial
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * entry for the 'this' pointer.
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!isStatic) {
40341aecd0a6bfea1e9a6713014b2b3d56fec8c552cDan Bornstein            for (LocalList.Entry arg : methodArgs) {
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (curParam == arg.getRegister()) {
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    lastEntryForReg[curParam] = arg;
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            curParam++;
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Write out the number of parameter entries that will follow.
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mark = output.getCursor();
414dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson        output.writeUleb128(szParamTypes);
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotate) {
417f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            annotate(output.getCursor() - mark,
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    String.format("parameters_size: %04x", szParamTypes));
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Then emit the string indicies of all the method parameters.
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Note that 'this', if applicable, is excluded.
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < szParamTypes; i++) {
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Type pt = paramTypes.get(i);
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LocalList.Entry found = null;
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mark = output.getCursor();
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
43141aecd0a6bfea1e9a6713014b2b3d56fec8c552cDan Bornstein            for (LocalList.Entry arg : methodArgs) {
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (curParam == arg.getRegister()) {
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    found = arg;
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (arg.getSignature() != null) {
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        /*
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * Parameters with signatures will be re-emitted
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * in complete as LOCAL_START_EXTENDED's below.
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         */
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        emitStringIndex(null);
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else {
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        emitStringIndex(arg.getName());
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    lastEntryForReg[curParam] = arg;
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (found == null) {
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * Emit a null symbol for "unnamed." This is common
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * for, e.g., synthesized methods and inner-class
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * this$0 arguments.
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                emitStringIndex(null);
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (annotate) {
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                String parameterName
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        = (found == null || found.getSignature() != null)
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                ? "<unnamed>" : found.getName().toHuman();
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                annotate(output.getCursor() - mark,
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        "parameter " + parameterName + " "
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                + RegisterSpec.PREFIX + curParam);
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            curParam += pt.getCategory();
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If anything emitted above has a type signature, emit it again as
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * a LOCAL_RESTART_EXTENDED
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (LocalList.Entry arg : lastEntryForReg) {
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (arg == null) {
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                continue;
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
481333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson            CstString signature = arg.getSignature();
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (signature != null) {
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                emitLocalStartExtended(arg);
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Builds a list of position entries, sorted by ascending address.
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return A sorted positions list
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private ArrayList<PositionList.Entry> buildSortedPositions() {
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int sz = (positions == null) ? 0 : positions.size();
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ArrayList<PositionList.Entry> result = new ArrayList(sz);
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < sz; i++) {
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.add(positions.get(i));
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Sort ascending by address.
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Collections.sort (result, new Comparator<PositionList.Entry>() {
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            public int compare (PositionList.Entry a, PositionList.Entry b) {
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return a.getAddress() - b.getAddress();
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            public boolean equals (Object obj) {
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               return obj == this;
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        });
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the register that begins the method's parameter range (including
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the 'this' parameter for non-static methods). The range continues until
51899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code regSize}
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return register as noted above
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int getParamBase() {
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return regSize
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                - desc.getParameterTypes().getWordCount() - (isStatic? 0 : 1);
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Extracts method arguments from a locals list. These will be collected
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * from the input list and sorted by ascending register in the
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * returned list.
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
53299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return list of non-{@code this} method argument locals,
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * sorted by ascending register
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private ArrayList<LocalList.Entry> extractMethodArguments() {
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ArrayList<LocalList.Entry> result
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                = new ArrayList(desc.getParameterTypes().size());
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int argBase = getParamBase();
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        BitSet seen = new BitSet(regSize - argBase);
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int sz = locals.size();
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < sz; i++) {
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LocalList.Entry e = locals.get(i);
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int reg = e.getRegister();
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (reg < argBase) {
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                continue;
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // only the lowest-start-address entry is included.
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (seen.get(reg - argBase)) {
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                continue;
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            seen.set(reg - argBase);
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.add(e);
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Sort by ascending register.
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Collections.sort(result, new Comparator<LocalList.Entry>() {
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            public int compare(LocalList.Entry a, LocalList.Entry b) {
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return a.getRegister() - b.getRegister();
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            public boolean equals(Object obj) {
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               return obj == this;
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        });
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns a string representation of this LocalList entry that is
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * appropriate for emitting as an annotation.
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
57799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param e {@code non-null;} entry
57899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} annotation string
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private String entryAnnotationString(LocalList.Entry e) {
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringBuilder sb = new StringBuilder();
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(RegisterSpec.PREFIX);
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(e.getRegister());
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(' ');
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
587333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson        CstString name = e.getName();
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (name == null) {
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append("null");
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(name.toHuman());
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(' ');
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        CstType type = e.getType();
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (type == null) {
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append("null");
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(type.toHuman());
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
602333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson        CstString signature = e.getSignature();
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (signature != null) {
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(' ');
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(signature.toHuman());
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sb.toString();
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Emits a {@link DebugInfoConstants#DBG_RESTART_LOCAL DBG_RESTART_LOCAL}
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * sequence.
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param entry entry associated with this restart
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void emitLocalRestart(LocalList.Entry entry)
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws IOException {
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int mark = output.getCursor();
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        output.writeByte(DBG_RESTART_LOCAL);
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        emitUnsignedLeb128(entry.getRegister());
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotateTo != null || debugPrint != null) {
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            annotate(output.getCursor() - mark,
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    String.format("%04x: +local restart %s",
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            address, entryAnnotationString(entry)));
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (DEBUG) {
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.err.println("emit local restart");
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Emits a string index as an unsigned LEB128. The actual value written
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is shifted by 1, so that the '0' value is reserved for "null". The
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * null symbol is used in some cases by the parameter name list
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * at the beginning of the sequence.
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
64499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param string {@code null-ok;} string to emit
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
647333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson    private void emitStringIndex(CstString string) throws IOException {
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((string == null) || (file == null)) {
649dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson            output.writeUleb128(0);
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
651dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson            output.writeUleb128(
652dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson                    1 + file.getStringIds().indexOf(string));
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (DEBUG) {
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.err.printf("Emit string %s\n",
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    string == null ? "<null>" : string.toQuoted());
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Emits a type index as an unsigned LEB128. The actual value written
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is shifted by 1, so that the '0' value is reserved for "null".
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
66599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param type {@code null-ok;} type to emit
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void emitTypeIndex(CstType type) throws IOException {
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((type == null) || (file == null)) {
670dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson            output.writeUleb128(0);
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
672dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson            output.writeUleb128(
673dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson                    1 + file.getTypeIds().indexOf(type));
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (DEBUG) {
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.err.printf("Emit type %s\n",
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    type == null ? "<null>" : type.toHuman());
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Emits a {@link DebugInfoConstants#DBG_START_LOCAL DBG_START_LOCAL} or
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@link DebugInfoConstants#DBG_START_LOCAL_EXTENDED
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * DBG_START_LOCAL_EXTENDED} sequence.
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param entry entry to emit
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void emitLocalStart(LocalList.Entry entry)
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throws IOException {
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (entry.getSignature() != null) {
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            emitLocalStartExtended(entry);
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int mark = output.getCursor();
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        output.writeByte(DBG_START_LOCAL);
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        emitUnsignedLeb128(entry.getRegister());
703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        emitStringIndex(entry.getName());
704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        emitTypeIndex(entry.getType());
705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotateTo != null || debugPrint != null) {
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            annotate(output.getCursor() - mark,
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    String.format("%04x: +local %s", address,
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            entryAnnotationString(entry)));
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (DEBUG) {
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.err.println("emit local start");
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Emits a {@link DebugInfoConstants#DBG_START_LOCAL_EXTENDED
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * DBG_START_LOCAL_EXTENDED} sequence.
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param entry entry to emit
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void emitLocalStartExtended(LocalList.Entry entry)
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throws IOException {
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int mark = output.getCursor();
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        output.writeByte(DBG_START_LOCAL_EXTENDED);
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        emitUnsignedLeb128(entry.getRegister());
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        emitStringIndex(entry.getName());
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        emitTypeIndex(entry.getType());
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        emitStringIndex(entry.getSignature());
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotateTo != null || debugPrint != null) {
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            annotate(output.getCursor() - mark,
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    String.format("%04x: +localx %s", address,
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            entryAnnotationString(entry)));
740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (DEBUG) {
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.err.println("emit local start");
744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Emits a {@link DebugInfoConstants#DBG_END_LOCAL DBG_END_LOCAL} sequence.
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
75099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param entry {@code entry non-null;} entry associated with end.
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void emitLocalEnd(LocalList.Entry entry)
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws IOException {
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int mark = output.getCursor();
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        output.writeByte(DBG_END_LOCAL);
759dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson        output.writeUleb128(entry.getRegister());
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotateTo != null || debugPrint != null) {
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            annotate(output.getCursor() - mark,
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    String.format("%04x: -local %s", address,
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            entryAnnotationString(entry)));
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (DEBUG) {
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.err.println("emit local end");
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Emits the necessary byte sequences to emit the given position table
774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * entry. This will typically be a single special opcode, although
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * it may also require DBG_ADVANCE_PC or DBG_ADVANCE_LINE.
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param entry position entry to emit.
778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void emitPosition(PositionList.Entry entry)
781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws IOException {
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        SourcePosition pos = entry.getPosition();
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int newLine = pos.getLine();
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int newAddress = entry.getAddress();
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int opcode;
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int deltaLines = newLine - line;
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int deltaAddress = newAddress - address;
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (deltaAddress < 0) {
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new RuntimeException(
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "Position entries must be in ascending address order");
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((deltaLines < DBG_LINE_BASE)
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                || (deltaLines > (DBG_LINE_BASE + DBG_LINE_RANGE -1))) {
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            emitAdvanceLine(deltaLines);
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            deltaLines = 0;
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        opcode = computeOpcode (deltaLines, deltaAddress);
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((opcode & ~0xff) > 0) {
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            emitAdvancePc(deltaAddress);
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            deltaAddress = 0;
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            opcode = computeOpcode (deltaLines, deltaAddress);
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((opcode & ~0xff) > 0) {
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                emitAdvanceLine(deltaLines);
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                deltaLines = 0;
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                opcode = computeOpcode (deltaLines, deltaAddress);
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        output.writeByte(opcode);
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        line += deltaLines;
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        address += deltaAddress;
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotateTo != null || debugPrint != null) {
823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            annotate(1,
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    String.format("%04x: line %d", address, line));
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Computes a special opcode that will encode the given position change.
830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If the return value is > 0xff, then the request cannot be fulfilled.
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Essentially the same as described in "DWARF Debugging Format Version 3"
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * section 6.2.5.1.
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
83499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param deltaLines {@code >= DBG_LINE_BASE, <= DBG_LINE_BASE +
83599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * DBG_LINE_RANGE;} the line change to encode
83699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param deltaAddress {@code >= 0;} the address change to encode
83799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code <= 0xff} if in range, otherwise parameters are out
83899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * of range
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static int computeOpcode(int deltaLines, int deltaAddress) {
841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (deltaLines < DBG_LINE_BASE
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                || deltaLines > (DBG_LINE_BASE + DBG_LINE_RANGE -1)) {
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
844f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            throw new RuntimeException("Parameter out of range");
845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (deltaLines - DBG_LINE_BASE)
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            + (DBG_LINE_RANGE * deltaAddress) + DBG_FIRST_SPECIAL;
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Emits an {@link DebugInfoConstants#DBG_ADVANCE_LINE DBG_ADVANCE_LINE}
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * sequence.
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param deltaLines amount to change line number register by
856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void emitAdvanceLine(int deltaLines) throws IOException {
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int mark = output.getCursor();
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        output.writeByte(DBG_ADVANCE_LINE);
862dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson        output.writeSleb128(deltaLines);
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        line += deltaLines;
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotateTo != null || debugPrint != null) {
866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            annotate(output.getCursor() - mark,
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    String.format("line = %d", line));
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (DEBUG) {
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.err.printf("Emitting advance_line for %d\n", deltaLines);
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
876f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein     * Emits an  {@link DebugInfoConstants#DBG_ADVANCE_PC DBG_ADVANCE_PC}
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * sequence.
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
87999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param deltaAddress {@code >= 0;} amount to change program counter by
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void emitAdvancePc(int deltaAddress) throws IOException {
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int mark = output.getCursor();
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        output.writeByte(DBG_ADVANCE_PC);
886dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson        output.writeUleb128(deltaAddress);
887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        address += deltaAddress;
888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotateTo != null || debugPrint != null) {
890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            annotate(output.getCursor() - mark,
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    String.format("%04x: advance pc", address));
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (DEBUG) {
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.err.printf("Emitting advance_pc for %d\n", deltaAddress);
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Emits an unsigned LEB128 value.
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
90299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param n {@code >= 0;} value to emit. Note that, although this can
90399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * represent integers larger than Integer.MAX_VALUE, we currently don't
90499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * allow that.
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void emitUnsignedLeb128(int n) throws IOException {
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // We'll never need the top end of the unsigned range anyway.
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (n < 0) {
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new RuntimeException(
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "Signed value where unsigned required: " + n);
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
914dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson        output.writeUleb128(n);
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Emits the {@link DebugInfoConstants#DBG_END_SEQUENCE DBG_END_SEQUENCE}
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * bytecode.
920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void emitEndSequence() {
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        output.writeByte(DBG_END_SEQUENCE);
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotateTo != null || debugPrint != null) {
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            annotate(1, "end sequence");
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
929