Skip to content
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

calling convention for MSP430 interrupts #38465

Merged
merged 2 commits into from
Jan 19, 2017

Conversation

japaric
Copy link
Member

@japaric japaric commented Dec 19, 2016

This calling convention is used to define interrup handlers on MSP430 microcontrollers. Usage looks like this:

#[no_mangle]
#[link_section = "__interrupt_vector_10"]
pub static TIM0_VECTOR: unsafe extern "msp430-interrupt" fn() = tim0;

unsafe extern "msp430-interrupt" fn tim0() {
  P1OUT.write(0x00);
}

which generates the following assembly:

Disassembly of section __interrupt_vector_10:

0000fff2 <TIM0_VECTOR>:
    fff2:       10 c0           interrupt service routine at 0xc010

Disassembly of section .text:

0000c010 <_ZN3msp4tim017h3193b957fd6a4fd4E>:
    c010:       c2 43 21 00     mov.b   #0,     &0x0021 ;r3 As==00
    c014:       00 13           reti
        ...

@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @alexcrichton (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

@petrochenkov
Copy link
Contributor

This should probably be feature gated as well - https://github.com/rust-lang/rust/blob/master/src/libsyntax/feature_gate.rs#L963 (+ the match needs to be exhaustive so a new ABI is not missed unintentionally next time).

@japaric
Copy link
Member Author

japaric commented Dec 19, 2016

I was wondering if we had feature gates for new ABIs. Thanks for the heads up, @petrochenkov. I'll add the gate in a bit.

@alexcrichton
Copy link
Member

Yeah we'll definitely want to gate this, but otherwise seems ok to me. In that sense that name shouldn't matter too much for now.

@pftbest
Copy link
Contributor

pftbest commented Dec 19, 2016

I have tested this PR, and it works fine. This rust code:

#[no_mangle]
#[link_section = "__interrupt_vector_10"]
pub static TIM0_VECTOR: unsafe extern "msp430-interrupt" fn() = tim0;

unsafe extern "msp430-interrupt" fn tim0() {
  P1OUT.write(0x00);
}

Generates this assembly:

Disassembly of section __interrupt_vector_10:

0000fff2 <TIM0_VECTOR>:
    fff2:       10 c0           interrupt service routine at 0xc010

Disassembly of section .text:

0000c010 <_ZN3msp4tim017h3193b957fd6a4fd4E>:
    c010:       c2 43 21 00     mov.b   #0,     &0x0021 ;r3 As==00
    c014:       00 13           reti
        ...

It looks good to me.

@japaric japaric changed the title WIP: calling convention for MSP430 interrupts calling convention for MSP430 interrupts Dec 19, 2016
@japaric
Copy link
Member Author

japaric commented Dec 19, 2016

@pftbest Excellent

r? @alexcrichton Added the feature gate. Should I create a tracking issue for the stability of the new ABI?

@alexcrichton
Copy link
Member

Looks like the travis failure is legitimate, and could you also add a test to ensure this ABI is gated? And yeah let's add a tracking issue.

@petrochenkov
Copy link
Contributor

could you also add a test to ensure this ABI is gated

(ABI stability tests are centralized in src\test\compile-fail\feature-gate-abi.rs)

@japaric
Copy link
Member Author

japaric commented Dec 20, 2016

@alexcrichton Updated. Still testing locally.

Thanks for the info, @petrochenkov!

@nagisa
Copy link
Member

nagisa commented Dec 20, 2016

Okay, so if my memory doesn’t mislead me, we added #[naked] functions precisely so that interrupt ABIs wouldn’t proliferate. Perhaps it would make more sense to focus more effort on stabilising (and fixing) that approach than adding a new ABI?

@japaric
Copy link
Member Author

japaric commented Dec 20, 2016

Perhaps it would make more sense to focus more effort on stabilising (and fixing) that approach than adding a new ABI?

Before even considering using this ABI as an argument for stabilizing naked functions, we should first verify that this particular ABI can actually be implemented using naked functions (I don't know the answer). If that's the case, this unstable ABI could be removed in favor of that (but ergonomics should be considered before reaching a decision).

Personally, I'd prefer to land a sure and ergonomic (but unstable) way to write interrupt handlers for this architecture, this ABI, right now and then consider whether such ABI should be stabilized or removed/deprecated in favor of (stable) naked functions.

@eddyb
Copy link
Member

eddyb commented Dec 20, 2016

TBH I would prefer an "interrupt" pseudo-ABI with platform-specific constraints that "does the right thing".

@pftbest
Copy link
Contributor

pftbest commented Dec 20, 2016

@nagisa
Consider this code:

unsafe extern "msp430-interrupt" fn tim0() {
    not_inlined_foo();
}

I can write it using naked functions like this:

#[naked]
unsafe extern "C" fn tim1() {
    asm! {
        "
        push	r15
        push	r14
        push	r13
        push	r12
        "
    }
    not_inlined_foo();
    asm! {
        "
        pop	r12
        pop	r13
        pop	r14
        pop	r15
        reti
        "
    }
}

It does not look pretty but at least it works the same.
Now consider this code:

unsafe extern "msp430-interrupt" fn tim0() {
    P1OUT.write(0x00);
}

This code I can't write as a naked function, because I don't know how many registers I need to save for this inlined .write call. I can wrap the code into a new inline(never) function and save all registers like in the first case, but it will be a massive overhead for such tiny MCU.

Also we would like to have support for the __bic_SR_register_on_exit intrinsic in the future, and it has a restriction that it can only be used inside an isr handler, so maybe this ABI will help to check for that.

@bors
Copy link
Contributor

bors commented Dec 21, 2016

☔ The latest upstream changes (presumably #38099) made this pull request unmergeable. Please resolve the merge conflicts.

@japaric
Copy link
Member Author

japaric commented Dec 21, 2016

rebased

@eddyb an "interrupt" ABI makes sense to me. I'd like to have at least one more interrupt-ish ABI (e.g. "avr-interrupt") before prototyping that; that way we can test in properly.

@pftbest those are my concerns exactly: ergonomics and error-proneness. In theory, it might be possible to create a syntax extension that implements "msp430-interrupt" on top of #[naked] but I don't know if that could have all the features that a real ABI enables (cf. the __bic_SR_register_on_exit intrinsic).

@nagisa
Copy link
Member

nagisa commented Dec 21, 2016

This code I can't write as a naked function, because I don't know how many registers I need to save for this inlined .write call.

The C ABI for your platform should have somewhere a list of caller-saved (volatile) and callee-saved (non-volatile) registers. The saving and restoring as well as call overhead are unfortunate, though and this is the reason why an interrupt ABI is strictly better than naked functions.

That being said, I would still rather we only had either one (naked fns) or the other (interrupt ABIs). The issue with 2nd thing is that LLVM obviously does not support your arbitrary hardware interrupt ABI, which is why naked got accepted, consciously and instead of interrupt ABIs.

@pftbest
Copy link
Contributor

pftbest commented Dec 21, 2016

@nagisa

The C ABI for your platform should have somewhere a list of caller-saved (volatile) and callee-saved (non-volatile) registers.

I was talking about it in my examples. If the code contains only call to non inlined function like in the first example, it is enough to save only caller-saved registers (r12-r15).
But if the code is inlined like in the second example it may be neccessary to save all the registers both volatile and non-volatile.

Some architectures do not have special ABI for interrupts, so they use naked functions. But for MSP430 it is available, and it would be unfortunate not being able to use it.

@pftbest
Copy link
Contributor

pftbest commented Dec 21, 2016

Just to give a perspective on the overhead of using naked functions, I did a caculation.
All numbers are taked from the datasheet

If the code is using proposed ABI it will have
6 cycles to enter ISR and start running user code
5 cycles to exit ISR

If the code is using naked functions it will get this numbers:
22 cycles to enter ISR and start running user code
(6 + 3x4 for each push + 4 for call) and
16 cycles to exit ISR
(3 for return + 2x4 for pop + 5)

You can say that if you care about this numbers you should be writing in assembly, but I think It would be great if rust could be at least as efficient as C in this regard.

@bors
Copy link
Contributor

bors commented Dec 30, 2016

☔ The latest upstream changes (presumably #38697) made this pull request unmergeable. Please resolve the merge conflicts.

@bors
Copy link
Contributor

bors commented Dec 31, 2016

☔ The latest upstream changes (presumably #38482) made this pull request unmergeable. Please resolve the merge conflicts.

@whitequark
Copy link
Member

@nagisa

The C ABI for your platform should have somewhere a list of caller-saved (volatile) and callee-saved (non-volatile) registers.

How is the C ABI (or any ABI) relevant here? An interrupt handler must save every register it uses, precisely because it is not invoked on a function boundary.

@nagisa
Copy link
Member

nagisa commented Jan 1, 2017

@whitequark Since we’re talking trampolines here, you can avoid saving the non-volatile (aka. callee-saved) registers because no callee is allowed to modify them without also saving them beforehand and restoring register later, right?

The preserve_mostcc and preserve_allcc LLVM CCs are relevant.


Remember that I’m not arguing against interrupt ABIs. I’m arguing for having EITHER one or the other and not both. Honestly, though, I dislike naked functions and would rather have interrupt ABIs (having seen what mess #[naked] is and despite what I said back then), but RFC process has ruled otherwise.

@whitequark
Copy link
Member

@whitequark Since we’re talking trampolines here, you can avoid saving the non-volatile (aka. callee-saved) registers because no callee is allowed to modify them without also saving them beforehand and restoring register later, right?

Ah, so what you're suggesting is a naked function that only contains a single call instruction, which calls the actual interrupt handler. I see how this may work.

Now, the $1M question: why not define the "interrupt" ABI to generate such a trampoline automatically?

@pftbest
Copy link
Contributor

pftbest commented Jan 1, 2017

@nagisa What conflict do you see in having both of them? C has both and no one complained as far as I know. Besides, naked functions may have other uses apart from the interrupts, like JITs and green threading for example.

@alexcrichton
Copy link
Member

er nvmd, I'll check it for you, you've reviewed

@alexcrichton
Copy link
Member

@japaric I believe this is ready to go after a rebase now.

@eddyb
Copy link
Member

eddyb commented Jan 17, 2017

r=me w/ rebase

This calling convention is used to define interrup handlers on MSP430
microcontrollers. Usage looks like this:

``` rust
#[no_mangle]
#[link_section = "__interrupt_vector_10"]
pub static TIM0_VECTOR: unsafe extern "msp430-interrupt" fn() = tim0;

unsafe extern "msp430-interrupt" fn tim0() {
  P1OUT.write(0x00);
}
```

which generates the following assembly:

``` asm
Disassembly of section __interrupt_vector_10:

0000fff2 <TIM0_VECTOR>:
    fff2:       10 c0           interrupt service routine at 0xc010

Disassembly of section .text:

0000c010 <_ZN3msp4tim017h3193b957fd6a4fd4E>:
    c010:       c2 43 21 00     mov.b   #0,     &0x0021 ;r3 As==00
    c014:       00 13           reti
        ...
```
@japaric
Copy link
Member Author

japaric commented Jan 19, 2017

@bors r=eddyb

yes, certainly. I was expecting a tracking issue for the relevant feature gate.

@nikomatsakis #38487

@bors
Copy link
Contributor

bors commented Jan 19, 2017

📌 Commit 6296d52 has been approved by eddyb

@bors
Copy link
Contributor

bors commented Jan 19, 2017

⌛ Testing commit 6296d52 with merge d7c4093...

@bors
Copy link
Contributor

bors commented Jan 19, 2017

💔 Test failed - status-travis

@nikomatsakis
Copy link
Contributor

@japaric

This failed because you have no test for this feature gate (it's a new requirement). The very helpful error message by @est31 explains what you have to do to fix it =)

Expected a gate test for the feature 'abi_msp430_interrupt'.

Hint: create a file named 'feature-gate-abi_msp430_interrupt.rs' in the compile-fail

      test suite, with its failures due to missing usage of

      #![feature(abi_msp430_interrupt)].

Hint: If you already have such a test and don't want to rename it,

      you can also add a // gate-test-abi_msp430_interrupt line to the test file.

Found 1 features without a gate test.

thread 'main' panicked at 'some tidy checks failed', /checkout/src/tools/tidy/src/main.rs:55

note: Run with `RUST_BACKTRACE=1` for a backtrace.

@japaric
Copy link
Member Author

japaric commented Jan 19, 2017

Thanks, @nikomatsakis. I had done that (the cfail test) for another PR but hadn't realize that it had to be done for this one too.

@bors r=eddyb

@bors
Copy link
Contributor

bors commented Jan 19, 2017

📌 Commit e928c75 has been approved by eddyb

@bors
Copy link
Contributor

bors commented Jan 19, 2017

⌛ Testing commit e928c75 with merge 8e29b4d...

bors added a commit that referenced this pull request Jan 19, 2017
calling convention for MSP430 interrupts

This calling convention is used to define interrup handlers on MSP430 microcontrollers. Usage looks like this:

``` rust
#[no_mangle]
#[link_section = "__interrupt_vector_10"]
pub static TIM0_VECTOR: unsafe extern "msp430-interrupt" fn() = tim0;

unsafe extern "msp430-interrupt" fn tim0() {
  P1OUT.write(0x00);
}
```

which generates the following assembly:

``` asm
Disassembly of section __interrupt_vector_10:

0000fff2 <TIM0_VECTOR>:
    fff2:       10 c0           interrupt service routine at 0xc010

Disassembly of section .text:

0000c010 <_ZN3msp4tim017h3193b957fd6a4fd4E>:
    c010:       c2 43 21 00     mov.b   #0,     &0x0021 ;r3 As==00
    c014:       00 13           reti
        ...
```
@bors
Copy link
Contributor

bors commented Jan 19, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: eddyb
Pushing 8e29b4d to master...

@bors bors merged commit e928c75 into rust-lang:master Jan 19, 2017
frewsxcv added a commit to frewsxcv/rust that referenced this pull request Mar 2, 2017
…ention, r=nagisa

Add support for the x86-interrupt calling convention

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:

```rust
extern "x86-interrupt" fn handler(stack_frame: &ExceptionStackFrame) {…}
```

for interrupts and exceptions without error code and

```rust
extern "x86-interrupt" fn handler_with_err_code(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

It is also possible to implement interrupt handlers on x86 through [naked functions](https://github.com/rust-lang/rfcs/blob/master/text/1201-naked-fns.md). In fact, almost all existing Rust OS projects for x86 use naked functions for this, including [Redox](https://github.com/redox-os/kernel/blob/b9793deb59c7650f0805dea96adb6b773ad99336/arch/x86_64/src/lib.rs#L109-L147), [IntermezzOS](https://github.com/intermezzOS/kernel/blob/f959cc18c78b1ba153f3ff7039d9ecc07f397628/interrupts/src/lib.rs#L28-L72), and [blog_os](https://github.com/phil-opp/blog_os/blob/844d739379ffdea6a7ede88365ec6e21a725bbf5/src/interrupts/mod.rs#L49-L64). So support for the `x86-interrupt` calling convention isn't absolutely needed.

However, it has a number of benefits to naked functions:

- **No inline assembly needed**: [Inline assembly](https://doc.rust-lang.org/book/inline-assembly.html) is highly unstable and dangerous. It's pretty easy to mess things up. Also, it uses an arcane syntax and requires that the programmer knows x86 assembly.
- **Higher performance**: A naked wrapper function always saves _all_ registers before calling the Rust function. This isn't needed for a compiler supported calling convention, since the compiler knows which registers are clobbered by the interrupt handler. Thus, only these registers need to be saved and restored.
- **Safer interfaces**: We can write a `set_handler` function that takes a `extern "x86-interrupt" fn(&ExceptionStackFrame)` and the compiler ensures that we always use the right function type for all handler functions. This isn't possible with the `#[naked]` attribute.
- **More convenient**: Instead of writing [tons of assembly boilerplate](https://github.com/redox-os/kernel/blob/b9793deb59c7650f0805dea96adb6b773ad99336/arch/x86_64/src/lib.rs#L109-L147) and desperately trying to improve things [through macros](https://github.com/phil-opp/blog_os/blob/844d739379ffdea6a7ede88365ec6e21a725bbf5/src/interrupts/mod.rs#L17-L92), we can just write [code like this](https://github.com/phil-opp/blog_os/blob/e6a61f9507a4c4fef6fb4e3474bc596391bc97d2/src/interrupts/mod.rs#L85-L89).
- **Naked functions are unreliable**: It is allowed to use Rust code inside a naked function, which sometimes works and sometimes not. For example, [calling a function](https://github.com/redox-os/kernel/blob/b9793deb59c7650f0805dea96adb6b773ad99336/arch/x86_64/src/lib.rs#L132) through Rust code seems to work fine without function prologue, but [code declaring a variable](https://is.gd/NQYXqE) silently adds a prologue even though the function is naked (look at the generated assembly, there is a `movl` instruction before the `nop`).

**Edit**: See the [tracking issue](rust-lang#40180) for an updated list of issues.

Unfortunately, the implementation of the `x86-interrupt` calling convention in LLVM has some issues that make it unsuitable for 64-bit kernels at the moment:

- LLVM always tries to backup the `xmm` registers on 64-bit platforms even if the target doesn't support SSE. This leads to invalid opcode exceptions whenever an interrupt handler is invoked. I submitted a fix to LLVM in [D29959](https://reviews.llvm.org/D29959). The fix is really small (<10 lines), so maybe we could backport it to [Rust's LLVM fork](https://github.com/rust-lang/llvm)?. **Edit**: The fix was merged to LLVM trunk in [rL295347](https://reviews.llvm.org/rL295347). Backported in rust-lang/llvm#63.

- On targets with SSE support, LLVM uses the `movaps` instruction for saving the `xmm` registers, which requires an alignment of 16. For handlers with error codes, however, the stack alignment is only 8, so a alignment exception occurs. This issue is tracked in [bug 26413](https://bugs.llvm.org/show_bug.cgi?id=26413). ~~Unfortunately, I don't know enough about LLVM to fix this.~~ **Edit**: Fix submitted in [D30049](https://reviews.llvm.org/D30049).

This PR adds experimental support for this calling convention under the `abi_x86_interrupt` feature gate. The implementation is very similar to rust-lang#38465 and was surprisingly simple :).

There is no accepted RFC for this change. In fact, the [RFC for interrupt calling convention](rust-lang/rfcs#1275) from 2015 was closed in favor of naked functions. However, the reactions to the recent [PR](rust-lang#38465) for a MSP430 interrupt calling convention were [in favor of experimental interrupt ABIs](rust-lang#38465 (comment)).

- [x] Add compile-fail tests for the feature gate.
- [x] Create tracking issue for the `abi_x86_interrupt` feature (and link it in code). **Edit**: Tracking issue: rust-lang#40180
- [x] Backport [rL295347](https://reviews.llvm.org/rL295347) to Rust's LLVM fork. **Edit**: Done in rust-lang/llvm#63

@tari @steveklabnik @jackpot51 @ticki @hawkw @thepowersgang, you might be interested in this.
frewsxcv added a commit to frewsxcv/rust that referenced this pull request Mar 2, 2017
…ention, r=nagisa

Add support for the x86-interrupt calling convention

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:

```rust
extern "x86-interrupt" fn handler(stack_frame: &ExceptionStackFrame) {…}
```

for interrupts and exceptions without error code and

```rust
extern "x86-interrupt" fn handler_with_err_code(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

It is also possible to implement interrupt handlers on x86 through [naked functions](https://github.com/rust-lang/rfcs/blob/master/text/1201-naked-fns.md). In fact, almost all existing Rust OS projects for x86 use naked functions for this, including [Redox](https://github.com/redox-os/kernel/blob/b9793deb59c7650f0805dea96adb6b773ad99336/arch/x86_64/src/lib.rs#L109-L147), [IntermezzOS](https://github.com/intermezzOS/kernel/blob/f959cc18c78b1ba153f3ff7039d9ecc07f397628/interrupts/src/lib.rs#L28-L72), and [blog_os](https://github.com/phil-opp/blog_os/blob/844d739379ffdea6a7ede88365ec6e21a725bbf5/src/interrupts/mod.rs#L49-L64). So support for the `x86-interrupt` calling convention isn't absolutely needed.

However, it has a number of benefits to naked functions:

- **No inline assembly needed**: [Inline assembly](https://doc.rust-lang.org/book/inline-assembly.html) is highly unstable and dangerous. It's pretty easy to mess things up. Also, it uses an arcane syntax and requires that the programmer knows x86 assembly.
- **Higher performance**: A naked wrapper function always saves _all_ registers before calling the Rust function. This isn't needed for a compiler supported calling convention, since the compiler knows which registers are clobbered by the interrupt handler. Thus, only these registers need to be saved and restored.
- **Safer interfaces**: We can write a `set_handler` function that takes a `extern "x86-interrupt" fn(&ExceptionStackFrame)` and the compiler ensures that we always use the right function type for all handler functions. This isn't possible with the `#[naked]` attribute.
- **More convenient**: Instead of writing [tons of assembly boilerplate](https://github.com/redox-os/kernel/blob/b9793deb59c7650f0805dea96adb6b773ad99336/arch/x86_64/src/lib.rs#L109-L147) and desperately trying to improve things [through macros](https://github.com/phil-opp/blog_os/blob/844d739379ffdea6a7ede88365ec6e21a725bbf5/src/interrupts/mod.rs#L17-L92), we can just write [code like this](https://github.com/phil-opp/blog_os/blob/e6a61f9507a4c4fef6fb4e3474bc596391bc97d2/src/interrupts/mod.rs#L85-L89).
- **Naked functions are unreliable**: It is allowed to use Rust code inside a naked function, which sometimes works and sometimes not. For example, [calling a function](https://github.com/redox-os/kernel/blob/b9793deb59c7650f0805dea96adb6b773ad99336/arch/x86_64/src/lib.rs#L132) through Rust code seems to work fine without function prologue, but [code declaring a variable](https://is.gd/NQYXqE) silently adds a prologue even though the function is naked (look at the generated assembly, there is a `movl` instruction before the `nop`).

**Edit**: See the [tracking issue](rust-lang#40180) for an updated list of issues.

Unfortunately, the implementation of the `x86-interrupt` calling convention in LLVM has some issues that make it unsuitable for 64-bit kernels at the moment:

- LLVM always tries to backup the `xmm` registers on 64-bit platforms even if the target doesn't support SSE. This leads to invalid opcode exceptions whenever an interrupt handler is invoked. I submitted a fix to LLVM in [D29959](https://reviews.llvm.org/D29959). The fix is really small (<10 lines), so maybe we could backport it to [Rust's LLVM fork](https://github.com/rust-lang/llvm)?. **Edit**: The fix was merged to LLVM trunk in [rL295347](https://reviews.llvm.org/rL295347). Backported in rust-lang/llvm#63.

- On targets with SSE support, LLVM uses the `movaps` instruction for saving the `xmm` registers, which requires an alignment of 16. For handlers with error codes, however, the stack alignment is only 8, so a alignment exception occurs. This issue is tracked in [bug 26413](https://bugs.llvm.org/show_bug.cgi?id=26413). ~~Unfortunately, I don't know enough about LLVM to fix this.~~ **Edit**: Fix submitted in [D30049](https://reviews.llvm.org/D30049).

This PR adds experimental support for this calling convention under the `abi_x86_interrupt` feature gate. The implementation is very similar to rust-lang#38465 and was surprisingly simple :).

There is no accepted RFC for this change. In fact, the [RFC for interrupt calling convention](rust-lang/rfcs#1275) from 2015 was closed in favor of naked functions. However, the reactions to the recent [PR](rust-lang#38465) for a MSP430 interrupt calling convention were [in favor of experimental interrupt ABIs](rust-lang#38465 (comment)).

- [x] Add compile-fail tests for the feature gate.
- [x] Create tracking issue for the `abi_x86_interrupt` feature (and link it in code). **Edit**: Tracking issue: rust-lang#40180
- [x] Backport [rL295347](https://reviews.llvm.org/rL295347) to Rust's LLVM fork. **Edit**: Done in rust-lang/llvm#63

@tari @steveklabnik @jackpot51 @ticki @hawkw @thepowersgang, you might be interested in this.
@japaric japaric mentioned this pull request Apr 7, 2017
9 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.