| Chris Lattner | 33ccf7e | 2003-08-03 17:24:10 +0000 | [diff] [blame] | 1 | //===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===// | 
| Misha Brukman | 3da94ae | 2005-04-22 00:00:37 +0000 | [diff] [blame] | 2 | // | 
| John Criswell | 01d4582 | 2003-10-20 20:20:30 +0000 | [diff] [blame] | 3 | //                     The LLVM Compiler Infrastructure | 
 | 4 | // | 
| Chris Lattner | 3060910 | 2007-12-29 20:37:13 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
 | 6 | // License. See LICENSE.TXT for details. | 
| Misha Brukman | 3da94ae | 2005-04-22 00:00:37 +0000 | [diff] [blame] | 7 | // | 
| John Criswell | 01d4582 | 2003-10-20 20:20:30 +0000 | [diff] [blame] | 8 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 33ccf7e | 2003-08-03 17:24:10 +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" | 
| Chris Lattner | 803a5f6 | 2004-08-01 04:04:35 +0000 | [diff] [blame] | 16 | #include "CodeGenTarget.h" | 
| Chris Lattner | 33ccf7e | 2003-08-03 17:24:10 +0000 | [diff] [blame] | 17 | #include "Record.h" | 
| Chris Lattner | 23132b1 | 2009-08-24 03:52:50 +0000 | [diff] [blame] | 18 | #include "llvm/ADT/StringExtras.h" | 
| Jeff Cohen | cb366d9 | 2005-11-01 18:04:06 +0000 | [diff] [blame] | 19 | #include <algorithm> | 
| Chris Lattner | 2082ebe | 2004-08-01 03:55:39 +0000 | [diff] [blame] | 20 | using namespace llvm; | 
| Brian Gaeke | d0fde30 | 2003-11-11 22:41:34 +0000 | [diff] [blame] | 21 |  | 
| Chris Lattner | 5fbe275 | 2008-01-06 01:21:51 +0000 | [diff] [blame] | 22 | static void PrintDefList(const std::vector<Record*> &Uses, | 
| Daniel Dunbar | 1a55180 | 2009-07-03 00:10:29 +0000 | [diff] [blame] | 23 |                          unsigned Num, raw_ostream &OS) { | 
| Chris Lattner | a3ac88d | 2005-08-18 21:36:47 +0000 | [diff] [blame] | 24 |   OS << "static const unsigned ImplicitList" << Num << "[] = { "; | 
 | 25 |   for (unsigned i = 0, e = Uses.size(); i != e; ++i) | 
 | 26 |     OS << getQualifiedName(Uses[i]) << ", "; | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 27 |   OS << "0 };\n"; | 
 | 28 | } | 
 | 29 |  | 
| Evan Cheng | b89be61 | 2008-10-17 21:00:09 +0000 | [diff] [blame] | 30 | static void PrintBarriers(std::vector<Record*> &Barriers, | 
| Daniel Dunbar | 1a55180 | 2009-07-03 00:10:29 +0000 | [diff] [blame] | 31 |                           unsigned Num, raw_ostream &OS) { | 
| Evan Cheng | b89be61 | 2008-10-17 21:00:09 +0000 | [diff] [blame] | 32 |   OS << "static const TargetRegisterClass* Barriers" << Num << "[] = { "; | 
 | 33 |   for (unsigned i = 0, e = Barriers.size(); i != e; ++i) | 
 | 34 |     OS << "&" << getQualifiedName(Barriers[i]) << "RegClass, "; | 
 | 35 |   OS << "NULL };\n"; | 
 | 36 | } | 
 | 37 |  | 
| Chris Lattner | ef8339b | 2008-01-06 01:20:13 +0000 | [diff] [blame] | 38 | //===----------------------------------------------------------------------===// | 
 | 39 | // Instruction Itinerary Information. | 
 | 40 | //===----------------------------------------------------------------------===// | 
 | 41 |  | 
 | 42 | struct RecordNameComparator { | 
 | 43 |   bool operator()(const Record *Rec1, const Record *Rec2) const { | 
 | 44 |     return Rec1->getName() < Rec2->getName(); | 
 | 45 |   } | 
 | 46 | }; | 
 | 47 |  | 
 | 48 | void InstrInfoEmitter::GatherItinClasses() { | 
 | 49 |   std::vector<Record*> DefList = | 
 | 50 |   Records.getAllDerivedDefinitions("InstrItinClass"); | 
 | 51 |   std::sort(DefList.begin(), DefList.end(), RecordNameComparator()); | 
 | 52 |    | 
 | 53 |   for (unsigned i = 0, N = DefList.size(); i < N; i++) | 
 | 54 |     ItinClassMap[DefList[i]->getName()] = i; | 
 | 55 | }   | 
 | 56 |  | 
 | 57 | unsigned InstrInfoEmitter::getItinClassNumber(const Record *InstRec) { | 
 | 58 |   return ItinClassMap[InstRec->getValueAsDef("Itinerary")->getName()]; | 
 | 59 | } | 
 | 60 |  | 
 | 61 | //===----------------------------------------------------------------------===// | 
 | 62 | // Operand Info Emission. | 
 | 63 | //===----------------------------------------------------------------------===// | 
 | 64 |  | 
| Chris Lattner | a0cca4a | 2006-11-06 23:49:51 +0000 | [diff] [blame] | 65 | std::vector<std::string> | 
 | 66 | InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { | 
 | 67 |   std::vector<std::string> Result; | 
| Chris Lattner | f196839 | 2006-11-10 02:01:40 +0000 | [diff] [blame] | 68 |    | 
| Chris Lattner | d5aa3e2 | 2005-08-19 18:46:26 +0000 | [diff] [blame] | 69 |   for (unsigned i = 0, e = Inst.OperandList.size(); i != e; ++i) { | 
| Chris Lattner | f196839 | 2006-11-10 02:01:40 +0000 | [diff] [blame] | 70 |     // Handle aggregate operands and normal operands the same way by expanding | 
 | 71 |     // either case into a list of operands for this op. | 
 | 72 |     std::vector<CodeGenInstruction::OperandInfo> OperandList; | 
| Chris Lattner | a0cca4a | 2006-11-06 23:49:51 +0000 | [diff] [blame] | 73 |  | 
| Chris Lattner | f196839 | 2006-11-10 02:01:40 +0000 | [diff] [blame] | 74 |     // This might be a multiple operand thing.  Targets like X86 have | 
 | 75 |     // registers in their multi-operand operands.  It may also be an anonymous | 
 | 76 |     // operand, which has a single operand, but no declared class for the | 
 | 77 |     // operand. | 
 | 78 |     DagInit *MIOI = Inst.OperandList[i].MIOperandInfo; | 
 | 79 |      | 
 | 80 |     if (!MIOI || MIOI->getNumArgs() == 0) { | 
 | 81 |       // Single, anonymous, operand. | 
 | 82 |       OperandList.push_back(Inst.OperandList[i]); | 
| Chris Lattner | 65303d6 | 2005-11-19 07:05:57 +0000 | [diff] [blame] | 83 |     } else { | 
| Chris Lattner | 65303d6 | 2005-11-19 07:05:57 +0000 | [diff] [blame] | 84 |       for (unsigned j = 0, e = Inst.OperandList[i].MINumOperands; j != e; ++j) { | 
| Chris Lattner | f196839 | 2006-11-10 02:01:40 +0000 | [diff] [blame] | 85 |         OperandList.push_back(Inst.OperandList[i]); | 
| Chris Lattner | a0cca4a | 2006-11-06 23:49:51 +0000 | [diff] [blame] | 86 |  | 
| Chris Lattner | f196839 | 2006-11-10 02:01:40 +0000 | [diff] [blame] | 87 |         Record *OpR = dynamic_cast<DefInit*>(MIOI->getArg(j))->getDef(); | 
 | 88 |         OperandList.back().Rec = OpR; | 
| Chris Lattner | 65303d6 | 2005-11-19 07:05:57 +0000 | [diff] [blame] | 89 |       } | 
| Chris Lattner | d5aa3e2 | 2005-08-19 18:46:26 +0000 | [diff] [blame] | 90 |     } | 
| Chris Lattner | f196839 | 2006-11-10 02:01:40 +0000 | [diff] [blame] | 91 |  | 
 | 92 |     for (unsigned j = 0, e = OperandList.size(); j != e; ++j) { | 
 | 93 |       Record *OpR = OperandList[j].Rec; | 
 | 94 |       std::string Res; | 
 | 95 |        | 
 | 96 |       if (OpR->isSubClassOf("RegisterClass")) | 
 | 97 |         Res += getQualifiedName(OpR) + "RegClassID, "; | 
| Chris Lattner | cb778a8 | 2009-07-29 21:10:12 +0000 | [diff] [blame] | 98 |       else if (OpR->isSubClassOf("PointerLikeRegClass")) | 
 | 99 |         Res += utostr(OpR->getValueAsInt("RegClassKind")) + ", "; | 
| Chris Lattner | f196839 | 2006-11-10 02:01:40 +0000 | [diff] [blame] | 100 |       else | 
 | 101 |         Res += "0, "; | 
| Chris Lattner | cb778a8 | 2009-07-29 21:10:12 +0000 | [diff] [blame] | 102 |        | 
| Chris Lattner | f196839 | 2006-11-10 02:01:40 +0000 | [diff] [blame] | 103 |       // Fill in applicable flags. | 
 | 104 |       Res += "0"; | 
 | 105 |          | 
 | 106 |       // Ptr value whose register class is resolved via callback. | 
| Chris Lattner | a938ac6 | 2009-07-29 20:43:05 +0000 | [diff] [blame] | 107 |       if (OpR->isSubClassOf("PointerLikeRegClass")) | 
| Chris Lattner | 0ff2396 | 2008-01-07 06:42:05 +0000 | [diff] [blame] | 108 |         Res += "|(1<<TOI::LookupPtrRegClass)"; | 
| Chris Lattner | f196839 | 2006-11-10 02:01:40 +0000 | [diff] [blame] | 109 |  | 
 | 110 |       // Predicate operands.  Check to see if the original unexpanded operand | 
 | 111 |       // was of type PredicateOperand. | 
| Evan Cheng | c419bd3 | 2007-07-06 23:23:38 +0000 | [diff] [blame] | 112 |       if (Inst.OperandList[i].Rec->isSubClassOf("PredicateOperand")) | 
| Chris Lattner | 0ff2396 | 2008-01-07 06:42:05 +0000 | [diff] [blame] | 113 |         Res += "|(1<<TOI::Predicate)"; | 
| Chris Lattner | f196839 | 2006-11-10 02:01:40 +0000 | [diff] [blame] | 114 |          | 
| Evan Cheng | 88cc092 | 2007-07-10 18:05:01 +0000 | [diff] [blame] | 115 |       // Optional def operands.  Check to see if the original unexpanded operand | 
 | 116 |       // was of type OptionalDefOperand. | 
 | 117 |       if (Inst.OperandList[i].Rec->isSubClassOf("OptionalDefOperand")) | 
| Chris Lattner | 0ff2396 | 2008-01-07 06:42:05 +0000 | [diff] [blame] | 118 |         Res += "|(1<<TOI::OptionalDef)"; | 
| Evan Cheng | 88cc092 | 2007-07-10 18:05:01 +0000 | [diff] [blame] | 119 |  | 
| Chris Lattner | f196839 | 2006-11-10 02:01:40 +0000 | [diff] [blame] | 120 |       // Fill in constraint info. | 
| Chris Lattner | 0bb7500 | 2006-11-15 02:38:17 +0000 | [diff] [blame] | 121 |       Res += ", " + Inst.OperandList[i].Constraints[j]; | 
| Chris Lattner | f196839 | 2006-11-10 02:01:40 +0000 | [diff] [blame] | 122 |       Result.push_back(Res); | 
 | 123 |     } | 
| Chris Lattner | d5aa3e2 | 2005-08-19 18:46:26 +0000 | [diff] [blame] | 124 |   } | 
| Evan Cheng | e2ba897 | 2006-11-01 00:27:05 +0000 | [diff] [blame] | 125 |  | 
| Chris Lattner | d5aa3e2 | 2005-08-19 18:46:26 +0000 | [diff] [blame] | 126 |   return Result; | 
 | 127 | } | 
 | 128 |  | 
| Daniel Dunbar | 1a55180 | 2009-07-03 00:10:29 +0000 | [diff] [blame] | 129 | void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,  | 
| Chris Lattner | ef8339b | 2008-01-06 01:20:13 +0000 | [diff] [blame] | 130 |                                        OperandInfoMapTy &OperandInfoIDs) { | 
 | 131 |   // ID #0 is for no operand info. | 
 | 132 |   unsigned OperandListNum = 0; | 
 | 133 |   OperandInfoIDs[std::vector<std::string>()] = ++OperandListNum; | 
 | 134 |    | 
 | 135 |   OS << "\n"; | 
 | 136 |   const CodeGenTarget &Target = CDP.getTargetInfo(); | 
 | 137 |   for (CodeGenTarget::inst_iterator II = Target.inst_begin(), | 
 | 138 |        E = Target.inst_end(); II != E; ++II) { | 
 | 139 |     std::vector<std::string> OperandInfo = GetOperandInfo(II->second); | 
 | 140 |     unsigned &N = OperandInfoIDs[OperandInfo]; | 
 | 141 |     if (N != 0) continue; | 
 | 142 |      | 
 | 143 |     N = ++OperandListNum; | 
 | 144 |     OS << "static const TargetOperandInfo OperandInfo" << N << "[] = { "; | 
 | 145 |     for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i) | 
 | 146 |       OS << "{ " << OperandInfo[i] << " }, "; | 
 | 147 |     OS << "};\n"; | 
 | 148 |   } | 
 | 149 | } | 
 | 150 |  | 
| Evan Cheng | b89be61 | 2008-10-17 21:00:09 +0000 | [diff] [blame] | 151 | void InstrInfoEmitter::DetectRegisterClassBarriers(std::vector<Record*> &Defs, | 
 | 152 |                                   const std::vector<CodeGenRegisterClass> &RCs, | 
 | 153 |                                   std::vector<Record*> &Barriers) { | 
 | 154 |   std::set<Record*> DefSet; | 
 | 155 |   unsigned NumDefs = Defs.size(); | 
 | 156 |   for (unsigned i = 0; i < NumDefs; ++i) | 
 | 157 |     DefSet.insert(Defs[i]); | 
 | 158 |  | 
 | 159 |   for (unsigned i = 0, e = RCs.size(); i != e; ++i) { | 
 | 160 |     const CodeGenRegisterClass &RC = RCs[i]; | 
 | 161 |     unsigned NumRegs = RC.Elements.size(); | 
 | 162 |     if (NumRegs > NumDefs) | 
 | 163 |       continue; // Can't possibly clobber this RC. | 
 | 164 |  | 
 | 165 |     bool Clobber = true; | 
 | 166 |     for (unsigned j = 0; j < NumRegs; ++j) { | 
 | 167 |       Record *Reg = RC.Elements[j]; | 
 | 168 |       if (!DefSet.count(Reg)) { | 
 | 169 |         Clobber = false; | 
 | 170 |         break; | 
 | 171 |       } | 
 | 172 |     } | 
 | 173 |     if (Clobber) | 
 | 174 |       Barriers.push_back(RC.TheDef); | 
 | 175 |   } | 
 | 176 | } | 
 | 177 |  | 
| Chris Lattner | ef8339b | 2008-01-06 01:20:13 +0000 | [diff] [blame] | 178 | //===----------------------------------------------------------------------===// | 
 | 179 | // Main Output. | 
 | 180 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 181 |  | 
 | 182 | // run - Emit the main instruction description records for the target... | 
| Daniel Dunbar | 1a55180 | 2009-07-03 00:10:29 +0000 | [diff] [blame] | 183 | void InstrInfoEmitter::run(raw_ostream &OS) { | 
| Jim Laskey | b5a0c0e | 2005-10-31 17:16:46 +0000 | [diff] [blame] | 184 |   GatherItinClasses(); | 
 | 185 |  | 
| Chris Lattner | bc01723 | 2003-08-06 04:32:07 +0000 | [diff] [blame] | 186 |   EmitSourceFileHeader("Target Instruction Descriptors", OS); | 
| Chris Lattner | 2c38413 | 2004-08-17 03:08:28 +0000 | [diff] [blame] | 187 |   OS << "namespace llvm {\n\n"; | 
 | 188 |  | 
| Dan Gohman | ee4fa19 | 2008-04-03 00:02:49 +0000 | [diff] [blame] | 189 |   CodeGenTarget &Target = CDP.getTargetInfo(); | 
| Chris Lattner | 7884b75 | 2003-08-07 05:39:09 +0000 | [diff] [blame] | 190 |   const std::string &TargetName = Target.getName(); | 
 | 191 |   Record *InstrInfo = Target.getInstructionSet(); | 
| Evan Cheng | b89be61 | 2008-10-17 21:00:09 +0000 | [diff] [blame] | 192 |   const std::vector<CodeGenRegisterClass> &RCs = Target.getRegisterClasses(); | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 193 |  | 
| Chris Lattner | a3ac88d | 2005-08-18 21:36:47 +0000 | [diff] [blame] | 194 |   // Keep track of all of the def lists we have emitted already. | 
 | 195 |   std::map<std::vector<Record*>, unsigned> EmittedLists; | 
| Chris Lattner | a3ac88d | 2005-08-18 21:36:47 +0000 | [diff] [blame] | 196 |   unsigned ListNumber = 0; | 
| Evan Cheng | b89be61 | 2008-10-17 21:00:09 +0000 | [diff] [blame] | 197 |   std::map<std::vector<Record*>, unsigned> EmittedBarriers; | 
 | 198 |   unsigned BarrierNumber = 0; | 
 | 199 |   std::map<Record*, unsigned> BarriersMap; | 
| Chris Lattner | a3ac88d | 2005-08-18 21:36:47 +0000 | [diff] [blame] | 200 |   | 
 | 201 |   // Emit all of the instruction's implicit uses and defs. | 
| Chris Lattner | ec35240 | 2004-08-01 05:04:00 +0000 | [diff] [blame] | 202 |   for (CodeGenTarget::inst_iterator II = Target.inst_begin(), | 
 | 203 |          E = Target.inst_end(); II != E; ++II) { | 
 | 204 |     Record *Inst = II->second.TheDef; | 
| Chris Lattner | 366080c | 2005-10-28 22:59:53 +0000 | [diff] [blame] | 205 |     std::vector<Record*> Uses = Inst->getValueAsListOfDefs("Uses"); | 
 | 206 |     if (!Uses.empty()) { | 
| Chris Lattner | a3ac88d | 2005-08-18 21:36:47 +0000 | [diff] [blame] | 207 |       unsigned &IL = EmittedLists[Uses]; | 
| Chris Lattner | 5fbe275 | 2008-01-06 01:21:51 +0000 | [diff] [blame] | 208 |       if (!IL) PrintDefList(Uses, IL = ++ListNumber, OS); | 
| Chris Lattner | a3ac88d | 2005-08-18 21:36:47 +0000 | [diff] [blame] | 209 |     } | 
| Chris Lattner | 366080c | 2005-10-28 22:59:53 +0000 | [diff] [blame] | 210 |     std::vector<Record*> Defs = Inst->getValueAsListOfDefs("Defs"); | 
 | 211 |     if (!Defs.empty()) { | 
| Evan Cheng | b89be61 | 2008-10-17 21:00:09 +0000 | [diff] [blame] | 212 |       std::vector<Record*> RCBarriers; | 
 | 213 |       DetectRegisterClassBarriers(Defs, RCs, RCBarriers); | 
 | 214 |       if (!RCBarriers.empty()) { | 
 | 215 |         unsigned &IB = EmittedBarriers[RCBarriers]; | 
 | 216 |         if (!IB) PrintBarriers(RCBarriers, IB = ++BarrierNumber, OS); | 
 | 217 |         BarriersMap.insert(std::make_pair(Inst, IB)); | 
 | 218 |       } | 
 | 219 |  | 
| Chris Lattner | 366080c | 2005-10-28 22:59:53 +0000 | [diff] [blame] | 220 |       unsigned &IL = EmittedLists[Defs]; | 
| Chris Lattner | 5fbe275 | 2008-01-06 01:21:51 +0000 | [diff] [blame] | 221 |       if (!IL) PrintDefList(Defs, IL = ++ListNumber, OS); | 
| Chris Lattner | a3ac88d | 2005-08-18 21:36:47 +0000 | [diff] [blame] | 222 |     } | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 223 |   } | 
 | 224 |  | 
| Chris Lattner | ef8339b | 2008-01-06 01:20:13 +0000 | [diff] [blame] | 225 |   OperandInfoMapTy OperandInfoIDs; | 
| Chris Lattner | d5aa3e2 | 2005-08-19 18:46:26 +0000 | [diff] [blame] | 226 |    | 
| Chris Lattner | 0e384b6 | 2005-08-19 16:57:28 +0000 | [diff] [blame] | 227 |   // Emit all of the operand info records. | 
| Chris Lattner | ef8339b | 2008-01-06 01:20:13 +0000 | [diff] [blame] | 228 |   EmitOperandInfo(OS, OperandInfoIDs); | 
| Chris Lattner | 0e384b6 | 2005-08-19 16:57:28 +0000 | [diff] [blame] | 229 |    | 
| Chris Lattner | 749c6f6 | 2008-01-07 07:27:27 +0000 | [diff] [blame] | 230 |   // Emit all of the TargetInstrDesc records in their ENUM ordering. | 
| Chris Lattner | 0e384b6 | 2005-08-19 16:57:28 +0000 | [diff] [blame] | 231 |   // | 
| Chris Lattner | 749c6f6 | 2008-01-07 07:27:27 +0000 | [diff] [blame] | 232 |   OS << "\nstatic const TargetInstrDesc " << TargetName | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 233 |      << "Insts[] = {\n"; | 
| Chris Lattner | f52e261 | 2006-01-27 01:44:09 +0000 | [diff] [blame] | 234 |   std::vector<const CodeGenInstruction*> NumberedInstructions; | 
 | 235 |   Target.getInstructionsByEnumValue(NumberedInstructions); | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 236 |  | 
| Chris Lattner | f52e261 | 2006-01-27 01:44:09 +0000 | [diff] [blame] | 237 |   for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) | 
 | 238 |     emitRecord(*NumberedInstructions[i], i, InstrInfo, EmittedLists, | 
| Evan Cheng | b89be61 | 2008-10-17 21:00:09 +0000 | [diff] [blame] | 239 |                BarriersMap, OperandInfoIDs, OS); | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 240 |   OS << "};\n"; | 
| Chris Lattner | 2c38413 | 2004-08-17 03:08:28 +0000 | [diff] [blame] | 241 |   OS << "} // End llvm namespace \n"; | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 242 | } | 
 | 243 |  | 
| Chris Lattner | ec35240 | 2004-08-01 05:04:00 +0000 | [diff] [blame] | 244 | void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, | 
| Chris Lattner | a3ac88d | 2005-08-18 21:36:47 +0000 | [diff] [blame] | 245 |                                   Record *InstrInfo, | 
| Chris Lattner | 366080c | 2005-10-28 22:59:53 +0000 | [diff] [blame] | 246 |                          std::map<std::vector<Record*>, unsigned> &EmittedLists, | 
| Evan Cheng | b89be61 | 2008-10-17 21:00:09 +0000 | [diff] [blame] | 247 |                                   std::map<Record*, unsigned> &BarriersMap, | 
| Chris Lattner | ef8339b | 2008-01-06 01:20:13 +0000 | [diff] [blame] | 248 |                                   const OperandInfoMapTy &OpInfo, | 
| Daniel Dunbar | 1a55180 | 2009-07-03 00:10:29 +0000 | [diff] [blame] | 249 |                                   raw_ostream &OS) { | 
| Chris Lattner | a529a37 | 2008-01-06 01:53:37 +0000 | [diff] [blame] | 250 |   int MinOperands = 0; | 
| Evan Cheng | 8d3af5e | 2006-06-15 07:22:16 +0000 | [diff] [blame] | 251 |   if (!Inst.OperandList.empty()) | 
| Chris Lattner | d98958f | 2005-08-19 00:59:49 +0000 | [diff] [blame] | 252 |     // Each logical operand can be multiple MI operands. | 
| Evan Cheng | 8d3af5e | 2006-06-15 07:22:16 +0000 | [diff] [blame] | 253 |     MinOperands = Inst.OperandList.back().MIOperandNo + | 
| Chris Lattner | d98958f | 2005-08-19 00:59:49 +0000 | [diff] [blame] | 254 |                   Inst.OperandList.back().MINumOperands; | 
| Dan Gohman | d35121a | 2008-05-29 19:57:41 +0000 | [diff] [blame] | 255 |  | 
| Evan Cheng | fb1aab0 | 2006-11-17 01:46:27 +0000 | [diff] [blame] | 256 |   OS << "  { "; | 
| Evan Cheng | b591082 | 2007-08-02 00:20:17 +0000 | [diff] [blame] | 257 |   OS << Num << ",\t" << MinOperands << ",\t" | 
| Chris Lattner | 4764189 | 2008-01-07 05:06:49 +0000 | [diff] [blame] | 258 |      << Inst.NumDefs << ",\t" << getItinClassNumber(Inst.TheDef) | 
 | 259 |      << ",\t\"" << Inst.TheDef->getName() << "\", 0"; | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 260 |  | 
 | 261 |   // Emit all of the target indepedent flags... | 
| Bill Wendling | 8370d38 | 2008-05-28 22:54:52 +0000 | [diff] [blame] | 262 |   if (Inst.isReturn)           OS << "|(1<<TID::Return)"; | 
 | 263 |   if (Inst.isBranch)           OS << "|(1<<TID::Branch)"; | 
 | 264 |   if (Inst.isIndirectBranch)   OS << "|(1<<TID::IndirectBranch)"; | 
 | 265 |   if (Inst.isBarrier)          OS << "|(1<<TID::Barrier)"; | 
 | 266 |   if (Inst.hasDelaySlot)       OS << "|(1<<TID::DelaySlot)"; | 
 | 267 |   if (Inst.isCall)             OS << "|(1<<TID::Call)"; | 
| Dan Gohman | 15511cf | 2008-12-03 18:15:48 +0000 | [diff] [blame] | 268 |   if (Inst.canFoldAsLoad)      OS << "|(1<<TID::FoldableAsLoad)"; | 
| Bill Wendling | 8370d38 | 2008-05-28 22:54:52 +0000 | [diff] [blame] | 269 |   if (Inst.mayLoad)            OS << "|(1<<TID::MayLoad)"; | 
 | 270 |   if (Inst.mayStore)           OS << "|(1<<TID::MayStore)"; | 
 | 271 |   if (Inst.isPredicable)       OS << "|(1<<TID::Predicable)"; | 
| Chris Lattner | 0ff2396 | 2008-01-07 06:42:05 +0000 | [diff] [blame] | 272 |   if (Inst.isConvertibleToThreeAddress) OS << "|(1<<TID::ConvertibleTo3Addr)"; | 
| Bill Wendling | 8370d38 | 2008-05-28 22:54:52 +0000 | [diff] [blame] | 273 |   if (Inst.isCommutable)       OS << "|(1<<TID::Commutable)"; | 
 | 274 |   if (Inst.isTerminator)       OS << "|(1<<TID::Terminator)"; | 
| Chris Lattner | 0ff2396 | 2008-01-07 06:42:05 +0000 | [diff] [blame] | 275 |   if (Inst.isReMaterializable) OS << "|(1<<TID::Rematerializable)"; | 
 | 276 |   if (Inst.isNotDuplicable)    OS << "|(1<<TID::NotDuplicable)"; | 
 | 277 |   if (Inst.hasOptionalDef)     OS << "|(1<<TID::HasOptionalDef)"; | 
| Dan Gohman | 533297b | 2009-10-29 18:10:34 +0000 | [diff] [blame] | 278 |   if (Inst.usesCustomInserter) OS << "|(1<<TID::UsesCustomInserter)"; | 
| Chris Lattner | 0ff2396 | 2008-01-07 06:42:05 +0000 | [diff] [blame] | 279 |   if (Inst.isVariadic)         OS << "|(1<<TID::Variadic)"; | 
| Bill Wendling | 8370d38 | 2008-05-28 22:54:52 +0000 | [diff] [blame] | 280 |   if (Inst.hasSideEffects)     OS << "|(1<<TID::UnmodeledSideEffects)"; | 
 | 281 |   if (Inst.isAsCheapAsAMove)   OS << "|(1<<TID::CheapAsAMove)"; | 
| Evan Cheng | 799d697 | 2009-10-01 08:21:18 +0000 | [diff] [blame] | 282 |   if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<TID::ExtraSrcRegAllocReq)"; | 
 | 283 |   if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<TID::ExtraDefRegAllocReq)"; | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 284 |   OS << ", 0"; | 
 | 285 |  | 
 | 286 |   // Emit all of the target-specific flags... | 
 | 287 |   ListInit *LI    = InstrInfo->getValueAsListInit("TSFlagsFields"); | 
 | 288 |   ListInit *Shift = InstrInfo->getValueAsListInit("TSFlagsShifts"); | 
 | 289 |   if (LI->getSize() != Shift->getSize()) | 
 | 290 |     throw "Lengths of " + InstrInfo->getName() + | 
 | 291 |           ":(TargetInfoFields, TargetInfoPositions) must be equal!"; | 
 | 292 |  | 
 | 293 |   for (unsigned i = 0, e = LI->getSize(); i != e; ++i) | 
| Chris Lattner | ec35240 | 2004-08-01 05:04:00 +0000 | [diff] [blame] | 294 |     emitShiftedValue(Inst.TheDef, dynamic_cast<StringInit*>(LI->getElement(i)), | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 295 |                      dynamic_cast<IntInit*>(Shift->getElement(i)), OS); | 
 | 296 |  | 
 | 297 |   OS << ", "; | 
 | 298 |  | 
 | 299 |   // Emit the implicit uses and defs lists... | 
| Chris Lattner | 366080c | 2005-10-28 22:59:53 +0000 | [diff] [blame] | 300 |   std::vector<Record*> UseList = Inst.TheDef->getValueAsListOfDefs("Uses"); | 
 | 301 |   if (UseList.empty()) | 
| Jim Laskey | cd4317e | 2006-07-21 21:15:20 +0000 | [diff] [blame] | 302 |     OS << "NULL, "; | 
| Misha Brukman | 3da94ae | 2005-04-22 00:00:37 +0000 | [diff] [blame] | 303 |   else | 
| Chris Lattner | 366080c | 2005-10-28 22:59:53 +0000 | [diff] [blame] | 304 |     OS << "ImplicitList" << EmittedLists[UseList] << ", "; | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 305 |  | 
| Chris Lattner | 366080c | 2005-10-28 22:59:53 +0000 | [diff] [blame] | 306 |   std::vector<Record*> DefList = Inst.TheDef->getValueAsListOfDefs("Defs"); | 
 | 307 |   if (DefList.empty()) | 
| Jim Laskey | cd4317e | 2006-07-21 21:15:20 +0000 | [diff] [blame] | 308 |     OS << "NULL, "; | 
| Misha Brukman | 3da94ae | 2005-04-22 00:00:37 +0000 | [diff] [blame] | 309 |   else | 
| Chris Lattner | 366080c | 2005-10-28 22:59:53 +0000 | [diff] [blame] | 310 |     OS << "ImplicitList" << EmittedLists[DefList] << ", "; | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 311 |  | 
| Evan Cheng | b89be61 | 2008-10-17 21:00:09 +0000 | [diff] [blame] | 312 |   std::map<Record*, unsigned>::iterator BI = BarriersMap.find(Inst.TheDef); | 
 | 313 |   if (BI == BarriersMap.end()) | 
 | 314 |     OS << "NULL, "; | 
 | 315 |   else | 
 | 316 |     OS << "Barriers" << BI->second << ", "; | 
 | 317 |  | 
| Chris Lattner | 0e384b6 | 2005-08-19 16:57:28 +0000 | [diff] [blame] | 318 |   // Emit the operand info. | 
| Chris Lattner | a0cca4a | 2006-11-06 23:49:51 +0000 | [diff] [blame] | 319 |   std::vector<std::string> OperandInfo = GetOperandInfo(Inst); | 
| Chris Lattner | d5aa3e2 | 2005-08-19 18:46:26 +0000 | [diff] [blame] | 320 |   if (OperandInfo.empty()) | 
 | 321 |     OS << "0"; | 
| Chris Lattner | 0e384b6 | 2005-08-19 16:57:28 +0000 | [diff] [blame] | 322 |   else | 
| Chris Lattner | ef8339b | 2008-01-06 01:20:13 +0000 | [diff] [blame] | 323 |     OS << "OperandInfo" << OpInfo.find(OperandInfo)->second; | 
| Chris Lattner | 0e384b6 | 2005-08-19 16:57:28 +0000 | [diff] [blame] | 324 |    | 
| Chris Lattner | ec35240 | 2004-08-01 05:04:00 +0000 | [diff] [blame] | 325 |   OS << " },  // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n"; | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 326 | } | 
 | 327 |  | 
| Jim Laskey | b5a0c0e | 2005-10-31 17:16:46 +0000 | [diff] [blame] | 328 |  | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 329 | void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val, | 
| Daniel Dunbar | 1a55180 | 2009-07-03 00:10:29 +0000 | [diff] [blame] | 330 |                                         IntInit *ShiftInt, raw_ostream &OS) { | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 331 |   if (Val == 0 || ShiftInt == 0) | 
 | 332 |     throw std::string("Illegal value or shift amount in TargetInfo*!"); | 
 | 333 |   RecordVal *RV = R->getValue(Val->getValue()); | 
 | 334 |   int Shift = ShiftInt->getValue(); | 
 | 335 |  | 
| Chris Lattner | f52e261 | 2006-01-27 01:44:09 +0000 | [diff] [blame] | 336 |   if (RV == 0 || RV->getValue() == 0) { | 
 | 337 |     // This isn't an error if this is a builtin instruction. | 
| Jim Laskey | a683f9b | 2007-01-26 17:29:20 +0000 | [diff] [blame] | 338 |     if (R->getName() != "PHI" && | 
 | 339 |         R->getName() != "INLINEASM" && | 
| Dan Gohman | 4406604 | 2008-07-01 00:05:16 +0000 | [diff] [blame] | 340 |         R->getName() != "DBG_LABEL" && | 
 | 341 |         R->getName() != "EH_LABEL" && | 
 | 342 |         R->getName() != "GC_LABEL" && | 
| Jakob Stoklund Olesen | 26207e5 | 2009-09-28 20:32:26 +0000 | [diff] [blame] | 343 |         R->getName() != "KILL" && | 
| Christopher Lamb | 08d5207 | 2007-07-26 07:48:21 +0000 | [diff] [blame] | 344 |         R->getName() != "EXTRACT_SUBREG" && | 
| Evan Cheng | da47e6e | 2008-03-15 00:03:38 +0000 | [diff] [blame] | 345 |         R->getName() != "INSERT_SUBREG" && | 
| Christopher Lamb | c929823 | 2008-03-16 03:12:01 +0000 | [diff] [blame] | 346 |         R->getName() != "IMPLICIT_DEF" && | 
| Dan Gohman | f8c7394 | 2009-04-13 15:38:05 +0000 | [diff] [blame] | 347 |         R->getName() != "SUBREG_TO_REG" && | 
| Dale Johannesen | 87563b3 | 2010-01-08 23:51:25 +0000 | [diff] [blame] | 348 |         R->getName() != "COPY_TO_REGCLASS" && | 
| Dale Johannesen | 243a32f | 2010-01-15 01:50:44 +0000 | [diff] [blame] | 349 |         R->getName() != "DEBUG_VALUE") | 
| Chris Lattner | f52e261 | 2006-01-27 01:44:09 +0000 | [diff] [blame] | 350 |       throw R->getName() + " doesn't have a field named '" +  | 
 | 351 |             Val->getValue() + "'!"; | 
 | 352 |     return; | 
 | 353 |   } | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 354 |  | 
 | 355 |   Init *Value = RV->getValue(); | 
 | 356 |   if (BitInit *BI = dynamic_cast<BitInit*>(Value)) { | 
 | 357 |     if (BI->getValue()) OS << "|(1<<" << Shift << ")"; | 
 | 358 |     return; | 
 | 359 |   } else if (BitsInit *BI = dynamic_cast<BitsInit*>(Value)) { | 
 | 360 |     // Convert the Bits to an integer to print... | 
 | 361 |     Init *I = BI->convertInitializerTo(new IntRecTy()); | 
 | 362 |     if (I) | 
 | 363 |       if (IntInit *II = dynamic_cast<IntInit*>(I)) { | 
| Chris Lattner | f52e261 | 2006-01-27 01:44:09 +0000 | [diff] [blame] | 364 |         if (II->getValue()) { | 
 | 365 |           if (Shift) | 
 | 366 |             OS << "|(" << II->getValue() << "<<" << Shift << ")"; | 
 | 367 |           else | 
 | 368 |             OS << "|" << II->getValue(); | 
 | 369 |         } | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 370 |         return; | 
 | 371 |       } | 
 | 372 |  | 
 | 373 |   } else if (IntInit *II = dynamic_cast<IntInit*>(Value)) { | 
| Chris Lattner | f52e261 | 2006-01-27 01:44:09 +0000 | [diff] [blame] | 374 |     if (II->getValue()) { | 
 | 375 |       if (Shift) | 
 | 376 |         OS << "|(" << II->getValue() << "<<" << Shift << ")"; | 
 | 377 |       else | 
 | 378 |         OS << II->getValue(); | 
 | 379 |     } | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 380 |     return; | 
 | 381 |   } | 
 | 382 |  | 
| Daniel Dunbar | 1a55180 | 2009-07-03 00:10:29 +0000 | [diff] [blame] | 383 |   errs() << "Unhandled initializer: " << *Val << "\n"; | 
| Chris Lattner | a3ae614 | 2003-08-03 21:57:51 +0000 | [diff] [blame] | 384 |   throw "In record '" + R->getName() + "' for TSFlag emission."; | 
 | 385 | } | 
| Brian Gaeke | d0fde30 | 2003-11-11 22:41:34 +0000 | [diff] [blame] | 386 |  |