Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New section of the book: nightly rust #23719

Merged
merged 1 commit into from
Mar 28, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/doc/trpl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ and will be able to understand most Rust code and write more complex programs.

In a similar fashion to "Intermediate," this section is full of individual,
deep-dive chapters, which stand alone and can be read in any order. These
chapters focus on the most complex features, as well as some things that
are only available in upcoming versions of Rust.
chapters focus on the most complex features,

After reading "Advanced," you'll be a Rust expert!
<h2 class="section-header"><a href="unstable.html">Unstable</a></h2>

In a similar fashion to "Intermediate," this section is full of individual,
deep-dive chapters, which stand alone and can be read in any order.

This chapter contains things that are only available on the nightly channel of
Rust.
6 changes: 6 additions & 0 deletions src/doc/trpl/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@
* [FFI](ffi.md)
* [Unsafe Code](unsafe.md)
* [Advanced Macros](advanced-macros.md)
* [Unstable Rust](unstable.md)
* [Compiler Plugins](plugins.md)
* [Inline Assembly](inline-assembly.md)
* [No stdlib](no-stdlib.md)
* [Intrinsics](intrinsics.md)
* [Lang items](lang-items.md)
* [Link args](link-args.md)
* [Conclusion](conclusion.md)
* [Glossary](glossary.md)
9 changes: 0 additions & 9 deletions src/doc/trpl/advanced-macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,6 @@ the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
within Rust's macro system.

```rust
#![feature(trace_macros)]

macro_rules! bct {
// cmd 0: d ... => ...
(0, $($ps:tt),* ; $_d:tt)
Expand All @@ -229,13 +227,6 @@ macro_rules! bct {
( $($ps:tt),* ; )
=> (());
}

fn main() {
trace_macros!(true);
# /* just check the definition
bct!(0, 0, 1, 1, 1 ; 1, 0, 1);
# */
}
```

Exercise: use macros to reduce duplication in the above definition of the
Expand Down
25 changes: 0 additions & 25 deletions src/doc/trpl/ffi.md
Original file line number Diff line number Diff line change
Expand Up @@ -366,31 +366,6 @@ A few examples of how this model can be used are:
On OSX, frameworks behave with the same semantics as a dynamic library.
## The `link_args` attribute
There is one other way to tell rustc how to customize linking, and that is via
the `link_args` attribute. This attribute is applied to `extern` blocks and
specifies raw flags which need to get passed to the linker when producing an
artifact. An example usage would be:
``` no_run
#![feature(link_args)]
#[link_args = "-foo -bar -baz"]
extern {}
# fn main() {}
```

Note that this feature is currently hidden behind the `feature(link_args)` gate
because this is not a sanctioned way of performing linking. Right now rustc
shells out to the system linker, so it makes sense to provide extra command line
arguments, but this will not always be the case. In the future rustc may use
LLVM directly to link native libraries in which case `link_args` will have no
meaning.

It is highly recommended to *not* use this attribute, and rather use the more
formal `#[link(...)]` attribute on `extern` blocks instead.

# Unsafe blocks
Some operations, like dereferencing unsafe pointers or calling functions that have been marked
Expand Down
141 changes: 141 additions & 0 deletions src/doc/trpl/inline-assembly.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
% Inline Assembly

For extremely low-level manipulations and performance reasons, one
might wish to control the CPU directly. Rust supports using inline
assembly to do this via the `asm!` macro. The syntax roughly matches
that of GCC & Clang:

```ignore
asm!(assembly template
: output operands
: input operands
: clobbers
: options
);
```

Any use of `asm` is feature gated (requires `#![feature(asm)]` on the
crate to allow) and of course requires an `unsafe` block.

> **Note**: the examples here are given in x86/x86-64 assembly, but
> all platforms are supported.
## Assembly template

The `assembly template` is the only required parameter and must be a
literal string (i.e. `""`)

```
#![feature(asm)]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn foo() {
unsafe {
asm!("NOP");
}
}
// other platforms
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
fn foo() { /* ... */ }
fn main() {
// ...
foo();
// ...
}
```

(The `feature(asm)` and `#[cfg]`s are omitted from now on.)

Output operands, input operands, clobbers and options are all optional
but you must add the right number of `:` if you skip them:

```
# #![feature(asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
# fn main() { unsafe {
asm!("xor %eax, %eax"
:
:
: "eax"
);
# } }
```

Whitespace also doesn't matter:

```
# #![feature(asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
# fn main() { unsafe {
asm!("xor %eax, %eax" ::: "eax");
# } }
```

## Operands

Input and output operands follow the same format: `:
"constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand
expressions must be mutable lvalues:

```
# #![feature(asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn add(a: i32, b: i32) -> i32 {
let mut c = 0;
unsafe {
asm!("add $2, $0"
: "=r"(c)
: "0"(a), "r"(b)
);
}
c
}
# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
# fn add(a: i32, b: i32) -> i32 { a + b }
fn main() {
assert_eq!(add(3, 14159), 14162)
}
```

## Clobbers

Some instructions modify registers which might otherwise have held
different values so we use the clobbers list to indicate to the
compiler not to assume any values loaded into those registers will
stay valid.

```
# #![feature(asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
# fn main() { unsafe {
// Put the value 0x200 in eax
asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax");
# } }
```

Input and output registers need not be listed since that information
is already communicated by the given constraints. Otherwise, any other
registers used either implicitly or explicitly should be listed.

If the assembly changes the condition code register `cc` should be
specified as one of the clobbers. Similarly, if the assembly modifies
memory, `memory` should also be specified.

## Options

The last section, `options` is specific to Rust. The format is comma
separated literal strings (i.e. `:"foo", "bar", "baz"`). It's used to
specify some extra info about the inline assembly:

Current valid options are:

1. *volatile* - specifying this is analogous to
`__asm__ __volatile__ (...)` in gcc/clang.
2. *alignstack* - certain instructions expect the stack to be
aligned a certain way (i.e. SSE) and specifying this indicates to
the compiler to insert its usual stack alignment code
3. *intel* - use intel syntax instead of the default AT&T.

25 changes: 25 additions & 0 deletions src/doc/trpl/intrinsics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
% Intrinsics

> **Note**: intrinsics will forever have an unstable interface, it is
> recommended to use the stable interfaces of libcore rather than intrinsics
> directly.
These are imported as if they were FFI functions, with the special
`rust-intrinsic` ABI. For example, if one was in a freestanding
context, but wished to be able to `transmute` between types, and
perform efficient pointer arithmetic, one would import those functions
via a declaration like

```
# #![feature(intrinsics)]
# fn main() {}
extern "rust-intrinsic" {
fn transmute<T, U>(x: T) -> U;
fn offset<T>(dst: *const T, offset: isize) -> *const T;
}
```

As with any other FFI functions, these are always `unsafe` to call.

79 changes: 79 additions & 0 deletions src/doc/trpl/lang-items.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
% 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`:

```
#![feature(lang_items, box_syntax, start, no_std)]
#![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 = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
```

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.
25 changes: 25 additions & 0 deletions src/doc/trpl/link-args.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
% Link args

There is one other way to tell rustc how to customize linking, and that is via
the `link_args` attribute. This attribute is applied to `extern` blocks and
specifies raw flags which need to get passed to the linker when producing an
artifact. An example usage would be:

``` no_run
#![feature(link_args)]
#[link_args = "-foo -bar -baz"]
extern {}
# fn main() {}
```

Note that this feature is currently hidden behind the `feature(link_args)` gate
because this is not a sanctioned way of performing linking. Right now rustc
shells out to the system linker, so it makes sense to provide extra command line
arguments, but this will not always be the case. In the future rustc may use
LLVM directly to link native libraries in which case `link_args` will have no
meaning.

It is highly recommended to *not* use this attribute, and rather use the more
formal `#[link(...)]` attribute on `extern` blocks instead.

Loading