Auto merge of #23593 - Manishearth:rollup, r=Manishearth
(yay, no Saturday)
This commit is contained in:
commit
809a554fca
19 changed files with 347 additions and 205 deletions
|
|
@ -242,7 +242,7 @@ full debug info with variable and type information.
|
|||
\fBopt\-level\fR=\fIVAL\fR
|
||||
Optimize with possible levels 0\[en]3
|
||||
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
.SH ENVIRONMENT
|
||||
|
||||
Some of these affect the output of the compiler, while others affect programs
|
||||
which link to the standard library.
|
||||
|
|
|
|||
|
|
@ -1982,7 +1982,7 @@ the namespace hierarchy as it normally would.
|
|||
## Attributes
|
||||
|
||||
```{.ebnf .gram}
|
||||
attribute : "#!" ? '[' meta_item ']' ;
|
||||
attribute : '#' '!' ? '[' meta_item ']' ;
|
||||
meta_item : ident [ '=' literal
|
||||
| '(' meta_seq ')' ] ? ;
|
||||
meta_seq : meta_item [ ',' meta_seq ] ? ;
|
||||
|
|
@ -3158,7 +3158,7 @@ ten_times(|j| println!("hello, {}", j));
|
|||
### While loops
|
||||
|
||||
```{.ebnf .gram}
|
||||
while_expr : "while" no_struct_literal_expr '{' block '}' ;
|
||||
while_expr : [ lifetime ':' ] "while" no_struct_literal_expr '{' block '}' ;
|
||||
```
|
||||
|
||||
A `while` loop begins by evaluating the boolean loop conditional expression.
|
||||
|
|
@ -3223,7 +3223,7 @@ A `continue` expression is only permitted in the body of a loop.
|
|||
### For expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
for_expr : "for" pat "in" no_struct_literal_expr '{' block '}' ;
|
||||
for_expr : [ lifetime ':' ] "for" pat "in" no_struct_literal_expr '{' block '}' ;
|
||||
```
|
||||
|
||||
A `for` expression is a syntactic construct for looping over elements provided
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Summary
|
||||
|
||||
* [I: The Basics](basic.md)
|
||||
* [The Basics](basic.md)
|
||||
* [Installing Rust](installing-rust.md)
|
||||
* [Hello, world!](hello-world.md)
|
||||
* [Hello, Cargo!](hello-cargo.md)
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* [Strings](strings.md)
|
||||
* [Arrays, Vectors, and Slices](arrays-vectors-and-slices.md)
|
||||
* [Standard Input](standard-input.md)
|
||||
* [II: Intermediate Rust](intermediate.md)
|
||||
* [Intermediate Rust](intermediate.md)
|
||||
* [Crates and Modules](crates-and-modules.md)
|
||||
* [Testing](testing.md)
|
||||
* [Pointers](pointers.md)
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
* [Concurrency](concurrency.md)
|
||||
* [Error Handling](error-handling.md)
|
||||
* [Documentation](documentation.md)
|
||||
* [III: Advanced Topics](advanced.md)
|
||||
* [Advanced Topics](advanced.md)
|
||||
* [FFI](ffi.md)
|
||||
* [Unsafe Code](unsafe.md)
|
||||
* [Advanced Macros](advanced-macros.md)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ use core::default::Default;
|
|||
use core::fmt::Debug;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::iter::{Map, FromIterator, IntoIterator};
|
||||
use core::ops::{Index, IndexMut};
|
||||
use core::ops::{Index};
|
||||
use core::{iter, fmt, mem, usize};
|
||||
use Bound::{self, Included, Excluded, Unbounded};
|
||||
|
||||
|
|
@ -925,15 +925,6 @@ impl<K: Ord, Q: ?Sized, V> Index<Q> for BTreeMap<K, V>
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<K: Ord, Q: ?Sized, V> IndexMut<Q> for BTreeMap<K, V>
|
||||
where K: Borrow<Q>, Q: Ord
|
||||
{
|
||||
fn index_mut(&mut self, key: &Q) -> &mut V {
|
||||
self.get_mut(key).expect("no entry found for key")
|
||||
}
|
||||
}
|
||||
|
||||
/// Genericises over how to get the correct type of iterator from the correct type
|
||||
/// of Node ownership.
|
||||
trait Traverse<N> {
|
||||
|
|
|
|||
128
src/librustc/README.md
Normal file
128
src/librustc/README.md
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
An informal guide to reading and working on the rustc compiler.
|
||||
==================================================================
|
||||
|
||||
If you wish to expand on this document, or have a more experienced
|
||||
Rust contributor add anything else to it, please get in touch:
|
||||
|
||||
* http://internals.rust-lang.org/
|
||||
* https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
|
||||
|
||||
or file a bug:
|
||||
|
||||
https://github.com/rust-lang/rust/issues
|
||||
|
||||
Your concerns are probably the same as someone else's.
|
||||
|
||||
The crates of rustc
|
||||
===================
|
||||
|
||||
Rustc consists of a number of crates, including `libsyntax`,
|
||||
`librustc`, `librustc_back`, `librustc_trans`, and `librustc_driver`
|
||||
(the names and divisions are not set in stone and may change;
|
||||
in general, a finer-grained division of crates is preferable):
|
||||
|
||||
- `libsyntax` contains those things concerned purely with syntax –
|
||||
that is, the AST, parser, pretty-printer, lexer, macro expander, and
|
||||
utilities for traversing ASTs – are in a separate crate called
|
||||
"syntax", whose files are in `./../libsyntax`, where `.` is the
|
||||
current directory (that is, the parent directory of front/, middle/,
|
||||
back/, and so on).
|
||||
|
||||
- `librustc` (the current directory) contains the high-level analysis
|
||||
passes, such as the type checker, borrow checker, and so forth.
|
||||
It is the heart of the compiler.
|
||||
|
||||
- `librustc_back` contains some very low-level details that are
|
||||
specific to different LLVM targets and so forth.
|
||||
|
||||
- `librustc_trans` contains the code to convert from Rust IR into LLVM
|
||||
IR, and then from LLVM IR into machine code, as well as the main
|
||||
driver that orchestrates all the other passes and various other bits
|
||||
of miscellany. In general it contains code that runs towards the
|
||||
end of the compilation process.
|
||||
|
||||
- `librustc_driver` invokes the compiler from `libsyntax`, then the
|
||||
analysis phases from `librustc`, and finally the lowering and
|
||||
codegen passes from `librustc_trans`.
|
||||
|
||||
Roughly speaking the "order" of the three crates is as follows:
|
||||
|
||||
libsyntax -> librustc -> librustc_trans
|
||||
| |
|
||||
+-----------------+-------------------+
|
||||
|
|
||||
librustc_driver
|
||||
|
||||
|
||||
Modules in the rustc crate
|
||||
==========================
|
||||
|
||||
The rustc crate itself consists of the following submodules
|
||||
(mostly, but not entirely, in their own directories):
|
||||
|
||||
- session: options and data that pertain to the compilation session as
|
||||
a whole
|
||||
- middle: middle-end: name resolution, typechecking, LLVM code
|
||||
generation
|
||||
- metadata: encoder and decoder for data required by separate
|
||||
compilation
|
||||
- plugin: infrastructure for compiler plugins
|
||||
- lint: infrastructure for compiler warnings
|
||||
- util: ubiquitous types and helper functions
|
||||
- lib: bindings to LLVM
|
||||
|
||||
The entry-point for the compiler is main() in the librustc_trans
|
||||
crate.
|
||||
|
||||
The 3 central data structures:
|
||||
------------------------------
|
||||
|
||||
1. `./../libsyntax/ast.rs` defines the AST. The AST is treated as
|
||||
immutable after parsing, but it depends on mutable context data
|
||||
structures (mainly hash maps) to give it meaning.
|
||||
|
||||
- Many – though not all – nodes within this data structure are
|
||||
wrapped in the type `spanned<T>`, meaning that the front-end has
|
||||
marked the input coordinates of that node. The member `node` is
|
||||
the data itself, the member `span` is the input location (file,
|
||||
line, column; both low and high).
|
||||
|
||||
- Many other nodes within this data structure carry a
|
||||
`def_id`. These nodes represent the 'target' of some name
|
||||
reference elsewhere in the tree. When the AST is resolved, by
|
||||
`middle/resolve.rs`, all names wind up acquiring a def that they
|
||||
point to. So anything that can be pointed-to by a name winds
|
||||
up with a `def_id`.
|
||||
|
||||
2. `middle/ty.rs` defines the datatype `sty`. This is the type that
|
||||
represents types after they have been resolved and normalized by
|
||||
the middle-end. The typeck phase converts every ast type to a
|
||||
`ty::sty`, and the latter is used to drive later phases of
|
||||
compilation. Most variants in the `ast::ty` tag have a
|
||||
corresponding variant in the `ty::sty` tag.
|
||||
|
||||
3. `./../librustc_llvm/lib.rs` defines the exported types
|
||||
`ValueRef`, `TypeRef`, `BasicBlockRef`, and several others.
|
||||
Each of these is an opaque pointer to an LLVM type,
|
||||
manipulated through the `lib::llvm` interface.
|
||||
|
||||
|
||||
Control and information flow within the compiler:
|
||||
-------------------------------------------------
|
||||
|
||||
- main() in lib.rs assumes control on startup. Options are
|
||||
parsed, platform is detected, etc.
|
||||
|
||||
- `./../libsyntax/parse/parser.rs` parses the input files and produces
|
||||
an AST that represents the input crate.
|
||||
|
||||
- Multiple middle-end passes (`middle/resolve.rs`, `middle/typeck.rs`)
|
||||
analyze the semantics of the resulting AST. Each pass generates new
|
||||
information about the AST and stores it in various environment data
|
||||
structures. The driver passes environments to each compiler pass
|
||||
that needs to refer to them.
|
||||
|
||||
- Finally, the `trans` module in `librustc_trans` translates the Rust
|
||||
AST to LLVM bitcode in a type-directed way. When it's finished
|
||||
synthesizing LLVM values, rustc asks LLVM to write them out in some
|
||||
form (`.bc`, `.o`) and possibly run the system linker.
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
An informal guide to reading and working on the rustc compiler.
|
||||
==================================================================
|
||||
|
||||
If you wish to expand on this document, or have a more experienced
|
||||
Rust contributor add anything else to it, please get in touch:
|
||||
|
||||
* http://internals.rust-lang.org/
|
||||
* https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
|
||||
|
||||
or file a bug:
|
||||
|
||||
https://github.com/rust-lang/rust/issues
|
||||
|
||||
Your concerns are probably the same as someone else's.
|
||||
|
||||
The crates of rustc
|
||||
===================
|
||||
|
||||
Rustc consists of four crates altogether: `libsyntax`, `librustc`,
|
||||
`librustc_back`, and `librustc_trans` (the names and divisions are not
|
||||
set in stone and may change; in general, a finer-grained division of
|
||||
crates is preferable):
|
||||
|
||||
- `libsyntax` contains those things concerned purely with syntax --
|
||||
that is, the AST, parser, pretty-printer, lexer, macro expander, and
|
||||
utilities for traversing ASTs -- are in a separate crate called
|
||||
"syntax", whose files are in ./../libsyntax, where . is the current
|
||||
directory (that is, the parent directory of front/, middle/, back/,
|
||||
and so on).
|
||||
|
||||
- `librustc` (the current directory) contains the high-level analysis
|
||||
passes, such as the type checker, borrow checker, and so forth.
|
||||
It is the heart of the compiler.
|
||||
|
||||
- `librustc_back` contains some very low-level details that are
|
||||
specific to different LLVM targets and so forth.
|
||||
|
||||
- `librustc_trans` contains the code to convert from Rust IR into LLVM
|
||||
IR, and then from LLVM IR into machine code, as well as the main
|
||||
driver that orchestrates all the other passes and various other bits
|
||||
of miscellany. In general it contains code that runs towards the
|
||||
end of the compilation process.
|
||||
|
||||
Roughly speaking the "order" of the three crates is as follows:
|
||||
|
||||
libsyntax -> librustc -> librustc_trans
|
||||
| |
|
||||
+-----------------+-------------------+
|
||||
|
|
||||
librustc_trans/driver
|
||||
|
||||
Here the role of `librustc_trans/driver` is to invoke the compiler
|
||||
from libsyntax, then the analysis phases from librustc, and finally
|
||||
the lowering and codegen passes from librustc_trans.
|
||||
|
||||
Modules in the rustc crate
|
||||
==========================
|
||||
|
||||
The rustc crate itself consists of the following subdirectories
|
||||
(mostly, but not entirely, in their own directories):
|
||||
|
||||
session - options and data that pertain to the compilation session as a whole
|
||||
middle - middle-end: name resolution, typechecking, LLVM code
|
||||
generation
|
||||
metadata - encoder and decoder for data required by
|
||||
separate compilation
|
||||
util - ubiquitous types and helper functions
|
||||
lib - bindings to LLVM
|
||||
|
||||
The entry-point for the compiler is main() in the librustc_trans
|
||||
crate.
|
||||
|
||||
The 3 central data structures:
|
||||
------------------------------
|
||||
|
||||
#1: ./../libsyntax/ast.rs defines the AST. The AST is treated as immutable
|
||||
after parsing, but it depends on mutable context data structures
|
||||
(mainly hash maps) to give it meaning.
|
||||
|
||||
- Many -- though not all -- nodes within this data structure are
|
||||
wrapped in the type `spanned<T>`, meaning that the front-end has
|
||||
marked the input coordinates of that node. The member .node is
|
||||
the data itself, the member .span is the input location (file,
|
||||
line, column; both low and high).
|
||||
|
||||
- Many other nodes within this data structure carry a
|
||||
def_id. These nodes represent the 'target' of some name
|
||||
reference elsewhere in the tree. When the AST is resolved, by
|
||||
middle/resolve.rs, all names wind up acquiring a def that they
|
||||
point to. So anything that can be pointed-to by a name winds
|
||||
up with a def_id.
|
||||
|
||||
#2: middle/ty.rs defines the datatype sty. This is the type that
|
||||
represents types after they have been resolved and normalized by
|
||||
the middle-end. The typeck phase converts every ast type to a
|
||||
ty::sty, and the latter is used to drive later phases of
|
||||
compilation. Most variants in the ast::ty tag have a
|
||||
corresponding variant in the ty::sty tag.
|
||||
|
||||
#3: lib/llvm.rs (in librustc_trans) defines the exported types
|
||||
ValueRef, TypeRef, BasicBlockRef, and several others. Each of
|
||||
these is an opaque pointer to an LLVM type, manipulated through
|
||||
the lib::llvm interface.
|
||||
|
||||
|
||||
Control and information flow within the compiler:
|
||||
-------------------------------------------------
|
||||
|
||||
- main() in lib.rs assumes control on startup. Options are
|
||||
parsed, platform is detected, etc.
|
||||
|
||||
- ./../libsyntax/parse/parser.rs parses the input files and produces an AST
|
||||
that represents the input crate.
|
||||
|
||||
- Multiple middle-end passes (middle/resolve.rs, middle/typeck.rs)
|
||||
analyze the semantics of the resulting AST. Each pass generates new
|
||||
information about the AST and stores it in various environment data
|
||||
structures. The driver passes environments to each compiler pass
|
||||
that needs to refer to them.
|
||||
|
||||
- Finally, the `trans` module in `librustc_trans` translates the Rust
|
||||
AST to LLVM bitcode in a type-directed way. When it's finished
|
||||
synthesizing LLVM values, rustc asks LLVM to write them out in some
|
||||
form (.bc, .o) and possibly run the system linker.
|
||||
|
|
@ -900,7 +900,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
return;
|
||||
}
|
||||
if self.glob_map.contains_key(&import_id) {
|
||||
self.glob_map[import_id].insert(name);
|
||||
self.glob_map.get_mut(&import_id).unwrap().insert(name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -603,7 +603,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
|||
|
||||
// We've successfully resolved the import. Write the results in.
|
||||
let mut import_resolutions = module_.import_resolutions.borrow_mut();
|
||||
let import_resolution = &mut (*import_resolutions)[target];
|
||||
let import_resolution = import_resolutions.get_mut(&target).unwrap();
|
||||
|
||||
{
|
||||
let mut check_and_write_import = |namespace, result: &_, used_public: &mut bool| {
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
See the README.txt in ../librustc.
|
||||
See the README.md in ../librustc.
|
||||
|
|
|
|||
|
|
@ -983,56 +983,72 @@ pub fn load_if_immediate<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
|
|||
/// gives us better information about what we are loading.
|
||||
pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
|
||||
ptr: ValueRef, t: Ty<'tcx>) -> ValueRef {
|
||||
if type_is_zero_size(cx.ccx(), t) {
|
||||
C_undef(type_of::type_of(cx.ccx(), t))
|
||||
} else if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() {
|
||||
// We want to pass small aggregates as immediate values, but using an aggregate LLVM type
|
||||
// for this leads to bad optimizations, so its arg type is an appropriately sized integer
|
||||
// and we have to convert it
|
||||
Load(cx, BitCast(cx, ptr, type_of::arg_type_of(cx.ccx(), t).ptr_to()))
|
||||
} else {
|
||||
unsafe {
|
||||
let global = llvm::LLVMIsAGlobalVariable(ptr);
|
||||
if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True {
|
||||
let val = llvm::LLVMGetInitializer(global);
|
||||
if !val.is_null() {
|
||||
// This could go into its own function, for DRY.
|
||||
// (something like "pre-store packing/post-load unpacking")
|
||||
if ty::type_is_bool(t) {
|
||||
return Trunc(cx, val, Type::i1(cx.ccx()));
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
if cx.unreachable.get() || type_is_zero_size(cx.ccx(), t) {
|
||||
return C_undef(type_of::type_of(cx.ccx(), t));
|
||||
}
|
||||
|
||||
let ptr = to_arg_ty_ptr(cx, ptr, t);
|
||||
|
||||
if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() {
|
||||
return Load(cx, ptr);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let global = llvm::LLVMIsAGlobalVariable(ptr);
|
||||
if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True {
|
||||
let val = llvm::LLVMGetInitializer(global);
|
||||
if !val.is_null() {
|
||||
return from_arg_ty(cx, val, t);
|
||||
}
|
||||
}
|
||||
if ty::type_is_bool(t) {
|
||||
Trunc(cx, LoadRangeAssert(cx, ptr, 0, 2, llvm::False), Type::i1(cx.ccx()))
|
||||
} else if ty::type_is_char(t) {
|
||||
// a char is a Unicode codepoint, and so takes values from 0
|
||||
// to 0x10FFFF inclusive only.
|
||||
LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, llvm::False)
|
||||
} else if (ty::type_is_region_ptr(t) || ty::type_is_unique(t))
|
||||
&& !common::type_is_fat_ptr(cx.tcx(), t) {
|
||||
LoadNonNull(cx, ptr)
|
||||
} else {
|
||||
Load(cx, ptr)
|
||||
}
|
||||
}
|
||||
|
||||
let val = if ty::type_is_bool(t) {
|
||||
LoadRangeAssert(cx, ptr, 0, 2, llvm::False)
|
||||
} else if ty::type_is_char(t) {
|
||||
// a char is a Unicode codepoint, and so takes values from 0
|
||||
// to 0x10FFFF inclusive only.
|
||||
LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, llvm::False)
|
||||
} else if (ty::type_is_region_ptr(t) || ty::type_is_unique(t))
|
||||
&& !common::type_is_fat_ptr(cx.tcx(), t) {
|
||||
LoadNonNull(cx, ptr)
|
||||
} else {
|
||||
Load(cx, ptr)
|
||||
};
|
||||
|
||||
from_arg_ty(cx, val, t)
|
||||
}
|
||||
|
||||
/// Helper for storing values in memory. Does the necessary conversion if the in-memory type
|
||||
/// differs from the type used for SSA values.
|
||||
pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t: Ty<'tcx>) {
|
||||
if ty::type_is_bool(t) {
|
||||
Store(cx, ZExt(cx, v, Type::i8(cx.ccx())), dst);
|
||||
} else if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() {
|
||||
Store(cx, to_arg_ty(cx, v, t), to_arg_ty_ptr(cx, dst, t));
|
||||
}
|
||||
|
||||
pub fn to_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
|
||||
if ty::type_is_bool(ty) {
|
||||
ZExt(bcx, val, Type::i8(bcx.ccx()))
|
||||
} else {
|
||||
val
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
|
||||
if ty::type_is_bool(ty) {
|
||||
Trunc(bcx, val, Type::i1(bcx.ccx()))
|
||||
} else {
|
||||
val
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_arg_ty_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ptr: ValueRef, ty: Ty<'tcx>) -> ValueRef {
|
||||
if type_is_immediate(bcx.ccx(), ty) && type_of::type_of(bcx.ccx(), ty).is_aggregate() {
|
||||
// We want to pass small aggregates as immediate values, but using an aggregate LLVM type
|
||||
// for this leads to bad optimizations, so its arg type is an appropriately sized integer
|
||||
// and we have to convert it
|
||||
Store(cx, v, BitCast(cx, dst, type_of::arg_type_of(cx.ccx(), t).ptr_to()));
|
||||
BitCast(bcx, ptr, type_of::arg_type_of(bcx.ccx(), ty).ptr_to())
|
||||
} else {
|
||||
Store(cx, v, dst);
|
||||
ptr
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -446,10 +446,15 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
|||
call_debug_location)
|
||||
}
|
||||
(_, "volatile_load") => {
|
||||
VolatileLoad(bcx, llargs[0])
|
||||
let tp_ty = *substs.types.get(FnSpace, 0);
|
||||
let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
|
||||
from_arg_ty(bcx, VolatileLoad(bcx, ptr), tp_ty)
|
||||
},
|
||||
(_, "volatile_store") => {
|
||||
VolatileStore(bcx, llargs[1], llargs[0]);
|
||||
let tp_ty = *substs.types.get(FnSpace, 0);
|
||||
let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
|
||||
let val = to_arg_ty(bcx, llargs[1], tp_ty);
|
||||
VolatileStore(bcx, val, ptr);
|
||||
C_nil(ccx)
|
||||
},
|
||||
|
||||
|
|
@ -709,8 +714,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
|||
llvm::SequentiallyConsistent
|
||||
};
|
||||
|
||||
let res = AtomicCmpXchg(bcx, llargs[0], llargs[1],
|
||||
llargs[2], order,
|
||||
let tp_ty = *substs.types.get(FnSpace, 0);
|
||||
let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
|
||||
let cmp = to_arg_ty(bcx, llargs[1], tp_ty);
|
||||
let src = to_arg_ty(bcx, llargs[2], tp_ty);
|
||||
let res = AtomicCmpXchg(bcx, ptr, cmp, src, order,
|
||||
strongest_failure_ordering);
|
||||
if unsafe { llvm::LLVMVersionMinor() >= 5 } {
|
||||
ExtractValue(bcx, res, 0)
|
||||
|
|
@ -720,10 +728,15 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
|||
}
|
||||
|
||||
"load" => {
|
||||
AtomicLoad(bcx, llargs[0], order)
|
||||
let tp_ty = *substs.types.get(FnSpace, 0);
|
||||
let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
|
||||
from_arg_ty(bcx, AtomicLoad(bcx, ptr, order), tp_ty)
|
||||
}
|
||||
"store" => {
|
||||
AtomicStore(bcx, llargs[1], llargs[0], order);
|
||||
let tp_ty = *substs.types.get(FnSpace, 0);
|
||||
let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
|
||||
let val = to_arg_ty(bcx, llargs[1], tp_ty);
|
||||
AtomicStore(bcx, val, ptr, order);
|
||||
C_nil(ccx)
|
||||
}
|
||||
|
||||
|
|
@ -749,7 +762,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
|||
_ => ccx.sess().fatal("unknown atomic operation")
|
||||
};
|
||||
|
||||
AtomicRMW(bcx, atom_op, llargs[0], llargs[1], order)
|
||||
let tp_ty = *substs.types.get(FnSpace, 0);
|
||||
let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
|
||||
let val = to_arg_ty(bcx, llargs[1], tp_ty);
|
||||
AtomicRMW(bcx, atom_op, ptr, val, order)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -380,7 +380,7 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> {
|
|||
// borrow_kind of the upvar to make sure it
|
||||
// is inferred to mutable if necessary
|
||||
let mut upvar_capture_map = self.fcx.inh.upvar_capture_map.borrow_mut();
|
||||
let ub = &mut upvar_capture_map[upvar_id];
|
||||
let ub = upvar_capture_map.get_mut(&upvar_id).unwrap();
|
||||
self.adjust_upvar_borrow_kind(upvar_id, ub, borrow_kind);
|
||||
|
||||
// also need to be in an FnMut closure since this is not an ImmBorrow
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ use hash::{Hash, SipHasher};
|
|||
use iter::{self, Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map};
|
||||
use marker::Sized;
|
||||
use mem::{self, replace};
|
||||
use ops::{Deref, FnMut, Index, IndexMut};
|
||||
use ops::{Deref, FnMut, Index};
|
||||
use option::Option::{self, Some, None};
|
||||
use rand::{self, Rng};
|
||||
use result::Result::{self, Ok, Err};
|
||||
|
|
@ -1258,18 +1258,6 @@ impl<K, Q: ?Sized, V, S> Index<Q> for HashMap<K, V, S>
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<K, V, S, Q: ?Sized> IndexMut<Q> for HashMap<K, V, S>
|
||||
where K: Eq + Hash + Borrow<Q>,
|
||||
Q: Eq + Hash,
|
||||
S: HashState,
|
||||
{
|
||||
#[inline]
|
||||
fn index_mut<'a>(&'a mut self, index: &Q) -> &'a mut V {
|
||||
self.get_mut(index).expect("no entry found for key")
|
||||
}
|
||||
}
|
||||
|
||||
/// HashMap iterator.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Iter<'a, K: 'a, V: 'a> {
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ use fmt;
|
|||
/// among threads to ensure that a possibly invalid invariant is not witnessed.
|
||||
///
|
||||
/// A poisoned mutex, however, does not prevent all access to the underlying
|
||||
/// data. The `PoisonError` type has an `into_guard` method which will return
|
||||
/// data. The `PoisonError` type has an `into_inner` method which will return
|
||||
/// the guard that would have otherwise been returned on a successful lock. This
|
||||
/// allows access to the data, despite the lock being poisoned.
|
||||
///
|
||||
|
|
@ -105,7 +105,7 @@ use fmt;
|
|||
/// // pattern matched on to return the underlying guard on both branches.
|
||||
/// let mut guard = match lock.lock() {
|
||||
/// Ok(guard) => guard,
|
||||
/// Err(poisoned) => poisoned.into_guard(),
|
||||
/// Err(poisoned) => poisoned.into_inner(),
|
||||
/// };
|
||||
///
|
||||
/// *guard += 1;
|
||||
|
|
|
|||
22
src/test/compile-fail-fulldeps/gated-macro-reexports.rs
Normal file
22
src/test/compile-fail-fulldeps/gated-macro-reexports.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that macro reexports item are gated by `macro_reexport` feature gate.
|
||||
|
||||
// aux-build:macro_reexport_1.rs
|
||||
// ignore-stage1
|
||||
|
||||
#![crate_type = "dylib"]
|
||||
|
||||
#[macro_reexport(reexported)]
|
||||
#[macro_use] #[no_link]
|
||||
extern crate macro_reexport_1;
|
||||
//~^ ERROR macros reexports are experimental and possibly buggy
|
||||
//~| HELP add #![feature(macro_reexport)] to the crate attributes to enable
|
||||
22
src/test/compile-fail/gated-box-patterns.rs
Normal file
22
src/test/compile-fail/gated-box-patterns.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that patterns including the box syntax are gated by `box_patterns` feature gate.
|
||||
|
||||
fn main() {
|
||||
let x = Box::new(1);
|
||||
|
||||
match x {
|
||||
box 1 => (),
|
||||
//~^ box pattern syntax is experimental
|
||||
//~| add #![feature(box_patterns)] to the crate attributes to enable
|
||||
_ => ()
|
||||
};
|
||||
}
|
||||
17
src/test/compile-fail/gated-box-syntax.rs
Normal file
17
src/test/compile-fail/gated-box-syntax.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that the use of the box syntax is gated by `box_syntax` feature gate.
|
||||
|
||||
fn main() {
|
||||
let x = box 3;
|
||||
//~^ ERROR box expression syntax is experimental; you can call `Box::new` instead.
|
||||
//~| HELP add #![feature(box_syntax)] to the crate attributes to enable
|
||||
}
|
||||
27
src/test/compile-fail/gated-simd-ffi.rs
Normal file
27
src/test/compile-fail/gated-simd-ffi.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that the use of smid types in the ffi is gated by `smid_ffi` feature gate.
|
||||
|
||||
#![feature(simd)]
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy)]
|
||||
#[simd]
|
||||
pub struct f32x4(f32, f32, f32, f32);
|
||||
|
||||
#[allow(dead_code)]
|
||||
extern {
|
||||
fn foo(x: f32x4);
|
||||
//~^ ERROR use of SIMD type `f32x4` in FFI is highly experimental and may result in invalid code
|
||||
//~| HELP add #![feature(simd_ffi)] to the crate attributes to enable
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
39
src/test/run-pass/issue-23550.rs
Normal file
39
src/test/run-pass/issue-23550.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(core)]
|
||||
#![allow(warnings)]
|
||||
|
||||
use std::intrinsics;
|
||||
|
||||
#[derive(Copy)]
|
||||
struct Wrap(i64);
|
||||
|
||||
// These volatile and atomic intrinsics used to cause an ICE
|
||||
|
||||
unsafe fn test_bool(p: &mut bool, v: bool) {
|
||||
intrinsics::volatile_load(p);
|
||||
intrinsics::volatile_store(p, v);
|
||||
intrinsics::atomic_load(p);
|
||||
intrinsics::atomic_cxchg(p, v, v);
|
||||
intrinsics::atomic_store(p, v);
|
||||
intrinsics::atomic_xchg(p, v);
|
||||
}
|
||||
|
||||
unsafe fn test_immediate_fca(p: &mut Wrap, v: Wrap) {
|
||||
intrinsics::volatile_load(p);
|
||||
intrinsics::volatile_store(p, v);
|
||||
intrinsics::atomic_load(p);
|
||||
intrinsics::atomic_cxchg(p, v, v);
|
||||
intrinsics::atomic_store(p, v);
|
||||
intrinsics::atomic_xchg(p, v);
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue