@@ -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
30333022static 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