SubtargetEmitter.cpp revision 3f696e568bae8afa5986e7af48156c2bac041ba7
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 // Skip default 426 if (Name == "NoItineraries") continue; 427 428 // Create and expand processor itinerary to cover all itinerary classes 429 std::vector<InstrItinerary> ItinList; 430 ItinList.resize(NItinClasses); 431 432 // Get itinerary data list 433 std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID"); 434 435 // For each itinerary data 436 for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) { 437 // Next itinerary data 438 Record *ItinData = ItinDataList[j]; 439 440 // Get string and stage count 441 std::string ItinStageString; 442 unsigned NStages; 443 FormItineraryStageString(Name, ItinData, ItinStageString, NStages); 444 445 // Get string and operand cycle count 446 std::string ItinOperandCycleString; 447 unsigned NOperandCycles; 448 FormItineraryOperandCycleString(ItinData, ItinOperandCycleString, 449 NOperandCycles); 450 451 std::string ItinBypassString; 452 FormItineraryBypassString(Name, ItinData, ItinBypassString, 453 NOperandCycles); 454 455 // Check to see if stage already exists and create if it doesn't 456 unsigned FindStage = 0; 457 if (NStages > 0) { 458 FindStage = ItinStageMap[ItinStageString]; 459 if (FindStage == 0) { 460 // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices 461 StageTable += ItinStageString + ", // " + itostr(StageCount); 462 if (NStages > 1) 463 StageTable += "-" + itostr(StageCount + NStages - 1); 464 StageTable += "\n"; 465 // Record Itin class number. 466 ItinStageMap[ItinStageString] = FindStage = StageCount; 467 StageCount += NStages; 468 } 469 } 470 471 // Check to see if operand cycle already exists and create if it doesn't 472 unsigned FindOperandCycle = 0; 473 if (NOperandCycles > 0) { 474 std::string ItinOperandString = ItinOperandCycleString+ItinBypassString; 475 FindOperandCycle = ItinOperandMap[ItinOperandString]; 476 if (FindOperandCycle == 0) { 477 // Emit as cycle, // index 478 OperandCycleTable += ItinOperandCycleString + ", // "; 479 std::string OperandIdxComment = itostr(OperandCycleCount); 480 if (NOperandCycles > 1) 481 OperandIdxComment += "-" 482 + itostr(OperandCycleCount + NOperandCycles - 1); 483 OperandCycleTable += OperandIdxComment + "\n"; 484 // Record Itin class number. 485 ItinOperandMap[ItinOperandCycleString] = 486 FindOperandCycle = OperandCycleCount; 487 // Emit as bypass, // index 488 BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n"; 489 OperandCycleCount += NOperandCycles; 490 } 491 } 492 493 // Locate where to inject into processor itinerary table 494 const std::string &Name = ItinData->getValueAsDef("TheClass")->getName(); 495 unsigned Find = ItinClassesMap[Name]; 496 497 // Set up itinerary as location and location + stage count 498 unsigned NumUOps = ItinClassList[Find]->getValueAsInt("NumMicroOps"); 499 InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages, 500 FindOperandCycle, 501 FindOperandCycle + NOperandCycles}; 502 503 // Inject - empty slots will be 0, 0 504 ItinList[Find] = Intinerary; 505 } 506 507 // Add process itinerary to list 508 ProcList.push_back(ItinList); 509 } 510 511 // Closing stage 512 StageTable += " { 0, 0, 0, llvm::InstrStage::Required } // End itinerary\n"; 513 StageTable += "};\n"; 514 515 // Closing operand cycles 516 OperandCycleTable += " 0 // End itinerary\n"; 517 OperandCycleTable += "};\n"; 518 519 BypassTable += " 0 // End itinerary\n"; 520 BypassTable += "};\n"; 521 522 // Emit tables. 523 OS << StageTable; 524 OS << OperandCycleTable; 525 OS << BypassTable; 526} 527 528void SubtargetEmitter::EmitItineraryProp(raw_ostream &OS, const Record *R, 529 const char *Name, char Separator) { 530 OS << " "; 531 int V = R->getValueAsInt(Name); 532 if (V >= 0) 533 OS << V << Separator << " // " << Name; 534 else 535 OS << "InstrItineraryProps::Default" << Name << Separator; 536 OS << '\n'; 537} 538 539// 540// EmitProcessorData - Generate data for processor itineraries. 541// 542void SubtargetEmitter:: 543EmitProcessorData(raw_ostream &OS, 544 std::vector<Record*> &ItinClassList, 545 std::vector<std::vector<InstrItinerary> > &ProcList) { 546 547 // Get an iterator for processor itinerary stages 548 std::vector<std::vector<InstrItinerary> >::iterator 549 ProcListIter = ProcList.begin(); 550 551 // For each processor itinerary 552 std::vector<Record*> Itins = 553 Records.getAllDerivedDefinitions("ProcessorItineraries"); 554 for (unsigned i = 0, N = Itins.size(); i < N; i++) { 555 // Next record 556 Record *Itin = Itins[i]; 557 558 // Get processor itinerary name 559 const std::string &Name = Itin->getName(); 560 561 // Skip default 562 if (Name == "NoItineraries") continue; 563 564 // Begin processor itinerary properties 565 OS << "\n"; 566 OS << "static const llvm::InstrItineraryProps " << Name << "Props(\n"; 567 EmitItineraryProp(OS, Itin, "IssueWidth", ','); 568 EmitItineraryProp(OS, Itin, "MinLatency", ','); 569 EmitItineraryProp(OS, Itin, "LoadLatency", ','); 570 EmitItineraryProp(OS, Itin, "HighLatency", ' '); 571 OS << ");\n"; 572 573 // Begin processor itinerary table 574 OS << "\n"; 575 OS << "static const llvm::InstrItinerary " << Name << "Entries" 576 << "[] = {\n"; 577 578 // For each itinerary class 579 std::vector<InstrItinerary> &ItinList = *ProcListIter++; 580 assert(ItinList.size() == ItinClassList.size() && "bad itinerary"); 581 for (unsigned j = 0, M = ItinList.size(); j < M; ++j) { 582 InstrItinerary &Intinerary = ItinList[j]; 583 584 // Emit in the form of 585 // { firstStage, lastStage, firstCycle, lastCycle } // index 586 if (Intinerary.FirstStage == 0) { 587 OS << " { 1, 0, 0, 0, 0 }"; 588 } else { 589 OS << " { " << 590 Intinerary.NumMicroOps << ", " << 591 Intinerary.FirstStage << ", " << 592 Intinerary.LastStage << ", " << 593 Intinerary.FirstOperandCycle << ", " << 594 Intinerary.LastOperandCycle << " }"; 595 } 596 597 OS << ", // " << j << " " << ItinClassList[j]->getName() << "\n"; 598 } 599 600 // End processor itinerary table 601 OS << " { 1, ~0U, ~0U, ~0U, ~0U } // end marker\n"; 602 OS << "};\n"; 603 604 OS << '\n'; 605 OS << "static const llvm::InstrItinerarySubtargetValue " 606 << Name << " = {\n"; 607 OS << " &" << Name << "Props,\n"; 608 OS << " " << Name << "Entries\n"; 609 OS << "};\n"; 610 } 611} 612 613// 614// EmitProcessorLookup - generate cpu name to itinerary lookup table. 615// 616void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) { 617 // Gather and sort processor information 618 std::vector<Record*> ProcessorList = 619 Records.getAllDerivedDefinitions("Processor"); 620 std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName()); 621 622 // Begin processor table 623 OS << "\n"; 624 OS << "// Sorted (by key) array of itineraries for CPU subtype.\n" 625 << "extern const llvm::SubtargetInfoKV " 626 << Target << "ProcItinKV[] = {\n"; 627 628 // For each processor 629 for (unsigned i = 0, N = ProcessorList.size(); i < N;) { 630 // Next processor 631 Record *Processor = ProcessorList[i]; 632 633 const std::string &Name = Processor->getValueAsString("Name"); 634 const std::string &ProcItin = 635 Processor->getValueAsDef("ProcItin")->getName(); 636 637 // Emit as { "cpu", procinit }, 638 OS << " { " 639 << "\"" << Name << "\", " 640 << "(void *)&" << ProcItin; 641 642 OS << " }"; 643 644 // Depending on ''if more in the list'' emit comma 645 if (++i < N) OS << ","; 646 647 OS << "\n"; 648 } 649 650 // End processor table 651 OS << "};\n"; 652} 653 654// 655// EmitData - Emits all stages and itineries, folding common patterns. 656// 657void SubtargetEmitter::EmitData(raw_ostream &OS) { 658 std::map<std::string, unsigned> ItinClassesMap; 659 // Gather and sort all itinerary classes 660 std::vector<Record*> ItinClassList = 661 Records.getAllDerivedDefinitions("InstrItinClass"); 662 std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord()); 663 664 // Enumerate all the itinerary classes 665 unsigned NItinClasses = CollectAllItinClasses(OS, ItinClassesMap, 666 ItinClassList); 667 // Make sure the rest is worth the effort 668 HasItineraries = NItinClasses != 1; // Ignore NoItinerary. 669 670 if (HasItineraries) { 671 std::vector<std::vector<InstrItinerary> > ProcList; 672 // Emit the stage data 673 EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap, 674 ItinClassList, ProcList); 675 // Emit the processor itinerary data 676 EmitProcessorData(OS, ItinClassList, ProcList); 677 // Emit the processor lookup data 678 EmitProcessorLookup(OS); 679 } 680} 681 682// 683// ParseFeaturesFunction - Produces a subtarget specific function for parsing 684// the subtarget features string. 685// 686void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS, 687 unsigned NumFeatures, 688 unsigned NumProcs) { 689 std::vector<Record*> Features = 690 Records.getAllDerivedDefinitions("SubtargetFeature"); 691 std::sort(Features.begin(), Features.end(), LessRecord()); 692 693 OS << "// ParseSubtargetFeatures - Parses features string setting specified\n" 694 << "// subtarget options.\n" 695 << "void llvm::"; 696 OS << Target; 697 OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n" 698 << " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n" 699 << " DEBUG(dbgs() << \"\\nCPU:\" << CPU << \"\\n\\n\");\n"; 700 701 if (Features.empty()) { 702 OS << "}\n"; 703 return; 704 } 705 706 OS << " uint64_t Bits = ReInitMCSubtargetInfo(CPU, FS);\n"; 707 708 for (unsigned i = 0; i < Features.size(); i++) { 709 // Next record 710 Record *R = Features[i]; 711 const std::string &Instance = R->getName(); 712 const std::string &Value = R->getValueAsString("Value"); 713 const std::string &Attribute = R->getValueAsString("Attribute"); 714 715 if (Value=="true" || Value=="false") 716 OS << " if ((Bits & " << Target << "::" 717 << Instance << ") != 0) " 718 << Attribute << " = " << Value << ";\n"; 719 else 720 OS << " if ((Bits & " << Target << "::" 721 << Instance << ") != 0 && " 722 << Attribute << " < " << Value << ") " 723 << Attribute << " = " << Value << ";\n"; 724 } 725 726 OS << "}\n"; 727} 728 729// 730// SubtargetEmitter::run - Main subtarget enumeration emitter. 731// 732void SubtargetEmitter::run(raw_ostream &OS) { 733 Target = CodeGenTarget(Records).getName(); 734 735 emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS); 736 737 OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n"; 738 OS << "#undef GET_SUBTARGETINFO_ENUM\n"; 739 740 OS << "namespace llvm {\n"; 741 Enumeration(OS, "SubtargetFeature", true); 742 OS << "} // End llvm namespace \n"; 743 OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n"; 744 745 OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n"; 746 OS << "#undef GET_SUBTARGETINFO_MC_DESC\n"; 747 748 OS << "namespace llvm {\n"; 749#if 0 750 OS << "namespace {\n"; 751#endif 752 unsigned NumFeatures = FeatureKeyValues(OS); 753 OS << "\n"; 754 unsigned NumProcs = CPUKeyValues(OS); 755 OS << "\n"; 756 EmitData(OS); 757 OS << "\n"; 758#if 0 759 OS << "}\n"; 760#endif 761 762 // MCInstrInfo initialization routine. 763 OS << "static inline void Init" << Target 764 << "MCSubtargetInfo(MCSubtargetInfo *II, " 765 << "StringRef TT, StringRef CPU, StringRef FS) {\n"; 766 OS << " II->InitMCSubtargetInfo(TT, CPU, FS, "; 767 if (NumFeatures) 768 OS << Target << "FeatureKV, "; 769 else 770 OS << "0, "; 771 if (NumProcs) 772 OS << Target << "SubTypeKV, "; 773 else 774 OS << "0, "; 775 if (HasItineraries) { 776 OS << Target << "ProcItinKV, " 777 << Target << "Stages, " 778 << Target << "OperandCycles, " 779 << Target << "ForwardingPathes, "; 780 } else 781 OS << "0, 0, 0, 0, "; 782 OS << NumFeatures << ", " << NumProcs << ");\n}\n\n"; 783 784 OS << "} // End llvm namespace \n"; 785 786 OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n"; 787 788 OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n"; 789 OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n"; 790 791 OS << "#include \"llvm/Support/Debug.h\"\n"; 792 OS << "#include \"llvm/Support/raw_ostream.h\"\n"; 793 ParseFeaturesFunction(OS, NumFeatures, NumProcs); 794 795 OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n"; 796 797 // Create a TargetSubtargetInfo subclass to hide the MC layer initialization. 798 OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n"; 799 OS << "#undef GET_SUBTARGETINFO_HEADER\n"; 800 801 std::string ClassName = Target + "GenSubtargetInfo"; 802 OS << "namespace llvm {\n"; 803 OS << "class DFAPacketizer;\n"; 804 OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n" 805 << " explicit " << ClassName << "(StringRef TT, StringRef CPU, " 806 << "StringRef FS);\n" 807 << "public:\n" 808 << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)" 809 << " const;\n" 810 << "};\n"; 811 OS << "} // End llvm namespace \n"; 812 813 OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n"; 814 815 OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n"; 816 OS << "#undef GET_SUBTARGETINFO_CTOR\n"; 817 818 OS << "namespace llvm {\n"; 819 OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n"; 820 OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n"; 821 if (HasItineraries) { 822 OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcItinKV[];\n"; 823 OS << "extern const llvm::InstrStage " << Target << "Stages[];\n"; 824 OS << "extern const unsigned " << Target << "OperandCycles[];\n"; 825 OS << "extern const unsigned " << Target << "ForwardingPathes[];\n"; 826 } 827 828 OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, " 829 << "StringRef FS)\n" 830 << " : TargetSubtargetInfo() {\n" 831 << " InitMCSubtargetInfo(TT, CPU, FS, "; 832 if (NumFeatures) 833 OS << Target << "FeatureKV, "; 834 else 835 OS << "0, "; 836 if (NumProcs) 837 OS << Target << "SubTypeKV, "; 838 else 839 OS << "0, "; 840 if (HasItineraries) { 841 OS << Target << "ProcItinKV, " 842 << Target << "Stages, " 843 << Target << "OperandCycles, " 844 << Target << "ForwardingPathes, "; 845 } else 846 OS << "0, 0, 0, 0, "; 847 OS << NumFeatures << ", " << NumProcs << ");\n}\n\n"; 848 OS << "} // End llvm namespace \n"; 849 850 OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n"; 851} 852 853namespace llvm { 854 855void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) { 856 SubtargetEmitter(RK).run(OS); 857} 858 859} // End llvm namespace 860