@@ -179,6 +179,12 @@ class RISCVAsmParser : public MCTargetAsmParser {
179
179
bool parseDirectiveInsn (SMLoc L);
180
180
bool parseDirectiveVariantCC ();
181
181
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
+
182
188
void setFeatureBits (uint64_t Feature, StringRef FeatureString) {
183
189
if (!(getSTI ().getFeatureBits ()[Feature])) {
184
190
MCSubtargetInfo &STI = copySTI ();
@@ -2039,6 +2045,49 @@ bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) {
2039
2045
return true ;
2040
2046
}
2041
2047
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
+
2042
2091
bool RISCVAsmParser::parseDirectiveOption () {
2043
2092
MCAsmParser &Parser = getParser ();
2044
2093
// Get the option token.
@@ -2071,6 +2120,109 @@ bool RISCVAsmParser::parseDirectiveOption() {
2071
2120
return false ;
2072
2121
}
2073
2122
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
+
2074
2226
if (Option == " rvc" ) {
2075
2227
if (Parser.parseEOL ())
2076
2228
return true ;
@@ -2127,9 +2279,9 @@ bool RISCVAsmParser::parseDirectiveOption() {
2127
2279
}
2128
2280
2129
2281
// 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'" );
2133
2285
Parser.eatToEndOfStatement ();
2134
2286
return false ;
2135
2287
}
@@ -2204,39 +2356,12 @@ bool RISCVAsmParser::parseDirectiveAttribute() {
2204
2356
else if (Tag != RISCVAttrs::ARCH)
2205
2357
getTargetStreamer ().emitTextAttribute (Tag, StringValue);
2206
2358
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 ;
2237
2362
2238
2363
// Then emit the arch string.
2239
- getTargetStreamer ().emitTextAttribute (Tag, ISAInfo-> toString () );
2364
+ getTargetStreamer ().emitTextAttribute (Tag, Result );
2240
2365
}
2241
2366
2242
2367
return false ;
0 commit comments