mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01: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. llvm-svn: 190793
This commit is contained in:
parent
aa157f020e
commit
efd2bb2366
@ -125,6 +125,13 @@ namespace {
|
||||
class AsmMatcherInfo;
|
||||
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 {
|
||||
RecordKeeper &Records;
|
||||
public:
|
||||
@ -185,7 +192,7 @@ struct ClassInfo {
|
||||
std::string ParserMethod;
|
||||
|
||||
/// 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.
|
||||
std::string DiagnosticType;
|
||||
@ -213,11 +220,11 @@ public:
|
||||
if (!isRegisterClass() || !RHS.isRegisterClass())
|
||||
return false;
|
||||
|
||||
std::set<Record*> Tmp;
|
||||
std::insert_iterator< std::set<Record*> > II(Tmp, Tmp.begin());
|
||||
RegisterSet Tmp;
|
||||
std::insert_iterator<RegisterSet> II(Tmp, Tmp.begin());
|
||||
std::set_intersection(Registers.begin(), Registers.end(),
|
||||
RHS.Registers.begin(), RHS.Registers.end(),
|
||||
II);
|
||||
II, LessRecordByID());
|
||||
|
||||
return !Tmp.empty();
|
||||
}
|
||||
@ -1057,6 +1064,18 @@ AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) {
|
||||
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::
|
||||
buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
|
||||
const std::vector<CodeGenRegister*> &Registers =
|
||||
@ -1064,33 +1083,35 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
|
||||
ArrayRef<CodeGenRegisterClass*> RegClassList =
|
||||
Target.getRegBank().getRegClasses();
|
||||
|
||||
typedef std::set<RegisterSet, LessRegisterSet> RegisterSetSet;
|
||||
|
||||
// The register sets used for matching.
|
||||
std::set< std::set<Record*> > RegisterSets;
|
||||
RegisterSetSet RegisterSets;
|
||||
|
||||
// Gather the defined sets.
|
||||
for (ArrayRef<CodeGenRegisterClass*>::const_iterator it =
|
||||
RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it)
|
||||
RegisterSets.insert(std::set<Record*>(
|
||||
RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it)
|
||||
RegisterSets.insert(RegisterSet(
|
||||
(*it)->getOrder().begin(), (*it)->getOrder().end()));
|
||||
|
||||
// Add any required singleton sets.
|
||||
for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(),
|
||||
ie = SingletonRegisters.end(); it != ie; ++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
|
||||
// a unique register set class), and build the mapping of registers to the set
|
||||
// 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(),
|
||||
ie = Registers.end(); it != ie; ++it) {
|
||||
const CodeGenRegister &CGR = **it;
|
||||
// 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) {
|
||||
if (!it->count(CGR.TheDef))
|
||||
continue;
|
||||
@ -1100,11 +1121,12 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::set<Record*> Tmp;
|
||||
RegisterSet Tmp;
|
||||
std::swap(Tmp, ContainingSet);
|
||||
std::insert_iterator< std::set<Record*> > II(ContainingSet,
|
||||
ContainingSet.begin());
|
||||
std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II);
|
||||
std::insert_iterator<RegisterSet> II(ContainingSet,
|
||||
ContainingSet.begin());
|
||||
std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II,
|
||||
LessRecordByID());
|
||||
}
|
||||
|
||||
if (!ContainingSet.empty()) {
|
||||
@ -1114,9 +1136,9 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
|
||||
}
|
||||
|
||||
// Construct the register classes.
|
||||
std::map<std::set<Record*>, ClassInfo*> RegisterSetClasses;
|
||||
std::map<RegisterSet, ClassInfo*, LessRegisterSet> RegisterSetClasses;
|
||||
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) {
|
||||
ClassInfo *CI = new ClassInfo();
|
||||
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,
|
||||
// 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) {
|
||||
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)
|
||||
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]);
|
||||
}
|
||||
|
||||
@ -1152,8 +1175,8 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
|
||||
Record *Def = RC.getDef();
|
||||
if (!Def)
|
||||
continue;
|
||||
ClassInfo *CI = RegisterSetClasses[std::set<Record*>(RC.getOrder().begin(),
|
||||
RC.getOrder().end())];
|
||||
ClassInfo *CI = RegisterSetClasses[RegisterSet(RC.getOrder().begin(),
|
||||
RC.getOrder().end())];
|
||||
if (CI->ValueName.empty()) {
|
||||
CI->ClassName = RC.getName();
|
||||
CI->Name = "MCK_" + RC.getName();
|
||||
@ -1165,7 +1188,7 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
|
||||
}
|
||||
|
||||
// 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)
|
||||
RegisterClasses[it->first] = RegisterSetClasses[it->second];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user