InitClass support when generating class files

Change-Id: I9ffcb3040d14a9700c67de52898a94fb3c51aa20
diff --git a/src/main/java/com/android/tools/r8/cf/CfPrinter.java b/src/main/java/com/android/tools/r8/cf/CfPrinter.java
index 9eedd04..ccd1686 100644
--- a/src/main/java/com/android/tools/r8/cf/CfPrinter.java
+++ b/src/main/java/com/android/tools/r8/cf/CfPrinter.java
@@ -23,6 +23,7 @@
 import com.android.tools.r8.cf.code.CfIf;
 import com.android.tools.r8.cf.code.CfIfCmp;
 import com.android.tools.r8.cf.code.CfIinc;
+import com.android.tools.r8.cf.code.CfInitClass;
 import com.android.tools.r8.cf.code.CfInstanceOf;
 import com.android.tools.r8.cf.code.CfInstruction;
 import com.android.tools.r8.cf.code.CfInvoke;
@@ -321,6 +322,12 @@
     appendType(constClass.getType());
   }
 
+  public void print(CfInitClass initClass) {
+    indent();
+    builder.append("initclass ");
+    appendType(initClass.getClassValue());
+  }
+
   public void print(CfReturnVoid ret) {
     print("return");
   }
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java b/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
index fc2a080..e9997b0 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.NumericType;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -128,7 +129,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitInsn(getAsmOpcode());
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
index 53536d2..85c4773 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
 import com.android.tools.r8.ir.conversion.CfState.Slot;
@@ -18,7 +19,7 @@
 public class CfArrayLength extends CfInstruction {
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitInsn(Opcodes.ARRAYLENGTH);
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
index 1f667b4..010bcfd 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.MemberType;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -55,7 +56,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitInsn(getLoadType());
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
index d0eadef..52df928 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.MemberType;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -53,7 +54,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitInsn(getStoreType());
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java b/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
index e89c480..19ca32e 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -29,7 +30,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitTypeInsn(Opcodes.CHECKCAST, lens.lookupInternalName(type));
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfCmp.java b/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
index dac3eca..259bfe3 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.Cmp;
 import com.android.tools.r8.ir.code.Cmp.Bias;
 import com.android.tools.r8.ir.code.NumericType;
@@ -78,7 +79,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitInsn(getAsmOpcode());
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java b/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
index 7f77ade..a203742 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -29,7 +30,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitLdcInsn(Type.getObjectType(getInternalName(lens)));
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
index a9a1d73..04e569b 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexMethodHandle;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.graph.UseRegistry.MethodHandleUse;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -29,7 +30,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitLdcInsn(handle.toAsmHandle(lens));
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
index 063b6fa..a67c3ed 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexProto;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -29,7 +30,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitLdcInsn(Type.getType(type.toDescriptorString(lens)));
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java b/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
index 7ad901a..c3be968 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -18,7 +19,7 @@
 public class CfConstNull extends CfInstruction {
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitInsn(Opcodes.ACONST_NULL);
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java b/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
index 72e4638..8977303 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -55,7 +56,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     switch (type) {
       case INT:
         {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstString.java b/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
index d52d901..08ee865 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
 import com.android.tools.r8.ir.conversion.IRBuilder;
@@ -41,7 +42,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitLdcInsn(string.toString());
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java b/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
index 36ba9b4..fbc4939 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
@@ -7,6 +7,7 @@
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexReference;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -46,7 +47,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     throw new Unreachable(
         "CfDexItemBasedConstString instructions should always be rewritten into CfConstString");
   }
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
index a000dcf..5812288 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
@@ -7,6 +7,7 @@
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -50,7 +51,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     String owner = lens.lookupInternalName(field.holder);
     String name = lens.lookupName(declaringField).toString();
     String desc = lens.lookupDescriptor(field.type).toString();
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
index e5a3c19..88d5ece 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
 import com.android.tools.r8.ir.conversion.IRBuilder;
@@ -211,7 +212,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     int stackCount = computeStackCount();
     Object[] stackTypes = computeStackTypes(stackCount, lens);
     int localsCount = computeLocalsCount();
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfGoto.java b/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
index efe67ba..412c97c7 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
 import com.android.tools.r8.ir.conversion.IRBuilder;
@@ -43,7 +44,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitJumpInsn(Opcodes.GOTO, target.getLabel());
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIf.java b/src/main/java/com/android/tools/r8/cf/code/CfIf.java
index 1ba9c06..ebc6a98 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIf.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIf.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.If;
 import com.android.tools.r8.ir.code.If.Type;
 import com.android.tools.r8.ir.code.ValueType;
@@ -68,7 +69,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitJumpInsn(getOpcode(), target.getLabel());
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java b/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
index 28a59d7..c2f34f7 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.If;
 import com.android.tools.r8.ir.code.If.Type;
 import com.android.tools.r8.ir.code.ValueType;
@@ -68,7 +69,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitJumpInsn(getOpcode(), target.getLabel());
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIinc.java b/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
index 92f2094..986d11f 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.NumericType;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -25,7 +26,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitIincInsn(var, increment);
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java b/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java
new file mode 100644
index 0000000..a355f58
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java
@@ -0,0 +1,72 @@
+// Copyright (c) 2020, 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.code;
+
+import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
+import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.ir.conversion.CfSourceCode;
+import com.android.tools.r8.ir.conversion.CfState;
+import com.android.tools.r8.ir.conversion.IRBuilder;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
+import com.android.tools.r8.naming.NamingLens;
+import org.objectweb.asm.MethodVisitor;
+
+public class CfInitClass extends CfInstruction {
+
+  private static final int OPCODE = org.objectweb.asm.Opcodes.GETSTATIC;
+
+  private final DexType clazz;
+
+  public CfInitClass(DexType clazz) {
+    this.clazz = clazz;
+  }
+
+  public DexType getClassValue() {
+    return clazz;
+  }
+
+  public int getOpcode() {
+    return OPCODE;
+  }
+
+  @Override
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
+    DexField field = initClassLens.getInitClassField(clazz);
+    String owner = lens.lookupInternalName(field.holder);
+    String name = lens.lookupName(field).toString();
+    String desc = lens.lookupDescriptor(field.type).toString();
+    visitor.visitFieldInsn(OPCODE, owner, name, desc);
+  }
+
+  @Override
+  public void print(CfPrinter printer) {
+    printer.print(this);
+  }
+
+  @Override
+  public void registerUse(UseRegistry registry, DexType context) {
+    registry.registerInitClass(clazz);
+  }
+
+  @Override
+  public boolean canThrow() {
+    return true;
+  }
+
+  @Override
+  public void buildIR(IRBuilder builder, CfState state, CfSourceCode code) {
+    int dest = state.push(builder.appView.dexItemFactory().intType).register;
+    builder.addInitClass(dest, clazz);
+  }
+
+  @Override
+  public ConstraintWithTarget inliningConstraint(
+      InliningConstraints inliningConstraints, DexType context) {
+    return inliningConstraints.forInitClass(clazz, context);
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java b/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
index d4d2066..5d0997f 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -38,7 +39,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitTypeInsn(Opcodes.INSTANCEOF, lens.lookupInternalName(type));
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
index 43d209e..d3cc826 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -16,7 +17,7 @@
 
 public abstract class CfInstruction {
 
-  public abstract void write(MethodVisitor visitor, NamingLens lens);
+  public abstract void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens);
 
   public abstract void print(CfPrinter printer);
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
index 6311bfd..1a5dd5c 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
@@ -16,6 +16,7 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.graph.GraphLense.GraphLenseLookupResult;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.code.Invoke;
 import com.android.tools.r8.ir.code.Invoke.Type;
@@ -69,7 +70,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     String owner = lens.lookupInternalName(method.holder);
     String name = lens.lookupName(method).toString();
     String desc = method.proto.toDescriptorString(lens);
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
index 231c115..ef0ec1b 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
@@ -18,6 +18,7 @@
 import com.android.tools.r8.graph.DexValue.DexValueMethodType;
 import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.graph.DexValue.DexValueType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -41,7 +42,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     DexMethodHandle bootstrapMethod = callSite.bootstrapMethod;
     List<DexValue> bootstrapArgs = callSite.bootstrapArgs;
     Object[] bsmArgs = new Object[bootstrapArgs.size()];
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java b/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
index 55aea68..7e678dc 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
 import com.android.tools.r8.ir.conversion.IRBuilder;
@@ -28,7 +29,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     throw error();
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLabel.java b/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
index df9d6bd..3901a1a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
 import com.android.tools.r8.ir.conversion.IRBuilder;
@@ -41,7 +42,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitLabel(getLabel());
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLoad.java b/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
index ae1fd85..80d6a8e 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -55,7 +56,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitVarInsn(getLoadType(), var);
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java b/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
index 1d03017..c2775a0 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.NumericType;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -103,7 +104,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitInsn(getAsmOpcode());
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java b/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
index dc117dd..6386b3c 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.Monitor.Type;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -29,7 +30,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitInsn(type == Type.ENTER ? Opcodes.MONITORENTER : Opcodes.MONITOREXIT);
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java b/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
index 936f62d..d12d76b 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -34,7 +35,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitMultiANewArrayInsn(lens.lookupInternalName(type), dimensions);
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNeg.java b/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
index 254ee77..02b2a83 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.NumericType;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -30,7 +31,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitInsn(getAsmOpcode());
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNew.java b/src/main/java/com/android/tools/r8/cf/code/CfNew.java
index 46821da..be087af 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNew.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNew.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -28,7 +29,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitTypeInsn(Opcodes.NEW, lens.lookupInternalName(type));
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java b/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
index 10504d9..1ce6048 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -63,7 +64,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     if (type.isPrimitiveArrayType()) {
       visitor.visitIntInsn(Opcodes.NEWARRAY, getPrimitiveTypeCode());
     } else {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNop.java b/src/main/java/com/android/tools/r8/cf/code/CfNop.java
index e124a0b..be9170c 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNop.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
 import com.android.tools.r8.ir.conversion.IRBuilder;
@@ -17,7 +18,7 @@
 public class CfNop extends CfInstruction {
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitInsn(Opcodes.NOP);
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java b/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
index c1118e5..dbedc8a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.NumericType;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -40,7 +41,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitInsn(this.getAsmOpcode());
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfPosition.java b/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
index 035604b..2dac0c6 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.Position;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -25,7 +26,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitLineNumber(position.line, label.getLabel());
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfReturn.java b/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
index 76475fa..e1b6de1 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -52,7 +53,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitInsn(getOpcode());
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java b/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
index fd55aa0..0bbe1cd 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
 import com.android.tools.r8.ir.conversion.IRBuilder;
@@ -22,7 +23,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitInsn(Opcodes.RETURN);
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
index 5886058..5821c3f 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
@@ -7,6 +7,7 @@
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -74,7 +75,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitInsn(opcode.opcode);
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfStore.java b/src/main/java/com/android/tools/r8/cf/code/CfStore.java
index 5f8a05d..d560b82 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfStore.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfStore.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
@@ -55,7 +56,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitVarInsn(getStoreType(), var);
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java b/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
index 47aff14..bfbe30f 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
 import com.android.tools.r8.ir.conversion.CfState.Slot;
@@ -68,7 +69,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     Label[] labels = new Label[targets.size()];
     for (int i = 0; i < targets.size(); i++) {
       labels[i] = targets.get(i).getLabel();
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfThrow.java b/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
index a7609c0..c0c094d 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InitClassLens;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
 import com.android.tools.r8.ir.conversion.CfState;
 import com.android.tools.r8.ir.conversion.CfState.Slot;
@@ -23,7 +24,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
+  public void write(MethodVisitor visitor, InitClassLens initClassLens, NamingLens lens) {
     visitor.visitInsn(Opcodes.ATHROW);
   }
 
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index 3a062e4..e504e54 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -313,7 +313,7 @@
   }
 
   public boolean canUseInitClass() {
-    return options.isGeneratingDex() && options.shouldRerunEnqueuer() && !initClassLens.isFinal();
+    return options.shouldRerunEnqueuer() && !initClassLens.isFinal();
   }
 
   public InitClassLens initClassLens() {
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index 4f8fa23..0c4267c 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -202,11 +202,12 @@
       NamingLens namingLens,
       AppView<?> appView,
       int classFileVersion) {
+    InitClassLens initClassLens = appView.initClassLens();
     InternalOptions options = appView.options();
     CfLabel parameterLabel = null;
     if (shouldAddParameterNames(method, appView)) {
       parameterLabel = new CfLabel();
-      parameterLabel.write(visitor, namingLens);
+      parameterLabel.write(visitor, initClassLens, namingLens);
     }
     for (CfInstruction instruction : instructions) {
       if (instruction instanceof CfFrame
@@ -214,7 +215,7 @@
           || (classFileVersion == 50 && !options.shouldKeepStackMapTable()))) {
         continue;
       }
-      instruction.write(visitor, namingLens);
+      instruction.write(visitor, initClassLens, namingLens);
     }
     visitor.visitEnd();
     visitor.visitMaxs(maxStack, maxLocals);
diff --git a/src/main/java/com/android/tools/r8/ir/code/InitClass.java b/src/main/java/com/android/tools/r8/ir/code/InitClass.java
index a4d0704..8dd260c 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InitClass.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InitClass.java
@@ -7,10 +7,9 @@
 import static com.android.tools.r8.optimize.MemberRebindingAnalysis.isTypeVisibleFromContext;
 
 import com.android.tools.r8.cf.LoadStoreHelper;
+import com.android.tools.r8.cf.code.CfInitClass;
 import com.android.tools.r8.code.DexInitClass;
 import com.android.tools.r8.dex.Constants;
-import com.android.tools.r8.errors.Unimplemented;
-import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.analysis.AbstractError;
@@ -73,7 +72,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    throw new Unreachable();
+    builder.add(new CfInitClass(clazz));
   }
 
   @Override
@@ -153,7 +152,7 @@
 
   @Override
   public void insertLoadAndStores(InstructionListIterator it, LoadStoreHelper helper) {
-    throw new Unimplemented();
+    helper.storeOutValue(this, it);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/shaking/ClassInitFieldSynthesizer.java b/src/main/java/com/android/tools/r8/shaking/ClassInitFieldSynthesizer.java
index 7e5847e..a6231aa 100644
--- a/src/main/java/com/android/tools/r8/shaking/ClassInitFieldSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/shaking/ClassInitFieldSynthesizer.java
@@ -42,14 +42,20 @@
       assert false;
       return;
     }
-    // Use an existing non-wide field if there is one (we can't use wide fields since we've only
-    // allocated a single register for the out-value of each ClassInit instruction).
+    // Use an existing static field if there is one.
     DexEncodedField encodedClinitField = null;
     for (DexEncodedField staticField : clazz.staticFields()) {
-      if (staticField.isPublic() && !staticField.field.type.isWideType()) {
-        encodedClinitField = staticField;
-        break;
+      // We need to field to be accessible from the contexts in which it is accessed.
+      if (!staticField.isPublic()) {
+        continue;
       }
+      // When compiling for dex, we can't use wide fields since we've only allocated a single
+      // register for the out-value of each ClassInit instruction
+      if (appView.options().isGeneratingDex() && staticField.field.type.isWideType()) {
+        continue;
+      }
+      encodedClinitField = staticField;
+      break;
     }
     if (encodedClinitField == null) {
       FieldAccessFlags accessFlags =
diff --git a/src/test/java/com/android/tools/r8/classmerging/InliningAfterStaticClassMergerTest.java b/src/test/java/com/android/tools/r8/classmerging/InliningAfterStaticClassMergerTest.java
index 5fdd52b..e2ee52f 100644
--- a/src/test/java/com/android/tools/r8/classmerging/InliningAfterStaticClassMergerTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/InliningAfterStaticClassMergerTest.java
@@ -102,18 +102,12 @@
     FoundClassSubject clazz = classes.get(0);
     assertEquals(StaticMergeCandidateA.class.getTypeName(), clazz.getOriginalName());
 
-    if (parameters.isCfRuntime()) {
-      // Check that StaticMergeCandidateB.m() has not been moved into StaticMergeCandidateA, because
-      // that would disable inlining of it.
-      assertEquals(1, clazz.allMethods().size());
-    } else {
-      // Check that StaticMergeCandidateB.m() has been inlined.
-      assertEquals(0, clazz.allMethods().size());
+    // Check that StaticMergeCandidateB.m() has been inlined.
+    assertEquals(0, clazz.allMethods().size());
 
-      // Check that a static field has been synthesized in order to trigger class initialization.
-      assertEquals(1, clazz.allStaticFields().size());
-      assertEquals("$r8$clinit", clazz.allStaticFields().get(0).getOriginalName());
-    }
+    // Check that a static field has been synthesized in order to trigger class initialization.
+    assertEquals(1, clazz.allStaticFields().size());
+    assertEquals("$r8$clinit", clazz.allStaticFields().get(0).getOriginalName());
 
     // Check that the test class only has a main method.
     ClassSubject classSubject = inspector.clazz(TestClass.class);
diff --git a/src/test/java/com/android/tools/r8/graph/initializedclasses/InitializedClassesInInstanceMethodsTest.java b/src/test/java/com/android/tools/r8/graph/initializedclasses/InitializedClassesInInstanceMethodsTest.java
index ee86dc8..9251ab8 100644
--- a/src/test/java/com/android/tools/r8/graph/initializedclasses/InitializedClassesInInstanceMethodsTest.java
+++ b/src/test/java/com/android/tools/r8/graph/initializedclasses/InitializedClassesInInstanceMethodsTest.java
@@ -71,15 +71,14 @@
     assertThat(outerClassSubject.uniqueMethodWithName("world"), not(isPresent()));
     assertThat(outerClassSubject.uniqueMethodWithName("exclamationMark"), not(isPresent()));
 
-    int numberOfExpectedAccessibilityBridges =
-        enableInitializedClassesInInstanceMethodsAnalysis || parameters.isDexRuntime() ? 0 : 3;
+    int numberOfExpectedAccessibilityBridges = 0;
     assertEquals(
         numberOfExpectedAccessibilityBridges,
         outerClassSubject
             .allMethods(method -> method.getOriginalName().contains("access$"))
             .size());
     assertEquals(
-        parameters.isDexRuntime() && !enableInitializedClassesInInstanceMethodsAnalysis,
+        !enableInitializedClassesInInstanceMethodsAnalysis,
         outerClassSubject.uniqueFieldWithName("$r8$clinit").isPresent());
 
     ClassSubject aClassSubject = inspector.clazz(Outer.A.class);
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/sideeffect/SingletonClassInitializerPatternCannotBePostponedTest.java b/src/test/java/com/android/tools/r8/ir/analysis/sideeffect/SingletonClassInitializerPatternCannotBePostponedTest.java
index 4213323..b3a0265 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/sideeffect/SingletonClassInitializerPatternCannotBePostponedTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/sideeffect/SingletonClassInitializerPatternCannotBePostponedTest.java
@@ -48,16 +48,9 @@
     ClassSubject classSubject = inspector.clazz(A.class);
     assertThat(classSubject, isPresent());
 
-    if (parameters.isCfRuntime()) {
-      // A.inlineable() cannot be inlined because it should trigger the class initialization of A,
-      // which should trigger the class initialization of B, which will print "Hello".
-      assertThat(classSubject.uniqueFieldWithName("$r8$clinit"), not(isPresent()));
-      assertThat(classSubject.uniqueMethodWithName("inlineable"), isPresent());
-    } else {
-      // A static field A.$r8$clinit has been synthesized to allow inlining of A.inlineable().
-      assertThat(classSubject.uniqueFieldWithName("$r8$clinit"), isPresent());
-      assertThat(classSubject.uniqueMethodWithName("inlineable"), not(isPresent()));
-    }
+    // A static field A.$r8$clinit has been synthesized to allow inlining of A.inlineable().
+    assertThat(classSubject.uniqueFieldWithName("$r8$clinit"), isPresent());
+    assertThat(classSubject.uniqueMethodWithName("inlineable"), not(isPresent()));
   }
 
   static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InliningFromCurrentClassTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InliningFromCurrentClassTest.java
index 27f3735..a7aa579 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InliningFromCurrentClassTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InliningFromCurrentClassTest.java
@@ -5,7 +5,6 @@
 package com.android.tools.r8.ir.optimize.inliner;
 
 import static com.android.tools.r8.utils.codeinspector.CodeMatchers.accessesField;
-import static com.android.tools.r8.utils.codeinspector.CodeMatchers.invokesMethod;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.core.IsNot.not;
@@ -81,13 +80,8 @@
 
     MethodSubject inlineableWithInitClassMethod =
         classC.uniqueMethodWithName("inlineableWithInitClass");
-    if (parameters.isCfRuntime()) {
-      assertThat(inlineableWithInitClassMethod, isPresent());
-      assertThat(testMethod, invokesMethod(inlineableWithInitClassMethod));
-    } else {
-      assertThat(inlineableWithInitClassMethod, not(isPresent()));
-      assertThat(testMethod, accessesField(classC.uniqueFieldWithName("$r8$clinit")));
-    }
+    assertThat(inlineableWithInitClassMethod, not(isPresent()));
+    assertThat(testMethod, accessesField(classC.uniqueFieldWithName("$r8$clinit")));
   }
 
   static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/MemberValuePropagationWithClassInitializationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/MemberValuePropagationWithClassInitializationTest.java
index c87d144..50e52e2 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/MemberValuePropagationWithClassInitializationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/MemberValuePropagationWithClassInitializationTest.java
@@ -30,7 +30,7 @@
 
   @Parameters(name = "{0}")
   public static TestParametersCollection data() {
-    return getTestParameters().withDexRuntimes().withAllApiLevels().build();
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
   }
 
   public MemberValuePropagationWithClassInitializationTest(TestParameters parameters) {
diff --git a/src/test/java/com/android/tools/r8/shaking/FieldReadsJasminTest.java b/src/test/java/com/android/tools/r8/shaking/FieldReadsJasminTest.java
index 0128ec3..ac18813 100644
--- a/src/test/java/com/android/tools/r8/shaking/FieldReadsJasminTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/FieldReadsJasminTest.java
@@ -258,12 +258,6 @@
             ensureFieldExistsAndReadOnlyOnce(
                 inspector, main.name, mainMethod.name, empty, "sField", false),
         inspector -> {
-          if (parameters.isCfRuntime()) {
-            ensureFieldExistsAndReadOnlyOnce(
-                inspector, main.name, mainMethod.name, empty, "sField", false);
-            return;
-          }
-
           ClassSubject emptyClassSubject = inspector.clazz(empty.name);
           assertThat(emptyClassSubject, isPresent());
           assertEquals(1, emptyClassSubject.allStaticFields().size());