diff --git a/llvm/docs/CodeGenerator.html b/llvm/docs/CodeGenerator.html index 3e0ac1be346c..de6a5c1ff4d8 100644 --- a/llvm/docs/CodeGenerator.html +++ b/llvm/docs/CodeGenerator.html @@ -1878,15 +1878,64 @@ We've tried hard to automate the generation of the assembler from the .td files part of the manual and repetitive data entry can be factored and shared with the compiler.

+ + +
Instruction Parsing
+ +

To Be Written

+ + + +
+ Instruction Alias Processing +
+ +
+

Once the instruction is parsed, it enters the MatchInstructionImpl function. +The MatchInstructionImpl function performs alias processing and then does +actual matching.

+ +

Alias processing if the phase that canonicalizes different lexical forms of +the same instructions down to one representation. There are several different +kinds of alias that are possible to implement and they are listed below in the +order that they are processed (which is in order from simplest/weakest to most +complex/powerful). Generally you want to use the first alias mechanism that +meets the needs of your instruction, because it will allow a more concise +description.

+ + +
Mnemonic Aliases
+ +
+ +

The first phase of alias processing is simple instruction mneomonic +remapping for classes of instructions which are allowed with two different +mneomonics. This phase is a simple and unconditionally remapping from one input +mnemonic to one output mnemonic. It isn't possible for this form of alias to +look at the operands at all, so the remapping must apply for all forms of a +given mnemonic. Mnemonic aliases are defined simply, for example X86 has: +

+ +
+
+def : MnemonicAlias<"cbw",     "cbtw">;
+def : MnemonicAlias<"smovq",   "movsq">;
+def : MnemonicAlias<"fldcww",  "fldcw">;
+def : MnemonicAlias<"fucompi", "fucomip">;
+def : MnemonicAlias<"ud2a",    "ud2">;
+
+
+ +

... and many others. With a MnemonicAlias definition, the mnemonic is +remapped simply and directly.

-
- Prolog/Epilog Code Insertion -
+
Instruction Matching
+

To Be Written

diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td index 7db2e86b3527..39f4ba722ce0 100644 --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -530,6 +530,25 @@ class AsmParser { def DefaultAsmParser : AsmParser; +/// MnemonicAlias - This class allows targets to define assembler mnemonic +/// aliases. This should be used when all forms of one mnemonic are accepted +/// with a different mnemonic. For example, X86 allows: +/// sal %al, 1 -> shl %al, 1 +/// sal %ax, %cl -> shl %ax, %cl +/// sal %eax, %cl -> shl %eax, %cl +/// etc. Though "sal" is accepted with many forms, all of them are directly +/// translated to a shl, so it can be handled with (in the case of X86, it +/// actually has one for each suffix as well): +/// def : MnemonicAlias<"sal", "shl">; +/// +/// Mnemonic aliases are mapped before any other translation in the match phase. +/// +class MnemonicAlias { + string FromMnemonic = From; + string ToMnemonic = To; +} + + //===----------------------------------------------------------------------===// // AsmWriter - This class can be implemented by targets that need to customize // the format of the .s file writer. diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index 4a8a63e2847c..0666414b5110 100644 --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -632,17 +632,6 @@ ParseInstruction(StringRef Name, SMLoc NameLoc, .Case("repe", "rep") .Case("repz", "rep") .Case("repnz", "repne") - .Case("iret", "iretl") - .Case("sysret", "sysretl") - .Case("cbw", "cbtw") - .Case("cwd", "cwtd") - .Case("cdq", "cltd") - .Case("cwde", "cwtl") - .Case("cdqe", "cltq") - .Case("smovb", "movsb") - .Case("smovw", "movsw") - .Case("smovl", "movsl") - .Case("smovq", "movsq") .Case("push", Is64Bit ? "pushq" : "pushl") .Case("pop", Is64Bit ? "popq" : "popl") .Case("pushf", Is64Bit ? "pushfq" : "pushfl") @@ -704,14 +693,10 @@ ParseInstruction(StringRef Name, SMLoc NameLoc, .Case("movzx", "movzb") // FIXME: Not correct. .Case("fildq", "fildll") .Case("fcompi", "fcomip") - .Case("fucompi", "fucomip") - .Case("fldcww", "fldcw") .Case("fnstcww", "fnstcw") .Case("fstcww", "fstcw") .Case("fnstsww", "fnstsw") .Case("fstsww", "fstsw") - .Case("verrw", "verr") - .Case("ud2a", "ud2") .Default(Name); // FIXME: Hack to recognize cmp{ss,sd,ps,pd}. diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td index 86e061647325..fd0caac48712 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -1254,3 +1254,26 @@ include "X86InstrSystem.td" // Compiler Pseudo Instructions and Pat Patterns include "X86InstrCompiler.td" +//===----------------------------------------------------------------------===// +// Assembler Aliases +//===----------------------------------------------------------------------===// + +def : MnemonicAlias<"iret", "iretl">; +def : MnemonicAlias<"sysret", "sysretl">; +def : MnemonicAlias<"cbw", "cbtw">; +def : MnemonicAlias<"cwd", "cwtd">; +def : MnemonicAlias<"cdq", "cltd">; +def : MnemonicAlias<"cwde", "cwtl">; +def : MnemonicAlias<"cdqe", "cltq">; +def : MnemonicAlias<"smovb", "movsb">; +def : MnemonicAlias<"smovw", "movsw">; +def : MnemonicAlias<"smovl", "movsl">; +def : MnemonicAlias<"smovq", "movsq">; + +def : MnemonicAlias<"fldcww", "fldcw">; +def : MnemonicAlias<"fucompi", "fucomip">; +def : MnemonicAlias<"ud2a", "ud2">; +def : MnemonicAlias<"verrw", "verr">; + + + diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp index e64ce2ffa89e..99a32d8a000a 100644 --- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp +++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp @@ -1514,6 +1514,26 @@ static void EmitComputeAvailableFeatures(CodeGenTarget &Target, OS << "}\n\n"; } +/// EmitMnemonicAliases - If the target has any MnemonicAlias<> definitions, +/// emit them. +static void EmitMnemonicAliases(raw_ostream &OS) { + std::vector Aliases = + Records.getAllDerivedDefinitions("MnemonicAlias"); + if (Aliases.empty()) return; + + OS << " // Process all MnemonicAliases to remap the mnemonic.\n"; + std::vector Cases; + for (unsigned i = 0, e = Aliases.size(); i != e; ++i) { + Record *R = Aliases[i]; + Cases.push_back(std::make_pair(R->getValueAsString("FromMnemonic"), + "Mnemonic = \"" + + R->getValueAsString("ToMnemonic") + + "\"; break;")); + } + + StringMatcher("Mnemonic", Cases, OS).Emit(); +} + void AsmMatcherEmitter::run(raw_ostream &OS) { CodeGenTarget Target; Record *AsmParser = Target.getAsmParser(); @@ -1701,6 +1721,12 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " // Get the current feature set.\n"; OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n"; + OS << " // Get the instruction mnemonic, which is the first token.\n"; + OS << " StringRef Mnemonic = ((" << Target.getName() + << "Operand*)Operands[0])->getToken();\n\n"; + + EmitMnemonicAliases(OS); + // Emit code to compute the class list for this operand vector. OS << " // Eliminate obvious mismatches.\n"; OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n"; @@ -1725,10 +1751,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << "i != e; ++i)\n"; OS << " Classes[i] = InvalidMatchClass;\n\n"; - OS << " // Get the instruction mnemonic, which is the first token.\n"; - OS << " StringRef Mnemonic = ((" << Target.getName() - << "Operand*)Operands[0])->getToken();\n\n"; - OS << " // Some state to try to produce better error messages.\n"; OS << " bool HadMatchOtherThanFeatures = false;\n\n"; OS << " // Set ErrorInfo to the operand that mismatches if it is \n";