/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.dx.dex.file;

import com.android.dx.dex.code.LocalList;
import com.android.dx.dex.code.PositionList;
import com.android.dx.rop.code.RegisterSpec;
import com.android.dx.rop.code.SourcePosition;
import com.android.dx.rop.cst.CstMethodRef;
import com.android.dx.rop.cst.CstType;
import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.type.Prototype;
import com.android.dx.rop.type.StdTypeList;
import com.android.dx.rop.type.Type;
import com.android.dx.util.ByteArrayAnnotatedOutput;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.ExceptionWithContext;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.BitSet;

import static com.android.dx.dex.file.DebugInfoConstants.*;

/**
 * An encoder for the dex debug info state machine format. The format
 * for each method enrty is as follows:
 * <ol>
 * <li> signed LEB128: initial value for line register.
 * <li> n instances of signed LEB128: string indicies (offset by 1)
 * for each method argument in left-to-right order
 * with {@code this} excluded. A value of '0' indicates "no name"
 * <li> A sequence of special or normal opcodes as defined in
 * {@code DebugInfoConstants}.
 * <li> A single terminating {@code OP_END_SEQUENCE}
 * </ol>
 */
public final class DebugInfoEncoder {
    private static final boolean DEBUG = false;

    /** {@code null-ok;} positions (line numbers) to encode */
    private final PositionList positions;

    /** {@code null-ok;} local variables to encode */
    private final LocalList locals;

    private final ByteArrayAnnotatedOutput output;
    private final DexFile file;
    private final int codeSize;
    private final int regSize;

    private final Prototype desc;
    private final boolean isStatic;

    /** current encoding state: bytecode address */
    private int address = 0;

    /** current encoding state: line number */
    private int line = 1;

    /**
     * if non-null: the output to write annotations to. No normal
     * output is written to this.
     */
    private AnnotatedOutput annotateTo;

    /** if non-null: another possible output for annotations */
    private PrintWriter debugPrint;

    /** if non-null: the prefix for each annotation or debugPrint line */
    private String prefix;

    /** true if output should be consumed during annotation */
    private boolean shouldConsume;

    /** indexed by register; last local alive in register */
    private final LocalList.Entry[] lastEntryForReg;

    /**
     * Creates an instance.
     *
     * @param positions {@code null-ok;} positions (line numbers) to encode
     * @param locals {@code null-ok;} local variables to encode
     * @param file {@code null-ok;} may only be {@code null} if simply using
     * this class to do a debug print
     * @param codeSize
     * @param regSize
     * @param isStatic
     * @param ref
     */
    public DebugInfoEncoder(PositionList positions, LocalList locals,
            DexFile file, int codeSize, int regSize,
            boolean isStatic, CstMethodRef ref) {
        this.positions = positions;
        this.locals = locals;
        this.file = file;
        this.desc = ref.getPrototype();
        this.isStatic = isStatic;
        this.codeSize = codeSize;
        this.regSize = regSize;

        output = new ByteArrayAnnotatedOutput();
        lastEntryForReg = new LocalList.Entry[regSize];
    }

    /**
     * Annotates or writes a message to the {@code debugPrint} writer
     * if applicable.
     *
     * @param length the number of bytes associated with this message
     * @param message the message itself
     */
    private void annotate(int length, String message) {
        if (prefix != null) {
            message = prefix + message;
        }

        if (annotateTo != null) {
            annotateTo.annotate(shouldConsume ? length : 0, message);
        }

        if (debugPrint != null) {
            debugPrint.println(message);
        }
    }

    /**
     * Converts this (PositionList, LocalList) pair into a state machine
     * sequence.
     *
     * @return {@code non-null;} encoded byte sequence without padding and
     * terminated with a {@code 0x00} byte
     */
    public byte[] convert() {
        try {
            byte[] ret;
            ret = convert0();

            if (DEBUG) {
                for (int i = 0 ; i < ret.length; i++) {
                    System.err.printf("byte %02x\n", (0xff & ret[i]));
                }
            }

            return ret;
        } catch (IOException ex) {
            throw ExceptionWithContext
                    .withContext(ex, "...while encoding debug info");
        }
    }

    /**
     * Converts and produces annotations on a stream. Does not write
     * actual bits to the {@code AnnotatedOutput}.
     *
     * @param prefix {@code null-ok;} prefix to attach to each line of output
     * @param debugPrint {@code null-ok;} if specified, an alternate output for
     * annotations
     * @param out {@code null-ok;} if specified, where annotations should go
     * @param consume whether to claim to have consumed output for
     * {@code out}
     * @return {@code non-null;} encoded output
     */
    public byte[] convertAndAnnotate(String prefix, PrintWriter debugPrint,
            AnnotatedOutput out, boolean consume) {
        this.prefix = prefix;
        this.debugPrint = debugPrint;
        annotateTo = out;
        shouldConsume = consume;

        byte[] result = convert();

        return result;
    }

    private byte[] convert0() throws IOException {
        ArrayList<PositionList.Entry> sortedPositions = buildSortedPositions();
        ArrayList<LocalList.Entry> methodArgs = extractMethodArguments();

        emitHeader(sortedPositions, methodArgs);

        // TODO: Make this mark be the actual prologue end.
        output.writeByte(DBG_SET_PROLOGUE_END);

        if (annotateTo != null || debugPrint != null) {
            annotate(1, String.format("%04x: prologue end",address));
        }

        int positionsSz = sortedPositions.size();
        int localsSz = locals.size();

        // Current index in sortedPositions
        int curPositionIdx = 0;
        // Current index in locals
        int curLocalIdx = 0;

        for (;;) {
            /*
             * Emit any information for the current address.
             */

            curLocalIdx = emitLocalsAtAddress(curLocalIdx);
            curPositionIdx =
                emitPositionsAtAddress(curPositionIdx, sortedPositions);

            /*
             * Figure out what the next important address is.
             */

            int nextAddrL = Integer.MAX_VALUE; // local variable
            int nextAddrP = Integer.MAX_VALUE; // position (line number)

            if (curLocalIdx < localsSz) {
                nextAddrL = locals.get(curLocalIdx).getAddress();
            }

            if (curPositionIdx < positionsSz) {
                nextAddrP = sortedPositions.get(curPositionIdx).getAddress();
            }

            int next = Math.min(nextAddrP, nextAddrL);

            // No next important address == done.
            if (next == Integer.MAX_VALUE) {
                break;
            }

            /*
             * If the only work remaining are local ends at the end of the
             * block, stop here. Those are implied anyway.
             */
            if (next == codeSize
                    && nextAddrL == Integer.MAX_VALUE
                    && nextAddrP == Integer.MAX_VALUE) {
                break;
            }

            if (next == nextAddrP) {
                // Combined advance PC + position entry
                emitPosition(sortedPositions.get(curPositionIdx++));
            } else {
                emitAdvancePc(next - address);
            }
        }

        emitEndSequence();

        return output.toByteArray();
    }

    /**
     * Emits all local variable activity that occurs at the current
     * {@link #address} starting at the given index into {@code
     * locals} and including all subsequent activity at the same
     * address.
     *
     * @param curLocalIdx Current index in locals
     * @return new value for {@code curLocalIdx}
     * @throws IOException
     */
    private int emitLocalsAtAddress(int curLocalIdx)
            throws IOException {
        int sz = locals.size();

        // TODO: Don't emit ends implied by starts.

        while ((curLocalIdx < sz)
                && (locals.get(curLocalIdx).getAddress() == address)) {
            LocalList.Entry entry = locals.get(curLocalIdx++);
            int reg = entry.getRegister();
            LocalList.Entry prevEntry = lastEntryForReg[reg];

            if (entry == prevEntry) {
                /*
                 * Here we ignore locals entries for parameters,
                 * which have already been represented and placed in the
                 * lastEntryForReg array.
                 */
                continue;
            }

            // At this point we have a new entry one way or another.
            lastEntryForReg[reg] = entry;

            if (entry.isStart()) {
                if ((prevEntry != null) && entry.matches(prevEntry)) {
                    /*
                     * The previous local in this register has the same
                     * name and type as the one being introduced now, so
                     * use the more efficient "restart" form.
                     */
                    if (prevEntry.isStart()) {
                        /*
                         * We should never be handed a start when a
                         * a matching local is already active.
                         */
                        throw new RuntimeException("shouldn't happen");
                    }
                    emitLocalRestart(entry);
                } else {
                    emitLocalStart(entry);
                }
            } else {
                /*
                 * Only emit a local end if it is *not* due to a direct
                 * replacement. Direct replacements imply an end of the
                 * previous local in the same register.
                 *
                 * TODO: Make sure the runtime can deal with implied
                 * local ends from category-2 interactions, and when so,
                 * also stop emitting local ends for those cases.
                 */
                if (entry.getDisposition()
                        != LocalList.Disposition.END_REPLACED) {
                    emitLocalEnd(entry);
                }
            }
        }

        return curLocalIdx;
    }

    /**
     * Emits all positions that occur at the current {@code address}
     *
     * @param curPositionIdx Current index in sortedPositions
     * @param sortedPositions positions, sorted by ascending address
     * @return new value for {@code curPositionIdx}
     * @throws IOException
     */
    private int emitPositionsAtAddress(int curPositionIdx,
            ArrayList<PositionList.Entry> sortedPositions)
            throws IOException {
        int positionsSz = sortedPositions.size();
        while ((curPositionIdx < positionsSz)
                && (sortedPositions.get(curPositionIdx).getAddress()
                        == address)) {
            emitPosition(sortedPositions.get(curPositionIdx++));
        }
        return curPositionIdx;
    }

    /**
     * Emits the header sequence, which consists of LEB128-encoded initial
     * line number and string indicies for names of all non-"this" arguments.
     *
     * @param sortedPositions positions, sorted by ascending address
     * @param methodArgs local list entries for method argumens arguments,
     * in left-to-right order omitting "this"
     * @throws IOException
     */
    private void emitHeader(ArrayList<PositionList.Entry> sortedPositions,
            ArrayList<LocalList.Entry> methodArgs) throws IOException {
        boolean annotate = (annotateTo != null) || (debugPrint != null);
        int mark = output.getCursor();

        // Start by initializing the line number register.
        if (sortedPositions.size() > 0) {
            PositionList.Entry entry = sortedPositions.get(0);
            line = entry.getPosition().getLine();
        }
        output.writeUleb128(line);

        if (annotate) {
            annotate(output.getCursor() - mark, "line_start: " + line);
        }

        int curParam = getParamBase();
        // paramTypes will not include 'this'
        StdTypeList paramTypes = desc.getParameterTypes();
        int szParamTypes = paramTypes.size();

        /*
         * Initialize lastEntryForReg to have an initial
         * entry for the 'this' pointer.
         */
        if (!isStatic) {
            for (LocalList.Entry arg : methodArgs) {
                if (curParam == arg.getRegister()) {
                    lastEntryForReg[curParam] = arg;
                    break;
                }
            }
            curParam++;
        }

        // Write out the number of parameter entries that will follow.
        mark = output.getCursor();
        output.writeUleb128(szParamTypes);

        if (annotate) {
            annotate(output.getCursor() - mark,
                    String.format("parameters_size: %04x", szParamTypes));
        }

        /*
         * Then emit the string indicies of all the method parameters.
         * Note that 'this', if applicable, is excluded.
         */
        for (int i = 0; i < szParamTypes; i++) {
            Type pt = paramTypes.get(i);
            LocalList.Entry found = null;

            mark = output.getCursor();

            for (LocalList.Entry arg : methodArgs) {
                if (curParam == arg.getRegister()) {
                    found = arg;

                    if (arg.getSignature() != null) {
                        /*
                         * Parameters with signatures will be re-emitted
                         * in complete as LOCAL_START_EXTENDED's below.
                         */
                        emitStringIndex(null);
                    } else {
                        emitStringIndex(arg.getName());
                    }
                    lastEntryForReg[curParam] = arg;

                    break;
                }
            }

            if (found == null) {
                /*
                 * Emit a null symbol for "unnamed." This is common
                 * for, e.g., synthesized methods and inner-class
                 * this$0 arguments.
                 */
                emitStringIndex(null);
            }

            if (annotate) {
                String parameterName
                        = (found == null || found.getSignature() != null)
                                ? "<unnamed>" : found.getName().toHuman();
                annotate(output.getCursor() - mark,
                        "parameter " + parameterName + " "
                                + RegisterSpec.PREFIX + curParam);
            }

            curParam += pt.getCategory();
        }

        /*
         * If anything emitted above has a type signature, emit it again as
         * a LOCAL_RESTART_EXTENDED
         */

        for (LocalList.Entry arg : lastEntryForReg) {
            if (arg == null) {
                continue;
            }

            CstString signature = arg.getSignature();

            if (signature != null) {
                emitLocalStartExtended(arg);
            }
        }
    }

    /**
     * Builds a list of position entries, sorted by ascending address.
     *
     * @return A sorted positions list
     */
    private ArrayList<PositionList.Entry> buildSortedPositions() {
        int sz = (positions == null) ? 0 : positions.size();
        ArrayList<PositionList.Entry> result = new ArrayList(sz);

        for (int i = 0; i < sz; i++) {
            result.add(positions.get(i));
        }

        // Sort ascending by address.
        Collections.sort (result, new Comparator<PositionList.Entry>() {
            public int compare (PositionList.Entry a, PositionList.Entry b) {
                return a.getAddress() - b.getAddress();
            }

            public boolean equals (Object obj) {
               return obj == this;
            }
        });
        return result;
    }

    /**
     * Gets the register that begins the method's parameter range (including
     * the 'this' parameter for non-static methods). The range continues until
     * {@code regSize}
     *
     * @return register as noted above
     */
    private int getParamBase() {
        return regSize
                - desc.getParameterTypes().getWordCount() - (isStatic? 0 : 1);
    }

    /**
     * Extracts method arguments from a locals list. These will be collected
     * from the input list and sorted by ascending register in the
     * returned list.
     *
     * @return list of non-{@code this} method argument locals,
     * sorted by ascending register
     */
    private ArrayList<LocalList.Entry> extractMethodArguments() {
        ArrayList<LocalList.Entry> result
                = new ArrayList(desc.getParameterTypes().size());
        int argBase = getParamBase();
        BitSet seen = new BitSet(regSize - argBase);
        int sz = locals.size();

        for (int i = 0; i < sz; i++) {
            LocalList.Entry e = locals.get(i);
            int reg = e.getRegister();

            if (reg < argBase) {
                continue;
            }

            // only the lowest-start-address entry is included.
            if (seen.get(reg - argBase)) {
                continue;
            }

            seen.set(reg - argBase);
            result.add(e);
        }

        // Sort by ascending register.
        Collections.sort(result, new Comparator<LocalList.Entry>() {
            public int compare(LocalList.Entry a, LocalList.Entry b) {
                return a.getRegister() - b.getRegister();
            }

            public boolean equals(Object obj) {
               return obj == this;
            }
        });

        return result;
    }

    /**
     * Returns a string representation of this LocalList entry that is
     * appropriate for emitting as an annotation.
     *
     * @param e {@code non-null;} entry
     * @return {@code non-null;} annotation string
     */
    private String entryAnnotationString(LocalList.Entry e) {
        StringBuilder sb = new StringBuilder();

        sb.append(RegisterSpec.PREFIX);
        sb.append(e.getRegister());
        sb.append(' ');

        CstString name = e.getName();
        if (name == null) {
            sb.append("null");
        } else {
            sb.append(name.toHuman());
        }
        sb.append(' ');

        CstType type = e.getType();
        if (type == null) {
            sb.append("null");
        } else {
            sb.append(type.toHuman());
        }

        CstString signature = e.getSignature();

        if (signature != null) {
            sb.append(' ');
            sb.append(signature.toHuman());
        }

        return sb.toString();
    }

    /**
     * Emits a {@link DebugInfoConstants#DBG_RESTART_LOCAL DBG_RESTART_LOCAL}
     * sequence.
     *
     * @param entry entry associated with this restart
     * @throws IOException
     */
    private void emitLocalRestart(LocalList.Entry entry)
            throws IOException {

        int mark = output.getCursor();

        output.writeByte(DBG_RESTART_LOCAL);
        emitUnsignedLeb128(entry.getRegister());

        if (annotateTo != null || debugPrint != null) {
            annotate(output.getCursor() - mark,
                    String.format("%04x: +local restart %s",
                            address, entryAnnotationString(entry)));
        }

        if (DEBUG) {
            System.err.println("emit local restart");
        }
    }

    /**
     * Emits a string index as an unsigned LEB128. The actual value written
     * is shifted by 1, so that the '0' value is reserved for "null". The
     * null symbol is used in some cases by the parameter name list
     * at the beginning of the sequence.
     *
     * @param string {@code null-ok;} string to emit
     * @throws IOException
     */
    private void emitStringIndex(CstString string) throws IOException {
        if ((string == null) || (file == null)) {
            output.writeUleb128(0);
        } else {
            output.writeUleb128(
                    1 + file.getStringIds().indexOf(string));
        }

        if (DEBUG) {
            System.err.printf("Emit string %s\n",
                    string == null ? "<null>" : string.toQuoted());
        }
    }

    /**
     * Emits a type index as an unsigned LEB128. The actual value written
     * is shifted by 1, so that the '0' value is reserved for "null".
     *
     * @param type {@code null-ok;} type to emit
     * @throws IOException
     */
    private void emitTypeIndex(CstType type) throws IOException {
        if ((type == null) || (file == null)) {
            output.writeUleb128(0);
        } else {
            output.writeUleb128(
                    1 + file.getTypeIds().indexOf(type));
        }

        if (DEBUG) {
            System.err.printf("Emit type %s\n",
                    type == null ? "<null>" : type.toHuman());
        }
    }

    /**
     * Emits a {@link DebugInfoConstants#DBG_START_LOCAL DBG_START_LOCAL} or
     * {@link DebugInfoConstants#DBG_START_LOCAL_EXTENDED
     * DBG_START_LOCAL_EXTENDED} sequence.
     *
     * @param entry entry to emit
     * @throws IOException
     */
    private void emitLocalStart(LocalList.Entry entry)
        throws IOException {

        if (entry.getSignature() != null) {
            emitLocalStartExtended(entry);
            return;
        }

        int mark = output.getCursor();

        output.writeByte(DBG_START_LOCAL);

        emitUnsignedLeb128(entry.getRegister());
        emitStringIndex(entry.getName());
        emitTypeIndex(entry.getType());

        if (annotateTo != null || debugPrint != null) {
            annotate(output.getCursor() - mark,
                    String.format("%04x: +local %s", address,
                            entryAnnotationString(entry)));
        }

        if (DEBUG) {
            System.err.println("emit local start");
        }
    }

    /**
     * Emits a {@link DebugInfoConstants#DBG_START_LOCAL_EXTENDED
     * DBG_START_LOCAL_EXTENDED} sequence.
     *
     * @param entry entry to emit
     * @throws IOException
     */
    private void emitLocalStartExtended(LocalList.Entry entry)
        throws IOException {

        int mark = output.getCursor();

        output.writeByte(DBG_START_LOCAL_EXTENDED);

        emitUnsignedLeb128(entry.getRegister());
        emitStringIndex(entry.getName());
        emitTypeIndex(entry.getType());
        emitStringIndex(entry.getSignature());

        if (annotateTo != null || debugPrint != null) {
            annotate(output.getCursor() - mark,
                    String.format("%04x: +localx %s", address,
                            entryAnnotationString(entry)));
        }

        if (DEBUG) {
            System.err.println("emit local start");
        }
    }

    /**
     * Emits a {@link DebugInfoConstants#DBG_END_LOCAL DBG_END_LOCAL} sequence.
     *
     * @param entry {@code entry non-null;} entry associated with end.
     * @throws IOException
     */
    private void emitLocalEnd(LocalList.Entry entry)
            throws IOException {

        int mark = output.getCursor();

        output.writeByte(DBG_END_LOCAL);
        output.writeUleb128(entry.getRegister());

        if (annotateTo != null || debugPrint != null) {
            annotate(output.getCursor() - mark,
                    String.format("%04x: -local %s", address,
                            entryAnnotationString(entry)));
        }

        if (DEBUG) {
            System.err.println("emit local end");
        }
    }

    /**
     * Emits the necessary byte sequences to emit the given position table
     * entry. This will typically be a single special opcode, although
     * it may also require DBG_ADVANCE_PC or DBG_ADVANCE_LINE.
     *
     * @param entry position entry to emit.
     * @throws IOException
     */
    private void emitPosition(PositionList.Entry entry)
            throws IOException {

        SourcePosition pos = entry.getPosition();
        int newLine = pos.getLine();
        int newAddress = entry.getAddress();

        int opcode;

        int deltaLines = newLine - line;
        int deltaAddress = newAddress - address;

        if (deltaAddress < 0) {
            throw new RuntimeException(
                    "Position entries must be in ascending address order");
        }

        if ((deltaLines < DBG_LINE_BASE)
                || (deltaLines > (DBG_LINE_BASE + DBG_LINE_RANGE -1))) {
            emitAdvanceLine(deltaLines);
            deltaLines = 0;
        }

        opcode = computeOpcode (deltaLines, deltaAddress);

        if ((opcode & ~0xff) > 0) {
            emitAdvancePc(deltaAddress);
            deltaAddress = 0;
            opcode = computeOpcode (deltaLines, deltaAddress);

            if ((opcode & ~0xff) > 0) {
                emitAdvanceLine(deltaLines);
                deltaLines = 0;
                opcode = computeOpcode (deltaLines, deltaAddress);
            }
        }

        output.writeByte(opcode);

        line += deltaLines;
        address += deltaAddress;

        if (annotateTo != null || debugPrint != null) {
            annotate(1,
                    String.format("%04x: line %d", address, line));
        }
    }

    /**
     * Computes a special opcode that will encode the given position change.
     * If the return value is > 0xff, then the request cannot be fulfilled.
     * Essentially the same as described in "DWARF Debugging Format Version 3"
     * section 6.2.5.1.
     *
     * @param deltaLines {@code >= DBG_LINE_BASE, <= DBG_LINE_BASE +
     * DBG_LINE_RANGE;} the line change to encode
     * @param deltaAddress {@code >= 0;} the address change to encode
     * @return {@code <= 0xff} if in range, otherwise parameters are out
     * of range
     */
    private static int computeOpcode(int deltaLines, int deltaAddress) {
        if (deltaLines < DBG_LINE_BASE
                || deltaLines > (DBG_LINE_BASE + DBG_LINE_RANGE -1)) {

            throw new RuntimeException("Parameter out of range");
        }

        return (deltaLines - DBG_LINE_BASE)
            + (DBG_LINE_RANGE * deltaAddress) + DBG_FIRST_SPECIAL;
    }

    /**
     * Emits an {@link DebugInfoConstants#DBG_ADVANCE_LINE DBG_ADVANCE_LINE}
     * sequence.
     *
     * @param deltaLines amount to change line number register by
     * @throws IOException
     */
    private void emitAdvanceLine(int deltaLines) throws IOException {
        int mark = output.getCursor();

        output.writeByte(DBG_ADVANCE_LINE);
        output.writeSleb128(deltaLines);
        line += deltaLines;

        if (annotateTo != null || debugPrint != null) {
            annotate(output.getCursor() - mark,
                    String.format("line = %d", line));
        }

        if (DEBUG) {
            System.err.printf("Emitting advance_line for %d\n", deltaLines);
        }
    }

    /**
     * Emits an  {@link DebugInfoConstants#DBG_ADVANCE_PC DBG_ADVANCE_PC}
     * sequence.
     *
     * @param deltaAddress {@code >= 0;} amount to change program counter by
     * @throws IOException
     */
    private void emitAdvancePc(int deltaAddress) throws IOException {
        int mark = output.getCursor();

        output.writeByte(DBG_ADVANCE_PC);
        output.writeUleb128(deltaAddress);
        address += deltaAddress;

        if (annotateTo != null || debugPrint != null) {
            annotate(output.getCursor() - mark,
                    String.format("%04x: advance pc", address));
        }

        if (DEBUG) {
            System.err.printf("Emitting advance_pc for %d\n", deltaAddress);
        }
    }

    /**
     * Emits an unsigned LEB128 value.
     *
     * @param n {@code >= 0;} value to emit. Note that, although this can
     * represent integers larger than Integer.MAX_VALUE, we currently don't
     * allow that.
     * @throws IOException
     */
    private void emitUnsignedLeb128(int n) throws IOException {
        // We'll never need the top end of the unsigned range anyway.
        if (n < 0) {
            throw new RuntimeException(
                    "Signed value where unsigned required: " + n);
        }

        output.writeUleb128(n);
    }

    /**
     * Emits the {@link DebugInfoConstants#DBG_END_SEQUENCE DBG_END_SEQUENCE}
     * bytecode.
     */
    private void emitEndSequence() {
        output.writeByte(DBG_END_SEQUENCE);

        if (annotateTo != null || debugPrint != null) {
            annotate(1, "end sequence");
        }
    }
}
