77// ===----------------------------------------------------------------------===//
88
99#include " llvm/Support/RISCVISAInfo.h"
10+ #include " llvm/ADT/MapVector.h"
1011#include " llvm/ADT/STLExtras.h"
1112#include " llvm/ADT/SetVector.h"
1213#include " llvm/ADT/StringExtras.h"
@@ -703,6 +704,106 @@ RISCVISAInfo::parseNormalizedArchString(StringRef Arch) {
703704 return std::move (ISAInfo);
704705}
705706
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+
706807llvm::Expected<std::unique_ptr<RISCVISAInfo>>
707808RISCVISAInfo::parseArchString (StringRef Arch, bool EnableExperimentalExtension,
708809 bool ExperimentalExtensionVersionCheck,
@@ -723,6 +824,9 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
723824
724825 unsigned XLen = HasRV64 ? 64 : 32 ;
725826 std::unique_ptr<RISCVISAInfo> ISAInfo (new RISCVISAInfo (XLen));
827+ MapVector<std::string, RISCVISAInfo::ExtensionVersion,
828+ std::map<std::string, unsigned >>
829+ SeenExtMap;
726830
727831 // The canonical order specified in ISA manual.
728832 // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
@@ -753,17 +857,6 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
753857 // Skip rvxxx
754858 StringRef Exts = Arch.substr (5 );
755859
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-
767860 unsigned Major, Minor, ConsumeLength;
768861 if (Baseline == ' g' ) {
769862 // Versions for g are disallowed, and this was checked for previously.
@@ -773,9 +866,10 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
773866 // version since the we don't have clear version scheme for that on
774867 // ISA spec.
775868 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
779873 llvm_unreachable (" Default extension version not found?" );
780874 }
781875 } else {
@@ -793,151 +887,69 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
793887 Minor = Version->Minor ;
794888 }
795889
796- ISAInfo->addExtension (StringRef (&Baseline, 1 ), {Major, Minor});
890+ // Postpone AddExtension until end of this function
891+ SeenExtMap[StringRef (&Baseline, 1 ).str ()] = {Major, Minor};
797892 }
798893
799894 // Consume the base ISA version number and any '_' between rvxxx and the
800895 // first extension
801896 Exts = Exts.drop_front (ConsumeLength);
802897 Exts.consume_front (" _" );
803898
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 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 ());
858933 }
859- return createStringError (errc::invalid_argument,
860- " unsupported standard user-level extension '" +
861- Twine (C) + " '" );
862934 }
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 ());
868935 }
869936
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 ;
904941
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 ());
918947 }
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 ());
940951 }
952+ ISAInfo->addExtension (ExtName, ExtVers);
941953 }
942954
943955 return RISCVISAInfo::postProcessAndChecking (std::move (ISAInfo));
0 commit comments