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