//===- RISCVTargetDefEmitter.cpp - Generate lists of RISC-V CPUs ----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This tablegen backend emits the include file needed by the target // parser to parse the RISC-V CPUs. // //===----------------------------------------------------------------------===// #include "llvm/Support/RISCVISAInfo.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" using namespace llvm; using ISAInfoTy = llvm::Expected>; // We can generate march string from target features as what has been described // in RISC-V ISA specification (version 20191213) 'Chapter 27. ISA Extension // Naming Conventions'. // // This is almost the same as RISCVFeatures::parseFeatureBits, except that we // get feature name from feature records instead of feature bits. static std::string getMArch(const Record &Rec) { std::vector FeatureVector; unsigned XLen = 32; // Convert features to FeatureVector. for (auto *Feature : Rec.getValueAsListOfDefs("Features")) { StringRef FeatureName = Feature->getValueAsString("Name"); if (llvm::RISCVISAInfo::isSupportedExtensionFeature(FeatureName)) FeatureVector.push_back((Twine("+") + FeatureName).str()); else if (FeatureName == "64bit") XLen = 64; } ISAInfoTy ISAInfo = llvm::RISCVISAInfo::parseFeatures(XLen, FeatureVector); if (!ISAInfo) report_fatal_error("Invalid features"); // RISCVISAInfo::toString will generate a march string with all the extensions // we have added to it. return (*ISAInfo)->toString(); } static void EmitRISCVTargetDef(RecordKeeper &RK, raw_ostream &OS) { OS << "#ifndef PROC\n" << "#define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_UNALIGNED_ACCESS)\n" << "#endif\n\n"; // Iterate on all definition records. for (const Record *Rec : RK.getAllDerivedDefinitions("RISCVProcessorModel")) { std::string MArch = Rec->getValueAsString("DefaultMarch").str(); // Compute MArch from features if we don't specify it. if (MArch.empty()) MArch = getMArch(*Rec); const bool FastUnalignedAccess = any_of(Rec->getValueAsListOfDefs("Features"), [&](auto &Feature) { return Feature->getValueAsString("Name") == "fast-unaligned-access"; }); OS << "PROC(" << Rec->getName() << ", " << "{\"" << Rec->getValueAsString("Name") << "\"}, " << "{\"" << MArch << "\"}, " << FastUnalignedAccess << ")\n"; } OS << "\n#undef PROC\n"; OS << "\n"; OS << "#ifndef TUNE_PROC\n" << "#define TUNE_PROC(ENUM, NAME)\n" << "#endif\n\n"; OS << "TUNE_PROC(GENERIC, \"generic\")\n"; for (const Record *Rec : RK.getAllDerivedDefinitions("RISCVTuneProcessorModel")) { OS << "TUNE_PROC(" << Rec->getName() << ", " << "\"" << Rec->getValueAsString("Name") << "\")\n"; } OS << "\n#undef TUNE_PROC\n"; } static TableGen::Emitter::Opt X("gen-riscv-target-def", EmitRISCVTargetDef, "Generate the list of CPU for RISCV");