[clang] [llvm] [Clang][SME] Detect always_inline used with mismatched streaming attributes (PR #77936)
Sander de Smalen via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 26 09:21:37 PST 2024
================
@@ -814,6 +821,93 @@ Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
/*allowHigherAlign*/ false);
}
+class SMEAttributes {
+public:
+ bool IsStreaming = false;
+ bool IsStreamingBody = false;
+ bool IsStreamingCompatible = false;
+ bool HasNewZA = false;
+
+ SMEAttributes(const FunctionDecl *F) {
+ if (F->hasAttr<ArmLocallyStreamingAttr>())
+ IsStreamingBody = true;
+ if (auto *NewAttr = F->getAttr<ArmNewAttr>()) {
+ if (NewAttr->isNewZA())
+ HasNewZA = true;
+ }
+ if (const auto *T = F->getType()->getAs<FunctionProtoType>()) {
+ if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask)
+ IsStreaming = true;
+ if (T->getAArch64SMEAttributes() &
+ FunctionType::SME_PStateSMCompatibleMask)
+ IsStreamingCompatible = true;
+ }
+ }
+
+ bool hasStreamingBody() const { return IsStreamingBody; }
+ bool hasStreamingInterface() const { return IsStreaming; }
+ bool hasStreamingCompatibleInterface() const { return IsStreamingCompatible; }
+ bool hasStreamingInterfaceOrBody() const {
+ return hasStreamingBody() || hasStreamingInterface();
+ }
+ bool hasNonStreamingInterface() const {
+ return !hasStreamingInterface() && !hasStreamingCompatibleInterface();
+ }
+ bool hasNonStreamingInterfaceAndBody() const {
+ return hasNonStreamingInterface() && !hasStreamingBody();
+ }
+
+ bool requiresSMChange(const SMEAttributes Callee,
+ bool BodyOverridesInterface = false) {
+ // If the transition is not through a call (e.g. when considering inlining)
+ // and Callee has a streaming body, then we can ignore the interface of
+ // Callee.
+ if (BodyOverridesInterface && Callee.hasStreamingBody()) {
+ return !hasStreamingInterfaceOrBody();
+ }
+
+ if (Callee.hasStreamingCompatibleInterface())
+ return false;
+
+ if (hasStreamingCompatibleInterface())
+ return true;
+
+ // Both non-streaming
+ if (hasNonStreamingInterfaceAndBody() && Callee.hasNonStreamingInterface())
+ return false;
+
+ // Both streaming
+ if (hasStreamingInterfaceOrBody() && Callee.hasStreamingInterface())
+ return false;
+
+ return Callee.hasStreamingInterface();
+ }
+
+ bool hasNewZABody() { return HasNewZA; }
+ bool requiresLazySave() const { return HasNewZA; }
+};
+
+void AArch64TargetCodeGenInfo::checkFunctionCallABI(
+ CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller,
+ const FunctionDecl *Callee, const CallArgList &Args) const {
+ if (!Callee->hasAttr<AlwaysInlineAttr>())
+ return;
+
+ SMEAttributes CalleeAttrs(Callee);
+ SMEAttributes CallerAttrs(Caller);
+
+ if (CallerAttrs.requiresSMChange(CalleeAttrs, true))
----------------
sdesmalen-arm wrote:
I think you can write this code without mimicking the (LLVM) SMEAttributes class, which makes the code a lot simpler.
For example, for the streaming-mode diagnostic you could do something like this:
```
bool CallerIsStreaming = Caller->hasAttr<ArmLocallyStreamingAttr>() || (CallerAttrs & SME_PStateSMEnabledMask);
bool CalleeIsStreaming = ...
bool CallerIsStreamingCompatible = !CallerIsStreaming && (CallerAttrs & SME_PStateSMCompatibleMask);
bool CalleeIsStreamingCompatible = ...
if (!CalleeIsStreamingCompatible)
if (CallerIsStreaming != CalleeIsStreaming || CallerIsStreamingCompatible))
// emit diagnostic
```
https://github.com/llvm/llvm-project/pull/77936
More information about the cfe-commits
mailing list