[TableGen] Add 'register alternative name matching' support

Summary:
This adds a new attribute which targets can set in TableGen which causes a function to be generated which matches register alternative names. This is very similar to `ShouldEmitMatchRegisterName`, except it works on alt names.

This patch is currently used by the out of tree part of the AVR backend. It reduces code duplication greatly, and has the effect that you do not need to hardcode altname to register mappings in C++.

It will not work on targets which have registers which share the same aliases.

Reviewers: stoklund, arsenm, dsanders, hfinkel, vkalintiris

Subscribers: hfinkel, dylanmckay, llvm-commits

Differential Revision: http://reviews.llvm.org/D16312

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@259636 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dylan McKay 2016-02-03 10:30:16 +00:00
parent 2eb4c2ae70
commit f4afd08249
2 changed files with 42 additions and 0 deletions

View File

@ -941,6 +941,14 @@ class AsmParser {
// written register name matcher
bit ShouldEmitMatchRegisterName = 1;
// Set to true if the target needs a generated 'alternative register name'
// matcher.
//
// This generates a function which can be used to lookup registers from
// their aliases. This function will fail when called on targets where
// several registers share the same alias (i.e. not a 1:1 mapping).
bit ShouldEmitMatchRegisterAltName = 0;
// HasMnemonicFirst - Set to false if target instructions don't always
// start with a mnemonic as the first token.
bit HasMnemonicFirst = 1;

View File

@ -2276,6 +2276,37 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser,
OS << "}\n\n";
}
/// Emit the function to match a string to the target
/// specific register enum.
static void emitMatchRegisterAltName(CodeGenTarget &Target, Record *AsmParser,
raw_ostream &OS) {
// Construct the match list.
std::vector<StringMatcher::StringPair> Matches;
const auto &Regs = Target.getRegBank().getRegisters();
for (const CodeGenRegister &Reg : Regs) {
auto AltNames = Reg.TheDef->getValueAsListOfStrings("AltNames");
for (auto AltName : AltNames) {
AltName = StringRef(AltName).trim();
// don't handle empty alternative names
if (AltName.empty())
continue;
Matches.emplace_back(AltName,
"return " + utostr(Reg.EnumValue) + ";");
}
}
OS << "static unsigned MatchRegisterAltName(StringRef Name) {\n";
StringMatcher("Name", Matches, OS).Emit();
OS << " return 0;\n";
OS << "}\n\n";
}
static const char *getMinimalTypeForRange(uint64_t Range) {
assert(Range <= 0xFFFFFFFFFFFFFFFFULL && "Enum too large");
if (Range > 0xFFFFFFFFULL)
@ -2816,6 +2847,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
if (AsmParser->getValueAsBit("ShouldEmitMatchRegisterName"))
emitMatchRegisterName(Target, AsmParser, OS);
if (AsmParser->getValueAsBit("ShouldEmitMatchRegisterAltName"))
emitMatchRegisterAltName(Target, AsmParser, OS);
OS << "#endif // GET_REGISTER_MATCHER\n\n";
OS << "\n#ifdef GET_SUBTARGET_FEATURE_NAME\n";