diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 26e59e452f5..c9b6a8ec419 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -738,7 +738,20 @@ class AssemblerPredicate { string AssemblerCondString = cond; } - +/// TokenAlias - This class allows targets to define assembler token +/// operand aliases. That is, a token literal operand which is equivalent +/// to another, canonical, token literal. For example, ARM allows: +/// vmov.u32 s4, #0 -> vmov.i32, #0 +/// 'u32' is a more specific designator for the 32-bit integer type specifier +/// and is legal for any instruction which accepts 'i32' as a datatype suffix. +/// def : TokenAlias<".u32", ".i32">; +/// +/// This works by marking the match class of 'From' as a subclass of the +/// match class of 'To'. +class TokenAlias { + string FromToken = From; + string ToToken = To; +} /// MnemonicAlias - This class allows targets to define assembler mnemonic /// aliases. This should be used when all forms of one mnemonic are accepted diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index e83fa0de9da..5ef0db905cc 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -252,11 +252,6 @@ public: switch (Kind) { case Invalid: assert(0 && "Invalid kind!"); - case Token: - // Tokens are comparable by value. - // - // FIXME: Compare by enum value. - return ValueName < RHS.ValueName; default: // This class precedes the RHS if it is a proper subset of the RHS. @@ -1304,6 +1299,17 @@ void AsmMatcherInfo::BuildInfo() { II->BuildAliasResultOperands(); } + // Process token alias definitions and set up the associated superclass + // information. + std::vector AllTokenAliases = + Records.getAllDerivedDefinitions("TokenAlias"); + for (unsigned i = 0, e = AllTokenAliases.size(); i != e; ++i) { + Record *Rec = AllTokenAliases[i]; + ClassInfo *FromClass = getTokenClass(Rec->getValueAsString("FromToken")); + ClassInfo *ToClass = getTokenClass(Rec->getValueAsString("ToToken")); + FromClass->SuperClasses.push_back(ToClass); + } + // Reorder classes so that classes precede super classes. std::sort(Classes.begin(), Classes.end(), less_ptr()); } @@ -1676,7 +1682,8 @@ static void EmitValidateOperandClass(AsmMatcherInfo &Info, // Check for Token operands first. OS << " if (Operand.isToken())\n"; - OS << " return matchTokenString(Operand.getToken()) == Kind;\n\n"; + OS << " return isSubclass(matchTokenString(Operand.getToken()), Kind);" + << "\n\n"; // Check for register operands, including sub-classes. OS << " if (Operand.isReg()) {\n"; @@ -1729,32 +1736,30 @@ static void EmitIsSubclass(CodeGenTarget &Target, ie = Infos.end(); it != ie; ++it) { ClassInfo &A = **it; - if (A.Kind != ClassInfo::Token) { - std::vector SuperClasses; - for (std::vector::iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - ClassInfo &B = **it; + std::vector SuperClasses; + for (std::vector::iterator it = Infos.begin(), + ie = Infos.end(); it != ie; ++it) { + ClassInfo &B = **it; - if (&A != &B && A.isSubsetOf(B)) - SuperClasses.push_back(B.Name); - } - - if (SuperClasses.empty()) - continue; - - OS << "\n case " << A.Name << ":\n"; - - if (SuperClasses.size() == 1) { - OS << " return B == " << SuperClasses.back() << ";\n"; - continue; - } - - OS << " switch (B) {\n"; - OS << " default: return false;\n"; - for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i) - OS << " case " << SuperClasses[i] << ": return true;\n"; - OS << " }\n"; + if (&A != &B && A.isSubsetOf(B)) + SuperClasses.push_back(B.Name); } + + if (SuperClasses.empty()) + continue; + + OS << "\n case " << A.Name << ":\n"; + + if (SuperClasses.size() == 1) { + OS << " return B == " << SuperClasses.back() << ";\n"; + continue; + } + + OS << " switch (B) {\n"; + OS << " default: return false;\n"; + for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i) + OS << " case " << SuperClasses[i] << ": return true;\n"; + OS << " }\n"; } OS << " }\n"; OS << "}\n\n";