Add line numbers to output of '--print-mapping'.
Bug:
Change-Id: I181011af558adb0d1feef7fe598df76b0d584603
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 11d9a23..7766a94 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -37,6 +37,10 @@
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
import com.android.tools.r8.utils.InternalOptions;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.ListIterator;
public class DexEncodedMethod extends KeyedDexItem<DexMethod> {
@@ -88,6 +92,100 @@
private CompilationState compilationState = CompilationState.NOT_PROCESSED;
private OptimizationInfo optimizationInfo = DefaultOptimizationInfo.DEFAULT;
+ // Encodes a mapping from a range of original to emitted line numbers:
+ // (originalFirst, originalFirst + length) -> (emittedFirst, emittedFirst + length)
+ public static class DebugPositionRange {
+ public final int originalFirst;
+ public final int emittedFirst;
+ private final int length; // 0 for a single line.
+
+ // The original source line numbers are compressed to a tight range
+ public DebugPositionRange(int originalFirst, int emittedFirst, int length) {
+ assert originalFirst >= 0 && emittedFirst >= 0 && length >= 0;
+ this.originalFirst = originalFirst;
+ this.length = length;
+ this.emittedFirst = emittedFirst;
+ }
+
+ public int getOriginalLast() {
+ return originalFirst + length;
+ }
+
+ public int getEmittedLast() {
+ return emittedFirst + length;
+ }
+ }
+
+ public static class DebugPositionRangeList {
+ // Build sorted list of DebugPositionRange objects (sorted by emitted position) from single
+ // line-to-line mappings
+ public static class Builder {
+ private static class Mapping implements Comparable<Mapping> {
+ public int original;
+ public int emitted;
+
+ Mapping(int original, int emitted) {
+ this.original = original;
+ this.emitted = emitted;
+ }
+
+ @Override
+ public int compareTo(Mapping rhs) {
+ if (emitted == rhs.emitted) {
+ return original - rhs.original;
+ } else {
+ return emitted - rhs.emitted;
+ }
+ }
+ };
+
+ public void add(int original, int emitted) {
+ list.add(new Mapping(original, emitted));
+ }
+
+ public List<DebugPositionRange> build() {
+ if (list.isEmpty()) {
+ return Collections.<DebugPositionRange>emptyList();
+ }
+
+ Collections.sort(list);
+
+ List<DebugPositionRange> result = new ArrayList<>();
+
+ ListIterator<Mapping> iterator = list.listIterator();
+ Mapping pendingMapping = iterator.next();
+ int pendingLength = 0;
+ while (iterator.hasNext()) {
+ Mapping mapping = iterator.next();
+ // Try to merge with last interval.
+ int originalDiff = mapping.original - (pendingMapping.original + pendingLength);
+ int emittedDiff = mapping.emitted - (pendingMapping.emitted + pendingLength);
+ if (originalDiff == 0 && emittedDiff == 0) {
+ // Skip duplicates.
+ continue;
+ }
+ assert emittedDiff > 0;
+ if (originalDiff == emittedDiff) {
+ pendingLength = mapping.original - pendingMapping.original;
+ } else {
+ result.add(
+ new DebugPositionRange(
+ pendingMapping.original, pendingMapping.emitted, pendingLength));
+ pendingMapping = mapping;
+ pendingLength = 0;
+ }
+ }
+ result.add(
+ new DebugPositionRange(pendingMapping.original, pendingMapping.emitted, pendingLength));
+ return Collections.unmodifiableList(result);
+ }
+
+ private List<Mapping> list = new ArrayList<>();
+ }
+ }
+
+ public List<DebugPositionRange> debugPositionRangeList = null;
+
public DexEncodedMethod(DexMethod method, DexAccessFlags accessFlags,
DexAnnotationSet annotations, DexAnnotationSetRefList parameterAnnotations, Code code) {
this.method = method;
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
index 923dbf1..3bdeefa 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
@@ -38,6 +38,7 @@
import com.android.tools.r8.graph.DexCode.TryHandler;
import com.android.tools.r8.graph.DexCode.TryHandler.TypeAddrPair;
import com.android.tools.r8.graph.DexDebugEventBuilder;
+import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
@@ -180,8 +181,14 @@
List<Instruction> dexInstructions = new ArrayList<>(numberOfInstructions);
int instructionOffset = 0;
InstructionIterator instructionIterator = ir.instructionIterator();
+ DexEncodedMethod.DebugPositionRangeList.Builder debugPositionListBuilder =
+ new DexEncodedMethod.DebugPositionRangeList.Builder();
while (instructionIterator.hasNext()) {
com.android.tools.r8.ir.code.Instruction ir = instructionIterator.next();
+ if (ir.isDebugPosition()) {
+ int line = ir.asDebugPosition().line;
+ debugPositionListBuilder.add(line, line);
+ }
Info info = getInfo(ir);
int previousInstructionCount = dexInstructions.size();
info.addInstructions(this, dexInstructions);
@@ -195,6 +202,8 @@
}
}
+ ir.method.debugPositionRangeList = debugPositionListBuilder.build();
+
// Compute switch payloads.
for (SwitchPayloadInfo switchPayloadInfo : switchPayloadInfos) {
// Align payloads at even addresses.
diff --git a/src/main/java/com/android/tools/r8/naming/MinifiedNameMapPrinter.java b/src/main/java/com/android/tools/r8/naming/MinifiedNameMapPrinter.java
index 14dd50e..e9ec08c 100644
--- a/src/main/java/com/android/tools/r8/naming/MinifiedNameMapPrinter.java
+++ b/src/main/java/com/android/tools/r8/naming/MinifiedNameMapPrinter.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexEncodedMethod.DebugPositionRange;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
@@ -84,16 +85,38 @@
}
}
+ private void writeMethod(
+ MethodSignature signature,
+ String renamed,
+ PrintStream out,
+ DexEncodedMethod.DebugPositionRange range) {
+ out.print(" ");
+ if (range != null) {
+ out.printf("%d:%d:", range.emittedFirst, range.getEmittedLast());
+ }
+ out.print(signature);
+ if (range != null && range.originalFirst != range.emittedFirst) {
+ out.printf(":%d:%d", range.originalFirst, range.getOriginalLast());
+ }
+ out.print(" -> ");
+ out.println(renamed);
+ }
+
private void write(DexEncodedMethod[] methods, PrintStream out) {
for (DexEncodedMethod encodedMethod : methods) {
DexMethod method = encodedMethod.method;
DexString renamed = namingLens.lookupName(method);
if (renamed != method.name) {
MethodSignature signature = MethodSignature.fromDexMethod(method);
- out.print(" ");
- out.print(signature);
- out.print(" -> ");
- out.println(renamed.toSourceString());
+ String renamedSourceString = renamed.toSourceString();
+ if (encodedMethod.debugPositionRangeList == null
+ || encodedMethod.debugPositionRangeList.isEmpty()) {
+ writeMethod(signature, renamedSourceString, out, null);
+ } else {
+ for (DebugPositionRange range : encodedMethod.debugPositionRangeList) {
+ writeMethod(signature, renamedSourceString, out, range);
+ }
+ }
}
}
}