[TableGen] Emit better error message for duplicate Subtarget features. (#102090)

- Keep track of last definition of a feature in a `DenseMap` and use 
  it to report a better error message when a duplicate feature is found.
- Use StringMap instead of a std::map in `EmitStageAndOperandCycleData`
- Add a unit test to check if duplicate names are flagged.
This commit is contained in:
Rahul Joshi 2024-08-06 14:39:04 -07:00 committed by GitHub
parent 28fa83f8d4
commit 4c97c52fe0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 23 additions and 8 deletions

View File

@ -0,0 +1,12 @@
// RUN: not llvm-tblgen -gen-subtarget -I %p/../../include %s 2>&1 | FileCheck %s -DFILE=%s
// Verify that subtarget features with same names result in an error.
include "llvm/Target/Target.td"
def MyTarget : Target;
def FeatureA : SubtargetFeature<"NameA", "", "", "">;
// CHECK: [[FILE]]:[[@LINE+2]]:5: error: Feature `NameA` already defined.
// CHECK: [[FILE]]:[[@LINE-3]]:5: note: Previous definition here.
def FeatureB : SubtargetFeature<"NameA", "", "", "">;

View File

@ -14,9 +14,11 @@
#include "Common/CodeGenSchedule.h" #include "Common/CodeGenSchedule.h"
#include "Common/CodeGenTarget.h" #include "Common/CodeGenTarget.h"
#include "Common/PredicateExpander.h" #include "Common/PredicateExpander.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCInstrItineraries.h" #include "llvm/MC/MCInstrItineraries.h"
#include "llvm/MC/MCSchedule.h" #include "llvm/MC/MCSchedule.h"
@ -31,8 +33,6 @@
#include <cassert> #include <cassert>
#include <cstdint> #include <cstdint>
#include <iterator> #include <iterator>
#include <map>
#include <set>
#include <string> #include <string>
#include <vector> #include <vector>
@ -259,8 +259,8 @@ unsigned SubtargetEmitter::FeatureKeyValues(
llvm::sort(FeatureList, LessRecordFieldName()); llvm::sort(FeatureList, LessRecordFieldName());
// Check that there are no duplicate keys // Check that there are no duplicate features.
std::set<StringRef> UniqueKeys; DenseMap<StringRef, const Record *> UniqueFeatures;
// Begin feature table // Begin feature table
OS << "// Sorted (by key) array of values for CPU features.\n" OS << "// Sorted (by key) array of values for CPU features.\n"
@ -291,9 +291,12 @@ unsigned SubtargetEmitter::FeatureKeyValues(
OS << " },\n"; OS << " },\n";
++NumFeatures; ++NumFeatures;
if (!UniqueKeys.insert(CommandLineName).second) auto [It, Inserted] = UniqueFeatures.insert({CommandLineName, Feature});
PrintFatalError("Duplicate key in SubtargetFeatureKV: " + if (!Inserted) {
CommandLineName); PrintError(Feature, "Feature `" + CommandLineName + "` already defined.");
const Record *Previous = It->second;
PrintFatalNote(Previous, "Previous definition here.");
}
} }
// End feature table // End feature table
@ -494,7 +497,7 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(
// operand cycles, and pipeline bypass tables. Then add the new Itinerary // operand cycles, and pipeline bypass tables. Then add the new Itinerary
// object with computed offsets to the ProcItinLists result. // object with computed offsets to the ProcItinLists result.
unsigned StageCount = 1, OperandCycleCount = 1; unsigned StageCount = 1, OperandCycleCount = 1;
std::map<std::string, unsigned> ItinStageMap, ItinOperandMap; StringMap<unsigned> ItinStageMap, ItinOperandMap;
for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) { for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) {
// Add process itinerary to the list. // Add process itinerary to the list.
std::vector<InstrItinerary> &ItinList = ProcItinLists.emplace_back(); std::vector<InstrItinerary> &ItinList = ProcItinLists.emplace_back();