Skip to content

[clang][sema][FMV] Forbid multi-versioning arm_streaming functions. #81268

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 4 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -3728,6 +3728,8 @@ def err_sme_definition_using_zt0_in_non_sme2_target : Error<
"function using ZT0 state requires 'sme2'">;
def err_conflicting_attributes_arm_state : Error<
"conflicting attributes for state '%0'">;
def err_sme_streaming_cannot_be_multiversioned : Error<
"streaming function cannot be multi-versioned">;
def err_unknown_arm_state : Error<
"unknown state '%0'">;
def err_missing_arm_state : Error<
Expand Down
13 changes: 6 additions & 7 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -4838,13 +4838,12 @@ class Sema final {
llvm::Error isValidSectionSpecifier(StringRef Str);
bool checkSectionName(SourceLocation LiteralLoc, StringRef Str);
bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str);
bool checkTargetVersionAttr(SourceLocation LiteralLoc, StringRef &Str,
bool &isDefault);
bool
checkTargetClonesAttrString(SourceLocation LiteralLoc, StringRef Str,
const StringLiteral *Literal, bool &HasDefault,
bool &HasCommas, bool &HasNotDefault,
SmallVectorImpl<SmallString<64>> &StringsBuffer);
bool checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D,
StringRef &Str, bool &isDefault);
bool checkTargetClonesAttrString(
SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal,
Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault,
SmallVectorImpl<SmallString<64>> &StringsBuffer);
bool checkMSInheritanceAttrOnDefinition(
CXXRecordDecl *RD, SourceRange Range, bool BestCase,
MSInheritanceModel SemanticSpelling);
Expand Down
22 changes: 17 additions & 5 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3501,9 +3501,16 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
return false;
}

static bool hasArmStreamingInterface(const FunctionDecl *FD) {
if (const auto *T = FD->getType()->getAs<FunctionProtoType>())
if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask)
return true;
return false;
}

// Check Target Version attrs
bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, StringRef &AttrStr,
bool &isDefault) {
bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D,
StringRef &AttrStr, bool &isDefault) {
enum FirstParam { Unsupported };
enum SecondParam { None };
enum ThirdParam { Target, TargetClones, TargetVersion };
Expand All @@ -3519,6 +3526,8 @@ bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, StringRef &AttrStr,
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << CurFeature << TargetVersion;
}
if (hasArmStreamingInterface(cast<FunctionDecl>(D)))
return Diag(LiteralLoc, diag::err_sme_streaming_cannot_be_multiversioned);
return false;
}

Expand All @@ -3527,7 +3536,7 @@ static void handleTargetVersionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
SourceLocation LiteralLoc;
bool isDefault = false;
if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc) ||
S.checkTargetVersionAttr(LiteralLoc, Str, isDefault))
S.checkTargetVersionAttr(LiteralLoc, D, Str, isDefault))
return;
// Do not create default only target_version attribute
if (!isDefault) {
Expand All @@ -3550,7 +3559,7 @@ static void handleTargetAttr(Sema &S, Decl *D, const ParsedAttr &AL) {

bool Sema::checkTargetClonesAttrString(
SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal,
bool &HasDefault, bool &HasCommas, bool &HasNotDefault,
Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault,
SmallVectorImpl<SmallString<64>> &StringsBuffer) {
enum FirstParam { Unsupported, Duplicate, Unknown };
enum SecondParam { None, CPU, Tune };
Expand Down Expand Up @@ -3619,6 +3628,9 @@ bool Sema::checkTargetClonesAttrString(
HasNotDefault = true;
}
}
if (hasArmStreamingInterface(cast<FunctionDecl>(D)))
return Diag(LiteralLoc,
diag::err_sme_streaming_cannot_be_multiversioned);
} else {
// Other targets ( currently X86 )
if (Cur.starts_with("arch=")) {
Expand Down Expand Up @@ -3670,7 +3682,7 @@ static void handleTargetClonesAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!S.checkStringLiteralArgumentAttr(AL, I, CurStr, &LiteralLoc) ||
S.checkTargetClonesAttrString(
LiteralLoc, CurStr,
cast<StringLiteral>(AL.getArgAsExpr(I)->IgnoreParenCasts()),
cast<StringLiteral>(AL.getArgAsExpr(I)->IgnoreParenCasts()), D,
HasDefault, HasCommas, HasNotDefault, StringsBuffer))
return;
}
Expand Down
40 changes: 40 additions & 0 deletions clang/test/Sema/aarch64-sme-func-attrs.c
Original file line number Diff line number Diff line change
Expand Up @@ -454,3 +454,43 @@ void unimplemented_spill_fill_za(void (*share_zt0_only)(void) __arm_inout("zt0")
// expected-note@+1 {{add '__arm_preserves("za")' to the callee if it preserves ZA}}
share_zt0_only();
}

// expected-cpp-error@+2 {{streaming function cannot be multi-versioned}}
// expected-error@+1 {{streaming function cannot be multi-versioned}}
__attribute__((target_version("sme2")))
void cannot_work_version(void) __arm_streaming {}
// expected-cpp-error@+5 {{function declared 'void ()' was previously declared 'void () __arm_streaming', which has different SME function attributes}}
// expected-cpp-note@-2 {{previous declaration is here}}
// expected-error@+3 {{function declared 'void (void)' was previously declared 'void (void) __arm_streaming', which has different SME function attributes}}
// expected-note@-4 {{previous declaration is here}}
__attribute__((target_version("default")))
void cannot_work_version(void) {}


// expected-cpp-error@+2 {{streaming function cannot be multi-versioned}}
// expected-error@+1 {{streaming function cannot be multi-versioned}}
__attribute__((target_clones("sme2")))
void cannot_work_clones(void) __arm_streaming {}


__attribute__((target("sme2")))
void just_fine_streaming(void) __arm_streaming {}
__attribute__((target_version("sme2")))
void just_fine(void) { just_fine_streaming(); }
__attribute__((target_version("default")))
void just_fine(void) {}


__arm_locally_streaming
__attribute__((target_version("sme2")))
void just_fine_locally_streaming(void) {}
__attribute__((target_version("default")))
void just_fine_locally_streaming(void) {}


void fmv_caller() {
cannot_work_version();
cannot_work_clones();
just_fine();
just_fine_locally_streaming();
}