[clang] [Clang][SME] Detect always_inline used with mismatched streaming attributes (PR #77936)
Sam Tebbs via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 15 05:46:20 PST 2024
https://github.com/SamTebbs33 updated https://github.com/llvm/llvm-project/pull/77936
>From bbc6c11cd3def5acbb2ba2f2ddc45df2c399f9d6 Mon Sep 17 00:00:00 2001
From: Samuel Tebbs <samuel.tebbs at arm.com>
Date: Wed, 10 Jan 2024 14:57:04 +0000
Subject: [PATCH 1/3] [Clang][SME] Detect always_inline used with mismatched
streaming attributes
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.
---
.../clang/Basic/DiagnosticFrontendKinds.td | 2 ++
clang/include/clang/Sema/Sema.h | 9 +++++++
clang/lib/CodeGen/CMakeLists.txt | 1 +
clang/lib/CodeGen/Targets/AArch64.cpp | 20 ++++++++++++++
clang/lib/Sema/SemaChecking.cpp | 27 +++++++------------
...-sme-func-attrs-inline-locally-streaming.c | 12 +++++++++
.../aarch64-sme-func-attrs-inline-streaming.c | 12 +++++++++
7 files changed, 66 insertions(+), 17 deletions(-)
create mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c
create mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 568000106a84dc7..dbd92b600a936e2 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 4c464a1ae4c67fe..0fed60103c9a2c3 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 52216d93a302bbb..03a6f2f1d7a9d26 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 7102d190fe008bd..ea3d5a97605f1c3 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 74f8f626fb1637c..160637dde448e43 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 000000000000000..4aa9fbf4a8fa18c
--- /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 at +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 000000000000000..7268a49bb2491d0
--- /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 at +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(); }
>From 0000293eac8600b97d2ca7374dda318eff1e7729 Mon Sep 17 00:00:00 2001
From: Sam Tebbs <samuel.tebbs at arm.com>
Date: Fri, 12 Jan 2024 15:13:28 +0000
Subject: [PATCH 2/3] fixup: formatting
---
clang/include/clang/Sema/Sema.h | 13 ++++++-------
clang/lib/CodeGen/Targets/AArch64.cpp | 16 ++++++++++------
2 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0fed60103c9a2c3..2ff1fcb01c91d8f 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13803,13 +13803,12 @@ class Sema final {
FormatArgumentPassingKind ArgPassingKind;
};
-enum ArmStreamingType {
- ArmNonStreaming,
- ArmStreaming,
- ArmStreamingCompatible,
- ArmStreamingOrSVE2p1
-};
-
+ enum ArmStreamingType {
+ ArmNonStreaming,
+ ArmStreaming,
+ ArmStreamingCompatible,
+ ArmStreamingOrSVE2p1
+ };
static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
bool IsVariadic, FormatStringInfo *FSI);
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index ea3d5a97605f1c3..43555f577f0f509 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -822,14 +822,18 @@ Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
void AArch64TargetCodeGenInfo::checkFunctionCallABI(
CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller,
const FunctionDecl *Callee, const CallArgList &Args) const {
- if (!Callee->hasAttr<AlwaysInlineAttr>())
- return;
+ if (!Callee->hasAttr<AlwaysInlineAttr>())
+ return;
- auto CalleeIsStreaming = Sema::getArmStreamingFnType(Callee) == Sema::ArmStreaming;
- auto CallerIsStreaming = Sema::getArmStreamingFnType(Caller) == Sema::ArmStreaming;
+ 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";
+ if (CalleeIsStreaming && !CallerIsStreaming)
+ CGM.getDiags().Report(CallLoc,
+ diag::err_function_alwaysinline_attribute_mismatch)
+ << Caller->getDeclName() << Callee->getDeclName() << "streaming";
}
std::unique_ptr<TargetCodeGenInfo>
>From edff82e0f24a568c6041b648aec5c6bb85ac1318 Mon Sep 17 00:00:00 2001
From: Sam Tebbs <samuel.tebbs at arm.com>
Date: Mon, 15 Jan 2024 11:32:44 +0000
Subject: [PATCH 3/3] fixup: allow streaming compatible callee and check if
modes are the same
---
clang/lib/CodeGen/Targets/AArch64.cpp | 11 ++++++-----
.../sme-inline-streaming-compatible-caller.c | 9 +++++++++
.../sme-inline-streaming-compatible.c | 17 +++++++++++++++++
.../sme-inline-streaming-locally.c} | 0
.../sme-inline-streaming.c} | 0
5 files changed, 32 insertions(+), 5 deletions(-)
create mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
create mode 100644 clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
rename clang/test/CodeGen/{aarch64-sme-func-attrs-inline-locally-streaming.c => aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c} (100%)
rename clang/test/CodeGen/{aarch64-sme-func-attrs-inline-streaming.c => aarch64-sme-func-attrs-inline/sme-inline-streaming.c} (100%)
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index 43555f577f0f509..7d944468d4dd493 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -825,12 +825,13 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI(
if (!Callee->hasAttr<AlwaysInlineAttr>())
return;
- auto CalleeIsStreaming =
- Sema::getArmStreamingFnType(Callee) == Sema::ArmStreaming;
- auto CallerIsStreaming =
- Sema::getArmStreamingFnType(Caller) == Sema::ArmStreaming;
+ auto CalleeStreamingMode = Sema::getArmStreamingFnType(Callee);
+ auto CallerStreamingMode = Sema::getArmStreamingFnType(Caller);
- if (CalleeIsStreaming && !CallerIsStreaming)
+ // The caller can inline the callee if their streaming modes match or the
+ // callee is streaming compatible
+ if (CalleeStreamingMode != CallerStreamingMode &&
+ CalleeStreamingMode != Sema::ArmStreamingCompatible)
CGM.getDiags().Report(CallLoc,
diag::err_function_alwaysinline_attribute_mismatch)
<< Caller->getDeclName() << Callee->getDeclName() << "streaming";
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
new file mode 100644
index 000000000000000..5c1779291a7e5b9
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible-caller.c
@@ -0,0 +1,9 @@
+// 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 at +1 {{always_inline function 'inlined_fn_streaming' and its caller 'inlined_fn_caller' have mismatched streaming attributes}}
+int inlined_fn_caller(void) __arm_streaming_compatible { return inlined_fn_streaming(); }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
new file mode 100644
index 000000000000000..a996c429fdda0da
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-compatible.c
@@ -0,0 +1,17 @@
+// 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_compatible(void) __arm_streaming_compatible {
+ return 42;
+}
+__attribute__((always_inline))
+int inlined_fn(void) {
+ return 42;
+}
+int inlined_fn_caller(void) { return inlined_fn_streaming_compatible(); }
+__arm_locally_streaming
+int inlined_fn_caller_local(void) { return inlined_fn_streaming_compatible(); }
+int inlined_fn_caller_streaming(void) __arm_streaming { return inlined_fn_streaming_compatible(); }
+// expected-error at +1 {{always_inline function 'inlined_fn' and its caller 'inlined_fn_caller_compatible' have mismatched streaming attributes}}
+int inlined_fn_caller_compatible(void) __arm_streaming_compatible { return inlined_fn(); }
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
similarity index 100%
rename from clang/test/CodeGen/aarch64-sme-func-attrs-inline-locally-streaming.c
rename to clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming-locally.c
diff --git a/clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c b/clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
similarity index 100%
rename from clang/test/CodeGen/aarch64-sme-func-attrs-inline-streaming.c
rename to clang/test/CodeGen/aarch64-sme-func-attrs-inline/sme-inline-streaming.c
More information about the cfe-commits
mailing list