InstrInfoEmitter.cpp revision 234353
192654Sjeff//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===//
292654Sjeff//
392654Sjeff//                     The LLVM Compiler Infrastructure
492654Sjeff//
592654Sjeff// This file is distributed under the University of Illinois Open Source
692654Sjeff// License. See LICENSE.TXT for details.
792654Sjeff//
892654Sjeff//===----------------------------------------------------------------------===//
992654Sjeff//
1092654Sjeff// This tablegen backend is responsible for emitting a description of the target
1192654Sjeff// instruction set for the code generator.
1292654Sjeff//
1392654Sjeff//===----------------------------------------------------------------------===//
1492654Sjeff
1592654Sjeff#include "InstrInfoEmitter.h"
1692654Sjeff#include "CodeGenTarget.h"
1792654Sjeff#include "SequenceToOffsetTable.h"
1892654Sjeff#include "llvm/TableGen/Record.h"
1992654Sjeff#include "llvm/ADT/StringExtras.h"
2092654Sjeff#include <algorithm>
2192654Sjeff#include <cstdio>
2292654Sjeffusing namespace llvm;
2392654Sjeff
2492654Sjeffstatic void PrintDefList(const std::vector<Record*> &Uses,
2592654Sjeff                         unsigned Num, raw_ostream &OS) {
2692654Sjeff  OS << "static const uint16_t ImplicitList" << Num << "[] = { ";
2792654Sjeff  for (unsigned i = 0, e = Uses.size(); i != e; ++i)
2892654Sjeff    OS << getQualifiedName(Uses[i]) << ", ";
2992654Sjeff  OS << "0 };\n";
3092654Sjeff}
3192654Sjeff
3292654Sjeff//===----------------------------------------------------------------------===//
3392654Sjeff// Instruction Itinerary Information.
3492654Sjeff//===----------------------------------------------------------------------===//
3592654Sjeff
3692654Sjeffvoid InstrInfoEmitter::GatherItinClasses() {
3792654Sjeff  std::vector<Record*> DefList =
3892654Sjeff  Records.getAllDerivedDefinitions("InstrItinClass");
3992654Sjeff  std::sort(DefList.begin(), DefList.end(), LessRecord());
4092654Sjeff
4192654Sjeff  for (unsigned i = 0, N = DefList.size(); i < N; i++)
4292654Sjeff    ItinClassMap[DefList[i]->getName()] = i;
4392654Sjeff}
4492654Sjeff
4592654Sjeffunsigned InstrInfoEmitter::getItinClassNumber(const Record *InstRec) {
4692654Sjeff  return ItinClassMap[InstRec->getValueAsDef("Itinerary")->getName()];
4792654Sjeff}
4892654Sjeff
4992654Sjeff//===----------------------------------------------------------------------===//
5092654Sjeff// Operand Info Emission.
5192654Sjeff//===----------------------------------------------------------------------===//
5292654Sjeff
5392654Sjeffstd::vector<std::string>
5492654SjeffInstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
5592654Sjeff  std::vector<std::string> Result;
5692654Sjeff
5792654Sjeff  for (unsigned i = 0, e = Inst.Operands.size(); i != e; ++i) {
5892654Sjeff    // Handle aggregate operands and normal operands the same way by expanding
5992654Sjeff    // either case into a list of operands for this op.
6092654Sjeff    std::vector<CGIOperandList::OperandInfo> OperandList;
6192654Sjeff
6292654Sjeff    // This might be a multiple operand thing.  Targets like X86 have
6392654Sjeff    // registers in their multi-operand operands.  It may also be an anonymous
6492654Sjeff    // operand, which has a single operand, but no declared class for the
6592654Sjeff    // operand.
6692654Sjeff    DagInit *MIOI = Inst.Operands[i].MIOperandInfo;
6792654Sjeff
6892654Sjeff    if (!MIOI || MIOI->getNumArgs() == 0) {
6992654Sjeff      // Single, anonymous, operand.
7092654Sjeff      OperandList.push_back(Inst.Operands[i]);
7192654Sjeff    } else {
7292654Sjeff      for (unsigned j = 0, e = Inst.Operands[i].MINumOperands; j != e; ++j) {
7392654Sjeff        OperandList.push_back(Inst.Operands[i]);
7492654Sjeff
7592654Sjeff        Record *OpR = dynamic_cast<DefInit*>(MIOI->getArg(j))->getDef();
7692654Sjeff        OperandList.back().Rec = OpR;
7792654Sjeff      }
7892654Sjeff    }
7992654Sjeff
8092654Sjeff    for (unsigned j = 0, e = OperandList.size(); j != e; ++j) {
8192654Sjeff      Record *OpR = OperandList[j].Rec;
8292654Sjeff      std::string Res;
8392654Sjeff
8492654Sjeff      if (OpR->isSubClassOf("RegisterOperand"))
8592654Sjeff        OpR = OpR->getValueAsDef("RegClass");
8692654Sjeff      if (OpR->isSubClassOf("RegisterClass"))
8792654Sjeff        Res += getQualifiedName(OpR) + "RegClassID, ";
8892654Sjeff      else if (OpR->isSubClassOf("PointerLikeRegClass"))
8992654Sjeff        Res += utostr(OpR->getValueAsInt("RegClassKind")) + ", ";
9092654Sjeff      else
9192654Sjeff        // -1 means the operand does not have a fixed register class.
9292654Sjeff        Res += "-1, ";
9392654Sjeff
9492654Sjeff      // Fill in applicable flags.
9592654Sjeff      Res += "0";
9692654Sjeff
9792654Sjeff      // Ptr value whose register class is resolved via callback.
9892654Sjeff      if (OpR->isSubClassOf("PointerLikeRegClass"))
9992654Sjeff        Res += "|(1<<MCOI::LookupPtrRegClass)";
10092654Sjeff
10192654Sjeff      // Predicate operands.  Check to see if the original unexpanded operand
10292654Sjeff      // was of type PredicateOperand.
10392654Sjeff      if (Inst.Operands[i].Rec->isSubClassOf("PredicateOperand"))
10492654Sjeff        Res += "|(1<<MCOI::Predicate)";
10592654Sjeff
10692654Sjeff      // Optional def operands.  Check to see if the original unexpanded operand
10792654Sjeff      // was of type OptionalDefOperand.
10892654Sjeff      if (Inst.Operands[i].Rec->isSubClassOf("OptionalDefOperand"))
10992654Sjeff        Res += "|(1<<MCOI::OptionalDef)";
11092654Sjeff
11192654Sjeff      // Fill in operand type.
11292654Sjeff      Res += ", MCOI::";
11392654Sjeff      assert(!Inst.Operands[i].OperandType.empty() && "Invalid operand type.");
11492654Sjeff      Res += Inst.Operands[i].OperandType;
11592654Sjeff
11692654Sjeff      // Fill in constraint info.
11792654Sjeff      Res += ", ";
11892654Sjeff
11992654Sjeff      const CGIOperandList::ConstraintInfo &Constraint =
12092654Sjeff        Inst.Operands[i].Constraints[j];
12192654Sjeff      if (Constraint.isNone())
12292654Sjeff        Res += "0";
12392654Sjeff      else if (Constraint.isEarlyClobber())
12492654Sjeff        Res += "(1 << MCOI::EARLY_CLOBBER)";
12592654Sjeff      else {
12692654Sjeff        assert(Constraint.isTied());
12792654Sjeff        Res += "((" + utostr(Constraint.getTiedOperand()) +
12892654Sjeff                    " << 16) | (1 << MCOI::TIED_TO))";
12992654Sjeff      }
13092654Sjeff
13192654Sjeff      Result.push_back(Res);
13292654Sjeff    }
13392654Sjeff  }
13492654Sjeff
13592654Sjeff  return Result;
13692654Sjeff}
13792654Sjeff
13892654Sjeffvoid InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
13992654Sjeff                                       OperandInfoMapTy &OperandInfoIDs) {
14092654Sjeff  // ID #0 is for no operand info.
14192654Sjeff  unsigned OperandListNum = 0;
14292654Sjeff  OperandInfoIDs[std::vector<std::string>()] = ++OperandListNum;
14392654Sjeff
14492654Sjeff  OS << "\n";
14592654Sjeff  const CodeGenTarget &Target = CDP.getTargetInfo();
14692654Sjeff  for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
14792654Sjeff       E = Target.inst_end(); II != E; ++II) {
14892654Sjeff    std::vector<std::string> OperandInfo = GetOperandInfo(**II);
14992654Sjeff    unsigned &N = OperandInfoIDs[OperandInfo];
15092654Sjeff    if (N != 0) continue;
15192654Sjeff
15292654Sjeff    N = ++OperandListNum;
15392654Sjeff    OS << "static const MCOperandInfo OperandInfo" << N << "[] = { ";
15492654Sjeff    for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i)
15592654Sjeff      OS << "{ " << OperandInfo[i] << " }, ";
15692654Sjeff    OS << "};\n";
15792654Sjeff  }
15892654Sjeff}
15992654Sjeff
16092654Sjeff//===----------------------------------------------------------------------===//
16192654Sjeff// Main Output.
16292654Sjeff//===----------------------------------------------------------------------===//
16392654Sjeff
16492654Sjeff// run - Emit the main instruction description records for the target...
16592654Sjeffvoid InstrInfoEmitter::run(raw_ostream &OS) {
16692654Sjeff  emitEnums(OS);
16792654Sjeff
16892654Sjeff  GatherItinClasses();
16992654Sjeff
17092654Sjeff  EmitSourceFileHeader("Target Instruction Descriptors", OS);
17192654Sjeff
17292654Sjeff  OS << "\n#ifdef GET_INSTRINFO_MC_DESC\n";
17392654Sjeff  OS << "#undef GET_INSTRINFO_MC_DESC\n";
17492654Sjeff
17592654Sjeff  OS << "namespace llvm {\n\n";
17692654Sjeff
17792654Sjeff  CodeGenTarget &Target = CDP.getTargetInfo();
17892654Sjeff  const std::string &TargetName = Target.getName();
17992654Sjeff  Record *InstrInfo = Target.getInstructionSet();
18092654Sjeff
18192654Sjeff  // Keep track of all of the def lists we have emitted already.
18292654Sjeff  std::map<std::vector<Record*>, unsigned> EmittedLists;
18392654Sjeff  unsigned ListNumber = 0;
18492654Sjeff
18592654Sjeff  // Emit all of the instruction's implicit uses and defs.
18692654Sjeff  for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
18792654Sjeff         E = Target.inst_end(); II != E; ++II) {
18892654Sjeff    Record *Inst = (*II)->TheDef;
18992654Sjeff    std::vector<Record*> Uses = Inst->getValueAsListOfDefs("Uses");
19092654Sjeff    if (!Uses.empty()) {
19192654Sjeff      unsigned &IL = EmittedLists[Uses];
19292654Sjeff      if (!IL) PrintDefList(Uses, IL = ++ListNumber, OS);
19392654Sjeff    }
19492654Sjeff    std::vector<Record*> Defs = Inst->getValueAsListOfDefs("Defs");
19592654Sjeff    if (!Defs.empty()) {
19692654Sjeff      unsigned &IL = EmittedLists[Defs];
19792654Sjeff      if (!IL) PrintDefList(Defs, IL = ++ListNumber, OS);
19892654Sjeff    }
19992654Sjeff  }
20092654Sjeff
20192654Sjeff  OperandInfoMapTy OperandInfoIDs;
20292654Sjeff
20392654Sjeff  // Emit all of the operand info records.
20492654Sjeff  EmitOperandInfo(OS, OperandInfoIDs);
20592654Sjeff
20692654Sjeff  // Emit all of the MCInstrDesc records in their ENUM ordering.
20792654Sjeff  //
20892654Sjeff  OS << "\nextern const MCInstrDesc " << TargetName << "Insts[] = {\n";
20992654Sjeff  const std::vector<const CodeGenInstruction*> &NumberedInstructions =
21092654Sjeff    Target.getInstructionsByEnumValue();
21192654Sjeff
21292654Sjeff  for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i)
21392654Sjeff    emitRecord(*NumberedInstructions[i], i, InstrInfo, EmittedLists,
21492654Sjeff               OperandInfoIDs, OS);
21592654Sjeff  OS << "};\n\n";
21692654Sjeff
21792654Sjeff  // Build an array of instruction names
21892654Sjeff  SequenceToOffsetTable<std::string> InstrNames;
21992654Sjeff  for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
22092654Sjeff    const CodeGenInstruction *Instr = NumberedInstructions[i];
22192654Sjeff    InstrNames.add(Instr->TheDef->getName());
22292654Sjeff  }
22392654Sjeff
22492654Sjeff  InstrNames.layout();
22592654Sjeff  OS << "extern const char " << TargetName << "InstrNameData[] = {\n";
22692654Sjeff  InstrNames.emit(OS, printChar);
22792654Sjeff  OS << "};\n\n";
22892654Sjeff
22992654Sjeff  OS << "extern const unsigned " << TargetName <<"InstrNameIndices[] = {";
23092654Sjeff  for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
23192654Sjeff    if (i % 8 == 0)
23292654Sjeff      OS << "\n    ";
23392654Sjeff    const CodeGenInstruction *Instr = NumberedInstructions[i];
23492654Sjeff    OS << InstrNames.get(Instr->TheDef->getName()) << "U, ";
23592654Sjeff  }
23692654Sjeff
23792654Sjeff  OS << "\n};\n\n";
23892654Sjeff
23992654Sjeff  // MCInstrInfo initialization routine.
24092654Sjeff  OS << "static inline void Init" << TargetName
24192654Sjeff     << "MCInstrInfo(MCInstrInfo *II) {\n";
24292654Sjeff  OS << "  II->InitMCInstrInfo(" << TargetName << "Insts, "
24392654Sjeff     << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, "
24492654Sjeff     << NumberedInstructions.size() << ");\n}\n\n";
24592654Sjeff
24692654Sjeff  OS << "} // End llvm namespace \n";
24792654Sjeff
24892654Sjeff  OS << "#endif // GET_INSTRINFO_MC_DESC\n\n";
24992654Sjeff
25092654Sjeff  // Create a TargetInstrInfo subclass to hide the MC layer initialization.
25192654Sjeff  OS << "\n#ifdef GET_INSTRINFO_HEADER\n";
25292654Sjeff  OS << "#undef GET_INSTRINFO_HEADER\n";
25392654Sjeff
25492654Sjeff  std::string ClassName = TargetName + "GenInstrInfo";
25592654Sjeff  OS << "namespace llvm {\n";
25692654Sjeff  OS << "struct " << ClassName << " : public TargetInstrInfoImpl {\n"
25792654Sjeff     << "  explicit " << ClassName << "(int SO = -1, int DO = -1);\n"
25892654Sjeff     << "};\n";
25992654Sjeff  OS << "} // End llvm namespace \n";
26092654Sjeff
26192654Sjeff  OS << "#endif // GET_INSTRINFO_HEADER\n\n";
26292654Sjeff
26392654Sjeff  OS << "\n#ifdef GET_INSTRINFO_CTOR\n";
26492654Sjeff  OS << "#undef GET_INSTRINFO_CTOR\n";
26592654Sjeff
26692654Sjeff  OS << "namespace llvm {\n";
26792654Sjeff  OS << "extern const MCInstrDesc " << TargetName << "Insts[];\n";
26892654Sjeff  OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n";
26992654Sjeff  OS << "extern const char " << TargetName << "InstrNameData[];\n";
27092654Sjeff  OS << ClassName << "::" << ClassName << "(int SO, int DO)\n"
27192654Sjeff     << "  : TargetInstrInfoImpl(SO, DO) {\n"
27292654Sjeff     << "  InitMCInstrInfo(" << TargetName << "Insts, "
27392654Sjeff     << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, "
27492654Sjeff     << NumberedInstructions.size() << ");\n}\n";
27592654Sjeff  OS << "} // End llvm namespace \n";
27692654Sjeff
27792654Sjeff  OS << "#endif // GET_INSTRINFO_CTOR\n\n";
27892654Sjeff}
27992654Sjeff
28092654Sjeffvoid InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
28192654Sjeff                                  Record *InstrInfo,
28292654Sjeff                         std::map<std::vector<Record*>, unsigned> &EmittedLists,
28392654Sjeff                                  const OperandInfoMapTy &OpInfo,
28492654Sjeff                                  raw_ostream &OS) {
28592654Sjeff  int MinOperands = 0;
28692654Sjeff  if (!Inst.Operands.size() == 0)
28792654Sjeff    // Each logical operand can be multiple MI operands.
28892654Sjeff    MinOperands = Inst.Operands.back().MIOperandNo +
28992654Sjeff                  Inst.Operands.back().MINumOperands;
29092654Sjeff
29192654Sjeff  OS << "  { ";
29292654Sjeff  OS << Num << ",\t" << MinOperands << ",\t"
29392654Sjeff     << Inst.Operands.NumDefs << ",\t"
29492654Sjeff     << getItinClassNumber(Inst.TheDef) << ",\t"
29592654Sjeff     << Inst.TheDef->getValueAsInt("Size") << ",\t0";
29692654Sjeff
29792654Sjeff  // Emit all of the target indepedent flags...
29892654Sjeff  if (Inst.isPseudo)           OS << "|(1<<MCID::Pseudo)";
29992654Sjeff  if (Inst.isReturn)           OS << "|(1<<MCID::Return)";
30092654Sjeff  if (Inst.isBranch)           OS << "|(1<<MCID::Branch)";
30192654Sjeff  if (Inst.isIndirectBranch)   OS << "|(1<<MCID::IndirectBranch)";
30292654Sjeff  if (Inst.isCompare)          OS << "|(1<<MCID::Compare)";
30392654Sjeff  if (Inst.isMoveImm)          OS << "|(1<<MCID::MoveImm)";
30492654Sjeff  if (Inst.isBitcast)          OS << "|(1<<MCID::Bitcast)";
30592654Sjeff  if (Inst.isBarrier)          OS << "|(1<<MCID::Barrier)";
30692654Sjeff  if (Inst.hasDelaySlot)       OS << "|(1<<MCID::DelaySlot)";
30792654Sjeff  if (Inst.isCall)             OS << "|(1<<MCID::Call)";
30892654Sjeff  if (Inst.canFoldAsLoad)      OS << "|(1<<MCID::FoldableAsLoad)";
30992654Sjeff  if (Inst.mayLoad)            OS << "|(1<<MCID::MayLoad)";
31092654Sjeff  if (Inst.mayStore)           OS << "|(1<<MCID::MayStore)";
31192654Sjeff  if (Inst.isPredicable)       OS << "|(1<<MCID::Predicable)";
31292654Sjeff  if (Inst.isConvertibleToThreeAddress) OS << "|(1<<MCID::ConvertibleTo3Addr)";
31392654Sjeff  if (Inst.isCommutable)       OS << "|(1<<MCID::Commutable)";
31492654Sjeff  if (Inst.isTerminator)       OS << "|(1<<MCID::Terminator)";
31592654Sjeff  if (Inst.isReMaterializable) OS << "|(1<<MCID::Rematerializable)";
31692654Sjeff  if (Inst.isNotDuplicable)    OS << "|(1<<MCID::NotDuplicable)";
31792654Sjeff  if (Inst.Operands.hasOptionalDef) OS << "|(1<<MCID::HasOptionalDef)";
31892654Sjeff  if (Inst.usesCustomInserter) OS << "|(1<<MCID::UsesCustomInserter)";
31992654Sjeff  if (Inst.hasPostISelHook)    OS << "|(1<<MCID::HasPostISelHook)";
32092654Sjeff  if (Inst.Operands.isVariadic)OS << "|(1<<MCID::Variadic)";
32192654Sjeff  if (Inst.hasSideEffects)     OS << "|(1<<MCID::UnmodeledSideEffects)";
32292654Sjeff  if (Inst.isAsCheapAsAMove)   OS << "|(1<<MCID::CheapAsAMove)";
32392654Sjeff  if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<MCID::ExtraSrcRegAllocReq)";
32492654Sjeff  if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<MCID::ExtraDefRegAllocReq)";
32592654Sjeff
32692654Sjeff  // Emit all of the target-specific flags...
32792654Sjeff  BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags");
32892654Sjeff  if (!TSF) throw "no TSFlags?";
32992654Sjeff  uint64_t Value = 0;
33092654Sjeff  for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) {
33192654Sjeff    if (BitInit *Bit = dynamic_cast<BitInit*>(TSF->getBit(i)))
33292654Sjeff      Value |= uint64_t(Bit->getValue()) << i;
33392654Sjeff    else
33492654Sjeff      throw "Invalid TSFlags bit in " + Inst.TheDef->getName();
33592654Sjeff  }
33692654Sjeff  OS << ", 0x";
33792654Sjeff  OS.write_hex(Value);
33892654Sjeff  OS << "ULL, ";
33992654Sjeff
34092654Sjeff  // Emit the implicit uses and defs lists...
34192654Sjeff  std::vector<Record*> UseList = Inst.TheDef->getValueAsListOfDefs("Uses");
34292654Sjeff  if (UseList.empty())
34392654Sjeff    OS << "NULL, ";
34492654Sjeff  else
34592654Sjeff    OS << "ImplicitList" << EmittedLists[UseList] << ", ";
34692654Sjeff
34792654Sjeff  std::vector<Record*> DefList = Inst.TheDef->getValueAsListOfDefs("Defs");
34892654Sjeff  if (DefList.empty())
34992654Sjeff    OS << "NULL, ";
35092654Sjeff  else
35192654Sjeff    OS << "ImplicitList" << EmittedLists[DefList] << ", ";
35292654Sjeff
35392654Sjeff  // Emit the operand info.
35492654Sjeff  std::vector<std::string> OperandInfo = GetOperandInfo(Inst);
35592654Sjeff  if (OperandInfo.empty())
35692654Sjeff    OS << "0";
35792654Sjeff  else
35892654Sjeff    OS << "OperandInfo" << OpInfo.find(OperandInfo)->second;
35992654Sjeff
36092654Sjeff  OS << " },  // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
36192654Sjeff}
36292758Sjeff
36392758Sjeff// emitEnums - Print out enum values for all of the instructions.
36492758Sjeffvoid InstrInfoEmitter::emitEnums(raw_ostream &OS) {
36592758Sjeff  EmitSourceFileHeader("Target Instruction Enum Values", OS);
36692758Sjeff
36792758Sjeff  OS << "\n#ifdef GET_INSTRINFO_ENUM\n";
36892758Sjeff  OS << "#undef GET_INSTRINFO_ENUM\n";
36992758Sjeff
37092758Sjeff  OS << "namespace llvm {\n\n";
37192758Sjeff
37292654Sjeff  CodeGenTarget Target(Records);
37392654Sjeff
37492654Sjeff  // We must emit the PHI opcode first...
37592654Sjeff  std::string Namespace = Target.getInstNamespace();
37692654Sjeff
37792654Sjeff  if (Namespace.empty()) {
37892654Sjeff    fprintf(stderr, "No instructions defined!\n");
37992654Sjeff    exit(1);
38092654Sjeff  }
38192654Sjeff
38292654Sjeff  const std::vector<const CodeGenInstruction*> &NumberedInstructions =
38392654Sjeff    Target.getInstructionsByEnumValue();
38492654Sjeff
38592654Sjeff  OS << "namespace " << Namespace << " {\n";
38692654Sjeff  OS << "  enum {\n";
38792654Sjeff  for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
38892654Sjeff    OS << "    " << NumberedInstructions[i]->TheDef->getName()
38992654Sjeff       << "\t= " << i << ",\n";
39092654Sjeff  }
39192654Sjeff  OS << "    INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n";
39292654Sjeff  OS << "  };\n}\n";
39392654Sjeff  OS << "} // End llvm namespace \n";
39492654Sjeff
39592654Sjeff  OS << "#endif // GET_INSTRINFO_ENUM\n\n";
39692654Sjeff}
39792654Sjeff