forked from OSchip/llvm-project
implement (and document!) the first kind of MC assembler alias, which
just remaps one mnemonic to another. Convert a few of the X86 aliases from .cpp to .td code. llvm-svn: 117815
This commit is contained in:
parent
4ab36ba726
commit
ba7b4fea97
|
@ -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
|
part of the manual and repetitive data entry can be factored and shared with the
|
||||||
compiler.</p>
|
compiler.</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ======================================================================= -->
|
||||||
|
<div class="doc_subsection" id="na_instparsing">Instruction Parsing</div>
|
||||||
|
|
||||||
|
<div class="doc_text"><p>To Be Written</p></div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ======================================================================= -->
|
||||||
|
<div class="doc_subsection" id="na_instaliases">
|
||||||
|
Instruction Alias Processing
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="doc_text">
|
||||||
|
<p>Once the instruction is parsed, it enters the MatchInstructionImpl function.
|
||||||
|
The MatchInstructionImpl function performs alias processing and then does
|
||||||
|
actual matching.</p>
|
||||||
|
|
||||||
|
<p>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.</p>
|
||||||
|
|
||||||
|
<!-- _______________________________________________________________________ -->
|
||||||
|
<div class="doc_subsubsection">Mnemonic Aliases</div>
|
||||||
|
|
||||||
|
<div class="doc_text">
|
||||||
|
|
||||||
|
<p>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:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="doc_code">
|
||||||
|
<pre>
|
||||||
|
def : MnemonicAlias<"cbw", "cbtw">;
|
||||||
|
def : MnemonicAlias<"smovq", "movsq">;
|
||||||
|
def : MnemonicAlias<"fldcww", "fldcw">;
|
||||||
|
def : MnemonicAlias<"fucompi", "fucomip">;
|
||||||
|
def : MnemonicAlias<"ud2a", "ud2">;
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>... and many others. With a MnemonicAlias definition, the mnemonic is
|
||||||
|
remapped simply and directly.</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!-- ======================================================================= -->
|
<!-- ======================================================================= -->
|
||||||
<div class="doc_subsection">
|
<div class="doc_subsection" id="na_matching">Instruction Matching</div>
|
||||||
<a name="proepicode">Prolog/Epilog Code Insertion</a>
|
|
||||||
</div>
|
|
||||||
<div class="doc_text"><p>To Be Written</p></div>
|
<div class="doc_text"><p>To Be Written</p></div>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -530,6 +530,25 @@ class AsmParser {
|
||||||
def DefaultAsmParser : 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 From, string To> {
|
||||||
|
string FromMnemonic = From;
|
||||||
|
string ToMnemonic = To;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// AsmWriter - This class can be implemented by targets that need to customize
|
// AsmWriter - This class can be implemented by targets that need to customize
|
||||||
// the format of the .s file writer.
|
// the format of the .s file writer.
|
||||||
|
|
|
@ -632,17 +632,6 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
|
||||||
.Case("repe", "rep")
|
.Case("repe", "rep")
|
||||||
.Case("repz", "rep")
|
.Case("repz", "rep")
|
||||||
.Case("repnz", "repne")
|
.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("push", Is64Bit ? "pushq" : "pushl")
|
||||||
.Case("pop", Is64Bit ? "popq" : "popl")
|
.Case("pop", Is64Bit ? "popq" : "popl")
|
||||||
.Case("pushf", Is64Bit ? "pushfq" : "pushfl")
|
.Case("pushf", Is64Bit ? "pushfq" : "pushfl")
|
||||||
|
@ -704,14 +693,10 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
|
||||||
.Case("movzx", "movzb") // FIXME: Not correct.
|
.Case("movzx", "movzb") // FIXME: Not correct.
|
||||||
.Case("fildq", "fildll")
|
.Case("fildq", "fildll")
|
||||||
.Case("fcompi", "fcomip")
|
.Case("fcompi", "fcomip")
|
||||||
.Case("fucompi", "fucomip")
|
|
||||||
.Case("fldcww", "fldcw")
|
|
||||||
.Case("fnstcww", "fnstcw")
|
.Case("fnstcww", "fnstcw")
|
||||||
.Case("fstcww", "fstcw")
|
.Case("fstcww", "fstcw")
|
||||||
.Case("fnstsww", "fnstsw")
|
.Case("fnstsww", "fnstsw")
|
||||||
.Case("fstsww", "fstsw")
|
.Case("fstsww", "fstsw")
|
||||||
.Case("verrw", "verr")
|
|
||||||
.Case("ud2a", "ud2")
|
|
||||||
.Default(Name);
|
.Default(Name);
|
||||||
|
|
||||||
// FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
|
// FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
|
||||||
|
|
|
@ -1254,3 +1254,26 @@ include "X86InstrSystem.td"
|
||||||
// Compiler Pseudo Instructions and Pat Patterns
|
// Compiler Pseudo Instructions and Pat Patterns
|
||||||
include "X86InstrCompiler.td"
|
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">;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1514,6 +1514,26 @@ static void EmitComputeAvailableFeatures(CodeGenTarget &Target,
|
||||||
OS << "}\n\n";
|
OS << "}\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// EmitMnemonicAliases - If the target has any MnemonicAlias<> definitions,
|
||||||
|
/// emit them.
|
||||||
|
static void EmitMnemonicAliases(raw_ostream &OS) {
|
||||||
|
std::vector<Record*> Aliases =
|
||||||
|
Records.getAllDerivedDefinitions("MnemonicAlias");
|
||||||
|
if (Aliases.empty()) return;
|
||||||
|
|
||||||
|
OS << " // Process all MnemonicAliases to remap the mnemonic.\n";
|
||||||
|
std::vector<StringMatcher::StringPair> 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) {
|
void AsmMatcherEmitter::run(raw_ostream &OS) {
|
||||||
CodeGenTarget Target;
|
CodeGenTarget Target;
|
||||||
Record *AsmParser = Target.getAsmParser();
|
Record *AsmParser = Target.getAsmParser();
|
||||||
|
@ -1701,6 +1721,12 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
||||||
OS << " // Get the current feature set.\n";
|
OS << " // Get the current feature set.\n";
|
||||||
OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\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.
|
// Emit code to compute the class list for this operand vector.
|
||||||
OS << " // Eliminate obvious mismatches.\n";
|
OS << " // Eliminate obvious mismatches.\n";
|
||||||
OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n";
|
OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n";
|
||||||
|
@ -1725,10 +1751,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
||||||
<< "i != e; ++i)\n";
|
<< "i != e; ++i)\n";
|
||||||
OS << " Classes[i] = InvalidMatchClass;\n\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 << " // Some state to try to produce better error messages.\n";
|
||||||
OS << " bool HadMatchOtherThanFeatures = false;\n\n";
|
OS << " bool HadMatchOtherThanFeatures = false;\n\n";
|
||||||
OS << " // Set ErrorInfo to the operand that mismatches if it is \n";
|
OS << " // Set ErrorInfo to the operand that mismatches if it is \n";
|
||||||
|
|
Loading…
Reference in New Issue