| Chris Lattner | f5bd1b7 | 2003-10-05 19:27:59 +0000 | [diff] [blame] | 1 | //===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===// | 
| John Criswell | d303203 | 2003-10-20 20:20:30 +0000 | [diff] [blame] | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file was developed by the LLVM research group and is distributed under | 
|  | 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | f5bd1b7 | 2003-10-05 19:27:59 +0000 | [diff] [blame] | 9 | // | 
|  | 10 | // This tablegen backend is responsible for emitting a description of the target | 
|  | 11 | // instruction set for the code generator. | 
|  | 12 | // | 
|  | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
|  | 15 | #include "InstrInfoEmitter.h" | 
|  | 16 | #include "CodeGenWrappers.h" | 
|  | 17 | #include "Record.h" | 
|  | 18 |  | 
| Brian Gaeke | 960707c | 2003-11-11 22:41:34 +0000 | [diff] [blame] | 19 | namespace llvm { | 
|  | 20 |  | 
| Chris Lattner | f5bd1b7 | 2003-10-05 19:27:59 +0000 | [diff] [blame] | 21 | // runEnums - Print out enum values for all of the instructions. | 
|  | 22 | void InstrInfoEmitter::runEnums(std::ostream &OS) { | 
|  | 23 | std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); | 
|  | 24 |  | 
|  | 25 | if (Insts.size() == 0) | 
|  | 26 | throw std::string("No 'Instruction' subclasses defined!"); | 
|  | 27 |  | 
|  | 28 | std::string Namespace = Insts[0]->getValueAsString("Namespace"); | 
|  | 29 |  | 
|  | 30 | EmitSourceFileHeader("Target Instruction Enum Values", OS); | 
|  | 31 |  | 
|  | 32 | if (!Namespace.empty()) | 
|  | 33 | OS << "namespace " << Namespace << " {\n"; | 
|  | 34 | OS << "  enum {\n"; | 
|  | 35 |  | 
|  | 36 | CodeGenTarget Target; | 
|  | 37 |  | 
|  | 38 | // We must emit the PHI opcode first... | 
|  | 39 | Record *InstrInfo = Target.getInstructionSet(); | 
|  | 40 | Record *PHI = InstrInfo->getValueAsDef("PHIInst"); | 
|  | 41 |  | 
|  | 42 | OS << "    " << PHI->getName() << ", \t// 0 (fixed for all targets)\n"; | 
|  | 43 |  | 
|  | 44 | // Print out the rest of the instructions now... | 
|  | 45 | for (unsigned i = 0, e = Insts.size(); i != e; ++i) | 
|  | 46 | if (Insts[i] != PHI) | 
|  | 47 | OS << "    " << Insts[i]->getName() << ", \t// " << i+1 << "\n"; | 
|  | 48 |  | 
|  | 49 | OS << "  };\n"; | 
|  | 50 | if (!Namespace.empty()) | 
|  | 51 | OS << "}\n"; | 
| Brian Gaeke | 960707c | 2003-11-11 22:41:34 +0000 | [diff] [blame] | 52 | EmitSourceFileTail(OS); | 
| Chris Lattner | f5bd1b7 | 2003-10-05 19:27:59 +0000 | [diff] [blame] | 53 | } | 
|  | 54 |  | 
|  | 55 | void InstrInfoEmitter::printDefList(ListInit *LI, const std::string &Name, | 
|  | 56 | std::ostream &OS) const { | 
|  | 57 | OS << "static const unsigned " << Name << "[] = { "; | 
|  | 58 | for (unsigned j = 0, e = LI->getSize(); j != e; ++j) | 
|  | 59 | if (DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(j))) | 
|  | 60 | OS << getQualifiedName(DI->getDef()) << ", "; | 
|  | 61 | else | 
|  | 62 | throw "Illegal value in '" + Name + "' list!"; | 
|  | 63 | OS << "0 };\n"; | 
|  | 64 | } | 
|  | 65 |  | 
|  | 66 |  | 
|  | 67 | // run - Emit the main instruction description records for the target... | 
|  | 68 | void InstrInfoEmitter::run(std::ostream &OS) { | 
|  | 69 | EmitSourceFileHeader("Target Instruction Descriptors", OS); | 
|  | 70 | CodeGenTarget Target; | 
|  | 71 | const std::string &TargetName = Target.getName(); | 
|  | 72 | Record *InstrInfo = Target.getInstructionSet(); | 
|  | 73 | Record *PHI = InstrInfo->getValueAsDef("PHIInst"); | 
|  | 74 |  | 
|  | 75 | std::vector<Record*> Instructions = | 
|  | 76 | Records.getAllDerivedDefinitions("Instruction"); | 
|  | 77 |  | 
| Alkis Evlogimenos | 5f1f337 | 2003-10-08 05:20:08 +0000 | [diff] [blame] | 78 | // Emit empty implicit uses and defs lists | 
|  | 79 | OS << "static const unsigned EmptyImpUses[] = { 0 };\n" | 
|  | 80 | << "static const unsigned EmptyImpDefs[] = { 0 };\n"; | 
|  | 81 |  | 
| Chris Lattner | f5bd1b7 | 2003-10-05 19:27:59 +0000 | [diff] [blame] | 82 | // Emit all of the instruction's implicit uses and defs... | 
|  | 83 | for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { | 
|  | 84 | Record *Inst = Instructions[i]; | 
|  | 85 | ListInit *LI = Inst->getValueAsListInit("Uses"); | 
|  | 86 | if (LI->getSize()) printDefList(LI, Inst->getName()+"ImpUses", OS); | 
|  | 87 | LI = Inst->getValueAsListInit("Defs"); | 
|  | 88 | if (LI->getSize()) printDefList(LI, Inst->getName()+"ImpDefs", OS); | 
|  | 89 | } | 
|  | 90 |  | 
|  | 91 | OS << "\nstatic const TargetInstrDescriptor " << TargetName | 
|  | 92 | << "Insts[] = {\n"; | 
|  | 93 | emitRecord(PHI, 0, InstrInfo, OS); | 
|  | 94 |  | 
|  | 95 | for (unsigned i = 0, e = Instructions.size(); i != e; ++i) | 
|  | 96 | if (Instructions[i] != PHI) | 
|  | 97 | emitRecord(Instructions[i], i+1, InstrInfo, OS); | 
|  | 98 | OS << "};\n"; | 
| Brian Gaeke | 960707c | 2003-11-11 22:41:34 +0000 | [diff] [blame] | 99 | EmitSourceFileTail(OS); | 
| Chris Lattner | f5bd1b7 | 2003-10-05 19:27:59 +0000 | [diff] [blame] | 100 | } | 
|  | 101 |  | 
|  | 102 | void InstrInfoEmitter::emitRecord(Record *R, unsigned Num, Record *InstrInfo, | 
|  | 103 | std::ostream &OS) { | 
|  | 104 | OS << "  { \"" << R->getValueAsString("Name") | 
|  | 105 | << "\",\t-1, -1, 0, false, 0, 0, 0, 0"; | 
|  | 106 |  | 
|  | 107 | // Emit all of the target indepedent flags... | 
|  | 108 | if (R->getValueAsBit("isReturn"))     OS << "|M_RET_FLAG"; | 
|  | 109 | if (R->getValueAsBit("isBranch"))     OS << "|M_BRANCH_FLAG"; | 
|  | 110 | if (R->getValueAsBit("isCall"  ))     OS << "|M_CALL_FLAG"; | 
|  | 111 | if (R->getValueAsBit("isTwoAddress")) OS << "|M_2_ADDR_FLAG"; | 
|  | 112 | if (R->getValueAsBit("isTerminator")) OS << "|M_TERMINATOR_FLAG"; | 
|  | 113 | OS << ", 0"; | 
|  | 114 |  | 
|  | 115 | // Emit all of the target-specific flags... | 
|  | 116 | ListInit *LI    = InstrInfo->getValueAsListInit("TSFlagsFields"); | 
|  | 117 | ListInit *Shift = InstrInfo->getValueAsListInit("TSFlagsShifts"); | 
|  | 118 | if (LI->getSize() != Shift->getSize()) | 
|  | 119 | throw "Lengths of " + InstrInfo->getName() + | 
|  | 120 | ":(TargetInfoFields, TargetInfoPositions) must be equal!"; | 
|  | 121 |  | 
|  | 122 | for (unsigned i = 0, e = LI->getSize(); i != e; ++i) | 
|  | 123 | emitShiftedValue(R, dynamic_cast<StringInit*>(LI->getElement(i)), | 
|  | 124 | dynamic_cast<IntInit*>(Shift->getElement(i)), OS); | 
|  | 125 |  | 
|  | 126 | OS << ", "; | 
|  | 127 |  | 
|  | 128 | // Emit the implicit uses and defs lists... | 
|  | 129 | LI = R->getValueAsListInit("Uses"); | 
|  | 130 | if (!LI->getSize()) | 
| Alkis Evlogimenos | 5f1f337 | 2003-10-08 05:20:08 +0000 | [diff] [blame] | 131 | OS << "EmptyImpUses, "; | 
| Chris Lattner | f5bd1b7 | 2003-10-05 19:27:59 +0000 | [diff] [blame] | 132 | else | 
|  | 133 | OS << R->getName() << "ImpUses, "; | 
|  | 134 |  | 
|  | 135 | LI = R->getValueAsListInit("Defs"); | 
|  | 136 | if (!LI->getSize()) | 
| Alkis Evlogimenos | 5f1f337 | 2003-10-08 05:20:08 +0000 | [diff] [blame] | 137 | OS << "EmptyImpDefs "; | 
| Chris Lattner | f5bd1b7 | 2003-10-05 19:27:59 +0000 | [diff] [blame] | 138 | else | 
|  | 139 | OS << R->getName() << "ImpDefs "; | 
|  | 140 |  | 
|  | 141 | OS << " },  // Inst #" << Num << " = " << R->getName() << "\n"; | 
|  | 142 | } | 
|  | 143 |  | 
|  | 144 | void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val, | 
|  | 145 | IntInit *ShiftInt, std::ostream &OS) { | 
|  | 146 | if (Val == 0 || ShiftInt == 0) | 
|  | 147 | throw std::string("Illegal value or shift amount in TargetInfo*!"); | 
|  | 148 | RecordVal *RV = R->getValue(Val->getValue()); | 
|  | 149 | int Shift = ShiftInt->getValue(); | 
|  | 150 |  | 
|  | 151 | if (RV == 0 || RV->getValue() == 0) | 
|  | 152 | throw R->getName() + " doesn't have a field named '" + Val->getValue()+"'!"; | 
|  | 153 |  | 
|  | 154 | Init *Value = RV->getValue(); | 
|  | 155 | if (BitInit *BI = dynamic_cast<BitInit*>(Value)) { | 
|  | 156 | if (BI->getValue()) OS << "|(1<<" << Shift << ")"; | 
|  | 157 | return; | 
|  | 158 | } else if (BitsInit *BI = dynamic_cast<BitsInit*>(Value)) { | 
|  | 159 | // Convert the Bits to an integer to print... | 
|  | 160 | Init *I = BI->convertInitializerTo(new IntRecTy()); | 
|  | 161 | if (I) | 
|  | 162 | if (IntInit *II = dynamic_cast<IntInit*>(I)) { | 
|  | 163 | if (II->getValue()) | 
|  | 164 | OS << "|(" << II->getValue() << "<<" << Shift << ")"; | 
|  | 165 | return; | 
|  | 166 | } | 
|  | 167 |  | 
|  | 168 | } else if (IntInit *II = dynamic_cast<IntInit*>(Value)) { | 
|  | 169 | if (II->getValue()) OS << "|(" << II->getValue() << "<<" << Shift << ")"; | 
|  | 170 | return; | 
|  | 171 | } | 
|  | 172 |  | 
|  | 173 | std::cerr << "Unhandled initializer: " << *Val << "\n"; | 
|  | 174 | throw "In record '" + R->getName() + "' for TSFlag emission."; | 
|  | 175 | } | 
| Brian Gaeke | 960707c | 2003-11-11 22:41:34 +0000 | [diff] [blame] | 176 |  | 
|  | 177 | } // End llvm namespace |