================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits