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