@@ -1246,6 +1246,7 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
1246
1246
bool isForcedDPP () const { return ForcedDPP; }
1247
1247
bool isForcedSDWA () const { return ForcedSDWA; }
1248
1248
ArrayRef<unsigned > getMatchedVariants () const ;
1249
+ StringRef getMatchedVariantName () const ;
1249
1250
1250
1251
std::unique_ptr<AMDGPUOperand> parseRegister (bool RestoreOnFailure = false );
1251
1252
bool ParseRegister (unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc,
@@ -1369,6 +1370,13 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
1369
1370
bool isInlineConstant (const MCInst &Inst, unsigned OpIdx) const ;
1370
1371
unsigned findImplicitSGPRReadInVOP (const MCInst &Inst) const ;
1371
1372
1373
+ bool isSupportedMnemo (StringRef Mnemo,
1374
+ const FeatureBitset &FBS);
1375
+ bool isSupportedMnemo (StringRef Mnemo,
1376
+ const FeatureBitset &FBS,
1377
+ ArrayRef<unsigned > Variants);
1378
+ bool checkUnsupportedInstruction (StringRef Name, const SMLoc &IDLoc);
1379
+
1372
1380
bool isId (const StringRef Id) const ;
1373
1381
bool isId (const AsmToken &Token, const StringRef Id) const ;
1374
1382
bool isToken (const AsmToken::TokenKind Kind) const ;
@@ -2837,6 +2845,15 @@ unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2837
2845
return Match_Success;
2838
2846
}
2839
2847
2848
+ static ArrayRef<unsigned > getAllVariants () {
2849
+ static const unsigned Variants[] = {
2850
+ AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3,
2851
+ AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::SDWA9, AMDGPUAsmVariants::DPP
2852
+ };
2853
+
2854
+ return makeArrayRef (Variants);
2855
+ }
2856
+
2840
2857
// What asm variants we should check
2841
2858
ArrayRef<unsigned > AMDGPUAsmParser::getMatchedVariants () const {
2842
2859
if (getForcedEncodingSize () == 32 ) {
@@ -2860,12 +2877,23 @@ ArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const {
2860
2877
return makeArrayRef (Variants);
2861
2878
}
2862
2879
2863
- static const unsigned Variants[] = {
2864
- AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3,
2865
- AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::SDWA9, AMDGPUAsmVariants::DPP
2866
- };
2880
+ return getAllVariants ();
2881
+ }
2867
2882
2868
- return makeArrayRef (Variants);
2883
+ StringRef AMDGPUAsmParser::getMatchedVariantName () const {
2884
+ if (getForcedEncodingSize () == 32 )
2885
+ return " e32" ;
2886
+
2887
+ if (isForcedVOP3 ())
2888
+ return " e64" ;
2889
+
2890
+ if (isForcedSDWA ())
2891
+ return " sdwa" ;
2892
+
2893
+ if (isForcedDPP ())
2894
+ return " dpp" ;
2895
+
2896
+ return " " ;
2869
2897
}
2870
2898
2871
2899
unsigned AMDGPUAsmParser::findImplicitSGPRReadInVOP (const MCInst &Inst) const {
@@ -3753,6 +3781,57 @@ static std::string AMDGPUMnemonicSpellCheck(StringRef S,
3753
3781
const FeatureBitset &FBS,
3754
3782
unsigned VariantID = 0 );
3755
3783
3784
+ static bool AMDGPUCheckMnemonic (StringRef Mnemonic,
3785
+ const FeatureBitset &AvailableFeatures,
3786
+ unsigned VariantID);
3787
+
3788
+ bool AMDGPUAsmParser::isSupportedMnemo (StringRef Mnemo,
3789
+ const FeatureBitset &FBS) {
3790
+ return isSupportedMnemo (Mnemo, FBS, getAllVariants ());
3791
+ }
3792
+
3793
+ bool AMDGPUAsmParser::isSupportedMnemo (StringRef Mnemo,
3794
+ const FeatureBitset &FBS,
3795
+ ArrayRef<unsigned > Variants) {
3796
+ for (auto Variant : Variants) {
3797
+ if (AMDGPUCheckMnemonic (Mnemo, FBS, Variant))
3798
+ return true ;
3799
+ }
3800
+
3801
+ return false ;
3802
+ }
3803
+
3804
+ bool AMDGPUAsmParser::checkUnsupportedInstruction (StringRef Mnemo,
3805
+ const SMLoc &IDLoc) {
3806
+ FeatureBitset FBS = ComputeAvailableFeatures (getSTI ().getFeatureBits ());
3807
+
3808
+ // Check if requested instruction variant is supported.
3809
+ if (isSupportedMnemo (Mnemo, FBS, getMatchedVariants ()))
3810
+ return false ;
3811
+
3812
+ // This instruction is not supported.
3813
+ // Clear any other pending errors because they are no longer relevant.
3814
+ getParser ().clearPendingErrors ();
3815
+
3816
+ // Requested instruction variant is not supported.
3817
+ // Check if any other variants are supported.
3818
+ StringRef VariantName = getMatchedVariantName ();
3819
+ if (!VariantName.empty () && isSupportedMnemo (Mnemo, FBS)) {
3820
+ return Error (IDLoc,
3821
+ Twine (VariantName,
3822
+ " variant of this instruction is not supported" ));
3823
+ }
3824
+
3825
+ // Finally check if this instruction is supported on any other GPU.
3826
+ if (isSupportedMnemo (Mnemo, FeatureBitset ().set ())) {
3827
+ return Error (IDLoc, " instruction not supported on this GPU" );
3828
+ }
3829
+
3830
+ // Instruction not supported on any GPU. Probably a typo.
3831
+ std::string Suggestion = AMDGPUMnemonicSpellCheck (Mnemo, FBS);
3832
+ return Error (IDLoc, " invalid instruction" + Suggestion);
3833
+ }
3834
+
3756
3835
bool AMDGPUAsmParser::MatchAndEmitInstruction (SMLoc IDLoc, unsigned &Opcode,
3757
3836
OperandVector &Operands,
3758
3837
MCStreamer &Out,
@@ -3782,27 +3861,26 @@ bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3782
3861
break ;
3783
3862
}
3784
3863
3785
- switch (Result) {
3786
- default : break ;
3787
- case Match_Success:
3864
+ if (Result == Match_Success) {
3788
3865
if (!validateInstruction (Inst, IDLoc, Operands)) {
3789
3866
return true ;
3790
3867
}
3791
3868
Inst.setLoc (IDLoc);
3792
3869
Out.emitInstruction (Inst, getSTI ());
3793
3870
return false ;
3871
+ }
3872
+
3873
+ StringRef Mnemo = ((AMDGPUOperand &)*Operands[0 ]).getToken ();
3874
+ if (checkUnsupportedInstruction (Mnemo, IDLoc)) {
3875
+ return true ;
3876
+ }
3794
3877
3878
+ switch (Result) {
3879
+ default : break ;
3795
3880
case Match_MissingFeature:
3881
+ // FIXME: this case should be analyzed and error message corrected.
3796
3882
return Error (IDLoc, " instruction not supported on this GPU" );
3797
3883
3798
- case Match_MnemonicFail: {
3799
- FeatureBitset FBS = ComputeAvailableFeatures (getSTI ().getFeatureBits ());
3800
- std::string Suggestion = AMDGPUMnemonicSpellCheck (
3801
- ((AMDGPUOperand &)*Operands[0 ]).getToken (), FBS);
3802
- return Error (IDLoc, " invalid instruction" + Suggestion,
3803
- ((AMDGPUOperand &)*Operands[0 ]).getLocRange ());
3804
- }
3805
-
3806
3884
case Match_InvalidOperand: {
3807
3885
SMLoc ErrorLoc = IDLoc;
3808
3886
if (ErrorInfo != ~0ULL ) {
@@ -3819,6 +3897,8 @@ bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3819
3897
case Match_PreferE32:
3820
3898
return Error (IDLoc, " internal error: instruction without _e64 suffix "
3821
3899
" should be encoded as e32" );
3900
+ case Match_MnemonicFail:
3901
+ llvm_unreachable (" Invalid instructions should have been handled already" );
3822
3902
}
3823
3903
llvm_unreachable (" Implement any new match types added!" );
3824
3904
}
@@ -4771,6 +4851,7 @@ bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
4771
4851
Parser.Lex ();
4772
4852
4773
4853
if (Res != MatchOperand_Success) {
4854
+ checkUnsupportedInstruction (Name, NameLoc);
4774
4855
if (!Parser.hasPendingError ()) {
4775
4856
// FIXME: use real operand location rather than the current location.
4776
4857
StringRef Msg =
@@ -7469,6 +7550,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAMDGPUAsmParser() {
7469
7550
#define GET_REGISTER_MATCHER
7470
7551
#define GET_MATCHER_IMPLEMENTATION
7471
7552
#define GET_MNEMONIC_SPELL_CHECKER
7553
+ #define GET_MNEMONIC_CHECKER
7472
7554
#include " AMDGPUGenAsmMatcher.inc"
7473
7555
7474
7556
// This fuction should be defined after auto-generated include so that we have
0 commit comments