Skip to content

Commit 1cc857f

Browse files
committed
Update naked fns for later discussion.
1 parent f54d26e commit 1cc857f

File tree

1 file changed

+61
-29
lines changed

1 file changed

+61
-29
lines changed

text/0000-naked-fns.md

Lines changed: 61 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -87,17 +87,14 @@ any calling convention the compiler is compatible with, calls to naked functions
8787
from within Rust code are forbidden unless the function is also declared with
8888
a well-defined ABI.
8989

90-
The function `call_foo` in the following code block is an error because the
91-
default (Rust) ABI is unspecified and as such a programmer can never write code
92-
in `foo` which is compatible:
90+
Defining a naked function with the default (Rust) ABI is an error, because the
91+
Rust ABI is unspecified and the programmer can never write a function which is
92+
guaranteed to be compatible. For example, The function declaration of `foo` in
93+
the following code block is an error.
9394

9495
```rust
9596
#[naked]
96-
fn foo() { }
97-
98-
fn call_foo() {
99-
foo();
100-
}
97+
unsafe fn foo() { }
10198
```
10299

103100
The following variant is not an error because the C calling convention is
@@ -107,28 +104,36 @@ function:
107104
```rust
108105
#[naked]
109106
extern "C" fn foo() { }
110-
111-
fn call_foo() {
112-
foo();
113-
}
114107
```
115108

116109
---
117110

118-
The current support for `extern` functions in `rustc` generates a minimum of two
119-
basic blocks for any function declared in Rust code with a non-default calling
120-
convention: a trampoline which translates the declared calling convention to the
121-
Rust convention, and a Rust ABI version of the function containing the actual
122-
implementation. Calls to the function from Rust code call the Rust ABI version
123-
directly.
111+
Because the compiler cannot verify the correctness of code written in a naked
112+
function (since it may have an unknown calling convention), naked functions must
113+
be declared `unsafe` or contain no non-`unsafe` statements in the body. The
114+
function `error` in the following code block is a compile-time error, whereas
115+
the functions `correct1` and `correct2` are permitted.
124116

125-
For naked functions, it is impossible for the compiler to generate a Rust ABI
126-
version of the function because the implementation may depend on the calling
127-
convention. In cases where calling a naked function from Rust is permitted, the
128-
compiler must be able to use the target calling convention directly rather than
129-
call the same function with the Rust convention.
117+
```
118+
#[naked]
119+
extern "C" fn error(x: &mut u8) {
120+
*x += 1;
121+
}
130122
131-
---
123+
#[naked]
124+
unsafe extern "C" fn correct1(x: &mut u8) {
125+
*x += 1;
126+
}
127+
128+
#[naked]
129+
extern "C" fn correct2() {
130+
unsafe {
131+
*x += 1;
132+
}
133+
}
134+
```
135+
136+
## Example
132137

133138
The following example illustrates the possible use of a naked function for
134139
implementation of an interrupt service routine on 32-bit x86.
@@ -162,6 +167,21 @@ fn main() {
162167
}
163168
```
164169

170+
## Implementation Considerations
171+
172+
The current support for `extern` functions in `rustc` generates a minimum of two
173+
basic blocks for any function declared in Rust code with a non-default calling
174+
convention: a trampoline which translates the declared calling convention to the
175+
Rust convention, and a Rust ABI version of the function containing the actual
176+
implementation. Calls to the function from Rust code call the Rust ABI version
177+
directly.
178+
179+
For naked functions, it is impossible for the compiler to generate a Rust ABI
180+
version of the function because the implementation may depend on the calling
181+
convention. In cases where calling a naked function from Rust is permitted, the
182+
compiler must be able to use the target calling convention directly rather than
183+
call the same function with the Rust convention.
184+
165185
# Drawbacks
166186

167187
The utility of this feature is extremely limited to most users, and it might be
@@ -179,8 +199,20 @@ external libraries such as `libffi`.
179199

180200
It is easy to quietly generate wrong code in naked functions, such as by causing
181201
the compiler to allocate stack space for temporaries where none were
182-
anticipated. It may be desirable to require that all statements inside naked
183-
functions be inside `unsafe` blocks (either by declaring the function `unsafe`
184-
or including `unsafe { }` in the function body) to reinforce the need for
185-
extreme care in the use of this feature. Requiring that the function always be
186-
marked `unsafe` is not desirable because its external API may be safe.
202+
anticipated. There is currently no restriction on writing Rust statements inside
203+
a naked function, while most compilers supporting similar features either
204+
require or strongly recommend that authors write only inline assembly inside
205+
naked functions to ensure no code is generated that assumes a particular stack
206+
layout. It may be desirable to place further restrictions on what statements are
207+
permitted in the body of a naked function, such as permitting only `asm!`
208+
statements.
209+
210+
The `unsafe` requirement on naked functions may not be desirable in all cases.
211+
However, relaxing that requirement in the future would not be a breaking change.
212+
213+
Because a naked function may use a calling convention unknown to the compiler,
214+
it may be useful to add a "unknown" calling convention to the compiler which is
215+
illegal to call directly. Absent this feature, functions implementing an unknown
216+
ABI would need to be declared with a calling convention which is known to be
217+
incorrect and depend on the programmer to avoid calling such a function
218+
incorrectly since it cannot be prevented statically.

0 commit comments

Comments
 (0)