void DisassemblerEmitter::run(raw_ostream &OS) {
  CodeGenTarget Target(Records);

  OS << "/*===- TableGen'erated file "
     << "---------------------------------------*- C -*-===*\n"
     << " *\n"
     << " * " << Target.getName() << " Disassembler\n"
     << " *\n"
     << " * Automatically generated file, do not edit!\n"
     << " *\n"
     << " *===---------------------------------------------------------------"
     << "-------===*/\n";

  // X86 uses a custom disassembler.
  if (Target.getName() == "X86") {
    DisassemblerTables Tables;
  
    const std::vector<const CodeGenInstruction*> &numberedInstructions =
      Target.getInstructionsByEnumValue();
    
    for (unsigned i = 0, e = numberedInstructions.size(); i != e; ++i)
      RecognizableInstr::processInstr(Tables, *numberedInstructions[i], i);

    // FIXME: As long as we are using exceptions, might as well drop this to the
    // actual conflict site.
    if (Tables.hasConflicts())
      throw TGError(Target.getTargetRecord()->getLoc(),
                    "Primary decode conflict");

    Tables.emit(OS);
    return;
  }

  // ARM and Thumb have a CHECK() macro to deal with DecodeStatuses.
  if (Target.getName() == "ARM" ||
      Target.getName() == "Thumb") {
    FixedLenDecoderEmitter(Records,
                           "ARM",
                           "if (!Check(S, ", ")) return MCDisassembler::Fail;",
                           "S", "MCDisassembler::Fail",
                           "  MCDisassembler::DecodeStatus S = MCDisassembler::Success;\n(void)S;").run(OS);
    return;
  }

  FixedLenDecoderEmitter(Records, Target.getName()).run(OS);
}
void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
  CodeGenTarget Target(Records);
  emitSourceFileHeader(" * " + Target.getName() + " Disassembler", OS);

  // X86 uses a custom disassembler.
  if (Target.getName() == "X86") {
    DisassemblerTables Tables;

    const std::vector<const CodeGenInstruction*> &numberedInstructions =
      Target.getInstructionsByEnumValue();

    for (unsigned i = 0, e = numberedInstructions.size(); i != e; ++i)
      RecognizableInstr::processInstr(Tables, *numberedInstructions[i], i);

    if (Tables.hasConflicts()) {
      PrintError(Target.getTargetRecord()->getLoc(), "Primary decode conflict");
      return;
    }

    Tables.emit(OS);
    return;
  }

  // ARM and Thumb have a CHECK() macro to deal with DecodeStatuses.
  if (Target.getName() == "ARM" || Target.getName() == "Thumb" ||
      Target.getName() == "AArch64" || Target.getName() == "ARM64") {
    std::string PredicateNamespace = Target.getName();
    if (PredicateNamespace == "Thumb")
      PredicateNamespace = "ARM";

    EmitFixedLenDecoder(Records, OS, PredicateNamespace,
                        "if (!Check(S, ", ")) return MCDisassembler::Fail;",
                        "S", "MCDisassembler::Fail",
                        "  MCDisassembler::DecodeStatus S = "
                          "MCDisassembler::Success;\n(void)S;");
    return;
  }

  EmitFixedLenDecoder(Records, OS, Target.getName(),
                      "if (", " == MCDisassembler::Fail)"
                       " return MCDisassembler::Fail;",
                      "MCDisassembler::Success", "MCDisassembler::Fail", "");
}