Reapply "Update marker API with access to more of the marker information"
This reverts commit bc4cbbe7dc15e8aa7af43f2e9213e1044bcdf556.
Change-Id: I113bde58038ef9f314070c1b19ac4e2b17de8b47
diff --git a/src/main/java/com/android/tools/r8/MarkerInfo.java b/src/main/java/com/android/tools/r8/MarkerInfo.java
index 32578c1..6c5925d 100644
--- a/src/main/java/com/android/tools/r8/MarkerInfo.java
+++ b/src/main/java/com/android/tools/r8/MarkerInfo.java
@@ -10,6 +10,9 @@
   /** Get the tool that has generated the marker. */
   String getTool();
 
+  /** Get the version of the tool that has generated the marker. */
+  String getVersion();
+
   /** True of the generating tool was the R8 compiler. */
   boolean isR8();
 
@@ -22,6 +25,30 @@
   /** Get the min-api specified by the marker, or -1 if not defined. */
   int getMinApi();
 
+  /** True if the "backend" information is present or can be inferred for the tool. */
+  boolean hasBackend();
+
+  /** True if the tool is known to be targeting class files as backend output. */
+  boolean isBackendClassFiles();
+
+  /** True if the tool is known to be targeting DEX as backend output. */
+  boolean isBackendDexFiles();
+
+  /** True if the tool has a known compilation mode (i.e., release or debug). */
+  boolean hasCompilationMode();
+
+  /** True if the tool has a known compilation mode and the mode is "debug". */
+  boolean isCompilationModeDebug();
+
+  /** True if the tool has a known compilation mode and the mode is "release". */
+  boolean isCompilationModeRelease();
+
+  /** True if the tool is R8 using compatibility mode. */
+  boolean isR8ModeCompatibility();
+
+  /** True if the tool is R8 using full mode (e.g., not in compatibility mode). */
+  boolean isR8ModeFull();
+
   /**
    * Get the raw encoding of the marker used by the compilers.
    *
diff --git a/src/main/java/com/android/tools/r8/dex/Marker.java b/src/main/java/com/android/tools/r8/dex/Marker.java
index c507995..f0bd037 100644
--- a/src/main/java/com/android/tools/r8/dex/Marker.java
+++ b/src/main/java/com/android/tools/r8/dex/Marker.java
@@ -152,8 +152,15 @@
     return this;
   }
 
+  public boolean hasCompilationMode() {
+    return jsonObject.has(COMPILATION_MODE);
+  }
+
   public String getCompilationMode() {
-    return jsonObject.get(COMPILATION_MODE).getAsString();
+    if (hasCompilationMode()) {
+      return jsonObject.get(COMPILATION_MODE).getAsString();
+    }
+    return null;
   }
 
   public Marker setCompilationMode(CompilationMode mode) {
@@ -167,13 +174,23 @@
   }
 
   public String getBackend() {
-    if (!hasBackend()) {
-      // Before adding backend we would always compile to dex if min-api was specified.
-      return hasMinApi()
-          ? StringUtils.toLowerCase(Backend.DEX.name())
-          : StringUtils.toLowerCase(Backend.CF.name());
+    if (hasBackend()) {
+      return jsonObject.get(BACKEND).getAsString();
     }
-    return jsonObject.get(BACKEND).getAsString();
+    switch (tool) {
+      case D8:
+      case L8:
+      case R8:
+        // Before adding backend we would always compile to dex if min-api was specified.
+        // This is not fully true for D8 which had a window from aug to oct 2020 where the min-api
+        // was added for CF builds too. However, that was (and still is) only used internally and
+        // those markers should be be found in the wild.
+        return hasMinApi()
+            ? StringUtils.toLowerCase(Backend.DEX.name())
+            : StringUtils.toLowerCase(Backend.CF.name());
+      default:
+        return null;
+    }
   }
 
   public boolean isCfBackend() {
diff --git a/src/main/java/com/android/tools/r8/utils/MarkerInfoImpl.java b/src/main/java/com/android/tools/r8/utils/MarkerInfoImpl.java
index bcbbeeb..5b6fe01 100644
--- a/src/main/java/com/android/tools/r8/utils/MarkerInfoImpl.java
+++ b/src/main/java/com/android/tools/r8/utils/MarkerInfoImpl.java
@@ -19,6 +19,11 @@
   }
 
   @Override
+  public String getVersion() {
+    return marker.getVersion();
+  }
+
+  @Override
   public String getTool() {
     return marker.getTool().toString();
   }
@@ -44,6 +49,46 @@
   }
 
   @Override
+  public boolean hasBackend() {
+    return marker.getBackend() != null;
+  }
+
+  @Override
+  public boolean isBackendClassFiles() {
+    return "cf".equals(marker.getBackend());
+  }
+
+  @Override
+  public boolean isBackendDexFiles() {
+    return "dex".equals(marker.getBackend());
+  }
+
+  @Override
+  public boolean hasCompilationMode() {
+    return marker.hasCompilationMode();
+  }
+
+  @Override
+  public boolean isCompilationModeDebug() {
+    return "debug".equals(marker.getCompilationMode());
+  }
+
+  @Override
+  public boolean isCompilationModeRelease() {
+    return "release".equals(marker.getCompilationMode());
+  }
+
+  @Override
+  public boolean isR8ModeCompatibility() {
+    return isR8() && "compatibility".equals(marker.getR8Mode());
+  }
+
+  @Override
+  public boolean isR8ModeFull() {
+    return isR8() && "full".equals(marker.getR8Mode());
+  }
+
+  @Override
   public String getRawEncoding() {
     return marker.toString();
   }
diff --git a/src/test/java/com/android/tools/r8/compilerapi/extractmarker/ExtractMarkerApiTest.java b/src/test/java/com/android/tools/r8/compilerapi/extractmarker/ExtractMarkerApiTest.java
index 20e2bd4..489b6a7 100644
--- a/src/test/java/com/android/tools/r8/compilerapi/extractmarker/ExtractMarkerApiTest.java
+++ b/src/test/java/com/android/tools/r8/compilerapi/extractmarker/ExtractMarkerApiTest.java
@@ -114,6 +114,14 @@
                 assertFalse(marker.isR8());
                 assertFalse(marker.isL8());
                 assertEquals(1, marker.getMinApi());
+                assertTrue(marker.hasBackend());
+                assertTrue(marker.isBackendDexFiles());
+                assertFalse(marker.isBackendClassFiles());
+                assertTrue(marker.hasCompilationMode());
+                assertTrue(marker.isCompilationModeDebug());
+                assertFalse(marker.isCompilationModeRelease());
+                assertFalse(marker.isR8ModeCompatibility());
+                assertFalse(marker.isR8ModeFull());
                 assertThat(marker.getRawEncoding(), startsWith("~~D8{"));
               } else {
                 assertTrue(origin == originCf || origin.equals(new PathOrigin(inputFile)));