@@ -493,7 +493,8 @@ struct MatchableInfo {
493
493
494
494
void initialize (const AsmMatcherInfo &Info,
495
495
SmallPtrSetImpl<Record*> &SingletonRegisters,
496
- AsmVariantInfo const &Variant);
496
+ AsmVariantInfo const &Variant,
497
+ bool HasMnemonicFirst);
497
498
498
499
// / validate - Return true if this matchable is a valid thing to match against
499
500
// / and perform a bunch of validity checking.
@@ -836,14 +837,33 @@ extractSingletonRegisterForAsmOperand(MatchableInfo::AsmOperand &Op,
836
837
837
838
void MatchableInfo::initialize (const AsmMatcherInfo &Info,
838
839
SmallPtrSetImpl<Record*> &SingletonRegisters,
839
- AsmVariantInfo const &Variant) {
840
+ AsmVariantInfo const &Variant,
841
+ bool HasMnemonicFirst) {
840
842
AsmVariantID = Variant.AsmVariantNo ;
841
843
AsmString =
842
844
CodeGenInstruction::FlattenAsmStringVariants (AsmString,
843
845
Variant.AsmVariantNo );
844
846
845
847
tokenizeAsmString (Info, Variant);
846
848
849
+ // The first token of the instruction is the mnemonic, which must be a
850
+ // simple string, not a $foo variable or a singleton register.
851
+ if (AsmOperands.empty ())
852
+ PrintFatalError (TheDef->getLoc (),
853
+ " Instruction '" + TheDef->getName () + " ' has no tokens" );
854
+
855
+ assert (!AsmOperands[0 ].Token .empty ());
856
+ if (HasMnemonicFirst) {
857
+ Mnemonic = AsmOperands[0 ].Token ;
858
+ if (Mnemonic[0 ] == ' $' )
859
+ PrintFatalError (TheDef->getLoc (),
860
+ " Invalid instruction mnemonic '" + Mnemonic + " '!" );
861
+
862
+ // Remove the first operand, it is tracked in the mnemonic field.
863
+ AsmOperands.erase (AsmOperands.begin ());
864
+ } else if (AsmOperands[0 ].Token [0 ] != ' $' )
865
+ Mnemonic = AsmOperands[0 ].Token ;
866
+
847
867
// Compute the require features.
848
868
for (Record *Predicate : TheDef->getValueAsListOfDefs (" Predicates" ))
849
869
if (const SubtargetFeatureInfo *Feature =
@@ -953,15 +973,6 @@ void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info,
953
973
}
954
974
if (InTok && Prev != String.size ())
955
975
addAsmOperand (String.substr (Prev), IsIsolatedToken);
956
-
957
- // The first token of the instruction is the mnemonic, which must be a
958
- // simple string, not a $foo variable or a singleton register.
959
- if (AsmOperands.empty ())
960
- PrintFatalError (TheDef->getLoc (),
961
- " Instruction '" + TheDef->getName () + " ' has no tokens" );
962
- assert (!AsmOperands[0 ].Token .empty ());
963
- if (AsmOperands[0 ].Token [0 ] != ' $' )
964
- Mnemonic = AsmOperands[0 ].Token ;
965
976
}
966
977
967
978
bool MatchableInfo::validate (StringRef CommentDelimiter, bool Hack) const {
@@ -1369,6 +1380,8 @@ void AsmMatcherInfo::buildInfo() {
1369
1380
assert (SubtargetFeatures.size () <= 64 && " Too many subtarget features!" );
1370
1381
}
1371
1382
1383
+ bool HasMnemonicFirst = AsmParser->getValueAsBit (" HasMnemonicFirst" );
1384
+
1372
1385
// Parse the instructions; we need to do this first so that we can gather the
1373
1386
// singleton register classes.
1374
1387
SmallPtrSet<Record*, 16 > SingletonRegisters;
@@ -1400,7 +1413,7 @@ void AsmMatcherInfo::buildInfo() {
1400
1413
1401
1414
auto II = llvm::make_unique<MatchableInfo>(*CGI);
1402
1415
1403
- II->initialize (*this , SingletonRegisters, Variant);
1416
+ II->initialize (*this , SingletonRegisters, Variant, HasMnemonicFirst );
1404
1417
1405
1418
// Ignore instructions which shouldn't be matched and diagnose invalid
1406
1419
// instruction definitions with an error.
@@ -1428,7 +1441,7 @@ void AsmMatcherInfo::buildInfo() {
1428
1441
1429
1442
auto II = llvm::make_unique<MatchableInfo>(std::move (Alias));
1430
1443
1431
- II->initialize (*this , SingletonRegisters, Variant);
1444
+ II->initialize (*this , SingletonRegisters, Variant, HasMnemonicFirst );
1432
1445
1433
1446
// Validate the alias definitions.
1434
1447
II->validate (CommentDelimiter, false );
@@ -1734,7 +1747,7 @@ static unsigned getConverterOperandID(const std::string &Name,
1734
1747
1735
1748
static void emitConvertFuncs (CodeGenTarget &Target, StringRef ClassName,
1736
1749
std::vector<std::unique_ptr<MatchableInfo>> &Infos,
1737
- raw_ostream &OS) {
1750
+ bool HasMnemonicFirst, raw_ostream &OS) {
1738
1751
SmallSetVector<std::string, 16 > OperandConversionKinds;
1739
1752
SmallSetVector<std::string, 16 > InstructionConversionKinds;
1740
1753
std::vector<std::vector<uint8_t > > ConversionTable;
@@ -1868,7 +1881,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
1868
1881
1869
1882
// Add the operand entry to the instruction kind conversion row.
1870
1883
ConversionRow.push_back (ID);
1871
- ConversionRow.push_back (OpInfo.AsmOperandNum );
1884
+ ConversionRow.push_back (OpInfo.AsmOperandNum + HasMnemonicFirst );
1872
1885
1873
1886
if (!IsNewConverter)
1874
1887
break ;
@@ -2472,7 +2485,7 @@ static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info,
2472
2485
static void emitCustomOperandParsing (raw_ostream &OS, CodeGenTarget &Target,
2473
2486
const AsmMatcherInfo &Info, StringRef ClassName,
2474
2487
StringToOffsetTable &StringTable,
2475
- unsigned MaxMnemonicIndex) {
2488
+ unsigned MaxMnemonicIndex, bool HasMnemonicFirst ) {
2476
2489
unsigned MaxMask = 0 ;
2477
2490
for (const OperandMatchEntry &OMI : Info.OperandMatchInfo ) {
2478
2491
MaxMask |= OMI.OperandMask ;
@@ -2586,19 +2599,25 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
2586
2599
OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n " ;
2587
2600
2588
2601
OS << " // Get the next operand index.\n " ;
2589
- OS << " unsigned NextOpNum = Operands.size();\n " ;
2602
+ OS << " unsigned NextOpNum = Operands.size()"
2603
+ << (HasMnemonicFirst ? " - 1" : " " ) << " ;\n " ;
2590
2604
2591
2605
// Emit code to search the table.
2592
2606
OS << " // Search the table.\n " ;
2593
- OS << " std::pair<const OperandMatchEntry*, const OperandMatchEntry*>" ;
2594
- OS << " MnemonicRange\n " ;
2595
- OS << " (OperandMatchTable, OperandMatchTable+" ;
2596
- OS << Info.OperandMatchInfo .size () << " );\n " ;
2597
- OS << " if(!Mnemonic.empty())\n " ;
2598
- OS << " MnemonicRange = std::equal_range(OperandMatchTable," ;
2599
- OS << " OperandMatchTable+"
2600
- << Info.OperandMatchInfo .size () << " , Mnemonic,\n "
2601
- << " LessOpcodeOperand());\n\n " ;
2607
+ if (HasMnemonicFirst) {
2608
+ OS << " auto MnemonicRange =\n " ;
2609
+ OS << " std::equal_range(std::begin(OperandMatchTable), "
2610
+ " std::end(OperandMatchTable),\n " ;
2611
+ OS << " Mnemonic, LessOpcodeOperand());\n\n " ;
2612
+ } else {
2613
+ OS << " auto MnemonicRange = std::make_pair(std::begin(OperandMatchTable),"
2614
+ " std::end(OperandMatchTable));\n " ;
2615
+ OS << " if (!Mnemonic.empty())\n " ;
2616
+ OS << " MnemonicRange =\n " ;
2617
+ OS << " std::equal_range(std::begin(OperandMatchTable), "
2618
+ " std::end(OperandMatchTable),\n " ;
2619
+ OS << " Mnemonic, LessOpcodeOperand());\n\n " ;
2620
+ }
2602
2621
2603
2622
OS << " if (MnemonicRange.first == MnemonicRange.second)\n " ;
2604
2623
OS << " return MatchOperand_NoMatch;\n\n " ;
@@ -2683,6 +2702,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
2683
2702
// Compute the information on the custom operand parsing.
2684
2703
Info.buildOperandMatchInfo ();
2685
2704
2705
+ bool HasMnemonicFirst = AsmParser->getValueAsBit (" HasMnemonicFirst" );
2706
+
2686
2707
// Write the output.
2687
2708
2688
2709
// Information for the class declaration.
@@ -2697,7 +2718,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
2697
2718
<< " &Operands);\n " ;
2698
2719
OS << " void convertToMapAndConstraints(unsigned Kind,\n " ;
2699
2720
OS << " const OperandVector &Operands) override;\n " ;
2700
- OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);\n " ;
2721
+ if (HasMnemonicFirst)
2722
+ OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);\n " ;
2701
2723
OS << " unsigned MatchInstructionImpl(const OperandVector &Operands,\n "
2702
2724
<< " MCInst &Inst,\n "
2703
2725
<< " uint64_t &ErrorInfo,"
@@ -2758,7 +2780,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
2758
2780
// Generate the convertToMCInst function to convert operands into an MCInst.
2759
2781
// Also, generate the convertToMapAndConstraints function for MS-style inline
2760
2782
// assembly. The latter doesn't actually generate a MCInst.
2761
- emitConvertFuncs (Target, ClassName, Info.Matchables , OS);
2783
+ emitConvertFuncs (Target, ClassName, Info.Matchables , HasMnemonicFirst, OS);
2762
2784
2763
2785
// Emit the enumeration for classes which participate in matching.
2764
2786
emitMatchClassEnumeration (Target, Info.Classes , OS);
@@ -2880,24 +2902,26 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
2880
2902
}
2881
2903
2882
2904
// A method to determine if a mnemonic is in the list.
2883
- OS << " bool " << Target.getName () << ClassName << " ::\n "
2884
- << " mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {\n " ;
2885
- OS << " // Find the appropriate table for this asm variant.\n " ;
2886
- OS << " const MatchEntry *Start, *End;\n " ;
2887
- OS << " switch (VariantID) {\n " ;
2888
- OS << " default: llvm_unreachable(\" invalid variant!\" );\n " ;
2889
- for (unsigned VC = 0 ; VC != VariantCount; ++VC) {
2890
- Record *AsmVariant = Target.getAsmParserVariant (VC);
2891
- int AsmVariantNo = AsmVariant->getValueAsInt (" Variant" );
2892
- OS << " case " << AsmVariantNo << " : Start = std::begin(MatchTable" << VC
2893
- << " ); End = std::end(MatchTable" << VC << " ); break;\n " ;
2905
+ if (HasMnemonicFirst) {
2906
+ OS << " bool " << Target.getName () << ClassName << " ::\n "
2907
+ << " mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {\n " ;
2908
+ OS << " // Find the appropriate table for this asm variant.\n " ;
2909
+ OS << " const MatchEntry *Start, *End;\n " ;
2910
+ OS << " switch (VariantID) {\n " ;
2911
+ OS << " default: llvm_unreachable(\" invalid variant!\" );\n " ;
2912
+ for (unsigned VC = 0 ; VC != VariantCount; ++VC) {
2913
+ Record *AsmVariant = Target.getAsmParserVariant (VC);
2914
+ int AsmVariantNo = AsmVariant->getValueAsInt (" Variant" );
2915
+ OS << " case " << AsmVariantNo << " : Start = std::begin(MatchTable" << VC
2916
+ << " ); End = std::end(MatchTable" << VC << " ); break;\n " ;
2917
+ }
2918
+ OS << " }\n " ;
2919
+ OS << " // Search the table.\n " ;
2920
+ OS << " auto MnemonicRange = " ;
2921
+ OS << " std::equal_range(Start, End, Mnemonic, LessOpcode());\n " ;
2922
+ OS << " return MnemonicRange.first != MnemonicRange.second;\n " ;
2923
+ OS << " }\n\n " ;
2894
2924
}
2895
- OS << " }\n " ;
2896
- OS << " // Search the table.\n " ;
2897
- OS << " std::pair<const MatchEntry*, const MatchEntry*> MnemonicRange =\n " ;
2898
- OS << " std::equal_range(Start, End, Mnemonic, LessOpcode());\n " ;
2899
- OS << " return MnemonicRange.first != MnemonicRange.second;\n " ;
2900
- OS << " }\n\n " ;
2901
2925
2902
2926
// Finally, build the match function.
2903
2927
OS << " unsigned " << Target.getName () << ClassName << " ::\n "
@@ -2906,8 +2930,10 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
2906
2930
<< " bool matchingInlineAsm, unsigned VariantID) {\n " ;
2907
2931
2908
2932
OS << " // Eliminate obvious mismatches.\n " ;
2909
- OS << " if (Operands.size() > " << MaxNumOperands << " ) {\n " ;
2910
- OS << " ErrorInfo = " << MaxNumOperands << " ;\n " ;
2933
+ OS << " if (Operands.size() > "
2934
+ << (MaxNumOperands + HasMnemonicFirst) << " ) {\n " ;
2935
+ OS << " ErrorInfo = "
2936
+ << (MaxNumOperands + HasMnemonicFirst) << " ;\n " ;
2911
2937
OS << " return Match_InvalidOperand;\n " ;
2912
2938
OS << " }\n\n " ;
2913
2939
@@ -2916,10 +2942,15 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
2916
2942
OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n " ;
2917
2943
2918
2944
OS << " // Get the instruction mnemonic, which is the first token.\n " ;
2919
- OS << " StringRef Mnemonic;\n " ;
2920
- OS << " if (Operands[0]->isToken())\n " ;
2921
- OS << " Mnemonic = ((" << Target.getName ()
2922
- << " Operand&)*Operands[0]).getToken();\n\n " ;
2945
+ if (HasMnemonicFirst) {
2946
+ OS << " StringRef Mnemonic = ((" << Target.getName ()
2947
+ << " Operand&)*Operands[0]).getToken();\n\n " ;
2948
+ } else {
2949
+ OS << " StringRef Mnemonic;\n " ;
2950
+ OS << " if (Operands[0]->isToken())\n " ;
2951
+ OS << " Mnemonic = ((" << Target.getName ()
2952
+ << " Operand&)*Operands[0]).getToken();\n\n " ;
2953
+ }
2923
2954
2924
2955
if (HasMnemonicAliases) {
2925
2956
OS << " // Process all MnemonicAliases to remap the mnemonic.\n " ;
@@ -2948,12 +2979,18 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
2948
2979
<< " ); End = std::end(MatchTable" << VC << " ); break;\n " ;
2949
2980
}
2950
2981
OS << " }\n " ;
2982
+
2951
2983
OS << " // Search the table.\n " ;
2952
- OS << " std::pair<const MatchEntry*, const MatchEntry*> "
2953
- " MnemonicRange(Start, End);\n " ;
2954
- OS << " unsigned SIndex = Mnemonic.empty() ? 0 : 1;\n " ;
2955
- OS << " if (!Mnemonic.empty())\n " ;
2956
- OS << " MnemonicRange = std::equal_range(Start, End, Mnemonic.lower(), LessOpcode());\n\n " ;
2984
+ if (HasMnemonicFirst) {
2985
+ OS << " auto MnemonicRange = "
2986
+ " std::equal_range(Start, End, Mnemonic, LessOpcode());\n\n " ;
2987
+ } else {
2988
+ OS << " auto MnemonicRange = std::make_pair(Start, End);\n " ;
2989
+ OS << " unsigned SIndex = Mnemonic.empty() ? 0 : 1;\n " ;
2990
+ OS << " if (!Mnemonic.empty())\n " ;
2991
+ OS << " MnemonicRange = "
2992
+ " std::equal_range(Start, End, Mnemonic.lower(), LessOpcode());\n\n " ;
2993
+ }
2957
2994
2958
2995
OS << " // Return a more specific error code if no mnemonics match.\n " ;
2959
2996
OS << " if (MnemonicRange.first == MnemonicRange.second)\n " ;
@@ -2963,16 +3000,25 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
2963
3000
<< " *ie = MnemonicRange.second;\n " ;
2964
3001
OS << " it != ie; ++it) {\n " ;
2965
3002
3003
+ if (HasMnemonicFirst) {
3004
+ OS << " // equal_range guarantees that instruction mnemonic matches.\n " ;
3005
+ OS << " assert(Mnemonic == it->getMnemonic());\n " ;
3006
+ }
3007
+
2966
3008
// Emit check that the subclasses match.
2967
3009
OS << " bool OperandsValid = true;\n " ;
2968
- OS << " for (unsigned i = SIndex; i != " << MaxNumOperands << " ; ++i) {\n " ;
3010
+ OS << " for (unsigned i = " << (HasMnemonicFirst ? " 0" : " SIndex" )
3011
+ << " ; i != " << MaxNumOperands << " ; ++i) {\n " ;
2969
3012
OS << " auto Formal = static_cast<MatchClassKind>(it->Classes[i]);\n " ;
2970
- OS << " if (i >= Operands.size()) {\n " ;
3013
+ OS << " if (i" << (HasMnemonicFirst ? " +1" : " " )
3014
+ << " >= Operands.size()) {\n " ;
2971
3015
OS << " OperandsValid = (Formal == " <<" InvalidMatchClass);\n " ;
2972
- OS << " if (!OperandsValid) ErrorInfo = i;\n " ;
3016
+ OS << " if (!OperandsValid) ErrorInfo = i"
3017
+ << (HasMnemonicFirst ? " +1" : " " ) << " ;\n " ;
2973
3018
OS << " break;\n " ;
2974
3019
OS << " }\n " ;
2975
- OS << " MCParsedAsmOperand &Actual = *Operands[i];\n " ;
3020
+ OS << " MCParsedAsmOperand &Actual = *Operands[i"
3021
+ << (HasMnemonicFirst ? " +1" : " " ) << " ];\n " ;
2976
3022
OS << " unsigned Diag = validateOperandClass(Actual, Formal);\n " ;
2977
3023
OS << " if (Diag == Match_Success)\n " ;
2978
3024
OS << " continue;\n " ;
@@ -2988,8 +3034,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
2988
3034
OS << " // If we already had a match that only failed due to a\n " ;
2989
3035
OS << " // target predicate, that diagnostic is preferred.\n " ;
2990
3036
OS << " if (!HadMatchOtherThanPredicate &&\n " ;
2991
- OS << " (it == MnemonicRange.first || ErrorInfo <= i)) {\n " ;
2992
- OS << " ErrorInfo = i;\n " ;
3037
+ OS << " (it == MnemonicRange.first || ErrorInfo <= i"
3038
+ << (HasMnemonicFirst ? " +1" : " " ) << " )) {\n " ;
3039
+ OS << " ErrorInfo = i" << (HasMnemonicFirst ? " +1" : " " ) << " ;\n " ;
2993
3040
OS << " // InvalidOperand is the default. Prefer specificity.\n " ;
2994
3041
OS << " if (Diag != Match_InvalidOperand)\n " ;
2995
3042
OS << " RetCode = Diag;\n " ;
@@ -3064,7 +3111,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
3064
3111
3065
3112
if (!Info.OperandMatchInfo .empty ())
3066
3113
emitCustomOperandParsing (OS, Target, Info, ClassName, StringTable,
3067
- MaxMnemonicIndex);
3114
+ MaxMnemonicIndex, HasMnemonicFirst );
3068
3115
3069
3116
OS << " #endif // GET_MATCHER_IMPLEMENTATION\n\n " ;
3070
3117
}
0 commit comments