diff --git a/llvm/include/llvm/TableGen/CodeGenHelpers.h b/llvm/include/llvm/TableGen/CodeGenHelpers.h index e22c6d4f6d390..053f7e4aab866 100644 --- a/llvm/include/llvm/TableGen/CodeGenHelpers.h +++ b/llvm/include/llvm/TableGen/CodeGenHelpers.h @@ -20,18 +20,37 @@ #include namespace llvm { -// Simple RAII helper for emitting ifdef-undef-endif scope. +// Simple RAII helper for emitting ifdef-undef-endif scope. `LateUndef` controls +// whether the undef is emitted at the start of the scope (false) or at the end +// of the scope (true). class IfDefEmitter { public: - IfDefEmitter(raw_ostream &OS, StringRef Name) : Name(Name.str()), OS(OS) { - OS << "#ifdef " << Name << "\n" - << "#undef " << Name << "\n\n"; + IfDefEmitter(raw_ostream &OS, StringRef Name, bool LateUndef = false) + : Name(Name.str()), OS(OS), LateUndef(LateUndef) { + OS << "#ifdef " << Name << "\n"; + if (!LateUndef) + OS << "#undef " << Name << "\n"; + OS << "\n"; + } + ~IfDefEmitter() { close(); } + + // Explicit function to close the ifdef scopes. + void close() { + if (Closed) + return; + + OS << "\n"; + if (LateUndef) + OS << "#undef " << Name << "\n"; + OS << "#endif // " << Name << "\n\n"; + Closed = true; } - ~IfDefEmitter() { OS << "\n#endif // " << Name << "\n\n"; } private: std::string Name; raw_ostream &OS; + bool LateUndef; + bool Closed = false; }; // Simple RAII helper for emitting header include guard (ifndef-define-endif). @@ -42,11 +61,20 @@ class IncludeGuardEmitter { OS << "#ifndef " << Name << "\n" << "#define " << Name << "\n\n"; } - ~IncludeGuardEmitter() { OS << "\n#endif // " << Name << "\n"; } + ~IncludeGuardEmitter() { close(); } + + // Explicit function to close the ifdef scopes. + void close() { + if (Closed) + return; + OS << "\n#endif // " << Name << "\n\n"; + Closed = true; + } private: std::string Name; raw_ostream &OS; + bool Closed = false; }; // Simple RAII helper for emitting namespace scope. Name can be a single @@ -64,7 +92,9 @@ class NamespaceEmitter { // Explicit function to close the namespace scopes. void close() { - if (!Closed && !Name.empty()) + if (Closed) + return; + if (!Name.empty()) OS << "} // namespace " << Name << "\n"; Closed = true; } diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp index 2f15cc8c76548..c3fb089d3f608 100644 --- a/llvm/utils/TableGen/SubtargetEmitter.cpp +++ b/llvm/utils/TableGen/SubtargetEmitter.cpp @@ -27,6 +27,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TableGen/CodeGenHelpers.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/StringToOffsetTable.h" @@ -75,7 +76,15 @@ class SubtargetEmitter : TargetFeaturesEmitter { CodeGenTarget TGT; CodeGenSchedModels &SchedModels; + FeatureMapTy emitEnums(raw_ostream &OS); void emitSubtargetInfoMacroCalls(raw_ostream &OS); + std::tuple + emitMCDesc(raw_ostream &OS, const FeatureMapTy &FeatureMap); + void emitTargetDesc(raw_ostream &OS); + void emitHeader(raw_ostream &OS); + void emitCtor(raw_ostream &OS, unsigned NumNames, unsigned NumFeatures, + unsigned NumProcs); + unsigned featureKeyValues(raw_ostream &OS, const FeatureMapTy &FeatureMap); unsigned cpuKeyValues(raw_ostream &OS, const FeatureMapTy &FeatureMap); unsigned cpuNames(raw_ostream &OS); @@ -141,7 +150,9 @@ class SubtargetEmitter : TargetFeaturesEmitter { /// Emit some information about the SubtargetFeature as calls to a macro so /// that they can be used from C++. void SubtargetEmitter::emitSubtargetInfoMacroCalls(raw_ostream &OS) { - OS << "\n#ifdef GET_SUBTARGETINFO_MACRO\n"; + // Undef the GET_SUBTARGETINFO_MACRO macro at the end of the scope since its + // used within the scope. + IfDefEmitter IfDefMacro(OS, "GET_SUBTARGETINFO_MACRO", /*LateUndef=*/true); std::vector FeatureList = Records.getAllDerivedDefinitions("SubtargetFeature"); @@ -167,14 +178,6 @@ void SubtargetEmitter::emitSubtargetInfoMacroCalls(raw_ostream &OS) { OS << "GET_SUBTARGETINFO_MACRO(" << FieldName << ", " << Default << ", " << Getter << ")\n"; } - OS << "#undef GET_SUBTARGETINFO_MACRO\n"; - OS << "#endif // GET_SUBTARGETINFO_MACRO\n\n"; - - OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n"; - OS << "#undef GET_SUBTARGETINFO_MC_DESC\n\n"; - - if (Target == "AArch64") - OS << "#include \"llvm/TargetParser/AArch64TargetParser.h\"\n\n"; } // @@ -440,26 +443,24 @@ void SubtargetEmitter::emitStageAndOperandCycleData( continue; StringRef Name = ProcModel.ItinsDef->getName(); - OS << "\n// Functional units for \"" << Name << "\"\n" - << "namespace " << Name << "FU {\n"; + OS << "\n// Functional units for \"" << Name << "\"\n"; + NamespaceEmitter FUNamespace(OS, (Name + Twine("FU")).str()); for (const auto &[Idx, FU] : enumerate(FUs)) OS << " const InstrStage::FuncUnits " << FU->getName() << " = 1ULL << " << Idx << ";\n"; - OS << "} // end namespace " << Name << "FU\n"; + FUNamespace.close(); ConstRecVec BPs = ProcModel.ItinsDef->getValueAsListOfDefs("BP"); if (BPs.empty()) continue; - OS << "\n// Pipeline forwarding paths for itineraries \"" << Name << "\"\n" - << "namespace " << Name << "Bypass {\n"; + OS << "\n// Pipeline forwarding paths for itineraries \"" << Name << "\"\n"; + NamespaceEmitter BypassNamespace(OS, (Name + Twine("Bypass")).str()); OS << " const unsigned NoBypass = 0;\n"; for (const auto &[Idx, BP] : enumerate(BPs)) OS << " const unsigned " << BP->getName() << " = 1 << " << Idx << ";\n"; - - OS << "} // end namespace " << Name << "Bypass\n"; } // Begin stages table @@ -1940,13 +1941,13 @@ void SubtargetEmitter::parseFeaturesFunction(raw_ostream &OS) { } void SubtargetEmitter::emitGenMCSubtargetInfo(raw_ostream &OS) { - OS << "namespace " << Target << "_MC {\n" - << "unsigned resolveVariantSchedClassImpl(unsigned SchedClass,\n" + NamespaceEmitter NS(OS, (Target + Twine("_MC")).str()); + OS << "unsigned resolveVariantSchedClassImpl(unsigned SchedClass,\n" << " const MCInst *MI, const MCInstrInfo *MCII, " << "const MCSubtargetInfo &STI, unsigned CPUID) {\n"; emitSchedModelHelpersImpl(OS, /* OnlyExpandMCPredicates */ true); OS << "}\n"; - OS << "} // end namespace " << Target << "_MC\n\n"; + NS.close(); OS << "struct " << Target << "GenMCSubtargetInfo : public MCSubtargetInfo {\n"; @@ -1982,8 +1983,7 @@ void SubtargetEmitter::emitGenMCSubtargetInfo(raw_ostream &OS) { } void SubtargetEmitter::emitMcInstrAnalysisPredicateFunctions(raw_ostream &OS) { - OS << "\n#ifdef GET_STIPREDICATE_DECLS_FOR_MC_ANALYSIS\n"; - OS << "#undef GET_STIPREDICATE_DECLS_FOR_MC_ANALYSIS\n\n"; + IfDefEmitter IfDefDecls(OS, "GET_STIPREDICATE_DECLS_FOR_MC_ANALYSIS"); STIPredicateExpander PE(Target, /*Indent=*/0); PE.setExpandForMC(true); @@ -1991,37 +1991,29 @@ void SubtargetEmitter::emitMcInstrAnalysisPredicateFunctions(raw_ostream &OS) { for (const STIPredicateFunction &Fn : SchedModels.getSTIPredicates()) PE.expandSTIPredicate(OS, Fn); - OS << "#endif // GET_STIPREDICATE_DECLS_FOR_MC_ANALYSIS\n\n"; - - OS << "\n#ifdef GET_STIPREDICATE_DEFS_FOR_MC_ANALYSIS\n"; - OS << "#undef GET_STIPREDICATE_DEFS_FOR_MC_ANALYSIS\n\n"; + IfDefDecls.close(); + IfDefEmitter IfDefDefs(OS, "GET_STIPREDICATE_DEFS_FOR_MC_ANALYSIS"); std::string ClassPrefix = Target + "MCInstrAnalysis"; PE.setExpandDefinition(true); PE.setClassPrefix(ClassPrefix); for (const STIPredicateFunction &Fn : SchedModels.getSTIPredicates()) PE.expandSTIPredicate(OS, Fn); - - OS << "#endif // GET_STIPREDICATE_DEFS_FOR_MC_ANALYSIS\n\n"; } -// -// SubtargetEmitter::run - Main subtarget enumeration emitter. -// -void SubtargetEmitter::run(raw_ostream &OS) { - emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS); - - OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n"; - OS << "#undef GET_SUBTARGETINFO_ENUM\n\n"; - - OS << "namespace llvm {\n"; - auto FeatureMap = enumeration(OS); - OS << "} // end namespace llvm\n\n"; - OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n"; +FeatureMapTy SubtargetEmitter::emitEnums(raw_ostream &OS) { + IfDefEmitter IfDef(OS, "GET_SUBTARGETINFO_ENUM"); + NamespaceEmitter NS(OS, "llvm"); + return enumeration(OS); +} - emitSubtargetInfoMacroCalls(OS); +std::tuple +SubtargetEmitter::emitMCDesc(raw_ostream &OS, const FeatureMapTy &FeatureMap) { + IfDefEmitter IfDef(OS, "GET_SUBTARGETINFO_MC_DESC"); + if (Target == "AArch64") + OS << "#include \"llvm/TargetParser/AArch64TargetParser.h\"\n\n"; + NamespaceEmitter LlvmNS(OS, "llvm"); - OS << "namespace llvm {\n"; unsigned NumFeatures = featureKeyValues(OS, FeatureMap); OS << "\n"; emitSchedModel(OS); @@ -2067,13 +2059,11 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "nullptr, nullptr, nullptr"; } OS << ");\n}\n\n"; + return {NumNames, NumFeatures, NumProcs}; +} - OS << "} // end namespace llvm\n\n"; - - OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n"; - - OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n"; - OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n\n"; +void SubtargetEmitter::emitTargetDesc(raw_ostream &OS) { + IfDefEmitter IfDef(OS, "GET_SUBTARGETINFO_TARGET_DESC"); OS << "#include \"llvm/ADT/BitmaskEnum.h\"\n"; OS << "#include \"llvm/Support/Debug.h\"\n"; @@ -2081,21 +2071,21 @@ void SubtargetEmitter::run(raw_ostream &OS) { if (Target == "AArch64") OS << "#include \"llvm/TargetParser/AArch64TargetParser.h\"\n\n"; parseFeaturesFunction(OS); +} - OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n"; - +void SubtargetEmitter::emitHeader(raw_ostream &OS) { // Create a TargetSubtargetInfo subclass to hide the MC layer initialization. - OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n"; - OS << "#undef GET_SUBTARGETINFO_HEADER\n\n"; + IfDefEmitter IfDef(OS, "GET_SUBTARGETINFO_HEADER"); + NamespaceEmitter LLVMNS(OS, "llvm"); std::string ClassName = Target + "GenSubtargetInfo"; - OS << "namespace llvm {\n"; OS << "class DFAPacketizer;\n"; - OS << "namespace " << Target << "_MC {\n" - << "unsigned resolveVariantSchedClassImpl(unsigned SchedClass," - << " const MCInst *MI, const MCInstrInfo *MCII, " - << "const MCSubtargetInfo &STI, unsigned CPUID);\n" - << "} // end namespace " << Target << "_MC\n\n"; + { + NamespaceEmitter MCNS(OS, (Target + Twine("_MC")).str()); + OS << "unsigned resolveVariantSchedClassImpl(unsigned SchedClass," + << " const MCInst *MI, const MCInstrInfo *MCII, " + << "const MCSubtargetInfo &STI, unsigned CPUID);\n"; + } OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n" << " explicit " << ClassName << "(const Triple &TT, StringRef CPU, " << "StringRef TuneCPU, StringRef FS);\n" @@ -2140,17 +2130,15 @@ void SubtargetEmitter::run(raw_ostream &OS) { PE.setByRef(false); for (const STIPredicateFunction &Fn : SchedModels.getSTIPredicates()) PE.expandSTIPredicate(OS, Fn); + OS << "};\n"; +} - OS << "};\n" - << "} // end namespace llvm\n\n"; - - OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n"; - - OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n"; - OS << "#undef GET_SUBTARGETINFO_CTOR\n\n"; - +void SubtargetEmitter::emitCtor(raw_ostream &OS, unsigned NumNames, + unsigned NumFeatures, unsigned NumProcs) { + IfDefEmitter IfDef(OS, "GET_SUBTARGETINFO_CTOR"); OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\n\n"; - OS << "namespace llvm {\n"; + + NamespaceEmitter LLVMNS(OS, "llvm"); OS << "extern const llvm::StringRef " << Target << "Names[];\n"; OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n"; OS << "extern const llvm::SubtargetSubTypeKV " << Target << "SubTypeKV[];\n"; @@ -2167,6 +2155,7 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "extern const unsigned " << Target << "ForwardingPaths[];\n"; } + std::string ClassName = Target + "GenSubtargetInfo"; OS << ClassName << "::" << ClassName << "(const Triple &TT, StringRef CPU, " << "StringRef TuneCPU, StringRef FS)\n"; @@ -2204,11 +2193,20 @@ void SubtargetEmitter::run(raw_ostream &OS) { emitSchedModelHelpers(ClassName, OS); emitHwModeCheck(ClassName, OS, /*IsMC=*/false); emitGetMacroFusions(ClassName, OS); +} - OS << "} // end namespace llvm\n\n"; - - OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n"; +// +// SubtargetEmitter::run - Main subtarget enumeration emitter. +// +void SubtargetEmitter::run(raw_ostream &OS) { + emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS); + auto FeatureMap = emitEnums(OS); + emitSubtargetInfoMacroCalls(OS); + auto [NumNames, NumFeatures, NumProcs] = emitMCDesc(OS, FeatureMap); + emitTargetDesc(OS); + emitHeader(OS); + emitCtor(OS, NumNames, NumFeatures, NumProcs); emitMcInstrAnalysisPredicateFunctions(OS); }