@@ -87,17 +87,14 @@ any calling convention the compiler is compatible with, calls to naked functions
87
87
from within Rust code are forbidden unless the function is also declared with
88
88
a well-defined ABI.
89
89
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.
93
94
94
95
``` rust
95
96
#[naked]
96
- fn foo () { }
97
-
98
- fn call_foo () {
99
- foo ();
100
- }
97
+ unsafe fn foo () { }
101
98
```
102
99
103
100
The following variant is not an error because the C calling convention is
@@ -107,28 +104,36 @@ function:
107
104
``` rust
108
105
#[naked]
109
106
extern " C" fn foo () { }
110
-
111
- fn call_foo () {
112
- foo ();
113
- }
114
107
```
115
108
116
109
---
117
110
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.
124
116
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
+ }
130
122
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
132
137
133
138
The following example illustrates the possible use of a naked function for
134
139
implementation of an interrupt service routine on 32-bit x86.
@@ -162,6 +167,21 @@ fn main() {
162
167
}
163
168
```
164
169
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
+
165
185
# Drawbacks
166
186
167
187
The utility of this feature is extremely limited to most users, and it might be
@@ -179,8 +199,20 @@ external libraries such as `libffi`.
179
199
180
200
It is easy to quietly generate wrong code in naked functions, such as by causing
181
201
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