Skip to content

Enforce correct number of arguments for "x86-interrupt" functions #145662

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions compiler/rustc_ast_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ ast_passes_abi_must_not_have_return_type=
.note = functions with the {$abi} ABI cannot have a return type
.help = remove the return type
ast_passes_abi_x86_interrupt =
invalid signature for `extern "x86-interrupt"` function
.note = functions with the "x86-interrupt" ABI must be have either 1 or 2 parameters (but found {$param_count})
ast_passes_assoc_const_without_body =
associated constant in `impl` without body
.suggestion = provide a definition for the constant
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,17 @@ impl<'a> AstValidator<'a> {
if let InterruptKind::X86 = interrupt_kind {
// "x86-interrupt" is special because it does have arguments.
// FIXME(workingjubilee): properly lint on acceptable input types.
let inputs = &sig.decl.inputs;
let param_count = inputs.len();
if !matches!(param_count, 1 | 2) {
let mut spans: Vec<Span> =
inputs.iter().map(|arg| arg.span).collect();
if spans.is_empty() {
spans = vec![sig.span];
}
self.dcx().emit_err(errors::AbiX86Interrupt { spans, param_count });
}

if let FnRetTy::Ty(ref ret_ty) = sig.decl.output
&& match &ret_ty.kind {
TyKind::Never => false,
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_ast_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -891,3 +891,12 @@ pub(crate) struct AbiMustNotHaveReturnType {
pub span: Span,
pub abi: ExternAbi,
}

#[derive(Diagnostic)]
#[diag(ast_passes_abi_x86_interrupt)]
#[note]
pub(crate) struct AbiX86Interrupt {
#[primary_span]
pub spans: Vec<Span>,
pub param_count: usize,
}
2 changes: 1 addition & 1 deletion tests/codegen-llvm/abi-x86-interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ use minicore::*;

// CHECK: define x86_intrcc void @has_x86_interrupt_abi
#[no_mangle]
pub extern "x86-interrupt" fn has_x86_interrupt_abi() {}
pub extern "x86-interrupt" fn has_x86_interrupt_abi(_p: *const u8) {}
4 changes: 2 additions & 2 deletions tests/codegen-llvm/naked-asan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ pub fn caller() {
unsafe { asm!("call {}", sym page_fault_handler) }
}

// CHECK: declare x86_intrcc void @page_fault_handler(){{.*}}#[[ATTRS:[0-9]+]]
// CHECK: declare x86_intrcc void @page_fault_handler(ptr {{.*}}, i64{{.*}}){{.*}}#[[ATTRS:[0-9]+]]
#[unsafe(naked)]
#[no_mangle]
pub extern "x86-interrupt" fn page_fault_handler() {
pub extern "x86-interrupt" fn page_fault_handler(_: u64, _: u64) {
naked_asm!("ud2")
}

Expand Down
18 changes: 9 additions & 9 deletions tests/ui/abi/cannot-be-called.avr.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -19,53 +19,53 @@ LL | extern "riscv-interrupt-s" fn riscv_s() {}
error[E0570]: "x86-interrupt" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:45:8
|
LL | extern "x86-interrupt" fn x86() {}
LL | extern "x86-interrupt" fn x86(_x: *const u8) {}
| ^^^^^^^^^^^^^^^

error[E0570]: "msp430-interrupt" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:70:25
--> $DIR/cannot-be-called.rs:72:25
|
LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) {
| ^^^^^^^^^^^^^^^^^^

error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:76:26
--> $DIR/cannot-be-called.rs:78:26
|
LL | fn riscv_m_ptr(f: extern "riscv-interrupt-m" fn()) {
| ^^^^^^^^^^^^^^^^^^^

error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:82:26
--> $DIR/cannot-be-called.rs:84:26
|
LL | fn riscv_s_ptr(f: extern "riscv-interrupt-s" fn()) {
| ^^^^^^^^^^^^^^^^^^^

error[E0570]: "x86-interrupt" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:88:22
--> $DIR/cannot-be-called.rs:90:22
|
LL | fn x86_ptr(f: extern "x86-interrupt" fn()) {
| ^^^^^^^^^^^^^^^

error: functions with the "avr-interrupt" ABI cannot be called
--> $DIR/cannot-be-called.rs:50:5
--> $DIR/cannot-be-called.rs:52:5
|
LL | avr();
| ^^^^^
|
note: an `extern "avr-interrupt"` function can only be called using inline assembly
--> $DIR/cannot-be-called.rs:50:5
--> $DIR/cannot-be-called.rs:52:5
|
LL | avr();
| ^^^^^

error: functions with the "avr-interrupt" ABI cannot be called
--> $DIR/cannot-be-called.rs:66:5
--> $DIR/cannot-be-called.rs:68:5
|
LL | f()
| ^^^
|
note: an `extern "avr-interrupt"` function can only be called using inline assembly
--> $DIR/cannot-be-called.rs:66:5
--> $DIR/cannot-be-called.rs:68:5
|
LL | f()
| ^^^
Expand Down
24 changes: 12 additions & 12 deletions tests/ui/abi/cannot-be-called.i686.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -23,49 +23,49 @@ LL | extern "riscv-interrupt-s" fn riscv_s() {}
| ^^^^^^^^^^^^^^^^^^^

error[E0570]: "avr-interrupt" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:64:22
--> $DIR/cannot-be-called.rs:66:22
|
LL | fn avr_ptr(f: extern "avr-interrupt" fn()) {
| ^^^^^^^^^^^^^^^

error[E0570]: "msp430-interrupt" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:70:25
--> $DIR/cannot-be-called.rs:72:25
|
LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) {
| ^^^^^^^^^^^^^^^^^^

error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:76:26
--> $DIR/cannot-be-called.rs:78:26
|
LL | fn riscv_m_ptr(f: extern "riscv-interrupt-m" fn()) {
| ^^^^^^^^^^^^^^^^^^^

error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:82:26
--> $DIR/cannot-be-called.rs:84:26
|
LL | fn riscv_s_ptr(f: extern "riscv-interrupt-s" fn()) {
| ^^^^^^^^^^^^^^^^^^^

error: functions with the "x86-interrupt" ABI cannot be called
--> $DIR/cannot-be-called.rs:58:5
--> $DIR/cannot-be-called.rs:60:5
|
LL | x86();
| ^^^^^
LL | x86(&raw const BYTE);
| ^^^^^^^^^^^^^^^^^^^^
|
note: an `extern "x86-interrupt"` function can only be called using inline assembly
--> $DIR/cannot-be-called.rs:58:5
--> $DIR/cannot-be-called.rs:60:5
|
LL | x86();
| ^^^^^
LL | x86(&raw const BYTE);
| ^^^^^^^^^^^^^^^^^^^^

error: functions with the "x86-interrupt" ABI cannot be called
--> $DIR/cannot-be-called.rs:90:5
--> $DIR/cannot-be-called.rs:92:5
|
LL | f()
| ^^^
|
note: an `extern "x86-interrupt"` function can only be called using inline assembly
--> $DIR/cannot-be-called.rs:90:5
--> $DIR/cannot-be-called.rs:92:5
|
LL | f()
| ^^^
Expand Down
18 changes: 9 additions & 9 deletions tests/ui/abi/cannot-be-called.msp430.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -19,53 +19,53 @@ LL | extern "riscv-interrupt-s" fn riscv_s() {}
error[E0570]: "x86-interrupt" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:45:8
|
LL | extern "x86-interrupt" fn x86() {}
LL | extern "x86-interrupt" fn x86(_x: *const u8) {}
| ^^^^^^^^^^^^^^^

error[E0570]: "avr-interrupt" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:64:22
--> $DIR/cannot-be-called.rs:66:22
|
LL | fn avr_ptr(f: extern "avr-interrupt" fn()) {
| ^^^^^^^^^^^^^^^

error[E0570]: "riscv-interrupt-m" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:76:26
--> $DIR/cannot-be-called.rs:78:26
|
LL | fn riscv_m_ptr(f: extern "riscv-interrupt-m" fn()) {
| ^^^^^^^^^^^^^^^^^^^

error[E0570]: "riscv-interrupt-s" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:82:26
--> $DIR/cannot-be-called.rs:84:26
|
LL | fn riscv_s_ptr(f: extern "riscv-interrupt-s" fn()) {
| ^^^^^^^^^^^^^^^^^^^

error[E0570]: "x86-interrupt" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:88:22
--> $DIR/cannot-be-called.rs:90:22
|
LL | fn x86_ptr(f: extern "x86-interrupt" fn()) {
| ^^^^^^^^^^^^^^^

error: functions with the "msp430-interrupt" ABI cannot be called
--> $DIR/cannot-be-called.rs:52:5
--> $DIR/cannot-be-called.rs:54:5
|
LL | msp430();
| ^^^^^^^^
|
note: an `extern "msp430-interrupt"` function can only be called using inline assembly
--> $DIR/cannot-be-called.rs:52:5
--> $DIR/cannot-be-called.rs:54:5
|
LL | msp430();
| ^^^^^^^^

error: functions with the "msp430-interrupt" ABI cannot be called
--> $DIR/cannot-be-called.rs:72:5
--> $DIR/cannot-be-called.rs:74:5
|
LL | f()
| ^^^
|
note: an `extern "msp430-interrupt"` function can only be called using inline assembly
--> $DIR/cannot-be-called.rs:72:5
--> $DIR/cannot-be-called.rs:74:5
|
LL | f()
| ^^^
Expand Down
24 changes: 12 additions & 12 deletions tests/ui/abi/cannot-be-called.riscv32.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,71 +13,71 @@ LL | extern "avr-interrupt" fn avr() {}
error[E0570]: "x86-interrupt" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:45:8
|
LL | extern "x86-interrupt" fn x86() {}
LL | extern "x86-interrupt" fn x86(_x: *const u8) {}
| ^^^^^^^^^^^^^^^

error[E0570]: "avr-interrupt" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:64:22
--> $DIR/cannot-be-called.rs:66:22
|
LL | fn avr_ptr(f: extern "avr-interrupt" fn()) {
| ^^^^^^^^^^^^^^^

error[E0570]: "msp430-interrupt" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:70:25
--> $DIR/cannot-be-called.rs:72:25
|
LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) {
| ^^^^^^^^^^^^^^^^^^

error[E0570]: "x86-interrupt" is not a supported ABI for the current target
--> $DIR/cannot-be-called.rs:88:22
--> $DIR/cannot-be-called.rs:90:22
|
LL | fn x86_ptr(f: extern "x86-interrupt" fn()) {
| ^^^^^^^^^^^^^^^

error: functions with the "riscv-interrupt-m" ABI cannot be called
--> $DIR/cannot-be-called.rs:54:5
--> $DIR/cannot-be-called.rs:56:5
|
LL | riscv_m();
| ^^^^^^^^^
|
note: an `extern "riscv-interrupt-m"` function can only be called using inline assembly
--> $DIR/cannot-be-called.rs:54:5
--> $DIR/cannot-be-called.rs:56:5
|
LL | riscv_m();
| ^^^^^^^^^

error: functions with the "riscv-interrupt-s" ABI cannot be called
--> $DIR/cannot-be-called.rs:56:5
--> $DIR/cannot-be-called.rs:58:5
|
LL | riscv_s();
| ^^^^^^^^^
|
note: an `extern "riscv-interrupt-s"` function can only be called using inline assembly
--> $DIR/cannot-be-called.rs:56:5
--> $DIR/cannot-be-called.rs:58:5
|
LL | riscv_s();
| ^^^^^^^^^

error: functions with the "riscv-interrupt-m" ABI cannot be called
--> $DIR/cannot-be-called.rs:78:5
--> $DIR/cannot-be-called.rs:80:5
|
LL | f()
| ^^^
|
note: an `extern "riscv-interrupt-m"` function can only be called using inline assembly
--> $DIR/cannot-be-called.rs:78:5
--> $DIR/cannot-be-called.rs:80:5
|
LL | f()
| ^^^

error: functions with the "riscv-interrupt-s" ABI cannot be called
--> $DIR/cannot-be-called.rs:84:5
--> $DIR/cannot-be-called.rs:86:5
|
LL | f()
| ^^^
|
note: an `extern "riscv-interrupt-s"` function can only be called using inline assembly
--> $DIR/cannot-be-called.rs:84:5
--> $DIR/cannot-be-called.rs:86:5
|
LL | f()
| ^^^
Expand Down
Loading
Loading