//===- ARMTargetDefEmitter.cpp - Generate data about ARM Architectures ----===// // // 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 exports information about CPUs, FPUs, architectures, // and features into a common format that can be used by both TargetParser and // the ARM and AArch64 backends. // //===----------------------------------------------------------------------===// #include "llvm/ADT/StringSet.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include using namespace llvm; static void EmitARMTargetDef(RecordKeeper &RK, raw_ostream &OS) { OS << "// Autogenerated by ARMTargetDefEmitter.cpp\n\n"; // Look through all SubtargetFeature defs with the given FieldName, and // collect the set of all Values that that FieldName is set to. auto gatherSubtargetFeatureFieldValues = [&RK](StringRef FieldName) { llvm::StringSet<> Set; for (const Record *Rec : RK.getAllDerivedDefinitions("SubtargetFeature")) { if (Rec->getValueAsString("FieldName") == FieldName) { Set.insert(Rec->getValueAsString("Value")); } } return Set; }; // Sort the extensions alphabetically, so they don't appear in tablegen order. std::vector SortedExtensions = RK.getAllDerivedDefinitions("Extension"); auto Alphabetical = [](Record *A, Record *B) -> bool { const auto MarchA = A->getValueAsString("MArchName"); const auto MarchB = B->getValueAsString("MArchName"); return MarchA.compare(MarchB) < 0; // A lexographically less than B }; std::sort(SortedExtensions.begin(), SortedExtensions.end(), Alphabetical); // The ARMProcFamilyEnum values are initialised by SubtargetFeature defs // which set the ARMProcFamily field. We can generate the enum from these defs // which look like this: // // def ProcA5 : SubtargetFeature<"a5", "ARMProcFamily", "CortexA5", // "Cortex-A5 ARM processors", []>; OS << "#ifndef ARM_PROCESSOR_FAMILY\n" << "#define ARM_PROCESSOR_FAMILY(ENUM)\n" << "#endif\n\n"; const StringSet<> ARMProcFamilyVals = gatherSubtargetFeatureFieldValues("ARMProcFamily"); for (const StringRef &Family : ARMProcFamilyVals.keys()) OS << "ARM_PROCESSOR_FAMILY(" << Family << ")\n"; OS << "\n#undef ARM_PROCESSOR_FAMILY\n\n"; OS << "#ifndef ARM_ARCHITECTURE\n" << "#define ARM_ARCHITECTURE(ENUM)\n" << "#endif\n\n"; // This should correspond to instances of the Architecture tablegen class. const StringSet<> ARMArchVals = gatherSubtargetFeatureFieldValues("ARMArch"); for (const StringRef &Arch : ARMArchVals.keys()) OS << "ARM_ARCHITECTURE(" << Arch << ")\n"; OS << "\n#undef ARM_ARCHITECTURE\n\n"; // Emit the ArchExtKind enum OS << "#ifdef EMIT_ARCHEXTKIND_ENUM\n" << "enum ArchExtKind : unsigned {\n" << " AEK_NONE = 1,\n"; for (const Record *Rec : SortedExtensions) { auto AEK = Rec->getValueAsString("ArchExtKindSpelling").upper(); if (AEK != "AEK_NONE") OS << " " << AEK << ",\n"; } OS << " AEK_NUM_EXTENSIONS\n" << "};\n" << "#undef EMIT_ARCHEXTKIND_ENUM\n" << "#endif // EMIT_ARCHEXTKIND_ENUM\n"; // Emit information for each defined Extension; used to build ArmExtKind. OS << "#ifdef EMIT_EXTENSIONS\n" << "inline constexpr ExtensionInfo Extensions[] = {\n"; for (const Record *Rec : SortedExtensions) { auto AEK = Rec->getValueAsString("ArchExtKindSpelling").upper(); OS << " "; OS << "{\"" << Rec->getValueAsString("MArchName") << "\""; if (auto Alias = Rec->getValueAsString("MArchAlias"); Alias.empty()) OS << ", {}"; else OS << ", \"" << Alias << "\""; OS << ", AArch64::" << AEK; if (AEK == "AEK_NONE") { // HACK: don't emit posfeat/negfeat strings for FMVOnlyExtensions. OS << ", {}, {}"; } else { OS << ", \"+" << Rec->getValueAsString("Name") << "\""; // posfeature OS << ", \"-" << Rec->getValueAsString("Name") << "\""; // negfeature } OS << ", " << Rec->getValueAsString("FMVBit"); OS << ", \"" << Rec->getValueAsString("FMVDependencies") << "\""; OS << ", " << (uint64_t)Rec->getValueAsInt("FMVPriority"); OS << "},\n"; }; OS << " {\"none\", {}, AArch64::AEK_NONE, {}, {}, FEAT_INIT, \"\", " "ExtensionInfo::MaxFMVPriority},\n"; OS << "};\n" << "#undef EMIT_EXTENSIONS\n" << "#endif // EMIT_EXTENSIONS\n" << "\n"; } static TableGen::Emitter::Opt X("gen-arm-target-def", EmitARMTargetDef, "Generate the ARM or AArch64 Architecture information header.");