SubtargetEmitter.cpp revision ab8be96fd30ca9396e6b84fdddf1ac6208984cad
1//===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This tablegen backend emits subtarget enumerations. 11// 12//===----------------------------------------------------------------------===// 13 14#include "SubtargetEmitter.h" 15#include "CodeGenTarget.h" 16#include "Record.h" 17#include "llvm/ADT/StringExtras.h" 18#include "llvm/Support/Debug.h" 19#include <algorithm> 20using namespace llvm; 21 22// 23// Enumeration - Emit the specified class as an enumeration. 24// 25void SubtargetEmitter::Enumeration(raw_ostream &OS, 26 const char *ClassName, 27 bool isBits) { 28 // Get all records of class and sort 29 std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName); 30 std::sort(DefList.begin(), DefList.end(), LessRecord()); 31 32 // Open enumeration 33 OS << "enum {\n"; 34 35 // For each record 36 unsigned N = DefList.size(); 37 if (N > 64) { 38 errs() << "Too many (> 64) subtarget features!\n"; 39 exit(1); 40 } 41 42 for (unsigned i = 0; i < N;) { 43 // Next record 44 Record *Def = DefList[i]; 45 46 // Get and emit name 47 OS << " " << Def->getName(); 48 49 // If bit flags then emit expression (1 << i) 50 if (isBits) OS << " = " << " 1ULL << " << i; 51 52 // Depending on 'if more in the list' emit comma 53 if (++i < N) OS << ","; 54 55 OS << "\n"; 56 } 57 58 // Close enumeration 59 OS << "};\n"; 60} 61 62// 63// FeatureKeyValues - Emit data of all the subtarget features. Used by the 64// command line. 65// 66void SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { 67 // Gather and sort all the features 68 std::vector<Record*> FeatureList = 69 Records.getAllDerivedDefinitions("SubtargetFeature"); 70 std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName()); 71 72 // Begin feature table 73 OS << "// Sorted (by key) array of values for CPU features.\n" 74 << "static const llvm::SubtargetFeatureKV FeatureKV[] = {\n"; 75 76 // For each feature 77 for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) { 78 // Next feature 79 Record *Feature = FeatureList[i]; 80 81 const std::string &Name = Feature->getName(); 82 const std::string &CommandLineName = Feature->getValueAsString("Name"); 83 const std::string &Desc = Feature->getValueAsString("Desc"); 84 85 if (CommandLineName.empty()) continue; 86 87 // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in } 88 OS << " { " 89 << "\"" << CommandLineName << "\", " 90 << "\"" << Desc << "\", " 91 << Name << ", "; 92 93 const std::vector<Record*> &ImpliesList = 94 Feature->getValueAsListOfDefs("Implies"); 95 96 if (ImpliesList.empty()) { 97 OS << "0ULL"; 98 } else { 99 for (unsigned j = 0, M = ImpliesList.size(); j < M;) { 100 OS << ImpliesList[j]->getName(); 101 if (++j < M) OS << " | "; 102 } 103 } 104 105 OS << " }"; 106 107 // Depending on 'if more in the list' emit comma 108 if ((i + 1) < N) OS << ","; 109 110 OS << "\n"; 111 } 112 113 // End feature table 114 OS << "};\n"; 115 116 // Emit size of table 117 OS<<"\nenum {\n"; 118 OS<<" FeatureKVSize = sizeof(FeatureKV)/sizeof(llvm::SubtargetFeatureKV)\n"; 119 OS<<"};\n"; 120} 121 122// 123// CPUKeyValues - Emit data of all the subtarget processors. Used by command 124// line. 125// 126void SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { 127 // Gather and sort processor information 128 std::vector<Record*> ProcessorList = 129 Records.getAllDerivedDefinitions("Processor"); 130 std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName()); 131 132 // Begin processor table 133 OS << "// Sorted (by key) array of values for CPU subtype.\n" 134 << "static const llvm::SubtargetFeatureKV SubTypeKV[] = {\n"; 135 136 // For each processor 137 for (unsigned i = 0, N = ProcessorList.size(); i < N;) { 138 // Next processor 139 Record *Processor = ProcessorList[i]; 140 141 const std::string &Name = Processor->getValueAsString("Name"); 142 const std::vector<Record*> &FeatureList = 143 Processor->getValueAsListOfDefs("Features"); 144 145 // Emit as { "cpu", "description", f1 | f2 | ... fn }, 146 OS << " { " 147 << "\"" << Name << "\", " 148 << "\"Select the " << Name << " processor\", "; 149 150 if (FeatureList.empty()) { 151 OS << "0ULL"; 152 } else { 153 for (unsigned j = 0, M = FeatureList.size(); j < M;) { 154 OS << FeatureList[j]->getName(); 155 if (++j < M) OS << " | "; 156 } 157 } 158 159 // The "0" is for the "implies" section of this data structure. 160 OS << ", 0ULL }"; 161 162 // Depending on 'if more in the list' emit comma 163 if (++i < N) OS << ","; 164 165 OS << "\n"; 166 } 167 168 // End processor table 169 OS << "};\n"; 170 171 // Emit size of table 172 OS<<"\nenum {\n"; 173 OS<<" SubTypeKVSize = sizeof(SubTypeKV)/sizeof(llvm::SubtargetFeatureKV)\n"; 174 OS<<"};\n"; 175} 176 177// 178// CollectAllItinClasses - Gathers and enumerates all the itinerary classes. 179// Returns itinerary class count. 180// 181unsigned SubtargetEmitter:: 182CollectAllItinClasses(raw_ostream &OS, 183 std::map<std::string, unsigned> &ItinClassesMap, 184 std::vector<Record*> &ItinClassList) { 185 // For each itinerary class 186 unsigned N = ItinClassList.size(); 187 for (unsigned i = 0; i < N; i++) { 188 // Next itinerary class 189 const Record *ItinClass = ItinClassList[i]; 190 // Get name of itinerary class 191 // Assign itinerary class a unique number 192 ItinClassesMap[ItinClass->getName()] = i; 193 } 194 195 // Emit size of table 196 OS<<"\nenum {\n"; 197 OS<<" ItinClassesSize = " << N << "\n"; 198 OS<<"};\n"; 199 200 // Return itinerary class count 201 return N; 202} 203 204// 205// FormItineraryStageString - Compose a string containing the stage 206// data initialization for the specified itinerary. N is the number 207// of stages. 208// 209void SubtargetEmitter::FormItineraryStageString(const std::string &Name, 210 Record *ItinData, 211 std::string &ItinString, 212 unsigned &NStages) { 213 // Get states list 214 const std::vector<Record*> &StageList = 215 ItinData->getValueAsListOfDefs("Stages"); 216 217 // For each stage 218 unsigned N = NStages = StageList.size(); 219 for (unsigned i = 0; i < N;) { 220 // Next stage 221 const Record *Stage = StageList[i]; 222 223 // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind } 224 int Cycles = Stage->getValueAsInt("Cycles"); 225 ItinString += " { " + itostr(Cycles) + ", "; 226 227 // Get unit list 228 const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units"); 229 230 // For each unit 231 for (unsigned j = 0, M = UnitList.size(); j < M;) { 232 // Add name and bitwise or 233 ItinString += Name + "FU::" + UnitList[j]->getName(); 234 if (++j < M) ItinString += " | "; 235 } 236 237 int TimeInc = Stage->getValueAsInt("TimeInc"); 238 ItinString += ", " + itostr(TimeInc); 239 240 int Kind = Stage->getValueAsInt("Kind"); 241 ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind); 242 243 // Close off stage 244 ItinString += " }"; 245 if (++i < N) ItinString += ", "; 246 } 247} 248 249// 250// FormItineraryOperandCycleString - Compose a string containing the 251// operand cycle initialization for the specified itinerary. N is the 252// number of operands that has cycles specified. 253// 254void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData, 255 std::string &ItinString, unsigned &NOperandCycles) { 256 // Get operand cycle list 257 const std::vector<int64_t> &OperandCycleList = 258 ItinData->getValueAsListOfInts("OperandCycles"); 259 260 // For each operand cycle 261 unsigned N = NOperandCycles = OperandCycleList.size(); 262 for (unsigned i = 0; i < N;) { 263 // Next operand cycle 264 const int OCycle = OperandCycleList[i]; 265 266 ItinString += " " + itostr(OCycle); 267 if (++i < N) ItinString += ", "; 268 } 269} 270 271void SubtargetEmitter::FormItineraryBypassString(const std::string &Name, 272 Record *ItinData, 273 std::string &ItinString, 274 unsigned NOperandCycles) { 275 const std::vector<Record*> &BypassList = 276 ItinData->getValueAsListOfDefs("Bypasses"); 277 unsigned N = BypassList.size(); 278 unsigned i = 0; 279 for (; i < N;) { 280 ItinString += Name + "Bypass::" + BypassList[i]->getName(); 281 if (++i < NOperandCycles) ItinString += ", "; 282 } 283 for (; i < NOperandCycles;) { 284 ItinString += " 0"; 285 if (++i < NOperandCycles) ItinString += ", "; 286 } 287} 288 289// 290// EmitStageAndOperandCycleData - Generate unique itinerary stages and 291// operand cycle tables. Record itineraries for processors. 292// 293void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, 294 unsigned NItinClasses, 295 std::map<std::string, unsigned> &ItinClassesMap, 296 std::vector<Record*> &ItinClassList, 297 std::vector<std::vector<InstrItinerary> > &ProcList) { 298 // Gather processor iteraries 299 std::vector<Record*> ProcItinList = 300 Records.getAllDerivedDefinitions("ProcessorItineraries"); 301 302 // If just no itinerary then don't bother 303 if (ProcItinList.size() < 2) return; 304 305 // Emit functional units for all the itineraries. 306 for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) { 307 // Next record 308 Record *Proc = ProcItinList[i]; 309 310 std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU"); 311 if (FUs.empty()) 312 continue; 313 314 const std::string &Name = Proc->getName(); 315 OS << "\n// Functional units for itineraries \"" << Name << "\"\n" 316 << "namespace " << Name << "FU {\n"; 317 318 for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j) 319 OS << " const unsigned " << FUs[j]->getName() 320 << " = 1 << " << j << ";\n"; 321 322 OS << "}\n"; 323 324 std::vector<Record*> BPs = Proc->getValueAsListOfDefs("BP"); 325 if (BPs.size()) { 326 OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name 327 << "\"\n" << "namespace " << Name << "Bypass {\n"; 328 329 OS << " const unsigned NoBypass = 0;\n"; 330 for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j) 331 OS << " const unsigned " << BPs[j]->getName() 332 << " = 1 << " << j << ";\n"; 333 334 OS << "}\n"; 335 } 336 } 337 338 // Begin stages table 339 std::string StageTable = "\nstatic const llvm::InstrStage Stages[] = {\n"; 340 StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n"; 341 342 // Begin operand cycle table 343 std::string OperandCycleTable = "static const unsigned OperandCycles[] = {\n"; 344 OperandCycleTable += " 0, // No itinerary\n"; 345 346 // Begin pipeline bypass table 347 std::string BypassTable = "static const unsigned ForwardingPathes[] = {\n"; 348 BypassTable += " 0, // No itinerary\n"; 349 350 unsigned StageCount = 1, OperandCycleCount = 1; 351 std::map<std::string, unsigned> ItinStageMap, ItinOperandMap; 352 for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) { 353 // Next record 354 Record *Proc = ProcItinList[i]; 355 356 // Get processor itinerary name 357 const std::string &Name = Proc->getName(); 358 359 // Skip default 360 if (Name == "NoItineraries") continue; 361 362 // Create and expand processor itinerary to cover all itinerary classes 363 std::vector<InstrItinerary> ItinList; 364 ItinList.resize(NItinClasses); 365 366 // Get itinerary data list 367 std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID"); 368 369 // For each itinerary data 370 for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) { 371 // Next itinerary data 372 Record *ItinData = ItinDataList[j]; 373 374 // Get string and stage count 375 std::string ItinStageString; 376 unsigned NStages; 377 FormItineraryStageString(Name, ItinData, ItinStageString, NStages); 378 379 // Get string and operand cycle count 380 std::string ItinOperandCycleString; 381 unsigned NOperandCycles; 382 FormItineraryOperandCycleString(ItinData, ItinOperandCycleString, 383 NOperandCycles); 384 385 std::string ItinBypassString; 386 FormItineraryBypassString(Name, ItinData, ItinBypassString, 387 NOperandCycles); 388 389 // Check to see if stage already exists and create if it doesn't 390 unsigned FindStage = 0; 391 if (NStages > 0) { 392 FindStage = ItinStageMap[ItinStageString]; 393 if (FindStage == 0) { 394 // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices 395 StageTable += ItinStageString + ", // " + itostr(StageCount); 396 if (NStages > 1) 397 StageTable += "-" + itostr(StageCount + NStages - 1); 398 StageTable += "\n"; 399 // Record Itin class number. 400 ItinStageMap[ItinStageString] = FindStage = StageCount; 401 StageCount += NStages; 402 } 403 } 404 405 // Check to see if operand cycle already exists and create if it doesn't 406 unsigned FindOperandCycle = 0; 407 if (NOperandCycles > 0) { 408 std::string ItinOperandString = ItinOperandCycleString+ItinBypassString; 409 FindOperandCycle = ItinOperandMap[ItinOperandString]; 410 if (FindOperandCycle == 0) { 411 // Emit as cycle, // index 412 OperandCycleTable += ItinOperandCycleString + ", // "; 413 std::string OperandIdxComment = itostr(OperandCycleCount); 414 if (NOperandCycles > 1) 415 OperandIdxComment += "-" 416 + itostr(OperandCycleCount + NOperandCycles - 1); 417 OperandCycleTable += OperandIdxComment + "\n"; 418 // Record Itin class number. 419 ItinOperandMap[ItinOperandCycleString] = 420 FindOperandCycle = OperandCycleCount; 421 // Emit as bypass, // index 422 BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n"; 423 OperandCycleCount += NOperandCycles; 424 } 425 } 426 427 // Locate where to inject into processor itinerary table 428 const std::string &Name = ItinData->getValueAsDef("TheClass")->getName(); 429 unsigned Find = ItinClassesMap[Name]; 430 431 // Set up itinerary as location and location + stage count 432 unsigned NumUOps = ItinClassList[Find]->getValueAsInt("NumMicroOps"); 433 InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages, 434 FindOperandCycle, 435 FindOperandCycle + NOperandCycles}; 436 437 // Inject - empty slots will be 0, 0 438 ItinList[Find] = Intinerary; 439 } 440 441 // Add process itinerary to list 442 ProcList.push_back(ItinList); 443 } 444 445 // Closing stage 446 StageTable += " { 0, 0, 0, llvm::InstrStage::Required } // End itinerary\n"; 447 StageTable += "};\n"; 448 449 // Closing operand cycles 450 OperandCycleTable += " 0 // End itinerary\n"; 451 OperandCycleTable += "};\n"; 452 453 BypassTable += " 0 // End itinerary\n"; 454 BypassTable += "};\n"; 455 456 // Emit tables. 457 OS << StageTable; 458 OS << OperandCycleTable; 459 OS << BypassTable; 460 461 // Emit size of tables 462 OS<<"\nenum {\n"; 463 OS<<" StagesSize = sizeof(Stages)/sizeof(llvm::InstrStage),\n"; 464 OS<<" OperandCyclesSize = sizeof(OperandCycles)/sizeof(unsigned)\n"; 465 OS<<"};\n"; 466} 467 468// 469// EmitProcessorData - Generate data for processor itineraries. 470// 471void SubtargetEmitter:: 472EmitProcessorData(raw_ostream &OS, 473 std::vector<Record*> &ItinClassList, 474 std::vector<std::vector<InstrItinerary> > &ProcList) { 475 // Get an iterator for processor itinerary stages 476 std::vector<std::vector<InstrItinerary> >::iterator 477 ProcListIter = ProcList.begin(); 478 479 // For each processor itinerary 480 std::vector<Record*> Itins = 481 Records.getAllDerivedDefinitions("ProcessorItineraries"); 482 for (unsigned i = 0, N = Itins.size(); i < N; i++) { 483 // Next record 484 Record *Itin = Itins[i]; 485 486 // Get processor itinerary name 487 const std::string &Name = Itin->getName(); 488 489 // Skip default 490 if (Name == "NoItineraries") continue; 491 492 // Begin processor itinerary table 493 OS << "\n"; 494 OS << "static const llvm::InstrItinerary " << Name << "[] = {\n"; 495 496 // For each itinerary class 497 std::vector<InstrItinerary> &ItinList = *ProcListIter++; 498 assert(ItinList.size() == ItinClassList.size() && "bad itinerary"); 499 for (unsigned j = 0, M = ItinList.size(); j < M; ++j) { 500 InstrItinerary &Intinerary = ItinList[j]; 501 502 // Emit in the form of 503 // { firstStage, lastStage, firstCycle, lastCycle } // index 504 if (Intinerary.FirstStage == 0) { 505 OS << " { 1, 0, 0, 0, 0 }"; 506 } else { 507 OS << " { " << 508 Intinerary.NumMicroOps << ", " << 509 Intinerary.FirstStage << ", " << 510 Intinerary.LastStage << ", " << 511 Intinerary.FirstOperandCycle << ", " << 512 Intinerary.LastOperandCycle << " }"; 513 } 514 515 OS << ", // " << j << " " << ItinClassList[j]->getName() << "\n"; 516 } 517 518 // End processor itinerary table 519 OS << " { 1, ~0U, ~0U, ~0U, ~0U } // end marker\n"; 520 OS << "};\n"; 521 } 522} 523 524// 525// EmitProcessorLookup - generate cpu name to itinerary lookup table. 526// 527void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) { 528 // Gather and sort processor information 529 std::vector<Record*> ProcessorList = 530 Records.getAllDerivedDefinitions("Processor"); 531 std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName()); 532 533 // Begin processor table 534 OS << "\n"; 535 OS << "// Sorted (by key) array of itineraries for CPU subtype.\n" 536 << "static const llvm::SubtargetInfoKV ProcItinKV[] = {\n"; 537 538 // For each processor 539 for (unsigned i = 0, N = ProcessorList.size(); i < N;) { 540 // Next processor 541 Record *Processor = ProcessorList[i]; 542 543 const std::string &Name = Processor->getValueAsString("Name"); 544 const std::string &ProcItin = 545 Processor->getValueAsDef("ProcItin")->getName(); 546 547 // Emit as { "cpu", procinit }, 548 OS << " { " 549 << "\"" << Name << "\", " 550 << "(void *)&" << ProcItin; 551 552 OS << " }"; 553 554 // Depending on ''if more in the list'' emit comma 555 if (++i < N) OS << ","; 556 557 OS << "\n"; 558 } 559 560 // End processor table 561 OS << "};\n"; 562 563 // Emit size of table 564 OS<<"\nenum {\n"; 565 OS<<" ProcItinKVSize = sizeof(ProcItinKV)/" 566 "sizeof(llvm::SubtargetInfoKV)\n"; 567 OS<<"};\n"; 568} 569 570// 571// EmitData - Emits all stages and itineries, folding common patterns. 572// 573void SubtargetEmitter::EmitData(raw_ostream &OS) { 574 std::map<std::string, unsigned> ItinClassesMap; 575 // Gather and sort all itinerary classes 576 std::vector<Record*> ItinClassList = 577 Records.getAllDerivedDefinitions("InstrItinClass"); 578 std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord()); 579 580 // Enumerate all the itinerary classes 581 unsigned NItinClasses = CollectAllItinClasses(OS, ItinClassesMap, 582 ItinClassList); 583 // Make sure the rest is worth the effort 584 HasItineraries = NItinClasses != 1; // Ignore NoItinerary. 585 586 if (HasItineraries) { 587 std::vector<std::vector<InstrItinerary> > ProcList; 588 // Emit the stage data 589 EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap, 590 ItinClassList, ProcList); 591 // Emit the processor itinerary data 592 EmitProcessorData(OS, ItinClassList, ProcList); 593 // Emit the processor lookup data 594 EmitProcessorLookup(OS); 595 } 596} 597 598// 599// ParseFeaturesFunction - Produces a subtarget specific function for parsing 600// the subtarget features string. 601// 602void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) { 603 std::vector<Record*> Features = 604 Records.getAllDerivedDefinitions("SubtargetFeature"); 605 std::sort(Features.begin(), Features.end(), LessRecord()); 606 607 OS << "// ParseSubtargetFeatures - Parses features string setting specified\n" 608 << "// subtarget options.\n" 609 << "std::string llvm::"; 610 OS << Target; 611 OS << "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n" 612 << " const std::string &CPU) {\n" 613 << " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n" 614 << " DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n" 615 << " SubtargetFeatures Features(FS);\n" 616 << " Features.setCPUIfNone(CPU);\n" 617 << " uint64_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n" 618 << " FeatureKV, FeatureKVSize);\n"; 619 620 for (unsigned i = 0; i < Features.size(); i++) { 621 // Next record 622 Record *R = Features[i]; 623 const std::string &Instance = R->getName(); 624 const std::string &Value = R->getValueAsString("Value"); 625 const std::string &Attribute = R->getValueAsString("Attribute"); 626 627 if (Value=="true" || Value=="false") 628 OS << " if ((Bits & " << Instance << ") != 0) " 629 << Attribute << " = " << Value << ";\n"; 630 else 631 OS << " if ((Bits & " << Instance << ") != 0 && " << Attribute << 632 " < " << Value << ") " << Attribute << " = " << Value << ";\n"; 633 } 634 635 if (HasItineraries) { 636 OS << "\n" 637 << " InstrItinerary *Itinerary = (InstrItinerary *)" 638 << "Features.getInfo(ProcItinKV, ProcItinKVSize);\n" 639 << " InstrItins = InstrItineraryData(Stages, OperandCycles, " 640 << "ForwardingPathes, Itinerary);\n"; 641 } 642 643 OS << " return Features.getCPU();\n" 644 << "}\n"; 645} 646 647// 648// SubtargetEmitter::run - Main subtarget enumeration emitter. 649// 650void SubtargetEmitter::run(raw_ostream &OS) { 651 Target = CodeGenTarget(Records).getName(); 652 653 EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS); 654 655 OS << "#include \"llvm/Support/Debug.h\"\n"; 656 OS << "#include \"llvm/Support/raw_ostream.h\"\n"; 657 OS << "#include \"llvm/MC/SubtargetFeature.h\"\n"; 658 OS << "#include \"llvm/MC/MCInstrItineraries.h\"\n\n"; 659 660// Enumeration(OS, "FuncUnit", true); 661// OS<<"\n"; 662// Enumeration(OS, "InstrItinClass", false); 663// OS<<"\n"; 664 Enumeration(OS, "SubtargetFeature", true); 665 OS<<"\n"; 666 FeatureKeyValues(OS); 667 OS<<"\n"; 668 CPUKeyValues(OS); 669 OS<<"\n"; 670 EmitData(OS); 671 OS<<"\n"; 672 ParseFeaturesFunction(OS); 673} 674