@@ -179,6 +179,12 @@ class RISCVAsmParser : public MCTargetAsmParser {
179179 bool parseDirectiveInsn (SMLoc L);
180180 bool parseDirectiveVariantCC ();
181181
182+ // / Helper to reset target features for a new arch string. It
183+ // / also records the new arch string that is expanded by RISCVISAInfo
184+ // / and reports error for invalid arch string.
185+ bool resetToArch (StringRef Arch, SMLoc Loc, std::string &Result,
186+ bool FromOptionDirective);
187+
182188 void setFeatureBits (uint64_t Feature, StringRef FeatureString) {
183189 if (!(getSTI ().getFeatureBits ()[Feature])) {
184190 MCSubtargetInfo &STI = copySTI ();
@@ -2039,6 +2045,49 @@ bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) {
20392045 return true ;
20402046}
20412047
2048+ bool RISCVAsmParser::resetToArch (StringRef Arch, SMLoc Loc, std::string &Result,
2049+ bool FromOptionDirective) {
2050+ for (auto Feature : RISCVFeatureKV)
2051+ if (llvm::RISCVISAInfo::isSupportedExtensionFeature (Feature.Key ))
2052+ clearFeatureBits (Feature.Value , Feature.Key );
2053+
2054+ auto ParseResult = llvm::RISCVISAInfo::parseArchString (
2055+ Arch, /* EnableExperimentalExtension=*/ true ,
2056+ /* ExperimentalExtensionVersionCheck=*/ true );
2057+ if (!ParseResult) {
2058+ std::string Buffer;
2059+ raw_string_ostream OutputErrMsg (Buffer);
2060+ handleAllErrors (ParseResult.takeError (), [&](llvm::StringError &ErrMsg) {
2061+ OutputErrMsg << " invalid arch name '" << Arch << " ', "
2062+ << ErrMsg.getMessage ();
2063+ });
2064+
2065+ return Error (Loc, OutputErrMsg.str ());
2066+ }
2067+ auto &ISAInfo = *ParseResult;
2068+
2069+ for (auto Feature : RISCVFeatureKV)
2070+ if (ISAInfo->hasExtension (Feature.Key ))
2071+ setFeatureBits (Feature.Value , Feature.Key );
2072+
2073+ if (FromOptionDirective) {
2074+ if (ISAInfo->getXLen () == 32 && isRV64 ())
2075+ return Error (Loc, " bad arch string switching from rv64 to rv32" );
2076+ else if (ISAInfo->getXLen () == 64 && !isRV64 ())
2077+ return Error (Loc, " bad arch string switching from rv32 to rv64" );
2078+ }
2079+
2080+ if (ISAInfo->getXLen () == 32 )
2081+ clearFeatureBits (RISCV::Feature64Bit, " 64bit" );
2082+ else if (ISAInfo->getXLen () == 64 )
2083+ setFeatureBits (RISCV::Feature64Bit, " 64bit" );
2084+ else
2085+ return Error (Loc, " bad arch string " + Arch);
2086+
2087+ Result = ISAInfo->toString ();
2088+ return false ;
2089+ }
2090+
20422091bool RISCVAsmParser::parseDirectiveOption () {
20432092 MCAsmParser &Parser = getParser ();
20442093 // Get the option token.
@@ -2071,6 +2120,109 @@ bool RISCVAsmParser::parseDirectiveOption() {
20712120 return false ;
20722121 }
20732122
2123+ if (Option == " arch" ) {
2124+
2125+ Parser.parseComma ();
2126+
2127+ bool PrefixEmitted = false ;
2128+ bool IsExtensionList = false ;
2129+ while (true ) {
2130+ bool IsAdd;
2131+ if (Parser.getTok ().is (AsmToken::Plus)) {
2132+ IsAdd = true ;
2133+ IsExtensionList = true ;
2134+ } else if (Parser.getTok ().is (AsmToken::Minus)) {
2135+ IsAdd = false ;
2136+ IsExtensionList = true ;
2137+ } else {
2138+ SMLoc ArchLoc = Parser.getTok ().getLoc ();
2139+
2140+ if (IsExtensionList)
2141+ return Error (ArchLoc, " unexpected token, expected + or -" );
2142+
2143+ StringRef Arch;
2144+ if (Parser.getTok ().is (AsmToken::Identifier))
2145+ Arch = Parser.getTok ().getString ();
2146+ else
2147+ return Error (ArchLoc,
2148+ " unexpected token, expected identifier" );
2149+
2150+ std::string Result;
2151+ if (resetToArch (Arch, ArchLoc, Result, true ))
2152+ return true ;
2153+
2154+ getTargetStreamer ().emitDirectiveOptionArchFullArch (Result,
2155+ PrefixEmitted);
2156+
2157+ Parser.Lex ();
2158+
2159+ return Parser.parseToken (AsmToken::EndOfStatement,
2160+ " unexpected token, expected end of statement" );
2161+ }
2162+
2163+ Parser.Lex ();
2164+
2165+ if (Parser.getTok ().isNot (AsmToken::Identifier))
2166+ return Error (Parser.getTok ().getLoc (),
2167+ " unexpected token, expected identifier" );
2168+
2169+ StringRef ExtStr = Parser.getTok ().getString ();
2170+
2171+ ArrayRef<SubtargetFeatureKV> KVArray (RISCVFeatureKV);
2172+ auto Ext = llvm::lower_bound (KVArray, ExtStr);
2173+ if (Ext == KVArray.end () || StringRef (Ext->Key ) != ExtStr ||
2174+ !RISCVISAInfo::isSupportedExtension (ExtStr)) {
2175+ if (isDigit (ExtStr.back ()))
2176+ return Error (
2177+ Parser.getTok ().getLoc (),
2178+ " Extension version number parsing not currently implemented" );
2179+ return Error (Parser.getTok ().getLoc (), " unknown extension feature" );
2180+ }
2181+
2182+ SMLoc Loc = Parser.getTok ().getLoc ();
2183+
2184+ Parser.Lex (); // Eat arch string
2185+ bool HasComma = getTok ().is (AsmToken::Comma);
2186+ if (IsAdd) {
2187+ setFeatureBits (Ext->Value , Ext->Key );
2188+ auto ParseResult = RISCVFeatures::parseFeatureBits (isRV64 (), STI->getFeatureBits ());
2189+ if (!ParseResult) {
2190+ std::string Buffer;
2191+ raw_string_ostream OutputErrMsg (Buffer);
2192+ handleAllErrors (ParseResult.takeError (), [&](llvm::StringError &ErrMsg) {
2193+ OutputErrMsg << ErrMsg.getMessage ();
2194+ });
2195+
2196+ return Error (Loc, OutputErrMsg.str ());
2197+ }
2198+ getTargetStreamer ().emitDirectiveOptionArchPlus (Ext->Key , PrefixEmitted,
2199+ HasComma);
2200+ } else {
2201+ // It is invalid to disable an extension that there are other enabled
2202+ // extensions depend on it.
2203+ // TODO: Make use of RISCVISAInfo to handle this
2204+ for (auto Feature : KVArray) {
2205+ if (getSTI ().hasFeature (Feature.Value ) &&
2206+ Feature.Implies .test (Ext->Value ))
2207+ return Error (Loc,
2208+ Twine (" Can't disable " ) + Ext->Key + " extension, " +
2209+ Feature.Key + " extension requires " + Ext->Key +
2210+ " extension be enabled" );
2211+ }
2212+
2213+ clearFeatureBits (Ext->Value , Ext->Key );
2214+ getTargetStreamer ().emitDirectiveOptionArchMinus (
2215+ Ext->Key , PrefixEmitted, HasComma);
2216+ }
2217+
2218+ if (!HasComma)
2219+ return Parser.parseToken (AsmToken::EndOfStatement,
2220+ " unexpected token, expected end of statement" );
2221+ // Eat comma
2222+ Parser.Lex ();
2223+ }
2224+ }
2225+
20742226 if (Option == " rvc" ) {
20752227 if (Parser.parseEOL ())
20762228 return true ;
@@ -2127,9 +2279,9 @@ bool RISCVAsmParser::parseDirectiveOption() {
21272279 }
21282280
21292281 // Unknown option.
2130- Warning (Parser.getTok ().getLoc (),
2131- " unknown option, expected 'push', 'pop ', 'rvc ', 'norvc ', 'relax' or "
2132- " 'norelax'" );
2282+ Warning (Parser.getTok ().getLoc (), " unknown option, expected 'push', 'pop', "
2283+ " 'rvc ', 'norvc ', 'arch ', 'relax' or "
2284+ " 'norelax'" );
21332285 Parser.eatToEndOfStatement ();
21342286 return false ;
21352287}
@@ -2204,39 +2356,12 @@ bool RISCVAsmParser::parseDirectiveAttribute() {
22042356 else if (Tag != RISCVAttrs::ARCH)
22052357 getTargetStreamer ().emitTextAttribute (Tag, StringValue);
22062358 else {
2207- StringRef Arch = StringValue;
2208- for (auto Feature : RISCVFeatureKV)
2209- if (llvm::RISCVISAInfo::isSupportedExtensionFeature (Feature.Key ))
2210- clearFeatureBits (Feature.Value , Feature.Key );
2211-
2212- auto ParseResult = llvm::RISCVISAInfo::parseArchString (
2213- StringValue, /* EnableExperimentalExtension=*/ true ,
2214- /* ExperimentalExtensionVersionCheck=*/ true );
2215- if (!ParseResult) {
2216- std::string Buffer;
2217- raw_string_ostream OutputErrMsg (Buffer);
2218- handleAllErrors (ParseResult.takeError (), [&](llvm::StringError &ErrMsg) {
2219- OutputErrMsg << " invalid arch name '" << Arch << " ', "
2220- << ErrMsg.getMessage ();
2221- });
2222-
2223- return Error (ValueExprLoc, OutputErrMsg.str ());
2224- }
2225- auto &ISAInfo = *ParseResult;
2226-
2227- for (auto Feature : RISCVFeatureKV)
2228- if (ISAInfo->hasExtension (Feature.Key ))
2229- setFeatureBits (Feature.Value , Feature.Key );
2230-
2231- if (ISAInfo->getXLen () == 32 )
2232- clearFeatureBits (RISCV::Feature64Bit, " 64bit" );
2233- else if (ISAInfo->getXLen () == 64 )
2234- setFeatureBits (RISCV::Feature64Bit, " 64bit" );
2235- else
2236- return Error (ValueExprLoc, " bad arch string " + Arch);
2359+ std::string Result;
2360+ if (resetToArch (StringValue, ValueExprLoc, Result, false ))
2361+ return true ;
22372362
22382363 // Then emit the arch string.
2239- getTargetStreamer ().emitTextAttribute (Tag, ISAInfo-> toString () );
2364+ getTargetStreamer ().emitTextAttribute (Tag, Result );
22402365 }
22412366
22422367 return false ;
0 commit comments