Skip to content

Commit 9d2fe1c

Browse files
sdesmalen-armagozillon
authored andcommitted
[Clang][AArch64] Emit 'unimplemented' diagnostic for SME (llvm#80295)
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.
1 parent 0a9c9da commit 9d2fe1c

File tree

3 files changed

+40
-29
lines changed

3 files changed

+40
-29
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3711,6 +3711,12 @@ def err_sme_za_call_no_za_state : Error<
37113711
"call to a shared ZA function requires the caller to have ZA state">;
37123712
def err_sme_zt0_call_no_zt0_state : Error<
37133713
"call to a shared ZT0 function requires the caller to have ZT0 state">;
3714+
def err_sme_unimplemented_za_save_restore : Error<
3715+
"call to a function that shares state other than 'za' from a "
3716+
"function that has live 'za' state requires a spill/fill of ZA, which is not yet "
3717+
"implemented">;
3718+
def note_sme_use_preserves_za : Note<
3719+
"add '__arm_preserves(\"za\")' to the callee if it preserves ZA">;
37143720
def err_sme_definition_using_sm_in_non_sme_target : Error<
37153721
"function executed in streaming-SVE mode requires 'sme'">;
37163722
def err_sme_definition_using_za_in_non_sme_target : Error<

clang/lib/Sema/SemaChecking.cpp

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7513,47 +7513,43 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
75137513
}
75147514
}
75157515

7516-
// If the callee uses AArch64 SME ZA state but the caller doesn't define
7517-
// any, then this is an error.
7518-
FunctionType::ArmStateValue ArmZAState =
7516+
FunctionType::ArmStateValue CalleeArmZAState =
75197517
FunctionType::getArmZAState(ExtInfo.AArch64SMEAttributes);
7520-
if (ArmZAState != FunctionType::ARM_None) {
7518+
FunctionType::ArmStateValue CalleeArmZT0State =
7519+
FunctionType::getArmZT0State(ExtInfo.AArch64SMEAttributes);
7520+
if (CalleeArmZAState != FunctionType::ARM_None ||
7521+
CalleeArmZT0State != FunctionType::ARM_None) {
75217522
bool CallerHasZAState = false;
7523+
bool CallerHasZT0State = false;
75227524
if (const auto *CallerFD = dyn_cast<FunctionDecl>(CurContext)) {
75237525
auto *Attr = CallerFD->getAttr<ArmNewAttr>();
75247526
if (Attr && Attr->isNewZA())
75257527
CallerHasZAState = true;
7526-
else if (const auto *FPT =
7527-
CallerFD->getType()->getAs<FunctionProtoType>())
7528-
CallerHasZAState = FunctionType::getArmZAState(
7529-
FPT->getExtProtoInfo().AArch64SMEAttributes) !=
7530-
FunctionType::ARM_None;
7531-
}
7532-
7533-
if (!CallerHasZAState)
7534-
Diag(Loc, diag::err_sme_za_call_no_za_state);
7535-
}
7536-
7537-
// If the callee uses AArch64 SME ZT0 state but the caller doesn't define
7538-
// any, then this is an error.
7539-
FunctionType::ArmStateValue ArmZT0State =
7540-
FunctionType::getArmZT0State(ExtInfo.AArch64SMEAttributes);
7541-
if (ArmZT0State != FunctionType::ARM_None) {
7542-
bool CallerHasZT0State = false;
7543-
if (const auto *CallerFD = dyn_cast<FunctionDecl>(CurContext)) {
7544-
auto *Attr = CallerFD->getAttr<ArmNewAttr>();
75457528
if (Attr && Attr->isNewZT0())
75467529
CallerHasZT0State = true;
7547-
else if (const auto *FPT =
7548-
CallerFD->getType()->getAs<FunctionProtoType>())
7549-
CallerHasZT0State =
7530+
if (const auto *FPT = CallerFD->getType()->getAs<FunctionProtoType>()) {
7531+
CallerHasZAState |=
7532+
FunctionType::getArmZAState(
7533+
FPT->getExtProtoInfo().AArch64SMEAttributes) !=
7534+
FunctionType::ARM_None;
7535+
CallerHasZT0State |=
75507536
FunctionType::getArmZT0State(
75517537
FPT->getExtProtoInfo().AArch64SMEAttributes) !=
75527538
FunctionType::ARM_None;
7539+
}
75537540
}
75547541

7555-
if (!CallerHasZT0State)
7542+
if (CalleeArmZAState != FunctionType::ARM_None && !CallerHasZAState)
7543+
Diag(Loc, diag::err_sme_za_call_no_za_state);
7544+
7545+
if (CalleeArmZT0State != FunctionType::ARM_None && !CallerHasZT0State)
75567546
Diag(Loc, diag::err_sme_zt0_call_no_zt0_state);
7547+
7548+
if (CallerHasZAState && CalleeArmZAState == FunctionType::ARM_None &&
7549+
CalleeArmZT0State != FunctionType::ARM_None) {
7550+
Diag(Loc, diag::err_sme_unimplemented_za_save_restore);
7551+
Diag(Loc, diag::note_sme_use_preserves_za);
7552+
}
75577553
}
75587554
}
75597555

clang/test/Sema/aarch64-sme-func-attrs.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -fsyntax-only -verify %s
2-
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -fsyntax-only -verify=expected-cpp -x c++ %s
1+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -fsyntax-only -verify %s
2+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -fsyntax-only -verify=expected-cpp -x c++ %s
33

44
// Valid attributes
55

@@ -445,3 +445,12 @@ void conflicting_state_attrs_preserves_out_zt0(void) __arm_preserves("zt0") __ar
445445
// expected-cpp-error@+2 {{conflicting attributes for state 'zt0'}}
446446
// expected-error@+1 {{conflicting attributes for state 'zt0'}}
447447
void conflicting_state_attrs_preserves_inout_zt0(void) __arm_preserves("zt0") __arm_inout("zt0");
448+
449+
// Test that we get a diagnostic for unimplemented case.
450+
void unimplemented_spill_fill_za(void (*share_zt0_only)(void) __arm_inout("zt0")) __arm_inout("za", "zt0") {
451+
// 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}}
452+
// expected-cpp-note@+3 {{add '__arm_preserves("za")' to the callee if it preserves ZA}}
453+
// 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}}
454+
// expected-note@+1 {{add '__arm_preserves("za")' to the callee if it preserves ZA}}
455+
share_zt0_only();
456+
}

0 commit comments

Comments
 (0)