Merge CfExtended and CfPop into CfStackInstruction

Change-Id: I270c8aebcf2628bf5336b4208ccc7345acadb043
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 8763e64..e57f161 100644
--- a/src/main/java/com/android/tools/r8/cf/CfPrinter.java
+++ b/src/main/java/com/android/tools/r8/cf/CfPrinter.java
@@ -14,7 +14,6 @@
 import com.android.tools.r8.cf.code.CfConstNull;
 import com.android.tools.r8.cf.code.CfConstNumber;
 import com.android.tools.r8.cf.code.CfConstString;
-import com.android.tools.r8.cf.code.CfExtended;
 import com.android.tools.r8.cf.code.CfFieldInstruction;
 import com.android.tools.r8.cf.code.CfFrame;
 import com.android.tools.r8.cf.code.CfFrame.Uninitialized;
@@ -35,10 +34,10 @@
 import com.android.tools.r8.cf.code.CfNew;
 import com.android.tools.r8.cf.code.CfNewArray;
 import com.android.tools.r8.cf.code.CfNop;
-import com.android.tools.r8.cf.code.CfPop;
 import com.android.tools.r8.cf.code.CfPosition;
 import com.android.tools.r8.cf.code.CfReturn;
 import com.android.tools.r8.cf.code.CfReturnVoid;
+import com.android.tools.r8.cf.code.CfStackInstruction;
 import com.android.tools.r8.cf.code.CfStore;
 import com.android.tools.r8.cf.code.CfSwitch;
 import com.android.tools.r8.cf.code.CfSwitch.Kind;
@@ -154,10 +153,37 @@
     print("nop");
   }
 
-  public void print(CfExtended instruction) {
+  public void print(CfStackInstruction instruction) {
     switch (instruction.getOpcode()) {
+      case Pop:
+        print("pop");
+        return;
+      case Pop2:
+        print("pop2");
+        return;
+      case Dup:
+        print("dup");
+        return;
+      case DupX1:
+        print("dup_x1");
+        return;
+      case DupX2:
+        print("dup_x2");
+        return;
+      case Dup2:
+        print("dup2");
+        return;
+      case Dup2X1:
+        print("dup2_x1");
+        return;
+      case Dup2X2:
+        print("dup2_x2");
+        return;
+      case Swap:
+        print("swap");
+        return;
       default:
-        print("???");
+        throw new Unreachable("Invalid instruction for CfStackInstruction");
     }
   }
 
@@ -216,10 +242,6 @@
     print(opcodeName(unop.getOpcode()));
   }
 
-  public void print(CfPop pop) {
-    print("pop");
-  }
-
   public void print(CfConstString constString) {
     indent();
     builder.append("ldc ").append(constString.getString());
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfExtended.java b/src/main/java/com/android/tools/r8/cf/code/CfExtended.java
deleted file mode 100644
index c75f0e3..0000000
--- a/src/main/java/com/android/tools/r8/cf/code/CfExtended.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2018, 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.naming.NamingLens;
-import org.objectweb.asm.MethodVisitor;
-
-public class CfExtended extends CfInstruction {
-
-  private final int opcode;
-
-  public CfExtended(int opcode) {
-    this.opcode = opcode;
-  }
-
-  @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
-    visitor.visitInsn(opcode);
-  }
-
-  @Override
-  public void print(CfPrinter printer) {
-    printer.print(this);
-  }
-
-  public int getOpcode() {
-    return opcode;
-  }
-}
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
deleted file mode 100644
index 9f485d2..0000000
--- a/src/main/java/com/android/tools/r8/cf/code/CfPop.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2017, 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.ir.code.ValueType;
-import com.android.tools.r8.naming.NamingLens;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-
-public class CfPop extends CfInstruction {
-
-  private final ValueType type;
-
-  public CfPop(ValueType type) {
-    this.type = type;
-  }
-
-  @Override
-  public void write(MethodVisitor visitor, NamingLens lens) {
-    visitor.visitInsn(type.isWide() ? Opcodes.POP2 : Opcodes.POP);
-  }
-
-  @Override
-  public void print(CfPrinter printer) {
-    printer.print(this);
-  }
-}
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
new file mode 100644
index 0000000..efda3f6
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
@@ -0,0 +1,81 @@
+// Copyright (c) 2018, 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.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;
+
+public class CfStackInstruction extends CfInstruction {
+
+  public enum Opcode {
+    Pop(Opcodes.POP),
+    Pop2(Opcodes.POP2),
+    Dup(Opcodes.DUP),
+    DupX1(Opcodes.DUP_X1),
+    DupX2(Opcodes.DUP_X2),
+    Dup2(Opcodes.DUP2),
+    Dup2X1(Opcodes.DUP2_X1),
+    Dup2X2(Opcodes.DUP2_X2),
+    Swap(Opcodes.SWAP);
+
+    private final int opcode;
+
+    Opcode(int opcode) {
+      this.opcode = opcode;
+    }
+  }
+
+  private final Opcode opcode;
+
+  public static CfStackInstruction fromAsm(int opcode) {
+    switch (opcode) {
+      case Opcodes.POP:
+        return new CfStackInstruction(Opcode.Pop);
+      case Opcodes.POP2:
+        return new CfStackInstruction(Opcode.Pop2);
+      case Opcodes.DUP:
+        return new CfStackInstruction(Opcode.Dup);
+      case Opcodes.DUP_X1:
+        return new CfStackInstruction(Opcode.DupX1);
+      case Opcodes.DUP_X2:
+        return new CfStackInstruction(Opcode.DupX2);
+      case Opcodes.DUP2:
+        return new CfStackInstruction(Opcode.Dup2);
+      case Opcodes.DUP2_X1:
+        return new CfStackInstruction(Opcode.Dup2X1);
+      case Opcodes.DUP2_X2:
+        return new CfStackInstruction(Opcode.Dup2X2);
+      case Opcodes.SWAP:
+        return new CfStackInstruction(Opcode.Swap);
+      default:
+        throw new Unreachable("Invalid opcode for CfStackInstruction");
+    }
+  }
+
+  public static CfStackInstruction popType(ValueType type) {
+    return new CfStackInstruction(type.isWide() ? Opcode.Pop2 : Opcode.Pop);
+  }
+
+  public CfStackInstruction(Opcode opcode) {
+    this.opcode = opcode;
+  }
+
+  @Override
+  public void write(MethodVisitor visitor, NamingLens lens) {
+    visitor.visitInsn(opcode.opcode);
+  }
+
+  @Override
+  public void print(CfPrinter printer) {
+    printer.print(this);
+  }
+
+  public Opcode getOpcode() {
+    return opcode;
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
index b18e916..ee70e51 100644
--- a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
@@ -20,7 +20,6 @@
 import com.android.tools.r8.cf.code.CfConstNull;
 import com.android.tools.r8.cf.code.CfConstNumber;
 import com.android.tools.r8.cf.code.CfConstString;
-import com.android.tools.r8.cf.code.CfExtended;
 import com.android.tools.r8.cf.code.CfFieldInstruction;
 import com.android.tools.r8.cf.code.CfFrame;
 import com.android.tools.r8.cf.code.CfFrame.Uninitialized;
@@ -41,10 +40,10 @@
 import com.android.tools.r8.cf.code.CfNew;
 import com.android.tools.r8.cf.code.CfNewArray;
 import com.android.tools.r8.cf.code.CfNop;
-import com.android.tools.r8.cf.code.CfPop;
 import com.android.tools.r8.cf.code.CfPosition;
 import com.android.tools.r8.cf.code.CfReturn;
 import com.android.tools.r8.cf.code.CfReturnVoid;
+import com.android.tools.r8.cf.code.CfStackInstruction;
 import com.android.tools.r8.cf.code.CfStore;
 import com.android.tools.r8.cf.code.CfSwitch;
 import com.android.tools.r8.cf.code.CfThrow;
@@ -810,11 +809,7 @@
           instructions.add(new CfArrayStore(getMemberTypeForOpcode(opcode)));
           break;
         case Opcodes.POP:
-          instructions.add(new CfPop(ValueType.INT_OR_FLOAT_OR_NULL));
-          break;
         case Opcodes.POP2:
-          instructions.add(new CfPop(ValueType.LONG_OR_DOUBLE));
-          break;
         case Opcodes.DUP:
         case Opcodes.DUP_X1:
         case Opcodes.DUP_X2:
@@ -822,8 +817,7 @@
         case Opcodes.DUP2_X1:
         case Opcodes.DUP2_X2:
         case Opcodes.SWAP:
-          // TODO(mathiasr): Merge with POP/POP2; rename into CfStackInstruction with enum field.
-          instructions.add(new CfExtended(opcode));
+          instructions.add(CfStackInstruction.fromAsm(opcode));
           break;
         case Opcodes.IADD:
         case Opcodes.LADD:
diff --git a/src/main/java/com/android/tools/r8/ir/code/Pop.java b/src/main/java/com/android/tools/r8/ir/code/Pop.java
index 9e29aae..70d6af4 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Pop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Pop.java
@@ -4,7 +4,7 @@
 package com.android.tools.r8.ir.code;
 
 import com.android.tools.r8.cf.LoadStoreHelper;
-import com.android.tools.r8.cf.code.CfPop;
+import com.android.tools.r8.cf.code.CfStackInstruction;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.conversion.CfBuilder;
@@ -61,7 +61,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfPop(inValues.get(0).type));
+    builder.add(CfStackInstruction.popType(inValues.get(0).type));
   }
 
   @Override