llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-backend-aarch64 Author: Sam Tebbs (SamTebbs33) <details> <summary>Changes</summary> This patch adds an error that is emitted when a streaming function is marked as always_inline and is called from a non-streaming function. --- Full diff: https://github.com/llvm/llvm-project/pull/77936.diff 7 Files Affected: - (modified) clang/include/clang/Basic/DiagnosticFrontendKinds.td (+2) - (modified) clang/include/clang/Sema/Sema.h (+9) - (modified) clang/lib/CodeGen/CMakeLists.txt (+1) - (modified) clang/lib/CodeGen/Targets/AArch64.cpp (+20) - (modified) clang/lib/Sema/SemaChecking.cpp (+10-17) - (added) clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c (+12) - (added) clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c (+12) ``````````diff diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 568000106a84dc..dbd92b600a936e 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -279,6 +279,8 @@ def err_builtin_needs_feature : Error<"%0 needs target feature %1">; def err_function_needs_feature : Error< "always_inline function %1 requires target feature '%2', but would " "be inlined into function %0 that is compiled without support for '%2'">; +def err_function_alwaysinline_attribute_mismatch : Error< + "always_inline function %1 and its caller %0 have mismatched %2 attributes">; def warn_avx_calling_convention : Warning<"AVX vector %select{return|argument}0 of type %1 without '%2' " diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 4c464a1ae4c67f..0fed60103c9a2c 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -13803,8 +13803,17 @@ class Sema final { FormatArgumentPassingKind ArgPassingKind; }; +enum ArmStreamingType { + ArmNonStreaming, + ArmStreaming, + ArmStreamingCompatible, + ArmStreamingOrSVE2p1 +}; + + static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember, bool IsVariadic, FormatStringInfo *FSI); + static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD); private: void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index 52216d93a302bb..03a6f2f1d7a9d2 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -151,4 +151,5 @@ add_clang_library(clangCodeGen clangFrontend clangLex clangSerialization + clangSema ) diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index 7102d190fe008b..ea3d5a97605f1c 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -8,6 +8,8 @@ #include "ABIInfoImpl.h" #include "TargetInfo.h" +#include "clang/Basic/DiagnosticFrontend.h" +#include "clang/Sema/Sema.h" using namespace clang; using namespace clang::CodeGen; @@ -153,6 +155,11 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo { } return TargetCodeGenInfo::isScalarizableAsmOperand(CGF, Ty); } + + void checkFunctionCallABI(CodeGenModule &CGM, SourceLocation CallLoc, + const FunctionDecl *Caller, + const FunctionDecl *Callee, + const CallArgList &Args) const override; }; class WindowsAArch64TargetCodeGenInfo : public AArch64TargetCodeGenInfo { @@ -812,6 +819,19 @@ Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, /*allowHigherAlign*/ false); } +void AArch64TargetCodeGenInfo::checkFunctionCallABI( + CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller, + const FunctionDecl *Callee, const CallArgList &Args) const { + if (!Callee->hasAttr<AlwaysInlineAttr>()) + return; + + auto CalleeIsStreaming = Sema::getArmStreamingFnType(Callee) == Sema::ArmStreaming; + auto CallerIsStreaming = Sema::getArmStreamingFnType(Caller) == Sema::ArmStreaming; + + if (CalleeIsStreaming && !CallerIsStreaming) + CGM.getDiags().Report(CallLoc, diag::err_function_alwaysinline_attribute_mismatch) << Caller->getDeclName() << Callee->getDeclName() << "streaming"; +} + std::unique_ptr<TargetCodeGenInfo> CodeGen::createAArch64TargetCodeGenInfo(CodeGenModule &CGM, AArch64ABIKind Kind) { diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 74f8f626fb1637..160637dde448e4 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2998,13 +2998,6 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context, llvm_unreachable("Invalid NeonTypeFlag!"); } -enum ArmStreamingType { - ArmNonStreaming, - ArmStreaming, - ArmStreamingCompatible, - ArmStreamingOrSVE2p1 -}; - bool Sema::ParseSVEImmChecks( CallExpr *TheCall, SmallVector<std::tuple<int, int, int>, 3> &ImmChecks) { // Perform all the immediate checks for this builtin call. @@ -3145,7 +3138,7 @@ bool Sema::ParseSVEImmChecks( return HasError; } -static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) { +Sema::ArmStreamingType Sema::getArmStreamingFnType(const FunctionDecl *FD) { if (FD->hasAttr<ArmLocallyStreamingAttr>()) return ArmStreaming; if (const auto *T = FD->getType()->getAs<FunctionProtoType>()) { @@ -3159,31 +3152,31 @@ static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) { static void checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall, const FunctionDecl *FD, - ArmStreamingType BuiltinType) { - ArmStreamingType FnType = getArmStreamingFnType(FD); - if (BuiltinType == ArmStreamingOrSVE2p1) { + Sema::ArmStreamingType BuiltinType) { + Sema::ArmStreamingType FnType = Sema::getArmStreamingFnType(FD); + if (BuiltinType == Sema::ArmStreamingOrSVE2p1) { // Check intrinsics that are available in [sve2p1 or sme/sme2]. llvm::StringMap<bool> CallerFeatureMap; S.Context.getFunctionFeatureMap(CallerFeatureMap, FD); if (Builtin::evaluateRequiredTargetFeatures("sve2p1", CallerFeatureMap)) - BuiltinType = ArmStreamingCompatible; + BuiltinType = Sema::ArmStreamingCompatible; else - BuiltinType = ArmStreaming; + BuiltinType = Sema::ArmStreaming; } - if (FnType == ArmStreaming && BuiltinType == ArmNonStreaming) { + if (FnType == Sema::ArmStreaming && BuiltinType == Sema::ArmNonStreaming) { S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) << TheCall->getSourceRange() << "streaming"; } - if (FnType == ArmStreamingCompatible && - BuiltinType != ArmStreamingCompatible) { + if (FnType == Sema::ArmStreamingCompatible && + BuiltinType != Sema::ArmStreamingCompatible) { S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) << TheCall->getSourceRange() << "streaming compatible"; return; } - if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming) { + if (FnType == Sema::ArmNonStreaming && BuiltinType == Sema::ArmStreaming) { S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) << TheCall->getSourceRange() << "non-streaming"; } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c new file mode 100644 index 00000000000000..4aa9fbf4a8fa18 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c @@ -0,0 +1,12 @@ +// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s + +// Conflicting attributes when using always_inline +__attribute__((always_inline)) __arm_locally_streaming +int inlined_fn_local(void) { + return 42; +} +// expected-error@+1 {{always_inline function 'inlined_fn_local' and its caller 'inlined_fn_caller' have mismatched streaming attributes}} +int inlined_fn_caller(void) { return inlined_fn_local(); } +__arm_locally_streaming +int inlined_fn_caller_local(void) { return inlined_fn_local(); } +int inlined_fn_caller_streaming(void) __arm_streaming { return inlined_fn_local(); } diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c new file mode 100644 index 00000000000000..7268a49bb2491d --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c @@ -0,0 +1,12 @@ +// RUN: %clang --target=aarch64-none-linux-gnu -march=armv9-a+sme -O3 -S -Xclang -verify %s + +// Conflicting attributes when using always_inline +__attribute__((always_inline)) +int inlined_fn_streaming(void) __arm_streaming { + return 42; +} +// expected-error@+1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}} +int inlined_fn_caller(void) { return inlined_fn_streaming(); } +__arm_locally_streaming +int inlined_fn_caller_local(void) { return inlined_fn_streaming(); } +int inlined_fn_caller_streaming(void) __arm_streaming { return inlined_fn_streaming(); } `````````` </details> https://github.com/llvm/llvm-project/pull/77936 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits