[clang] de2b9f8 - [Clang][RISCV] Allow three SiFive CLIC interrupt arguments (#216159)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 19 02:51:44 PDT 2026
Author: Zeyi Xu
Date: 2026-08-19T17:51:39+08:00
New Revision: de2b9f862475f6949a26918d3e614d9db98dd5b4
URL: https://github.com/llvm/llvm-project/commit/de2b9f862475f6949a26918d3e614d9db98dd5b4
DIFF: https://github.com/llvm/llvm-project/commit/de2b9f862475f6949a26918d3e614d9db98dd5b4.diff
LOG: [Clang][RISCV] Allow three SiFive CLIC interrupt arguments (#216159)
The SiFive CLIC interrupt values may be combined with each other and
with the machine value, but the interrupt attribute previously accepted
at most two arguments.
This commit allows three arguments for the combination of machine,
SiFive-CLIC-preemptible, and SiFive-CLIC-stack-swap.
Fixes #216138
Added:
Modified:
clang/docs/ReleaseNotes.md
clang/lib/Sema/SemaRISCV.cpp
clang/test/Sema/riscv-interrupt-attr-qci.c
clang/test/Sema/riscv-interrupt-attr-rnmi.c
clang/test/Sema/riscv-interrupt-attr-sifive.c
clang/test/Sema/riscv-interrupt-attr.c
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 2571149b02a12..b585161ba3ff4 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -562,6 +562,9 @@ features cannot lower the translation-unit ABI level;
#### RISC-V Support
+- Fixed a bug where the `interrupt` attribute did not accept `machine` together
+ with both `SiFive-CLIC-preemptible` and `SiFive-CLIC-stack-swap`.
+
- Added `-march=native` for better compatibility with ARM, AArch64, and X86. This
option will be treated like `-mcpu=native` if `-mcpu` is not present. If
`-mcpu` is present, the ISA will be selected from the host CPU and the tune
diff --git a/clang/lib/Sema/SemaRISCV.cpp b/clang/lib/Sema/SemaRISCV.cpp
index 9647a7d913744..d4c6495fbacfb 100644
--- a/clang/lib/Sema/SemaRISCV.cpp
+++ b/clang/lib/Sema/SemaRISCV.cpp
@@ -1618,7 +1618,7 @@ void SemaRISCV::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
// - Must be a function.
// - Must have no parameters.
// - Must have the 'void' return type.
- // - The attribute itself must have at most 2 arguments
+ // - The attribute itself must have at most 3 arguments
// - The attribute arguments must be string literals, and valid choices.
// - The attribute arguments must be a valid combination
// - The current target must support the right extensions for the combination.
@@ -1641,13 +1641,13 @@ void SemaRISCV::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
return;
}
- if (!AL.checkAtMostNumArgs(SemaRef, 2))
+ if (!AL.checkAtMostNumArgs(SemaRef, 3))
return;
bool HasSiFiveCLICType = false;
bool HasUnaryType = false;
- SmallSet<RISCVInterruptAttr::InterruptType, 2> Types;
+ SmallSet<RISCVInterruptAttr::InterruptType, 3> Types;
for (unsigned ArgIndex = 0; ArgIndex < AL.getNumArgs(); ++ArgIndex) {
RISCVInterruptAttr::InterruptType Type;
StringRef TypeString;
@@ -1745,7 +1745,7 @@ void SemaRISCV::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
}
}
- SmallVector<RISCVInterruptAttr::InterruptType, 2> TypesVec(Types.begin(),
+ SmallVector<RISCVInterruptAttr::InterruptType, 3> TypesVec(Types.begin(),
Types.end());
D->addAttr(::new (getASTContext()) RISCVInterruptAttr(
diff --git a/clang/test/Sema/riscv-interrupt-attr-qci.c b/clang/test/Sema/riscv-interrupt-attr-qci.c
index c957963fbc20d..63ff61a2c0de4 100644
--- a/clang/test/Sema/riscv-interrupt-attr-qci.c
+++ b/clang/test/Sema/riscv-interrupt-attr-qci.c
@@ -16,6 +16,11 @@ void foo_nest_interrupt(void) {}
__attribute__((interrupt("qci-nest", "qci-nest")))
void foo_nest_nest_interrupt(void) {}
+// CHECK-LABEL: @foo_nest_nest_nest_interrupt() #0
+// CHECK: ret void
+__attribute__((interrupt("qci-nest", "qci-nest", "qci-nest")))
+void foo_nest_nest_nest_interrupt(void) {}
+
// CHECK-LABEL: @foo_nonest_interrupt() #1
// CHECK: ret void
__attribute__((interrupt("qci-nonest")))
@@ -26,6 +31,11 @@ void foo_nonest_interrupt(void) {}
__attribute__((interrupt("qci-nonest", "qci-nonest")))
void foo_nonest_nonest_interrupt(void) {}
+// CHECK-LABEL: @foo_nonest_nonest_nonest_interrupt() #1
+// CHECK: ret void
+__attribute__((interrupt("qci-nonest", "qci-nonest", "qci-nonest")))
+void foo_nonest_nonest_nonest_interrupt(void) {}
+
// CHECK: attributes #0
// CHECK: "interrupt"="qci-nest"
// CHECK: attributes #1
@@ -48,6 +58,8 @@ __attribute__((interrupt("qci-nonest"))) void foo_nonest(void) {} // disabled-er
__attribute__((interrupt("qci-nest", "qci-nest"))) void foo_nest_nest(void) {} // disabled-error {{RISC-V 'interrupt' attribute 'qci-nest' requires extension 'Xqciint'}}
__attribute__((interrupt("qci-nonest", "qci-nonest"))) void foo_nonest_nonest(void) {} // disabled-error {{RISC-V 'interrupt' attribute 'qci-nonest' requires extension 'Xqciint'}}
+__attribute__((interrupt("qci-nest", "qci-nest", "qci-nest"))) void foo_nest_nest_nest(void) {} // disabled-error {{RISC-V 'interrupt' attribute 'qci-nest' requires extension 'Xqciint'}}
+__attribute__((interrupt("qci-nonest", "qci-nonest", "qci-nonest"))) void foo_nonest_nonest_nonest(void) {} // disabled-error {{RISC-V 'interrupt' attribute 'qci-nonest' requires extension 'Xqciint'}}
// This tests the errors for the qci interrupts when using
diff --git a/clang/test/Sema/riscv-interrupt-attr-rnmi.c b/clang/test/Sema/riscv-interrupt-attr-rnmi.c
index 964bae52a56f9..02d25d357306f 100644
--- a/clang/test/Sema/riscv-interrupt-attr-rnmi.c
+++ b/clang/test/Sema/riscv-interrupt-attr-rnmi.c
@@ -14,12 +14,18 @@ void foo_rnmi_interrupt(void) {}
__attribute__((interrupt("rnmi", "rnmi")))
void foo_rnmi_rnmi_interrupt(void) {}
+// CHECK-LABEL: @foo_rnmi_rnmi_rnmi_interrupt() #0
+// CHECK: ret void
+__attribute__((interrupt("rnmi", "rnmi", "rnmi")))
+void foo_rnmi_rnmi_rnmi_interrupt(void) {}
+
// CHECK: attributes #0
// CHECK: "interrupt"="rnmi"
#else
__attribute__((interrupt("rnmi"))) void test_rnmi(void) {} // disabled-error {{RISC-V 'interrupt' attribute 'rnmi' requires extension 'Smrnmi'}}
__attribute__((interrupt("rnmi", "rnmi"))) void test_rnmi_rnmi(void) {} // disabled-error {{RISC-V 'interrupt' attribute 'rnmi' requires extension 'Smrnmi'}}
+__attribute__((interrupt("rnmi", "rnmi", "rnmi"))) void test_rnmi_rnmi_rnmi(void) {} // disabled-error {{RISC-V 'interrupt' attribute 'rnmi' requires extension 'Smrnmi'}}
__attribute__((interrupt("rnmi", "supervisor"))) void foo_rnmi_supervisor(void) {} // both-error {{RISC-V 'interrupt' attribute contains invalid combination of interrupt types}}
__attribute__((interrupt("rnmi", "machine"))) void foo_rnmi_machine(void) {} // both-error {{RISC-V 'interrupt' attribute contains invalid combination of interrupt types}}
diff --git a/clang/test/Sema/riscv-interrupt-attr-sifive.c b/clang/test/Sema/riscv-interrupt-attr-sifive.c
index 9b41e38664d8d..2e7c7a8e03075 100644
--- a/clang/test/Sema/riscv-interrupt-attr-sifive.c
+++ b/clang/test/Sema/riscv-interrupt-attr-sifive.c
@@ -56,6 +56,17 @@ void foo_preemptible_machine(void) {}
__attribute__((interrupt("machine", "SiFive-CLIC-preemptible")))
void foo_machine_preemptible(void) {}
+// CHECK-LABEL: @foo_machine_stack_swap_preemptible() #2
+// CHECK: ret void
+__attribute__((interrupt("machine", "SiFive-CLIC-stack-swap",
+ "SiFive-CLIC-preemptible")))
+void foo_machine_stack_swap_preemptible(void) {}
+
+// CHECK-LABEL: @foo_preemptible_stack_swap_machine() #2
+// CHECK: ret void
+__attribute__((interrupt("SiFive-CLIC-preemptible",
+ "SiFive-CLIC-stack-swap", "machine")))
+void foo_preemptible_stack_swap_machine(void) {}
// CHECK: attributes #0
// CHECK: "interrupt"="SiFive-CLIC-stack-swap"
@@ -77,8 +88,10 @@ __attribute__((interrupt("machine", "SiFive-CLIC-preemptible"))) void foo15(void
__attribute__((interrupt("SiFive-CLIC-preemptible", "SiFive-CLIC-stack-swap"))) void foo16(void) {} // disabled-error {{RISC-V 'interrupt' attribute 'SiFive-CLIC-preemptible' requires extension 'XSfmclic'}}
__attribute__((interrupt("SiFive-CLIC-stack-swap", "SiFive-CLIC-preemptible"))) void foo17(void) {} // disabled-error {{RISC-V 'interrupt' attribute 'SiFive-CLIC-stack-swap' requires extension 'XSfmclic'}}
+__attribute__((interrupt("machine", "SiFive-CLIC-stack-swap", "SiFive-CLIC-preemptible"))) void foo18(void) {} // disabled-error {{requires extension 'XSfmclic'}}
-__attribute__((interrupt("machine", "machine", "SiFive-CLIC-preemptible"))) void foo24(void) {} // both-error {{'interrupt' attribute takes no more than 2 arguments}}
+__attribute__((interrupt("machine", "machine", "SiFive-CLIC-preemptible"))) void foo24(void) {} // disabled-error {{requires extension 'XSfmclic'}}
+__attribute__((interrupt("machine", "machine", "SiFive-CLIC-preemptible", "SiFive-CLIC-stack-swap"))) void foo25(void) {} // both-error {{'interrupt' attribute takes no more than 3 arguments}}
__attribute__((interrupt("SiFive-CLIC-preemptible", "supervisor"))) void foo27(void) {} // both-error {{RISC-V 'interrupt' attribute contains invalid combination of interrupt types}}
diff --git a/clang/test/Sema/riscv-interrupt-attr.c b/clang/test/Sema/riscv-interrupt-attr.c
index f46723e892fb6..9f503a806703c 100644
--- a/clang/test/Sema/riscv-interrupt-attr.c
+++ b/clang/test/Sema/riscv-interrupt-attr.c
@@ -42,7 +42,9 @@ struct a test __attribute__((interrupt)); // expected-warning {{'interrupt' attr
__attribute__((interrupt)) int foo3(void) {return 0;} // expected-warning {{RISC-V 'interrupt' attribute only applies to functions that have a 'void' return type}}
__attribute__((interrupt())) void foo5(int a) {} // expected-warning {{RISC-V 'interrupt' attribute only applies to functions that have no parameters}}
-__attribute__((interrupt("machine", "supervisor", "machine"))) void foo15(void) {} // expected-error {{'interrupt' attribute takes no more than 2 arguments}}
+__attribute__((interrupt("machine", "supervisor", "machine"))) void foo15(void) {} // expected-error {{RISC-V 'interrupt' attribute contains invalid combination of interrupt types}}
+
+__attribute__((interrupt("machine", "machine", "machine", "machine"))) void foo_too_many_args(void) {} // expected-error {{'interrupt' attribute takes no more than 3 arguments}}
__attribute__((interrupt(42))) void foo0(void) {} // expected-error {{expected string literal as argument of 'interrupt' attribute}}
__attribute__((interrupt("machine", 1))) void foo2(void) {} // expected-error {{expected string literal as argument of 'interrupt' attribute}}
@@ -68,6 +70,8 @@ __attribute__((interrupt)) void foo14(void) {}
__attribute__((interrupt("machine", "machine"))) void foo_machine_twice(void) {}
__attribute__((interrupt("supervisor", "supervisor"))) void foo_supervisor_supervisor(void) {}
+__attribute__((interrupt("machine", "machine", "machine"))) void foo_three_machine_args(void) {}
+__attribute__((interrupt("supervisor", "supervisor", "supervisor"))) void foo_three_supervisor_args(void) {}
#endif
More information about the cfe-commits
mailing list