Skip to content

Commit b448058

Browse files
committed
Add support for x86-interrupt calling convention
Tracking issue: #40180 This calling convention can be used for definining interrupt handlers on 32-bit and 64-bit x86 targets. The compiler then uses `iret` instead of `ret` for returning and ensures that all registers are restored to their original values. Usage: ``` extern "x86-interrupt" fn handler(stack_frame: &ExceptionStackFrame) {…} ``` for interrupts and exceptions without error code and ``` extern "x86-interrupt" fn page_fault_handler(stack_frame: &ExceptionStackFrame, error_code: u64) {…} ``` for exceptions that push an error code (e.g., page faults or general protection faults). The programmer must ensure that the correct version is used for each interrupt. For more details see the [LLVM PR][1] and the corresponding [proposal][2]. [1]: https://reviews.llvm.org/D15567 [2]: http://lists.llvm.org/pipermail/cfe-dev/2015-September/045171.html
1 parent 8ae411e commit b448058

File tree

7 files changed

+48
-1
lines changed

7 files changed

+48
-1
lines changed

src/librustc_llvm/ffi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub enum CallConv {
5353
X86_64_SysV = 78,
5454
X86_64_Win64 = 79,
5555
X86_VectorCall = 80,
56+
X86_Intr = 83,
5657
}
5758

5859
/// LLVMRustLinkage

src/librustc_trans/abi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ impl FnType {
355355
Aapcs => llvm::ArmAapcsCallConv,
356356
PtxKernel => llvm::PtxKernel,
357357
Msp430Interrupt => llvm::Msp430Intr,
358+
X86Interrupt => llvm::X86_Intr,
358359

359360
// These API constants ought to be more specific...
360361
Cdecl => llvm::CCallConv,

src/libsyntax/abi.rs

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub enum Abi {
2525
SysV64,
2626
PtxKernel,
2727
Msp430Interrupt,
28+
X86Interrupt,
2829

2930
// Multiplatform / generic ABIs
3031
Rust,
@@ -59,6 +60,7 @@ const AbiDatas: &'static [AbiData] = &[
5960
AbiData {abi: Abi::SysV64, name: "sysv64", generic: false },
6061
AbiData {abi: Abi::PtxKernel, name: "ptx-kernel", generic: false },
6162
AbiData {abi: Abi::Msp430Interrupt, name: "msp430-interrupt", generic: false },
63+
AbiData {abi: Abi::X86Interrupt, name: "x86-interrupt", generic: false },
6264

6365
// Cross-platform ABIs
6466
AbiData {abi: Abi::Rust, name: "Rust", generic: true },

src/libsyntax/feature_gate.rs

+7
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,9 @@ declare_features! (
330330
// Used to identify crates that contain sanitizer runtimes
331331
// rustc internal
332332
(active, sanitizer_runtime, "1.17.0", None),
333+
334+
// `extern "x86-interrupt" fn()`
335+
(active, abi_x86_interrupt, "1.17.0", Some(40180)),
333336
);
334337

335338
declare_features! (
@@ -1036,6 +1039,10 @@ impl<'a> PostExpansionVisitor<'a> {
10361039
gate_feature_post!(&self, abi_msp430_interrupt, span,
10371040
"msp430-interrupt ABI is experimental and subject to change");
10381041
},
1042+
Abi::X86Interrupt => {
1043+
gate_feature_post!(&self, abi_x86_interrupt, span,
1044+
"x86-interrupt ABI is experimental and subject to change");
1045+
},
10391046
// Stable
10401047
Abi::Cdecl |
10411048
Abi::Stdcall |

src/test/codegen/abi-x86-interrupt.rs

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Checks if the correct annotation for the x86-interrupt ABI is passed to
12+
// llvm. Also checks that the abi_x86_interrupt feature gate allows usage
13+
// of the x86-interrupt abi.
14+
15+
// ignore-arm
16+
// ignore-aarch64
17+
// min-llvm-version 3.8
18+
19+
// compile-flags: -C no-prepopulate-passes
20+
21+
#![crate_type = "lib"]
22+
#![feature(abi_x86_interrupt)]
23+
24+
// CHECK: define x86_intrcc i64 @has_x86_interrupt_abi
25+
#[no_mangle]
26+
pub extern "x86-interrupt" fn has_x86_interrupt_abi(a: i64) -> i64 {
27+
a * 2
28+
}

src/test/compile-fail/feature-gate-abi.rs

+8
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// gate-test-platform_intrinsics
1313
// gate-test-abi_vectorcall
1414
// gate-test-abi_ptx
15+
// gate-test-abi_x86_interrupt
1516

1617
// Functions
1718
extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
@@ -20,6 +21,7 @@ extern "vectorcall" fn f3() {} //~ ERROR vectorcall is experimental and subject
2021
extern "rust-call" fn f4() {} //~ ERROR rust-call ABI is subject to change
2122
extern "msp430-interrupt" fn f5() {} //~ ERROR msp430-interrupt ABI is experimental
2223
extern "ptx-kernel" fn f6() {} //~ ERROR PTX ABIs are experimental and subject to change
24+
extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental
2325

2426
// Methods in trait definition
2527
trait Tr {
@@ -29,13 +31,15 @@ trait Tr {
2931
extern "rust-call" fn m4(); //~ ERROR rust-call ABI is subject to change
3032
extern "msp430-interrupt" fn m5(); //~ ERROR msp430-interrupt ABI is experimental
3133
extern "ptx-kernel" fn m6(); //~ ERROR PTX ABIs are experimental and subject to change
34+
extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental
3235

3336
extern "rust-intrinsic" fn dm1() {} //~ ERROR intrinsics are subject to change
3437
extern "platform-intrinsic" fn dm2() {} //~ ERROR platform intrinsics are experimental
3538
extern "vectorcall" fn dm3() {} //~ ERROR vectorcall is experimental and subject to change
3639
extern "rust-call" fn dm4() {} //~ ERROR rust-call ABI is subject to change
3740
extern "msp430-interrupt" fn dm5() {} //~ ERROR msp430-interrupt ABI is experimental
3841
extern "ptx-kernel" fn dm6() {} //~ ERROR PTX ABIs are experimental and subject to change
42+
extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental
3943
}
4044

4145
struct S;
@@ -48,6 +52,7 @@ impl Tr for S {
4852
extern "rust-call" fn m4() {} //~ ERROR rust-call ABI is subject to change
4953
extern "msp430-interrupt" fn m5() {} //~ ERROR msp430-interrupt ABI is experimental
5054
extern "ptx-kernel" fn m6() {} //~ ERROR PTX ABIs are experimental and subject to change
55+
extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental
5156
}
5257

5358
// Methods in inherent impl
@@ -58,6 +63,7 @@ impl S {
5863
extern "rust-call" fn im4() {} //~ ERROR rust-call ABI is subject to change
5964
extern "msp430-interrupt" fn im5() {} //~ ERROR msp430-interrupt ABI is experimental
6065
extern "ptx-kernel" fn im6() {} //~ ERROR PTX ABIs are experimental and subject to change
66+
extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental
6167
}
6268

6369
// Function pointer types
@@ -67,6 +73,7 @@ type A3 = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental and sub
6773
type A4 = extern "rust-call" fn(); //~ ERROR rust-call ABI is subject to change
6874
type A5 = extern "msp430-interrupt" fn(); //~ ERROR msp430-interrupt ABI is experimental
6975
type A6 = extern "ptx-kernel" fn (); //~ ERROR PTX ABIs are experimental and subject to change
76+
type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental
7077

7178
// Foreign modules
7279
extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change
@@ -75,5 +82,6 @@ extern "vectorcall" {} //~ ERROR vectorcall is experimental and subject to chang
7582
extern "rust-call" {} //~ ERROR rust-call ABI is subject to change
7683
extern "msp430-interrupt" {} //~ ERROR msp430-interrupt ABI is experimental
7784
extern "ptx-kernel" {} //~ ERROR PTX ABIs are experimental and subject to change
85+
extern "x86-interrupt" {} //~ ERROR x86-interrupt ABI is experimental
7886

7987
fn main() {}

src/test/ui/codemap_tests/unicode.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted], found `路濫狼á́́`
1+
error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted], found `路濫狼á́́`
22
--> $DIR/unicode.rs:11:8
33
|
44
11 | extern "路濫狼á́́" fn foo() {}

0 commit comments

Comments
 (0)