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