Merge "Support private static interface methods"
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 86903fe..2f8de76 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
@@ -12,11 +12,15 @@
 
   private final DexMethod method;
   private final int opcode;
+  private final boolean itf;
 
-  public CfInvoke(int opcode, DexMethod method) {
+  public CfInvoke(int opcode, DexMethod method, boolean itf) {
     assert Opcodes.INVOKEVIRTUAL <= opcode && opcode <= Opcodes.INVOKEINTERFACE;
+    assert !(opcode == Opcodes.INVOKEVIRTUAL && itf) : "InvokeVirtual on interface type";
+    assert !(opcode == Opcodes.INVOKEINTERFACE && !itf) : "InvokeInterface on class type";
     this.opcode = opcode;
     this.method = method;
+    this.itf = itf;
   }
 
   public DexMethod getMethod() {
@@ -32,8 +36,7 @@
     String owner = method.getHolder().getInternalName();
     String name = method.name.toString();
     String desc = method.proto.toDescriptorString();
-    boolean isInterface = opcode == Opcodes.INVOKEINTERFACE;
-    visitor.visitMethodInsn(opcode, owner, name, desc, isInterface);
+    visitor.visitMethodInsn(opcode, owner, name, desc, itf);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Invoke.java b/src/main/java/com/android/tools/r8/ir/code/Invoke.java
index 7f24908..af6d5a3 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Invoke.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Invoke.java
@@ -39,15 +39,20 @@
 
   public static Invoke create(
       Type type, DexItem target, DexProto proto, Value result, List<Value> arguments) {
+    return create(type, target, proto, result, arguments, false);
+  }
+
+  public static Invoke create(
+      Type type, DexItem target, DexProto proto, Value result, List<Value> arguments, boolean itf) {
     switch (type) {
       case DIRECT:
-        return new InvokeDirect((DexMethod) target, result, arguments);
+        return new InvokeDirect((DexMethod) target, result, arguments, itf);
       case INTERFACE:
         return new InvokeInterface((DexMethod) target, result, arguments);
       case STATIC:
-        return new InvokeStatic((DexMethod) target, result, arguments);
+        return new InvokeStatic((DexMethod) target, result, arguments, itf);
       case SUPER:
-        return new InvokeSuper((DexMethod) target, result, arguments);
+        return new InvokeSuper((DexMethod) target, result, arguments, itf);
       case VIRTUAL:
         return new InvokeVirtual((DexMethod) target, result, arguments);
       case NEW_ARRAY:
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
index 7338a2b..fa85845 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
@@ -21,8 +21,15 @@
 
 public class InvokeDirect extends InvokeMethodWithReceiver {
 
+  private final boolean itf;
+
   public InvokeDirect(DexMethod target, Value result, List<Value> arguments) {
+    this(target, result, arguments, false);
+  }
+
+  public InvokeDirect(DexMethod target, Value result, List<Value> arguments, boolean itf) {
     super(target, result, arguments);
+    this.itf = itf;
   }
 
   @Override
@@ -114,6 +121,6 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfInvoke(Opcodes.INVOKESPECIAL, getInvokedMethod()));
+    builder.add(new CfInvoke(Opcodes.INVOKESPECIAL, getInvokedMethod(), itf));
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java b/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
index 60aee95..d29e3eb 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
@@ -103,6 +103,6 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfInvoke(Opcodes.INVOKEINTERFACE, getInvokedMethod()));
+    builder.add(new CfInvoke(Opcodes.INVOKEINTERFACE, getInvokedMethod(), true));
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java b/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java
index 01cd5f5..0e63cc7 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java
@@ -90,7 +90,7 @@
     // To translate InvokePolymorphic back into InvokeVirtual, use the original prototype
     // that is stored in getProto().
     DexMethod method = factory.createMethod(dexMethod.holder, getProto(), dexMethod.name);
-    builder.add(new CfInvoke(Opcodes.INVOKEVIRTUAL, method));
+    builder.add(new CfInvoke(Opcodes.INVOKEVIRTUAL, method, false));
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
index e628f39..896fca9 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
@@ -22,8 +22,15 @@
 
 public class InvokeStatic extends InvokeMethod {
 
+  private final boolean itf;
+
   public InvokeStatic(DexMethod target, Value result, List<Value> arguments) {
+    this(target, result, arguments, false);
+  }
+
+  public InvokeStatic(DexMethod target, Value result, List<Value> arguments, boolean itf) {
     super(target, result, arguments);
+    this.itf = itf;
   }
 
   @Override
@@ -109,7 +116,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfInvoke(Opcodes.INVOKESTATIC, getInvokedMethod()));
+    builder.add(new CfInvoke(Opcodes.INVOKESTATIC, getInvokedMethod(), itf));
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java b/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
index 9e9a096..c761184 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
@@ -22,8 +22,11 @@
 
 public class InvokeSuper extends InvokeMethodWithReceiver {
 
-  public InvokeSuper(DexMethod target, Value result, List<Value> arguments) {
+  public final boolean itf;
+
+  public InvokeSuper(DexMethod target, Value result, List<Value> arguments, boolean itf) {
     super(target, result, arguments);
+    this.itf = itf;
   }
 
   @Override
@@ -76,7 +79,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfInvoke(Opcodes.INVOKESPECIAL, getInvokedMethod()));
+    builder.add(new CfInvoke(Opcodes.INVOKESPECIAL, getInvokedMethod(), itf));
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
index 8a41c4e..5ef74b8 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
@@ -103,6 +103,6 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfInvoke(Opcodes.INVOKEVIRTUAL, getInvokedMethod()));
+    builder.add(new CfInvoke(Opcodes.INVOKEVIRTUAL, getInvokedMethod(), false));
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 20051f9..72402b3 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -997,7 +997,8 @@
     add(instruction);
   }
 
-  public void addInvoke(Type type, DexItem item, DexProto callSiteProto, List<Value> arguments)
+  public void addInvoke(
+      Type type, DexItem item, DexProto callSiteProto, List<Value> arguments, boolean itf)
       throws ApiLevelException {
     if (type == Invoke.Type.POLYMORPHIC) {
       assert item instanceof DexMethod;
@@ -1014,7 +1015,12 @@
             null /* sourceString */);
       }
     }
-    add(Invoke.create(type, item, callSiteProto, null, arguments));
+    add(Invoke.create(type, item, callSiteProto, null, arguments, itf));
+  }
+
+  public void addInvoke(Type type, DexItem item, DexProto callSiteProto, List<Value> arguments)
+      throws ApiLevelException {
+    addInvoke(type, item, callSiteProto, arguments, false);
   }
 
   public void addInvoke(
@@ -1024,12 +1030,23 @@
       List<ValueType> types,
       List<Integer> registers)
       throws ApiLevelException {
+    addInvoke(type, item, callSiteProto, types, registers, false);
+  }
+
+  public void addInvoke(
+      Invoke.Type type,
+      DexItem item,
+      DexProto callSiteProto,
+      List<ValueType> types,
+      List<Integer> registers,
+      boolean itf)
+      throws ApiLevelException {
     assert types.size() == registers.size();
     List<Value> arguments = new ArrayList<>(types.size());
     for (int i = 0; i < types.size(); i++) {
       arguments.add(readRegister(registers.get(i), types.get(i)));
     }
-    addInvoke(type, item, callSiteProto, arguments);
+    addInvoke(type, item, callSiteProto, arguments, itf);
   }
 
   public void addInvokeCustomRegisters(
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
index b584448..a20a0a1 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
@@ -2606,7 +2606,7 @@
             }
             callSiteProto = application.getProto(insn.desc);
           }
-          builder.addInvoke(invokeType, targetMethod, callSiteProto, types, registers);
+          builder.addInvoke(invokeType, targetMethod, callSiteProto, types, registers, insn.itf);
         });
   }
 
diff --git a/src/test/java/com/android/tools/r8/R8CFRunExamplesJava9Test.java b/src/test/java/com/android/tools/r8/R8CFRunExamplesJava9Test.java
index f4d3da5..b3950b4 100644
--- a/src/test/java/com/android/tools/r8/R8CFRunExamplesJava9Test.java
+++ b/src/test/java/com/android/tools/r8/R8CFRunExamplesJava9Test.java
@@ -107,8 +107,6 @@
 
   private static List<String> expectedFailures =
       ImmutableList.of(
-          "native-private-interface-methods",
-          "desugared-private-interface-methods"
       );
 
   private boolean expectedToFailCf(String testName) {