Skip to content

[NFC][Clang][FMV] Refactor sema checking of target_version/clones attributes. #149067

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 22, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -4922,13 +4922,6 @@ class Sema final : public SemaBase {
// handled later in the process, once we know how many exist.
bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str);

/// Check Target Version attrs
bool checkTargetVersionAttr(SourceLocation Loc, Decl *D, StringRef Str);
bool checkTargetClonesAttrString(
SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal,
Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault,
SmallVectorImpl<SmallString<64>> &StringsBuffer);

ErrorAttr *mergeErrorAttr(Decl *D, const AttributeCommonInfo &CI,
StringRef NewUserDiagnostic);
FormatAttr *mergeFormatAttr(Decl *D, const AttributeCommonInfo &CI,
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Sema/SemaARM.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ class SemaARM : public SemaBase {
/// Return true if the given vector types are lax-compatible SVE vector types,
/// false otherwise.
bool areLaxCompatibleSveTypes(QualType FirstType, QualType SecondType);

bool checkTargetVersionAttr(StringRef Str, SourceLocation Loc);
bool checkTargetClonesAttr(SmallVectorImpl<StringRef> &Strs,
SmallVectorImpl<SourceLocation> &Locs,
SmallVectorImpl<SmallString<64>> &Buffer);
};

SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD);
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Sema/SemaRISCV.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ class SemaRISCV : public SemaBase {
bool DeclareAndesVectorBuiltins = false;

std::unique_ptr<sema::RISCVIntrinsicManager> IntrinsicManager;

bool checkTargetVersionAttr(StringRef Str, SourceLocation Loc);
bool checkTargetClonesAttr(SmallVectorImpl<StringRef> &Strs,
SmallVectorImpl<SourceLocation> &Locs,
SmallVectorImpl<SmallString<64>> &Buffer);
};

std::unique_ptr<sema::RISCVIntrinsicManager>
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Sema/SemaX86.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ class SemaX86 : public SemaBase {

void handleAnyInterruptAttr(Decl *D, const ParsedAttr &AL);
void handleForceAlignArgPointerAttr(Decl *D, const ParsedAttr &AL);

bool checkTargetClonesAttr(SmallVectorImpl<StringRef> &Strs,
SmallVectorImpl<SourceLocation> &Locs,
SmallVectorImpl<SmallString<64>> &Buffer);
};
} // namespace clang

Expand Down
87 changes: 87 additions & 0 deletions clang/lib/Sema/SemaARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1535,4 +1535,91 @@ bool SemaARM::areLaxCompatibleSveTypes(QualType FirstType,
IsLaxCompatible(SecondType, FirstType);
}

enum FirstParam { Unsupported, Duplicate, Unknown };
enum SecondParam { None, CPU, Tune };
enum ThirdParam { Target, TargetClones, TargetVersion };

bool SemaARM::checkTargetVersionAttr(StringRef Str, SourceLocation Loc) {
llvm::SmallVector<StringRef, 8> Features;
Str.split(Features, '+');
for (StringRef Feat : Features) {
Feat = Feat.trim();
if (Feat == "default")
continue;
if (!getASTContext().getTargetInfo().validateCpuSupports(Feat))
return Diag(Loc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << Feat << TargetVersion;
}
return false;
}

bool SemaARM::checkTargetClonesAttr(SmallVectorImpl<StringRef> &Strs,
SmallVectorImpl<SourceLocation> &Locs,
SmallVectorImpl<SmallString<64>> &Buffer) {
if (!getASTContext().getTargetInfo().hasFeature("fmv"))
return true;

assert(Strs.size() == Locs.size() &&
"Mismatch between number of strings and locations");

bool HasDefault = false;
bool HasNonDefault = false;
for (unsigned I = 0; I < Strs.size(); ++I) {
StringRef Str = Strs[I].trim();
SourceLocation Loc = Locs[I];

if (Str.empty())
return Diag(Loc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << "" << TargetClones;

if (Str == "default") {
if (HasDefault)
Diag(Loc, diag::warn_target_clone_duplicate_options);
else {
Buffer.push_back(Str);
HasDefault = true;
}
continue;
}

bool HasCodeGenImpact = false;
llvm::SmallVector<StringRef, 8> Features;
llvm::SmallVector<StringRef, 8> ValidFeatures;
Str.split(Features, '+');
for (StringRef Feat : Features) {
Feat = Feat.trim();
if (!getASTContext().getTargetInfo().validateCpuSupports(Feat)) {
Diag(Loc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << Feat << TargetClones;
continue;
}
if (getASTContext().getTargetInfo().doesFeatureAffectCodeGen(Feat))
HasCodeGenImpact = true;
ValidFeatures.push_back(Feat);
}
// Canonize TargetClones Attributes
SmallString<64> NewStr;
llvm::sort(ValidFeatures);
for (StringRef Feat : ValidFeatures) {
if (!NewStr.empty())
NewStr.append("+");
NewStr.append(Feat);
}
if (llvm::is_contained(Buffer, NewStr))
Diag(Loc, diag::warn_target_clone_duplicate_options);
else if (!HasCodeGenImpact)
// Ignore features in target_clone attribute that don't impact
// code generation
Diag(Loc, diag::warn_target_clone_no_impact_options);
else if (!NewStr.empty()) {
Buffer.push_back(NewStr);
HasNonDefault = true;
}
}
if (!HasNonDefault)
return true;

return false;
}

} // namespace clang
Loading