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