\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.
# 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)
* [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)
* [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)
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};
}
}
-#[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> {
--- /dev/null
+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.
+++ /dev/null
-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.
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;
}
// 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| {
-See the README.txt in ../librustc.
+See the README.md in ../librustc.
/// 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
}
}
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)
},
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)
}
"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)
}
_ => 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)
}
}
// 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
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};
}
}
-#[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> {
/// 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.
///
/// // 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;
--- /dev/null
+// 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
--- /dev/null
+// 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
+ _ => ()
+ };
+}
--- /dev/null
+// 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
+}
--- /dev/null
+// 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() {}
--- /dev/null
+// 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() {}