Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/Basic/RISCVTargetDefEmitter.cpp
213799 views
//===- RISCVTargetDefEmitter.cpp - Generate lists of RISC-V CPUs ----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This tablegen backend emits the include file needed by RISCVTargetParser.cpp9// and RISCVISAInfo.cpp to parse the RISC-V CPUs and extensions.10//11//===----------------------------------------------------------------------===//1213#include "llvm/ADT/DenseSet.h"14#include "llvm/Support/Format.h"15#include "llvm/Support/RISCVISAUtils.h"16#include "llvm/TableGen/Record.h"17#include "llvm/TableGen/TableGenBackend.h"1819using namespace llvm;2021static StringRef getExtensionName(const Record *R) {22StringRef Name = R->getValueAsString("Name");23Name.consume_front("experimental-");24return Name;25}2627static void printExtensionTable(raw_ostream &OS,28ArrayRef<const Record *> Extensions,29bool Experimental) {30OS << "static const RISCVSupportedExtension Supported";31if (Experimental)32OS << "Experimental";33OS << "Extensions[] = {\n";3435for (const Record *R : Extensions) {36if (R->getValueAsBit("Experimental") != Experimental)37continue;3839OS.indent(4) << "{\"" << getExtensionName(R) << "\", {"40<< R->getValueAsInt("MajorVersion") << ", "41<< R->getValueAsInt("MinorVersion") << "}},\n";42}4344OS << "};\n\n";45}4647static void emitRISCVExtensions(const RecordKeeper &Records, raw_ostream &OS) {48OS << "#ifdef GET_SUPPORTED_EXTENSIONS\n";49OS << "#undef GET_SUPPORTED_EXTENSIONS\n\n";5051std::vector<const Record *> Extensions =52Records.getAllDerivedDefinitionsIfDefined("RISCVExtension");53llvm::sort(Extensions, [](const Record *Rec1, const Record *Rec2) {54return getExtensionName(Rec1) < getExtensionName(Rec2);55});5657if (!Extensions.empty()) {58printExtensionTable(OS, Extensions, /*Experimental=*/false);59printExtensionTable(OS, Extensions, /*Experimental=*/true);60}6162OS << "#endif // GET_SUPPORTED_EXTENSIONS\n\n";6364OS << "#ifdef GET_IMPLIED_EXTENSIONS\n";65OS << "#undef GET_IMPLIED_EXTENSIONS\n\n";6667if (!Extensions.empty()) {68OS << "\nstatic constexpr ImpliedExtsEntry ImpliedExts[] = {\n";69for (const Record *Ext : Extensions) {70auto ImpliesList = Ext->getValueAsListOfDefs("Implies");71if (ImpliesList.empty())72continue;7374StringRef Name = getExtensionName(Ext);7576for (auto *ImpliedExt : ImpliesList) {77if (!ImpliedExt->isSubClassOf("RISCVExtension"))78continue;7980OS.indent(4) << "{ {\"" << Name << "\"}, \""81<< getExtensionName(ImpliedExt) << "\"},\n";82}83}8485OS << "};\n\n";86}8788OS << "#endif // GET_IMPLIED_EXTENSIONS\n\n";89}9091// We can generate march string from target features as what has been described92// in RISC-V ISA specification (version 20191213) 'Chapter 27. ISA Extension93// Naming Conventions'.94//95// This is almost the same as RISCVFeatures::parseFeatureBits, except that we96// get feature name from feature records instead of feature bits.97static void printMArch(raw_ostream &OS, ArrayRef<const Record *> Features) {98RISCVISAUtils::OrderedExtensionMap Extensions;99unsigned XLen = 0;100101// Convert features to FeatureVector.102for (const Record *Feature : Features) {103StringRef FeatureName = getExtensionName(Feature);104if (Feature->isSubClassOf("RISCVExtension")) {105unsigned Major = Feature->getValueAsInt("MajorVersion");106unsigned Minor = Feature->getValueAsInt("MinorVersion");107Extensions[FeatureName.str()] = {Major, Minor};108} else if (FeatureName == "64bit") {109assert(XLen == 0 && "Already determined XLen");110XLen = 64;111} else if (FeatureName == "32bit") {112assert(XLen == 0 && "Already determined XLen");113XLen = 32;114}115}116117assert(XLen != 0 && "Unable to determine XLen");118119OS << "rv" << XLen;120121ListSeparator LS("_");122for (auto const &Ext : Extensions)123OS << LS << Ext.first << Ext.second.Major << 'p' << Ext.second.Minor;124}125126static void printProfileTable(raw_ostream &OS,127ArrayRef<const Record *> Profiles,128bool Experimental) {129OS << "static constexpr RISCVProfile Supported";130if (Experimental)131OS << "Experimental";132OS << "Profiles[] = {\n";133134for (const Record *Rec : Profiles) {135if (Rec->getValueAsBit("Experimental") != Experimental)136continue;137138StringRef Name = Rec->getValueAsString("Name");139Name.consume_front("experimental-");140OS.indent(4) << "{\"" << Name << "\",\"";141printMArch(OS, Rec->getValueAsListOfDefs("Implies"));142OS << "\"},\n";143}144145OS << "};\n\n";146}147148static void emitRISCVProfiles(const RecordKeeper &Records, raw_ostream &OS) {149OS << "#ifdef GET_SUPPORTED_PROFILES\n";150OS << "#undef GET_SUPPORTED_PROFILES\n\n";151152auto Profiles = Records.getAllDerivedDefinitionsIfDefined("RISCVProfile");153154if (!Profiles.empty()) {155printProfileTable(OS, Profiles, /*Experimental=*/false);156bool HasExperimentalProfiles = any_of(Profiles, [&](auto &Rec) {157return Rec->getValueAsBit("Experimental");158});159if (HasExperimentalProfiles)160printProfileTable(OS, Profiles, /*Experimental=*/true);161}162163OS << "#endif // GET_SUPPORTED_PROFILES\n\n";164}165166static void emitRISCVProcs(const RecordKeeper &RK, raw_ostream &OS) {167OS << "#ifndef PROC\n"168<< "#define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN"169<< ", FAST_VECTOR_UNALIGN, MVENDORID, MARCHID, MIMPID)\n"170<< "#endif\n\n";171172// Iterate on all definition records.173for (const Record *Rec :174RK.getAllDerivedDefinitionsIfDefined("RISCVProcessorModel")) {175const std::vector<const Record *> &Features =176Rec->getValueAsListOfDefs("Features");177bool FastScalarUnalignedAccess = any_of(Features, [&](auto &Feature) {178return Feature->getValueAsString("Name") == "unaligned-scalar-mem";179});180181bool FastVectorUnalignedAccess = any_of(Features, [&](auto &Feature) {182return Feature->getValueAsString("Name") == "unaligned-vector-mem";183});184185OS << "PROC(" << Rec->getName() << ", {\"" << Rec->getValueAsString("Name")186<< "\"}, {\"";187188StringRef MArch = Rec->getValueAsString("DefaultMarch");189190// Compute MArch from features if we don't specify it.191if (MArch.empty())192printMArch(OS, Features);193else194OS << MArch;195196uint32_t MVendorID = Rec->getValueAsInt("MVendorID");197uint64_t MArchID = Rec->getValueAsInt("MArchID");198uint64_t MImpID = Rec->getValueAsInt("MImpID");199200OS << "\"}, " << FastScalarUnalignedAccess << ", "201<< FastVectorUnalignedAccess;202OS << ", " << format_hex(MVendorID, 10);203OS << ", " << format_hex(MArchID, 18);204OS << ", " << format_hex(MImpID, 18);205OS << ")\n";206}207OS << "\n#undef PROC\n";208OS << "\n";209OS << "#ifndef TUNE_PROC\n"210<< "#define TUNE_PROC(ENUM, NAME)\n"211<< "#endif\n\n";212213for (const Record *Rec :214RK.getAllDerivedDefinitionsIfDefined("RISCVTuneProcessorModel")) {215OS << "TUNE_PROC(" << Rec->getName() << ", "216<< "\"" << Rec->getValueAsString("Name") << "\")\n";217}218219OS << "\n#undef TUNE_PROC\n";220}221222static void emitRISCVExtensionBitmask(const RecordKeeper &RK, raw_ostream &OS) {223std::vector<const Record *> Extensions =224RK.getAllDerivedDefinitionsIfDefined("RISCVExtensionBitmask");225llvm::sort(Extensions, [](const Record *Rec1, const Record *Rec2) {226unsigned GroupID1 = Rec1->getValueAsInt("GroupID");227unsigned GroupID2 = Rec2->getValueAsInt("GroupID");228if (GroupID1 != GroupID2)229return GroupID1 < GroupID2;230231return Rec1->getValueAsInt("BitPos") < Rec2->getValueAsInt("BitPos");232});233234#ifndef NDEBUG235llvm::DenseSet<std::pair<uint64_t, uint64_t>> Seen;236#endif237238OS << "#ifdef GET_RISCVExtensionBitmaskTable_IMPL\n";239OS << "static const RISCVExtensionBitmask ExtensionBitmask[]={\n";240for (const Record *Rec : Extensions) {241unsigned GroupIDVal = Rec->getValueAsInt("GroupID");242unsigned BitPosVal = Rec->getValueAsInt("BitPos");243244StringRef ExtName = Rec->getValueAsString("Name");245ExtName.consume_front("experimental-");246247#ifndef NDEBUG248assert(Seen.insert({GroupIDVal, BitPosVal}).second && "duplicated bitmask");249#endif250251OS.indent(4) << "{"252<< "\"" << ExtName << "\""253<< ", " << GroupIDVal << ", " << BitPosVal << "ULL"254<< "},\n";255}256OS << "};\n";257OS << "#endif\n";258}259260static void emitRiscvTargetDef(const RecordKeeper &RK, raw_ostream &OS) {261emitRISCVExtensions(RK, OS);262emitRISCVProfiles(RK, OS);263emitRISCVProcs(RK, OS);264emitRISCVExtensionBitmask(RK, OS);265}266267static TableGen::Emitter::Opt X("gen-riscv-target-def", emitRiscvTargetDef,268"Generate the list of CPUs and extensions for "269"RISC-V");270271272