VarHandle desugaring test of types not supported by desugaring

Bug: b/247076137
Change-Id: I4634d35f094a40d1725dc9f9c909ac3e96df88c7
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaringMethods.java b/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaringMethods.java
index 112f246..849a6b4 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaringMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaringMethods.java
@@ -57,6 +57,7 @@
     factory.createSynthesizedType("Ljava/lang/Long;");
     factory.createSynthesizedType("Ljava/lang/RuntimeException;");
     factory.createSynthesizedType("Ljava/lang/Short;");
+    factory.createSynthesizedType("Ljava/lang/UnsupportedOperationException;");
     factory.createSynthesizedType("Ljava/lang/reflect/Field;");
     factory.createSynthesizedType("Lsun/misc/Unsafe;");
   }
@@ -521,6 +522,9 @@
     CfLabel label7 = new CfLabel();
     CfLabel label8 = new CfLabel();
     CfLabel label9 = new CfLabel();
+    CfLabel label10 = new CfLabel();
+    CfLabel label11 = new CfLabel();
+    CfLabel label12 = new CfLabel();
     return new CfCode(
         method.holder,
         4,
@@ -610,6 +614,107 @@
                     factory.classType,
                     factory.createString("type"))),
             label7,
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.classType,
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isPrimitive")),
+                false),
+            new CfIf(If.Type.EQ, ValueType.INT, label10),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label10),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label10),
+            label8,
+            new CfNew(factory.createType("Ljava/lang/UnsupportedOperationException;")),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfNew(factory.stringBuilderType),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
+                false),
+            new CfConstString(factory.createString("Using a VarHandle for a field of type '")),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
+                false),
+            new CfLoad(ValueType.OBJECT, 3),
+            label9,
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.classType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("getName")),
+                false),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
+                false),
+            new CfConstString(
+                factory.createString(
+                    "' requires native VarHandle support available from Android 13. VarHandle"
+                        + " desugaring only supports primitive types int and long and reference"
+                        + " types.")),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringBuilderType, factory.stringType),
+                    factory.createString("append")),
+                false),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.stringBuilderType,
+                    factory.createProto(factory.stringType),
+                    factory.createString("toString")),
+                false),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/UnsupportedOperationException;"),
+                    factory.createProto(factory.voidType, factory.stringType),
+                    factory.createString("<init>")),
+                false),
+            new CfThrow(),
+            label10,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Lcom/android/tools/r8/DesugarVarHandle;")),
+                      FrameType.initializedNonNullReference(factory.classType),
+                      FrameType.initializedNonNullReference(factory.stringType),
+                      FrameType.initializedNonNullReference(factory.classType),
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/reflect/Field;")),
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/reflect/Field;"))
+                    })),
             new CfLoad(ValueType.OBJECT, 0),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInstanceFieldRead(
@@ -640,9 +745,9 @@
                     factory.createType("Lcom/android/tools/r8/DesugarVarHandle;"),
                     factory.longType,
                     factory.createString("offset"))),
-            label8,
+            label11,
             new CfReturnVoid(),
-            label9),
+            label12),
         ImmutableList.of(),
         ImmutableList.of());
   }
diff --git a/src/test/examplesJava9/varhandle/InstanceBooleanField.java b/src/test/examplesJava9/varhandle/InstanceBooleanField.java
new file mode 100644
index 0000000..89c034a
--- /dev/null
+++ b/src/test/examplesJava9/varhandle/InstanceBooleanField.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package varhandle;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
+public class InstanceBooleanField {
+
+  private boolean field;
+
+  public static void testSet(VarHandle varHandle) {
+    System.out.println("testGet");
+
+    InstanceBooleanField instance = new InstanceBooleanField();
+    System.out.println(varHandle.get(instance));
+
+    // boolean and Boolean values.
+    varHandle.set(instance, true);
+    System.out.println((boolean) varHandle.get(instance));
+    varHandle.set(instance, Boolean.FALSE);
+    System.out.println(varHandle.get(instance));
+  }
+
+  public static void testCompareAndSet(VarHandle varHandle) {
+    System.out.println("testCompareAndSet");
+
+    InstanceBooleanField instance = new InstanceBooleanField();
+
+    // boolean and Boolean values.
+    varHandle.compareAndSet(instance, true, false);
+    System.out.println((boolean) varHandle.get(instance));
+    varHandle.compareAndSet(instance, false, true);
+    System.out.println((boolean) varHandle.get(instance));
+    varHandle.compareAndSet(instance, Boolean.TRUE, false);
+    System.out.println(varHandle.get(instance));
+    varHandle.compareAndSet(instance, false, Boolean.TRUE);
+    System.out.println(varHandle.get(instance));
+    varHandle.compareAndSet(instance, Boolean.TRUE, Boolean.FALSE);
+    System.out.println(varHandle.get(instance));
+  }
+
+  public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
+    VarHandle varHandle;
+    try {
+      varHandle =
+          MethodHandles.lookup().findVarHandle(InstanceBooleanField.class, "field", boolean.class);
+    } catch (UnsupportedOperationException e) {
+      System.out.println("Got UnsupportedOperationException");
+      return;
+    }
+
+    testSet(varHandle);
+    testCompareAndSet(varHandle);
+  }
+}
diff --git a/src/test/examplesJava9/varhandle/InstanceByteField.java b/src/test/examplesJava9/varhandle/InstanceByteField.java
new file mode 100644
index 0000000..242df89
--- /dev/null
+++ b/src/test/examplesJava9/varhandle/InstanceByteField.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package varhandle;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
+public class InstanceByteField {
+
+  private byte field;
+
+  public static void testSet(VarHandle varHandle) {
+    System.out.println("testGet");
+
+    InstanceByteField instance = new InstanceByteField();
+    System.out.println(varHandle.get(instance));
+
+    // byte and Byte values.
+    varHandle.set(instance, (byte) 1);
+    System.out.println((byte) varHandle.get(instance));
+    varHandle.set(instance, Byte.valueOf((byte) 2));
+    System.out.println(varHandle.get(instance));
+  }
+
+  public static void testCompareAndSet(VarHandle varHandle) {
+    System.out.println("testCompareAndSet");
+
+    InstanceByteField instance = new InstanceByteField();
+
+    // byte and Byte values.
+    varHandle.compareAndSet(instance, (byte) 1, (byte) 2);
+    System.out.println((byte) varHandle.get(instance));
+    varHandle.compareAndSet(instance, (byte) 0, (byte) 1);
+    System.out.println((byte) varHandle.get(instance));
+    varHandle.compareAndSet(instance, Byte.valueOf((byte) 1), (byte) 2);
+    System.out.println(varHandle.get(instance));
+    varHandle.compareAndSet(instance, (byte) 2, Byte.valueOf((byte) 3));
+    System.out.println(varHandle.get(instance));
+    varHandle.compareAndSet(instance, Byte.valueOf((byte) 3), Byte.valueOf((byte) 4));
+    System.out.println(varHandle.get(instance));
+  }
+
+  public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
+    VarHandle varHandle;
+    try {
+      varHandle =
+          MethodHandles.lookup().findVarHandle(InstanceByteField.class, "field", byte.class);
+    } catch (UnsupportedOperationException e) {
+      System.out.println("Got UnsupportedOperationException");
+      return;
+    }
+
+    testSet(varHandle);
+    testCompareAndSet(varHandle);
+  }
+}
diff --git a/src/test/examplesJava9/varhandle/InstanceDoubleField.java b/src/test/examplesJava9/varhandle/InstanceDoubleField.java
new file mode 100644
index 0000000..5b59463
--- /dev/null
+++ b/src/test/examplesJava9/varhandle/InstanceDoubleField.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package varhandle;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
+public class InstanceDoubleField {
+
+  private double field;
+
+  public static void testSet(VarHandle varHandle) {
+    System.out.println("testGet");
+
+    InstanceDoubleField instance = new InstanceDoubleField();
+    System.out.println(varHandle.get(instance));
+
+    // double and Double values.
+    varHandle.set(instance, 1.0);
+    System.out.println((double) varHandle.get(instance));
+    varHandle.set(instance, Double.valueOf(2));
+    System.out.println(varHandle.get(instance));
+  }
+
+  public static void testCompareAndSet(VarHandle varHandle) {
+    System.out.println("testCompareAndSet");
+
+    InstanceDoubleField instance = new InstanceDoubleField();
+
+    // double and Double values.
+    varHandle.compareAndSet(instance, 1.0, 2.0);
+    System.out.println((double) varHandle.get(instance));
+    varHandle.compareAndSet(instance, 0.0, 1.0);
+    System.out.println((double) varHandle.get(instance));
+    varHandle.compareAndSet(instance, Double.valueOf(1), 2.0);
+    System.out.println(varHandle.get(instance));
+    varHandle.compareAndSet(instance, 2.0, Double.valueOf(3));
+    System.out.println(varHandle.get(instance));
+    varHandle.compareAndSet(instance, Double.valueOf(3), Double.valueOf(4));
+    System.out.println(varHandle.get(instance));
+  }
+
+  public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
+    VarHandle varHandle;
+    try {
+      varHandle =
+          MethodHandles.lookup().findVarHandle(InstanceDoubleField.class, "field", double.class);
+    } catch (UnsupportedOperationException e) {
+      System.out.println("Got UnsupportedOperationException");
+      return;
+    }
+
+    testSet(varHandle);
+    testCompareAndSet(varHandle);
+  }
+}
diff --git a/src/test/examplesJava9/varhandle/InstanceFloatField.java b/src/test/examplesJava9/varhandle/InstanceFloatField.java
new file mode 100644
index 0000000..06960c4
--- /dev/null
+++ b/src/test/examplesJava9/varhandle/InstanceFloatField.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package varhandle;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
+public class InstanceFloatField {
+
+  private float field;
+
+  public static void testSet(VarHandle varHandle) {
+    System.out.println("testGet");
+
+    InstanceFloatField instance = new InstanceFloatField();
+    System.out.println(varHandle.get(instance));
+
+    // float and Float values.
+    varHandle.set(instance, 1.0f);
+    System.out.println((float) varHandle.get(instance));
+    varHandle.set(instance, Float.valueOf(2));
+    System.out.println(varHandle.get(instance));
+  }
+
+  public static void testCompareAndSet(VarHandle varHandle) {
+    System.out.println("testCompareAndSet");
+
+    InstanceFloatField instance = new InstanceFloatField();
+
+    // float and Float values.
+    varHandle.compareAndSet(instance, 1.0f, 2.0f);
+    System.out.println((float) varHandle.get(instance));
+    varHandle.compareAndSet(instance, 0.0f, 1.0f);
+    System.out.println((float) varHandle.get(instance));
+    varHandle.compareAndSet(instance, Float.valueOf(1), 2.0f);
+    System.out.println(varHandle.get(instance));
+    varHandle.compareAndSet(instance, 2.0f, Float.valueOf(3f));
+    System.out.println(varHandle.get(instance));
+    varHandle.compareAndSet(instance, Float.valueOf(3), Float.valueOf(4));
+    System.out.println(varHandle.get(instance));
+  }
+
+  public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
+    VarHandle varHandle;
+    try {
+      varHandle =
+          MethodHandles.lookup().findVarHandle(InstanceFloatField.class, "field", float.class);
+    } catch (UnsupportedOperationException e) {
+      System.out.println("Got UnsupportedOperationException");
+      return;
+    }
+
+    testSet(varHandle);
+    testCompareAndSet(varHandle);
+  }
+}
diff --git a/src/test/examplesJava9/varhandle/InstanceShortField.java b/src/test/examplesJava9/varhandle/InstanceShortField.java
new file mode 100644
index 0000000..7890cf2
--- /dev/null
+++ b/src/test/examplesJava9/varhandle/InstanceShortField.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package varhandle;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
+public class InstanceShortField {
+
+  private short field;
+
+  public static void testSet(VarHandle varHandle) {
+    System.out.println("testGet");
+
+    InstanceShortField instance = new InstanceShortField();
+    System.out.println(varHandle.get(instance));
+
+    // short and Short values.
+    varHandle.set(instance, (short) 1);
+    System.out.println((short) varHandle.get(instance));
+    varHandle.set(instance, Short.valueOf((short) 2));
+    System.out.println(varHandle.get(instance));
+  }
+
+  public static void testCompareAndSet(VarHandle varHandle) {
+    System.out.println("testCompareAndSet");
+
+    InstanceShortField instance = new InstanceShortField();
+
+    // short and Short values.
+    varHandle.compareAndSet(instance, (short) 1, (short) 2);
+    System.out.println((short) varHandle.get(instance));
+    varHandle.compareAndSet(instance, (short) 0, (short) 1);
+    System.out.println((short) varHandle.get(instance));
+    varHandle.compareAndSet(instance, Short.valueOf((short) 1), (short) 2);
+    System.out.println(varHandle.get(instance));
+    varHandle.compareAndSet(instance, (short) 2, Short.valueOf((short) 3));
+    System.out.println(varHandle.get(instance));
+    varHandle.compareAndSet(instance, Short.valueOf((short) 3), Short.valueOf((short) 4));
+    System.out.println(varHandle.get(instance));
+  }
+
+  public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
+    VarHandle varHandle;
+    try {
+      varHandle =
+          MethodHandles.lookup().findVarHandle(InstanceShortField.class, "field", short.class);
+    } catch (UnsupportedOperationException e) {
+      System.out.println("Got UnsupportedOperationException");
+      return;
+    }
+
+    testSet(varHandle);
+    testCompareAndSet(varHandle);
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceBooleanFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceBooleanFieldTest.java
new file mode 100644
index 0000000..d9fc4c4
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceBooleanFieldTest.java
@@ -0,0 +1,62 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.cf.varhandle;
+
+import com.android.tools.r8.examples.jdk9.VarHandle;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class VarHandleDesugaringInstanceBooleanFieldTest extends VarHandleDesugaringTestBase {
+
+  private static final String EXPECTED_OUTPUT =
+      StringUtils.lines(
+          "testGet",
+          "false",
+          "true",
+          "false",
+          "testCompareAndSet",
+          "false",
+          "true",
+          "false",
+          "true",
+          "false");
+
+  private static final String MAIN_CLASS = VarHandle.InstanceBooleanField.typeName();
+  private static final String JAR_ENTRY = "varhandle/InstanceBooleanField.class";
+
+  @Override
+  protected String getMainClass() {
+    return MAIN_CLASS;
+  }
+
+  @Override
+  protected String getKeepRules() {
+    return "-keep class " + getMainClass() + "{ <fields>; }";
+  }
+
+  @Override
+  protected List<String> getJarEntries() {
+    return ImmutableList.of(JAR_ENTRY);
+  }
+
+  @Override
+  protected String getExpectedOutputForReferenceImplementation() {
+    return EXPECTED_OUTPUT;
+  }
+
+  @Override
+  protected String getExpectedOutputForDesugaringImplementation() {
+    return StringUtils.lines("Got UnsupportedOperationException");
+  }
+
+  @Override
+  protected boolean getTestWithDesugaring() {
+    return true;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceByteFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceByteFieldTest.java
new file mode 100644
index 0000000..a96b5a9
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceByteFieldTest.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.cf.varhandle;
+
+import com.android.tools.r8.examples.jdk9.VarHandle;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class VarHandleDesugaringInstanceByteFieldTest extends VarHandleDesugaringTestBase {
+
+  private static final String EXPECTED_OUTPUT =
+      StringUtils.lines("testGet", "0", "1", "2", "testCompareAndSet", "0", "1", "2", "3", "4");
+
+  private static final String MAIN_CLASS = VarHandle.InstanceByteField.typeName();
+  private static final String JAR_ENTRY = "varhandle/InstanceByteField.class";
+
+  @Override
+  protected String getMainClass() {
+    return MAIN_CLASS;
+  }
+
+  @Override
+  protected String getKeepRules() {
+    return "-keep class " + getMainClass() + "{ <fields>; }";
+  }
+
+  @Override
+  protected List<String> getJarEntries() {
+    return ImmutableList.of(JAR_ENTRY);
+  }
+
+  @Override
+  protected String getExpectedOutputForReferenceImplementation() {
+    return EXPECTED_OUTPUT;
+  }
+
+  @Override
+  protected String getExpectedOutputForDesugaringImplementation() {
+    return StringUtils.lines("Got UnsupportedOperationException");
+  }
+
+  @Override
+  protected boolean getTestWithDesugaring() {
+    return true;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceDoubleFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceDoubleFieldTest.java
new file mode 100644
index 0000000..194f25f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceDoubleFieldTest.java
@@ -0,0 +1,53 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.cf.varhandle;
+
+import com.android.tools.r8.examples.jdk9.VarHandle;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class VarHandleDesugaringInstanceDoubleFieldTest extends VarHandleDesugaringTestBase {
+
+  private static final String EXPECTED_OUTPUT =
+      StringUtils.lines(
+          "testGet", "0.0", "1.0", "2.0", "testCompareAndSet", "0.0", "1.0", "2.0", "3.0", "4.0");
+
+  private static final String MAIN_CLASS = VarHandle.InstanceDoubleField.typeName();
+  private static final String JAR_ENTRY = "varhandle/InstanceDoubleField.class";
+
+  @Override
+  protected String getMainClass() {
+    return MAIN_CLASS;
+  }
+
+  @Override
+  protected String getKeepRules() {
+    return "-keep class " + getMainClass() + "{ <fields>; }";
+  }
+
+  @Override
+  protected List<String> getJarEntries() {
+    return ImmutableList.of(JAR_ENTRY);
+  }
+
+  @Override
+  protected String getExpectedOutputForReferenceImplementation() {
+    return EXPECTED_OUTPUT;
+  }
+
+  @Override
+  protected String getExpectedOutputForDesugaringImplementation() {
+    return StringUtils.lines("Got UnsupportedOperationException");
+  }
+
+  @Override
+  protected boolean getTestWithDesugaring() {
+    return true;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceFloatFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceFloatFieldTest.java
new file mode 100644
index 0000000..457753b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceFloatFieldTest.java
@@ -0,0 +1,53 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.cf.varhandle;
+
+import com.android.tools.r8.examples.jdk9.VarHandle;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class VarHandleDesugaringInstanceFloatFieldTest extends VarHandleDesugaringTestBase {
+
+  private static final String EXPECTED_OUTPUT =
+      StringUtils.lines(
+          "testGet", "0.0", "1.0", "2.0", "testCompareAndSet", "0.0", "1.0", "2.0", "3.0", "4.0");
+
+  private static final String MAIN_CLASS = VarHandle.InstanceFloatField.typeName();
+  private static final String JAR_ENTRY = "varhandle/InstanceFloatField.class";
+
+  @Override
+  protected String getMainClass() {
+    return MAIN_CLASS;
+  }
+
+  @Override
+  protected String getKeepRules() {
+    return "-keep class " + getMainClass() + "{ <fields>; }";
+  }
+
+  @Override
+  protected List<String> getJarEntries() {
+    return ImmutableList.of(JAR_ENTRY);
+  }
+
+  @Override
+  protected String getExpectedOutputForReferenceImplementation() {
+    return EXPECTED_OUTPUT;
+  }
+
+  @Override
+  protected String getExpectedOutputForDesugaringImplementation() {
+    return StringUtils.lines("Got UnsupportedOperationException");
+  }
+
+  @Override
+  protected boolean getTestWithDesugaring() {
+    return true;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceShortFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceShortFieldTest.java
new file mode 100644
index 0000000..a5947eb
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceShortFieldTest.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.cf.varhandle;
+
+import com.android.tools.r8.examples.jdk9.VarHandle;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class VarHandleDesugaringInstanceShortFieldTest extends VarHandleDesugaringTestBase {
+
+  private static final String EXPECTED_OUTPUT =
+      StringUtils.lines("testGet", "0", "1", "2", "testCompareAndSet", "0", "1", "2", "3", "4");
+
+  private static final String MAIN_CLASS = VarHandle.InstanceShortField.typeName();
+  private static final String JAR_ENTRY = "varhandle/InstanceShortField.class";
+
+  @Override
+  protected String getMainClass() {
+    return MAIN_CLASS;
+  }
+
+  @Override
+  protected String getKeepRules() {
+    return "-keep class " + getMainClass() + "{ <fields>; }";
+  }
+
+  @Override
+  protected List<String> getJarEntries() {
+    return ImmutableList.of(JAR_ENTRY);
+  }
+
+  @Override
+  protected String getExpectedOutputForReferenceImplementation() {
+    return EXPECTED_OUTPUT;
+  }
+
+  @Override
+  protected String getExpectedOutputForDesugaringImplementation() {
+    return StringUtils.lines("Got UnsupportedOperationException");
+  }
+
+  @Override
+  protected boolean getTestWithDesugaring() {
+    return true;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringTestBase.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringTestBase.java
index 6a73d66..892cdc3 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringTestBase.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringTestBase.java
@@ -65,6 +65,10 @@
 
   protected abstract String getExpectedOutputForReferenceImplementation();
 
+  protected String getExpectedOutputForDesugaringImplementation() {
+    return getExpectedOutputForReferenceImplementation();
+  }
+
   protected String getExpectedOutputForArtImplementation() {
     return getExpectedOutputForReferenceImplementation();
   }
@@ -198,7 +202,7 @@
                                   .getDexRuntimeVersion()
                                   .isNewerThanOrEqual(Version.V13_0_0)
                           ? getExpectedOutputForArtImplementation()
-                          : getExpectedOutputForReferenceImplementation()))
+                          : getExpectedOutputForDesugaringImplementation()))
           .inspect(this::inspect);
     } else {
       testForD8(parameters.getBackend())
@@ -220,6 +224,18 @@
   // TODO(b/247076137: Also turn on VarHandle desugaring for R8 tests.
   @Test
   public void testR8() throws Throwable {
+    // TODO(b/247076137: The "default" VM is acting up on some tests - skip these as they will
+    // be fixed when VarHandle desugaring is enabled for R8.
+    if (parameters.isDexRuntime()
+        && parameters.asDexRuntime().getVersion().isEqualTo(Version.DEFAULT)
+        && parameters.getApiLevel().equals(AndroidApiLevel.B)
+        && (this instanceof VarHandleDesugaringInstanceBooleanFieldTest
+            || this instanceof VarHandleDesugaringInstanceByteFieldTest
+            || this instanceof VarHandleDesugaringInstanceShortFieldTest
+            || this instanceof VarHandleDesugaringInstanceFloatFieldTest
+            || this instanceof VarHandleDesugaringInstanceDoubleFieldTest)) {
+      return;
+    }
     testForR8(parameters.getBackend())
         .applyIf(
             parameters.isDexRuntime(),
diff --git a/src/test/java/com/android/tools/r8/examples/jdk9/VarHandle.java b/src/test/java/com/android/tools/r8/examples/jdk9/VarHandle.java
index 620e01b..0cb3d7f 100644
--- a/src/test/java/com/android/tools/r8/examples/jdk9/VarHandle.java
+++ b/src/test/java/com/android/tools/r8/examples/jdk9/VarHandle.java
@@ -29,6 +29,21 @@
   public static final JavaExampleClassProxy InstanceLongField =
       new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/InstanceLongField");
 
+  public static final JavaExampleClassProxy InstanceBooleanField =
+      new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/InstanceBooleanField");
+
+  public static final JavaExampleClassProxy InstanceByteField =
+      new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/InstanceByteField");
+
+  public static final JavaExampleClassProxy InstanceShortField =
+      new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/InstanceShortField");
+
+  public static final JavaExampleClassProxy InstanceFloatField =
+      new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/InstanceFloatField");
+
+  public static final JavaExampleClassProxy InstanceDoubleField =
+      new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/InstanceDoubleField");
+
   public static final JavaExampleClassProxy InstanceObjectField =
       new JavaExampleClassProxy(EXAMPLE_FILE, "varhandle/InstanceObjectField");
 
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/varhandle/DesugarVarHandle.java b/src/test/java/com/android/tools/r8/ir/desugar/varhandle/DesugarVarHandle.java
index 30b3240..5780485 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/varhandle/DesugarVarHandle.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/varhandle/DesugarVarHandle.java
@@ -79,6 +79,14 @@
     this.recv = recv;
     Field field = recv.getDeclaredField(name);
     this.type = field.getType();
+    if (type.isPrimitive() && type != int.class && type != long.class) {
+      throw new UnsupportedOperationException(
+          "Using a VarHandle for a field of type '"
+              + type.getName()
+              + "' requires native VarHandle support available from Android 13. "
+              + "VarHandle desugaring only supports primitive types int and long and "
+              + "reference types.");
+    }
     this.offset = U.objectFieldOffset(recv.getDeclaredField(name));
   }