]>
Commit | Line | Data |
---|---|---|
8bb4bdeb | 1 | # `lang_items` |
92a42be0 | 2 | |
8bb4bdeb | 3 | The tracking issue for this feature is: None. |
92a42be0 | 4 | |
8bb4bdeb | 5 | ------------------------ |
92a42be0 | 6 | |
8bb4bdeb XL |
7 | The `rustc` compiler has certain pluggable operations, that is, |
8 | functionality that isn't hard-coded into the language, but is | |
9 | implemented in libraries, with a special marker to tell the compiler | |
10 | it exists. The marker is the attribute `#[lang = "..."]` and there are | |
11 | various different values of `...`, i.e. various different 'lang | |
12 | items'. | |
13 | ||
14 | For example, `Box` pointers require two lang items, one for allocation | |
15 | and one for deallocation. A freestanding program that uses the `Box` | |
16 | sugar for dynamic allocations via `malloc` and `free`: | |
17 | ||
18 | ```rust,ignore | |
19 | #![feature(lang_items, box_syntax, start, libc, core_intrinsics)] | |
20 | #![no_std] | |
21 | use core::intrinsics; | |
94b46f34 | 22 | use core::panic::PanicInfo; |
8bb4bdeb XL |
23 | |
24 | extern crate libc; | |
25 | ||
26 | #[lang = "owned_box"] | |
27 | pub struct Box<T>(*mut T); | |
28 | ||
29 | #[lang = "exchange_malloc"] | |
30 | unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { | |
31 | let p = libc::malloc(size as libc::size_t) as *mut u8; | |
32 | ||
33 | // Check if `malloc` failed: | |
34 | if p as usize == 0 { | |
35 | intrinsics::abort(); | |
36 | } | |
37 | ||
38 | p | |
39 | } | |
40 | ||
8bb4bdeb XL |
41 | #[lang = "box_free"] |
42 | unsafe fn box_free<T: ?Sized>(ptr: *mut T) { | |
2c00a5a8 | 43 | libc::free(ptr as *mut libc::c_void) |
8bb4bdeb XL |
44 | } |
45 | ||
46 | #[start] | |
2c00a5a8 XL |
47 | fn main(_argc: isize, _argv: *const *const u8) -> isize { |
48 | let _x = box 1; | |
8bb4bdeb XL |
49 | |
50 | 0 | |
51 | } | |
52 | ||
53 | #[lang = "eh_personality"] extern fn rust_eh_personality() {} | |
94b46f34 | 54 | #[lang = "panic_impl"] extern fn rust_begin_panic(info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } } |
2c00a5a8 XL |
55 | #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {} |
56 | #[no_mangle] pub extern fn rust_eh_register_frames () {} | |
57 | #[no_mangle] pub extern fn rust_eh_unregister_frames () {} | |
8bb4bdeb XL |
58 | ``` |
59 | ||
60 | Note the use of `abort`: the `exchange_malloc` lang item is assumed to | |
61 | return a valid pointer, and so needs to do the check internally. | |
62 | ||
63 | Other features provided by lang items include: | |
64 | ||
65 | - overloadable operators via traits: the traits corresponding to the | |
66 | `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all | |
67 | marked with lang items; those specific four are `eq`, `ord`, | |
68 | `deref`, and `add` respectively. | |
69 | - stack unwinding and general failure; the `eh_personality`, | |
70 | `eh_unwind_resume`, `fail` and `fail_bounds_checks` lang items. | |
71 | - the traits in `std::marker` used to indicate types of | |
72 | various kinds; lang items `send`, `sync` and `copy`. | |
73 | - the marker types and variance indicators found in | |
74 | `std::marker`; lang items `covariant_type`, | |
75 | `contravariant_lifetime`, etc. | |
76 | ||
77 | Lang items are loaded lazily by the compiler; e.g. if one never uses | |
78 | `Box` then there is no need to define functions for `exchange_malloc` | |
2c00a5a8 | 79 | and `box_free`. `rustc` will emit an error when an item is needed |
8bb4bdeb XL |
80 | but not found in the current crate or any that it depends on. |
81 | ||
82 | Most lang items are defined by `libcore`, but if you're trying to build | |
83 | an executable without the standard library, you'll run into the need | |
84 | for lang items. The rest of this page focuses on this use-case, even though | |
85 | lang items are a bit broader than that. | |
3157f602 XL |
86 | |
87 | ### Using libc | |
88 | ||
8bb4bdeb XL |
89 | In order to build a `#[no_std]` executable we will need libc as a dependency. |
90 | We can specify this using our `Cargo.toml` file: | |
3157f602 XL |
91 | |
92 | ```toml | |
93 | [dependencies] | |
5bcae85e | 94 | libc = { version = "0.2.14", default-features = false } |
3157f602 XL |
95 | ``` |
96 | ||
97 | Note that the default features have been disabled. This is a critical step - | |
98 | **the default features of libc include the standard library and so must be | |
99 | disabled.** | |
100 | ||
101 | ### Writing an executable without stdlib | |
102 | ||
103 | Controlling the entry point is possible in two ways: the `#[start]` attribute, | |
104 | or overriding the default shim for the C `main` function with your own. | |
92a42be0 SL |
105 | |
106 | The function marked `#[start]` is passed the command line parameters | |
107 | in the same format as C: | |
108 | ||
5bcae85e | 109 | ```rust,ignore |
32a655c1 | 110 | #![feature(lang_items, core_intrinsics)] |
92a42be0 SL |
111 | #![feature(start)] |
112 | #![no_std] | |
32a655c1 | 113 | use core::intrinsics; |
94b46f34 | 114 | use core::panic::PanicInfo; |
92a42be0 | 115 | |
476ff2be | 116 | // Pull in the system libc library for what crt0.o likely requires. |
92a42be0 SL |
117 | extern crate libc; |
118 | ||
476ff2be | 119 | // Entry point for this program. |
92a42be0 SL |
120 | #[start] |
121 | fn start(_argc: isize, _argv: *const *const u8) -> isize { | |
122 | 0 | |
123 | } | |
124 | ||
5bcae85e | 125 | // These functions are used by the compiler, but not |
92a42be0 SL |
126 | // for a bare-bones hello world. These are normally |
127 | // provided by libstd. | |
5bcae85e SL |
128 | #[lang = "eh_personality"] |
129 | #[no_mangle] | |
9e0c209e SL |
130 | pub extern fn rust_eh_personality() { |
131 | } | |
132 | ||
133 | // This function may be needed based on the compilation target. | |
134 | #[lang = "eh_unwind_resume"] | |
135 | #[no_mangle] | |
136 | pub extern fn rust_eh_unwind_resume() { | |
5bcae85e SL |
137 | } |
138 | ||
94b46f34 | 139 | #[lang = "panic_impl"] |
5bcae85e | 140 | #[no_mangle] |
94b46f34 | 141 | pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { |
32a655c1 | 142 | unsafe { intrinsics::abort() } |
5bcae85e | 143 | } |
92a42be0 SL |
144 | ``` |
145 | ||
146 | To override the compiler-inserted `main` shim, one has to disable it | |
147 | with `#![no_main]` and then create the appropriate symbol with the | |
148 | correct ABI and the correct name, which requires overriding the | |
149 | compiler's name mangling too: | |
150 | ||
5bcae85e | 151 | ```rust,ignore |
32a655c1 | 152 | #![feature(lang_items, core_intrinsics)] |
92a42be0 SL |
153 | #![feature(start)] |
154 | #![no_std] | |
155 | #![no_main] | |
32a655c1 | 156 | use core::intrinsics; |
94b46f34 | 157 | use core::panic::PanicInfo; |
92a42be0 | 158 | |
476ff2be | 159 | // Pull in the system libc library for what crt0.o likely requires. |
92a42be0 SL |
160 | extern crate libc; |
161 | ||
476ff2be | 162 | // Entry point for this program. |
92a42be0 | 163 | #[no_mangle] // ensure that this symbol is called `main` in the output |
5bcae85e | 164 | pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 { |
92a42be0 SL |
165 | 0 |
166 | } | |
167 | ||
9e0c209e | 168 | // These functions are used by the compiler, but not |
5bcae85e SL |
169 | // for a bare-bones hello world. These are normally |
170 | // provided by libstd. | |
171 | #[lang = "eh_personality"] | |
172 | #[no_mangle] | |
9e0c209e SL |
173 | pub extern fn rust_eh_personality() { |
174 | } | |
175 | ||
176 | // This function may be needed based on the compilation target. | |
177 | #[lang = "eh_unwind_resume"] | |
178 | #[no_mangle] | |
179 | pub extern fn rust_eh_unwind_resume() { | |
5bcae85e SL |
180 | } |
181 | ||
94b46f34 | 182 | #[lang = "panic_impl"] |
5bcae85e | 183 | #[no_mangle] |
94b46f34 | 184 | pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { |
32a655c1 | 185 | unsafe { intrinsics::abort() } |
5bcae85e | 186 | } |
92a42be0 SL |
187 | ``` |
188 | ||
3b2f2976 XL |
189 | In many cases, you may need to manually link to the `compiler_builtins` crate |
190 | when building a `no_std` binary. You may observe this via linker error messages | |
191 | such as "```undefined reference to `__rust_probestack'```". Using this crate | |
192 | also requires enabling the library feature `compiler_builtins_lib`. You can read | |
193 | more about this [here][compiler-builtins-lib]. | |
194 | ||
195 | [compiler-builtins-lib]: library-features/compiler-builtins-lib.html | |
196 | ||
9e0c209e | 197 | ## More about the language items |
5bcae85e SL |
198 | |
199 | The compiler currently makes a few assumptions about symbols which are | |
200 | available in the executable to call. Normally these functions are provided by | |
201 | the standard library, but without it you must define your own. These symbols | |
202 | are called "language items", and they each have an internal name, and then a | |
203 | signature that an implementation must conform to. | |
92a42be0 | 204 | |
9e0c209e | 205 | The first of these functions, `rust_eh_personality`, is used by the failure |
7453a54e SL |
206 | mechanisms of the compiler. This is often mapped to GCC's personality function |
207 | (see the [libstd implementation][unwind] for more information), but crates | |
208 | which do not trigger a panic can be assured that this function is never | |
9e0c209e SL |
209 | called. The language item's name is `eh_personality`. |
210 | ||
3157f602 | 211 | [unwind]: https://github.com/rust-lang/rust/blob/master/src/libpanic_unwind/gcc.rs |
5bcae85e | 212 | |
9e0c209e | 213 | The second function, `rust_begin_panic`, is also used by the failure mechanisms of the |
5bcae85e | 214 | compiler. When a panic happens, this controls the message that's displayed on |
94b46f34 | 215 | the screen. While the language item's name is `panic_impl`, the symbol name is |
5bcae85e | 216 | `rust_begin_panic`. |
9e0c209e SL |
217 | |
218 | A third function, `rust_eh_unwind_resume`, is also needed if the `custom_unwind_resume` | |
219 | flag is set in the options of the compilation target. It allows customizing the | |
220 | process of resuming unwind at the end of the landing pads. The language item's name | |
221 | is `eh_unwind_resume`. | |
abe05a73 XL |
222 | |
223 | ## List of all language items | |
224 | ||
225 | This is a list of all language items in Rust along with where they are located in | |
226 | the source code. | |
227 | ||
228 | - Primitives | |
229 | - `i8`: `libcore/num/mod.rs` | |
230 | - `i16`: `libcore/num/mod.rs` | |
231 | - `i32`: `libcore/num/mod.rs` | |
232 | - `i64`: `libcore/num/mod.rs` | |
233 | - `i128`: `libcore/num/mod.rs` | |
234 | - `isize`: `libcore/num/mod.rs` | |
235 | - `u8`: `libcore/num/mod.rs` | |
236 | - `u16`: `libcore/num/mod.rs` | |
237 | - `u32`: `libcore/num/mod.rs` | |
238 | - `u64`: `libcore/num/mod.rs` | |
239 | - `u128`: `libcore/num/mod.rs` | |
240 | - `usize`: `libcore/num/mod.rs` | |
241 | - `f32`: `libstd/f32.rs` | |
242 | - `f64`: `libstd/f64.rs` | |
83c7162d | 243 | - `char`: `libcore/char.rs` |
abe05a73 XL |
244 | - `slice`: `liballoc/slice.rs` |
245 | - `str`: `liballoc/str.rs` | |
246 | - `const_ptr`: `libcore/ptr.rs` | |
247 | - `mut_ptr`: `libcore/ptr.rs` | |
248 | - `unsafe_cell`: `libcore/cell.rs` | |
249 | - Runtime | |
250 | - `start`: `libstd/rt.rs` | |
251 | - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC) | |
252 | - `eh_personality`: `libpanic_unwind/seh64_gnu.rs` (SEH64 GNU) | |
253 | - `eh_personality`: `libpanic_unwind/seh.rs` (SEH) | |
254 | - `eh_unwind_resume`: `libpanic_unwind/seh64_gnu.rs` (SEH64 GNU) | |
255 | - `eh_unwind_resume`: `libpanic_unwind/gcc.rs` (GCC) | |
256 | - `msvc_try_filter`: `libpanic_unwind/seh.rs` (SEH) | |
257 | - `panic`: `libcore/panicking.rs` | |
258 | - `panic_bounds_check`: `libcore/panicking.rs` | |
94b46f34 XL |
259 | - `panic_impl`: `libcore/panicking.rs` |
260 | - `panic_impl`: `libstd/panicking.rs` | |
abe05a73 XL |
261 | - Allocations |
262 | - `owned_box`: `liballoc/boxed.rs` | |
263 | - `exchange_malloc`: `liballoc/heap.rs` | |
264 | - `box_free`: `liballoc/heap.rs` | |
265 | - Operands | |
266 | - `not`: `libcore/ops/bit.rs` | |
267 | - `bitand`: `libcore/ops/bit.rs` | |
268 | - `bitor`: `libcore/ops/bit.rs` | |
269 | - `bitxor`: `libcore/ops/bit.rs` | |
270 | - `shl`: `libcore/ops/bit.rs` | |
271 | - `shr`: `libcore/ops/bit.rs` | |
272 | - `bitand_assign`: `libcore/ops/bit.rs` | |
273 | - `bitor_assign`: `libcore/ops/bit.rs` | |
274 | - `bitxor_assign`: `libcore/ops/bit.rs` | |
275 | - `shl_assign`: `libcore/ops/bit.rs` | |
276 | - `shr_assign`: `libcore/ops/bit.rs` | |
277 | - `deref`: `libcore/ops/deref.rs` | |
278 | - `deref_mut`: `libcore/ops/deref.rs` | |
279 | - `index`: `libcore/ops/index.rs` | |
280 | - `index_mut`: `libcore/ops/index.rs` | |
281 | - `add`: `libcore/ops/arith.rs` | |
282 | - `sub`: `libcore/ops/arith.rs` | |
283 | - `mul`: `libcore/ops/arith.rs` | |
284 | - `div`: `libcore/ops/arith.rs` | |
285 | - `rem`: `libcore/ops/arith.rs` | |
286 | - `neg`: `libcore/ops/arith.rs` | |
287 | - `add_assign`: `libcore/ops/arith.rs` | |
288 | - `sub_assign`: `libcore/ops/arith.rs` | |
289 | - `mul_assign`: `libcore/ops/arith.rs` | |
290 | - `div_assign`: `libcore/ops/arith.rs` | |
291 | - `rem_assign`: `libcore/ops/arith.rs` | |
292 | - `eq`: `libcore/cmp.rs` | |
293 | - `ord`: `libcore/cmp.rs` | |
294 | - Functions | |
295 | - `fn`: `libcore/ops/function.rs` | |
296 | - `fn_mut`: `libcore/ops/function.rs` | |
297 | - `fn_once`: `libcore/ops/function.rs` | |
298 | - `generator_state`: `libcore/ops/generator.rs` | |
299 | - `generator`: `libcore/ops/generator.rs` | |
300 | - Other | |
301 | - `coerce_unsized`: `libcore/ops/unsize.rs` | |
302 | - `drop`: `libcore/ops/drop.rs` | |
303 | - `drop_in_place`: `libcore/ptr.rs` | |
304 | - `clone`: `libcore/clone.rs` | |
305 | - `copy`: `libcore/marker.rs` | |
306 | - `send`: `libcore/marker.rs` | |
307 | - `sized`: `libcore/marker.rs` | |
308 | - `unsize`: `libcore/marker.rs` | |
309 | - `sync`: `libcore/marker.rs` | |
310 | - `phantom_data`: `libcore/marker.rs` | |
311 | - `freeze`: `libcore/marker.rs` | |
312 | - `debug_trait`: `libcore/fmt/mod.rs` | |
2c00a5a8 | 313 | - `non_zero`: `libcore/nonzero.rs` |