SrcOp2 = (SrcOp2 == (unsigned)-1) ? SrcOp1 : SrcOp2;
}
- ResOperands.push_back(ResOperand::getTiedOp(TiedOp, SrcOp1, SrcOp2));
- continue;
+ // If the alias operand is of a different operand class, we only want
+ // to benefit from the tied-operands check and just match the operand
+ // as a normal, but not copy the original (TiedOp) to the result
+ // instruction. We do this by passing -1 as the tied operand to copy.
+ if (ResultInst->Operands[i].Rec->getName() !=
+ ResultInst->Operands[TiedOp].Rec->getName()) {
+ SrcOp1 = ResOperands[TiedOp].AsmOperandNum;
+ int SubIdx = CGA.ResultInstOperandIndex[AliasOpNo].second;
+ StringRef Name = CGA.ResultOperands[AliasOpNo].getName();
+ SrcOp2 = findAsmOperand(Name, SubIdx);
+ ResOperands.push_back(
+ ResOperand::getTiedOp((unsigned)-1, SrcOp1, SrcOp2));
+ } else {
+ ResOperands.push_back(ResOperand::getTiedOp(TiedOp, SrcOp1, SrcOp2));
+ continue;
+ }
}
// Handle all the suboperands for this operand.
CvtOS << " std::begin(TiedAsmOperandTable)) &&\n";
CvtOS << " \"Tied operand not found\");\n";
CvtOS << " unsigned TiedResOpnd = TiedAsmOperandTable[OpIdx][0];\n";
- CvtOS << " Inst.addOperand(Inst.getOperand(TiedResOpnd));\n";
+ CvtOS << " if (TiedResOpnd != (uint8_t) -1)\n";
+ CvtOS << " Inst.addOperand(Inst.getOperand(TiedResOpnd));\n";
CvtOS << " break;\n";
CvtOS << " }\n";
enum { CVT_Done, CVT_Reg, CVT_Tied };
// Map of e.g. <0, 2, 3> -> "Tie_0_2_3" enum label.
- std::map<std::tuple<unsigned, unsigned, unsigned>, std::string>
+ std::map<std::tuple<uint8_t, uint8_t, uint8_t>, std::string>
TiedOperandsEnumMap;
for (auto &II : Infos) {
// If this operand is tied to a previous one, just copy the MCInst
// operand from the earlier one.We can only tie single MCOperand values.
assert(OpInfo.MINumOperands == 1 && "Not a singular MCOperand");
- unsigned TiedOp = OpInfo.TiedOperands.ResOpnd;
- unsigned SrcOp1 = OpInfo.TiedOperands.SrcOpnd1Idx + HasMnemonicFirst;
- unsigned SrcOp2 = OpInfo.TiedOperands.SrcOpnd2Idx + HasMnemonicFirst;
- assert(i > TiedOp && "Tied operand precedes its target!");
+ uint8_t TiedOp = OpInfo.TiedOperands.ResOpnd;
+ uint8_t SrcOp1 =
+ OpInfo.TiedOperands.SrcOpnd1Idx + HasMnemonicFirst;
+ uint8_t SrcOp2 =
+ OpInfo.TiedOperands.SrcOpnd2Idx + HasMnemonicFirst;
+ assert((i > TiedOp || TiedOp == (uint8_t)-1) &&
+ "Tied operand precedes its target!");
auto TiedTupleName = std::string("Tie") + utostr(TiedOp) + '_' +
utostr(SrcOp1) + '_' + utostr(SrcOp2);
Signature += "__" + TiedTupleName;
if (TiedOperandsEnumMap.size()) {
// The number of tied operand combinations will be small in practice,
// but just add the assert to be sure.
- assert(TiedOperandsEnumMap.size() <= 255 &&
+ assert(TiedOperandsEnumMap.size() <= 254 &&
"Too many tied-operand combinations to reference with "
- "an 8bit offset from the conversion table");
+ "an 8bit offset from the conversion table, where index "
+ "'255' is reserved as operand not to be copied.");
OS << "enum {\n";
for (auto &KV : TiedOperandsEnumMap) {
}
OS << "};\n\n";
- OS << "const char TiedAsmOperandTable[][3] = {\n";
+ OS << "const uint8_t TiedAsmOperandTable[][3] = {\n";
for (auto &KV : TiedOperandsEnumMap) {
- OS << " /* " << KV.second << " */ { " << std::get<0>(KV.first) << ", "
- << std::get<1>(KV.first) << ", " << std::get<2>(KV.first) << " },\n";
+ OS << " /* " << KV.second << " */ { "
+ << utostr(std::get<0>(KV.first)) << ", "
+ << utostr(std::get<1>(KV.first)) << ", "
+ << utostr(std::get<2>(KV.first)) << " },\n";
}
OS << "};\n\n";
} else
- OS << "const char TiedAsmOperandTable[][3] = { /* empty */ {0, 0, 0} "
- "};\n\n";
+ OS << "const uint8_t TiedAsmOperandTable[][3] = "
+ "{ /* empty */ {0, 0, 0} };\n\n";
OS << "namespace {\n";
// For a tied operand, emit a reference to the TiedAsmOperandTable
// that contains the operand to copy, and the parsed operands to
// check for their tied constraints.
- auto Key = std::make_tuple((unsigned)ConversionTable[Row][i + 1],
- (unsigned)ConversionTable[Row][i + 2],
- (unsigned)ConversionTable[Row][i + 3]);
+ auto Key = std::make_tuple((uint8_t)ConversionTable[Row][i + 1],
+ (uint8_t)ConversionTable[Row][i + 2],
+ (uint8_t)ConversionTable[Row][i + 3]);
auto TiedOpndEnum = TiedOperandsEnumMap.find(Key);
assert(TiedOpndEnum != TiedOperandsEnumMap.end() &&
"No record for tied operand pair");
static void emitAsmTiedOperandConstraints(CodeGenTarget &Target,
AsmMatcherInfo &Info,
raw_ostream &OS) {
+ std::string AsmParserName =
+ Info.AsmParser->getValueAsString("AsmParserClassName");
OS << "static bool ";
- OS << "checkAsmTiedOperandConstraints(unsigned Kind,\n";
+ OS << "checkAsmTiedOperandConstraints(const " << Target.getName()
+ << AsmParserName << "&AsmParser,\n";
+ OS << " unsigned Kind,\n";
OS << " const OperandVector &Operands,\n";
OS << " uint64_t &ErrorInfo) {\n";
OS << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n";
OS << " if (OpndNum1 != OpndNum2) {\n";
OS << " auto &SrcOp1 = Operands[OpndNum1];\n";
OS << " auto &SrcOp2 = Operands[OpndNum2];\n";
- OS << " if (SrcOp1->isReg() && SrcOp2->isReg() &&\n";
- OS << " SrcOp1->getReg() != SrcOp2->getReg()) {\n";
- OS << " ErrorInfo = OpndNum2;\n";
- OS << " return false;\n";
+ OS << " if (SrcOp1->isReg() && SrcOp2->isReg()) {\n";
+ OS << " if (!AsmParser.regsEqual(*SrcOp1, *SrcOp2)) {\n";
+ OS << " ErrorInfo = OpndNum2;\n";
+ OS << " return false;\n";
+ OS << " }\n";
OS << " }\n";
OS << " }\n";
OS << " break;\n";
OS << " if (matchingInlineAsm) {\n";
OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n";
if (!ReportMultipleNearMisses) {
- OS << " if (!checkAsmTiedOperandConstraints(it->ConvertFn, Operands, ErrorInfo))\n";
+ OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
+ "Operands, ErrorInfo))\n";
OS << " return Match_InvalidTiedOperand;\n";
OS << "\n";
}
}
if (!ReportMultipleNearMisses) {
- OS << " if (!checkAsmTiedOperandConstraints(it->ConvertFn, Operands, ErrorInfo))\n";
+ OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
+ "Operands, ErrorInfo))\n";
OS << " return Match_InvalidTiedOperand;\n";
OS << "\n";
}