Skip to content

Commit d08d315

Browse files
authored
[clang][sema][FMV] Forbid multi-versioning arm_streaming functions. (#81268)
The streaming mode change is incompatible with the ifunc mechanism used to implement FMV: we can't conditionally change it based on the particular callee that is resolved at runtime. Fixes: #80077
1 parent 69ddf1e commit d08d315

File tree

4 files changed

+65
-12
lines changed

4 files changed

+65
-12
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3728,6 +3728,8 @@ def err_sme_definition_using_zt0_in_non_sme2_target : Error<
37283728
"function using ZT0 state requires 'sme2'">;
37293729
def err_conflicting_attributes_arm_state : Error<
37303730
"conflicting attributes for state '%0'">;
3731+
def err_sme_streaming_cannot_be_multiversioned : Error<
3732+
"streaming function cannot be multi-versioned">;
37313733
def err_unknown_arm_state : Error<
37323734
"unknown state '%0'">;
37333735
def err_missing_arm_state : Error<

clang/include/clang/Sema/Sema.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4838,13 +4838,12 @@ class Sema final {
48384838
llvm::Error isValidSectionSpecifier(StringRef Str);
48394839
bool checkSectionName(SourceLocation LiteralLoc, StringRef Str);
48404840
bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str);
4841-
bool checkTargetVersionAttr(SourceLocation LiteralLoc, StringRef &Str,
4842-
bool &isDefault);
4843-
bool
4844-
checkTargetClonesAttrString(SourceLocation LiteralLoc, StringRef Str,
4845-
const StringLiteral *Literal, bool &HasDefault,
4846-
bool &HasCommas, bool &HasNotDefault,
4847-
SmallVectorImpl<SmallString<64>> &StringsBuffer);
4841+
bool checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D,
4842+
StringRef &Str, bool &isDefault);
4843+
bool checkTargetClonesAttrString(
4844+
SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal,
4845+
Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault,
4846+
SmallVectorImpl<SmallString<64>> &StringsBuffer);
48484847
bool checkMSInheritanceAttrOnDefinition(
48494848
CXXRecordDecl *RD, SourceRange Range, bool BestCase,
48504849
MSInheritanceModel SemanticSpelling);

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3501,9 +3501,16 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
35013501
return false;
35023502
}
35033503

3504+
static bool hasArmStreamingInterface(const FunctionDecl *FD) {
3505+
if (const auto *T = FD->getType()->getAs<FunctionProtoType>())
3506+
if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask)
3507+
return true;
3508+
return false;
3509+
}
3510+
35043511
// Check Target Version attrs
3505-
bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, StringRef &AttrStr,
3506-
bool &isDefault) {
3512+
bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D,
3513+
StringRef &AttrStr, bool &isDefault) {
35073514
enum FirstParam { Unsupported };
35083515
enum SecondParam { None };
35093516
enum ThirdParam { Target, TargetClones, TargetVersion };
@@ -3519,6 +3526,8 @@ bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, StringRef &AttrStr,
35193526
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
35203527
<< Unsupported << None << CurFeature << TargetVersion;
35213528
}
3529+
if (hasArmStreamingInterface(cast<FunctionDecl>(D)))
3530+
return Diag(LiteralLoc, diag::err_sme_streaming_cannot_be_multiversioned);
35223531
return false;
35233532
}
35243533

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

35513560
bool Sema::checkTargetClonesAttrString(
35523561
SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal,
3553-
bool &HasDefault, bool &HasCommas, bool &HasNotDefault,
3562+
Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault,
35543563
SmallVectorImpl<SmallString<64>> &StringsBuffer) {
35553564
enum FirstParam { Unsupported, Duplicate, Unknown };
35563565
enum SecondParam { None, CPU, Tune };
@@ -3619,6 +3628,9 @@ bool Sema::checkTargetClonesAttrString(
36193628
HasNotDefault = true;
36203629
}
36213630
}
3631+
if (hasArmStreamingInterface(cast<FunctionDecl>(D)))
3632+
return Diag(LiteralLoc,
3633+
diag::err_sme_streaming_cannot_be_multiversioned);
36223634
} else {
36233635
// Other targets ( currently X86 )
36243636
if (Cur.starts_with("arch=")) {
@@ -3670,7 +3682,7 @@ static void handleTargetClonesAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
36703682
if (!S.checkStringLiteralArgumentAttr(AL, I, CurStr, &LiteralLoc) ||
36713683
S.checkTargetClonesAttrString(
36723684
LiteralLoc, CurStr,
3673-
cast<StringLiteral>(AL.getArgAsExpr(I)->IgnoreParenCasts()),
3685+
cast<StringLiteral>(AL.getArgAsExpr(I)->IgnoreParenCasts()), D,
36743686
HasDefault, HasCommas, HasNotDefault, StringsBuffer))
36753687
return;
36763688
}

clang/test/Sema/aarch64-sme-func-attrs.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,3 +454,43 @@ void unimplemented_spill_fill_za(void (*share_zt0_only)(void) __arm_inout("zt0")
454454
// expected-note@+1 {{add '__arm_preserves("za")' to the callee if it preserves ZA}}
455455
share_zt0_only();
456456
}
457+
458+
// expected-cpp-error@+2 {{streaming function cannot be multi-versioned}}
459+
// expected-error@+1 {{streaming function cannot be multi-versioned}}
460+
__attribute__((target_version("sme2")))
461+
void cannot_work_version(void) __arm_streaming {}
462+
// expected-cpp-error@+5 {{function declared 'void ()' was previously declared 'void () __arm_streaming', which has different SME function attributes}}
463+
// expected-cpp-note@-2 {{previous declaration is here}}
464+
// expected-error@+3 {{function declared 'void (void)' was previously declared 'void (void) __arm_streaming', which has different SME function attributes}}
465+
// expected-note@-4 {{previous declaration is here}}
466+
__attribute__((target_version("default")))
467+
void cannot_work_version(void) {}
468+
469+
470+
// expected-cpp-error@+2 {{streaming function cannot be multi-versioned}}
471+
// expected-error@+1 {{streaming function cannot be multi-versioned}}
472+
__attribute__((target_clones("sme2")))
473+
void cannot_work_clones(void) __arm_streaming {}
474+
475+
476+
__attribute__((target("sme2")))
477+
void just_fine_streaming(void) __arm_streaming {}
478+
__attribute__((target_version("sme2")))
479+
void just_fine(void) { just_fine_streaming(); }
480+
__attribute__((target_version("default")))
481+
void just_fine(void) {}
482+
483+
484+
__arm_locally_streaming
485+
__attribute__((target_version("sme2")))
486+
void just_fine_locally_streaming(void) {}
487+
__attribute__((target_version("default")))
488+
void just_fine_locally_streaming(void) {}
489+
490+
491+
void fmv_caller() {
492+
cannot_work_version();
493+
cannot_work_clones();
494+
just_fine();
495+
just_fine_locally_streaming();
496+
}

0 commit comments

Comments
 (0)