-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
RFC on low level features #55
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
- Start Date: 2014-04-29 | ||
- RFC PR #: (leave this empty) | ||
- Rust Issue #: (leave this empty) | ||
|
||
# Summary | ||
|
||
Add a few features that would allow to write better system-level code: weak | ||
symbols, naked functions, pure assembly functions. | ||
|
||
# Motivation | ||
|
||
Those features are available in C and C++ and are often used in embedded | ||
development. | ||
|
||
# Detailed design | ||
|
||
### Weak symbols | ||
|
||
`linkage` attribute should be extended to be allowed in function context | ||
(alternatively a new attribute should be provided): | ||
|
||
```rust | ||
#[no_mangle] | ||
#[linkage(weak)] | ||
pub fn isr_handler() { | ||
... | ||
} | ||
``` | ||
|
||
This would allow to provide default implementations that could be overriden by | ||
specific code. | ||
|
||
### Naked functions | ||
|
||
Provide an attribute that would allow to generate a naked function, without | ||
stack guard prologue, common function prologue and epilogue. The only statement | ||
that could be safely used in naked function is `asm!` that doesn't modify | ||
operands (alternatively, naked functions are always considered _unsafe_). | ||
|
||
```rust | ||
#[naked] | ||
pub fn isr_handler { | ||
asm!("mrs r0, psp | ||
stmdb r0!, {r4-r11} | ||
msr psp, r0" :::: "volatile"); | ||
switch_stack(); | ||
} | ||
``` | ||
|
||
would generate the following machine code: | ||
|
||
``` | ||
isr_handler: | ||
// asm! block | ||
mrs r0, psp | ||
stmdb r0!, {r4-r11} | ||
msr psp, r0 | ||
|
||
// function call | ||
bl switch_stack | ||
|
||
// the only generated instruction | ||
bx lr | ||
``` | ||
|
||
Note how in this example the provided code is incorrect, as `bl` will overwrite | ||
the contents of `lr` register, so that the final `bx lr` instruction will do | ||
something unexpected. It might be useful to disallow function calls from naked | ||
function unless those are done explicity from `asm!` (which is quite hard, | ||
unless the called function has `#[no_mangle]`). | ||
|
||
### Pure assembly functions | ||
|
||
This the extension of naked funcations above, but no code would be generated by | ||
compiler at all. Those functions could be written in an external .s file, but | ||
including them in source code would allow better management, including `#[cfg]` | ||
usage to pick the correct implementation. | ||
|
||
# Alternatives | ||
|
||
N/A | ||
|
||
# Unresolved questions | ||
|
||
N/A |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this be addressed by allowing something like
as a freestanding statement?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Partially. I'm not sure there are absolutely no valid cases to have a naked function with a mangled name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, this statement would be a better fit for "Pure assembly functions" below. Naked function still generates a "return-from-function" statement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@huonw: No. Currently, the workaround is not that simple. This statement must be reachable from Rust code so that it is not recognized as dead code and optimized away.
I believe an appropriate ABI string should be supported. (
unsafe
could be implied byextern "naked"
, and extern "ABI" unsafe fn can't be declared as per rust-lang/rust#10025)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Erm, why couldn't we just make any freestanding
asm!
"hardcoded" to be reachable?Presumably the programmer didn't accidentally throw it there, and approximately knows what they're doing if they're writing raw functions in asm, so the compiler can just trust them and assume it's being used & hence is reachable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to ABI string approach, looks more elegant (
extern "bare"
would be the second case, if rust ends up supporting both).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would rust parse the assembly as well? Where would dangling instructions end up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It wouldn't make sense for
asm!
statements that are notvolatile
. Either way, the programmer could put it somewhere in an unused function, making the compiler generate lots of dead code.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't know, probably not; e.g., gcc just throws it all (essentially) verbatim into the final output.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally agree with that, but it's a bit out of scope of this RFC. Or should I add it here as well?
That's the problem of top-level asm!. I'm not sure what is the scope of the statement — is it the translation unit itself? What section is it going to end up in, if rust switches to "-ffunction-sections"?
Re-using the function syntax provides answers for all these questions.