7a3fdfbf67
This commit removes all morestack support from the compiler which entails: * Segmented stacks are no longer emitted in codegen. * We no longer build or distribute libmorestack.a * The `stack_exhausted` lang item is no longer required The only current use of the segmented stack support in LLVM is to detect stack overflow. This is no longer really required, however, because we already have guard pages for all threads and registered signal handlers watching for a segfault on those pages (to print out a stack overflow message). Additionally, major platforms (aka Windows) already don't use morestack. This means that Rust is by default less likely to catch stack overflows because if a function takes up more than one page of stack space it won't hit the guard page. This is what the purpose of morestack was (to catch this case), but it's better served with stack probes which have more cross platform support and no runtime support necessary. Until LLVM supports this for all platform it looks like morestack isn't really buying us much. cc #16012 (still need stack probes) Closes #26458 (a drive-by fix to help diagnostics on stack overflow)
80 lines
2.6 KiB
Markdown
80 lines
2.6 KiB
Markdown
% Lang items
|
|
|
|
> **Note**: lang items are often provided by crates in the Rust distribution,
|
|
> and lang items themselves have an unstable interface. It is recommended to use
|
|
> officially distributed crates instead of defining your own 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
|
|
#![feature(lang_items, box_syntax, start, no_std, libc)]
|
|
#![no_std]
|
|
|
|
extern crate libc;
|
|
|
|
extern {
|
|
fn abort() -> !;
|
|
}
|
|
|
|
#[lang = "owned_box"]
|
|
pub struct Box<T>(*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;
|
|
|
|
// malloc failed
|
|
if p as usize == 0 {
|
|
abort();
|
|
}
|
|
|
|
p
|
|
}
|
|
#[lang = "exchange_free"]
|
|
unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) {
|
|
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 eh_personality() {}
|
|
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
|
|
# #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}
|
|
```
|
|
|
|
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`, `fail`
|
|
and `fail_bounds_checks` lang items.
|
|
- the traits in `std::marker` used to indicate types of
|
|
various kinds; lang items `send`, `sync` and `copy`.
|
|
- the marker types and variance indicators found in
|
|
`std::marker`; lang items `covariant_type`,
|
|
`contravariant_lifetime`, etc.
|
|
|
|
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 `exchange_free`. `rustc` will emit an error when an item is needed
|
|
but not found in the current crate or any that it depends on.
|