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 "llvm/TableGen/Record.h" 17 #include "llvm/ADT/StringExtras.h" 18 #include "llvm/Support/Debug.h" 19 #include <algorithm> 20 using namespace llvm; 21 22 // 23 // Enumeration - Emit the specified class as an enumeration. 24 // 25 void 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 unsigned N = DefList.size(); 33 if (N == 0) 34 return; 35 if (N > 64) { 36 errs() << "Too many (> 64) subtarget features!\n"; 37 exit(1); 38 } 39 40 OS << "namespace " << Target << " {\n"; 41 42 // Open enumeration 43 OS << "enum {\n"; 44 45 // For each record 46 for (unsigned i = 0; i < N;) { 47 // Next record 48 Record *Def = DefList[i]; 49 50 // Get and emit name 51 OS << " " << Def->getName(); 52 53 // If bit flags then emit expression (1 << i) 54 if (isBits) OS << " = " << " 1ULL << " << i; 55 56 // Depending on 'if more in the list' emit comma 57 if (++i < N) OS << ","; 58 59 OS << "\n"; 60 } 61 62 // Close enumeration 63 OS << "};\n"; 64 65 OS << "}\n"; 66 } 67 68 // 69 // FeatureKeyValues - Emit data of all the subtarget features. Used by the 70 // command line. 71 // 72 unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { 73 // Gather and sort all the features 74 std::vector<Record*> FeatureList = 75 Records.getAllDerivedDefinitions("SubtargetFeature"); 76 77 if (FeatureList.empty()) 78 return 0; 79 80 std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName()); 81 82 // Begin feature table 83 OS << "// Sorted (by key) array of values for CPU features.\n" 84 << "extern const llvm::SubtargetFeatureKV " << Target 85 << "FeatureKV[] = {\n"; 86 87 // For each feature 88 unsigned NumFeatures = 0; 89 for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) { 90 // Next feature 91 Record *Feature = FeatureList[i]; 92 93 const std::string &Name = Feature->getName(); 94 const std::string &CommandLineName = Feature->getValueAsString("Name"); 95 const std::string &Desc = Feature->getValueAsString("Desc"); 96 97 if (CommandLineName.empty()) continue; 98 99 // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in } 100 OS << " { " 101 << "\"" << CommandLineName << "\", " 102 << "\"" << Desc << "\", " 103 << Target << "::" << Name << ", "; 104 105 const std::vector<Record*> &ImpliesList = 106 Feature->getValueAsListOfDefs("Implies"); 107 108 if (ImpliesList.empty()) { 109 OS << "0ULL"; 110 } else { 111 for (unsigned j = 0, M = ImpliesList.size(); j < M;) { 112 OS << Target << "::" << ImpliesList[j]->getName(); 113 if (++j < M) OS << " | "; 114 } 115 } 116 117 OS << " }"; 118 ++NumFeatures; 119 120 // Depending on 'if more in the list' emit comma 121 if ((i + 1) < N) OS << ","; 122 123 OS << "\n"; 124 } 125 126 // End feature table 127 OS << "};\n"; 128 129 return NumFeatures; 130 } 131 132 // 133 // CPUKeyValues - Emit data of all the subtarget processors. Used by command 134 // line. 135 // 136 unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { 137 // Gather and sort processor information 138 std::vector<Record*> ProcessorList = 139 Records.getAllDerivedDefinitions("Processor"); 140 std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName()); 141 142 // Begin processor table 143 OS << "// Sorted (by key) array of values for CPU subtype.\n" 144 << "extern const llvm::SubtargetFeatureKV " << Target 145 << "SubTypeKV[] = {\n"; 146 147 // For each processor 148 for (unsigned i = 0, N = ProcessorList.size(); i < N;) { 149 // Next processor 150 Record *Processor = ProcessorList[i]; 151 152 const std::string &Name = Processor->getValueAsString("Name"); 153 const std::vector<Record*> &FeatureList = 154 Processor->getValueAsListOfDefs("Features"); 155 156 // Emit as { "cpu", "description", f1 | f2 | ... fn }, 157 OS << " { " 158 << "\"" << Name << "\", " 159 << "\"Select the " << Name << " processor\", "; 160 161 if (FeatureList.empty()) { 162 OS << "0ULL"; 163 } else { 164 for (unsigned j = 0, M = FeatureList.size(); j < M;) { 165 OS << Target << "::" << FeatureList[j]->getName(); 166 if (++j < M) OS << " | "; 167 } 168 } 169 170 // The "0" is for the "implies" section of this data structure. 171 OS << ", 0ULL }"; 172 173 // Depending on 'if more in the list' emit comma 174 if (++i < N) OS << ","; 175 176 OS << "\n"; 177 } 178 179 // End processor table 180 OS << "};\n"; 181 182 return ProcessorList.size(); 183 } 184 185 // 186 // CollectAllItinClasses - Gathers and enumerates all the itinerary classes. 187 // Returns itinerary class count. 188 // 189 unsigned SubtargetEmitter:: 190 CollectAllItinClasses(raw_ostream &OS, 191 std::map<std::string, unsigned> &ItinClassesMap, 192 std::vector<Record*> &ItinClassList) { 193 // For each itinerary class 194 unsigned N = ItinClassList.size(); 195 for (unsigned i = 0; i < N; i++) { 196 // Next itinerary class 197 const Record *ItinClass = ItinClassList[i]; 198 // Get name of itinerary class 199 // Assign itinerary class a unique number 200 ItinClassesMap[ItinClass->getName()] = i; 201 } 202 203 // Return itinerary class count 204 return N; 205 } 206 207 // 208 // FormItineraryStageString - Compose a string containing the stage 209 // data initialization for the specified itinerary. N is the number 210 // of stages. 211 // 212 void SubtargetEmitter::FormItineraryStageString(const std::string &Name, 213 Record *ItinData, 214 std::string &ItinString, 215 unsigned &NStages) { 216 // Get states list 217 const std::vector<Record*> &StageList = 218 ItinData->getValueAsListOfDefs("Stages"); 219 220 // For each stage 221 unsigned N = NStages = StageList.size(); 222 for (unsigned i = 0; i < N;) { 223 // Next stage 224 const Record *Stage = StageList[i]; 225 226 // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind } 227 int Cycles = Stage->getValueAsInt("Cycles"); 228 ItinString += " { " + itostr(Cycles) + ", "; 229 230 // Get unit list 231 const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units"); 232 233 // For each unit 234 for (unsigned j = 0, M = UnitList.size(); j < M;) { 235 // Add name and bitwise or 236 ItinString += Name + "FU::" + UnitList[j]->getName(); 237 if (++j < M) ItinString += " | "; 238 } 239 240 int TimeInc = Stage->getValueAsInt("TimeInc"); 241 ItinString += ", " + itostr(TimeInc); 242 243 int Kind = Stage->getValueAsInt("Kind"); 244 ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind); 245 246 // Close off stage 247 ItinString += " }"; 248 if (++i < N) ItinString += ", "; 249 } 250 } 251 252 // 253 // FormItineraryOperandCycleString - Compose a string containing the 254 // operand cycle initialization for the specified itinerary. N is the 255 // number of operands that has cycles specified. 256 // 257 void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData, 258 std::string &ItinString, unsigned &NOperandCycles) { 259 // Get operand cycle list 260 const std::vector<int64_t> &OperandCycleList = 261 ItinData->getValueAsListOfInts("OperandCycles"); 262 263 // For each operand cycle 264 unsigned N = NOperandCycles = OperandCycleList.size(); 265 for (unsigned i = 0; i < N;) { 266 // Next operand cycle 267 const int OCycle = OperandCycleList[i]; 268 269 ItinString += " " + itostr(OCycle); 270 if (++i < N) ItinString += ", "; 271 } 272 } 273 274 void SubtargetEmitter::FormItineraryBypassString(const std::string &Name, 275 Record *ItinData, 276 std::string &ItinString, 277 unsigned NOperandCycles) { 278 const std::vector<Record*> &BypassList = 279 ItinData->getValueAsListOfDefs("Bypasses"); 280 unsigned N = BypassList.size(); 281 unsigned i = 0; 282 for (; i < N;) { 283 ItinString += Name + "Bypass::" + BypassList[i]->getName(); 284 if (++i < NOperandCycles) ItinString += ", "; 285 } 286 for (; i < NOperandCycles;) { 287 ItinString += " 0"; 288 if (++i < NOperandCycles) ItinString += ", "; 289 } 290 } 291 292 // 293 // EmitStageAndOperandCycleData - Generate unique itinerary stages and 294 // operand cycle tables. Record itineraries for processors. 295 // 296 void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, 297 unsigned NItinClasses, 298 std::map<std::string, unsigned> &ItinClassesMap, 299 std::vector<Record*> &ItinClassList, 300 std::vector<std::vector<InstrItinerary> > &ProcList) { 301 // Gather processor iteraries 302 std::vector<Record*> ProcItinList = 303 Records.getAllDerivedDefinitions("ProcessorItineraries"); 304 305 // If just no itinerary then don't bother 306 if (ProcItinList.size() < 2) return; 307 308 // Emit functional units for all the itineraries. 309 for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) { 310 // Next record 311 Record *Proc = ProcItinList[i]; 312 313 std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU"); 314 if (FUs.empty()) 315 continue; 316 317 const std::string &Name = Proc->getName(); 318 OS << "\n// Functional units for itineraries \"" << Name << "\"\n" 319 << "namespace " << Name << "FU {\n"; 320 321 for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j) 322 OS << " const unsigned " << FUs[j]->getName() 323 << " = 1 << " << j << ";\n"; 324 325 OS << "}\n"; 326 327 std::vector<Record*> BPs = Proc->getValueAsListOfDefs("BP"); 328 if (BPs.size()) { 329 OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name 330 << "\"\n" << "namespace " << Name << "Bypass {\n"; 331 332 OS << " const unsigned NoBypass = 0;\n"; 333 for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j) 334 OS << " const unsigned " << BPs[j]->getName() 335 << " = 1 << " << j << ";\n"; 336 337 OS << "}\n"; 338 } 339 } 340 341 // Begin stages table 342 std::string StageTable = "\nextern const llvm::InstrStage " + Target + 343 "Stages[] = {\n"; 344 StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n"; 345 346 // Begin operand cycle table 347 std::string OperandCycleTable = "extern const unsigned " + Target + 348 "OperandCycles[] = {\n"; 349 OperandCycleTable += " 0, // No itinerary\n"; 350 351 // Begin pipeline bypass table 352 std::string BypassTable = "extern const unsigned " + Target + 353 "ForwardingPathes[] = {\n"; 354 BypassTable += " 0, // No itinerary\n"; 355 356 unsigned StageCount = 1, OperandCycleCount = 1; 357 std::map<std::string, unsigned> ItinStageMap, ItinOperandMap; 358 for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) { 359 // Next record 360 Record *Proc = ProcItinList[i]; 361 362 // Get processor itinerary name 363 const std::string &Name = Proc->getName(); 364 365 // Skip default 366 if (Name == "NoItineraries") continue; 367 368 // Create and expand processor itinerary to cover all itinerary classes 369 std::vector<InstrItinerary> ItinList; 370 ItinList.resize(NItinClasses); 371 372 // Get itinerary data list 373 std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID"); 374 375 // For each itinerary data 376 for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) { 377 // Next itinerary data 378 Record *ItinData = ItinDataList[j]; 379 380 // Get string and stage count 381 std::string ItinStageString; 382 unsigned NStages; 383 FormItineraryStageString(Name, ItinData, ItinStageString, NStages); 384 385 // Get string and operand cycle count 386 std::string ItinOperandCycleString; 387 unsigned NOperandCycles; 388 FormItineraryOperandCycleString(ItinData, ItinOperandCycleString, 389 NOperandCycles); 390 391 std::string ItinBypassString; 392 FormItineraryBypassString(Name, ItinData, ItinBypassString, 393 NOperandCycles); 394 395 // Check to see if stage already exists and create if it doesn't 396 unsigned FindStage = 0; 397 if (NStages > 0) { 398 FindStage = ItinStageMap[ItinStageString]; 399 if (FindStage == 0) { 400 // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices 401 StageTable += ItinStageString + ", // " + itostr(StageCount); 402 if (NStages > 1) 403 StageTable += "-" + itostr(StageCount + NStages - 1); 404 StageTable += "\n"; 405 // Record Itin class number. 406 ItinStageMap[ItinStageString] = FindStage = StageCount; 407 StageCount += NStages; 408 } 409 } 410 411 // Check to see if operand cycle already exists and create if it doesn't 412 unsigned FindOperandCycle = 0; 413 if (NOperandCycles > 0) { 414 std::string ItinOperandString = ItinOperandCycleString+ItinBypassString; 415 FindOperandCycle = ItinOperandMap[ItinOperandString]; 416 if (FindOperandCycle == 0) { 417 // Emit as cycle, // index 418 OperandCycleTable += ItinOperandCycleString + ", // "; 419 std::string OperandIdxComment = itostr(OperandCycleCount); 420 if (NOperandCycles > 1) 421 OperandIdxComment += "-" 422 + itostr(OperandCycleCount + NOperandCycles - 1); 423 OperandCycleTable += OperandIdxComment + "\n"; 424 // Record Itin class number. 425 ItinOperandMap[ItinOperandCycleString] = 426 FindOperandCycle = OperandCycleCount; 427 // Emit as bypass, // index 428 BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n"; 429 OperandCycleCount += NOperandCycles; 430 } 431 } 432 433 // Locate where to inject into processor itinerary table 434 const std::string &Name = ItinData->getValueAsDef("TheClass")->getName(); 435 unsigned Find = ItinClassesMap[Name]; 436 437 // Set up itinerary as location and location + stage count 438 unsigned NumUOps = ItinClassList[Find]->getValueAsInt("NumMicroOps"); 439 InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages, 440 FindOperandCycle, 441 FindOperandCycle + NOperandCycles}; 442 443 // Inject - empty slots will be 0, 0 444 ItinList[Find] = Intinerary; 445 } 446 447 // Add process itinerary to list 448 ProcList.push_back(ItinList); 449 } 450 451 // Closing stage 452 StageTable += " { 0, 0, 0, llvm::InstrStage::Required } // End itinerary\n"; 453 StageTable += "};\n"; 454 455 // Closing operand cycles 456 OperandCycleTable += " 0 // End itinerary\n"; 457 OperandCycleTable += "};\n"; 458 459 BypassTable += " 0 // End itinerary\n"; 460 BypassTable += "};\n"; 461 462 // Emit tables. 463 OS << StageTable; 464 OS << OperandCycleTable; 465 OS << BypassTable; 466 } 467 468 // 469 // EmitProcessorData - Generate data for processor itineraries. 470 // 471 void SubtargetEmitter:: 472 EmitProcessorData(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 // 527 void 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 << "extern const llvm::SubtargetInfoKV " 537 << Target << "ProcItinKV[] = {\n"; 538 539 // For each processor 540 for (unsigned i = 0, N = ProcessorList.size(); i < N;) { 541 // Next processor 542 Record *Processor = ProcessorList[i]; 543 544 const std::string &Name = Processor->getValueAsString("Name"); 545 const std::string &ProcItin = 546 Processor->getValueAsDef("ProcItin")->getName(); 547 548 // Emit as { "cpu", procinit }, 549 OS << " { " 550 << "\"" << Name << "\", " 551 << "(void *)&" << ProcItin; 552 553 OS << " }"; 554 555 // Depending on ''if more in the list'' emit comma 556 if (++i < N) OS << ","; 557 558 OS << "\n"; 559 } 560 561 // End processor table 562 OS << "};\n"; 563 } 564 565 // 566 // EmitData - Emits all stages and itineries, folding common patterns. 567 // 568 void SubtargetEmitter::EmitData(raw_ostream &OS) { 569 std::map<std::string, unsigned> ItinClassesMap; 570 // Gather and sort all itinerary classes 571 std::vector<Record*> ItinClassList = 572 Records.getAllDerivedDefinitions("InstrItinClass"); 573 std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord()); 574 575 // Enumerate all the itinerary classes 576 unsigned NItinClasses = CollectAllItinClasses(OS, ItinClassesMap, 577 ItinClassList); 578 // Make sure the rest is worth the effort 579 HasItineraries = NItinClasses != 1; // Ignore NoItinerary. 580 581 if (HasItineraries) { 582 std::vector<std::vector<InstrItinerary> > ProcList; 583 // Emit the stage data 584 EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap, 585 ItinClassList, ProcList); 586 // Emit the processor itinerary data 587 EmitProcessorData(OS, ItinClassList, ProcList); 588 // Emit the processor lookup data 589 EmitProcessorLookup(OS); 590 } 591 } 592 593 // 594 // ParseFeaturesFunction - Produces a subtarget specific function for parsing 595 // the subtarget features string. 596 // 597 void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS, 598 unsigned NumFeatures, 599 unsigned NumProcs) { 600 std::vector<Record*> Features = 601 Records.getAllDerivedDefinitions("SubtargetFeature"); 602 std::sort(Features.begin(), Features.end(), LessRecord()); 603 604 OS << "// ParseSubtargetFeatures - Parses features string setting specified\n" 605 << "// subtarget options.\n" 606 << "void llvm::"; 607 OS << Target; 608 OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n" 609 << " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n" 610 << " DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n"; 611 612 if (Features.empty()) { 613 OS << "}\n"; 614 return; 615 } 616 617 OS << " uint64_t Bits = ReInitMCSubtargetInfo(CPU, FS);\n"; 618 619 for (unsigned i = 0; i < Features.size(); i++) { 620 // Next record 621 Record *R = Features[i]; 622 const std::string &Instance = R->getName(); 623 const std::string &Value = R->getValueAsString("Value"); 624 const std::string &Attribute = R->getValueAsString("Attribute"); 625 626 if (Value=="true" || Value=="false") 627 OS << " if ((Bits & " << Target << "::" 628 << Instance << ") != 0) " 629 << Attribute << " = " << Value << ";\n"; 630 else 631 OS << " if ((Bits & " << Target << "::" 632 << Instance << ") != 0 && " 633 << Attribute << " < " << Value << ") " 634 << Attribute << " = " << Value << ";\n"; 635 } 636 637 OS << "}\n"; 638 } 639 640 // 641 // SubtargetEmitter::run - Main subtarget enumeration emitter. 642 // 643 void SubtargetEmitter::run(raw_ostream &OS) { 644 Target = CodeGenTarget(Records).getName(); 645 646 EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS); 647 648 OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n"; 649 OS << "#undef GET_SUBTARGETINFO_ENUM\n"; 650 651 OS << "namespace llvm {\n"; 652 Enumeration(OS, "SubtargetFeature", true); 653 OS << "} // End llvm namespace \n"; 654 OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n"; 655 656 OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n"; 657 OS << "#undef GET_SUBTARGETINFO_MC_DESC\n"; 658 659 OS << "namespace llvm {\n"; 660 #if 0 661 OS << "namespace {\n"; 662 #endif 663 unsigned NumFeatures = FeatureKeyValues(OS); 664 OS << "\n"; 665 unsigned NumProcs = CPUKeyValues(OS); 666 OS << "\n"; 667 EmitData(OS); 668 OS << "\n"; 669 #if 0 670 OS << "}\n"; 671 #endif 672 673 // MCInstrInfo initialization routine. 674 OS << "static inline void Init" << Target 675 << "MCSubtargetInfo(MCSubtargetInfo *II, " 676 << "StringRef TT, StringRef CPU, StringRef FS) {\n"; 677 OS << " II->InitMCSubtargetInfo(TT, CPU, FS, "; 678 if (NumFeatures) 679 OS << Target << "FeatureKV, "; 680 else 681 OS << "0, "; 682 if (NumProcs) 683 OS << Target << "SubTypeKV, "; 684 else 685 OS << "0, "; 686 if (HasItineraries) { 687 OS << Target << "ProcItinKV, " 688 << Target << "Stages, " 689 << Target << "OperandCycles, " 690 << Target << "ForwardingPathes, "; 691 } else 692 OS << "0, 0, 0, 0, "; 693 OS << NumFeatures << ", " << NumProcs << ");\n}\n\n"; 694 695 OS << "} // End llvm namespace \n"; 696 697 OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n"; 698 699 OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n"; 700 OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n"; 701 702 OS << "#include \"llvm/Support/Debug.h\"\n"; 703 OS << "#include \"llvm/Support/raw_ostream.h\"\n"; 704 ParseFeaturesFunction(OS, NumFeatures, NumProcs); 705 706 OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n"; 707 708 // Create a TargetSubtargetInfo subclass to hide the MC layer initialization. 709 OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n"; 710 OS << "#undef GET_SUBTARGETINFO_HEADER\n"; 711 712 std::string ClassName = Target + "GenSubtargetInfo"; 713 OS << "namespace llvm {\n"; 714 OS << "class DFAPacketizer;\n"; 715 OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n" 716 << " explicit " << ClassName << "(StringRef TT, StringRef CPU, " 717 << "StringRef FS);\n" 718 << "public:\n" 719 << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)" 720 << " const;\n" 721 << "};\n"; 722 OS << "} // End llvm namespace \n"; 723 724 OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n"; 725 726 OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n"; 727 OS << "#undef GET_SUBTARGETINFO_CTOR\n"; 728 729 OS << "namespace llvm {\n"; 730 OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n"; 731 OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n"; 732 if (HasItineraries) { 733 OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcItinKV[];\n"; 734 OS << "extern const llvm::InstrStage " << Target << "Stages[];\n"; 735 OS << "extern const unsigned " << Target << "OperandCycles[];\n"; 736 OS << "extern const unsigned " << Target << "ForwardingPathes[];\n"; 737 } 738 739 OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, " 740 << "StringRef FS)\n" 741 << " : TargetSubtargetInfo() {\n" 742 << " InitMCSubtargetInfo(TT, CPU, FS, "; 743 if (NumFeatures) 744 OS << Target << "FeatureKV, "; 745 else 746 OS << "0, "; 747 if (NumProcs) 748 OS << Target << "SubTypeKV, "; 749 else 750 OS << "0, "; 751 if (HasItineraries) { 752 OS << Target << "ProcItinKV, " 753 << Target << "Stages, " 754 << Target << "OperandCycles, " 755 << Target << "ForwardingPathes, "; 756 } else 757 OS << "0, 0, 0, 0, "; 758 OS << NumFeatures << ", " << NumProcs << ");\n}\n\n"; 759 OS << "} // End llvm namespace \n"; 760 761 OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n"; 762 } 763