7
7
// ===----------------------------------------------------------------------===//
8
8
9
9
#include " llvm/Support/RISCVISAInfo.h"
10
+ #include " llvm/ADT/MapVector.h"
10
11
#include " llvm/ADT/STLExtras.h"
11
12
#include " llvm/ADT/SetVector.h"
12
13
#include " llvm/ADT/StringExtras.h"
@@ -703,6 +704,106 @@ RISCVISAInfo::parseNormalizedArchString(StringRef Arch) {
703
704
return std::move (ISAInfo);
704
705
}
705
706
707
+ static Error splitExtsByUnderscore (StringRef Exts,
708
+ std::vector<std::string> &SplitExts) {
709
+ SmallVector<StringRef, 8 > Split;
710
+ if (Exts.empty ())
711
+ return Error::success ();
712
+
713
+ Exts.split (Split, " _" );
714
+
715
+ for (auto Ext : Split) {
716
+ if (Ext.empty ())
717
+ return createStringError (errc::invalid_argument,
718
+ " extension name missing after separator '_'" );
719
+
720
+ SplitExts.push_back (Ext.str ());
721
+ }
722
+ return Error::success ();
723
+ }
724
+
725
+ static Error processMultiLetterExtension (
726
+ StringRef RawExt,
727
+ MapVector<std::string, RISCVISAInfo::ExtensionVersion,
728
+ std::map<std::string, unsigned >> &SeenExtMap,
729
+ bool IgnoreUnknown, bool EnableExperimentalExtension,
730
+ bool ExperimentalExtensionVersionCheck) {
731
+ StringRef Type = getExtensionType (RawExt);
732
+ StringRef Desc = getExtensionTypeDesc (RawExt);
733
+ auto Pos = findLastNonVersionCharacter (RawExt) + 1 ;
734
+ StringRef Name (RawExt.substr (0 , Pos));
735
+ StringRef Vers (RawExt.substr (Pos));
736
+
737
+ if (Type.empty ()) {
738
+ if (IgnoreUnknown)
739
+ return Error::success ();
740
+ return createStringError (errc::invalid_argument,
741
+ " invalid extension prefix '" + RawExt + " '" );
742
+ }
743
+
744
+ if (!IgnoreUnknown && Name.size () == Type.size ())
745
+ return createStringError (errc::invalid_argument,
746
+ " %s name missing after '%s'" , Desc.str ().c_str (),
747
+ Type.str ().c_str ());
748
+
749
+ unsigned Major, Minor, ConsumeLength;
750
+ if (auto E = getExtensionVersion (Name, Vers, Major, Minor, ConsumeLength,
751
+ EnableExperimentalExtension,
752
+ ExperimentalExtensionVersionCheck)) {
753
+ if (IgnoreUnknown) {
754
+ consumeError (std::move (E));
755
+ return Error::success ();
756
+ }
757
+ return E;
758
+ }
759
+
760
+ // Check if duplicated extension.
761
+ if (!IgnoreUnknown && SeenExtMap.contains (Name.str ()))
762
+ return createStringError (errc::invalid_argument, " duplicated %s '%s'" ,
763
+ Desc.str ().c_str (), Name.str ().c_str ());
764
+
765
+ if (IgnoreUnknown && !RISCVISAInfo::isSupportedExtension (Name))
766
+ return Error::success ();
767
+
768
+ SeenExtMap[Name.str ()] = {Major, Minor};
769
+ return Error::success ();
770
+ }
771
+
772
+ static Error processSingleLetterExtension (
773
+ StringRef &RawExt,
774
+ MapVector<std::string, RISCVISAInfo::ExtensionVersion,
775
+ std::map<std::string, unsigned >> &SeenExtMap,
776
+ bool IgnoreUnknown, bool EnableExperimentalExtension,
777
+ bool ExperimentalExtensionVersionCheck) {
778
+ unsigned Major, Minor, ConsumeLength;
779
+ StringRef Name = RawExt.take_front (1 );
780
+ RawExt.consume_front (Name);
781
+ if (auto E = getExtensionVersion (Name, RawExt, Major, Minor, ConsumeLength,
782
+ EnableExperimentalExtension,
783
+ ExperimentalExtensionVersionCheck)) {
784
+ if (IgnoreUnknown) {
785
+ consumeError (std::move (E));
786
+ RawExt = RawExt.substr (ConsumeLength);
787
+ return Error::success ();
788
+ }
789
+ return E;
790
+ }
791
+
792
+ RawExt = RawExt.substr (ConsumeLength);
793
+
794
+ // Check if duplicated extension.
795
+ if (!IgnoreUnknown && SeenExtMap.contains (Name.str ()))
796
+ return createStringError (errc::invalid_argument,
797
+ " duplicated standard user-level extension '%s'" ,
798
+ Name.str ().c_str ());
799
+
800
+ if (IgnoreUnknown && !RISCVISAInfo::isSupportedExtension (Name))
801
+ return Error::success ();
802
+
803
+ SeenExtMap[Name.str ()] = {Major, Minor};
804
+ return Error::success ();
805
+ }
806
+
706
807
llvm::Expected<std::unique_ptr<RISCVISAInfo>>
707
808
RISCVISAInfo::parseArchString (StringRef Arch, bool EnableExperimentalExtension,
708
809
bool ExperimentalExtensionVersionCheck,
@@ -723,6 +824,9 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
723
824
724
825
unsigned XLen = HasRV64 ? 64 : 32 ;
725
826
std::unique_ptr<RISCVISAInfo> ISAInfo (new RISCVISAInfo (XLen));
827
+ MapVector<std::string, RISCVISAInfo::ExtensionVersion,
828
+ std::map<std::string, unsigned >>
829
+ SeenExtMap;
726
830
727
831
// The canonical order specified in ISA manual.
728
832
// Ref: Table 22.1 in RISC-V User-Level ISA V2.2
@@ -753,17 +857,6 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
753
857
// Skip rvxxx
754
858
StringRef Exts = Arch.substr (5 );
755
859
756
- // Remove multi-letter standard extensions, non-standard extensions and
757
- // supervisor-level extensions. They have 'z', 'x', 's' prefixes.
758
- // Parse them at the end.
759
- // Find the very first occurrence of 's', 'x' or 'z'.
760
- StringRef OtherExts;
761
- size_t Pos = Exts.find_first_of (" zsx" );
762
- if (Pos != StringRef::npos) {
763
- OtherExts = Exts.substr (Pos);
764
- Exts = Exts.substr (0 , Pos);
765
- }
766
-
767
860
unsigned Major, Minor, ConsumeLength;
768
861
if (Baseline == ' g' ) {
769
862
// Versions for g are disallowed, and this was checked for previously.
@@ -773,9 +866,10 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
773
866
// version since the we don't have clear version scheme for that on
774
867
// ISA spec.
775
868
for (const auto *Ext : RISCVGImplications) {
776
- if (auto Version = findDefaultVersion (Ext))
777
- ISAInfo->addExtension (Ext, *Version);
778
- else
869
+ if (auto Version = findDefaultVersion (Ext)) {
870
+ // Postpone AddExtension until end of this function
871
+ SeenExtMap[Ext] = {Version->Major , Version->Minor };
872
+ } else
779
873
llvm_unreachable (" Default extension version not found?" );
780
874
}
781
875
} else {
@@ -793,151 +887,69 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
793
887
Minor = Version->Minor ;
794
888
}
795
889
796
- ISAInfo->addExtension (StringRef (&Baseline, 1 ), {Major, Minor});
890
+ // Postpone AddExtension until end of this function
891
+ SeenExtMap[StringRef (&Baseline, 1 ).str ()] = {Major, Minor};
797
892
}
798
893
799
894
// Consume the base ISA version number and any '_' between rvxxx and the
800
895
// first extension
801
896
Exts = Exts.drop_front (ConsumeLength);
802
897
Exts.consume_front (" _" );
803
898
804
- auto StdExtsItr = StdExts.begin ();
805
- auto StdExtsEnd = StdExts.end ();
806
- auto GoToNextExt = [](StringRef::iterator &I, unsigned ConsumeLength,
807
- StringRef::iterator E) {
808
- I += 1 + ConsumeLength;
809
- if (I != E && *I == ' _' )
810
- ++I;
811
- };
812
- for (auto I = Exts.begin (), E = Exts.end (); I != E;) {
813
- char C = *I;
814
-
815
- // Check ISA extensions are specified in the canonical order.
816
- while (StdExtsItr != StdExtsEnd && *StdExtsItr != C)
817
- ++StdExtsItr;
818
-
819
- if (StdExtsItr == StdExtsEnd) {
820
- // Either c contains a valid extension but it was not given in
821
- // canonical order or it is an invalid extension.
822
- if (StdExts.contains (C)) {
823
- return createStringError (
824
- errc::invalid_argument,
825
- " standard user-level extension not given in canonical order '" +
826
- Twine (C) + " '" );
827
- }
828
-
829
- return createStringError (errc::invalid_argument,
830
- " invalid standard user-level extension '" +
831
- Twine (C) + " '" );
832
- }
833
-
834
- // Move to next char to prevent repeated letter.
835
- ++StdExtsItr;
836
-
837
- StringRef Next;
838
- unsigned Major, Minor, ConsumeLength;
839
- if (std::next (I) != E)
840
- Next = StringRef (std::next (I), E - std::next (I));
841
- if (auto E = getExtensionVersion (StringRef (&C, 1 ), Next, Major, Minor,
842
- ConsumeLength, EnableExperimentalExtension,
843
- ExperimentalExtensionVersionCheck)) {
844
- if (IgnoreUnknown) {
845
- consumeError (std::move (E));
846
- GoToNextExt (I, ConsumeLength, Exts.end ());
847
- continue ;
848
- }
849
- return std::move (E);
850
- }
851
-
852
- // The order is OK, then push it into features.
853
- // Currently LLVM supports only "mafdcvh".
854
- if (!isSupportedExtension (StringRef (&C, 1 ))) {
855
- if (IgnoreUnknown) {
856
- GoToNextExt (I, ConsumeLength, Exts.end ());
857
- continue ;
899
+ std::vector<std::string> SplittedExts;
900
+ if (auto E = splitExtsByUnderscore (Exts, SplittedExts))
901
+ return std::move (E);
902
+
903
+ for (auto &Ext : SplittedExts) {
904
+ StringRef CurrExt = Ext;
905
+ while (!CurrExt.empty ()) {
906
+ if (AllStdExts.contains (CurrExt.front ())) {
907
+ if (auto E = processSingleLetterExtension (
908
+ CurrExt, SeenExtMap, IgnoreUnknown, EnableExperimentalExtension,
909
+ ExperimentalExtensionVersionCheck))
910
+ return std::move (E);
911
+ } else if (CurrExt.front () == ' z' || CurrExt.front () == ' s' ||
912
+ CurrExt.front () == ' x' ) {
913
+ // Handle other types of extensions other than the standard
914
+ // general purpose and standard user-level extensions.
915
+ // Parse the ISA string containing non-standard user-level
916
+ // extensions, standard supervisor-level extensions and
917
+ // non-standard supervisor-level extensions.
918
+ // These extensions start with 'z', 's', 'x' prefixes, might have a
919
+ // version number (major, minor) and are separated by a single
920
+ // underscore '_'. We do not enforce a canonical order for them.
921
+ if (auto E = processMultiLetterExtension (
922
+ CurrExt, SeenExtMap, IgnoreUnknown, EnableExperimentalExtension,
923
+ ExperimentalExtensionVersionCheck))
924
+ return std::move (E);
925
+ // Multi-letter extension must be seperate following extension with
926
+ // underscore
927
+ break ;
928
+ } else {
929
+ // FIXME: Could it be ignored by IgnoreUnknown?
930
+ return createStringError (errc::invalid_argument,
931
+ " invalid standard user-level extension '%c'" ,
932
+ CurrExt.front ());
858
933
}
859
- return createStringError (errc::invalid_argument,
860
- " unsupported standard user-level extension '" +
861
- Twine (C) + " '" );
862
934
}
863
- ISAInfo->addExtension (StringRef (&C, 1 ), {Major, Minor});
864
-
865
- // Consume full extension name and version, including any optional '_'
866
- // between this extension and the next
867
- GoToNextExt (I, ConsumeLength, Exts.end ());
868
935
}
869
936
870
- // Handle other types of extensions other than the standard
871
- // general purpose and standard user-level extensions.
872
- // Parse the ISA string containing non-standard user-level
873
- // extensions, standard supervisor-level extensions and
874
- // non-standard supervisor-level extensions.
875
- // These extensions start with 'z', 's', 'x' prefixes, might have a version
876
- // number (major, minor) and are separated by a single underscore '_'. We do
877
- // not enforce a canonical order for them.
878
- // Set the hardware features for the extensions that are supported.
879
-
880
- // Multi-letter extensions are seperated by a single underscore
881
- // as described in RISC-V User-Level ISA V2.2.
882
- SmallVector<StringRef, 8 > Split;
883
- OtherExts.split (Split, ' _' );
884
-
885
- SmallVector<StringRef, 8 > AllExts;
886
- if (Split.size () > 1 || Split[0 ] != " " ) {
887
- for (StringRef Ext : Split) {
888
- if (Ext.empty ())
889
- return createStringError (errc::invalid_argument,
890
- " extension name missing after separator '_'" );
891
-
892
- StringRef Type = getExtensionType (Ext);
893
- StringRef Desc = getExtensionTypeDesc (Ext);
894
- auto Pos = findLastNonVersionCharacter (Ext) + 1 ;
895
- StringRef Name (Ext.substr (0 , Pos));
896
- StringRef Vers (Ext.substr (Pos));
897
-
898
- if (Type.empty ()) {
899
- if (IgnoreUnknown)
900
- continue ;
901
- return createStringError (errc::invalid_argument,
902
- " invalid extension prefix '" + Ext + " '" );
903
- }
937
+ // Check all Extensions are supported.
938
+ for (auto &SeenExtAndVers : SeenExtMap) {
939
+ const std::string &ExtName = SeenExtAndVers.first ;
940
+ RISCVISAInfo::ExtensionVersion ExtVers = SeenExtAndVers.second ;
904
941
905
- if (!IgnoreUnknown && Name.size () == Type.size ())
906
- return createStringError (errc::invalid_argument,
907
- Desc + " name missing after '" + Type + " '" );
908
-
909
- unsigned Major, Minor, ConsumeLength;
910
- if (auto E = getExtensionVersion (Name, Vers, Major, Minor, ConsumeLength,
911
- EnableExperimentalExtension,
912
- ExperimentalExtensionVersionCheck)) {
913
- if (IgnoreUnknown) {
914
- consumeError (std::move (E));
915
- continue ;
916
- }
917
- return std::move (E);
942
+ if (!RISCVISAInfo::isSupportedExtension (ExtName)) {
943
+ if (ExtName.size () == 1 ) {
944
+ return createStringError (
945
+ errc::invalid_argument,
946
+ " unsupported standard user-level extension '%s'" , ExtName.c_str ());
918
947
}
919
-
920
- // Check if duplicated extension.
921
- if (!IgnoreUnknown && llvm::is_contained (AllExts, Name))
922
- return createStringError (errc::invalid_argument,
923
- " duplicated " + Desc + " '" + Name + " '" );
924
-
925
- if (IgnoreUnknown && !isSupportedExtension (Name))
926
- continue ;
927
-
928
- ISAInfo->addExtension (Name, {Major, Minor});
929
- // Extension format is correct, keep parsing the extensions.
930
- // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
931
- AllExts.push_back (Name);
932
- }
933
- }
934
-
935
- for (auto Ext : AllExts) {
936
- if (!isSupportedExtension (Ext)) {
937
- StringRef Desc = getExtensionTypeDesc (getExtensionType (Ext));
938
- return createStringError (errc::invalid_argument,
939
- " unsupported " + Desc + " '" + Ext + " '" );
948
+ return createStringError (errc::invalid_argument, " unsupported %s '%s'" ,
949
+ getExtensionTypeDesc (ExtName).str ().c_str (),
950
+ ExtName.c_str ());
940
951
}
952
+ ISAInfo->addExtension (ExtName, ExtVers);
941
953
}
942
954
943
955
return RISCVISAInfo::postProcessAndChecking (std::move (ISAInfo));
0 commit comments