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