mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-29 10:32:47 +00:00
TableGen: give asm match classes deterministic order.
TableGen was sorting the entries in some of its internal data structures by pointer. This order filtered through to the final matching table and affected the diagnostics produced on bad assembly occasionally. It also turns out STL algorithms are ridiculously easy to misuse on containers with custom order methods. (No bugs before, or now that I know of, but plenty in the middle). This should fix the sanitizer bot, which ends up with weird pointers. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190793 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6dd670af75
commit
03f9197d62
@ -125,6 +125,13 @@ namespace {
|
|||||||
class AsmMatcherInfo;
|
class AsmMatcherInfo;
|
||||||
struct SubtargetFeatureInfo;
|
struct SubtargetFeatureInfo;
|
||||||
|
|
||||||
|
// Register sets are used as keys in some second-order sets TableGen creates
|
||||||
|
// when generating its data structures. This means that the order of two
|
||||||
|
// RegisterSets can be seen in the outputted AsmMatcher tables occasionally, and
|
||||||
|
// can even affect compiler output (at least seen in diagnostics produced when
|
||||||
|
// all matches fail). So we use a type that sorts them consistently.
|
||||||
|
typedef std::set<Record*, LessRecordByID> RegisterSet;
|
||||||
|
|
||||||
class AsmMatcherEmitter {
|
class AsmMatcherEmitter {
|
||||||
RecordKeeper &Records;
|
RecordKeeper &Records;
|
||||||
public:
|
public:
|
||||||
@ -185,7 +192,7 @@ struct ClassInfo {
|
|||||||
std::string ParserMethod;
|
std::string ParserMethod;
|
||||||
|
|
||||||
/// For register classes, the records for all the registers in this class.
|
/// For register classes, the records for all the registers in this class.
|
||||||
std::set<Record*> Registers;
|
RegisterSet Registers;
|
||||||
|
|
||||||
/// For custom match classes, he diagnostic kind for when the predicate fails.
|
/// For custom match classes, he diagnostic kind for when the predicate fails.
|
||||||
std::string DiagnosticType;
|
std::string DiagnosticType;
|
||||||
@ -213,11 +220,11 @@ public:
|
|||||||
if (!isRegisterClass() || !RHS.isRegisterClass())
|
if (!isRegisterClass() || !RHS.isRegisterClass())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::set<Record*> Tmp;
|
RegisterSet Tmp;
|
||||||
std::insert_iterator< std::set<Record*> > II(Tmp, Tmp.begin());
|
std::insert_iterator<RegisterSet> II(Tmp, Tmp.begin());
|
||||||
std::set_intersection(Registers.begin(), Registers.end(),
|
std::set_intersection(Registers.begin(), Registers.end(),
|
||||||
RHS.Registers.begin(), RHS.Registers.end(),
|
RHS.Registers.begin(), RHS.Registers.end(),
|
||||||
II);
|
II, LessRecordByID());
|
||||||
|
|
||||||
return !Tmp.empty();
|
return !Tmp.empty();
|
||||||
}
|
}
|
||||||
@ -1057,6 +1064,18 @@ AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) {
|
|||||||
PrintFatalError(Rec->getLoc(), "operand has no match class!");
|
PrintFatalError(Rec->getLoc(), "operand has no match class!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct LessRegisterSet {
|
||||||
|
bool operator() (const RegisterSet &LHS, const RegisterSet & RHS) {
|
||||||
|
// std::set<T> defines its own compariso "operator<", but it
|
||||||
|
// performs a lexicographical comparison by T's innate comparison
|
||||||
|
// for some reason. We don't want non-deterministic pointer
|
||||||
|
// comparisons so use this instead.
|
||||||
|
return std::lexicographical_compare(LHS.begin(), LHS.end(),
|
||||||
|
RHS.begin(), RHS.end(),
|
||||||
|
LessRecordByID());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void AsmMatcherInfo::
|
void AsmMatcherInfo::
|
||||||
buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
|
buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
|
||||||
const std::vector<CodeGenRegister*> &Registers =
|
const std::vector<CodeGenRegister*> &Registers =
|
||||||
@ -1064,33 +1083,35 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
|
|||||||
ArrayRef<CodeGenRegisterClass*> RegClassList =
|
ArrayRef<CodeGenRegisterClass*> RegClassList =
|
||||||
Target.getRegBank().getRegClasses();
|
Target.getRegBank().getRegClasses();
|
||||||
|
|
||||||
|
typedef std::set<RegisterSet, LessRegisterSet> RegisterSetSet;
|
||||||
|
|
||||||
// The register sets used for matching.
|
// The register sets used for matching.
|
||||||
std::set< std::set<Record*> > RegisterSets;
|
RegisterSetSet RegisterSets;
|
||||||
|
|
||||||
// Gather the defined sets.
|
// Gather the defined sets.
|
||||||
for (ArrayRef<CodeGenRegisterClass*>::const_iterator it =
|
for (ArrayRef<CodeGenRegisterClass*>::const_iterator it =
|
||||||
RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it)
|
RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it)
|
||||||
RegisterSets.insert(std::set<Record*>(
|
RegisterSets.insert(RegisterSet(
|
||||||
(*it)->getOrder().begin(), (*it)->getOrder().end()));
|
(*it)->getOrder().begin(), (*it)->getOrder().end()));
|
||||||
|
|
||||||
// Add any required singleton sets.
|
// Add any required singleton sets.
|
||||||
for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(),
|
for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(),
|
||||||
ie = SingletonRegisters.end(); it != ie; ++it) {
|
ie = SingletonRegisters.end(); it != ie; ++it) {
|
||||||
Record *Rec = *it;
|
Record *Rec = *it;
|
||||||
RegisterSets.insert(std::set<Record*>(&Rec, &Rec + 1));
|
RegisterSets.insert(RegisterSet(&Rec, &Rec + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Introduce derived sets where necessary (when a register does not determine
|
// Introduce derived sets where necessary (when a register does not determine
|
||||||
// a unique register set class), and build the mapping of registers to the set
|
// a unique register set class), and build the mapping of registers to the set
|
||||||
// they should classify to.
|
// they should classify to.
|
||||||
std::map<Record*, std::set<Record*> > RegisterMap;
|
std::map<Record*, RegisterSet> RegisterMap;
|
||||||
for (std::vector<CodeGenRegister*>::const_iterator it = Registers.begin(),
|
for (std::vector<CodeGenRegister*>::const_iterator it = Registers.begin(),
|
||||||
ie = Registers.end(); it != ie; ++it) {
|
ie = Registers.end(); it != ie; ++it) {
|
||||||
const CodeGenRegister &CGR = **it;
|
const CodeGenRegister &CGR = **it;
|
||||||
// Compute the intersection of all sets containing this register.
|
// Compute the intersection of all sets containing this register.
|
||||||
std::set<Record*> ContainingSet;
|
RegisterSet ContainingSet;
|
||||||
|
|
||||||
for (std::set< std::set<Record*> >::iterator it = RegisterSets.begin(),
|
for (RegisterSetSet::iterator it = RegisterSets.begin(),
|
||||||
ie = RegisterSets.end(); it != ie; ++it) {
|
ie = RegisterSets.end(); it != ie; ++it) {
|
||||||
if (!it->count(CGR.TheDef))
|
if (!it->count(CGR.TheDef))
|
||||||
continue;
|
continue;
|
||||||
@ -1100,11 +1121,12 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<Record*> Tmp;
|
RegisterSet Tmp;
|
||||||
std::swap(Tmp, ContainingSet);
|
std::swap(Tmp, ContainingSet);
|
||||||
std::insert_iterator< std::set<Record*> > II(ContainingSet,
|
std::insert_iterator<RegisterSet> II(ContainingSet,
|
||||||
ContainingSet.begin());
|
ContainingSet.begin());
|
||||||
std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II);
|
std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II,
|
||||||
|
LessRecordByID());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ContainingSet.empty()) {
|
if (!ContainingSet.empty()) {
|
||||||
@ -1114,9 +1136,9 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Construct the register classes.
|
// Construct the register classes.
|
||||||
std::map<std::set<Record*>, ClassInfo*> RegisterSetClasses;
|
std::map<RegisterSet, ClassInfo*, LessRegisterSet> RegisterSetClasses;
|
||||||
unsigned Index = 0;
|
unsigned Index = 0;
|
||||||
for (std::set< std::set<Record*> >::iterator it = RegisterSets.begin(),
|
for (RegisterSetSet::iterator it = RegisterSets.begin(),
|
||||||
ie = RegisterSets.end(); it != ie; ++it, ++Index) {
|
ie = RegisterSets.end(); it != ie; ++it, ++Index) {
|
||||||
ClassInfo *CI = new ClassInfo();
|
ClassInfo *CI = new ClassInfo();
|
||||||
CI->Kind = ClassInfo::RegisterClass0 + Index;
|
CI->Kind = ClassInfo::RegisterClass0 + Index;
|
||||||
@ -1134,13 +1156,14 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
|
|||||||
|
|
||||||
// Find the superclasses; we could compute only the subgroup lattice edges,
|
// Find the superclasses; we could compute only the subgroup lattice edges,
|
||||||
// but there isn't really a point.
|
// but there isn't really a point.
|
||||||
for (std::set< std::set<Record*> >::iterator it = RegisterSets.begin(),
|
for (RegisterSetSet::iterator it = RegisterSets.begin(),
|
||||||
ie = RegisterSets.end(); it != ie; ++it) {
|
ie = RegisterSets.end(); it != ie; ++it) {
|
||||||
ClassInfo *CI = RegisterSetClasses[*it];
|
ClassInfo *CI = RegisterSetClasses[*it];
|
||||||
for (std::set< std::set<Record*> >::iterator it2 = RegisterSets.begin(),
|
for (RegisterSetSet::iterator it2 = RegisterSets.begin(),
|
||||||
ie2 = RegisterSets.end(); it2 != ie2; ++it2)
|
ie2 = RegisterSets.end(); it2 != ie2; ++it2)
|
||||||
if (*it != *it2 &&
|
if (*it != *it2 &&
|
||||||
std::includes(it2->begin(), it2->end(), it->begin(), it->end()))
|
std::includes(it2->begin(), it2->end(), it->begin(), it->end(),
|
||||||
|
LessRecordByID()))
|
||||||
CI->SuperClasses.push_back(RegisterSetClasses[*it2]);
|
CI->SuperClasses.push_back(RegisterSetClasses[*it2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1152,8 +1175,8 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
|
|||||||
Record *Def = RC.getDef();
|
Record *Def = RC.getDef();
|
||||||
if (!Def)
|
if (!Def)
|
||||||
continue;
|
continue;
|
||||||
ClassInfo *CI = RegisterSetClasses[std::set<Record*>(RC.getOrder().begin(),
|
ClassInfo *CI = RegisterSetClasses[RegisterSet(RC.getOrder().begin(),
|
||||||
RC.getOrder().end())];
|
RC.getOrder().end())];
|
||||||
if (CI->ValueName.empty()) {
|
if (CI->ValueName.empty()) {
|
||||||
CI->ClassName = RC.getName();
|
CI->ClassName = RC.getName();
|
||||||
CI->Name = "MCK_" + RC.getName();
|
CI->Name = "MCK_" + RC.getName();
|
||||||
@ -1165,7 +1188,7 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Populate the map for individual registers.
|
// Populate the map for individual registers.
|
||||||
for (std::map<Record*, std::set<Record*> >::iterator it = RegisterMap.begin(),
|
for (std::map<Record*, RegisterSet>::iterator it = RegisterMap.begin(),
|
||||||
ie = RegisterMap.end(); it != ie; ++it)
|
ie = RegisterMap.end(); it != ie; ++it)
|
||||||
RegisterClasses[it->first] = RegisterSetClasses[it->second];
|
RegisterClasses[it->first] = RegisterSetClasses[it->second];
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user