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