@@ -1976,7 +1976,8 @@ emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
1976
1976
<< " convertToMCInst(unsigned Kind, MCInst &Inst, "
1977
1977
<< " unsigned Opcode,\n "
1978
1978
<< " const OperandVector &Operands,\n "
1979
- << " const SmallBitVector &OptionalOperandsMask) {\n " ;
1979
+ << " const SmallBitVector &OptionalOperandsMask,\n "
1980
+ << " ArrayRef<unsigned> DefaultsOffset) {\n " ;
1980
1981
} else {
1981
1982
CvtOS << " void " << Target.getName () << ClassName << " ::\n "
1982
1983
<< " convertToMCInst(unsigned Kind, MCInst &Inst, "
@@ -1985,25 +1986,13 @@ emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
1985
1986
}
1986
1987
CvtOS << " assert(Kind < CVT_NUM_SIGNATURES && \" Invalid signature!\" );\n " ;
1987
1988
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
- }
2003
1989
CvtOS << " unsigned OpIdx;\n " ;
2004
1990
CvtOS << " Inst.setOpcode(Opcode);\n " ;
2005
1991
CvtOS << " for (const uint8_t *p = Converter; *p; p += 2) {\n " ;
2006
1992
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.
2007
1996
CvtOS << " OpIdx = *(p + 1) - DefaultsOffset[*(p + 1)];\n " ;
2008
1997
} else {
2009
1998
CvtOS << " OpIdx = *(p + 1);\n " ;
@@ -3031,15 +3020,17 @@ emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
3031
3020
}
3032
3021
3033
3022
static void emitAsmTiedOperandConstraints (CodeGenTarget &Target,
3034
- AsmMatcherInfo &Info,
3035
- raw_ostream &OS ) {
3023
+ AsmMatcherInfo &Info, raw_ostream &OS,
3024
+ bool HasOptionalOperands ) {
3036
3025
std::string AsmParserName =
3037
3026
std::string (Info.AsmParser ->getValueAsString (" AsmParserClassName" ));
3038
3027
OS << " static bool " ;
3039
3028
OS << " checkAsmTiedOperandConstraints(const " << Target.getName ()
3040
3029
<< 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 " ;
3043
3034
OS << " uint64_t &ErrorInfo) {\n " ;
3044
3035
OS << " assert(Kind < CVT_NUM_SIGNATURES && \" Invalid signature!\" );\n " ;
3045
3036
OS << " const uint8_t *Converter = ConversionTable[Kind];\n " ;
@@ -3052,6 +3043,13 @@ static void emitAsmTiedOperandConstraints(CodeGenTarget &Target,
3052
3043
OS << " \" Tied operand not found\" );\n " ;
3053
3044
OS << " unsigned OpndNum1 = TiedAsmOperandTable[OpIdx][1];\n " ;
3054
3045
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
+ }
3055
3053
OS << " if (OpndNum1 != OpndNum2) {\n " ;
3056
3054
OS << " auto &SrcOp1 = Operands[OpndNum1];\n " ;
3057
3055
OS << " auto &SrcOp2 = Operands[OpndNum2];\n " ;
@@ -3291,7 +3289,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
3291
3289
<< " unsigned Opcode,\n "
3292
3290
<< " const OperandVector &Operands,\n "
3293
3291
<< " const SmallBitVector "
3294
- " &OptionalOperandsMask);\n " ;
3292
+ " &OptionalOperandsMask,\n "
3293
+ << " ArrayRef<unsigned> DefaultsOffset);\n " ;
3295
3294
} else {
3296
3295
OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, "
3297
3296
<< " unsigned Opcode,\n "
@@ -3405,7 +3404,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
3405
3404
Info.SubtargetFeatures , OS);
3406
3405
3407
3406
if (!ReportMultipleNearMisses)
3408
- emitAsmTiedOperandConstraints (Target, Info, OS);
3407
+ emitAsmTiedOperandConstraints (Target, Info, OS, HasOptionalOperands );
3409
3408
3410
3409
StringToOffsetTable StringTable;
3411
3410
@@ -3928,11 +3927,39 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
3928
3927
OS << " }\n\n " ;
3929
3928
}
3930
3929
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
+
3931
3950
OS << " if (matchingInlineAsm) {\n " ;
3932
3951
OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n " ;
3933
3952
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
+ }
3936
3963
OS << " return Match_InvalidTiedOperand;\n " ;
3937
3964
OS << " \n " ;
3938
3965
}
@@ -3942,7 +3969,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
3942
3969
<< " // operands into the appropriate MCInst.\n " ;
3943
3970
if (HasOptionalOperands) {
3944
3971
OS << " convertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands,\n "
3945
- << " OptionalOperandsMask);\n " ;
3972
+ << " OptionalOperandsMask, DefaultsOffset );\n " ;
3946
3973
} else {
3947
3974
OS << " convertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands);\n " ;
3948
3975
}
@@ -4022,8 +4049,16 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
4022
4049
}
4023
4050
4024
4051
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
+ }
4027
4062
OS << " return Match_InvalidTiedOperand;\n " ;
4028
4063
OS << " \n " ;
4029
4064
}
0 commit comments