Enable R8 support for using PCs in mapping file.

Bug: 37830524
Bug: 185884184
Bug: 186018416
Bug: 186015503
Change-Id: I6f0426acf536f17183b9a34f3795c750f90ec2a2
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 17aaf3e..74ed75a 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -321,8 +321,6 @@
   // TODO(b/138917494): Disable until we have numbers on potential performance penalties.
   public boolean enableRedundantConstNumberOptimization = false;
 
-  public boolean enablePcDebugInfoOutput = false;
-
   public String synthesizedClassPrefix = "";
 
   // Number of threads to use while processing the dex files.
@@ -1559,7 +1557,7 @@
   }
 
   public boolean canUseDexPcAsDebugInformation() {
-    return enablePcDebugInfoOutput && !debug && hasMinApi(AndroidApiLevel.O);
+    return !debug && hasMinApi(AndroidApiLevel.O);
   }
 
   public boolean isInterfaceMethodDesugaringEnabled() {
diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
index 3663ec2..da825d1 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -358,7 +358,7 @@
           if (code != null) {
             if (code.isDexCode() && doesContainPositions(code.asDexCode())) {
               if (appView.options().canUseDexPcAsDebugInformation() && methods.size() == 1) {
-                optimizeDexCodePositionsForPc(method, kotlinRemapper, mappedPositions);
+                optimizeDexCodePositionsForPc(method, appView, kotlinRemapper, mappedPositions);
               } else {
                 optimizeDexCodePositions(
                     method, appView, kotlinRemapper, mappedPositions, identityMapping);
@@ -761,6 +761,7 @@
 
   private static void optimizeDexCodePositionsForPc(
       DexEncodedMethod method,
+      AppView<?> appView,
       PositionRemapper positionRemapper,
       List<MappedPosition> mappedPositions) {
     // Do the actual processing for each method.
@@ -770,7 +771,9 @@
     Pair<Integer, Position> lastPosition = new Pair<>();
 
     DexDebugEventVisitor visitor =
-        new DexDebugPositionState(debugInfo.startLine, method.getReference()) {
+        new DexDebugPositionState(
+            debugInfo.startLine,
+            appView.graphLens().getOriginalMethodSignature(method.getReference())) {
           @Override
           public void visit(Default defaultEvent) {
             super.visit(defaultEvent);
diff --git a/src/test/examples/shaking1/print-mapping-dex.ref b/src/test/examples/shaking1/print-mapping-dex.ref
index 602e5f8..7ba8ee8 100644
--- a/src/test/examples/shaking1/print-mapping-dex.ref
+++ b/src/test/examples/shaking1/print-mapping-dex.ref
@@ -1,5 +1,5 @@
 shaking1.Shaking -> shaking1.Shaking:
 shaking1.Used -> a.a:
     java.lang.String method() -> a
-    1:1:void main(java.lang.String[]):8:8 -> main
-    1:1:void <init>(java.lang.String):12:12 -> <init>
+    0:16:void main(java.lang.String[]):8:8 -> main
+    0:3:void <init>(java.lang.String):12:12 -> <init>
diff --git a/src/test/java/com/android/tools/r8/R8TestBuilder.java b/src/test/java/com/android/tools/r8/R8TestBuilder.java
index 637a88b..5594bee 100644
--- a/src/test/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/R8TestBuilder.java
@@ -61,6 +61,8 @@
   private List<String> applyMappingMaps = new ArrayList<>();
   private final List<Path> features = new ArrayList<>();
 
+  private boolean createDefaultProguardMapConsumer = true;
+
   @Override
   R8TestCompileResult internalCompile(
       Builder builder, Consumer<InternalOptions> optionsConsumer, Supplier<AndroidApp> app)
@@ -69,21 +71,23 @@
       builder.addProguardConfiguration(keepRules, Origin.unknown());
     }
     builder.addMainDexRulesFiles(mainDexRulesFiles);
-    StringBuilder proguardMapBuilder = new StringBuilder();
     builder.setDisableTreeShaking(!enableTreeShaking);
     builder.setDisableMinification(!enableMinification);
-    builder.setProguardMapConsumer(
-        new StringConsumer() {
-          @Override
-          public void accept(String string, DiagnosticsHandler handler) {
-            proguardMapBuilder.append(string);
-          }
+    StringBuilder proguardMapBuilder = new StringBuilder();
+    if (createDefaultProguardMapConsumer) {
+      builder.setProguardMapConsumer(
+          new StringConsumer() {
+            @Override
+            public void accept(String string, DiagnosticsHandler handler) {
+              proguardMapBuilder.append(string);
+            }
 
-          @Override
-          public void finished(DiagnosticsHandler handler) {
-            // Nothing to do.
-          }
-        });
+            @Override
+            public void finished(DiagnosticsHandler handler) {
+              // Nothing to do.
+            }
+          });
+    }
 
     if (!applyMappingMaps.isEmpty()) {
       try {
@@ -118,7 +122,7 @@
             app.get(),
             box.proguardConfiguration,
             box.syntheticProguardRules,
-            proguardMapBuilder.toString(),
+            createDefaultProguardMapConsumer ? proguardMapBuilder.toString() : null,
             graphConsumer,
             minApiLevel,
             features);
@@ -661,4 +665,9 @@
     features.add(path);
     return self();
   }
+
+  public T noDefaultProguardMapConsumer() {
+    createDefaultProguardMapConsumer = false;
+    return self();
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index a6895ce..dcc3cee 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -1746,6 +1746,10 @@
     return AndroidApiLevel.K;
   }
 
+  public static AndroidApiLevel apiLevelWithPcAsLineNumberSupport() {
+    return AndroidApiLevel.O;
+  }
+
   public static boolean canUseJavaUtilObjects(TestParameters parameters) {
     return parameters.isCfRuntime()
         || parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.K);
diff --git a/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java b/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java
index 319327d..965b610 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java
@@ -3,23 +3,17 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.debug;
 
+import static org.junit.Assume.assumeTrue;
 
-import static com.android.tools.r8.naming.ClassNameMapper.MissingFileAction.MISSING_FILE_IS_EMPTY_MAP;
-
-import com.android.tools.r8.CompilationMode;
-import com.android.tools.r8.OutputMode;
-import com.android.tools.r8.R8Command;
-import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.R8TestCompileResult;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersBuilder;
 import com.android.tools.r8.debug.DebugTestBase.JUnit3Wrapper.Command;
-import com.android.tools.r8.debug.DebugTestConfig.RuntimeKind;
-import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.naming.ClassNameMapper.MissingFileAction;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
 import com.google.common.collect.ImmutableList;
-import java.nio.file.Path;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
 import java.util.List;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -30,85 +24,61 @@
 @RunWith(Parameterized.class)
 public class DebugInfoWhenInliningTest extends DebugTestBase {
 
-  public enum Config {
-    CF,
-    DEX_NO_FORCE_JUMBO,
-    DEX_FORCE_JUMBO
-  };
-
   private static final String CLASS_NAME = "Inlining1";
   private static final String SOURCE_FILE = "Inlining1.java";
 
   private DebugTestConfig makeConfig(
-      LineNumberOptimization lineNumberOptimization,
-      boolean writeProguardMap,
-      RuntimeKind runtimeKind)
-      throws Exception {
-    DebugTestConfig config = null;
-    Path outdir = temp.newFolder().toPath();
-    Path outjar = outdir.resolve("r8_compiled.jar");
-    R8Command.Builder builder =
-        R8Command.builder()
+      LineNumberOptimization lineNumberOptimization, boolean writeProguardMap) throws Exception {
+    R8TestCompileResult result =
+        testForR8(parameters.getBackend())
             .addProgramFiles(DEBUGGEE_JAR)
-            .setMode(CompilationMode.RELEASE)
-            .addProguardConfiguration(
-                ImmutableList.of(
-                    "-keep class "
-                        + CLASS_NAME
-                        + " { public static void main(java.lang.String[]); }"),
-                Origin.unknown())
-            .setDisableMinification(true)
-            .addProguardConfiguration(
-                ImmutableList.of("-keepattributes SourceFile,LineNumberTable"), Origin.unknown());
-
-    if (runtimeKind == RuntimeKind.DEX) {
-      AndroidApiLevel minSdk = ToolHelper.getMinApiLevelForDexVm();
-      builder
-          .setMinApiLevel(minSdk.getLevel())
-          .addLibraryFiles(ToolHelper.getAndroidJar(minSdk))
-          .setOutput(outjar, OutputMode.DexIndexed);
-      config = new DexDebugTestConfig(outjar);
-    } else {
-      assert (runtimeKind == RuntimeKind.CF);
-      builder
-          .setOutput(outjar, OutputMode.ClassFile)
-          .addLibraryFiles(ToolHelper.getJava8RuntimeJar());
-      config = new CfDebugTestConfig(outjar);
-    }
-
+            .addKeepMainRule(CLASS_NAME)
+            .noMinification()
+            .addKeepAttributeSourceFile()
+            .addKeepAttributeLineNumberTable()
+            .setMinApi(parameters.getApiLevel())
+            .addOptionsModification(
+                options -> {
+                  options.lineNumberOptimization = lineNumberOptimization;
+                  options.testing.forceJumboStringProcessing = forceJumboStringProcessing;
+                  // TODO(b/117848700): Can we make these tests neutral to inlining threshold?
+                  // Also CF needs improvements here.
+                  options.inliningInstructionLimit = parameters.isCfRuntime() ? 5 : 4;
+                })
+            .compile();
+    DebugTestConfig config = result.debugConfig();
     if (writeProguardMap) {
-      Path proguardMapPath = outdir.resolve("proguard.map");
-      builder.setProguardMapOutputPath(proguardMapPath);
-      config.setProguardMap(proguardMapPath, MISSING_FILE_IS_EMPTY_MAP);
+      config.setProguardMap(result.writeProguardMap(), MissingFileAction.MISSING_FILE_IS_EMPTY_MAP);
     }
-
-    ToolHelper.runR8(
-        builder.build(), options -> {
-          options.lineNumberOptimization = lineNumberOptimization;
-          options.testing.forceJumboStringProcessing = forceJumboStringProcessing;
-          // TODO(b/117848700): Can we make these tests neutral to inlining threshold?
-          // Also CF needs improvements here.
-          options.inliningInstructionLimit = runtimeKind == RuntimeKind.CF ? 5 : 4;
-        });
-
     return config;
   }
 
-  private boolean forceJumboStringProcessing;
-  private RuntimeKind runtimeKind;
+  private final TestParameters parameters;
+  private final boolean forceJumboStringProcessing;
 
-  @Parameters(name = "config: {0}")
-  public static Collection<Config> data() {
-    return Arrays.asList(Config.values());
+  @Parameters(name = "{0}, force-jumbo: {1}")
+  public static List<Object[]> data() {
+    return buildParameters(
+        TestParametersBuilder.builder().withAllRuntimesAndApiLevels().build(),
+        BooleanUtils.values());
   }
 
-  public DebugInfoWhenInliningTest(Config config) {
-    this.forceJumboStringProcessing = config == Config.DEX_FORCE_JUMBO;
-    this.runtimeKind = config == Config.CF ? RuntimeKind.CF : RuntimeKind.DEX;
+  public DebugInfoWhenInliningTest(TestParameters parameters, boolean forceJumboString) {
+    assumeTrue(!parameters.isCfRuntime() || !forceJumboString);
+    this.parameters = parameters;
+    this.forceJumboStringProcessing = forceJumboString;
+  }
+
+  private void assumeMappingIsNotToPCs() {
+    assumeTrue(
+        "Ignoring test when the line number table is removed.",
+        parameters.isCfRuntime()
+            || parameters.getApiLevel().isLessThan(apiLevelWithPcAsLineNumberSupport()));
   }
 
   @Test
   public void testEachLineNotOptimized() throws Throwable {
+    assumeMappingIsNotToPCs();
     // The reason why the not-optimized test contains half as many line numbers as the optimized
     // one:
     //
@@ -116,11 +86,12 @@
     // (innermost callee) the line numbers are actually 7, 7, 32, 32, ... but even if the positions
     // are emitted duplicated in the dex code, the debugger stops only when there's a change.
     int[] lineNumbers = {7, 32, 11, 7};
-    testEachLine(makeConfig(LineNumberOptimization.OFF, false, runtimeKind), lineNumbers);
+    testEachLine(makeConfig(LineNumberOptimization.OFF, false), lineNumbers);
   }
 
   @Test
   public void testEachLineNotOptimizedWithMap() throws Throwable {
+    assumeMappingIsNotToPCs();
     // The reason why the not-optimized test contains half as many line numbers as the optimized
     // one:
     //
@@ -128,17 +99,19 @@
     // (innermost callee) the line numbers are actually 7, 7, 32, 32, ... but even if the positions
     // are emitted duplicated in the dex code, the debugger stops only when there's a change.
     int[] lineNumbers = {7, 32, 11, 7};
-    testEachLine(makeConfig(LineNumberOptimization.OFF, true, runtimeKind), lineNumbers);
+    testEachLine(makeConfig(LineNumberOptimization.OFF, true), lineNumbers);
   }
 
   @Test
   public void testEachLineOptimized() throws Throwable {
+    assumeMappingIsNotToPCs();
     int[] lineNumbers = {1, 2, 3, 4, 5, 6, 7, 8};
-    testEachLine(makeConfig(LineNumberOptimization.ON, false, runtimeKind), lineNumbers);
+    testEachLine(makeConfig(LineNumberOptimization.ON, false), lineNumbers);
   }
 
   @Test
   public void testEachLineOptimizedWithMap() throws Throwable {
+    assumeMappingIsNotToPCs();
     int[] lineNumbers = {7, 7, 32, 32, 11, 11, 7, 7};
     List<List<SignatureAndLine>> inlineFramesList =
         ImmutableList.of(
@@ -170,8 +143,7 @@
                 new SignatureAndLine("void Inlining3.differentFileMultilevelInliningLevel2()", 7),
                 new SignatureAndLine("void Inlining2.differentFileMultilevelInliningLevel1()", 36),
                 new SignatureAndLine("void main(java.lang.String[])", 26)));
-    testEachLine(
-        makeConfig(LineNumberOptimization.ON, true, runtimeKind), lineNumbers, inlineFramesList);
+    testEachLine(makeConfig(LineNumberOptimization.ON, true), lineNumbers, inlineFramesList);
   }
 
   private void testEachLine(DebugTestConfig config, int[] lineNumbers) throws Throwable {
diff --git a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
index c34c633..d92d4ec 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
@@ -652,10 +652,23 @@
 
       String getObfuscatedMethodName(
           String originalClassName, String originalMethodName, String methodSignature);
+
+      boolean canUsePcForMissingLineNumberTable();
     }
 
     private class IdentityTranslator implements Translator {
 
+      private final boolean usePcForMissingLineTable;
+
+      public IdentityTranslator(boolean usePcForMissingLineNumberTable) {
+        this.usePcForMissingLineTable = usePcForMissingLineNumberTable;
+      }
+
+      @Override
+      public boolean canUsePcForMissingLineNumberTable() {
+        return usePcForMissingLineTable;
+      }
+
       @Override
       public String getOriginalClassName(String obfuscatedClassName) {
         return obfuscatedClassName;
@@ -709,7 +722,9 @@
     private class ClassNameMapperTranslator extends IdentityTranslator {
       private final ClassNameMapper classNameMapper;
 
-      public ClassNameMapperTranslator(ClassNameMapper classNameMapper) {
+      public ClassNameMapperTranslator(
+          ClassNameMapper classNameMapper, boolean usePcForMissingLineTable) {
+        super(usePcForMissingLineTable);
         this.classNameMapper = classNameMapper;
       }
 
@@ -872,9 +887,11 @@
       this.debuggeeClassName = debuggeeClassName;
       this.commandsQueue = new ArrayDeque<>(commands);
       if (classNameMapper == null) {
-        this.translator = new IdentityTranslator();
+        this.translator = new IdentityTranslator(config.shouldUsePcForMissingLineNumberTable());
       } else {
-        this.translator = new ClassNameMapperTranslator(classNameMapper);
+        this.translator =
+            new ClassNameMapperTranslator(
+                classNameMapper, config.shouldUsePcForMissingLineNumberTable());
       }
     }
 
@@ -1161,6 +1178,9 @@
           long startCodeIndex = reply.getNextValueAsLong();
           long endCodeIndex = reply.getNextValueAsLong();
           int lines = reply.getNextValueAsInt();
+          if (lines == 0 && translator.canUsePcForMissingLineNumberTable()) {
+            return (int) location.index;
+          }
           int line = -1;
           long previousLineCodeIndex = -1;
           for (int i = 0; i < lines; ++i) {
diff --git a/src/test/java/com/android/tools/r8/debug/DebugTestConfig.java b/src/test/java/com/android/tools/r8/debug/DebugTestConfig.java
index 1dc24d8..4ab22aa 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugTestConfig.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugTestConfig.java
@@ -25,6 +25,7 @@
 
   private Path proguardMap = null;
   private ClassNameMapper.MissingFileAction missingProguardMapAction;
+  private boolean usePcForMissingLineNumberTable = false;
 
   /** The expected runtime kind for the debuggee. */
   public abstract RuntimeKind getRuntimeKind();
@@ -37,6 +38,14 @@
     return getRuntimeKind() == RuntimeKind.DEX;
   }
 
+  public void allowUsingPcForMissingLineNumberTable() {
+    usePcForMissingLineNumberTable = true;
+  }
+
+  public boolean shouldUsePcForMissingLineNumberTable() {
+    return usePcForMissingLineNumberTable;
+  }
+
   /** Classpath paths for the debuggee. */
   public List<Path> getPaths() {
     return paths;
diff --git a/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java b/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java
index 35f24c9..d307de3 100644
--- a/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java
+++ b/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java
@@ -4,18 +4,14 @@
 package com.android.tools.r8.debug;
 
 import static com.android.tools.r8.naming.ClassNameMapper.MissingFileAction.MISSING_FILE_IS_EMPTY_MAP;
+import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationMode;
-import com.android.tools.r8.OutputMode;
-import com.android.tools.r8.R8Command;
-import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.debug.DebugTestConfig.RuntimeKind;
-import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.R8TestCompileResult;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersBuilder;
+import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
-import com.google.common.collect.ImmutableList;
-import java.nio.file.Path;
-import java.util.Collection;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -29,114 +25,96 @@
     20, 7, 8, 28, 29, 9, 21, 12, 13, 22, 16, 17
   };
   private static final int[] OPTIMIZED_LINE_NUMBERS = {1, 1, 2, 1, 2, 1, 2, 3, 2, 3, 4, 3};
+
   private static final String CLASS1 = "LineNumberOptimization1";
   private static final String CLASS2 = "LineNumberOptimization2";
   private static final String FILE1 = CLASS1 + ".java";
   private static final String FILE2 = CLASS2 + ".java";
   private static final String MAIN_SIGNATURE = "([Ljava/lang/String;)V";
 
-  private RuntimeKind runtimeKind;
+  private final TestParameters parameters;
 
   @Parameterized.Parameters(name = "{0}")
-  public static Collection<Object[]> setup() {
-    return ImmutableList.of(
-        new Object[] {"CF", RuntimeKind.CF}, new Object[] {"DEX", RuntimeKind.DEX});
+  public static TestParametersCollection setup() {
+    return TestParametersBuilder.builder().withAllRuntimesAndApiLevels().build();
   }
 
-  public LineNumberOptimizationTest(String name, RuntimeKind runtimeKind) {
-    this.runtimeKind = runtimeKind;
+  public LineNumberOptimizationTest(TestParameters parameters) {
+    this.parameters = parameters;
   }
 
-  private static DebugTestConfig makeConfig(
+  private DebugTestConfig makeConfig(
       LineNumberOptimization lineNumberOptimization,
       boolean writeProguardMap,
-      boolean dontOptimizeByEnablingDebug,
-      RuntimeKind runtimeKind)
+      boolean dontOptimizeByEnablingDebug)
       throws Exception {
-    Path outdir = temp.newFolder().toPath();
-    Path outjar = outdir.resolve("r8_compiled.jar");
 
-    R8Command.Builder builder =
-        R8Command.builder()
+    R8TestCompileResult result =
+        testForR8(parameters.getBackend())
             .addProgramFiles(DEBUGGEE_JAR)
+            .setMinApi(parameters.getApiLevel())
             .setMode(dontOptimizeByEnablingDebug ? CompilationMode.DEBUG : CompilationMode.RELEASE)
-            .setDisableTreeShaking(true)
-            .setDisableMinification(true)
-            .addProguardConfiguration(
-                ImmutableList.of("-keepattributes SourceFile,LineNumberTable"), Origin.unknown());
+            .noTreeShaking()
+            .noMinification()
+            .addKeepAttributeSourceFile()
+            .addKeepAttributeLineNumberTable()
+            .addOptionsModification(
+                options -> {
+                  if (!dontOptimizeByEnablingDebug) {
+                    options.lineNumberOptimization = lineNumberOptimization;
+                  }
+                  options.enableInlining = false;
+                })
+            .compile();
 
-    DebugTestConfig config = null;
-
-    if (runtimeKind == RuntimeKind.CF) {
-      builder
-          .setOutput(outjar, OutputMode.ClassFile)
-          .addLibraryFiles(ToolHelper.getJava8RuntimeJar());
-      config = new CfDebugTestConfig(outjar);
-    } else {
-      assert (runtimeKind == RuntimeKind.DEX);
-      AndroidApiLevel minSdk = ToolHelper.getMinApiLevelForDexVm();
-      builder
-          .setMinApiLevel(minSdk.getLevel())
-          .addLibraryFiles(ToolHelper.getAndroidJar(minSdk))
-          .setOutput(outjar, OutputMode.DexIndexed);
-      config = new D8DebugTestConfig();
-    }
-
-    config.addPaths(outjar);
+    DebugTestConfig config = result.debugConfig();
     if (writeProguardMap) {
-      Path proguardMapPath = outdir.resolve("proguard.map");
-      builder.setProguardMapOutputPath(proguardMapPath);
-      config.setProguardMap(proguardMapPath, MISSING_FILE_IS_EMPTY_MAP);
+      config.setProguardMap(result.writeProguardMap(), MISSING_FILE_IS_EMPTY_MAP);
     }
-
-    ToolHelper.runR8(
-        builder.build(),
-        options -> {
-          if (!dontOptimizeByEnablingDebug) {
-            options.lineNumberOptimization = lineNumberOptimization;
-          }
-          options.enableInlining = false;
-        });
-
     return config;
   }
 
+  private void assumeMappingIsNotToPCs() {
+    assumeTrue(
+        "Ignoring test when the line number table is removed.",
+        parameters.isCfRuntime()
+            || parameters.getApiLevel().isLessThan(apiLevelWithPcAsLineNumberSupport()));
+  }
+
   @Test
   public void testNotOptimized() throws Throwable {
-    testRelease(
-        makeConfig(LineNumberOptimization.OFF, false, false, runtimeKind), ORIGINAL_LINE_NUMBERS);
+    assumeMappingIsNotToPCs();
+    testRelease(makeConfig(LineNumberOptimization.OFF, false, false), ORIGINAL_LINE_NUMBERS);
   }
 
   @Test
   public void testNotOptimizedWithMap() throws Throwable {
-    testRelease(
-        makeConfig(LineNumberOptimization.OFF, true, false, runtimeKind), ORIGINAL_LINE_NUMBERS);
+    assumeMappingIsNotToPCs();
+    testRelease(makeConfig(LineNumberOptimization.OFF, true, false), ORIGINAL_LINE_NUMBERS);
   }
 
   @Test
   public void testNotOptimizedByEnablingDebug() throws Throwable {
-    testDebug(
-        makeConfig(LineNumberOptimization.OFF, false, true, runtimeKind),
-        ORIGINAL_LINE_NUMBERS_DEBUG);
+    testDebug(makeConfig(LineNumberOptimization.OFF, false, true), ORIGINAL_LINE_NUMBERS_DEBUG);
   }
 
   @Test
   public void testNotOptimizedByEnablingDebugWithMap() throws Throwable {
-    testDebug(
-        makeConfig(LineNumberOptimization.OFF, true, true, runtimeKind),
-        ORIGINAL_LINE_NUMBERS_DEBUG);
+    testDebug(makeConfig(LineNumberOptimization.OFF, true, true), ORIGINAL_LINE_NUMBERS_DEBUG);
   }
 
   @Test
   public void testOptimized() throws Throwable {
-    testRelease(
-        makeConfig(LineNumberOptimization.ON, false, false, runtimeKind), OPTIMIZED_LINE_NUMBERS);
+    assumeMappingIsNotToPCs();
+    DebugTestConfig config = makeConfig(LineNumberOptimization.ON, false, false);
+    config.allowUsingPcForMissingLineNumberTable();
+    testRelease(config, OPTIMIZED_LINE_NUMBERS);
   }
 
   @Test
   public void testOptimizedWithMap() throws Throwable {
-    testRelease(
-        makeConfig(LineNumberOptimization.ON, true, false, runtimeKind), ORIGINAL_LINE_NUMBERS);
+    assumeMappingIsNotToPCs();
+    testRelease(makeConfig(LineNumberOptimization.ON, true, false), ORIGINAL_LINE_NUMBERS);
   }
 
   private void testDebug(DebugTestConfig config, int[] lineNumbers) throws Throwable {
diff --git a/src/test/java/com/android/tools/r8/debug/R8DebugNonMinifiedProgramTestRunner.java b/src/test/java/com/android/tools/r8/debug/R8DebugNonMinifiedProgramTestRunner.java
index 3f61638..9771a28 100644
--- a/src/test/java/com/android/tools/r8/debug/R8DebugNonMinifiedProgramTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debug/R8DebugNonMinifiedProgramTestRunner.java
@@ -6,6 +6,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.R8FullTestBuilder;
 import com.android.tools.r8.R8TestCompileResult;
@@ -69,6 +70,13 @@
             });
   }
 
+  private void assumeMappingIsNotToPCs() {
+    assumeTrue(
+        "Ignoring test when the line number table is removed.",
+        parameters.isCfRuntime()
+            || parameters.getApiLevel().isLessThan(apiLevelWithPcAsLineNumberSupport()));
+  }
+
   @Test
   public void testDebugMode() throws Throwable {
     runTest(compiledDebug.apply(parameters.getBackend(), parameters.getApiLevel()));
@@ -76,6 +84,7 @@
 
   @Test
   public void testNoOptimizationAndNoMinification() throws Throwable {
+    assumeMappingIsNotToPCs();
     runTest(compiledNoOptNoMinify.apply(parameters.getBackend(), parameters.getApiLevel()));
   }
 
diff --git a/src/test/java/com/android/tools/r8/debuginfo/CanonicalizeWithInline.java b/src/test/java/com/android/tools/r8/debuginfo/CanonicalizeWithInline.java
index 395f29f..73aff7f 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/CanonicalizeWithInline.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/CanonicalizeWithInline.java
@@ -8,17 +8,35 @@
 import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8TestCompileResult;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.dex.DexParser;
 import com.android.tools.r8.dex.DexSection;
+import com.android.tools.r8.utils.AndroidApiLevel;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import org.junit.Assert;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
+@RunWith(Parameterized.class)
 public class CanonicalizeWithInline extends TestBase {
 
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withNoneRuntime().build();
+  }
+
+  private final TestParameters parameters;
+
+  public CanonicalizeWithInline(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
   private int getNumberOfDebugInfos(Path file) throws IOException {
     DexSection[] dexSections = DexParser.parseMapFrom(file);
     for (DexSection dexSection : dexSections) {
@@ -36,6 +54,7 @@
 
     R8TestCompileResult result =
         testForR8(Backend.DEX)
+            .setMinApi(AndroidApiLevel.B)
             .addProgramClasses(clazzA, clazzB)
             .addKeepRules(
                 "-keepattributes SourceFile,LineNumberTable",
diff --git a/src/test/java/com/android/tools/r8/debuginfo/DexPcWithDebugInfoForOverloadedMethodsTestRunner.java b/src/test/java/com/android/tools/r8/debuginfo/DexPcWithDebugInfoForOverloadedMethodsTestRunner.java
index 18913cc..d6e30b4 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/DexPcWithDebugInfoForOverloadedMethodsTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/DexPcWithDebugInfoForOverloadedMethodsTestRunner.java
@@ -70,11 +70,6 @@
         .addKeepAttributeLineNumberTable()
         .addKeepAttributes(ProguardKeepAttributes.SOURCE_FILE)
         .setMinApi(parameters.getApiLevel())
-        .addOptionsModification(
-            internalOptions -> {
-              // TODO(b/37830524): Remove when activated.
-              internalOptions.enablePcDebugInfoOutput = true;
-            })
         .run(parameters.getRuntime(), MAIN)
         .assertFailureWithErrorThatMatches(containsString(EXPECTED))
         .inspectOriginalStackTrace(
diff --git a/src/test/java/com/android/tools/r8/debuginfo/EnsureNoDebugInfoEmittedForPcOnlyTestRunner.java b/src/test/java/com/android/tools/r8/debuginfo/EnsureNoDebugInfoEmittedForPcOnlyTestRunner.java
index 270e7cd..c2f1811 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/EnsureNoDebugInfoEmittedForPcOnlyTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/EnsureNoDebugInfoEmittedForPcOnlyTestRunner.java
@@ -19,7 +19,6 @@
 import com.android.tools.r8.naming.retrace.StackTrace;
 import com.android.tools.r8.naming.retrace.StackTrace.StackTraceLine;
 import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
@@ -53,11 +52,6 @@
     return parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.O);
   }
 
-  // TODO(b/37830524): Remove when activated.
-  private void enablePcDebugInfoOutput(InternalOptions options) {
-    options.enablePcDebugInfoOutput = true;
-  }
-
   @Test
   public void testD8Debug() throws Exception {
     testForD8(parameters.getBackend())
@@ -65,7 +59,6 @@
         .addProgramClasses(MAIN)
         .setMinApi(parameters.getApiLevel())
         .internalEnableMappingOutput()
-        .addOptionsModification(this::enablePcDebugInfoOutput)
         .run(parameters.getRuntime(), MAIN)
         // For a debug build we always expect the output to have actual line information.
         .inspectFailure(this::checkHasLineNumberInfo)
@@ -79,7 +72,6 @@
         .addProgramClasses(MAIN)
         .setMinApi(parameters.getApiLevel())
         .internalEnableMappingOutput()
-        .addOptionsModification(this::enablePcDebugInfoOutput)
         .run(parameters.getRuntime(), MAIN)
         .inspectFailure(
             inspector -> {
@@ -98,7 +90,6 @@
         .release()
         .addProgramClasses(MAIN)
         .setMinApi(parameters.getApiLevel())
-        .addOptionsModification(this::enablePcDebugInfoOutput)
         .run(parameters.getRuntime(), MAIN)
         // If compiling without a map output actual debug info should also be retained. Otherwise
         // there would not be any way to obtain the actual lines.
@@ -114,7 +105,6 @@
         .addKeepMainRule(MAIN)
         .addKeepAttributeLineNumberTable()
         .setMinApi(parameters.getApiLevel())
-        .addOptionsModification(this::enablePcDebugInfoOutput)
         .run(parameters.getRuntime(), MAIN)
         .inspectOriginalStackTrace(
             (stackTrace, inspector) -> {
diff --git a/src/test/java/com/android/tools/r8/debuginfo/InliningWithoutPositionsTestRunner.java b/src/test/java/com/android/tools/r8/debuginfo/InliningWithoutPositionsTestRunner.java
index 3e60ef1..9efecb4 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/InliningWithoutPositionsTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/InliningWithoutPositionsTestRunner.java
@@ -6,25 +6,22 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.CompilationMode;
-import com.android.tools.r8.OutputMode;
-import com.android.tools.r8.R8Command;
+import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersBuilder;
 import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
-import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.debuginfo.InliningWithoutPositionsTestSourceDump.Location;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.naming.ClassNamingForNameMapper;
 import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRange;
 import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRangesOfName;
 import com.android.tools.r8.naming.Range;
-import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.AndroidApiLevel;
-import com.google.common.collect.ImmutableList;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
@@ -39,12 +36,7 @@
 import org.junit.runners.Parameterized.Parameters;
 
 @RunWith(Parameterized.class)
-public class InliningWithoutPositionsTestRunner {
-
-  enum Backend {
-    CF,
-    DEX
-  }
+public class InliningWithoutPositionsTestRunner extends TestBase {
 
   private static final String TEST_CLASS = "InliningWithoutPositionsTestSource";
   private static final String TEST_PACKAGE = "com.android.tools.r8.debuginfo";
@@ -52,7 +44,7 @@
 
   @ClassRule public static TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
 
-  private final Backend backend;
+  private final TestParameters parameters;
   private final boolean mainPos;
   private final boolean foo1Pos;
   private final boolean barPos;
@@ -62,13 +54,14 @@
   @Parameters(name = "{0}: main/foo1/bar/foo2 positions: {1}/{2}/{3}/{4}, throwLocation: {5}")
   public static Collection<Object[]> data() {
     List<Object[]> testCases = new ArrayList<>();
-    for (Backend backend : Backend.values()) {
+    for (TestParameters parameters :
+        TestParametersBuilder.builder().withAllRuntimes().withApiLevel(AndroidApiLevel.B).build()) {
     for (int i = 0; i < 16; ++i) {
       for (Location throwLocation : Location.values()) {
         if (throwLocation != Location.MAIN) {
             testCases.add(
                 new Object[] {
-                  backend, (i & 1) != 0, (i & 2) != 0, (i & 4) != 0, (i & 8) != 0, throwLocation
+                  parameters, (i & 1) != 0, (i & 2) != 0, (i & 4) != 0, (i & 8) != 0, throwLocation
                 });
         }
       }
@@ -78,13 +71,13 @@
   }
 
   public InliningWithoutPositionsTestRunner(
-      Backend backend,
+      TestParameters parameters,
       boolean mainPos,
       boolean foo1Pos,
       boolean barPos,
       boolean foo2Pos,
       Location throwLocation) {
-    this.backend = backend;
+    this.parameters = parameters;
     this.mainPos = mainPos;
     this.foo1Pos = foo1Pos;
     this.barPos = barPos;
@@ -97,54 +90,23 @@
     // See InliningWithoutPositionsTestSourceDump for the code compiled here.
     Path testClassDir = temp.newFolder().toPath();
     Path testClassPath = testClassDir.resolve(TEST_CLASS + ".class");
-    Path outputPath = temp.newFolder().toPath();
-
     Files.write(
         testClassPath,
         InliningWithoutPositionsTestSourceDump.dump(
             mainPos, foo1Pos, barPos, foo2Pos, throwLocation));
 
-    Path proguardMapPath = testClassDir.resolve("proguard.map");
-
-    R8Command.Builder builder =
-        R8Command.builder()
+    R8TestRunResult result =
+        testForR8(parameters.getBackend())
+            .setMinApi(parameters.getApiLevel())
             .addProgramFiles(testClassPath)
             .setMode(CompilationMode.RELEASE)
-            .setProguardMapOutputPath(proguardMapPath);
-    if (backend == Backend.DEX) {
-      AndroidApiLevel minSdk = ToolHelper.getMinApiLevelForDexVm();
-      builder
-          .setMinApiLevel(minSdk.getLevel())
-          .addLibraryFiles(ToolHelper.getAndroidJar(minSdk))
-          .setOutput(outputPath, OutputMode.DexIndexed);
-    } else {
-      assert (backend == Backend.CF);
-      builder
-          .addLibraryFiles(ToolHelper.getJava8RuntimeJar())
-          .setOutput(outputPath, OutputMode.ClassFile);
-    }
-    builder
-        .addProguardConfiguration(
-            ImmutableList.of(
-                "-keep class " + MAIN_CLASS + " { public static void main(java.lang.String[]); }"),
-            Origin.unknown())
-        .setDisableMinification(true)
-        .addProguardConfiguration(
-            ImmutableList.of("-keepattributes SourceFile,LineNumberTable"), Origin.unknown());
-
-    ToolHelper.runR8(builder.build(), options -> options.inliningInstructionLimit = 40);
-
-    ProcessResult result;
-    if (backend == Backend.DEX) {
-      ArtCommandBuilder artCommandBuilder = new ArtCommandBuilder();
-      artCommandBuilder.appendClasspath(outputPath.resolve("classes.dex").toString());
-      artCommandBuilder.setMainClass(MAIN_CLASS);
-
-      result = ToolHelper.runArtRaw(artCommandBuilder);
-    } else {
-      result = ToolHelper.runJava(outputPath, MAIN_CLASS);
-    }
-    assertNotEquals(result.exitCode, 0);
+            .addKeepMainRule(MAIN_CLASS)
+            .noMinification()
+            .addKeepAttributeSourceFile()
+            .addKeepAttributeLineNumberTable()
+            .addOptionsModification(options -> options.inliningInstructionLimit = 40)
+            .run(parameters.getRuntime(), MAIN_CLASS)
+            .assertFailure();
 
     // Verify stack trace.
     // result.stderr looks like this:
@@ -152,7 +114,7 @@
     //     Exception in thread "main" java.lang.RuntimeException: <FOO1-exception>
     //       at
     // com.android.tools.r8.debuginfo.InliningWithoutPositionsTestSource.main(InliningWithoutPositionsTestSource.java:1)
-    String[] lines = result.stderr.split("\n");
+    String[] lines = result.getStdErr().split("\n");
 
     // The line containing 'java.lang.RuntimeException' should contain the expected message, which
     // is "LOCATIONCODE-exception>"
@@ -189,7 +151,7 @@
     //     1:1:void bar():0:0 -> main
     //     1:1:void foo(boolean):0 -> main
     //     1:1:void main(java.lang.String[]):0 -> main
-    ClassNameMapper mapper = ClassNameMapper.mapperFromFile(proguardMapPath);
+    ClassNameMapper mapper = ClassNameMapper.mapperFromString(result.proguardMap());
     assertNotNull(mapper);
 
     ClassNamingForNameMapper classNaming = mapper.getClassNaming(TEST_PACKAGE + "." + TEST_CLASS);
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/SyntheticInitClassPositionTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/SyntheticInitClassPositionTest.java
index 1dc11c0..fe6ef20 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/SyntheticInitClassPositionTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/SyntheticInitClassPositionTest.java
@@ -52,7 +52,6 @@
         .addKeepAttributeLineNumberTable()
         .addKeepAttributeSourceFile()
         .setMinApi(parameters.getApiLevel())
-        .compile()
         .run(parameters.getRuntime(), Main.class)
         .assertFailureWithErrorThatThrows(ExceptionInInitializerError.class)
         .inspectStackTrace(stackTrace -> assertThat(stackTrace, isSame(expectedStackTrace)));
diff --git a/src/test/java/com/android/tools/r8/naming/retrace/StackTrace.java b/src/test/java/com/android/tools/r8/naming/retrace/StackTrace.java
index 3b0b052..8dde075 100644
--- a/src/test/java/com/android/tools/r8/naming/retrace/StackTrace.java
+++ b/src/test/java/com/android/tools/r8/naming/retrace/StackTrace.java
@@ -23,6 +23,7 @@
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
 import org.hamcrest.TypeSafeMatcher;
@@ -284,11 +285,13 @@
     return new StackTrace(stackTraceLines, stderr);
   }
 
+  private static List<StackTraceLine> internalConvert(Stream<String> lines) {
+    return lines.map(StackTraceLine::parse).collect(Collectors.toList());
+  }
+
   private static List<StackTraceLine> internalExtractFromJvm(String stderr) {
-    return StringUtils.splitLines(stderr).stream()
-        .filter(s -> s.startsWith(TAB_AT_PREFIX))
-        .map(StackTraceLine::parse)
-        .collect(Collectors.toList());
+    return internalConvert(
+        StringUtils.splitLines(stderr).stream().filter(s -> s.startsWith(TAB_AT_PREFIX)));
   }
 
   public static StackTrace extractFromJvm(String stderr) {
@@ -324,7 +327,7 @@
             .build(),
         allowExperimentalMapping);
     // Keep the original stderr in the retraced stacktrace.
-    return new StackTrace(internalExtractFromJvm(StringUtils.lines(box.result)), originalStderr);
+    return new StackTrace(internalConvert(box.result.stream()), originalStderr);
   }
 
   public StackTrace filter(Predicate<StackTraceLine> filter) {
diff --git a/src/test/java/com/android/tools/r8/naming/retraceproguard/DesugarStaticInterfaceMethodsRetraceTest.java b/src/test/java/com/android/tools/r8/naming/retraceproguard/DesugarStaticInterfaceMethodsRetraceTest.java
index 47240a5..04f722d 100644
--- a/src/test/java/com/android/tools/r8/naming/retraceproguard/DesugarStaticInterfaceMethodsRetraceTest.java
+++ b/src/test/java/com/android/tools/r8/naming/retraceproguard/DesugarStaticInterfaceMethodsRetraceTest.java
@@ -6,6 +6,7 @@
 
 import static com.android.tools.r8.naming.retraceproguard.StackTrace.isSameExceptForFileName;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.NeverInline;
@@ -51,6 +52,9 @@
 
   @Test
   public void testSourceFileAndLineNumberTable() throws Exception {
+    // TODO(b/186015503): This test fails when mapping via PCs.
+    //  also the test should be updated to use TestParameters and api levels.
+    assumeTrue("b/186015503", !backend.isDex() || mode != CompilationMode.RELEASE);
     runTest(
         ImmutableList.of("-keepattributes SourceFile,LineNumberTable"),
         // For the desugaring to companion classes the retrace stacktrace is still the same
diff --git a/src/test/java/com/android/tools/r8/regress/b150400371/DebuginfoForInlineFrameRegressionTest.java b/src/test/java/com/android/tools/r8/regress/b150400371/DebuginfoForInlineFrameRegressionTest.java
index 68c1d36..90617f7 100644
--- a/src/test/java/com/android/tools/r8/regress/b150400371/DebuginfoForInlineFrameRegressionTest.java
+++ b/src/test/java/com/android/tools/r8/regress/b150400371/DebuginfoForInlineFrameRegressionTest.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.regress.b150400371;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
@@ -44,8 +45,12 @@
             (inspector) -> {
               MethodSubject main =
                   inspector.method(InlineInto.class.getDeclaredMethod("main", String[].class));
-              IntSet lines = new IntArraySet(main.getLineNumberTable().getLines());
-              assertEquals(2, lines.size());
+              if (parameters.getApiLevel().isLessThan(apiLevelWithPcAsLineNumberSupport())) {
+                IntSet lines = new IntArraySet(main.getLineNumberTable().getLines());
+                assertEquals(2, lines.size());
+              } else {
+                assertNull(main.getLineNumberTable());
+              }
             });
   }
 
diff --git a/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionInSameFileRetraceTests.java b/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionInSameFileRetraceTests.java
index dfe1002..24fad30 100644
--- a/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionInSameFileRetraceTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionInSameFileRetraceTests.java
@@ -47,7 +47,11 @@
   public static List<Object[]> data() {
     // TODO(b/141817471): Extend with compilation modes.
     return buildParameters(
-        getTestParameters().withAllRuntimesAndApiLevels().build(),
+        getTestParameters()
+            .withAllRuntimes()
+            // TODO(b/186018416): Update to support tests retracing with PC mappings.
+            .withApiLevelsEndingAtExcluding(apiLevelWithPcAsLineNumberSupport())
+            .build(),
         getKotlinTestParameters().withAllCompilersAndTargetVersions().build());
   }
 
diff --git a/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionRetraceTest.java b/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionRetraceTest.java
index 232c1f5..ed842eb 100644
--- a/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionRetraceTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionRetraceTest.java
@@ -47,7 +47,11 @@
   public static List<Object[]> data() {
     // TODO(b/141817471): Extend with compilation modes.
     return buildParameters(
-        getTestParameters().withAllRuntimesAndApiLevels().build(),
+        getTestParameters()
+            .withAllRuntimes()
+            // TODO(b/186018416): Update to support tests retracing with PC mappings.
+            .withApiLevelsEndingAtExcluding(apiLevelWithPcAsLineNumberSupport())
+            .build(),
         getKotlinTestParameters().withAllCompilersAndTargetVersions().build());
   }
 
diff --git a/src/test/java/com/android/tools/r8/shaking/attributes/KeepAttributesTest.java b/src/test/java/com/android/tools/r8/shaking/attributes/KeepAttributesTest.java
index a314e96..82bcb21 100644
--- a/src/test/java/com/android/tools/r8/shaking/attributes/KeepAttributesTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/attributes/KeepAttributesTest.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.shaking.attributes;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -62,6 +63,11 @@
     assertFalse(mainMethod.hasLocalVariableTable());
   }
 
+  private boolean doesNotHavePcSupport() {
+    return parameters.isCfRuntime()
+        || parameters.getApiLevel().isLessThan(apiLevelWithPcAsLineNumberSupport());
+  }
+
   @Test
   public void keepLineNumberTable()
       throws CompilationFailedException, IOException, ExecutionException {
@@ -69,7 +75,7 @@
         "-keepattributes " + ProguardKeepAttributes.LINE_NUMBER_TABLE
     );
     MethodSubject mainMethod = compileRunAndGetMain(keepRules, CompilationMode.RELEASE);
-    assertTrue(mainMethod.hasLineNumberTable());
+    assertEquals(doesNotHavePcSupport(), mainMethod.hasLineNumberTable());
     assertFalse(mainMethod.hasLocalVariableTable());
   }
 
@@ -83,7 +89,7 @@
             + ProguardKeepAttributes.LOCAL_VARIABLE_TABLE
     );
     MethodSubject mainMethod = compileRunAndGetMain(keepRules, CompilationMode.RELEASE);
-    assertTrue(mainMethod.hasLineNumberTable());
+    assertEquals(doesNotHavePcSupport(), mainMethod.hasLineNumberTable());
     // Locals are never included in release builds.
     assertFalse(mainMethod.hasLocalVariableTable());
   }