1 //===- RISCVTargetDefEmitter.cpp - Generate lists of RISC-V CPUs ----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This tablegen backend emits the include file needed by the target 10 // parser to parse the RISC-V CPUs. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/Support/RISCVISAInfo.h" 15 #include "llvm/TableGen/Record.h" 16 #include "llvm/TableGen/TableGenBackend.h" 17 18 using namespace llvm; 19 20 using ISAInfoTy = llvm::Expected<std::unique_ptr<RISCVISAInfo>>; 21 22 // We can generate march string from target features as what has been described 23 // in RISC-V ISA specification (version 20191213) 'Chapter 27. ISA Extension 24 // Naming Conventions'. 25 // 26 // This is almost the same as RISCVFeatures::parseFeatureBits, except that we 27 // get feature name from feature records instead of feature bits. 28 static std::string getMArch(const Record &Rec) { 29 std::vector<std::string> FeatureVector; 30 unsigned XLen = 32; 31 32 // Convert features to FeatureVector. 33 for (auto *Feature : Rec.getValueAsListOfDefs("Features")) { 34 StringRef FeatureName = Feature->getValueAsString("Name"); 35 if (llvm::RISCVISAInfo::isSupportedExtensionFeature(FeatureName)) 36 FeatureVector.push_back((Twine("+") + FeatureName).str()); 37 else if (FeatureName == "64bit") 38 XLen = 64; 39 } 40 41 ISAInfoTy ISAInfo = llvm::RISCVISAInfo::parseFeatures(XLen, FeatureVector); 42 if (!ISAInfo) 43 report_fatal_error("Invalid features"); 44 45 // RISCVISAInfo::toString will generate a march string with all the extensions 46 // we have added to it. 47 return (*ISAInfo)->toString(); 48 } 49 50 static void EmitRISCVTargetDef(RecordKeeper &RK, raw_ostream &OS) { 51 OS << "#ifndef PROC\n" 52 << "#define PROC(ENUM, NAME, DEFAULT_MARCH)\n" 53 << "#endif\n\n"; 54 55 // Iterate on all definition records. 56 for (const Record *Rec : RK.getAllDerivedDefinitions("RISCVProcessorModel")) { 57 std::string MArch = Rec->getValueAsString("DefaultMarch").str(); 58 59 // Compute MArch from features if we don't specify it. 60 if (MArch.empty()) 61 MArch = getMArch(*Rec); 62 63 OS << "PROC(" << Rec->getName() << ", " 64 << "{\"" << Rec->getValueAsString("Name") << "\"}, " 65 << "{\"" << MArch << "\"})\n"; 66 } 67 OS << "\n#undef PROC\n"; 68 OS << "\n"; 69 OS << "#ifndef TUNE_PROC\n" 70 << "#define TUNE_PROC(ENUM, NAME)\n" 71 << "#endif\n\n"; 72 OS << "TUNE_PROC(GENERIC, \"generic\")\n"; 73 74 for (const Record *Rec : 75 RK.getAllDerivedDefinitions("RISCVTuneProcessorModel")) { 76 OS << "TUNE_PROC(" << Rec->getName() << ", " 77 << "\"" << Rec->getValueAsString("Name") << "\")\n"; 78 } 79 80 OS << "\n#undef TUNE_PROC\n"; 81 } 82 83 static TableGen::Emitter::Opt X("gen-riscv-target-def", EmitRISCVTargetDef, 84 "Generate the list of CPU for RISCV"); 85