@@ -235,6 +235,47 @@ ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {
235235 clang::RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin);
236236}
237237
238+ static std::vector<std::string>
239+ collectNonISAExtFeature (const std::vector<std::string> &FeaturesNeedOverride,
240+ int XLen) {
241+ auto ParseResult =
242+ llvm::RISCVISAInfo::parseFeatures (XLen, FeaturesNeedOverride);
243+
244+ if (!ParseResult) {
245+ consumeError (ParseResult.takeError ());
246+ return std::vector<std::string>();
247+ }
248+
249+ std::vector<std::string> ImpliedFeatures = (*ParseResult)->toFeatureVector ();
250+
251+ std::vector<std::string> NonISAExtFeatureVec;
252+
253+ llvm::copy_if (FeaturesNeedOverride, std::back_inserter (NonISAExtFeatureVec),
254+ [&](const std::string &Feat) {
255+ return !llvm::is_contained (ImpliedFeatures, Feat);
256+ });
257+
258+ return NonISAExtFeatureVec;
259+ }
260+
261+ static std::vector<std::string>
262+ resolveTargetAttrOverride (const std::vector<std::string> &FeaturesVec,
263+ int XLen) {
264+ auto I = llvm::find (FeaturesVec, " __RISCV_TargetAttrNeedOverride" );
265+ if (I == FeaturesVec.end ())
266+ return FeaturesVec;
267+
268+ const std::vector<std::string> FeaturesNeedOverride (FeaturesVec.begin (), I);
269+ std::vector<std::string> NonISAExtFeature =
270+ collectNonISAExtFeature (FeaturesNeedOverride, XLen);
271+
272+ auto ResolvedFeature = std::vector (++I, FeaturesVec.end ());
273+ ResolvedFeature.insert (ResolvedFeature.end (), NonISAExtFeature.begin (),
274+ NonISAExtFeature.end ());
275+
276+ return ResolvedFeature;
277+ }
278+
238279bool RISCVTargetInfo::initFeatureMap (
239280 llvm::StringMap<bool > &Features, DiagnosticsEngine &Diags, StringRef CPU,
240281 const std::vector<std::string> &FeaturesVec) const {
@@ -248,7 +289,10 @@ bool RISCVTargetInfo::initFeatureMap(
248289 Features[" 32bit" ] = true ;
249290 }
250291
251- auto ParseResult = llvm::RISCVISAInfo::parseFeatures (XLen, FeaturesVec);
292+ std::vector<std::string> NewFeaturesVec =
293+ resolveTargetAttrOverride (FeaturesVec, XLen);
294+
295+ auto ParseResult = llvm::RISCVISAInfo::parseFeatures (XLen, NewFeaturesVec);
252296 if (!ParseResult) {
253297 std::string Buffer;
254298 llvm::raw_string_ostream OutputErrMsg (Buffer);
@@ -262,7 +306,7 @@ bool RISCVTargetInfo::initFeatureMap(
262306 // RISCVISAInfo makes implications for ISA features
263307 std::vector<std::string> ImpliedFeatures = (*ParseResult)->toFeatureVector ();
264308 // Add non-ISA features like `relax` and `save-restore` back
265- for (const std::string &Feature : FeaturesVec )
309+ for (const std::string &Feature : NewFeaturesVec )
266310 if (!llvm::is_contained (ImpliedFeatures, Feature))
267311 ImpliedFeatures.push_back (Feature);
268312
@@ -359,3 +403,82 @@ void RISCVTargetInfo::fillValidTuneCPUList(
359403 bool Is64Bit = getTriple ().isArch64Bit ();
360404 llvm::RISCV::fillValidTuneCPUArchList (Values, Is64Bit);
361405}
406+
407+ static void handleFullArchString (StringRef FullArchStr,
408+ std::vector<std::string> &Features) {
409+ Features.push_back (" __RISCV_TargetAttrNeedOverride" );
410+ auto RII = llvm::RISCVISAInfo::parseArchString (
411+ FullArchStr, /* EnableExperimentalExtension */ true );
412+ if (!RII) {
413+ consumeError (RII.takeError ());
414+ // Forward the invalid FullArchStr.
415+ Features.push_back (" +" + FullArchStr.str ());
416+ } else {
417+ std::vector<std::string> FeatStrings = (*RII)->toFeatureVector ();
418+ for (auto FeatString : FeatStrings)
419+ Features.push_back (FeatString);
420+ }
421+ }
422+
423+ ParsedTargetAttr RISCVTargetInfo::parseTargetAttr (StringRef Features) const {
424+ ParsedTargetAttr Ret;
425+ if (Features == " default" )
426+ return Ret;
427+ SmallVector<StringRef, 1 > AttrFeatures;
428+ Features.split (AttrFeatures, " ;" );
429+ bool FoundArch = false ;
430+
431+ for (auto &Feature : AttrFeatures) {
432+ Feature = Feature.trim ();
433+ StringRef AttrString = Feature.split (" =" ).second .trim ();
434+
435+ if (Feature.startswith (" arch=" )) {
436+ // Override last features
437+ Ret.Features .clear ();
438+ if (FoundArch)
439+ Ret.Duplicate = " arch=" ;
440+ FoundArch = true ;
441+
442+ if (AttrString.startswith (" +" )) {
443+ // EXTENSION like arch=+v,+zbb
444+ SmallVector<StringRef, 1 > Exts;
445+ AttrString.split (Exts, " ," );
446+ for (auto Ext : Exts) {
447+ if (Ext.empty ())
448+ continue ;
449+
450+ StringRef ExtName = Ext.substr (1 );
451+ std::string TargetFeature =
452+ llvm::RISCVISAInfo::getTargetFeatureForExtension (ExtName);
453+ if (!TargetFeature.empty ())
454+ Ret.Features .push_back (Ext.front () + TargetFeature);
455+ else
456+ Ret.Features .push_back (Ext.str ());
457+ }
458+ } else {
459+ // full-arch-string like arch=rv64gcv
460+ handleFullArchString (AttrString, Ret.Features );
461+ }
462+ } else if (Feature.startswith (" cpu=" )) {
463+ if (!Ret.CPU .empty ())
464+ Ret.Duplicate = " cpu=" ;
465+
466+ Ret.CPU = AttrString;
467+
468+ if (!FoundArch) {
469+ // Update Features with CPU's features
470+ StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu (Ret.CPU );
471+ if (MarchFromCPU != " " ) {
472+ Ret.Features .clear ();
473+ handleFullArchString (MarchFromCPU, Ret.Features );
474+ }
475+ }
476+ } else if (Feature.startswith (" tune=" )) {
477+ if (!Ret.Tune .empty ())
478+ Ret.Duplicate = " tune=" ;
479+
480+ Ret.Tune = AttrString;
481+ }
482+ }
483+ return Ret;
484+ }
0 commit comments