Operands[0] = X86Operand::CreateToken("fstps", NameLoc);
}
-
- // "clr <reg>" -> "xor <reg>, <reg>".
- if ((Name == "clrb" || Name == "clrw" || Name == "clrl" || Name == "clrq" ||
- Name == "clr") && Operands.size() == 2 &&
- static_cast<X86Operand*>(Operands[1])->isReg()) {
- unsigned RegNo = static_cast<X86Operand*>(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) {
// 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)>;
return -1;
}
- void BuildResultOperands();
+ void BuildInstructionResultOperands();
+ void BuildAliasResultOperands();
/// operator< - Compare two matchables.
bool operator<(const MatchableInfo &RHS) const {
BuildAliasOperandReference(II, OperandName, Op);
}
- II->BuildResultOperands();
+ if (II->DefRec.is<const CodeGenInstruction*>())
+ II->BuildInstructionResultOperands();
+ else
+ II->BuildAliasResultOperands();
}
// Reorder classes so that classes preceed super classes.
OperandName.str() + "'");
}
-void MatchableInfo::BuildResultOperands() {
+void MatchableInfo::BuildInstructionResultOperands() {
const CodeGenInstruction *ResultInst = getResultInst();
// Loop over all operands of the result instruction, determining how to
}
}
+void MatchableInfo::BuildAliasResultOperands() {
+ const CodeGenInstAlias &CGA = *DefRec.get<const CodeGenInstAlias*>();
+ 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<MatchableInfo*> &Infos,
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<Record*> 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<DefInit*>(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());
// 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!");
}