Skip to content

Commit 199bbe2

Browse files
authored
[MC] Teach checkAsmTiedOperandConstraints about optional operands (#81381)
At some point in the past, optional operands have become allowed in the middle of an instruction. However, `checkAsmTiedOperandConstrains` hasn't been modified to support this. This patch adds the support by pulling operand offsets counting out of `convertToMCInst` and reusing it in `checkAsmTiedOperandConstrains`.
1 parent d50dec6 commit 199bbe2

File tree

1 file changed

+62
-27
lines changed

1 file changed

+62
-27
lines changed

llvm/utils/TableGen/AsmMatcherEmitter.cpp

Lines changed: 62 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1976,7 +1976,8 @@ emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
19761976
<< "convertToMCInst(unsigned Kind, MCInst &Inst, "
19771977
<< "unsigned Opcode,\n"
19781978
<< " const OperandVector &Operands,\n"
1979-
<< " const SmallBitVector &OptionalOperandsMask) {\n";
1979+
<< " const SmallBitVector &OptionalOperandsMask,\n"
1980+
<< " ArrayRef<unsigned> DefaultsOffset) {\n";
19801981
} else {
19811982
CvtOS << "void " << Target.getName() << ClassName << "::\n"
19821983
<< "convertToMCInst(unsigned Kind, MCInst &Inst, "
@@ -1985,25 +1986,13 @@ emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
19851986
}
19861987
CvtOS << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n";
19871988
CvtOS << " const uint8_t *Converter = ConversionTable[Kind];\n";
1988-
if (HasOptionalOperands) {
1989-
size_t MaxNumOperands = 0;
1990-
for (const auto &MI : Infos) {
1991-
MaxNumOperands = std::max(MaxNumOperands, MI->AsmOperands.size());
1992-
}
1993-
CvtOS << " unsigned DefaultsOffset[" << (MaxNumOperands + 1)
1994-
<< "] = { 0 };\n";
1995-
CvtOS << " assert(OptionalOperandsMask.size() == " << (MaxNumOperands)
1996-
<< ");\n";
1997-
CvtOS << " for (unsigned i = 0, NumDefaults = 0; i < " << (MaxNumOperands)
1998-
<< "; ++i) {\n";
1999-
CvtOS << " DefaultsOffset[i + 1] = NumDefaults;\n";
2000-
CvtOS << " NumDefaults += (OptionalOperandsMask[i] ? 1 : 0);\n";
2001-
CvtOS << " }\n";
2002-
}
20031989
CvtOS << " unsigned OpIdx;\n";
20041990
CvtOS << " Inst.setOpcode(Opcode);\n";
20051991
CvtOS << " for (const uint8_t *p = Converter; *p; p += 2) {\n";
20061992
if (HasOptionalOperands) {
1993+
// When optional operands are involved, formal and actual operand indices
1994+
// may differ. Map the former to the latter by subtracting the number of
1995+
// absent optional operands.
20071996
CvtOS << " OpIdx = *(p + 1) - DefaultsOffset[*(p + 1)];\n";
20081997
} else {
20091998
CvtOS << " OpIdx = *(p + 1);\n";
@@ -3031,15 +3020,17 @@ emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
30313020
}
30323021

30333022
static void emitAsmTiedOperandConstraints(CodeGenTarget &Target,
3034-
AsmMatcherInfo &Info,
3035-
raw_ostream &OS) {
3023+
AsmMatcherInfo &Info, raw_ostream &OS,
3024+
bool HasOptionalOperands) {
30363025
std::string AsmParserName =
30373026
std::string(Info.AsmParser->getValueAsString("AsmParserClassName"));
30383027
OS << "static bool ";
30393028
OS << "checkAsmTiedOperandConstraints(const " << Target.getName()
30403029
<< AsmParserName << "&AsmParser,\n";
3041-
OS << " unsigned Kind,\n";
3042-
OS << " const OperandVector &Operands,\n";
3030+
OS << " unsigned Kind, const OperandVector "
3031+
"&Operands,\n";
3032+
if (HasOptionalOperands)
3033+
OS << " ArrayRef<unsigned> DefaultsOffset,\n";
30433034
OS << " uint64_t &ErrorInfo) {\n";
30443035
OS << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n";
30453036
OS << " const uint8_t *Converter = ConversionTable[Kind];\n";
@@ -3052,6 +3043,13 @@ static void emitAsmTiedOperandConstraints(CodeGenTarget &Target,
30523043
OS << " \"Tied operand not found\");\n";
30533044
OS << " unsigned OpndNum1 = TiedAsmOperandTable[OpIdx][1];\n";
30543045
OS << " unsigned OpndNum2 = TiedAsmOperandTable[OpIdx][2];\n";
3046+
if (HasOptionalOperands) {
3047+
// When optional operands are involved, formal and actual operand indices
3048+
// may differ. Map the former to the latter by subtracting the number of
3049+
// absent optional operands.
3050+
OS << " OpndNum1 = OpndNum1 - DefaultsOffset[OpndNum1];\n";
3051+
OS << " OpndNum2 = OpndNum2 - DefaultsOffset[OpndNum2];\n";
3052+
}
30553053
OS << " if (OpndNum1 != OpndNum2) {\n";
30563054
OS << " auto &SrcOp1 = Operands[OpndNum1];\n";
30573055
OS << " auto &SrcOp2 = Operands[OpndNum2];\n";
@@ -3291,7 +3289,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
32913289
<< "unsigned Opcode,\n"
32923290
<< " const OperandVector &Operands,\n"
32933291
<< " const SmallBitVector "
3294-
"&OptionalOperandsMask);\n";
3292+
"&OptionalOperandsMask,\n"
3293+
<< " ArrayRef<unsigned> DefaultsOffset);\n";
32953294
} else {
32963295
OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, "
32973296
<< "unsigned Opcode,\n"
@@ -3405,7 +3404,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
34053404
Info.SubtargetFeatures, OS);
34063405

34073406
if (!ReportMultipleNearMisses)
3408-
emitAsmTiedOperandConstraints(Target, Info, OS);
3407+
emitAsmTiedOperandConstraints(Target, Info, OS, HasOptionalOperands);
34093408

34103409
StringToOffsetTable StringTable;
34113410

@@ -3928,11 +3927,39 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
39283927
OS << " }\n\n";
39293928
}
39303929

3930+
// When converting parsed operands to MCInst we need to know whether optional
3931+
// operands were parsed or not so that we can choose the correct converter
3932+
// function. We also need to know this when checking tied operand constraints.
3933+
// DefaultsOffset is an array of deltas between the formal (MCInst) and the
3934+
// actual (parsed operand array) operand indices. When all optional operands
3935+
// are present, all elements of the array are zeros. If some of the optional
3936+
// operands are absent, the array might look like '0, 0, 1, 1, 1, 2, 2, 3',
3937+
// where each increment in value reflects the absence of an optional operand.
3938+
if (HasOptionalOperands) {
3939+
OS << " unsigned DefaultsOffset[" << (MaxNumOperands + 1)
3940+
<< "] = { 0 };\n";
3941+
OS << " assert(OptionalOperandsMask.size() == " << (MaxNumOperands)
3942+
<< ");\n";
3943+
OS << " for (unsigned i = 0, NumDefaults = 0; i < " << (MaxNumOperands)
3944+
<< "; ++i) {\n";
3945+
OS << " DefaultsOffset[i + 1] = NumDefaults;\n";
3946+
OS << " NumDefaults += (OptionalOperandsMask[i] ? 1 : 0);\n";
3947+
OS << " }\n\n";
3948+
}
3949+
39313950
OS << " if (matchingInlineAsm) {\n";
39323951
OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n";
39333952
if (!ReportMultipleNearMisses) {
3934-
OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
3935-
"Operands, ErrorInfo))\n";
3953+
if (HasOptionalOperands) {
3954+
OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
3955+
"Operands,\n";
3956+
OS << " DefaultsOffset, "
3957+
"ErrorInfo))\n";
3958+
} else {
3959+
OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
3960+
"Operands,\n";
3961+
OS << " ErrorInfo))\n";
3962+
}
39363963
OS << " return Match_InvalidTiedOperand;\n";
39373964
OS << "\n";
39383965
}
@@ -3942,7 +3969,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
39423969
<< " // operands into the appropriate MCInst.\n";
39433970
if (HasOptionalOperands) {
39443971
OS << " convertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands,\n"
3945-
<< " OptionalOperandsMask);\n";
3972+
<< " OptionalOperandsMask, DefaultsOffset);\n";
39463973
} else {
39473974
OS << " convertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands);\n";
39483975
}
@@ -4022,8 +4049,16 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
40224049
}
40234050

40244051
if (!ReportMultipleNearMisses) {
4025-
OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
4026-
"Operands, ErrorInfo))\n";
4052+
if (HasOptionalOperands) {
4053+
OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
4054+
"Operands,\n";
4055+
OS << " DefaultsOffset, "
4056+
"ErrorInfo))\n";
4057+
} else {
4058+
OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
4059+
"Operands,\n";
4060+
OS << " ErrorInfo))\n";
4061+
}
40274062
OS << " return Match_InvalidTiedOperand;\n";
40284063
OS << "\n";
40294064
}

0 commit comments

Comments
 (0)