diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index e57e34fb457..30d3a7e6c5a 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -983,17 +983,6 @@ ParseInstruction(StringRef Name, SMLoc NameLoc, Operands[0] = X86Operand::CreateToken("fstps", NameLoc); } - - // "clr " -> "xor , ". - if ((Name == "clrb" || Name == "clrw" || Name == "clrl" || Name == "clrq" || - Name == "clr") && Operands.size() == 2 && - static_cast(Operands[1])->isReg()) { - unsigned RegNo = static_cast(Operands[1])->getReg(); - Operands.push_back(X86Operand::CreateReg(RegNo, NameLoc, NameLoc)); - delete Operands[0]; - Operands[0] = X86Operand::CreateToken("xor", NameLoc); - } - // FIXME: Hack to handle recognize "aa[dm]" -> "aa[dm] $0xA". if ((Name.startswith("aad") || Name.startswith("aam")) && Operands.size() == 1) { diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index ad3fe1556be..fdb17a13724 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -1370,6 +1370,12 @@ defm : IntegerCondCodeMnemonicAlias<"cmov", "q">; // Assembler Instruction Aliases //===----------------------------------------------------------------------===// +// clr aliases. +def : InstAlias<"clrb $reg", (XOR8rr GR8 :$reg, GR8 :$reg)>; +def : InstAlias<"clrw $reg", (XOR16rr GR16:$reg, GR16:$reg)>; +def : InstAlias<"clrl $reg", (XOR32rr GR32:$reg, GR32:$reg)>; +def : InstAlias<"clrq $reg", (XOR64rr GR64:$reg, GR64:$reg)>; + // movsx aliases def : InstAlias<"movsx $src, $dst", (MOVSX16rr8W GR16:$dst, GR8:$src)>; diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index be72ab449b2..6a70c5a4b5f 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -372,7 +372,8 @@ struct MatchableInfo { return -1; } - void BuildResultOperands(); + void BuildInstructionResultOperands(); + void BuildAliasResultOperands(); /// operator< - Compare two matchables. bool operator<(const MatchableInfo &RHS) const { @@ -1112,7 +1113,10 @@ void AsmMatcherInfo::BuildInfo() { BuildAliasOperandReference(II, OperandName, Op); } - II->BuildResultOperands(); + if (II->DefRec.is()) + II->BuildInstructionResultOperands(); + else + II->BuildAliasResultOperands(); } // Reorder classes so that classes preceed super classes. @@ -1182,7 +1186,7 @@ void AsmMatcherInfo::BuildAliasOperandReference(MatchableInfo *II, OperandName.str() + "'"); } -void MatchableInfo::BuildResultOperands() { +void MatchableInfo::BuildInstructionResultOperands() { const CodeGenInstruction *ResultInst = getResultInst(); // Loop over all operands of the result instruction, determining how to @@ -1212,6 +1216,36 @@ void MatchableInfo::BuildResultOperands() { } } +void MatchableInfo::BuildAliasResultOperands() { + const CodeGenInstAlias &CGA = *DefRec.get(); + const CodeGenInstruction *ResultInst = getResultInst(); + + // Loop over all operands of the result instruction, determining how to + // populate them. + unsigned AliasOpNo = 0; + for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { + const CGIOperandList::OperandInfo &OpInfo = ResultInst->Operands[i]; + + // If this is a tied operand, just copy from the previously handled operand. + int TiedOp = OpInfo.getTiedRegister(); + if (TiedOp != -1) { + ResOperands.push_back(ResOperand::getTiedOp(TiedOp, &OpInfo)); + continue; + } + + // Find out what operand from the asmparser that this MCInst operand comes + // from. + int SrcOperand = FindAsmOperandNamed(CGA.ResultOperands[AliasOpNo++].Name); + if (SrcOperand != -1) { + ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, &OpInfo)); + continue; + } + + throw TGError(TheDef->getLoc(), "Instruction '" + + TheDef->getName() + "' has operand '" + OpInfo.Name + + "' that doesn't appear in asm string!"); + } +} static void EmitConvertToMCInst(CodeGenTarget &Target, std::vector &Infos, diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index c32a58649bd..73b7b78d09b 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -400,30 +400,35 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { ResultInst = &T.getInstruction(DI->getDef()); - // Check number of arguments in the result. - if (ResultInst->Operands.size() != Result->getNumArgs()) - throw TGError(R->getLoc(), "result has " + utostr(Result->getNumArgs()) + - " arguments, but " + ResultInst->TheDef->getName() + - " instruction expects " + utostr(ResultInst->Operands.size())+ - " operands!"); - // NameClass - If argument names are repeated, we need to verify they have // the same class. StringMap NameClass; // Decode and validate the arguments of the result. - for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) { - Init *Arg = Result->getArg(i); + unsigned AliasOpNo = 0; + for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { + // Tied registers don't have an entry in the result dag. + if (ResultInst->Operands[i].getTiedRegister() != -1) + continue; + + if (AliasOpNo >= Result->getNumArgs()) + throw TGError(R->getLoc(), "result has " + utostr(Result->getNumArgs()) + + " arguments, but " + ResultInst->TheDef->getName() + + " instruction expects " + + utostr(ResultInst->Operands.size()) + " operands!"); + + + Init *Arg = Result->getArg(AliasOpNo); // If the operand is a record, it must have a name, and the record type must // match up with the instruction's argument type. if (DefInit *ADI = dynamic_cast(Arg)) { - if (Result->getArgName(i).empty()) - throw TGError(R->getLoc(), "result argument #" + utostr(i) + + if (Result->getArgName(AliasOpNo).empty()) + throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + " must have a name!"); if (ADI->getDef() != ResultInst->Operands[i].Rec) - throw TGError(R->getLoc(), "result argument #" + utostr(i) + + throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + " declared with class " + ADI->getDef()->getName() + ", instruction operand is class " + ResultInst->Operands[i].Rec->getName()); @@ -431,18 +436,26 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { // Verify we don't have something like: (someinst GR16:$foo, GR32:$foo) // $foo can exist multiple times in the result list, but it must have the // same type. - Record *&Entry = NameClass[Result->getArgName(i)]; + Record *&Entry = NameClass[Result->getArgName(AliasOpNo)]; if (Entry && Entry != ADI->getDef()) - throw TGError(R->getLoc(), "result value $" + Result->getArgName(i) + + throw TGError(R->getLoc(), "result value $" + + Result->getArgName(AliasOpNo) + " is both " + Entry->getName() + " and " + ADI->getDef()->getName() + "!"); // Now that it is validated, add it. - ResultOperands.push_back(ResultOperand(Result->getArgName(i), + ResultOperands.push_back(ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef())); + ++AliasOpNo; continue; } throw TGError(R->getLoc(), "result of inst alias has unknown operand type"); } + + if (AliasOpNo != Result->getNumArgs()) + throw TGError(R->getLoc(), "result has " + utostr(Result->getNumArgs()) + + " arguments, but " + ResultInst->TheDef->getName() + + " instruction expects " + utostr(ResultInst->Operands.size())+ + " operands!"); }