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