CF backend: Implement minification

Add NamingLens argument to CfCode.write() and CfInstruction.write().

In CfApplicationWriter, pass NamingLens on to all components.

The change to InnerClassAttribute is covered by Art005_annotationsTest.

Change-Id: I81b18fbd224bce5bb3ecb4bb08a6843975408f85
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 0b5e678..dfe7c1b 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
@@ -4,13 +4,14 @@
 package com.android.tools.r8.cf.code;
 
 import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
 public class CfArrayLength extends CfInstruction {
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, 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 3ff24b9..85405e4 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.ir.code.MemberType;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
@@ -46,7 +47,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, 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 6d7ca1a..4b13af4 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.ir.code.MemberType;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
@@ -46,7 +47,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, NamingLens lens) {
     visitor.visitInsn(getStoreType());
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfBinop.java b/src/main/java/com/android/tools/r8/cf/code/CfBinop.java
index af78290..6f8e868 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfBinop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfBinop.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.cf.code;
 
 import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 
 public class CfBinop extends CfInstruction {
@@ -19,7 +20,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, NamingLens lens) {
     visitor.visitInsn(opcode);
   }
 
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 214d7b0..e46d475 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
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
@@ -22,8 +23,8 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
-    visitor.visitTypeInsn(Opcodes.CHECKCAST, type.getInternalName());
+  public void write(MethodVisitor visitor, NamingLens lens) {
+    visitor.visitTypeInsn(Opcodes.CHECKCAST, lens.lookupInternalName(type));
   }
 
   @Override
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 74a470c..e4037e4 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
@@ -7,6 +7,7 @@
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Type;
 
@@ -23,8 +24,8 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
-    visitor.visitLdcInsn(Type.getObjectType(getInternalName()));
+  public void write(MethodVisitor visitor, NamingLens lens) {
+    visitor.visitLdcInsn(Type.getObjectType(getInternalName(lens)));
   }
 
   @Override
@@ -32,11 +33,11 @@
     printer.print(this);
   }
 
-  private String getInternalName() {
+  private String getInternalName(NamingLens lens) {
     switch (type.toShorty()) {
       case '[':
       case 'L':
-        return type.getInternalName();
+        return lens.lookupInternalName(type);
       case 'Z':
         return "java/lang/Boolean/TYPE";
       case 'B':
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 2cbfafe..ca34be7 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
@@ -7,6 +7,7 @@
 import com.android.tools.r8.graph.DexMethodHandle;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 
 public class CfConstMethodHandle extends CfInstruction {
@@ -22,8 +23,8 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
-    visitor.visitLdcInsn(handle.toAsmHandle());
+  public void write(MethodVisitor visitor, NamingLens lens) {
+    visitor.visitLdcInsn(handle.toAsmHandle(lens));
   }
 
   @Override
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 35b64a5..7e06a88 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
@@ -7,6 +7,7 @@
 import com.android.tools.r8.graph.DexProto;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Type;
 
@@ -23,8 +24,8 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
-    visitor.visitLdcInsn(Type.getType(type.toDescriptorString()));
+  public void write(MethodVisitor visitor, NamingLens lens) {
+    visitor.visitLdcInsn(Type.getType(type.toDescriptorString(lens)));
   }
 
   @Override
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 a788a3b..385669d 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
@@ -4,13 +4,14 @@
 package com.android.tools.r8.cf.code;
 
 import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
 public class CfConstNull extends CfInstruction {
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, 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 246cf0b..07fd664 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.ir.code.ValueType;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
@@ -48,7 +49,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, 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 0f7f9f7..a22f279 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
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 
 public class CfConstString extends CfInstruction {
@@ -20,7 +21,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, NamingLens lens) {
     visitor.visitLdcInsn(string.toString());
   }
 
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 96b19ce..e30d8ce 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
@@ -8,6 +8,7 @@
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
@@ -30,10 +31,10 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
-    String owner = field.getHolder().getInternalName();
-    String name = field.name.toString();
-    String desc = field.type.toDescriptorString();
+  public void write(MethodVisitor visitor, NamingLens lens) {
+    String owner = lens.lookupInternalName(field.getHolder());
+    String name = lens.lookupName(field).toString();
+    String desc = lens.lookupDescriptor(field.type).toString();
     visitor.visitFieldInsn(opcode, owner, name, desc);
   }
 
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 b589a78..2818e44 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.naming.NamingLens;
 import it.unimi.dsi.fastutil.ints.Int2ReferenceSortedMap;
 import java.util.List;
 import org.objectweb.asm.MethodVisitor;
@@ -33,11 +34,11 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, NamingLens lens) {
     int stackCount = computeStackCount();
-    Object[] stackTypes = computeStackTypes(stackCount);
+    Object[] stackTypes = computeStackTypes(stackCount, lens);
     int localsCount = computeLocalsCount();
-    Object[] localsTypes = computeLocalsTypes(localsCount);
+    Object[] localsTypes = computeLocalsTypes(localsCount, lens);
     visitor.visitFrame(F_NEW, localsCount, localsTypes, stackCount, stackTypes);
   }
 
@@ -49,14 +50,14 @@
     return stack.size();
   }
 
-  private Object[] computeStackTypes(int stackCount) {
+  private Object[] computeStackTypes(int stackCount, NamingLens lens) {
     assert stackCount == stack.size();
     if (stackCount == 0) {
       return null;
     }
     Object[] stackTypes = new Object[stackCount];
     for (int i = 0; i < stackCount; i++) {
-      stackTypes[i] = getType(stack.get(i));
+      stackTypes[i] = getType(stack.get(i), lens);
     }
     return stackTypes;
   }
@@ -78,7 +79,7 @@
     return localsCount;
   }
 
-  private Object[] computeLocalsTypes(int localsCount) {
+  private Object[] computeLocalsTypes(int localsCount, NamingLens lens) {
     if (localsCount == 0) {
       return null;
     }
@@ -87,7 +88,7 @@
     int localIndex = 0;
     for (int i = 0; i <= maxRegister; i++) {
       DexType type = locals.get(i);
-      Object typeOpcode = getType(type);
+      Object typeOpcode = getType(type, lens);
       localsTypes[localIndex++] = typeOpcode;
       if (type != null && isWide(type)) {
         i++;
@@ -96,7 +97,7 @@
     return localsTypes;
   }
 
-  private Object getType(DexType type) {
+  private Object getType(DexType type, NamingLens lens) {
     if (type == null) {
       return Opcodes.TOP;
     }
@@ -105,7 +106,7 @@
     }
     switch (type.toShorty()) {
       case 'L':
-        return type.getInternalName();
+        return lens.lookupInternalName(type);
       case 'I':
         return Opcodes.INTEGER;
       case 'F':
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 c881e7b..47cfed6 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
@@ -4,6 +4,7 @@
 package com.android.tools.r8.cf.code;
 
 import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
@@ -20,7 +21,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, 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 d928ff7..d39c358 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
@@ -8,6 +8,7 @@
 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;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
@@ -60,7 +61,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, 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 dc8b63f..2a076e4 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
@@ -8,6 +8,7 @@
 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;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
@@ -60,7 +61,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, NamingLens lens) {
     visitor.visitJumpInsn(getOpcode(), target.getLabel());
   }
 }
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 8daed44..deba4ad 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
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
@@ -22,8 +23,8 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
-    visitor.visitTypeInsn(Opcodes.INSTANCEOF, type.getInternalName());
+  public void write(MethodVisitor visitor, NamingLens lens) {
+    visitor.visitTypeInsn(Opcodes.INSTANCEOF, lens.lookupInternalName(type));
   }
 
   @Override
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 72c457f..04ab380 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
@@ -6,11 +6,12 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 
 public abstract class CfInstruction {
 
-  public abstract void write(MethodVisitor visitor);
+  public abstract void write(MethodVisitor visitor, 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 6fdf2bb..82f2438 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
@@ -9,6 +9,7 @@
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
@@ -36,10 +37,10 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
-    String owner = method.getHolder().getInternalName();
-    String name = method.name.toString();
-    String desc = method.proto.toDescriptorString();
+  public void write(MethodVisitor visitor, NamingLens lens) {
+    String owner = lens.lookupInternalName(method.getHolder());
+    String name = lens.lookupName(method).toString();
+    String desc = method.proto.toDescriptorString(lens);
     visitor.visitMethodInsn(opcode, owner, name, desc, itf);
   }
 
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 22841e3..ca8f7cb 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.DexValueString;
 import com.android.tools.r8.graph.DexValue.DexValueType;
 import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.naming.NamingLens;
 import java.util.List;
 import org.objectweb.asm.Handle;
 import org.objectweb.asm.MethodVisitor;
@@ -32,14 +33,14 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, NamingLens lens) {
     DexMethodHandle bootstrapMethod = callSite.bootstrapMethod;
     List<DexValue> bootstrapArgs = callSite.bootstrapArgs;
     Object[] bsmArgs = new Object[bootstrapArgs.size()];
     for (int i = 0; i < bootstrapArgs.size(); i++) {
-      bsmArgs[i] = decodeBootstrapArgument(bootstrapArgs.get(i));
+      bsmArgs[i] = decodeBootstrapArgument(bootstrapArgs.get(i), lens);
     }
-    Handle bsmHandle = bootstrapMethod.toAsmHandle();
+    Handle bsmHandle = bootstrapMethod.toAsmHandle(lens);
     visitor.visitInvokeDynamicInsn(
         callSite.methodName.toString(),
         callSite.methodProto.toDescriptorString(),
@@ -47,7 +48,7 @@
         bsmArgs);
   }
 
-  private Object decodeBootstrapArgument(DexValue dexValue) {
+  private Object decodeBootstrapArgument(DexValue dexValue, NamingLens lens) {
     if (dexValue instanceof DexValueInt) {
       return ((DexValueInt) dexValue).getValue();
     } else if (dexValue instanceof DexValueLong) {
@@ -63,7 +64,7 @@
     } else if (dexValue instanceof DexValueMethodType) {
       return Type.getMethodType(((DexValueMethodType) dexValue).value.toDescriptorString());
     } else if (dexValue instanceof DexValueMethodHandle) {
-      return ((DexValueMethodHandle) dexValue).value.toAsmHandle();
+      return ((DexValueMethodHandle) dexValue).value.toAsmHandle(lens);
     } else {
       throw new Unreachable(
           "Unsupported bootstrap argument of type " + dexValue.getClass().getSimpleName());
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 13d9078..401e4e8 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
@@ -4,6 +4,7 @@
 package com.android.tools.r8.cf.code;
 
 import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.Label;
 import org.objectweb.asm.MethodVisitor;
 
@@ -24,7 +25,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, 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 7d6be37..58c59a5 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.ir.code.ValueType;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
@@ -37,7 +38,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, NamingLens lens) {
     visitor.visitVarInsn(getLoadType(), var);
   }
 
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 76052c5..b38ef12 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.ir.code.Monitor.Type;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
@@ -21,7 +22,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, 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 e5c8455..a2f3da2 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
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 
 public class CfMultiANewArray extends CfInstruction {
@@ -27,8 +28,8 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
-    visitor.visitMultiANewArrayInsn(type.getInternalName(), dimensions);
+  public void write(MethodVisitor visitor, NamingLens lens) {
+    visitor.visitMultiANewArrayInsn(lens.lookupInternalName(type), dimensions);
   }
 
   @Override
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 ff2cd4b..b7261b6 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
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
@@ -22,8 +23,8 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
-    visitor.visitTypeInsn(Opcodes.NEW, type.getInternalName());
+  public void write(MethodVisitor visitor, NamingLens lens) {
+    visitor.visitTypeInsn(Opcodes.NEW, lens.lookupInternalName(type));
   }
 
   @Override
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 c199551..708a414 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
@@ -7,9 +7,10 @@
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.naming.NamingLens;
+import com.android.tools.r8.utils.DescriptorUtils;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
 
 public class CfNewArray extends CfInstruction {
 
@@ -47,17 +48,20 @@
     }
   }
 
-  private String getElementInternalName() {
+  private String getElementInternalName(NamingLens lens) {
     assert !type.isPrimitiveArrayType();
-    return Type.getType(type.toDescriptorString().substring(1)).getInternalName();
+    String renamedArrayType = lens.lookupDescriptor(type).toString();
+    assert renamedArrayType.charAt(0) == '[';
+    String elementType = renamedArrayType.substring(1);
+    return DescriptorUtils.descriptorToInternalName(elementType);
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, NamingLens lens) {
     if (type.isPrimitiveArrayType()) {
       visitor.visitIntInsn(Opcodes.NEWARRAY, getPrimitiveTypeCode());
     } else {
-      visitor.visitTypeInsn(Opcodes.ANEWARRAY, getElementInternalName());
+      visitor.visitTypeInsn(Opcodes.ANEWARRAY, getElementInternalName(lens));
     }
   }
 
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 e8eb664..2cdd37c 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
@@ -4,13 +4,14 @@
 package com.android.tools.r8.cf.code;
 
 import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
 public class CfNop extends CfInstruction {
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, NamingLens lens) {
     visitor.visitInsn(Opcodes.NOP);
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfPop.java b/src/main/java/com/android/tools/r8/cf/code/CfPop.java
index 68cedb9..9f485d2 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfPop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfPop.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.ir.code.ValueType;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
@@ -17,7 +18,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, NamingLens lens) {
     visitor.visitInsn(type.isWide() ? Opcodes.POP2 : Opcodes.POP);
   }
 
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 8004ad8..169d252 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.ir.code.Position;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 
 public class CfPosition extends CfInstruction {
@@ -18,7 +19,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, 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 c426dbd..7993919 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.ir.code.ValueType;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
@@ -39,7 +40,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, 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 b8bfc7d..7d98073 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
@@ -4,13 +4,14 @@
 package com.android.tools.r8.cf.code;
 
 import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
 public class CfReturnVoid extends CfInstruction {
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, NamingLens lens) {
     visitor.visitInsn(Opcodes.RETURN);
   }
 
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 2526a58..817045c 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.ir.code.ValueType;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
@@ -37,7 +38,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, 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 6d84c85..f27064c 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
@@ -4,6 +4,7 @@
 package com.android.tools.r8.cf.code;
 
 import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.naming.NamingLens;
 import it.unimi.dsi.fastutil.ints.IntArrayList;
 import it.unimi.dsi.fastutil.ints.IntList;
 import java.util.List;
@@ -44,7 +45,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, 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 cff3a8c..ef73d10 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
@@ -4,13 +4,14 @@
 package com.android.tools.r8.cf.code;
 
 import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
 public class CfThrow extends CfInstruction {
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, NamingLens lens) {
     visitor.visitInsn(Opcodes.ATHROW);
   }
 
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfUnop.java b/src/main/java/com/android/tools/r8/cf/code/CfUnop.java
index 6e50bb7..6b4bf76 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfUnop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfUnop.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.cf.code;
 
 import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.MethodVisitor;
 
 public class CfUnop extends CfInstruction {
@@ -15,7 +16,7 @@
   }
 
   @Override
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, NamingLens lens) {
     visitor.visitInsn(this.opcode);
   }
 
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 18a4e78..a14811a 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.ir.code.Position;
 import com.android.tools.r8.ir.code.ValueNumberGenerator;
 import com.android.tools.r8.naming.ClassNameMapper;
+import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.utils.InternalOptions;
 import java.util.Collections;
 import java.util.List;
@@ -112,9 +113,9 @@
     return this;
   }
 
-  public void write(MethodVisitor visitor) {
+  public void write(MethodVisitor visitor, NamingLens namingLens) {
     for (CfInstruction instruction : instructions) {
-      instruction.write(visitor);
+      instruction.write(visitor, namingLens);
     }
     visitor.visitEnd();
     visitor.visitMaxs(maxStack, maxLocals);
@@ -128,14 +129,14 @@
             start,
             end,
             target,
-            guard == DexItemFactory.catchAllType ? null : guard.getInternalName());
+            guard == DexItemFactory.catchAllType ? null : namingLens.lookupInternalName(guard));
       }
     }
     for (LocalVariableInfo localVariable : localVariables) {
       DebugLocalInfo info = localVariable.local;
       visitor.visitLocalVariable(
           info.name.toString(),
-          info.type.toDescriptorString(),
+          namingLens.lookupDescriptor(info.type).toString(),
           info.signature == null ? null : info.signature.toString(),
           localVariable.start.getLabel(),
           localVariable.end.getLabel(),
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index b71e4c5..0a357bf 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -38,6 +38,7 @@
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
 import com.android.tools.r8.naming.MemberNaming.Signature;
+import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.utils.InternalOptions;
 import java.util.Collections;
 import java.util.List;
@@ -296,13 +297,17 @@
   }
 
   public String descriptor() {
+    return descriptor(NamingLens.getIdentityLens());
+  }
+
+  public String descriptor(NamingLens namingLens) {
     StringBuilder builder = new StringBuilder();
     builder.append("(");
     for (DexType type : method.proto.parameters.values) {
-      builder.append(type.descriptor.toString());
+      builder.append(namingLens.lookupDescriptor(type).toString());
     }
     builder.append(")");
-    builder.append(method.proto.returnType.descriptor.toString());
+    builder.append(namingLens.lookupDescriptor(method.proto.returnType).toString());
     return builder.toString();
   }
 
diff --git a/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java b/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java
index 8b98b7c..a9e3b8e 100644
--- a/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java
@@ -292,16 +292,16 @@
     return sortedCompareTo(other.getSortedIndex());
   }
 
-  public Handle toAsmHandle() {
+  public Handle toAsmHandle(NamingLens lens) {
     String owner;
     String name;
     String desc;
     boolean itf;
     if (isMethodHandle()) {
       DexMethod method = asMethod();
-      owner = method.holder.getInternalName();
-      name = method.name.toString();
-      desc = method.proto.toDescriptorString();
+      owner = lens.lookupInternalName(method.holder);
+      name = lens.lookupName(method).toString();
+      desc = method.proto.toDescriptorString(lens);
       if (method.holder.toDescriptorString().equals("Ljava/lang/invoke/LambdaMetafactory;")) {
         itf = false;
       } else {
@@ -310,9 +310,9 @@
     } else {
       assert isFieldHandle();
       DexField field = asField();
-      owner = field.clazz.getInternalName();
-      name = field.name.toString();
-      desc = field.type.toDescriptorString();
+      owner = lens.lookupInternalName(field.clazz);
+      name = lens.lookupName(field).toString();
+      desc = lens.lookupDescriptor(field.type).toString();
       itf = field.clazz.isInterface();
     }
     return new Handle(getAsmTag(), owner, name, desc, itf);
diff --git a/src/main/java/com/android/tools/r8/graph/DexProto.java b/src/main/java/com/android/tools/r8/graph/DexProto.java
index 69eaeb5..7acab73 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProto.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProto.java
@@ -93,13 +93,17 @@
   }
 
   public String toDescriptorString() {
+    return toDescriptorString(NamingLens.getIdentityLens());
+  }
+
+  public String toDescriptorString(NamingLens lens) {
     StringBuilder builder = new StringBuilder();
     builder.append("(");
     for (int i = 0; i < parameters.values.length; i++) {
-      builder.append(parameters.values[i].toDescriptorString());
+      builder.append(lens.lookupDescriptor(parameters.values[i]));
     }
     builder.append(")");
-    builder.append(returnType.toDescriptorString());
+    builder.append(lens.lookupDescriptor(returnType));
     return builder.toString();
   }
 }
diff --git a/src/main/java/com/android/tools/r8/graph/DexType.java b/src/main/java/com/android/tools/r8/graph/DexType.java
index cc1f8e7..820e20b 100644
--- a/src/main/java/com/android/tools/r8/graph/DexType.java
+++ b/src/main/java/com/android/tools/r8/graph/DexType.java
@@ -463,8 +463,7 @@
   /** Get the fully qualified name using '/' in place of '.', ala the "internal type name" in ASM */
   public String getInternalName() {
     assert isClassType() || isArrayType();
-    String descriptor = toDescriptorString();
-    return isArrayType() ? descriptor : descriptor.substring(1, descriptor.length() - 1);
+    return DescriptorUtils.descriptorToInternalName(toDescriptorString());
   }
 
   public boolean isImmediateSubtypeOf(DexType type) {
diff --git a/src/main/java/com/android/tools/r8/graph/EnclosingMethodAttribute.java b/src/main/java/com/android/tools/r8/graph/EnclosingMethodAttribute.java
index fc5589f..57bc3c4 100644
--- a/src/main/java/com/android/tools/r8/graph/EnclosingMethodAttribute.java
+++ b/src/main/java/com/android/tools/r8/graph/EnclosingMethodAttribute.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.graph;
 
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.ClassWriter;
 
 /**
@@ -31,14 +32,14 @@
     this.enclosingMethod = enclosingMethod;
   }
 
-  public void write(ClassWriter writer) {
+  public void write(ClassWriter writer, NamingLens lens) {
     if (enclosingMethod != null) {
       writer.visitOuterClass(
-          enclosingMethod.getHolder().getInternalName(),
-          enclosingMethod.name.toString(),
-          enclosingMethod.proto.toDescriptorString());
+          lens.lookupInternalName(enclosingMethod.getHolder()),
+          lens.lookupName(enclosingMethod).toString(),
+          enclosingMethod.proto.toDescriptorString(lens));
     } else {
-      writer.visitOuterClass(enclosingClass.getInternalName(), null, null);
+      writer.visitOuterClass(lens.lookupInternalName(enclosingClass), null, null);
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/graph/InnerClassAttribute.java b/src/main/java/com/android/tools/r8/graph/InnerClassAttribute.java
index ed22c96..cd62ef3 100644
--- a/src/main/java/com/android/tools/r8/graph/InnerClassAttribute.java
+++ b/src/main/java/com/android/tools/r8/graph/InnerClassAttribute.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.graph;
 
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.naming.NamingLens;
 import org.objectweb.asm.ClassWriter;
 
 /** Representation of an entry in the Java InnerClasses attribute table. */
@@ -59,11 +60,13 @@
     return innerName;
   }
 
-  public void write(ClassWriter writer) {
+  public void write(ClassWriter writer, NamingLens lens) {
+    String internalName = lens.lookupInternalName(inner);
+    String simpleName = lens.lookupSimpleName(inner, innerName);
     writer.visitInnerClass(
-        inner.getInternalName(),
-        outer == null ? null : outer.getInternalName(),
-        innerName == null ? null : innerName.toString(),
+        internalName,
+        outer == null ? null : lens.lookupInternalName(outer),
+        innerName == null ? null : simpleName,
         access);
   }
 
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index 5eb2bb7..c8be00e 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -108,25 +108,27 @@
     writer.visitSource(clazz.sourceFile != null ? clazz.sourceFile.toString() : null, null);
     int version = clazz.getClassFileVersion();
     int access = clazz.accessFlags.getAsCfAccessFlags();
-    String desc = clazz.type.toDescriptorString();
-    String name = clazz.type.getInternalName();
+    String desc = namingLens.lookupDescriptor(clazz.type).toString();
+    String name = namingLens.lookupInternalName(clazz.type);
     String signature = getSignature(clazz.annotations);
     String superName =
-        clazz.type == options.itemFactory.objectType ? null : clazz.superType.getInternalName();
+        clazz.type == options.itemFactory.objectType
+            ? null
+            : namingLens.lookupInternalName(clazz.superType);
     String[] interfaces = new String[clazz.interfaces.values.length];
     for (int i = 0; i < clazz.interfaces.values.length; i++) {
-      interfaces[i] = clazz.interfaces.values[i].getInternalName();
+      interfaces[i] = namingLens.lookupInternalName(clazz.interfaces.values[i]);
     }
     writer.visit(version, access, name, signature, superName, interfaces);
     writeAnnotations(writer::visitAnnotation, clazz.annotations.annotations);
     ImmutableMap<DexString, DexValue> defaults = getAnnotationDefaults(clazz.annotations);
 
     if (clazz.getEnclosingMethod() != null) {
-      clazz.getEnclosingMethod().write(writer);
+      clazz.getEnclosingMethod().write(writer, namingLens);
     }
 
     for (InnerClassAttribute entry : clazz.getInnerClasses()) {
-      entry.write(writer);
+      entry.write(writer, namingLens);
     }
 
     for (DexEncodedField field : clazz.staticFields()) {
@@ -175,6 +177,7 @@
     if (value == null) {
       return null;
     }
+    // Signature has already been minified by ClassNameMinifier.renameTypesInGenericSignatures().
     DexValue[] parts = value.getValues();
     StringBuilder res = new StringBuilder();
     for (DexValue part : parts) {
@@ -208,7 +211,7 @@
     DexValue[] values = value.getValues();
     String[] res = new String[values.length];
     for (int i = 0; i < values.length; i++) {
-      res[i] = ((DexValueType) values[i]).value.getInternalName();
+      res[i] = namingLens.lookupInternalName(((DexValueType) values[i]).value);
     }
     return res;
   }
@@ -222,8 +225,8 @@
 
   private void writeField(DexEncodedField field, ClassWriter writer) {
     int access = field.accessFlags.getAsCfAccessFlags();
-    String name = field.field.name.toString();
-    String desc = field.field.type.toDescriptorString();
+    String name = namingLens.lookupName(field.field).toString();
+    String desc = namingLens.lookupDescriptor(field.field.type).toString();
     String signature = getSignature(field.annotations);
     Object value = getStaticValue(field);
     FieldVisitor visitor = writer.visitField(access, name, desc, signature, value);
@@ -234,8 +237,8 @@
   private void writeMethod(
       DexEncodedMethod method, ClassWriter writer, ImmutableMap<DexString, DexValue> defaults) {
     int access = method.accessFlags.getAsCfAccessFlags();
-    String name = method.method.name.toString();
-    String desc = method.descriptor();
+    String name = namingLens.lookupName(method.method).toString();
+    String desc = method.descriptor(namingLens);
     String signature = getSignature(method.annotations);
     String[] exceptions = getExceptions(method.annotations);
     MethodVisitor visitor = writer.visitMethod(access, name, desc, signature, exceptions);
@@ -332,10 +335,11 @@
 
   private void writeCode(Code code, MethodVisitor visitor) {
     if (code.isJarCode()) {
+      assert namingLens.isIdentityLens();
       code.asJarCode().writeTo(visitor);
     } else {
       assert code.isCfCode();
-      code.asCfCode().write(visitor);
+      code.asCfCode().write(visitor, namingLens);
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
index dd00254..4f49fbe 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
@@ -438,14 +438,15 @@
           appInfo.dexItemFactory.createType(
               getDescriptorFromClassBinaryName(
                   getClassBinaryNameFromDescriptor(enclosingDescriptor)
-                  + '$' + name));
+                      + Minifier.INNER_CLASS_SEPARATOR
+                      + name));
       String enclosingRenamedBinaryName =
           getClassBinaryNameFromDescriptor(
               renaming.getOrDefault(enclosingType, enclosingType.descriptor).toString());
       String renamed =
           getClassBinaryNameFromDescriptor(
               renaming.getOrDefault(type, type.descriptor).toString());
-      assert renamed.startsWith(enclosingRenamedBinaryName + '$');
+      assert renamed.startsWith(enclosingRenamedBinaryName + Minifier.INNER_CLASS_SEPARATOR);
       String outName = renamed.substring(enclosingRenamedBinaryName.length() + 1);
       renamedSignature.append(outName);
       return type;
diff --git a/src/main/java/com/android/tools/r8/naming/Minifier.java b/src/main/java/com/android/tools/r8/naming/Minifier.java
index 82eb242..6bd0c6d 100644
--- a/src/main/java/com/android/tools/r8/naming/Minifier.java
+++ b/src/main/java/com/android/tools/r8/naming/Minifier.java
@@ -25,6 +25,8 @@
 
 public class Minifier {
 
+  static final char INNER_CLASS_SEPARATOR = '$';
+
   private final AppInfoWithLiveness appInfo;
   private final RootSet rootSet;
   private final InternalOptions options;
@@ -77,6 +79,12 @@
     }
 
     @Override
+    public String lookupSimpleName(DexType inner, DexString innerName) {
+      String internalName = lookupInternalName(inner);
+      return internalName.substring(internalName.lastIndexOf(INNER_CLASS_SEPARATOR) + 1);
+    }
+
+    @Override
     public DexString lookupName(DexMethod method) {
       return renaming.getOrDefault(method, method.name);
     }
diff --git a/src/main/java/com/android/tools/r8/naming/NamingLens.java b/src/main/java/com/android/tools/r8/naming/NamingLens.java
index ca6c1c8..fe73dc5 100644
--- a/src/main/java/com/android/tools/r8/naming/NamingLens.java
+++ b/src/main/java/com/android/tools/r8/naming/NamingLens.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.optimize.MemberRebindingAnalysis;
+import com.android.tools.r8.utils.DescriptorUtils;
 import com.google.common.collect.ImmutableMap;
 import java.util.Map;
 import java.util.function.Consumer;
@@ -30,6 +31,8 @@
 
   public abstract DexString lookupDescriptor(DexType type);
 
+  public abstract String lookupSimpleName(DexType inner, DexString innerName);
+
   public abstract DexString lookupName(DexMethod method);
 
   public abstract DexString lookupName(DexField field);
@@ -42,6 +45,11 @@
     return this instanceof IdentityLens;
   }
 
+  public String lookupInternalName(DexType type) {
+    assert type.isClassType() || type.isArrayType();
+    return DescriptorUtils.descriptorToInternalName(lookupDescriptor(type).toString());
+  }
+
   abstract void forAllRenamedTypes(Consumer<DexType> consumer);
 
   abstract <T extends DexItem> Map<String, T> getRenamedItems(
@@ -68,6 +76,11 @@
     }
 
     @Override
+    public String lookupSimpleName(DexType inner, DexString innerName) {
+      return innerName == null ? null : innerName.toString();
+    }
+
+    @Override
     public DexString lookupName(DexMethod method) {
       return method.name;
     }
diff --git a/src/main/java/com/android/tools/r8/utils/DescriptorUtils.java b/src/main/java/com/android/tools/r8/utils/DescriptorUtils.java
index b79e8e6..fa045e6 100644
--- a/src/main/java/com/android/tools/r8/utils/DescriptorUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/DescriptorUtils.java
@@ -138,6 +138,23 @@
   }
 
   /**
+   * Convert a class type descriptor to an ASM internal name.
+   *
+   * @param descriptor type descriptor
+   * @return Java type name
+   */
+  public static String descriptorToInternalName(String descriptor) {
+    switch (descriptor.charAt(0)) {
+      case '[':
+        return descriptor;
+      case 'L':
+        return descriptor.substring(1, descriptor.length() - 1);
+      default:
+        throw new Unreachable("Not array or class type");
+    }
+  }
+
+  /**
    * Convert a type descriptor to a Java type name. Will also deobfuscate class names if a
    * class mapper is provided.
    *
diff --git a/src/test/java/com/android/tools/r8/debug/MinificationTest.java b/src/test/java/com/android/tools/r8/debug/MinificationTest.java
index 5f63038..2f995db 100644
--- a/src/test/java/com/android/tools/r8/debug/MinificationTest.java
+++ b/src/test/java/com/android/tools/r8/debug/MinificationTest.java
@@ -3,13 +3,20 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.debug;
 
+import static org.junit.Assert.assertTrue;
+
 import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.TestBase.MinifyMode;
 import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.debug.DebugTestConfig.RuntimeKind;
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.naming.MemberNaming.MethodSignature;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.DexInspector;
+import com.android.tools.r8.utils.DexInspector.ClassSubject;
 import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
 import com.google.common.collect.ImmutableList;
 import java.nio.file.Path;
@@ -28,13 +35,15 @@
 
   private static final String SOURCE_FILE = "Minified.java";
 
-  @Parameterized.Parameters(name = "minification: {0}, proguardMap: {1}")
+  @Parameterized.Parameters(name = "backend:{0} minification:{1} proguardMap:{2}")
   public static Collection minificationControl() {
     ImmutableList.Builder<Object> builder = ImmutableList.builder();
-    for (MinifyMode mode : MinifyMode.values()) {
-      builder.add((Object) new Object[]{mode, false});
-      if (mode.isMinify()) {
-        builder.add((Object) new Object[]{mode, true});
+    for (RuntimeKind kind : RuntimeKind.values()) {
+      for (MinifyMode mode : MinifyMode.values()) {
+        builder.add((Object) new Object[] {kind, mode, false});
+        if (mode.isMinify()) {
+          builder.add((Object) new Object[] {kind, mode, true});
+        }
       }
     }
     return builder.build();
@@ -43,10 +52,13 @@
   @Rule
   public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
 
+  private final RuntimeKind runtimeKind;
   private final MinifyMode minificationMode;
   private final boolean writeProguardMap;
 
-  public MinificationTest(MinifyMode minificationMode, boolean writeProguardMap) throws Exception {
+  public MinificationTest(
+      RuntimeKind runtimeKind, MinifyMode minificationMode, boolean writeProguardMap) {
+    this.runtimeKind = runtimeKind;
     this.minificationMode = minificationMode;
     this.writeProguardMap = writeProguardMap;
   }
@@ -69,15 +81,19 @@
     }
 
     AndroidApiLevel minSdk = ToolHelper.getMinApiLevelForDexVm();
-    Path dexOutputDir = temp.newFolder().toPath();
-    Path proguardMap = writeProguardMap ? dexOutputDir.resolve("proguard.map") : null;
+    Path outputPath = temp.getRoot().toPath().resolve("classes.zip");
+    Path proguardMap = writeProguardMap ? temp.getRoot().toPath().resolve("proguard.map") : null;
+    OutputMode outputMode =
+        runtimeKind == RuntimeKind.CF ? OutputMode.ClassFile : OutputMode.DexIndexed;
     R8Command.Builder builder =
         R8Command.builder()
             .addProgramFiles(DEBUGGEE_JAR)
-            .setOutput(dexOutputDir, OutputMode.DexIndexed)
-            .setMinApiLevel(minSdk.getLevel())
+            .setOutput(outputPath, outputMode)
             .setMode(CompilationMode.DEBUG)
             .addLibraryFiles(ToolHelper.getAndroidJar(minSdk));
+    if (runtimeKind != RuntimeKind.CF) {
+      builder.setMinApiLevel(minSdk.getLevel());
+    }
     if (proguardMap != null) {
       builder.setProguardMapOutputPath(proguardMap);
     }
@@ -91,9 +107,22 @@
             ? (oc -> oc.lineNumberOptimization = LineNumberOptimization.OFF)
             : null);
 
-    DexDebugTestConfig config = new DexDebugTestConfig(dexOutputDir.resolve("classes.dex"));
-    config.setProguardMap(proguardMap);
-    return config;
+    switch (runtimeKind) {
+      case CF:
+        {
+          CfDebugTestConfig config = new CfDebugTestConfig(outputPath);
+          config.setProguardMap(proguardMap);
+          return config;
+        }
+      case DEX:
+        {
+          DexDebugTestConfig config = new DexDebugTestConfig(outputPath);
+          config.setProguardMap(proguardMap);
+          return config;
+        }
+      default:
+        throw new Unreachable();
+    }
   }
 
   @Test
@@ -104,8 +133,15 @@
     final String innerClassName = minifiedNames() ? "a" : "Minified$Inner";
     final String innerMethodName = minifiedNames() ? "a" : "innerTest";
     final String innerSignature = "()I";
+    DebugTestConfig config = getTestConfig();
+    checkStructure(
+        config,
+        className,
+        MethodSignature.fromSignature(methodName, signature),
+        innerClassName,
+        MethodSignature.fromSignature(innerMethodName, innerSignature));
     runDebugTest(
-        getTestConfig(),
+        config,
         className,
         breakpoint(className, methodName, signature),
         run(),
@@ -126,8 +162,14 @@
     final String innerClassName = minifiedNames() ? "a" : "Minified$Inner";
     final String innerMethodName = minifiedNames() ? "a" : "innerTest";
     final String innerSignature = "()I";
+    DebugTestConfig config = getTestConfig();
+    checkStructure(
+        config,
+        className,
+        innerClassName,
+        MethodSignature.fromSignature(innerMethodName, innerSignature));
     runDebugTest(
-        getTestConfig(),
+        config,
         className,
         breakpoint(innerClassName, innerMethodName, innerSignature),
         run(),
@@ -135,4 +177,30 @@
         checkLine(SOURCE_FILE, 8),
         run());
   }
+
+  private void checkStructure(
+      DebugTestConfig config,
+      String className,
+      MethodSignature method,
+      String innerClassName,
+      MethodSignature innerMethod)
+      throws Throwable {
+    Path proguardMap = config.getProguardMap();
+    String mappingFile = proguardMap == null ? null : proguardMap.toString();
+    DexInspector inspector = new DexInspector(config.getPaths(), mappingFile);
+    ClassSubject clazz = inspector.clazz(className);
+    assertTrue(clazz.isPresent());
+    if (method != null) {
+      assertTrue(clazz.method(method).isPresent());
+    }
+    ClassSubject innerClass = inspector.clazz(innerClassName);
+    assertTrue(innerClass.isPresent());
+    assertTrue(innerClass.method(innerMethod).isPresent());
+  }
+
+  private void checkStructure(
+      DebugTestConfig config, String className, String innerClassName, MethodSignature innerMethod)
+      throws Throwable {
+    checkStructure(config, className, null, innerClassName, innerMethod);
+  }
 }