Clean-up Synthesized Cf code

Change-Id: Ia14678369fa8d7bf6468302403f7b0ac3e019e50
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 16efa70..9944273 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -52,7 +52,7 @@
 import com.android.tools.r8.ir.optimize.info.MutableCallSiteOptimizationInfo;
 import com.android.tools.r8.ir.optimize.info.UpdatableMethodOptimizationInfo;
 import com.android.tools.r8.ir.regalloc.RegisterAllocator;
-import com.android.tools.r8.ir.synthetic.CfEmulateInterfaceSyntheticSourceCodeProvider;
+import com.android.tools.r8.ir.synthetic.EmulateInterfaceSyntheticCfCodeProvider;
 import com.android.tools.r8.ir.synthetic.FieldAccessorSourceCode;
 import com.android.tools.r8.ir.synthetic.ForwardMethodSourceCode;
 import com.android.tools.r8.ir.synthetic.SynthesizedCode;
@@ -881,7 +881,6 @@
       DexMethod libraryMethod,
       List<Pair<DexType, DexMethod>> extraDispatchCases,
       AppView<?> appView) {
-    // TODO(134732760): Deal with overrides for correct dispatch to implementations of Interfaces
     assert isDefaultMethod() || isStatic();
     DexEncodedMethod.Builder builder = DexEncodedMethod.builder(this);
     builder.setMethod(newMethod);
@@ -889,26 +888,11 @@
     builder.accessFlags.setStatic();
     builder.accessFlags.unsetPrivate();
     builder.accessFlags.setPublic();
-    DexEncodedMethod newEncodedMethod = builder.build();
-    newEncodedMethod.setCode(
-        new SynthesizedCode(
-            new CfEmulateInterfaceSyntheticSourceCodeProvider(
-                this.method.holder,
-                companionMethod,
-                newEncodedMethod,
-                libraryMethod,
-                this.method,
-                extraDispatchCases,
-                appView),
-            registry -> {
-              registry.registerInvokeInterface(libraryMethod);
-              for (Pair<DexType, DexMethod> dispatch : extraDispatchCases) {
-                registry.registerInvokeStatic(dispatch.getSecond());
-              }
-              registry.registerInvokeStatic(companionMethod);
-            }),
-        appView);
-    return newEncodedMethod;
+    builder.setCode(
+        new EmulateInterfaceSyntheticCfCodeProvider(
+                this.method.holder, companionMethod, libraryMethod, extraDispatchCases, appView)
+            .generateCfCode());
+    return builder.build();
   }
 
   public DexEncodedMethod toStaticForwardingBridge(DexClass holder, DexMethod newMethod) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
index 141d7c0..c87b921 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.CfCode;
 import com.android.tools.r8.graph.ClassAccessFlags;
+import com.android.tools.r8.graph.Code;
 import com.android.tools.r8.graph.DexAnnotationSet;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexClass;
@@ -26,10 +27,10 @@
 import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.graph.ParameterAnnotationsList;
 import com.android.tools.r8.ir.conversion.IRConverter;
-import com.android.tools.r8.ir.synthetic.CfDesugaredLibraryAPIConversionSourceCodeProvider.CfAPIConverterConstructorCodeProvider;
-import com.android.tools.r8.ir.synthetic.CfDesugaredLibraryAPIConversionSourceCodeProvider.CfAPIConverterVivifiedWrapperCodeProvider;
-import com.android.tools.r8.ir.synthetic.CfDesugaredLibraryAPIConversionSourceCodeProvider.CfAPIConverterWrapperCodeProvider;
-import com.android.tools.r8.ir.synthetic.CfDesugaredLibraryAPIConversionSourceCodeProvider.CfAPIConverterWrapperConversionCodeProvider;
+import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConverterConstructorCfCodeProvider;
+import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConverterVivifiedWrapperCfCodeProvider;
+import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConverterWrapperCfCodeProvider;
+import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConverterWrapperConversionCfCodeProvider;
 import com.android.tools.r8.origin.SynthesizedOrigin;
 import com.android.tools.r8.utils.Box;
 import com.android.tools.r8.utils.DescriptorUtils;
@@ -179,7 +180,7 @@
     return synthesizeWrapper(
         converter.vivifiedTypeFor(type),
         dexClass.sourceFile,
-        synthetiseVirtualMethodsForTypeWrapper(dexClass.asLibraryClass(), wrapperField),
+        synthesizeVirtualMethodsForTypeWrapper(dexClass.asLibraryClass(), wrapperField),
         wrapperField);
   }
 
@@ -191,7 +192,7 @@
     return synthesizeWrapper(
         type,
         dexClass.sourceFile,
-        synthetiseVirtualMethodsForVivifiedTypeWrapper(dexClass.asLibraryClass(), wrapperField),
+        synthesizeVirtualMethodsForVivifiedTypeWrapper(dexClass.asLibraryClass(), wrapperField),
         wrapperField);
   }
 
@@ -225,7 +226,7 @@
         Collections.emptyList());
   }
 
-  private DexEncodedMethod[] synthetiseVirtualMethodsForVivifiedTypeWrapper(
+  private DexEncodedMethod[] synthesizeVirtualMethodsForVivifiedTypeWrapper(
       DexLibraryClass dexClass, DexEncodedField wrapperField) {
     List<DexEncodedMethod> dexMethods = allImplementedMethods(dexClass);
     List<DexEncodedMethod> generatedMethods = new ArrayList<>();
@@ -244,24 +245,18 @@
               wrapperField.field.holder,
               dexEncodedMethod.method.proto,
               dexEncodedMethod.method.name);
-      DexEncodedMethod newDexEncodedMethod =
-          newSynthesizedMethod(methodToInstall, dexEncodedMethod);
       CfCode cfCode =
-          new CfAPIConverterVivifiedWrapperCodeProvider(
-                  newDexEncodedMethod,
-                  newDexEncodedMethod.method,
-                  appView,
-                  newDexEncodedMethod.method,
-                  wrapperField.field,
-                  converter)
-              .getCfCode();
-      newDexEncodedMethod.setCode(cfCode, appView);
+          new APIConverterVivifiedWrapperCfCodeProvider(
+                  appView, methodToInstall, wrapperField.field, converter)
+              .generateCfCode();
+      DexEncodedMethod newDexEncodedMethod =
+          newSynthesizedMethod(methodToInstall, dexEncodedMethod, cfCode);
       generatedMethods.add(newDexEncodedMethod);
     }
     return generatedMethods.toArray(DexEncodedMethod.EMPTY_ARRAY);
   }
 
-  private DexEncodedMethod[] synthetiseVirtualMethodsForTypeWrapper(
+  private DexEncodedMethod[] synthesizeVirtualMethodsForTypeWrapper(
       DexLibraryClass dexClass, DexEncodedField wrapperField) {
     List<DexEncodedMethod> dexMethods = allImplementedMethods(dexClass);
     List<DexEncodedMethod> generatedMethods = new ArrayList<>();
@@ -279,18 +274,12 @@
 
       DexMethod methodToInstall =
           methodWithVivifiedTypeInSignature(dexEncodedMethod.method, wrapperField.field.holder);
-      DexEncodedMethod newDexEncodedMethod =
-          newSynthesizedMethod(methodToInstall, dexEncodedMethod);
       CfCode cfCode =
-          new CfAPIConverterWrapperCodeProvider(
-                  newDexEncodedMethod,
-                  newDexEncodedMethod.method,
-                  appView,
-                  dexEncodedMethod.method,
-                  wrapperField.field,
-                  converter)
-              .getCfCode();
-      newDexEncodedMethod.setCode(cfCode, appView);
+          new APIConverterWrapperCfCodeProvider(
+                  appView, dexEncodedMethod.method, wrapperField.field, converter)
+              .generateCfCode();
+      DexEncodedMethod newDexEncodedMethod =
+          newSynthesizedMethod(methodToInstall, dexEncodedMethod, cfCode);
       generatedMethods.add(newDexEncodedMethod);
     }
     return generatedMethods.toArray(DexEncodedMethod.EMPTY_ARRAY);
@@ -315,7 +304,7 @@
   }
 
   private DexEncodedMethod newSynthesizedMethod(
-      DexMethod methodToInstall, DexEncodedMethod template) {
+      DexMethod methodToInstall, DexEncodedMethod template, Code code) {
     MethodAccessFlags newFlags = template.accessFlags.copy();
     assert newFlags.isPublic();
     newFlags.unsetAbstract();
@@ -325,7 +314,7 @@
         newFlags,
         DexAnnotationSet.empty(),
         ParameterAnnotationsList.empty(),
-        null);
+        code);
   }
 
   private List<DexEncodedMethod> allImplementedMethods(DexLibraryClass libraryClass) {
@@ -380,24 +369,22 @@
             field.holder,
             factory.createProto(factory.voidType, field.type),
             factory.initMethodName);
-    DexEncodedMethod dexEncodedMethod =
-        newSynthesizedMethod(method, Constants.ACC_PRIVATE | Constants.ACC_SYNTHETIC, true);
-    dexEncodedMethod.setCode(
-        new CfAPIConverterConstructorCodeProvider(dexEncodedMethod, method, appView, field)
-            .getCfCode(),
-        appView);
-    return dexEncodedMethod;
+    return newSynthesizedMethod(
+        method,
+        Constants.ACC_PRIVATE | Constants.ACC_SYNTHETIC,
+        true,
+        new APIConverterConstructorCfCodeProvider(appView, field).generateCfCode());
   }
 
   private DexEncodedMethod newSynthesizedMethod(
-      DexMethod methodToInstall, int flags, boolean constructor) {
+      DexMethod methodToInstall, int flags, boolean constructor, Code code) {
     MethodAccessFlags accessFlags = MethodAccessFlags.fromSharedAccessFlags(flags, constructor);
     return new DexEncodedMethod(
         methodToInstall,
         accessFlags,
         DexAnnotationSet.empty(),
         ParameterAnnotationsList.empty(),
-        null);
+        code);
   }
 
   // Wrapper finalization section.
@@ -463,19 +450,17 @@
     DexMethod method =
         factory.createMethod(
             holder, factory.createProto(returnType, argType), factory.convertMethodName);
-    DexEncodedMethod dexEncodedMethod =
-        newSynthesizedMethod(
-            method, Constants.ACC_SYNTHETIC | Constants.ACC_STATIC | Constants.ACC_PUBLIC, false);
-    dexEncodedMethod.setCode(
-        new CfAPIConverterWrapperConversionCodeProvider(
-                dexEncodedMethod,
-                method,
+    CfCode cfCode =
+        new APIConverterWrapperConversionCfCodeProvider(
                 appView,
                 argType,
                 reverseWrapperType,
                 factory.createField(holder, returnType, factory.wrapperFieldName))
-            .getCfCode(),
-        appView);
-    return dexEncodedMethod;
+            .generateCfCode();
+    return newSynthesizedMethod(
+        method,
+        Constants.ACC_SYNTHETIC | Constants.ACC_STATIC | Constants.ACC_PUBLIC,
+        false,
+        cfCode);
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/CfSyntheticSourceCodeProvider.java b/src/main/java/com/android/tools/r8/ir/synthetic/CfSyntheticSourceCodeProvider.java
deleted file mode 100644
index 8d45643..0000000
--- a/src/main/java/com/android/tools/r8/ir/synthetic/CfSyntheticSourceCodeProvider.java
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2019, 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.ir.synthetic;
-
-import com.android.tools.r8.cf.code.CfInstruction;
-import com.android.tools.r8.cf.code.CfTryCatch;
-import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.CfCode;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.ir.code.Position;
-import com.android.tools.r8.ir.conversion.CfSourceCode;
-import com.android.tools.r8.ir.conversion.SourceCode;
-import com.android.tools.r8.ir.synthetic.AbstractSynthesizedCode.SourceCodeProvider;
-import com.android.tools.r8.origin.Origin;
-import com.google.common.collect.ImmutableList;
-import java.util.List;
-
-// TODO(b/134732760): I think a general clean-up is required here.
-// Instead of being a sourceCodeProvider, this should just have API getCfCode() and not
-// get(Position). All users should be rewritten to use getCfCode(). That would simplify a lot the
-// code everywhere.
-public abstract class CfSyntheticSourceCodeProvider implements SourceCodeProvider {
-
-  private final DexEncodedMethod method;
-  private final DexMethod originalMethod;
-  protected final AppView<?> appView;
-
-  public CfSyntheticSourceCodeProvider(
-      DexEncodedMethod method, DexMethod originalMethod, AppView<?> appView) {
-    this.method = method;
-    this.originalMethod = originalMethod;
-    this.appView = appView;
-  }
-
-  @Override
-  public SourceCode get(Position callerPosition) {
-    CfCode code = generateCfCode(callerPosition);
-    return new CfSourceCode(
-        code,
-        code.getLocalVariables(),
-        method,
-        originalMethod,
-        callerPosition,
-        Origin.unknown(),
-        appView);
-  }
-
-  public CfCode getCfCode() {
-    return generateCfCode(null);
-  }
-
-  protected abstract CfCode generateCfCode(Position callerPosition);
-
-  protected CfCode standardCfCodeFromInstructions(List<CfInstruction> instructions) {
-    return new CfCode(
-        method.method.holder,
-        defaultMaxStack(),
-        defaultMaxLocals(),
-        instructions,
-        defaultTryCatchs(),
-        ImmutableList.of());
-  }
-
-  protected int defaultMaxStack() {
-    return 16;
-  }
-
-  protected int defaultMaxLocals() {
-    return 16;
-  }
-
-  protected List<CfTryCatch> defaultTryCatchs() {
-    return ImmutableList.of();
-  }
-}
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/CfDesugaredLibraryAPIConversionSourceCodeProvider.java b/src/main/java/com/android/tools/r8/ir/synthetic/DesugaredLibraryAPIConversionCfCodeProvider.java
similarity index 84%
rename from src/main/java/com/android/tools/r8/ir/synthetic/CfDesugaredLibraryAPIConversionSourceCodeProvider.java
rename to src/main/java/com/android/tools/r8/ir/synthetic/DesugaredLibraryAPIConversionCfCodeProvider.java
index c177828..00eb005 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/CfDesugaredLibraryAPIConversionSourceCodeProvider.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/DesugaredLibraryAPIConversionCfCodeProvider.java
@@ -19,7 +19,6 @@
 import com.android.tools.r8.cf.code.CfStackInstruction;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.CfCode;
-import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
@@ -27,7 +26,6 @@
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.code.If;
-import com.android.tools.r8.ir.code.Position;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.desugar.DesugaredLibraryAPIConverter;
 import com.android.tools.r8.utils.StringDiagnostic;
@@ -35,9 +33,9 @@
 import java.util.List;
 import org.objectweb.asm.Opcodes;
 
-public class CfDesugaredLibraryAPIConversionSourceCodeProvider {
+public class DesugaredLibraryAPIConversionCfCodeProvider {
 
-  static boolean shouldConvert(
+  private static boolean shouldConvert(
       DexType type,
       DesugaredLibraryAPIConverter converter,
       AppView<?> appView,
@@ -58,28 +56,25 @@
     return false;
   }
 
-  public static class CfAPIConverterVivifiedWrapperCodeProvider
-      extends CfSyntheticSourceCodeProvider {
+  public static class APIConverterVivifiedWrapperCfCodeProvider extends SyntheticCfCodeProvider {
 
     DexField wrapperField;
     DexMethod forwardMethod;
     DesugaredLibraryAPIConverter converter;
 
-    public CfAPIConverterVivifiedWrapperCodeProvider(
-        DexEncodedMethod method,
-        DexMethod originalMethod,
+    public APIConverterVivifiedWrapperCfCodeProvider(
         AppView<?> appView,
         DexMethod forwardMethod,
-        DexField wrappedValue,
+        DexField wrapperField,
         DesugaredLibraryAPIConverter converter) {
-      super(method, originalMethod, appView);
+      super(appView, wrapperField.holder);
       this.forwardMethod = forwardMethod;
-      this.wrapperField = wrappedValue;
+      this.wrapperField = wrapperField;
       this.converter = converter;
     }
 
     @Override
-    protected CfCode generateCfCode(Position callerPosition) {
+    public CfCode generateCfCode() {
       DexItemFactory factory = appView.dexItemFactory();
       List<CfInstruction> instructions = new ArrayList<>();
       // Wrapped value is a vivified type. Method uses type as external. Forward method should
@@ -136,27 +131,25 @@
     }
   }
 
-  public static class CfAPIConverterWrapperCodeProvider extends CfSyntheticSourceCodeProvider {
+  public static class APIConverterWrapperCfCodeProvider extends SyntheticCfCodeProvider {
 
     DexField wrapperField;
     DexMethod forwardMethod;
     DesugaredLibraryAPIConverter converter;
 
-    public CfAPIConverterWrapperCodeProvider(
-        DexEncodedMethod method,
-        DexMethod originalMethod,
+    public APIConverterWrapperCfCodeProvider(
         AppView<?> appView,
         DexMethod forwardMethod,
-        DexField wrappedValue,
+        DexField wrapperField,
         DesugaredLibraryAPIConverter converter) {
-      super(method, originalMethod, appView);
+      super(appView, wrapperField.holder);
       this.forwardMethod = forwardMethod;
-      this.wrapperField = wrappedValue;
+      this.wrapperField = wrapperField;
       this.converter = converter;
     }
 
     @Override
-    protected CfCode generateCfCode(Position callerPosition) {
+    public CfCode generateCfCode() {
       DexItemFactory factory = appView.dexItemFactory();
       List<CfInstruction> instructions = new ArrayList<>();
       // Wrapped value is a type. Method uses vivifiedTypes as external. Forward method should
@@ -202,28 +195,22 @@
     }
   }
 
-  public static class CfAPIConverterWrapperConversionCodeProvider
-      extends CfSyntheticSourceCodeProvider {
+  public static class APIConverterWrapperConversionCfCodeProvider extends SyntheticCfCodeProvider {
 
     DexType argType;
     DexType reverseWrapperType;
     DexField wrapperField;
 
-    public CfAPIConverterWrapperConversionCodeProvider(
-        DexEncodedMethod method,
-        DexMethod originalMethod,
-        AppView<?> appView,
-        DexType argType,
-        DexType reverseWrapperType,
-        DexField wrapperField) {
-      super(method, originalMethod, appView);
+    public APIConverterWrapperConversionCfCodeProvider(
+        AppView<?> appView, DexType argType, DexType reverseWrapperType, DexField wrapperField) {
+      super(appView, wrapperField.holder);
       this.argType = argType;
       this.reverseWrapperType = reverseWrapperType;
       this.wrapperField = wrapperField;
     }
 
     @Override
-    protected CfCode generateCfCode(Position callerPosition) {
+    public CfCode generateCfCode() {
       DexItemFactory factory = appView.dexItemFactory();
       List<CfInstruction> instructions = new ArrayList<>();
 
@@ -265,18 +252,17 @@
     }
   }
 
-  public static class CfAPIConverterConstructorCodeProvider extends CfSyntheticSourceCodeProvider {
+  public static class APIConverterConstructorCfCodeProvider extends SyntheticCfCodeProvider {
 
     DexField wrapperField;
 
-    public CfAPIConverterConstructorCodeProvider(
-        DexEncodedMethod method, DexMethod originalMethod, AppView<?> appView, DexField field) {
-      super(method, originalMethod, appView);
-      this.wrapperField = field;
+    public APIConverterConstructorCfCodeProvider(AppView<?> appView, DexField wrapperField) {
+      super(appView, wrapperField.holder);
+      this.wrapperField = wrapperField;
     }
 
     @Override
-    protected CfCode generateCfCode(Position callerPosition) {
+    public CfCode generateCfCode() {
       DexItemFactory factory = appView.dexItemFactory();
       List<CfInstruction> instructions = new ArrayList<>();
       instructions.add(new CfLoad(ValueType.fromDexType(wrapperField.holder), 0));
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/CfEmulateInterfaceSyntheticSourceCodeProvider.java b/src/main/java/com/android/tools/r8/ir/synthetic/EmulateInterfaceSyntheticCfCodeProvider.java
similarity index 90%
rename from src/main/java/com/android/tools/r8/ir/synthetic/CfEmulateInterfaceSyntheticSourceCodeProvider.java
rename to src/main/java/com/android/tools/r8/ir/synthetic/EmulateInterfaceSyntheticCfCodeProvider.java
index b3c1567..3cb4210 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/CfEmulateInterfaceSyntheticSourceCodeProvider.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/EmulateInterfaceSyntheticCfCodeProvider.java
@@ -15,33 +15,29 @@
 import com.android.tools.r8.cf.code.CfReturnVoid;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.CfCode;
-import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.code.If;
-import com.android.tools.r8.ir.code.Position;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.utils.Pair;
 import java.util.ArrayList;
 import java.util.List;
 import org.objectweb.asm.Opcodes;
 
-public class CfEmulateInterfaceSyntheticSourceCodeProvider extends CfSyntheticSourceCodeProvider {
+public class EmulateInterfaceSyntheticCfCodeProvider extends SyntheticCfCodeProvider {
 
   private final DexType interfaceType;
   private final DexMethod companionMethod;
   private final DexMethod libraryMethod;
   private final List<Pair<DexType, DexMethod>> extraDispatchCases;
 
-  public CfEmulateInterfaceSyntheticSourceCodeProvider(
+  public EmulateInterfaceSyntheticCfCodeProvider(
       DexType interfaceType,
       DexMethod companionMethod,
-      DexEncodedMethod method,
       DexMethod libraryMethod,
-      DexMethod originalMethod,
       List<Pair<DexType, DexMethod>> extraDispatchCases,
       AppView<?> appView) {
-    super(method, originalMethod, appView);
+    super(appView, interfaceType);
     this.interfaceType = interfaceType;
     this.companionMethod = companionMethod;
     this.libraryMethod = libraryMethod;
@@ -49,7 +45,7 @@
   }
 
   @Override
-  protected CfCode generateCfCode(Position callerPosition) {
+  public CfCode generateCfCode() {
     List<CfInstruction> instructions = new ArrayList<>();
     CfLabel[] labels = new CfLabel[extraDispatchCases.size() + 1];
     for (int i = 0; i < labels.length; i++) {
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticCfCodeProvider.java b/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticCfCodeProvider.java
new file mode 100644
index 0000000..c01b0b8
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticCfCodeProvider.java
@@ -0,0 +1,48 @@
+// Copyright (c) 2019, 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.ir.synthetic;
+
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfTryCatch;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.CfCode;
+import com.android.tools.r8.graph.DexType;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+
+public abstract class SyntheticCfCodeProvider {
+
+  protected final AppView<?> appView;
+  private final DexType holder;
+
+  protected SyntheticCfCodeProvider(AppView<?> appView, DexType holder) {
+    this.appView = appView;
+    this.holder = holder;
+  }
+
+  public abstract CfCode generateCfCode();
+
+  protected CfCode standardCfCodeFromInstructions(List<CfInstruction> instructions) {
+    return new CfCode(
+        holder,
+        defaultMaxStack(),
+        defaultMaxLocals(),
+        instructions,
+        defaultTryCatchs(),
+        ImmutableList.of());
+  }
+
+  protected int defaultMaxStack() {
+    return 16;
+  }
+
+  protected int defaultMaxLocals() {
+    return 16;
+  }
+
+  protected List<CfTryCatch> defaultTryCatchs() {
+    return ImmutableList.of();
+  }
+}