[AArch64][SME] Add diagnostics for SME attributes on lambda functions (#121777)
CheckFunctionDeclaration emits diagnostics if any SME attributes are used by a function definition without the required +sme or +sme2 target features. This patch moves these diagnostics to a new function in SemaARM and also adds a call to this from ActOnStartOfLambdaDefinition.
This commit is contained in:
@@ -79,6 +79,8 @@ public:
|
||||
void handleNewAttr(Decl *D, const ParsedAttr &AL);
|
||||
void handleCmseNSEntryAttr(Decl *D, const ParsedAttr &AL);
|
||||
void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
|
||||
|
||||
void CheckSMEFunctionDefAttributes(const FunctionDecl *FD);
|
||||
};
|
||||
|
||||
SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD);
|
||||
|
||||
@@ -1328,4 +1328,57 @@ void SemaARM::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
|
||||
ARMInterruptAttr(getASTContext(), AL, Kind));
|
||||
}
|
||||
|
||||
// Check if the function definition uses any AArch64 SME features without
|
||||
// having the '+sme' feature enabled and warn user if sme locally streaming
|
||||
// function returns or uses arguments with VL-based types.
|
||||
void SemaARM::CheckSMEFunctionDefAttributes(const FunctionDecl *FD) {
|
||||
const auto *Attr = FD->getAttr<ArmNewAttr>();
|
||||
bool UsesSM = FD->hasAttr<ArmLocallyStreamingAttr>();
|
||||
bool UsesZA = Attr && Attr->isNewZA();
|
||||
bool UsesZT0 = Attr && Attr->isNewZT0();
|
||||
|
||||
if (FD->hasAttr<ArmLocallyStreamingAttr>()) {
|
||||
if (FD->getReturnType()->isSizelessVectorType())
|
||||
Diag(FD->getLocation(),
|
||||
diag::warn_sme_locally_streaming_has_vl_args_returns)
|
||||
<< /*IsArg=*/false;
|
||||
if (llvm::any_of(FD->parameters(), [](ParmVarDecl *P) {
|
||||
return P->getOriginalType()->isSizelessVectorType();
|
||||
}))
|
||||
Diag(FD->getLocation(),
|
||||
diag::warn_sme_locally_streaming_has_vl_args_returns)
|
||||
<< /*IsArg=*/true;
|
||||
}
|
||||
if (const auto *FPT = FD->getType()->getAs<FunctionProtoType>()) {
|
||||
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
|
||||
UsesSM |= EPI.AArch64SMEAttributes & FunctionType::SME_PStateSMEnabledMask;
|
||||
UsesZA |= FunctionType::getArmZAState(EPI.AArch64SMEAttributes) !=
|
||||
FunctionType::ARM_None;
|
||||
UsesZT0 |= FunctionType::getArmZT0State(EPI.AArch64SMEAttributes) !=
|
||||
FunctionType::ARM_None;
|
||||
}
|
||||
|
||||
ASTContext &Context = getASTContext();
|
||||
if (UsesSM || UsesZA) {
|
||||
llvm::StringMap<bool> FeatureMap;
|
||||
Context.getFunctionFeatureMap(FeatureMap, FD);
|
||||
if (!FeatureMap.contains("sme")) {
|
||||
if (UsesSM)
|
||||
Diag(FD->getLocation(),
|
||||
diag::err_sme_definition_using_sm_in_non_sme_target);
|
||||
else
|
||||
Diag(FD->getLocation(),
|
||||
diag::err_sme_definition_using_za_in_non_sme_target);
|
||||
}
|
||||
}
|
||||
if (UsesZT0) {
|
||||
llvm::StringMap<bool> FeatureMap;
|
||||
Context.getFunctionFeatureMap(FeatureMap, FD);
|
||||
if (!FeatureMap.contains("sme2")) {
|
||||
Diag(FD->getLocation(),
|
||||
diag::err_sme_definition_using_zt0_in_non_sme2_target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace clang
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "clang/Sema/ParsedTemplate.h"
|
||||
#include "clang/Sema/Scope.h"
|
||||
#include "clang/Sema/ScopeInfo.h"
|
||||
#include "clang/Sema/SemaARM.h"
|
||||
#include "clang/Sema/SemaCUDA.h"
|
||||
#include "clang/Sema/SemaHLSL.h"
|
||||
#include "clang/Sema/SemaInternal.h"
|
||||
@@ -12297,58 +12298,8 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the function definition uses any AArch64 SME features without
|
||||
// having the '+sme' feature enabled and warn user if sme locally streaming
|
||||
// function returns or uses arguments with VL-based types.
|
||||
if (DeclIsDefn) {
|
||||
const auto *Attr = NewFD->getAttr<ArmNewAttr>();
|
||||
bool UsesSM = NewFD->hasAttr<ArmLocallyStreamingAttr>();
|
||||
bool UsesZA = Attr && Attr->isNewZA();
|
||||
bool UsesZT0 = Attr && Attr->isNewZT0();
|
||||
|
||||
if (NewFD->hasAttr<ArmLocallyStreamingAttr>()) {
|
||||
if (NewFD->getReturnType()->isSizelessVectorType())
|
||||
Diag(NewFD->getLocation(),
|
||||
diag::warn_sme_locally_streaming_has_vl_args_returns)
|
||||
<< /*IsArg=*/false;
|
||||
if (llvm::any_of(NewFD->parameters(), [](ParmVarDecl *P) {
|
||||
return P->getOriginalType()->isSizelessVectorType();
|
||||
}))
|
||||
Diag(NewFD->getLocation(),
|
||||
diag::warn_sme_locally_streaming_has_vl_args_returns)
|
||||
<< /*IsArg=*/true;
|
||||
}
|
||||
if (const auto *FPT = NewFD->getType()->getAs<FunctionProtoType>()) {
|
||||
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
|
||||
UsesSM |=
|
||||
EPI.AArch64SMEAttributes & FunctionType::SME_PStateSMEnabledMask;
|
||||
UsesZA |= FunctionType::getArmZAState(EPI.AArch64SMEAttributes) !=
|
||||
FunctionType::ARM_None;
|
||||
UsesZT0 |= FunctionType::getArmZT0State(EPI.AArch64SMEAttributes) !=
|
||||
FunctionType::ARM_None;
|
||||
}
|
||||
|
||||
if (UsesSM || UsesZA) {
|
||||
llvm::StringMap<bool> FeatureMap;
|
||||
Context.getFunctionFeatureMap(FeatureMap, NewFD);
|
||||
if (!FeatureMap.contains("sme")) {
|
||||
if (UsesSM)
|
||||
Diag(NewFD->getLocation(),
|
||||
diag::err_sme_definition_using_sm_in_non_sme_target);
|
||||
else
|
||||
Diag(NewFD->getLocation(),
|
||||
diag::err_sme_definition_using_za_in_non_sme_target);
|
||||
}
|
||||
}
|
||||
if (UsesZT0) {
|
||||
llvm::StringMap<bool> FeatureMap;
|
||||
Context.getFunctionFeatureMap(FeatureMap, NewFD);
|
||||
if (!FeatureMap.contains("sme2")) {
|
||||
Diag(NewFD->getLocation(),
|
||||
diag::err_sme_definition_using_zt0_in_non_sme2_target);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DeclIsDefn && Context.getTargetInfo().getTriple().isAArch64())
|
||||
ARM().CheckSMEFunctionDefAttributes(NewFD);
|
||||
|
||||
return Redeclaration;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "clang/Sema/Lookup.h"
|
||||
#include "clang/Sema/Scope.h"
|
||||
#include "clang/Sema/ScopeInfo.h"
|
||||
#include "clang/Sema/SemaARM.h"
|
||||
#include "clang/Sema/SemaCUDA.h"
|
||||
#include "clang/Sema/SemaInternal.h"
|
||||
#include "clang/Sema/SemaOpenMP.h"
|
||||
@@ -1455,6 +1456,9 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
|
||||
// Attributes on the lambda apply to the method.
|
||||
ProcessDeclAttributes(CurScope, Method, ParamInfo);
|
||||
|
||||
if (Context.getTargetInfo().getTriple().isAArch64())
|
||||
ARM().CheckSMEFunctionDefAttributes(Method);
|
||||
|
||||
// CUDA lambdas get implicit host and device attributes.
|
||||
if (getLangOpts().CUDA)
|
||||
CUDA().SetLambdaAttrs(Method);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -std=c++23 -fsyntax-only -verify %s
|
||||
|
||||
// This test is testing the diagnostics that Clang emits when compiling without '+sme'.
|
||||
|
||||
@@ -48,3 +48,9 @@ void streaming_compatible_def2(void (*streaming_fn_ptr)(void) __arm_streaming,
|
||||
// Also test when call-site is not a function.
|
||||
int streaming_decl_ret_int() __arm_streaming;
|
||||
int x = streaming_decl_ret_int(); // expected-error {{call to a streaming function requires 'sme'}}
|
||||
|
||||
void sme_attrs_lambdas() {
|
||||
[] __arm_locally_streaming () { return; }(); // expected-error {{function executed in streaming-SVE mode requires 'sme'}}
|
||||
[] __arm_new("za") () { return; }(); // expected-error {{function using ZA state requires 'sme'}}
|
||||
[] __arm_new("zt0") () { return; }(); // expected-error {{function using ZT0 state requires 'sme2'}}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user