-
Notifications
You must be signed in to change notification settings - Fork 13.3k
[Clang][AArch64] Emit 'unimplemented' diagnostic for SME #80295
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
[Clang][AArch64] Emit 'unimplemented' diagnostic for SME #80295
Conversation
@llvm/pr-subscribers-clang Author: Sander de Smalen (sdesmalen-arm) ChangesWhen a function F has ZA and ZT0 state, calls another function G that only This is not yet implemented in LLVM and does not result in a compile-time Full diff: https://github.com/llvm/llvm-project/pull/80295.diff 3 Files Affected:
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 7638a7e84c3c0..21a767cfc5e5c 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3711,6 +3711,12 @@ def err_sme_za_call_no_za_state : Error<
"call to a shared ZA function requires the caller to have ZA state">;
def err_sme_zt0_call_no_zt0_state : Error<
"call to a shared ZT0 function requires the caller to have ZT0 state">;
+def err_sme_unimplemented_za_save_restore : Error<
+ "call to a function that shares state other than 'za' from a "
+ "function that has live 'za' state requires a spill/fill of ZA, which is not yet "
+ "implemented">;
+def note_sme_use_preserves_za : Note<
+ "add '__arm_preserves(\"za\")' to the callee if it preserves ZA">;
def err_sme_definition_using_sm_in_non_sme_target : Error<
"function executed in streaming-SVE mode requires 'sme'">;
def err_sme_definition_using_za_in_non_sme_target : Error<
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 7b877da1a928f..db9dc55c13b8d 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -7513,47 +7513,44 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
}
}
- // If the callee uses AArch64 SME ZA state but the caller doesn't define
- // any, then this is an error.
- FunctionType::ArmStateValue ArmZAState =
+ FunctionType::ArmStateValue CalleeArmZAState =
FunctionType::getArmZAState(ExtInfo.AArch64SMEAttributes);
- if (ArmZAState != FunctionType::ARM_None) {
+ FunctionType::ArmStateValue CalleeArmZT0State =
+ FunctionType::getArmZT0State(ExtInfo.AArch64SMEAttributes);
+ if (CalleeArmZAState != FunctionType::ARM_None ||
+ CalleeArmZT0State != FunctionType::ARM_None) {
bool CallerHasZAState = false;
+ bool CallerHasZT0State = false;
if (const auto *CallerFD = dyn_cast<FunctionDecl>(CurContext)) {
auto *Attr = CallerFD->getAttr<ArmNewAttr>();
if (Attr && Attr->isNewZA())
CallerHasZAState = true;
- else if (const auto *FPT =
- CallerFD->getType()->getAs<FunctionProtoType>())
- CallerHasZAState = FunctionType::getArmZAState(
- FPT->getExtProtoInfo().AArch64SMEAttributes) !=
- FunctionType::ARM_None;
- }
-
- if (!CallerHasZAState)
- Diag(Loc, diag::err_sme_za_call_no_za_state);
- }
-
- // If the callee uses AArch64 SME ZT0 state but the caller doesn't define
- // any, then this is an error.
- FunctionType::ArmStateValue ArmZT0State =
- FunctionType::getArmZT0State(ExtInfo.AArch64SMEAttributes);
- if (ArmZT0State != FunctionType::ARM_None) {
- bool CallerHasZT0State = false;
- if (const auto *CallerFD = dyn_cast<FunctionDecl>(CurContext)) {
- auto *Attr = CallerFD->getAttr<ArmNewAttr>();
if (Attr && Attr->isNewZT0())
CallerHasZT0State = true;
- else if (const auto *FPT =
- CallerFD->getType()->getAs<FunctionProtoType>())
- CallerHasZT0State =
+ if (const auto *FPT = CallerFD->getType()->getAs<FunctionProtoType>()) {
+ CallerHasZAState |=
+ FunctionType::getArmZAState(
+ FPT->getExtProtoInfo().AArch64SMEAttributes) !=
+ FunctionType::ARM_None;
+ CallerHasZT0State |=
FunctionType::getArmZT0State(
FPT->getExtProtoInfo().AArch64SMEAttributes) !=
FunctionType::ARM_None;
+ }
}
- if (!CallerHasZT0State)
+ if (CalleeArmZAState != FunctionType::ARM_None && !CallerHasZAState)
+ Diag(Loc, diag::err_sme_za_call_no_za_state);
+
+ if (CalleeArmZT0State != FunctionType::ARM_None && !CallerHasZT0State)
Diag(Loc, diag::err_sme_zt0_call_no_zt0_state);
+
+ if (CallerHasZAState &&
+ CalleeArmZAState == FunctionType::ARM_None &&
+ CalleeArmZT0State != FunctionType::ARM_None) {
+ Diag(Loc, diag::err_sme_unimplemented_za_save_restore);
+ Diag(Loc, diag::note_sme_use_preserves_za);
+ }
}
}
diff --git a/clang/test/Sema/aarch64-sme-func-attrs.c b/clang/test/Sema/aarch64-sme-func-attrs.c
index 97409ae7d6040..2bf1886951f1f 100644
--- a/clang/test/Sema/aarch64-sme-func-attrs.c
+++ b/clang/test/Sema/aarch64-sme-func-attrs.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -fsyntax-only -verify %s
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -fsyntax-only -verify=expected-cpp -x c++ %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -fsyntax-only -verify=expected-cpp -x c++ %s
// Valid attributes
@@ -445,3 +445,12 @@ void conflicting_state_attrs_preserves_out_zt0(void) __arm_preserves("zt0") __ar
// expected-cpp-error@+2 {{conflicting attributes for state 'zt0'}}
// expected-error@+1 {{conflicting attributes for state 'zt0'}}
void conflicting_state_attrs_preserves_inout_zt0(void) __arm_preserves("zt0") __arm_inout("zt0");
+
+// Test that we get a diagnostic for unimplemented case.
+void unimplemented_spill_fill_za(void (*share_zt0_only)(void) __arm_inout("zt0")) __arm_inout("za", "zt0") {
+ // expected-cpp-error@+4 {{call to a function that shares state other than 'za' from a function that has live 'za' state requires a spill/fill of ZA, which is not yet implemented}}
+ // expected-cpp-note@+3 {{add '__arm_preserves("za")' to the callee if it preserves ZA}}
+ // expected-error@+2 {{call to a function that shares state other than 'za' from a function that has live 'za' state requires a spill/fill of ZA, which is not yet implemented}}
+ // expected-note@+1 {{add '__arm_preserves("za")' to the callee if it preserves ZA}}
+ share_zt0_only();
+}
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
When a function F has ZA and ZT0 state, calls another function G that only shares ZT0 state with its caller, F will have to save ZA before the call to G, and restore it afterwards (rather than setting up a lazy-sve). This is not yet implemented in LLVM and does not result in a compile-time error either. So instead of silently generating incorrect code, it's better to emit an error saying this is not yet implemented.
12600c8
to
4705005
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
When a function F has ZA and ZT0 state, calls another function G that only shares ZT0 state with its caller, F will have to save ZA before the call to G, and restore it afterwards (rather than setting up a lazy-sve). This is not yet implemented in LLVM and does not result in a compile-time error either. So instead of silently generating incorrect code, it's better to emit an error saying this is not yet implemented. (cherry picked from commit 319f4c0)
When a function F has ZA and ZT0 state, calls another function G that only shares ZT0 state with its caller, F will have to save ZA before the call to G, and restore it afterwards (rather than setting up a lazy-sve). This is not yet implemented in LLVM and does not result in a compile-time error either. So instead of silently generating incorrect code, it's better to emit an error saying this is not yet implemented. (cherry picked from commit 319f4c0)
When a function F has ZA and ZT0 state, calls another function G that only shares ZT0 state with its caller, F will have to save ZA before the call to G, and restore it afterwards (rather than setting up a lazy-sve). This is not yet implemented in LLVM and does not result in a compile-time error either. So instead of silently generating incorrect code, it's better to emit an error saying this is not yet implemented.
When a function F has ZA and ZT0 state, calls another function G that only shares ZT0 state with its caller, F will have to save ZA before the call to G, and restore it afterwards (rather than setting up a lazy-sve). This is not yet implemented in LLVM and does not result in a compile-time error either. So instead of silently generating incorrect code, it's better to emit an error saying this is not yet implemented. (cherry picked from commit 319f4c0)
When a function F has ZA and ZT0 state, calls another function G that only shares ZT0 state with its caller, F will have to save ZA before the call to G, and restore it afterwards (rather than setting up a lazy-sve). This is not yet implemented in LLVM and does not result in a compile-time error either. So instead of silently generating incorrect code, it's better to emit an error saying this is not yet implemented. (cherry picked from commit 319f4c0)
When a function F has ZA and ZT0 state, calls another function G that only shares ZT0 state with its caller, F will have to save ZA before the call to G, and restore it afterwards (rather than setting up a lazy-sve). This is not yet implemented in LLVM and does not result in a compile-time error either. So instead of silently generating incorrect code, it's better to emit an error saying this is not yet implemented. (cherry picked from commit 319f4c0)
When a function F has ZA and ZT0 state, calls another function G that only shares ZT0 state with its caller, F will have to save ZA before the call to G, and restore it afterwards (rather than setting up a lazy-sve). This is not yet implemented in LLVM and does not result in a compile-time error either. So instead of silently generating incorrect code, it's better to emit an error saying this is not yet implemented. (cherry picked from commit 319f4c0)
When a function F has ZA and ZT0 state, calls another function G that only
shares ZT0 state with its caller, F will have to save ZA before the call to G,
and restore it afterwards (rather than setting up a lazy-sve).
This is not yet implemented in LLVM and does not result in a compile-time
error either. So instead of silently generating incorrect code, it's better to
emit an error saying this is not yet implemented.