77// ===----------------------------------------------------------------------===//
88
99#include " llvm/Support/RISCVISAInfo.h"
10- #include " llvm/ADT/MapVector.h"
1110#include " llvm/ADT/STLExtras.h"
1211#include " llvm/ADT/SetVector.h"
1312#include " llvm/ADT/StringExtras.h"
@@ -704,106 +703,6 @@ RISCVISAInfo::parseNormalizedArchString(StringRef Arch) {
704703 return std::move (ISAInfo);
705704}
706705
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-
807706llvm::Expected<std::unique_ptr<RISCVISAInfo>>
808707RISCVISAInfo::parseArchString (StringRef Arch, bool EnableExperimentalExtension,
809708 bool ExperimentalExtensionVersionCheck,
@@ -824,9 +723,6 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
824723
825724 unsigned XLen = HasRV64 ? 64 : 32 ;
826725 std::unique_ptr<RISCVISAInfo> ISAInfo (new RISCVISAInfo (XLen));
827- MapVector<std::string, RISCVISAInfo::ExtensionVersion,
828- std::map<std::string, unsigned >>
829- SeenExtMap;
830726
831727 // The canonical order specified in ISA manual.
832728 // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
@@ -857,6 +753,17 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
857753 // Skip rvxxx
858754 StringRef Exts = Arch.substr (5 );
859755
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+
860767 unsigned Major, Minor, ConsumeLength;
861768 if (Baseline == ' g' ) {
862769 // Versions for g are disallowed, and this was checked for previously.
@@ -866,10 +773,9 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
866773 // version since the we don't have clear version scheme for that on
867774 // ISA spec.
868775 for (const auto *Ext : RISCVGImplications) {
869- if (auto Version = findDefaultVersion (Ext)) {
870- // Postpone AddExtension until end of this function
871- SeenExtMap[Ext] = {Version->Major , Version->Minor };
872- } else
776+ if (auto Version = findDefaultVersion (Ext))
777+ ISAInfo->addExtension (Ext, *Version);
778+ else
873779 llvm_unreachable (" Default extension version not found?" );
874780 }
875781 } else {
@@ -887,69 +793,151 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
887793 Minor = Version->Minor ;
888794 }
889795
890- // Postpone AddExtension until end of this function
891- SeenExtMap[StringRef (&Baseline, 1 ).str ()] = {Major, Minor};
796+ ISAInfo->addExtension (StringRef (&Baseline, 1 ), {Major, Minor});
892797 }
893798
894799 // Consume the base ISA version number and any '_' between rvxxx and the
895800 // first extension
896801 Exts = Exts.drop_front (ConsumeLength);
897802 Exts.consume_front (" _" );
898803
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 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 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 ());
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 ;
933858 }
859+ return createStringError (errc::invalid_argument,
860+ " unsupported standard user-level extension '" +
861+ Twine (C) + " '" );
934862 }
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 ());
935868 }
936869
937- // Check all Extensions are supported.
938- for (auto &SeenExtAndVers : SeenExtMap) {
939- const std::string &ExtName = SeenExtAndVers.first ;
940- RISCVISAInfo::ExtensionVersion ExtVers = SeenExtAndVers.second ;
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, ' _' );
941884
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 ());
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+ }
904+
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);
947918 }
948- return createStringError (errc::invalid_argument, " unsupported %s '%s'" ,
949- getExtensionTypeDesc (ExtName).str ().c_str (),
950- ExtName.c_str ());
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 + " '" );
951940 }
952- ISAInfo->addExtension (ExtName, ExtVers);
953941 }
954942
955943 return RISCVISAInfo::postProcessAndChecking (std::move (ISAInfo));
0 commit comments