From 395fc50832bf380951f7a710544e9b6569295c60 Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Tue, 1 Dec 2020 11:38:12 +0300 Subject: [PATCH 1/5] Document lang items --- src/SUMMARY.md | 1 + src/lang-items.md | 289 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 290 insertions(+) create mode 100644 src/lang-items.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index fbeedbe15..61918dfc8 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -80,6 +80,7 @@ - [Panic Implementation](./panic-implementation.md) - [AST Validation](./ast-validation.md) - [Feature Gate Checking](./feature-gate-ck.md) + - [Lang Items](./lang-items.md) - [The HIR (High-level IR)](./hir.md) - [Lowering AST to HIR](./lowering.md) - [Debugging](./hir-debugging.md) diff --git a/src/lang-items.md b/src/lang-items.md new file mode 100644 index 000000000..d5100c797 --- /dev/null +++ b/src/lang-items.md @@ -0,0 +1,289 @@ +# Lang items + + +The `rustc` compiler has certain pluggable operations, that is, +functionality that isn't hard-coded into the language, but is +implemented in libraries, with a special marker to tell the compiler +it exists. The marker is the attribute `#[lang = "..."]` and there are +various different values of `...`, i.e. various different 'lang +items'. + +For example, `Box` pointers require two lang items, one for allocation +and one for deallocation. A freestanding program that uses the `Box` +sugar for dynamic allocations via `malloc` and `free`: + +```rust,ignore +#![feature(lang_items, box_syntax, start, libc, core_intrinsics)] +#![no_std] +use core::intrinsics; +use core::panic::PanicInfo; + +extern crate libc; + +#[lang = "owned_box"] +pub struct Box(*mut T); + +#[lang = "exchange_malloc"] +unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { + let p = libc::malloc(size as libc::size_t) as *mut u8; + + // Check if `malloc` failed: + if p as usize == 0 { + intrinsics::abort(); + } + + p +} + +#[lang = "box_free"] +unsafe fn box_free(ptr: *mut T) { + libc::free(ptr as *mut libc::c_void) +} + +#[start] +fn main(_argc: isize, _argv: *const *const u8) -> isize { + let _x = box 1; + + 0 +} + +#[lang = "eh_personality"] extern fn rust_eh_personality() {} +#[lang = "panic_impl"] extern fn rust_begin_panic(info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } } +#[no_mangle] pub extern fn rust_eh_register_frames () {} +#[no_mangle] pub extern fn rust_eh_unregister_frames () {} +``` + +Note the use of `abort`: the `exchange_malloc` lang item is assumed to +return a valid pointer, and so needs to do the check internally. + +Other features provided by lang items include: + +- overloadable operators via traits: the traits corresponding to the + `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all + marked with lang items; those specific four are `eq`, `ord`, + `deref`, and `add` respectively. +- stack unwinding and general failure; the `eh_personality`, + `panic` and `panic_bounds_checks` lang items. +- the traits in `std::marker` used to indicate types of + various kinds; lang items `send`, `sync` and `copy`. +- the special marker types used for variance indicators found in + `core::marker`; lang item `phantom_data`. + +Lang items are loaded lazily by the compiler; e.g. if one never uses +`Box` then there is no need to define functions for `exchange_malloc` +and `box_free`. `rustc` will emit an error when an item is needed +but not found in the current crate or any that it depends on. + +Most lang items are defined by `libcore`, but if you're trying to build +an executable without the standard library, you'll run into the need +for lang items. The rest of this page focuses on this use-case, even though +lang items are a bit broader than that. + +### Using libc + +In order to build a `#[no_std]` executable we will need libc as a dependency. +We can specify this using our `Cargo.toml` file: + +```toml +[dependencies] +libc = { version = "0.2.14", default-features = false } +``` + +Note that the default features have been disabled. This is a critical step - +**the default features of libc include the standard library and so must be +disabled.** + +### Writing an executable without stdlib + +Controlling the entry point is possible in two ways: the `#[start]` attribute, +or overriding the default shim for the C `main` function with your own. + +The function marked `#[start]` is passed the command line parameters +in the same format as C: + +```rust,ignore +#![feature(lang_items, core_intrinsics)] +#![feature(start)] +#![no_std] +use core::intrinsics; +use core::panic::PanicInfo; + +// Pull in the system libc library for what crt0.o likely requires. +extern crate libc; + +// Entry point for this program. +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} + +// These functions are used by the compiler, but not +// for a bare-bones hello world. These are normally +// provided by libstd. +#[lang = "eh_personality"] +#[no_mangle] +pub extern fn rust_eh_personality() { +} + +#[lang = "panic_impl"] +#[no_mangle] +pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { + unsafe { intrinsics::abort() } +} +``` + +To override the compiler-inserted `main` shim, one has to disable it +with `#![no_main]` and then create the appropriate symbol with the +correct ABI and the correct name, which requires overriding the +compiler's name mangling too: + +```rust,ignore +#![feature(lang_items, core_intrinsics)] +#![feature(start)] +#![no_std] +#![no_main] +use core::intrinsics; +use core::panic::PanicInfo; + +// Pull in the system libc library for what crt0.o likely requires. +extern crate libc; + +// Entry point for this program. +#[no_mangle] // ensure that this symbol is called `main` in the output +pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 { + 0 +} + +// These functions are used by the compiler, but not +// for a bare-bones hello world. These are normally +// provided by libstd. +#[lang = "eh_personality"] +#[no_mangle] +pub extern fn rust_eh_personality() { +} + +#[lang = "panic_impl"] +#[no_mangle] +pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { + unsafe { intrinsics::abort() } +} +``` + +In many cases, you may need to manually link to the `compiler_builtins` crate +when building a `no_std` binary. You may observe this via linker error messages +such as "```undefined reference to `__rust_probestack'```". + +## More about the language items + +The compiler currently makes a few assumptions about symbols which are +available in the executable to call. Normally these functions are provided by +the standard library, but without it you must define your own. These symbols +are called "language items", and they each have an internal name, and then a +signature that an implementation must conform to. + +The first of these functions, `rust_eh_personality`, is used by the failure +mechanisms of the compiler. This is often mapped to GCC's personality function +(see the [libstd implementation][unwind] for more information), but crates +which do not trigger a panic can be assured that this function is never +called. The language item's name is `eh_personality`. + +[unwind]: https://github.com/rust-lang/rust/blob/master/src/libpanic_unwind/gcc.rs + +The second function, `rust_begin_panic`, is also used by the failure mechanisms of the +compiler. When a panic happens, this controls the message that's displayed on +the screen. While the language item's name is `panic_impl`, the symbol name is +`rust_begin_panic`. + +Finally, a `eh_catch_typeinfo` static is needed for certain targets which +implement Rust panics on top of C++ exceptions. + +## List of all language items + +This is a list of all language items in Rust along with where they are located in +the source code. + +- Primitives + - `i8`: `libcore/num/mod.rs` + - `i16`: `libcore/num/mod.rs` + - `i32`: `libcore/num/mod.rs` + - `i64`: `libcore/num/mod.rs` + - `i128`: `libcore/num/mod.rs` + - `isize`: `libcore/num/mod.rs` + - `u8`: `libcore/num/mod.rs` + - `u16`: `libcore/num/mod.rs` + - `u32`: `libcore/num/mod.rs` + - `u64`: `libcore/num/mod.rs` + - `u128`: `libcore/num/mod.rs` + - `usize`: `libcore/num/mod.rs` + - `f32`: `libstd/f32.rs` + - `f64`: `libstd/f64.rs` + - `char`: `libcore/char.rs` + - `slice`: `liballoc/slice.rs` + - `str`: `liballoc/str.rs` + - `const_ptr`: `libcore/ptr.rs` + - `mut_ptr`: `libcore/ptr.rs` +- Runtime + - `start`: `libstd/rt.rs` + - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC) + - `eh_personality`: `libpanic_unwind/gcc.rs` (GNU) + - `eh_personality`: `libpanic_unwind/seh.rs` (SEH) + - `eh_catch_typeinfo`: `libpanic_unwind/emcc.rs` (EMCC) + - `panic`: `libcore/panicking.rs` + - `panic_bounds_check`: `libcore/panicking.rs` + - `panic_impl`: `libcore/panicking.rs` + - `panic_impl`: `libstd/panicking.rs` +- Allocations + - `owned_box`: `liballoc/boxed.rs` + - `exchange_malloc`: `liballoc/heap.rs` + - `box_free`: `liballoc/heap.rs` +- Operands + - `not`: `libcore/ops/bit.rs` + - `bitand`: `libcore/ops/bit.rs` + - `bitor`: `libcore/ops/bit.rs` + - `bitxor`: `libcore/ops/bit.rs` + - `shl`: `libcore/ops/bit.rs` + - `shr`: `libcore/ops/bit.rs` + - `bitand_assign`: `libcore/ops/bit.rs` + - `bitor_assign`: `libcore/ops/bit.rs` + - `bitxor_assign`: `libcore/ops/bit.rs` + - `shl_assign`: `libcore/ops/bit.rs` + - `shr_assign`: `libcore/ops/bit.rs` + - `deref`: `libcore/ops/deref.rs` + - `deref_mut`: `libcore/ops/deref.rs` + - `index`: `libcore/ops/index.rs` + - `index_mut`: `libcore/ops/index.rs` + - `add`: `libcore/ops/arith.rs` + - `sub`: `libcore/ops/arith.rs` + - `mul`: `libcore/ops/arith.rs` + - `div`: `libcore/ops/arith.rs` + - `rem`: `libcore/ops/arith.rs` + - `neg`: `libcore/ops/arith.rs` + - `add_assign`: `libcore/ops/arith.rs` + - `sub_assign`: `libcore/ops/arith.rs` + - `mul_assign`: `libcore/ops/arith.rs` + - `div_assign`: `libcore/ops/arith.rs` + - `rem_assign`: `libcore/ops/arith.rs` + - `eq`: `libcore/cmp.rs` + - `ord`: `libcore/cmp.rs` +- Functions + - `fn`: `libcore/ops/function.rs` + - `fn_mut`: `libcore/ops/function.rs` + - `fn_once`: `libcore/ops/function.rs` + - `generator_state`: `libcore/ops/generator.rs` + - `generator`: `libcore/ops/generator.rs` +- Opting out + - `unsafe_cell` (relaxes pointer provenance rules, allowing const-to-mut casts): `libcore/cell.rs` + - `manually_drop` (opts out of implicit destructor call): `libcore/mem/manually_drop.rs` +- Other + - `coerce_unsized`: `libcore/ops/unsize.rs` + - `drop`: `libcore/ops/drop.rs` + - `drop_in_place`: `libcore/ptr.rs` + - `clone`: `libcore/clone.rs` + - `copy`: `libcore/marker.rs` + - `send`: `libcore/marker.rs` + - `sized`: `libcore/marker.rs` + - `unsize`: `libcore/marker.rs` + - `sync`: `libcore/marker.rs` + - `phantom_data`: `libcore/marker.rs` + - `discriminant_kind`: `libcore/marker.rs` + - `freeze`: `libcore/marker.rs` From 603b08857ce41a17bf5b463289dcc79f0ff63f4c Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Sun, 6 Dec 2020 22:05:04 +0300 Subject: [PATCH 2/5] Update docs a bit --- src/lang-items.md | 62 ++++++++++++----------------------------------- 1 file changed, 16 insertions(+), 46 deletions(-) diff --git a/src/lang-items.md b/src/lang-items.md index d5100c797..e9e89c1b8 100644 --- a/src/lang-items.md +++ b/src/lang-items.md @@ -8,55 +8,17 @@ it exists. The marker is the attribute `#[lang = "..."]` and there are various different values of `...`, i.e. various different 'lang items'. -For example, `Box` pointers require two lang items, one for allocation -and one for deallocation. A freestanding program that uses the `Box` -sugar for dynamic allocations via `malloc` and `free`: +Many such lang items can be implemented only in one sensible way, such as +`add` (`trait core::ops::Add`) or `future_trait` +(`trait core::future::Future`). -```rust,ignore -#![feature(lang_items, box_syntax, start, libc, core_intrinsics)] -#![no_std] -use core::intrinsics; -use core::panic::PanicInfo; - -extern crate libc; - -#[lang = "owned_box"] -pub struct Box(*mut T); - -#[lang = "exchange_malloc"] -unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { - let p = libc::malloc(size as libc::size_t) as *mut u8; - - // Check if `malloc` failed: - if p as usize == 0 { - intrinsics::abort(); - } - - p -} +Others can be overriden to achieve some +specific goals. -#[lang = "box_free"] -unsafe fn box_free(ptr: *mut T) { - libc::free(ptr as *mut libc::c_void) -} - -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { - let _x = box 1; +For example, later sections describe how to control +your binary startup or override panic implementation. - 0 -} - -#[lang = "eh_personality"] extern fn rust_eh_personality() {} -#[lang = "panic_impl"] extern fn rust_begin_panic(info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } } -#[no_mangle] pub extern fn rust_eh_register_frames () {} -#[no_mangle] pub extern fn rust_eh_unregister_frames () {} -``` - -Note the use of `abort`: the `exchange_malloc` lang item is assumed to -return a valid pointer, and so needs to do the check internally. - -Other features provided by lang items include: +Features provided by lang items include: - overloadable operators via traits: the traits corresponding to the `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all @@ -197,6 +159,14 @@ the screen. While the language item's name is `panic_impl`, the symbol name is Finally, a `eh_catch_typeinfo` static is needed for certain targets which implement Rust panics on top of C++ exceptions. +## Well-known paths + +In several cases compiler finds specific item not by `lang` attribute. Instead +item path is hardcored. For example compiler assumes `Iterator` trait to be +available as `core::iter::Iterator`. This only happens when item is required +on early compilation stages (for example `Iterator` is used in for loops +desugaring). + ## List of all language items This is a list of all language items in Rust along with where they are located in From 5235869a0911c19c4b4a9eaaa57ca65c64767f8c Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Sun, 6 Dec 2020 22:31:59 +0300 Subject: [PATCH 3/5] Update paths --- src/lang-items.md | 154 +++++++++++++++++++++++----------------------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/src/lang-items.md b/src/lang-items.md index e9e89c1b8..a3bca2a6e 100644 --- a/src/lang-items.md +++ b/src/lang-items.md @@ -173,87 +173,87 @@ This is a list of all language items in Rust along with where they are located i the source code. - Primitives - - `i8`: `libcore/num/mod.rs` - - `i16`: `libcore/num/mod.rs` - - `i32`: `libcore/num/mod.rs` - - `i64`: `libcore/num/mod.rs` - - `i128`: `libcore/num/mod.rs` - - `isize`: `libcore/num/mod.rs` - - `u8`: `libcore/num/mod.rs` - - `u16`: `libcore/num/mod.rs` - - `u32`: `libcore/num/mod.rs` - - `u64`: `libcore/num/mod.rs` - - `u128`: `libcore/num/mod.rs` - - `usize`: `libcore/num/mod.rs` - - `f32`: `libstd/f32.rs` - - `f64`: `libstd/f64.rs` - - `char`: `libcore/char.rs` - - `slice`: `liballoc/slice.rs` - - `str`: `liballoc/str.rs` - - `const_ptr`: `libcore/ptr.rs` - - `mut_ptr`: `libcore/ptr.rs` + - `i8`: `library/core/src/num/mod.rs` + - `i16`: `library/core/src/num/mod.rs` + - `i32`: `library/core/src/num/mod.rs` + - `i64`: `library/core/src/num/mod.rs` + - `i128`: `library/core/src/num/mod.rs` + - `isize`: `library/core/src/num/mod.rs` + - `u8`: `library/core/src/num/mod.rs` + - `u16`: `library/core/src/num/mod.rs` + - `u32`: `library/core/src/num/mod.rs` + - `u64`: `library/core/src/num/mod.rs` + - `u128`: `library/core/src/num/mod.rs` + - `usize`: `library/core/src/num/mod.rs` + - `f32`: `library/std/src/f32.rs` + - `f64`: `library/std/src/f64.rs` + - `char`: `library/core/src/char.rs` + - `slice`: `library/alloc/src/slice.rs` + - `str`: `library/alloc/src/str.rs` + - `const_ptr`: `library/core/src/ptr.rs` + - `mut_ptr`: `library/core/src/ptr.rs` - Runtime - - `start`: `libstd/rt.rs` - - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC) - - `eh_personality`: `libpanic_unwind/gcc.rs` (GNU) - - `eh_personality`: `libpanic_unwind/seh.rs` (SEH) - - `eh_catch_typeinfo`: `libpanic_unwind/emcc.rs` (EMCC) - - `panic`: `libcore/panicking.rs` - - `panic_bounds_check`: `libcore/panicking.rs` - - `panic_impl`: `libcore/panicking.rs` - - `panic_impl`: `libstd/panicking.rs` + - `start`: `library/std/src/rt.rs` + - `eh_personality`: `library/panic_unwind/src/emcc.rs` (EMCC) + - `eh_personality`: `library/panic_unwind/src/gcc.rs` (GNU) + - `eh_personality`: `library/panic_unwind/src/seh.rs` (SEH) + - `eh_catch_typeinfo`: `library/panic_unwind/src/emcc.rs` (EMCC) + - `panic`: `library/core/src/panicking.rs` + - `panic_bounds_check`: `library/core/src/panicking.rs` + - `panic_impl`: `library/core/src/panicking.rs` + - `panic_impl`: `library/std/src/panicking.rs` - Allocations - - `owned_box`: `liballoc/boxed.rs` - - `exchange_malloc`: `liballoc/heap.rs` - - `box_free`: `liballoc/heap.rs` + - `owned_box`: `library/alloc/src/boxed.rs` + - `exchange_malloc`: `library/alloc/src/heap.rs` + - `box_free`: `library/alloc/src/heap.rs` - Operands - - `not`: `libcore/ops/bit.rs` - - `bitand`: `libcore/ops/bit.rs` - - `bitor`: `libcore/ops/bit.rs` - - `bitxor`: `libcore/ops/bit.rs` - - `shl`: `libcore/ops/bit.rs` - - `shr`: `libcore/ops/bit.rs` - - `bitand_assign`: `libcore/ops/bit.rs` - - `bitor_assign`: `libcore/ops/bit.rs` - - `bitxor_assign`: `libcore/ops/bit.rs` - - `shl_assign`: `libcore/ops/bit.rs` - - `shr_assign`: `libcore/ops/bit.rs` - - `deref`: `libcore/ops/deref.rs` - - `deref_mut`: `libcore/ops/deref.rs` - - `index`: `libcore/ops/index.rs` - - `index_mut`: `libcore/ops/index.rs` - - `add`: `libcore/ops/arith.rs` - - `sub`: `libcore/ops/arith.rs` - - `mul`: `libcore/ops/arith.rs` - - `div`: `libcore/ops/arith.rs` - - `rem`: `libcore/ops/arith.rs` - - `neg`: `libcore/ops/arith.rs` - - `add_assign`: `libcore/ops/arith.rs` - - `sub_assign`: `libcore/ops/arith.rs` - - `mul_assign`: `libcore/ops/arith.rs` - - `div_assign`: `libcore/ops/arith.rs` - - `rem_assign`: `libcore/ops/arith.rs` - - `eq`: `libcore/cmp.rs` - - `ord`: `libcore/cmp.rs` + - `not`: `library/core/src/ops/bit.rs` + - `bitand`: `library/core/src/ops/bit.rs` + - `bitor`: `library/core/src/ops/bit.rs` + - `bitxor`: `library/core/src/ops/bit.rs` + - `shl`: `library/core/src/ops/bit.rs` + - `shr`: `library/core/src/ops/bit.rs` + - `bitand_assign`: `library/core/src/ops/bit.rs` + - `bitor_assign`: `library/core/src/ops/bit.rs` + - `bitxor_assign`: `library/core/src/ops/bit.rs` + - `shl_assign`: `library/core/src/ops/bit.rs` + - `shr_assign`: `library/core/src/ops/bit.rs` + - `deref`: `library/core/src/ops/deref.rs` + - `deref_mut`: `library/core/src/ops/deref.rs` + - `index`: `library/core/src/ops/index.rs` + - `index_mut`: `library/core/src/ops/index.rs` + - `add`: `library/core/src/ops/arith.rs` + - `sub`: `library/core/src/ops/arith.rs` + - `mul`: `library/core/src/ops/arith.rs` + - `div`: `library/core/src/ops/arith.rs` + - `rem`: `library/core/src/ops/arith.rs` + - `neg`: `library/core/src/ops/arith.rs` + - `add_assign`: `library/core/src/ops/arith.rs` + - `sub_assign`: `library/core/src/ops/arith.rs` + - `mul_assign`: `library/core/src/ops/arith.rs` + - `div_assign`: `library/core/src/ops/arith.rs` + - `rem_assign`: `library/core/src/ops/arith.rs` + - `eq`: `library/core/src/cmp.rs` + - `ord`: `library/core/src/cmp.rs` - Functions - - `fn`: `libcore/ops/function.rs` - - `fn_mut`: `libcore/ops/function.rs` - - `fn_once`: `libcore/ops/function.rs` - - `generator_state`: `libcore/ops/generator.rs` - - `generator`: `libcore/ops/generator.rs` + - `fn`: `library/core/src/ops/function.rs` + - `fn_mut`: `library/core/src/ops/function.rs` + - `fn_once`: `library/core/src/ops/function.rs` + - `generator_state`: `library/core/src/ops/generator.rs` + - `generator`: `library/core/src/ops/generator.rs` - Opting out - - `unsafe_cell` (relaxes pointer provenance rules, allowing const-to-mut casts): `libcore/cell.rs` - - `manually_drop` (opts out of implicit destructor call): `libcore/mem/manually_drop.rs` + - `unsafe_cell` (relaxes pointer provenance rules, allowing const-to-mut casts): `library/core/src/cell.rs` + - `manually_drop` (opts out of implicit destructor call): `library/core/src/mem/manually_drop.rs` - Other - - `coerce_unsized`: `libcore/ops/unsize.rs` - - `drop`: `libcore/ops/drop.rs` - - `drop_in_place`: `libcore/ptr.rs` - - `clone`: `libcore/clone.rs` - - `copy`: `libcore/marker.rs` - - `send`: `libcore/marker.rs` - - `sized`: `libcore/marker.rs` - - `unsize`: `libcore/marker.rs` - - `sync`: `libcore/marker.rs` + - `coerce_unsized`: `library/core/src/ops/unsize.rs` + - `drop`: `library/core/src/ops/drop.rs` + - `drop_in_place`: `library/core/src/ptr.rs` + - `clone`: `library/core/src/clone.rs` + - `copy`: `library/core/src/marker.rs` + - `send`: `library/core/src/marker.rs` + - `sized`: `libcrary/ore/msrc/arker.rs` + - `unsize`: `library/core/src/marker.rs` + - `sync`: `library/core/src/marker.rs` - `phantom_data`: `libcore/marker.rs` - - `discriminant_kind`: `libcore/marker.rs` - - `freeze`: `libcore/marker.rs` + - `discriminant_kind`: `library/core/src/marker.rs` + - `freeze`: `library/core/src/marker.rs` From dd8a2e1f39b64044d3a82ffce4d8d0d61a5db297 Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Tue, 13 Apr 2021 21:53:53 +0300 Subject: [PATCH 4/5] Remove all examples --- src/lang-items.md | 129 +--------------------------------------------- 1 file changed, 1 insertion(+), 128 deletions(-) diff --git a/src/lang-items.md b/src/lang-items.md index a3bca2a6e..617d689a5 100644 --- a/src/lang-items.md +++ b/src/lang-items.md @@ -38,134 +38,7 @@ but not found in the current crate or any that it depends on. Most lang items are defined by `libcore`, but if you're trying to build an executable without the standard library, you'll run into the need -for lang items. The rest of this page focuses on this use-case, even though -lang items are a bit broader than that. - -### Using libc - -In order to build a `#[no_std]` executable we will need libc as a dependency. -We can specify this using our `Cargo.toml` file: - -```toml -[dependencies] -libc = { version = "0.2.14", default-features = false } -``` - -Note that the default features have been disabled. This is a critical step - -**the default features of libc include the standard library and so must be -disabled.** - -### Writing an executable without stdlib - -Controlling the entry point is possible in two ways: the `#[start]` attribute, -or overriding the default shim for the C `main` function with your own. - -The function marked `#[start]` is passed the command line parameters -in the same format as C: - -```rust,ignore -#![feature(lang_items, core_intrinsics)] -#![feature(start)] -#![no_std] -use core::intrinsics; -use core::panic::PanicInfo; - -// Pull in the system libc library for what crt0.o likely requires. -extern crate libc; - -// Entry point for this program. -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { - 0 -} - -// These functions are used by the compiler, but not -// for a bare-bones hello world. These are normally -// provided by libstd. -#[lang = "eh_personality"] -#[no_mangle] -pub extern fn rust_eh_personality() { -} - -#[lang = "panic_impl"] -#[no_mangle] -pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { - unsafe { intrinsics::abort() } -} -``` - -To override the compiler-inserted `main` shim, one has to disable it -with `#![no_main]` and then create the appropriate symbol with the -correct ABI and the correct name, which requires overriding the -compiler's name mangling too: - -```rust,ignore -#![feature(lang_items, core_intrinsics)] -#![feature(start)] -#![no_std] -#![no_main] -use core::intrinsics; -use core::panic::PanicInfo; - -// Pull in the system libc library for what crt0.o likely requires. -extern crate libc; - -// Entry point for this program. -#[no_mangle] // ensure that this symbol is called `main` in the output -pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 { - 0 -} - -// These functions are used by the compiler, but not -// for a bare-bones hello world. These are normally -// provided by libstd. -#[lang = "eh_personality"] -#[no_mangle] -pub extern fn rust_eh_personality() { -} - -#[lang = "panic_impl"] -#[no_mangle] -pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { - unsafe { intrinsics::abort() } -} -``` - -In many cases, you may need to manually link to the `compiler_builtins` crate -when building a `no_std` binary. You may observe this via linker error messages -such as "```undefined reference to `__rust_probestack'```". - -## More about the language items - -The compiler currently makes a few assumptions about symbols which are -available in the executable to call. Normally these functions are provided by -the standard library, but without it you must define your own. These symbols -are called "language items", and they each have an internal name, and then a -signature that an implementation must conform to. - -The first of these functions, `rust_eh_personality`, is used by the failure -mechanisms of the compiler. This is often mapped to GCC's personality function -(see the [libstd implementation][unwind] for more information), but crates -which do not trigger a panic can be assured that this function is never -called. The language item's name is `eh_personality`. - -[unwind]: https://github.com/rust-lang/rust/blob/master/src/libpanic_unwind/gcc.rs - -The second function, `rust_begin_panic`, is also used by the failure mechanisms of the -compiler. When a panic happens, this controls the message that's displayed on -the screen. While the language item's name is `panic_impl`, the symbol name is -`rust_begin_panic`. - -Finally, a `eh_catch_typeinfo` static is needed for certain targets which -implement Rust panics on top of C++ exceptions. - -## Well-known paths - -In several cases compiler finds specific item not by `lang` attribute. Instead -item path is hardcored. For example compiler assumes `Iterator` trait to be -available as `core::iter::Iterator`. This only happens when item is required -on early compilation stages (for example `Iterator` is used in for loops -desugaring). +for lang items. ## List of all language items From 7002e1581917551779ed4c324fe01da71b6553ea Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Tue, 13 Apr 2021 22:00:36 +0300 Subject: [PATCH 5/5] Fix line length --- src/lang-items.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lang-items.md b/src/lang-items.md index 617d689a5..f6fc2f817 100644 --- a/src/lang-items.md +++ b/src/lang-items.md @@ -115,7 +115,8 @@ the source code. - `generator_state`: `library/core/src/ops/generator.rs` - `generator`: `library/core/src/ops/generator.rs` - Opting out - - `unsafe_cell` (relaxes pointer provenance rules, allowing const-to-mut casts): `library/core/src/cell.rs` + - `unsafe_cell` (relaxes pointer provenance rules, allowing const-to-mut + casts): `library/core/src/cell.rs` - `manually_drop` (opts out of implicit destructor call): `library/core/src/mem/manually_drop.rs` - Other - `coerce_unsized`: `library/core/src/ops/unsize.rs`