SubtargetEmitter.cpp revision fc992996f751e0941951b6d08d8f1e80ebec1385
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> 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 // 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// 85unsigned 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// 149unsigned 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// 202unsigned SubtargetEmitter:: 203CollectAllItinClasses(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// 225void 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// 270void 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 287void 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// 309void 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 481void SubtargetEmitter::EmitItineraryProp(raw_ostream &OS, const Record *R, 482 const char *Name, char Separator) { 483 OS << " "; 484 int V = R->getValueAsInt(Name); 485 if (V >= 0) 486 OS << V << Separator << " // " << Name; 487 else 488 OS << "DefaultItineraryProps." << Name << Separator; 489 OS << '\n'; 490} 491 492// 493// EmitProcessorData - Generate data for processor itineraries. 494// 495void SubtargetEmitter:: 496EmitProcessorData(raw_ostream &OS, 497 std::vector<Record*> &ItinClassList, 498 std::vector<std::vector<InstrItinerary> > &ProcList) { 499 OS << "static const llvm::InstrItineraryProps " << "DefaultItineraryProps;"; 500 501 // Get an iterator for processor itinerary stages 502 std::vector<std::vector<InstrItinerary> >::iterator 503 ProcListIter = ProcList.begin(); 504 505 // For each processor itinerary 506 std::vector<Record*> Itins = 507 Records.getAllDerivedDefinitions("ProcessorItineraries"); 508 for (unsigned i = 0, N = Itins.size(); i < N; i++) { 509 // Next record 510 Record *Itin = Itins[i]; 511 512 // Get processor itinerary name 513 const std::string &Name = Itin->getName(); 514 515 // Skip default 516 if (Name == "NoItineraries") continue; 517 518 // Begin processor itinerary properties 519 OS << "\n"; 520 OS << "static const llvm::InstrItineraryProps " << Name << "Props(\n"; 521 EmitItineraryProp(OS, Itin, "IssueWidth", ','); 522 EmitItineraryProp(OS, Itin, "MinLatency", ','); 523 EmitItineraryProp(OS, Itin, "LoadLatency", ','); 524 EmitItineraryProp(OS, Itin, "HighLatency", ' '); 525 OS << ");\n"; 526 527 // Begin processor itinerary table 528 OS << "\n"; 529 OS << "static const llvm::InstrItinerary " << Name << "Entries" 530 << "[] = {\n"; 531 532 // For each itinerary class 533 std::vector<InstrItinerary> &ItinList = *ProcListIter++; 534 assert(ItinList.size() == ItinClassList.size() && "bad itinerary"); 535 for (unsigned j = 0, M = ItinList.size(); j < M; ++j) { 536 InstrItinerary &Intinerary = ItinList[j]; 537 538 // Emit in the form of 539 // { firstStage, lastStage, firstCycle, lastCycle } // index 540 if (Intinerary.FirstStage == 0) { 541 OS << " { 1, 0, 0, 0, 0 }"; 542 } else { 543 OS << " { " << 544 Intinerary.NumMicroOps << ", " << 545 Intinerary.FirstStage << ", " << 546 Intinerary.LastStage << ", " << 547 Intinerary.FirstOperandCycle << ", " << 548 Intinerary.LastOperandCycle << " }"; 549 } 550 551 OS << ", // " << j << " " << ItinClassList[j]->getName() << "\n"; 552 } 553 554 // End processor itinerary table 555 OS << " { 1, ~0U, ~0U, ~0U, ~0U } // end marker\n"; 556 OS << "};\n"; 557 558 OS << '\n'; 559 OS << "static const llvm::InstrItinerarySubtargetValue " 560 << Name << " = {\n"; 561 OS << " &" << Name << "Props,\n"; 562 OS << " " << Name << "Entries\n"; 563 OS << "};\n"; 564 } 565} 566 567// 568// EmitProcessorLookup - generate cpu name to itinerary lookup table. 569// 570void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) { 571 // Gather and sort processor information 572 std::vector<Record*> ProcessorList = 573 Records.getAllDerivedDefinitions("Processor"); 574 std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName()); 575 576 // Begin processor table 577 OS << "\n"; 578 OS << "// Sorted (by key) array of itineraries for CPU subtype.\n" 579 << "extern const llvm::SubtargetInfoKV " 580 << Target << "ProcItinKV[] = {\n"; 581 582 // For each processor 583 for (unsigned i = 0, N = ProcessorList.size(); i < N;) { 584 // Next processor 585 Record *Processor = ProcessorList[i]; 586 587 const std::string &Name = Processor->getValueAsString("Name"); 588 const std::string &ProcItin = 589 Processor->getValueAsDef("ProcItin")->getName(); 590 591 // Emit as { "cpu", procinit }, 592 OS << " { " 593 << "\"" << Name << "\", " 594 << "(void *)&" << ProcItin; 595 596 OS << " }"; 597 598 // Depending on ''if more in the list'' emit comma 599 if (++i < N) OS << ","; 600 601 OS << "\n"; 602 } 603 604 // End processor table 605 OS << "};\n"; 606} 607 608// 609// EmitData - Emits all stages and itineries, folding common patterns. 610// 611void SubtargetEmitter::EmitData(raw_ostream &OS) { 612 std::map<std::string, unsigned> ItinClassesMap; 613 // Gather and sort all itinerary classes 614 std::vector<Record*> ItinClassList = 615 Records.getAllDerivedDefinitions("InstrItinClass"); 616 std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord()); 617 618 // Enumerate all the itinerary classes 619 unsigned NItinClasses = CollectAllItinClasses(OS, ItinClassesMap, 620 ItinClassList); 621 // Make sure the rest is worth the effort 622 HasItineraries = NItinClasses != 1; // Ignore NoItinerary. 623 624 if (HasItineraries) { 625 std::vector<std::vector<InstrItinerary> > ProcList; 626 // Emit the stage data 627 EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap, 628 ItinClassList, ProcList); 629 // Emit the processor itinerary data 630 EmitProcessorData(OS, ItinClassList, ProcList); 631 // Emit the processor lookup data 632 EmitProcessorLookup(OS); 633 } 634} 635 636// 637// ParseFeaturesFunction - Produces a subtarget specific function for parsing 638// the subtarget features string. 639// 640void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS, 641 unsigned NumFeatures, 642 unsigned NumProcs) { 643 std::vector<Record*> Features = 644 Records.getAllDerivedDefinitions("SubtargetFeature"); 645 std::sort(Features.begin(), Features.end(), LessRecord()); 646 647 OS << "// ParseSubtargetFeatures - Parses features string setting specified\n" 648 << "// subtarget options.\n" 649 << "void llvm::"; 650 OS << Target; 651 OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n" 652 << " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n" 653 << " DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n"; 654 655 if (Features.empty()) { 656 OS << "}\n"; 657 return; 658 } 659 660 OS << " uint64_t Bits = ReInitMCSubtargetInfo(CPU, FS);\n"; 661 662 for (unsigned i = 0; i < Features.size(); i++) { 663 // Next record 664 Record *R = Features[i]; 665 const std::string &Instance = R->getName(); 666 const std::string &Value = R->getValueAsString("Value"); 667 const std::string &Attribute = R->getValueAsString("Attribute"); 668 669 if (Value=="true" || Value=="false") 670 OS << " if ((Bits & " << Target << "::" 671 << Instance << ") != 0) " 672 << Attribute << " = " << Value << ";\n"; 673 else 674 OS << " if ((Bits & " << Target << "::" 675 << Instance << ") != 0 && " 676 << Attribute << " < " << Value << ") " 677 << Attribute << " = " << Value << ";\n"; 678 } 679 680 OS << "}\n"; 681} 682 683// 684// SubtargetEmitter::run - Main subtarget enumeration emitter. 685// 686void SubtargetEmitter::run(raw_ostream &OS) { 687 Target = CodeGenTarget(Records).getName(); 688 689 EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS); 690 691 OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n"; 692 OS << "#undef GET_SUBTARGETINFO_ENUM\n"; 693 694 OS << "namespace llvm {\n"; 695 Enumeration(OS, "SubtargetFeature", true); 696 OS << "} // End llvm namespace \n"; 697 OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n"; 698 699 OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n"; 700 OS << "#undef GET_SUBTARGETINFO_MC_DESC\n"; 701 702 OS << "namespace llvm {\n"; 703#if 0 704 OS << "namespace {\n"; 705#endif 706 unsigned NumFeatures = FeatureKeyValues(OS); 707 OS << "\n"; 708 unsigned NumProcs = CPUKeyValues(OS); 709 OS << "\n"; 710 EmitData(OS); 711 OS << "\n"; 712#if 0 713 OS << "}\n"; 714#endif 715 716 // MCInstrInfo initialization routine. 717 OS << "static inline void Init" << Target 718 << "MCSubtargetInfo(MCSubtargetInfo *II, " 719 << "StringRef TT, StringRef CPU, StringRef FS) {\n"; 720 OS << " II->InitMCSubtargetInfo(TT, CPU, FS, "; 721 if (NumFeatures) 722 OS << Target << "FeatureKV, "; 723 else 724 OS << "0, "; 725 if (NumProcs) 726 OS << Target << "SubTypeKV, "; 727 else 728 OS << "0, "; 729 if (HasItineraries) { 730 OS << Target << "ProcItinKV, " 731 << Target << "Stages, " 732 << Target << "OperandCycles, " 733 << Target << "ForwardingPathes, "; 734 } else 735 OS << "0, 0, 0, 0, "; 736 OS << NumFeatures << ", " << NumProcs << ");\n}\n\n"; 737 738 OS << "} // End llvm namespace \n"; 739 740 OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n"; 741 742 OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n"; 743 OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n"; 744 745 OS << "#include \"llvm/Support/Debug.h\"\n"; 746 OS << "#include \"llvm/Support/raw_ostream.h\"\n"; 747 ParseFeaturesFunction(OS, NumFeatures, NumProcs); 748 749 OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n"; 750 751 // Create a TargetSubtargetInfo subclass to hide the MC layer initialization. 752 OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n"; 753 OS << "#undef GET_SUBTARGETINFO_HEADER\n"; 754 755 std::string ClassName = Target + "GenSubtargetInfo"; 756 OS << "namespace llvm {\n"; 757 OS << "class DFAPacketizer;\n"; 758 OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n" 759 << " explicit " << ClassName << "(StringRef TT, StringRef CPU, " 760 << "StringRef FS);\n" 761 << "public:\n" 762 << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)" 763 << " const;\n" 764 << "};\n"; 765 OS << "} // End llvm namespace \n"; 766 767 OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n"; 768 769 OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n"; 770 OS << "#undef GET_SUBTARGETINFO_CTOR\n"; 771 772 OS << "namespace llvm {\n"; 773 OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n"; 774 OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n"; 775 if (HasItineraries) { 776 OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcItinKV[];\n"; 777 OS << "extern const llvm::InstrStage " << Target << "Stages[];\n"; 778 OS << "extern const unsigned " << Target << "OperandCycles[];\n"; 779 OS << "extern const unsigned " << Target << "ForwardingPathes[];\n"; 780 } 781 782 OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, " 783 << "StringRef FS)\n" 784 << " : TargetSubtargetInfo() {\n" 785 << " InitMCSubtargetInfo(TT, CPU, FS, "; 786 if (NumFeatures) 787 OS << Target << "FeatureKV, "; 788 else 789 OS << "0, "; 790 if (NumProcs) 791 OS << Target << "SubTypeKV, "; 792 else 793 OS << "0, "; 794 if (HasItineraries) { 795 OS << Target << "ProcItinKV, " 796 << Target << "Stages, " 797 << Target << "OperandCycles, " 798 << Target << "ForwardingPathes, "; 799 } else 800 OS << "0, 0, 0, 0, "; 801 OS << NumFeatures << ", " << NumProcs << ");\n}\n\n"; 802 OS << "} // End llvm namespace \n"; 803 804 OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n"; 805} 806