/**
   * Create code for the work function of a built-in filter.
   *
   * @param filter The filter that the work function is being built for
   * @param selfID A unique id assigned in FlatIRToC
   * @param p A printer to output the generated code
   */
  static void predefinedFilterWork(SIRPredefinedFilter filter, int selfID, CodegenPrintWriter p) {

    Tape inputTape = RegisterStreams.getFilterInStream(filter);
    Tape outputTape = RegisterStreams.getFilterOutStream(filter);

    // Caller has printed function name and an iteration parameter ____n
    // Generate loop to execute body of this function ____n times,
    // In loop generate specialized code for function.
    p.print("void " + ClusterUtils.getWorkName(filter, selfID) + "(int ____n) {");
    p.indent();
    p.newLine();
    p.indent();
    //        p.println("// predefinedFilterWork " + filter.getName());

    // SIRFileReader
    if (filter instanceof SIRFileReader) {
      if (!(KjcOptions.mencoder || KjcOptions.blender)) {
        genFileReaderWork((SIRFileReader) filter, outputTape, selfID, p);
      }
      // SIRFileWriter
    } else if (filter instanceof SIRFileWriter) {
      if (!(KjcOptions.mencoder || KjcOptions.blender)) {
        genFileWriterWork((SIRFileWriter) filter, inputTape, selfID, p);
      }
      // SIRIdentity
    } else if (filter instanceof SIRIdentity) {
      assert false : "should not process SIRIdentity here";
      p.println("for (; 0 < ____n; ____n--) {");
      p.indent();
      p.println("  " + outputTape.getPushName() + "(" + inputTape.getPopName() + "());");
      p.outdent();
      p.print("}"); // end of for loop.
    } else if (filter instanceof SIRDummySink || filter instanceof SIRDummySource) {
      // DummySource and SummySink do not appear in any of our
      // application code.  Are they part of the language?
      // TODO: get right exception for unimplemented.
      throw new Error("Unsupported predefined filter " + filter.getName());
    } else {
      // TODO: get right unchecked exception for unextended code...
      throw new Error("Unknown predefined filter " + filter.getName());
    }
    p.newLine();
    p.outdent(); // end of method body
    p.outdent(); // end of method definition
    p.print("}");
    p.newLine();
    p.newLine();
  }
  /**
   * Create code for the init function of built-in filter
   *
   * @param filter The filter for which we are creating init function
   * @param return_type The return type for the init function
   * @param function_name The name for the init function
   * @param selfID The unique identifier that FlatIRToCluster has assigned to the function
   * @param cleanupCode A list of statements run at "clean-up" time to which this code can add
   *     requests to close files, etc.
   * @param p The printer for outputting code for the function
   */
  static void predefinedFilterInit(
      SIRPredefinedFilter filter,
      CType return_type,
      String function_name,
      int selfID,
      List /*String*/ cleanupCode,
      CodegenPrintWriter p) {

    // No wrapper code around init since may need to create defns at file
    // level. We assume that the code generator will continue to
    // generate code for init before code for work, so scope of
    // any file-level code will include the work function.

    //        p.println("// predefinedFilterInit " + filter.getName()
    //      + " " + filter.getInputType().toString() + " -> "
    //      + filter.getOutputType().toString());

    if (filter instanceof SIRFileReader) {
      if (!(KjcOptions.mencoder || KjcOptions.blender)) {
        genFileReaderInit(
            (SIRFileReader) filter, return_type, function_name, selfID, cleanupCode, p);
      }
    } else if (filter instanceof SIRFileWriter) {
      if (!(KjcOptions.mencoder || KjcOptions.blender)) {
        genFileWriterInit(
            (SIRFileWriter) filter, return_type, function_name, selfID, cleanupCode, p);
      }
    } else if (filter instanceof SIRIdentity
        || filter instanceof SIRDummySink
        || filter instanceof SIRDummySource) {
      // all of these have filters produce empty init functions.
      startParameterlessFunction(CommonUtils.CTypeToStringA(return_type, true), function_name, p);
      endFunction(p);
    } else if (filter instanceof SIRDummySink) {
      // TODO:  get right exception for unimplemented.
      throw new Error("Unsupported predefined filter " + filter.getName());
    } else if (filter instanceof SIRDummySource) {
      throw new Error("Unsupported predefined filter " + filter.getName());
    } else {
      // TODO:  get right unchecked exception for unextended code...
      throw new Error("Unknown predefined filter " + filter.getName());
    }
  }