1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/* 2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project 3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License"); 5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License. 6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at 7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * http://www.apache.org/licenses/LICENSE-2.0 9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software 11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS, 12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and 14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License. 15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.dex.file; 18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.dex.code.LocalList; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.dex.code.PositionList; 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.RegisterSpec; 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.SourcePosition; 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstMethodRef; 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstType; 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstUtf8; 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.Prototype; 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.StdTypeList; 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.Type; 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.AnnotatedOutput; 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.ByteArrayAnnotatedOutput; 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.ExceptionWithContext; 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.IOException; 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.PrintWriter; 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.ArrayList; 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.Collections; 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.Comparator; 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.BitSet; 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport static com.android.dexgen.dex.file.DebugInfoConstants.*; 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * An encoder for the dex debug info state machine format. The format 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * for each method enrty is as follows: 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <ol> 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <li> signed LEB128: initial value for line register. 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <li> n instances of signed LEB128: string indicies (offset by 1) 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * for each method argument in left-to-right order 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * with {@code this} excluded. A value of '0' indicates "no name" 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <li> A sequence of special or normal opcodes as defined in 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code DebugInfoConstants}. 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <li> A single terminating {@code OP_END_SEQUENCE} 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * </ol> 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class DebugInfoEncoder { 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static final boolean DEBUG = false; 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code null-ok;} positions (line numbers) to encode */ 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final PositionList positions; 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code null-ok;} local variables to encode */ 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final LocalList locals; 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final ByteArrayAnnotatedOutput output; 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final DexFile file; 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final int codeSize; 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final int regSize; 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final Prototype desc; 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final boolean isStatic; 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** current encoding state: bytecode address */ 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int address = 0; 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** current encoding state: line number */ 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int line = 1; 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * if non-null: the output to write annotations to. No normal 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * output is written to this. 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private AnnotatedOutput annotateTo; 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** if non-null: another possible output for annotations */ 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private PrintWriter debugPrint; 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** if non-null: the prefix for each annotation or debugPrint line */ 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private String prefix; 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** true if output should be consumed during annotation */ 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private boolean shouldConsume; 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** indexed by register; last local alive in register */ 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final LocalList.Entry[] lastEntryForReg; 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Creates an instance. 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param positions {@code null-ok;} positions (line numbers) to encode 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param locals {@code null-ok;} local variables to encode 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param file {@code null-ok;} may only be {@code null} if simply using 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * this class to do a debug print 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param codeSize 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param regSize 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param isStatic 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param ref 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public DebugInfoEncoder(PositionList positions, LocalList locals, 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul DexFile file, int codeSize, int regSize, 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul boolean isStatic, CstMethodRef ref) { 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.positions = positions; 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.locals = locals; 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.file = file; 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.desc = ref.getPrototype(); 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.isStatic = isStatic; 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.codeSize = codeSize; 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.regSize = regSize; 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output = new ByteArrayAnnotatedOutput(); 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul lastEntryForReg = new LocalList.Entry[regSize]; 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Annotates or writes a message to the {@code debugPrint} writer 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * if applicable. 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param length the number of bytes associated with this message 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param message the message itself 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void annotate(int length, String message) { 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (prefix != null) { 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul message = prefix + message; 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotateTo != null) { 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul annotateTo.annotate(shouldConsume ? length : 0, message); 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (debugPrint != null) { 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul debugPrint.println(message); 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Converts this (PositionList, LocalList) pair into a state machine 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * sequence. 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} encoded byte sequence without padding and 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * terminated with a {@code 0x00} byte 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public byte[] convert() { 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul try { 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul byte[] ret; 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ret = convert0(); 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (DEBUG) { 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0 ; i < ret.length; i++) { 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul System.err.printf("byte %02x\n", (0xff & ret[i])); 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return ret; 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } catch (IOException ex) { 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw ExceptionWithContext 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul .withContext(ex, "...while encoding debug info"); 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Converts and produces annotations on a stream. Does not write 171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * actual bits to the {@code AnnotatedOutput}. 172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param prefix {@code null-ok;} prefix to attach to each line of output 174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param debugPrint {@code null-ok;} if specified, an alternate output for 175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * annotations 176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code null-ok;} if specified, where annotations should go 177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param consume whether to claim to have consumed output for 178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code out} 179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} encoded output 180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public byte[] convertAndAnnotate(String prefix, PrintWriter debugPrint, 182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul AnnotatedOutput out, boolean consume) { 183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.prefix = prefix; 184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.debugPrint = debugPrint; 185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul annotateTo = out; 186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul shouldConsume = consume; 187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul byte[] result = convert(); 189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return result; 191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private byte[] convert0() throws IOException { 194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ArrayList<PositionList.Entry> sortedPositions = buildSortedPositions(); 195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ArrayList<LocalList.Entry> methodArgs = extractMethodArguments(); 196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitHeader(sortedPositions, methodArgs); 198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // TODO: Make this mark be the actual prologue end. 200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeByte(DBG_SET_PROLOGUE_END); 201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotateTo != null || debugPrint != null) { 203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul annotate(1, String.format("%04x: prologue end",address)); 204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int positionsSz = sortedPositions.size(); 207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int localsSz = locals.size(); 208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Current index in sortedPositions 210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int curPositionIdx = 0; 211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Current index in locals 212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int curLocalIdx = 0; 213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (;;) { 215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Emit any information for the current address. 217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul curLocalIdx = emitLocalsAtAddress(curLocalIdx); 220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul curPositionIdx = 221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitPositionsAtAddress(curPositionIdx, sortedPositions); 222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Figure out what the next important address is. 225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int nextAddrL = Integer.MAX_VALUE; // local variable 228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int nextAddrP = Integer.MAX_VALUE; // position (line number) 229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (curLocalIdx < localsSz) { 231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul nextAddrL = locals.get(curLocalIdx).getAddress(); 232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (curPositionIdx < positionsSz) { 235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul nextAddrP = sortedPositions.get(curPositionIdx).getAddress(); 236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int next = Math.min(nextAddrP, nextAddrL); 239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // No next important address == done. 241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (next == Integer.MAX_VALUE) { 242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul break; 243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * If the only work remaining are local ends at the end of the 247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * block, stop here. Those are implied anyway. 248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (next == codeSize 250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && nextAddrL == Integer.MAX_VALUE 251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && nextAddrP == Integer.MAX_VALUE) { 252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul break; 253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (next == nextAddrP) { 256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Combined advance PC + position entry 257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitPosition(sortedPositions.get(curPositionIdx++)); 258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitAdvancePc(next - address); 260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitEndSequence(); 264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return output.toByteArray(); 266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Emits all local variable activity that occurs at the current 270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@link #address} starting at the given index into {@code 271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * locals} and including all subsequent activity at the same 272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * address. 273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param curLocalIdx Current index in locals 275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return new value for {@code curLocalIdx} 276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws IOException 277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int emitLocalsAtAddress(int curLocalIdx) 279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throws IOException { 280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = locals.size(); 281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // TODO: Don't emit ends implied by starts. 283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul while ((curLocalIdx < sz) 285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && (locals.get(curLocalIdx).getAddress() == address)) { 286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul LocalList.Entry entry = locals.get(curLocalIdx++); 287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int reg = entry.getRegister(); 288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul LocalList.Entry prevEntry = lastEntryForReg[reg]; 289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (entry == prevEntry) { 291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Here we ignore locals entries for parameters, 293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * which have already been represented and placed in the 294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * lastEntryForReg array. 295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul continue; 297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // At this point we have a new entry one way or another. 300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul lastEntryForReg[reg] = entry; 301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (entry.isStart()) { 303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((prevEntry != null) && entry.matches(prevEntry)) { 304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * The previous local in this register has the same 306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * name and type as the one being introduced now, so 307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * use the more efficient "restart" form. 308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (prevEntry.isStart()) { 310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * We should never be handed a start when a 312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * a matching local is already active. 313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException("shouldn't happen"); 315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitLocalRestart(entry); 317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 318917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitLocalStart(entry); 319917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 320917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 321917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 322917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Only emit a local end if it is *not* due to a direct 323917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * replacement. Direct replacements imply an end of the 324917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * previous local in the same register. 325917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 326917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * TODO: Make sure the runtime can deal with implied 327917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * local ends from category-2 interactions, and when so, 328917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * also stop emitting local ends for those cases. 329917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 330917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (entry.getDisposition() 331917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul != LocalList.Disposition.END_REPLACED) { 332917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitLocalEnd(entry); 333917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 334917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 335917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 336917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 337917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return curLocalIdx; 338917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 339917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 340917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 341917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Emits all positions that occur at the current {@code address} 342917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 343917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param curPositionIdx Current index in sortedPositions 344917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param sortedPositions positions, sorted by ascending address 345917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return new value for {@code curPositionIdx} 346917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws IOException 347917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 348917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int emitPositionsAtAddress(int curPositionIdx, 349917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ArrayList<PositionList.Entry> sortedPositions) 350917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throws IOException { 351917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int positionsSz = sortedPositions.size(); 352917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul while ((curPositionIdx < positionsSz) 353917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && (sortedPositions.get(curPositionIdx).getAddress() 354917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul == address)) { 355917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitPosition(sortedPositions.get(curPositionIdx++)); 356917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 357917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return curPositionIdx; 358917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 359917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 360917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 361917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Emits the header sequence, which consists of LEB128-encoded initial 362917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * line number and string indicies for names of all non-"this" arguments. 363917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 364917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param sortedPositions positions, sorted by ascending address 365917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param methodArgs local list entries for method argumens arguments, 366917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * in left-to-right order omitting "this" 367917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws IOException 368917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 369917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void emitHeader(ArrayList<PositionList.Entry> sortedPositions, 370917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ArrayList<LocalList.Entry> methodArgs) throws IOException { 371917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul boolean annotate = (annotateTo != null) || (debugPrint != null); 372917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int mark = output.getCursor(); 373917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 374917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Start by initializing the line number register. 375917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (sortedPositions.size() > 0) { 376917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul PositionList.Entry entry = sortedPositions.get(0); 377917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul line = entry.getPosition().getLine(); 378917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 379917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeUnsignedLeb128(line); 380917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 381917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotate) { 382917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul annotate(output.getCursor() - mark, "line_start: " + line); 383917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 384917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 385917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int curParam = getParamBase(); 386917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // paramTypes will not include 'this' 387917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StdTypeList paramTypes = desc.getParameterTypes(); 388917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int szParamTypes = paramTypes.size(); 389917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 390917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 391917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Initialize lastEntryForReg to have an initial 392917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * entry for the 'this' pointer. 393917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 394917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (!isStatic) { 395917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (LocalList.Entry arg : methodArgs) { 396917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (curParam == arg.getRegister()) { 397917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul lastEntryForReg[curParam] = arg; 398917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul break; 399917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 400917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 401917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul curParam++; 402917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 403917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 404917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Write out the number of parameter entries that will follow. 405917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul mark = output.getCursor(); 406917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeUnsignedLeb128(szParamTypes); 407917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 408917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotate) { 409917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul annotate(output.getCursor() - mark, 410917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul String.format("parameters_size: %04x", szParamTypes)); 411917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 412917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 413917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 414917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Then emit the string indicies of all the method parameters. 415917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Note that 'this', if applicable, is excluded. 416917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 417917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < szParamTypes; i++) { 418917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Type pt = paramTypes.get(i); 419917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul LocalList.Entry found = null; 420917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 421917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul mark = output.getCursor(); 422917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 423917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (LocalList.Entry arg : methodArgs) { 424917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (curParam == arg.getRegister()) { 425917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul found = arg; 426917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 427917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (arg.getSignature() != null) { 428917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 429917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Parameters with signatures will be re-emitted 430917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * in complete as LOCAL_START_EXTENDED's below. 431917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 432917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitStringIndex(null); 433917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 434917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitStringIndex(arg.getName()); 435917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 436917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul lastEntryForReg[curParam] = arg; 437917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 438917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul break; 439917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 440917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 441917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 442917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (found == null) { 443917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 444917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Emit a null symbol for "unnamed." This is common 445917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * for, e.g., synthesized methods and inner-class 446917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * this$0 arguments. 447917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 448917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitStringIndex(null); 449917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 450917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 451917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotate) { 452917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul String parameterName 453917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul = (found == null || found.getSignature() != null) 454917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ? "<unnamed>" : found.getName().toHuman(); 455917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul annotate(output.getCursor() - mark, 456917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul "parameter " + parameterName + " " 457917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul + RegisterSpec.PREFIX + curParam); 458917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 459917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 460917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul curParam += pt.getCategory(); 461917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 462917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 463917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 464917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * If anything emitted above has a type signature, emit it again as 465917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * a LOCAL_RESTART_EXTENDED 466917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 467917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 468917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (LocalList.Entry arg : lastEntryForReg) { 469917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (arg == null) { 470917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul continue; 471917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 472917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 473917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul CstUtf8 signature = arg.getSignature(); 474917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 475917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (signature != null) { 476917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitLocalStartExtended(arg); 477917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 478917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 479917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 480917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 481917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 482917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Builds a list of position entries, sorted by ascending address. 483917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 484917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return A sorted positions list 485917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 486917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private ArrayList<PositionList.Entry> buildSortedPositions() { 487917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = (positions == null) ? 0 : positions.size(); 488917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ArrayList<PositionList.Entry> result = new ArrayList(sz); 489917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 490917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 491917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result.add(positions.get(i)); 492917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 493917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 494917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Sort ascending by address. 495917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Collections.sort (result, new Comparator<PositionList.Entry>() { 496917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int compare (PositionList.Entry a, PositionList.Entry b) { 497917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return a.getAddress() - b.getAddress(); 498917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 499917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 500917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean equals (Object obj) { 501917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return obj == this; 502917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 503917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul }); 504917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return result; 505917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 506917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 507917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 508917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the register that begins the method's parameter range (including 509917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the 'this' parameter for non-static methods). The range continues until 510917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code regSize} 511917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 512917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return register as noted above 513917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 514917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int getParamBase() { 515917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return regSize 516917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul - desc.getParameterTypes().getWordCount() - (isStatic? 0 : 1); 517917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 518917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 519917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 520917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Extracts method arguments from a locals list. These will be collected 521917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * from the input list and sorted by ascending register in the 522917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * returned list. 523917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 524917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return list of non-{@code this} method argument locals, 525917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * sorted by ascending register 526917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 527917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private ArrayList<LocalList.Entry> extractMethodArguments() { 528917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ArrayList<LocalList.Entry> result 529917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul = new ArrayList(desc.getParameterTypes().size()); 530917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int argBase = getParamBase(); 531917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul BitSet seen = new BitSet(regSize - argBase); 532917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = locals.size(); 533917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 534917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 535917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul LocalList.Entry e = locals.get(i); 536917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int reg = e.getRegister(); 537917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 538917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (reg < argBase) { 539917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul continue; 540917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 541917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 542917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // only the lowest-start-address entry is included. 543917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (seen.get(reg - argBase)) { 544917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul continue; 545917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 546917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 547917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul seen.set(reg - argBase); 548917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result.add(e); 549917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 550917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 551917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Sort by ascending register. 552917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Collections.sort(result, new Comparator<LocalList.Entry>() { 553917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int compare(LocalList.Entry a, LocalList.Entry b) { 554917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return a.getRegister() - b.getRegister(); 555917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 556917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 557917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean equals(Object obj) { 558917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return obj == this; 559917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 560917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul }); 561917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 562917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return result; 563917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 564917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 565917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 566917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns a string representation of this LocalList entry that is 567917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * appropriate for emitting as an annotation. 568917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 569917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param e {@code non-null;} entry 570917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} annotation string 571917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 572917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private String entryAnnotationString(LocalList.Entry e) { 573917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StringBuilder sb = new StringBuilder(); 574917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 575917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(RegisterSpec.PREFIX); 576917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(e.getRegister()); 577917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(' '); 578917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 579917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul CstUtf8 name = e.getName(); 580917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (name == null) { 581917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append("null"); 582917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 583917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(name.toHuman()); 584917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 585917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(' '); 586917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 587917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul CstType type = e.getType(); 588917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (type == null) { 589917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append("null"); 590917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 591917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(type.toHuman()); 592917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 593917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 594917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul CstUtf8 signature = e.getSignature(); 595917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 596917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (signature != null) { 597917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(' '); 598917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(signature.toHuman()); 599917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 600917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 601917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return sb.toString(); 602917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 603917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 604917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 605917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Emits a {@link DebugInfoConstants#DBG_RESTART_LOCAL DBG_RESTART_LOCAL} 606917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * sequence. 607917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 608917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param entry entry associated with this restart 609917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws IOException 610917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 611917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void emitLocalRestart(LocalList.Entry entry) 612917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throws IOException { 613917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 614917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int mark = output.getCursor(); 615917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 616917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeByte(DBG_RESTART_LOCAL); 617917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitUnsignedLeb128(entry.getRegister()); 618917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 619917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotateTo != null || debugPrint != null) { 620917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul annotate(output.getCursor() - mark, 621917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul String.format("%04x: +local restart %s", 622917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul address, entryAnnotationString(entry))); 623917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 624917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 625917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (DEBUG) { 626917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul System.err.println("emit local restart"); 627917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 628917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 629917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 630917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 631917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Emits a string index as an unsigned LEB128. The actual value written 632917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * is shifted by 1, so that the '0' value is reserved for "null". The 633917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * null symbol is used in some cases by the parameter name list 634917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * at the beginning of the sequence. 635917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 636917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param string {@code null-ok;} string to emit 637917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws IOException 638917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 639917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void emitStringIndex(CstUtf8 string) throws IOException { 640917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((string == null) || (file == null)) { 641917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeUnsignedLeb128(0); 642917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 643917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeUnsignedLeb128( 644917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 1 + file.getStringIds().indexOf(string)); 645917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 646917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 647917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (DEBUG) { 648917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul System.err.printf("Emit string %s\n", 649917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul string == null ? "<null>" : string.toQuoted()); 650917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 651917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 652917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 653917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 654917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Emits a type index as an unsigned LEB128. The actual value written 655917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * is shifted by 1, so that the '0' value is reserved for "null". 656917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 657917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param type {@code null-ok;} type to emit 658917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws IOException 659917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 660917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void emitTypeIndex(CstType type) throws IOException { 661917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((type == null) || (file == null)) { 662917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeUnsignedLeb128(0); 663917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 664917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeUnsignedLeb128( 665917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 1 + file.getTypeIds().indexOf(type)); 666917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 667917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 668917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (DEBUG) { 669917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul System.err.printf("Emit type %s\n", 670917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul type == null ? "<null>" : type.toHuman()); 671917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 672917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 673917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 674917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 675917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Emits a {@link DebugInfoConstants#DBG_START_LOCAL DBG_START_LOCAL} or 676917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@link DebugInfoConstants#DBG_START_LOCAL_EXTENDED 677917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * DBG_START_LOCAL_EXTENDED} sequence. 678917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 679917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param entry entry to emit 680917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws IOException 681917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 682917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void emitLocalStart(LocalList.Entry entry) 683917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throws IOException { 684917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 685917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (entry.getSignature() != null) { 686917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitLocalStartExtended(entry); 687917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return; 688917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 689917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 690917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int mark = output.getCursor(); 691917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 692917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeByte(DBG_START_LOCAL); 693917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 694917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitUnsignedLeb128(entry.getRegister()); 695917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitStringIndex(entry.getName()); 696917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitTypeIndex(entry.getType()); 697917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 698917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotateTo != null || debugPrint != null) { 699917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul annotate(output.getCursor() - mark, 700917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul String.format("%04x: +local %s", address, 701917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul entryAnnotationString(entry))); 702917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 703917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 704917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (DEBUG) { 705917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul System.err.println("emit local start"); 706917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 707917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 708917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 709917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 710917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Emits a {@link DebugInfoConstants#DBG_START_LOCAL_EXTENDED 711917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * DBG_START_LOCAL_EXTENDED} sequence. 712917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 713917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param entry entry to emit 714917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws IOException 715917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 716917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void emitLocalStartExtended(LocalList.Entry entry) 717917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throws IOException { 718917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 719917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int mark = output.getCursor(); 720917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 721917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeByte(DBG_START_LOCAL_EXTENDED); 722917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 723917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitUnsignedLeb128(entry.getRegister()); 724917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitStringIndex(entry.getName()); 725917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitTypeIndex(entry.getType()); 726917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitStringIndex(entry.getSignature()); 727917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 728917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotateTo != null || debugPrint != null) { 729917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul annotate(output.getCursor() - mark, 730917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul String.format("%04x: +localx %s", address, 731917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul entryAnnotationString(entry))); 732917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 733917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 734917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (DEBUG) { 735917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul System.err.println("emit local start"); 736917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 737917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 738917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 739917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 740917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Emits a {@link DebugInfoConstants#DBG_END_LOCAL DBG_END_LOCAL} sequence. 741917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 742917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param entry {@code entry non-null;} entry associated with end. 743917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws IOException 744917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 745917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void emitLocalEnd(LocalList.Entry entry) 746917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throws IOException { 747917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 748917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int mark = output.getCursor(); 749917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 750917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeByte(DBG_END_LOCAL); 751917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeUnsignedLeb128(entry.getRegister()); 752917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 753917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotateTo != null || debugPrint != null) { 754917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul annotate(output.getCursor() - mark, 755917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul String.format("%04x: -local %s", address, 756917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul entryAnnotationString(entry))); 757917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 758917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 759917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (DEBUG) { 760917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul System.err.println("emit local end"); 761917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 762917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 763917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 764917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 765917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Emits the necessary byte sequences to emit the given position table 766917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * entry. This will typically be a single special opcode, although 767917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * it may also require DBG_ADVANCE_PC or DBG_ADVANCE_LINE. 768917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 769917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param entry position entry to emit. 770917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws IOException 771917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 772917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void emitPosition(PositionList.Entry entry) 773917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throws IOException { 774917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 775917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul SourcePosition pos = entry.getPosition(); 776917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int newLine = pos.getLine(); 777917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int newAddress = entry.getAddress(); 778917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 779917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int opcode; 780917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 781917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int deltaLines = newLine - line; 782917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int deltaAddress = newAddress - address; 783917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 784917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (deltaAddress < 0) { 785917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException( 786917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul "Position entries must be in ascending address order"); 787917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 788917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 789917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((deltaLines < DBG_LINE_BASE) 790917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul || (deltaLines > (DBG_LINE_BASE + DBG_LINE_RANGE -1))) { 791917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitAdvanceLine(deltaLines); 792917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul deltaLines = 0; 793917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 794917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 795917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul opcode = computeOpcode (deltaLines, deltaAddress); 796917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 797917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((opcode & ~0xff) > 0) { 798917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitAdvancePc(deltaAddress); 799917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul deltaAddress = 0; 800917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul opcode = computeOpcode (deltaLines, deltaAddress); 801917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 802917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((opcode & ~0xff) > 0) { 803917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul emitAdvanceLine(deltaLines); 804917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul deltaLines = 0; 805917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul opcode = computeOpcode (deltaLines, deltaAddress); 806917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 807917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 808917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 809917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeByte(opcode); 810917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 811917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul line += deltaLines; 812917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul address += deltaAddress; 813917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 814917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotateTo != null || debugPrint != null) { 815917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul annotate(1, 816917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul String.format("%04x: line %d", address, line)); 817917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 818917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 819917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 820917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 821917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Computes a special opcode that will encode the given position change. 822917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * If the return value is > 0xff, then the request cannot be fulfilled. 823917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Essentially the same as described in "DWARF Debugging Format Version 3" 824917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * section 6.2.5.1. 825917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 826917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param deltaLines {@code >= DBG_LINE_BASE, <= DBG_LINE_BASE + 827917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * DBG_LINE_RANGE;} the line change to encode 828917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param deltaAddress {@code >= 0;} the address change to encode 829917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code <= 0xff} if in range, otherwise parameters are out 830917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * of range 831917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 832917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static int computeOpcode(int deltaLines, int deltaAddress) { 833917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (deltaLines < DBG_LINE_BASE 834917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul || deltaLines > (DBG_LINE_BASE + DBG_LINE_RANGE -1)) { 835917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 836917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException("Parameter out of range"); 837917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 838917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 839917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (deltaLines - DBG_LINE_BASE) 840917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul + (DBG_LINE_RANGE * deltaAddress) + DBG_FIRST_SPECIAL; 841917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 842917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 843917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 844917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Emits an {@link DebugInfoConstants#DBG_ADVANCE_LINE DBG_ADVANCE_LINE} 845917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * sequence. 846917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 847917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param deltaLines amount to change line number register by 848917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws IOException 849917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 850917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void emitAdvanceLine(int deltaLines) throws IOException { 851917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int mark = output.getCursor(); 852917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 853917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeByte(DBG_ADVANCE_LINE); 854917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeSignedLeb128(deltaLines); 855917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul line += deltaLines; 856917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 857917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotateTo != null || debugPrint != null) { 858917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul annotate(output.getCursor() - mark, 859917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul String.format("line = %d", line)); 860917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 861917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 862917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (DEBUG) { 863917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul System.err.printf("Emitting advance_line for %d\n", deltaLines); 864917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 865917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 866917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 867917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 868917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Emits an {@link DebugInfoConstants#DBG_ADVANCE_PC DBG_ADVANCE_PC} 869917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * sequence. 870917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 871917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param deltaAddress {@code >= 0;} amount to change program counter by 872917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws IOException 873917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 874917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void emitAdvancePc(int deltaAddress) throws IOException { 875917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int mark = output.getCursor(); 876917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 877917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeByte(DBG_ADVANCE_PC); 878917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeUnsignedLeb128(deltaAddress); 879917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul address += deltaAddress; 880917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 881917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotateTo != null || debugPrint != null) { 882917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul annotate(output.getCursor() - mark, 883917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul String.format("%04x: advance pc", address)); 884917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 885917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 886917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (DEBUG) { 887917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul System.err.printf("Emitting advance_pc for %d\n", deltaAddress); 888917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 889917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 890917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 891917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 892917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Emits an unsigned LEB128 value. 893917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 894917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param n {@code >= 0;} value to emit. Note that, although this can 895917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * represent integers larger than Integer.MAX_VALUE, we currently don't 896917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * allow that. 897917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws IOException 898917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 899917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void emitUnsignedLeb128(int n) throws IOException { 900917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // We'll never need the top end of the unsigned range anyway. 901917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (n < 0) { 902917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException( 903917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul "Signed value where unsigned required: " + n); 904917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 905917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 906917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeUnsignedLeb128(n); 907917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 908917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 909917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 910917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Emits the {@link DebugInfoConstants#DBG_END_SEQUENCE DBG_END_SEQUENCE} 911917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * bytecode. 912917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 913917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void emitEndSequence() { 914917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.writeByte(DBG_END_SEQUENCE); 915917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 916917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotateTo != null || debugPrint != null) { 917917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul annotate(1, "end sequence"); 918917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 919917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 920917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 921