forked from OSchip/llvm-project
Implement (and document!) support for MnemonicAlias's to have Requires
directives, allowing things like this: def : MnemonicAlias<"pop", "popl">, Requires<[In32BitMode]>; def : MnemonicAlias<"pop", "popq">, Requires<[In64BitMode]>; Move the rest of the X86 MnemonicAliases over to the .td file. llvm-svn: 117830
This commit is contained in:
parent
cda8eb7a21
commit
2cb092dc55
|
@ -1896,7 +1896,7 @@ compiler.</p>
|
|||
The MatchInstructionImpl function performs alias processing and then does
|
||||
actual matching.</p>
|
||||
|
||||
<p>Alias processing if the phase that canonicalizes different lexical forms of
|
||||
<p>Alias processing is 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
|
||||
|
@ -1911,7 +1911,7 @@ description.</p>
|
|||
|
||||
<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
|
||||
mnemonics. 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:
|
||||
|
@ -1928,7 +1928,19 @@ def : MnemonicAlias<"ud2a", "ud2">;
|
|||
</div>
|
||||
|
||||
<p>... and many others. With a MnemonicAlias definition, the mnemonic is
|
||||
remapped simply and directly.</p>
|
||||
remapped simply and directly. Though MnemonicAlias's can't look at any aspect
|
||||
of the instruction (such as the operands) they can depend on global modes (the
|
||||
same ones supported by the matcher), through a Requires clause:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
def : MnemonicAlias<"pushf", "pushfq">, Requires<[In64BitMode]>;
|
||||
def : MnemonicAlias<"pushf", "pushfl">, Requires<[In32BitMode]>;
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>In this example, the mnemonic gets mapped into different a new one depending
|
||||
on the current instruction set.</p>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -541,11 +541,18 @@ def DefaultAsmParser : AsmParser;
|
|||
/// actually has one for each suffix as well):
|
||||
/// def : MnemonicAlias<"sal", "shl">;
|
||||
///
|
||||
/// Mnemonic aliases are mapped before any other translation in the match phase.
|
||||
/// Mnemonic aliases are mapped before any other translation in the match phase,
|
||||
/// and do allow Requires predicates, e.g.:
|
||||
///
|
||||
/// def : MnemonicAlias<"pushf", "pushfq">, Requires<[In64BitMode]>;
|
||||
/// def : MnemonicAlias<"pushf", "pushfl">, Requires<[In32BitMode]>;
|
||||
///
|
||||
class MnemonicAlias<string From, string To> {
|
||||
string FromMnemonic = From;
|
||||
string ToMnemonic = To;
|
||||
|
||||
// Predicates - Predicates that must be true for this remapping to happen.
|
||||
list<Predicate> Predicates = [];
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -620,16 +620,10 @@ X86Operand *X86ATTAsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
|
|||
bool X86ATTAsmParser::
|
||||
ParseInstruction(StringRef Name, SMLoc NameLoc,
|
||||
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||
// FIXME: Hack to recognize some aliases.
|
||||
StringRef PatchedName = StringSwitch<StringRef>(Name)
|
||||
.Case("push", Is64Bit ? "pushq" : "pushl")
|
||||
.Case("pop", Is64Bit ? "popq" : "popl")
|
||||
.Case("pushf", Is64Bit ? "pushfq" : "pushfl")
|
||||
.Case("popf", Is64Bit ? "popfq" : "popfl")
|
||||
.Case("retl", Is64Bit ? "retl" : "ret")
|
||||
.Case("retq", Is64Bit ? "ret" : "retq")
|
||||
.Case("movzx", "movzb") // FIXME: Not correct.
|
||||
.Default(Name);
|
||||
// FIXME: This is not correct at all.
|
||||
if (Name == "movzx") Name = "movzb";
|
||||
|
||||
StringRef PatchedName = Name;
|
||||
|
||||
// FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
|
||||
const MCExpr *ExtraImmOp = 0;
|
||||
|
@ -714,9 +708,9 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
|
|||
|
||||
// Determine whether this is an instruction prefix.
|
||||
bool isPrefix =
|
||||
PatchedName == "lock" || PatchedName == "rep" ||
|
||||
PatchedName == "repe" || PatchedName == "repz" ||
|
||||
PatchedName == "repne" || PatchedName == "repnz";
|
||||
Name == "lock" || Name == "rep" ||
|
||||
Name == "repe" || Name == "repz" ||
|
||||
Name == "repne" || Name == "repnz";
|
||||
|
||||
|
||||
// This does the actual operand parsing. Don't parse any more if we have a
|
||||
|
|
|
@ -1266,13 +1266,25 @@ def : MnemonicAlias<"cdq", "cltd">;
|
|||
def : MnemonicAlias<"cwde", "cwtl">;
|
||||
def : MnemonicAlias<"cdqe", "cltq">;
|
||||
|
||||
def : MnemonicAlias<"pushfd", "pushfl">;
|
||||
def : MnemonicAlias<"pop", "popl">, Requires<[In32BitMode]>;
|
||||
def : MnemonicAlias<"pop", "popq">, Requires<[In64BitMode]>;
|
||||
def : MnemonicAlias<"popf", "popfl">, Requires<[In32BitMode]>;
|
||||
def : MnemonicAlias<"popf", "popfq">, Requires<[In64BitMode]>;
|
||||
def : MnemonicAlias<"popfd", "popfl">;
|
||||
|
||||
def : MnemonicAlias<"push", "pushl">, Requires<[In32BitMode]>;
|
||||
def : MnemonicAlias<"push", "pushq">, Requires<[In64BitMode]>;
|
||||
def : MnemonicAlias<"pushf", "pushfl">, Requires<[In32BitMode]>;
|
||||
def : MnemonicAlias<"pushf", "pushfq">, Requires<[In64BitMode]>;
|
||||
def : MnemonicAlias<"pushfd", "pushfl">;
|
||||
|
||||
def : MnemonicAlias<"repe", "rep">;
|
||||
def : MnemonicAlias<"repz", "rep">;
|
||||
def : MnemonicAlias<"repnz", "repne">;
|
||||
|
||||
def : MnemonicAlias<"retl", "ret">, Requires<[In32BitMode]>;
|
||||
def : MnemonicAlias<"retq", "ret">, Requires<[In64BitMode]>;
|
||||
|
||||
def : MnemonicAlias<"salb", "shlb">;
|
||||
def : MnemonicAlias<"salw", "shlw">;
|
||||
def : MnemonicAlias<"sall", "shll">;
|
||||
|
|
|
@ -587,7 +587,7 @@ private:
|
|||
|
||||
SubtargetFeatureInfo *&Entry = SubtargetFeatures[Def];
|
||||
if (!Entry) {
|
||||
Entry = new SubtargetFeatureInfo;
|
||||
Entry = new SubtargetFeatureInfo();
|
||||
Entry->TheDef = Def;
|
||||
Entry->Index = SubtargetFeatures.size() - 1;
|
||||
Entry->EnumName = "Feature_" + Def->getName();
|
||||
|
@ -1514,6 +1514,35 @@ static void EmitComputeAvailableFeatures(CodeGenTarget &Target,
|
|||
OS << "}\n\n";
|
||||
}
|
||||
|
||||
static std::string GetAliasRequiredFeatures(Record *R) {
|
||||
// FIXME: This is a total hack.
|
||||
std::vector<Record*> ReqFeatures = R->getValueAsListOfDefs("Predicates");
|
||||
|
||||
std::string Result;
|
||||
unsigned NumFeatures = 0;
|
||||
for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) {
|
||||
Record *Pred = ReqFeatures[i];
|
||||
|
||||
// FIXME: Total hack; for now, we just limit ourselves to In32BitMode
|
||||
// and In64BitMode, because we aren't going to have the right feature
|
||||
// masks for SSE and friends. We need to decide what we are going to do
|
||||
// about CPU subtypes to implement this the right way.
|
||||
if (Pred->getName() != "In32BitMode" &&
|
||||
Pred->getName() != "In64BitMode")
|
||||
continue;
|
||||
|
||||
if (NumFeatures)
|
||||
Result += '|';
|
||||
|
||||
Result += "Feature_" + Pred->getName();
|
||||
++NumFeatures;
|
||||
}
|
||||
|
||||
if (NumFeatures > 1)
|
||||
Result = '(' + Result + ')';
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// EmitMnemonicAliases - If the target has any MnemonicAlias<> definitions,
|
||||
/// emit a function for them and return true, otherwise return false.
|
||||
static bool EmitMnemonicAliases(raw_ostream &OS) {
|
||||
|
@ -1539,22 +1568,45 @@ static bool EmitMnemonicAliases(raw_ostream &OS) {
|
|||
for (std::map<std::string, std::vector<Record*> >::iterator
|
||||
I = AliasesFromMnemonic.begin(), E = AliasesFromMnemonic.end();
|
||||
I != E; ++I) {
|
||||
const std::string &From = I->first;
|
||||
const std::vector<Record*> &ToVec = I->second;
|
||||
|
||||
// Loop through each alias and emit code that handles each case. If there
|
||||
// are two instructions without predicates, emit an error. If there is one,
|
||||
// emit it last.
|
||||
std::string MatchCode;
|
||||
int AliasWithNoPredicate = -1;
|
||||
|
||||
// If there is only one destination mnemonic, generate simple code.
|
||||
if (ToVec.size() == 1) {
|
||||
Cases.push_back(std::make_pair(From, "Mnemonic = \"" +
|
||||
ToVec[0]->getValueAsString("ToMnemonic") +
|
||||
"\"; return;"));
|
||||
continue;
|
||||
for (unsigned i = 0, e = ToVec.size(); i != e; ++i) {
|
||||
Record *R = ToVec[i];
|
||||
std::string FeatureMask = GetAliasRequiredFeatures(R);
|
||||
|
||||
// If this unconditionally matches, remember it for later and diagnose
|
||||
// duplicates.
|
||||
if (FeatureMask.empty()) {
|
||||
if (AliasWithNoPredicate != -1) {
|
||||
// We can't have two aliases from the same mnemonic with no predicate.
|
||||
PrintError(ToVec[AliasWithNoPredicate]->getLoc(),
|
||||
"two MnemonicAliases with the same 'from' mnemonic!");
|
||||
PrintError(R->getLoc(), "this is the other MnemonicAliases.");
|
||||
throw std::string("ERROR: Invalid MnemonicAliases definitions!");
|
||||
}
|
||||
|
||||
AliasWithNoPredicate = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
MatchCode += "if ((Features & " + FeatureMask + ") == "+FeatureMask+")\n";
|
||||
MatchCode += " Mnemonic = \"" +R->getValueAsString("ToMnemonic")+"\";\n";
|
||||
}
|
||||
|
||||
// Otherwise, diagnose an error, can't have two aliases from the same
|
||||
// mnemonic.
|
||||
PrintError(ToVec[0]->getLoc(), "two MnemonicAliases with the same 'from' mnemonic!");
|
||||
PrintError(ToVec[1]->getLoc(), "this is the other MnemonicAliases.");
|
||||
throw std::string("ERROR: Invalid MnemonicAliases definitions!");
|
||||
if (AliasWithNoPredicate != -1) {
|
||||
Record *R = ToVec[AliasWithNoPredicate];
|
||||
MatchCode += "Mnemonic = \"" + R->getValueAsString("ToMnemonic") + "\";";
|
||||
}
|
||||
|
||||
MatchCode += "return;";
|
||||
|
||||
Cases.push_back(std::make_pair(I->first, MatchCode));
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue