Add IR instruction builders

Change-Id: Id24bbb84bbc185a58283c687bd980d3c8af3015b
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java b/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
index 865d83b..5afa942 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
@@ -44,6 +44,10 @@
     this.type = type;
   }
 
+  public static Builder builder() {
+    return new Builder();
+  }
+
   @Override
   public int opcode() {
     return Opcodes.ARRAY_GET;
@@ -299,4 +303,40 @@
   public void buildLir(LirBuilder<Value, ?> builder) {
     builder.addArrayGet(getMemberType(), array(), index());
   }
+
+  public static class Builder extends BuilderBase<Builder, ArrayGet> {
+
+    private Value arrayValue;
+    private Value indexValue;
+    private MemberType memberType;
+
+    public Builder setArrayValue(Value arrayValue) {
+      this.arrayValue = arrayValue;
+      return this;
+    }
+
+    public Builder setIndexValue(Value indexValue) {
+      this.indexValue = indexValue;
+      return this;
+    }
+
+    public Builder setMemberType(MemberType memberType) {
+      this.memberType = memberType;
+      return this;
+    }
+
+    @Override
+    public ArrayGet build() {
+      if (memberType == null && outValue.getType().isReferenceType()) {
+        memberType = MemberType.OBJECT;
+      }
+      assert memberType != null;
+      return amend(new ArrayGet(memberType, outValue, arrayValue, indexValue));
+    }
+
+    @Override
+    public Builder self() {
+      return this;
+    }
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/code/Instruction.java b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
index 126f23a..9b4fffb 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
@@ -45,6 +45,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.function.Consumer;
 import java.util.function.Predicate;
 
 public abstract class Instruction
@@ -1764,6 +1765,13 @@
     protected Value outValue;
     protected Position position;
 
+    public final B applyIf(boolean condition, Consumer<B> consumer) {
+      if (condition) {
+        consumer.accept(self());
+      }
+      return self();
+    }
+
     public abstract I build();
 
     public abstract B self();
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 b60c42e..c448a2d 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
@@ -52,6 +52,11 @@
   }
 
   @Override
+  public Builder newBuilder() {
+    return builder();
+  }
+
+  @Override
   public int opcode() {
     return Opcodes.INVOKE_DIRECT;
   }
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 f677699..e4c26ae 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
@@ -32,6 +32,15 @@
     super(target, result, arguments);
   }
 
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  @Override
+  public Builder newBuilder() {
+    return builder();
+  }
+
   @Override
   public boolean getInterfaceBit() {
     return true;
@@ -147,4 +156,17 @@
   public void buildLir(LirBuilder<Value, ?> builder) {
     builder.addInvokeInterface(getInvokedMethod(), arguments());
   }
+
+  public static class Builder extends InvokeMethod.Builder<Builder, InvokeInterface> {
+
+    @Override
+    public InvokeInterface build() {
+      return amend(new InvokeInterface(method, outValue, arguments));
+    }
+
+    @Override
+    public Builder self() {
+      return this;
+    }
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java b/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
index e15b67c..c40827c 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
@@ -77,6 +77,8 @@
     }
   }
 
+  public abstract Builder<? extends Builder, ? extends InvokeMethod> newBuilder();
+
   public Value getFirstNonReceiverArgument() {
     return getArgument(getFirstNonReceiverArgumentIndex());
   }
@@ -346,11 +348,12 @@
     return false;
   }
 
-  abstract static class Builder<B extends Builder<B, I>, I extends InvokeMethod>
+  public abstract static class Builder<B extends Builder<B, I>, I extends InvokeMethod>
       extends BuilderBase<B, I> {
 
     protected DexMethod method;
     protected List<Value> arguments = Collections.emptyList();
+    protected boolean isInterface = false;
 
     public B setArguments(Value... arguments) {
       return setArguments(Arrays.asList(arguments));
@@ -367,6 +370,11 @@
           factory, TypeElement.fromDexType(method.getReturnType(), maybeNull(), appView));
     }
 
+    public B setIsInterface(boolean isInterface) {
+      this.isInterface = isInterface;
+      return self();
+    }
+
     public B setSingleArgument(Value argument) {
       return setArguments(ImmutableList.of(argument));
     }
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 9ef005e..601448c 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
@@ -37,6 +37,11 @@
   }
 
   @Override
+  public Builder<? extends Builder, ? extends InvokeMethod> newBuilder() {
+    throw new Unreachable();
+  }
+
+  @Override
   public boolean getInterfaceBit() {
     return false;
   }
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 8abaa2c..16f0c04 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
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.ir.code;
 
-
 import com.android.tools.r8.cf.code.CfInvoke;
 import com.android.tools.r8.dex.code.DexInstruction;
 import com.android.tools.r8.dex.code.DexInvokeStatic;
@@ -48,6 +47,11 @@
   }
 
   @Override
+  public Builder newBuilder() {
+    return builder();
+  }
+
+  @Override
   public boolean getInterfaceBit() {
     return isInterface;
   }
@@ -229,7 +233,7 @@
       assert method != null;
       assert method.getArity() == arguments.size();
       assert outValue == null || !method.getReturnType().isVoidType();
-      return amend(new InvokeStatic(method, outValue, arguments));
+      return amend(new InvokeStatic(method, outValue, arguments, isInterface));
     }
 
     @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 d1d9ad4..b5520a0 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
@@ -34,6 +34,15 @@
     this.isInterface = isInterface;
   }
 
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  @Override
+  public Builder newBuilder() {
+    return builder();
+  }
+
   @Override
   public boolean getInterfaceBit() {
     return isInterface;
@@ -132,4 +141,17 @@
   public void buildLir(LirBuilder<Value, ?> builder) {
     builder.addInvokeSuper(getInvokedMethod(), arguments(), isInterface);
   }
+
+  public static class Builder extends InvokeMethod.Builder<Builder, InvokeSuper> {
+
+    @Override
+    public InvokeSuper build() {
+      return amend(new InvokeSuper(method, outValue, arguments, isInterface));
+    }
+
+    @Override
+    public Builder self() {
+      return this;
+    }
+  }
 }
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 6d97ebe..b1cf3bd 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
@@ -37,6 +37,11 @@
   }
 
   @Override
+  public Builder newBuilder() {
+    return builder();
+  }
+
+  @Override
   public boolean getInterfaceBit() {
     return false;
   }