mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 07:31:28 +00:00
[TableGen] Handle duplicate rules in combiners (#69296)
We would crash when a rule was accidentally added twice to a combiner. This patch adds a warning instead to skip the already-processed rules.
This commit is contained in:
parent
0841955bf3
commit
d2b74d7e42
@ -0,0 +1,30 @@
|
||||
// RUN: llvm-tblgen -I %p/../../../../include -gen-global-isel-combiner \
|
||||
// RUN: -combiners=Combiner %s 2>&1 | FileCheck %s
|
||||
|
||||
include "llvm/Target/Target.td"
|
||||
include "llvm/Target/GlobalISel/Combine.td"
|
||||
|
||||
// Check we don't crash if a combine is present twice in the list.
|
||||
|
||||
def MyTargetISA : InstrInfo;
|
||||
def MyTarget : Target { let InstructionSet = MyTargetISA; }
|
||||
|
||||
def dummy;
|
||||
|
||||
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: warning: skipping rule 'Foo' because it has already been processed
|
||||
def Foo : GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (G_ZEXT $root, $x)),
|
||||
(apply (G_TRUNC $root, $x))>;
|
||||
|
||||
def Bar : GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (G_TRUNC $root, $x)),
|
||||
(apply (G_ZEXT $root, $x))>;
|
||||
|
||||
def FooBar : GICombineGroup<[ Foo, Bar ]>;
|
||||
|
||||
def Combiner: GICombiner<"GenMyCombiner", [
|
||||
FooBar,
|
||||
Foo
|
||||
]>;
|
@ -3307,6 +3307,10 @@ class GICombinerEmitter final : public GlobalISelMatchTableExecutorEmitter {
|
||||
// combine rule used to disable/enable it.
|
||||
std::vector<std::pair<unsigned, std::string>> AllCombineRules;
|
||||
|
||||
// Keep track of all rules we've seen so far to ensure we don't process
|
||||
// the same rule twice.
|
||||
StringSet<> RulesSeen;
|
||||
|
||||
MatchTable buildMatchTable(MutableArrayRef<RuleMatcher> Rules);
|
||||
|
||||
void emitRuleConfigImpl(raw_ostream &OS);
|
||||
@ -3624,27 +3628,37 @@ void GICombinerEmitter::gatherRules(
|
||||
std::vector<RuleMatcher> &ActiveRules,
|
||||
const std::vector<Record *> &&RulesAndGroups) {
|
||||
for (Record *Rec : RulesAndGroups) {
|
||||
if (Rec->isValueUnset("Rules")) {
|
||||
AllCombineRules.emplace_back(NextRuleID, Rec->getName().str());
|
||||
CombineRuleBuilder CRB(Target, SubtargetFeatures, *Rec, NextRuleID++,
|
||||
ActiveRules);
|
||||
|
||||
if (!CRB.parseAll()) {
|
||||
assert(ErrorsPrinted && "Parsing failed without errors!");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (StopAfterParse) {
|
||||
CRB.print(outs());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!CRB.emitRuleMatchers()) {
|
||||
assert(ErrorsPrinted && "Emission failed without errors!");
|
||||
continue;
|
||||
}
|
||||
} else
|
||||
if (!Rec->isValueUnset("Rules")) {
|
||||
gatherRules(ActiveRules, Rec->getValueAsListOfDefs("Rules"));
|
||||
continue;
|
||||
}
|
||||
|
||||
StringRef RuleName = Rec->getName();
|
||||
if (!RulesSeen.insert(RuleName).second) {
|
||||
PrintWarning(Rec->getLoc(),
|
||||
"skipping rule '" + Rec->getName() +
|
||||
"' because it has already been processed");
|
||||
continue;
|
||||
}
|
||||
|
||||
AllCombineRules.emplace_back(NextRuleID, Rec->getName().str());
|
||||
CombineRuleBuilder CRB(Target, SubtargetFeatures, *Rec, NextRuleID++,
|
||||
ActiveRules);
|
||||
|
||||
if (!CRB.parseAll()) {
|
||||
assert(ErrorsPrinted && "Parsing failed without errors!");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (StopAfterParse) {
|
||||
CRB.print(outs());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!CRB.emitRuleMatchers()) {
|
||||
assert(ErrorsPrinted && "Emission failed without errors!");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user