- [link_llvm_intrinsics](link-llvm-intrinsics.md)
- [linkage](linkage.md)
- [linked_list_extras](linked-list-extras.md)
+- [linker_flavor](linker-flavor.md)
- [log_syntax](log-syntax.md)
- [lookup_host](lookup-host.md)
- [loop_break_value](loop-break-value.md)
- [macro_reexport](macro-reexport.md)
- [main](main.md)
+- [manually_drop](manually-drop.md)
- [map_entry_recover_keys](map-entry-recover-keys.md)
- [mpsc_select](mpsc-select.md)
- [n16](n16.md)
- [str_checked_slicing](str-checked-slicing.md)
- [str_escape](str-escape.md)
- [str_internals](str-internals.md)
+- [str_mut_extras](str-mut-extras.md)
- [struct_field_attributes](struct-field-attributes.md)
- [structural_match](structural-match.md)
- [target_feature](target-feature.md)
--- /dev/null
+# `linker-flavor`
+
+The tracking issue for this feature is: None
+
+------------------------
+
+Every `rustc` target defaults to some linker. For example, Linux targets default
+to gcc. In some cases, you may want to override the default; you can do that
+with the unstable CLI argument: `-Z linker-flavor`.
+
+Here how you would use this flag to link a Rust binary for the
+`thumbv7m-none-eabi` using LLD instead of GCC.
+
+``` text
+$ xargo rustc --target thumbv7m-none-eabi -- \
+ -C linker=ld.lld \
+ -Z linker-flavor=ld \
+ -Z print-link-args | tr ' ' '\n'
+"ld.lld"
+"-L"
+"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib"
+"$PWD/target/thumbv7m-none-eabi/debug/deps/app-512e9dbf385f233c.0.o"
+"-o"
+"$PWD/target/thumbv7m-none-eabi/debug/deps/app-512e9dbf385f233c"
+"--gc-sections"
+"-L"
+"$PWD/target/thumbv7m-none-eabi/debug/deps"
+"-L"
+"$PWD/target/debug/deps"
+"-L"
+"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib"
+"-Bstatic"
+"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib/libcore-e1ccb7dfb1cb9ebb.rlib"
+"-Bdynamic"
+```
+
+Whereas the default is:
+
+``` text
+$ xargo rustc --target thumbv7m-none-eabi -- \
+ -C link-arg=-nostartfiles \
+ -Z print-link-args | tr ' ' '\n'
+"arm-none-eabi-gcc"
+"-L"
+"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib"
+"$PWD/target/thumbv7m-none-eabi/debug/deps/app-961e39416baa38d9.0.o"
+"-o"
+"$PWD/target/thumbv7m-none-eabi/debug/deps/app-961e39416baa38d9"
+"-Wl,--gc-sections"
+"-nodefaultlibs"
+"-L"
+"$PWD/target/thumbv7m-none-eabi/debug/deps"
+"-L"
+"$PWD/target/debug/deps"
+"-L"
+"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib"
+"-Wl,-Bstatic"
+"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib/libcore-e1ccb7dfb1cb9ebb.rlib"
+"-nostartfiles"
+"-Wl,-Bdynamic"
+```
--- /dev/null
+# `str_mut_extras`
+
+The tracking issue for this feature is: [#str_mut_extras]
+
+[#str_mut_extras]: https://github.com/rust-lang/rust/issues/41119
+
+------------------------
+
// should be good to go!
cmd.arg("--with-jemalloc-prefix=je_");
cmd.arg("--disable-tls");
- } else if target.contains("dragonfly") {
+ } else if target.contains("dragonfly") || target.contains("musl") {
cmd.arg("--with-jemalloc-prefix=je_");
}
// request it as unprefixing cause segfaults (mismatches in allocators).
extern "C" {
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
- target_os = "dragonfly", target_os = "windows"),
+ target_os = "dragonfly", target_os = "windows", target_env = "musl"),
link_name = "je_mallocx")]
fn mallocx(size: size_t, flags: c_int) -> *mut c_void;
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
- target_os = "dragonfly", target_os = "windows"),
+ target_os = "dragonfly", target_os = "windows", target_env = "musl"),
link_name = "je_rallocx")]
fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
- target_os = "dragonfly", target_os = "windows"),
+ target_os = "dragonfly", target_os = "windows", target_env = "musl"),
link_name = "je_xallocx")]
fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
- target_os = "dragonfly", target_os = "windows"),
+ target_os = "dragonfly", target_os = "windows", target_env = "musl"),
link_name = "je_sdallocx")]
fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
- target_os = "dragonfly", target_os = "windows"),
+ target_os = "dragonfly", target_os = "windows", target_env = "musl"),
link_name = "je_nallocx")]
fn nallocx(size: size_t, flags: c_int) -> size_t;
}
#![feature(heap_api)]
#![feature(inclusive_range)]
#![feature(lang_items)]
+#![feature(manually_drop)]
#![feature(nonzero)]
#![feature(pattern)]
#![feature(placement_in)]
#![feature(specialization)]
#![feature(staged_api)]
#![feature(str_internals)]
+#![feature(str_mut_extras)]
#![feature(trusted_len)]
#![feature(unicode)]
#![feature(unique)]
// performance than with the 2nd method.
//
// All methods were benchmarked, and the 3rd showed best results. So we chose that one.
- let mut tmp = NoDrop { value: ptr::read(&v[0]) };
+ let mut tmp = mem::ManuallyDrop::new(ptr::read(&v[0]));
// Intermediate state of the insertion process is always tracked by `hole`, which
// serves two purposes:
// fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it
// initially held exactly once.
let mut hole = InsertionHole {
- src: &mut tmp.value,
+ src: &mut *tmp,
dest: &mut v[1],
};
ptr::copy_nonoverlapping(&v[1], &mut v[0], 1);
for i in 2..v.len() {
- if !is_less(&v[i], &tmp.value) {
+ if !is_less(&v[i], &*tmp) {
break;
}
ptr::copy_nonoverlapping(&v[i], &mut v[i - 1], 1);
}
}
- // Holds a value, but never drops it.
- #[allow(unions_with_drop_fields)]
- union NoDrop<T> {
- value: T
- }
-
// When dropped, copies from `src` into `dest`.
struct InsertionHole<T> {
src: *mut T,
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::str::{from_utf8, Chars, CharIndices, Bytes};
#[stable(feature = "rust1", since = "1.0.0")]
-pub use core::str::{from_utf8_unchecked, ParseBoolError};
+pub use core::str::{from_utf8_unchecked, from_utf8_unchecked_mut, ParseBoolError};
#[stable(feature = "rust1", since = "1.0.0")]
pub use std_unicode::str::SplitWhitespace;
#[stable(feature = "rust1", since = "1.0.0")]
core_str::StrExt::as_bytes(self)
}
+ /// Converts a mutable string slice to a mutable byte slice.
+ #[unstable(feature = "str_mut_extras", issue = "41119")]
+ #[inline(always)]
+ pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
+ core_str::StrExt::as_bytes_mut(self)
+ }
+
/// Converts a string slice to a raw pointer.
///
/// As string slices are a slice of bytes, the raw pointer points to a
impl ops::IndexMut<ops::RangeFull> for String {
#[inline]
fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str {
- unsafe { mem::transmute(&mut *self.vec) }
+ unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) }
}
}
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
impl ops::DerefMut for String {
#[inline]
fn deref_mut(&mut self) -> &mut str {
- unsafe { mem::transmute(&mut *self.vec) }
+ unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) }
}
}
use convert::TryFrom;
use fmt::{self, Write};
use slice;
+use str::from_utf8_unchecked_mut;
use iter::FusedIterator;
use mem::transmute;
code,
dst.len())
};
- transmute(slice::from_raw_parts_mut(dst.as_mut_ptr(), len))
+ from_utf8_unchecked_mut(dst.get_unchecked_mut(..len))
}
}
/// ```
#[lang = "eq"]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"]
pub trait PartialEq<Rhs: ?Sized = Self> {
/// This method tests for `self` and `other` values to be equal, and is used
/// by `==`.
/// ```
#[lang = "ord"]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"]
pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
/// This method returns an ordering between `self` and `other` values if one exists.
///
/// initialize memory previous set to the result of `uninit`.
pub fn uninit<T>() -> T;
- /// Moves a value out of scope without running drop glue.
- pub fn forget<T>(_: T) -> ();
-
/// Reinterprets the bits of a value of one type as another type.
///
/// Both types must have the same size. Neither the original, nor the result,
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn forget<T>(t: T) {
- unsafe { intrinsics::forget(t) }
+ ManuallyDrop::new(t);
}
/// Returns the size of a type in bytes.
}
}
+
+/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
+///
+/// This wrapper is 0-cost.
+///
+/// # Examples
+///
+/// This wrapper helps with explicitly documenting the drop order dependencies between fields of
+/// the type:
+///
+/// ```rust
+/// # #![feature(manually_drop)]
+/// use std::mem::ManuallyDrop;
+/// struct Peach;
+/// struct Banana;
+/// struct Melon;
+/// struct FruitBox {
+/// // Immediately clear there’s something non-trivial going on with these fields.
+/// peach: ManuallyDrop<Peach>,
+/// melon: Melon, // Field that’s independent of the other two.
+/// banana: ManuallyDrop<Banana>,
+/// }
+///
+/// impl Drop for FruitBox {
+/// fn drop(&mut self) {
+/// unsafe {
+/// // Explicit ordering in which field destructors are run specified in the intuitive
+/// // location – the destructor of the structure containing the fields.
+/// // Moreover, one can now reorder fields within the struct however much they want.
+/// ManuallyDrop::drop(&mut self.peach);
+/// ManuallyDrop::drop(&mut self.banana);
+/// }
+/// // After destructor for `FruitBox` runs (this function), the destructor for Melon gets
+/// // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`.
+/// }
+/// }
+/// ```
+#[unstable(feature = "manually_drop", issue = "40673")]
+#[allow(unions_with_drop_fields)]
+pub union ManuallyDrop<T>{ value: T }
+
+impl<T> ManuallyDrop<T> {
+ /// Wrap a value to be manually dropped.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # #![feature(manually_drop)]
+ /// use std::mem::ManuallyDrop;
+ /// ManuallyDrop::new(Box::new(()));
+ /// ```
+ #[unstable(feature = "manually_drop", issue = "40673")]
+ #[inline]
+ pub fn new(value: T) -> ManuallyDrop<T> {
+ ManuallyDrop { value: value }
+ }
+
+ /// Extract the value from the ManuallyDrop container.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # #![feature(manually_drop)]
+ /// use std::mem::ManuallyDrop;
+ /// let x = ManuallyDrop::new(Box::new(()));
+ /// let _: Box<()> = ManuallyDrop::into_inner(x);
+ /// ```
+ #[unstable(feature = "manually_drop", issue = "40673")]
+ #[inline]
+ pub fn into_inner(slot: ManuallyDrop<T>) -> T {
+ unsafe {
+ slot.value
+ }
+ }
+
+ /// Manually drops the contained value.
+ ///
+ /// # Unsafety
+ ///
+ /// This function runs the destructor of the contained value and thus the wrapped value
+ /// now represents uninitialized data. It is up to the user of this method to ensure the
+ /// uninitialized data is not actually used.
+ #[unstable(feature = "manually_drop", issue = "40673")]
+ #[inline]
+ pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
+ ptr::drop_in_place(&mut slot.value)
+ }
+}
+
+#[unstable(feature = "manually_drop", issue = "40673")]
+impl<T> ::ops::Deref for ManuallyDrop<T> {
+ type Target = T;
+ #[inline]
+ fn deref(&self) -> &Self::Target {
+ unsafe {
+ &self.value
+ }
+ }
+}
+
+#[unstable(feature = "manually_drop", issue = "40673")]
+impl<T> ::ops::DerefMut for ManuallyDrop<T> {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ unsafe {
+ &mut self.value
+ }
+ }
+}
+
+#[unstable(feature = "manually_drop", issue = "40673")]
+impl<T: ::fmt::Debug> ::fmt::Debug for ManuallyDrop<T> {
+ fn fmt(&self, fmt: &mut ::fmt::Formatter) -> ::fmt::Result {
+ unsafe {
+ fmt.debug_tuple("ManuallyDrop").field(&self.value).finish()
+ }
+ }
+}
/// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html
#[lang = "add"]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} + {RHS}`"]
pub trait Add<RHS=Self> {
/// The resulting type after applying the `+` operator
#[stable(feature = "rust1", since = "1.0.0")]
/// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html
#[lang = "sub"]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} - {RHS}`"]
pub trait Sub<RHS=Self> {
/// The resulting type after applying the `-` operator
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[lang = "mul"]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} * {RHS}`"]
pub trait Mul<RHS=Self> {
/// The resulting type after applying the `*` operator
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[lang = "div"]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} / {RHS}`"]
pub trait Div<RHS=Self> {
/// The resulting type after applying the `/` operator
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[lang = "rem"]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} % {RHS}`"]
pub trait Rem<RHS=Self> {
/// The resulting type after applying the `%` operator
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[lang = "bitand"]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"]
pub trait BitAnd<RHS=Self> {
/// The resulting type after applying the `&` operator
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[lang = "bitor"]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"]
pub trait BitOr<RHS=Self> {
/// The resulting type after applying the `|` operator
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[lang = "bitxor"]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"]
pub trait BitXor<RHS=Self> {
/// The resulting type after applying the `^` operator
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[lang = "shl"]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"]
pub trait Shl<RHS> {
/// The resulting type after applying the `<<` operator
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[lang = "shr"]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"]
pub trait Shr<RHS> {
/// The resulting type after applying the `>>` operator
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[lang = "add_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} += {Rhs}`"]
pub trait AddAssign<Rhs=Self> {
/// The method for the `+=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[lang = "sub_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} -= {Rhs}`"]
pub trait SubAssign<Rhs=Self> {
/// The method for the `-=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[lang = "mul_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} *= {Rhs}`"]
pub trait MulAssign<Rhs=Self> {
/// The method for the `*=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[lang = "div_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} /= {Rhs}`"]
pub trait DivAssign<Rhs=Self> {
/// The method for the `/=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[lang = "rem_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} %= {Rhs}`"]
pub trait RemAssign<Rhs=Self> {
/// The method for the `%=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[lang = "bitand_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"]
pub trait BitAndAssign<Rhs=Self> {
/// The method for the `&=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[lang = "bitor_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"]
pub trait BitOrAssign<Rhs=Self> {
/// The method for the `|=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[lang = "bitxor_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"]
pub trait BitXorAssign<Rhs=Self> {
/// The method for the `^=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[lang = "shl_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"]
pub trait ShlAssign<Rhs> {
/// The method for the `<<=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
/// ```
#[lang = "shr_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"]
pub trait ShrAssign<Rhs=Self> {
/// The method for the `>>=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
use mem;
use ptr;
-/// Holds a value, but never drops it.
-#[allow(unions_with_drop_fields)]
-union NoDrop<T> {
- value: T
-}
-
/// When dropped, copies from `src` into `dest`.
struct CopyOnDrop<T> {
src: *mut T,
// Read the first element into a stack-allocated variable. If a following comparison
// operation panics, `hole` will get dropped and automatically write the element back
// into the slice.
- let mut tmp = NoDrop { value: ptr::read(v.get_unchecked(0)) };
+ let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(0)));
let mut hole = CopyOnDrop {
- src: &mut tmp.value,
+ src: &mut *tmp,
dest: v.get_unchecked_mut(1),
};
ptr::copy_nonoverlapping(v.get_unchecked(1), v.get_unchecked_mut(0), 1);
for i in 2..len {
- if !is_less(v.get_unchecked(i), &tmp.value) {
+ if !is_less(v.get_unchecked(i), &*tmp) {
break;
}
// Read the last element into a stack-allocated variable. If a following comparison
// operation panics, `hole` will get dropped and automatically write the element back
// into the slice.
- let mut tmp = NoDrop { value: ptr::read(v.get_unchecked(len - 1)) };
+ let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(len - 1)));
let mut hole = CopyOnDrop {
- src: &mut tmp.value,
+ src: &mut *tmp,
dest: v.get_unchecked_mut(len - 2),
};
ptr::copy_nonoverlapping(v.get_unchecked(len - 2), v.get_unchecked_mut(len - 1), 1);
for i in (0..len-2).rev() {
- if !is_less(&tmp.value, v.get_unchecked(i)) {
+ if !is_less(&*tmp, v.get_unchecked(i)) {
break;
}
// Read the pivot into a stack-allocated variable for efficiency. If a following comparison
// operation panics, the pivot will be automatically written back into the slice.
- let mut tmp = NoDrop { value: unsafe { ptr::read(pivot) } };
+ let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
let _pivot_guard = CopyOnDrop {
- src: unsafe { &mut tmp.value },
+ src: &mut *tmp,
dest: pivot,
};
- let pivot = unsafe { &tmp.value };
+ let pivot = &*tmp;
// Find the first pair of out-of-order elements.
let mut l = 0;
// Read the pivot into a stack-allocated variable for efficiency. If a following comparison
// operation panics, the pivot will be automatically written back into the slice.
- let mut tmp = NoDrop { value: unsafe { ptr::read(pivot) } };
+ let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
let _pivot_guard = CopyOnDrop {
- src: unsafe { &mut tmp.value },
+ src: &mut *tmp,
dest: pivot,
};
- let pivot = unsafe { &tmp.value };
+ let pivot = &*tmp;
// Now partition the slice.
let mut l = 0;
use convert::TryFrom;
use fmt;
use iter::{Map, Cloned, FusedIterator};
-use mem;
use slice::{self, SliceIndex};
+use mem;
pub mod pattern;
Ok(unsafe { from_utf8_unchecked(v) })
}
+/// Converts a mutable slice of bytes to a mutable string slice.
+#[unstable(feature = "str_mut_extras", issue = "41119")]
+pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
+ run_utf8_validation(v)?;
+ Ok(unsafe { from_utf8_unchecked_mut(v) })
+}
+
/// Forms a str from a pointer and a length.
///
/// The `len` argument is the number of bytes in the string.
/// str is returned.
///
unsafe fn from_raw_parts_mut<'a>(p: *mut u8, len: usize) -> &'a mut str {
- mem::transmute::<&mut [u8], &mut str>(slice::from_raw_parts_mut(p, len))
+ from_utf8_unchecked_mut(slice::from_raw_parts_mut(p, len))
}
/// Converts a slice of bytes to a string slice without checking
mem::transmute(v)
}
+/// Converts a slice of bytes to a string slice without checking
+/// that the string contains valid UTF-8; mutable version.
+///
+/// See the immutable version, [`from_utf8_unchecked()`][fromutf8], for more information.
+///
+/// [fromutf8]: fn.from_utf8_unchecked.html
+#[inline(always)]
+#[unstable(feature = "str_mut_extras", issue = "41119")]
+pub unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str {
+ mem::transmute(v)
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for Utf8Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
mod traits {
use cmp::Ordering;
use ops;
- use mem;
use slice::{self, SliceIndex};
use str::eq_slice;
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
let ptr = slice.as_ptr().offset(self.start as isize);
let len = self.end - self.start;
- mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len))
+ super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, len))
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
#[inline]
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
let ptr = slice.as_ptr();
- mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, self.end))
+ super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, self.end))
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
let ptr = slice.as_ptr().offset(self.start as isize);
let len = slice.len() - self.start;
- mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len))
+ super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, len))
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
#[inline]
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
let ptr = slice.as_ptr();
- mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, self.end + 1))
+ super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, self.end + 1))
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
fn is_char_boundary(&self, index: usize) -> bool;
#[stable(feature = "core", since = "1.6.0")]
fn as_bytes(&self) -> &[u8];
+ #[unstable(feature = "str_mut_extras", issue = "0")]
+ unsafe fn as_bytes_mut(&mut self) -> &mut [u8];
#[stable(feature = "core", since = "1.6.0")]
fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>;
#[stable(feature = "core", since = "1.6.0")]
unsafe { mem::transmute(self) }
}
+ #[inline]
+ unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
+ mem::transmute(self)
+ }
+
fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
pat.into_searcher(self).next_match().map(|(i, _)| i)
}
use session::{early_error, early_warn, Session};
use session::search_paths::SearchPaths;
-use rustc_back::PanicStrategy;
+use rustc_back::{LinkerFlavor, PanicStrategy};
use rustc_back::target::Target;
use lint;
use middle::cstore;
Some("either `panic` or `abort`");
pub const parse_sanitizer: Option<&'static str> =
Some("one of: `address`, `leak`, `memory` or `thread`");
+ pub const parse_linker_flavor: Option<&'static str> =
+ Some(::rustc_back::LinkerFlavor::one_of());
+ pub const parse_optimization_fuel: Option<&'static str> =
+ Some("crate=integer");
}
#[allow(dead_code)]
mod $mod_set {
use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer};
- use rustc_back::PanicStrategy;
+ use rustc_back::{LinkerFlavor, PanicStrategy};
$(
pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
}
true
}
+
+ fn parse_linker_flavor(slote: &mut Option<LinkerFlavor>, v: Option<&str>) -> bool {
+ match v.and_then(LinkerFlavor::from_str) {
+ Some(lf) => *slote = Some(lf),
+ _ => return false,
+ }
+ true
+ }
+
+ fn parse_optimization_fuel(slot: &mut Option<(String, u64)>, v: Option<&str>) -> bool {
+ match v {
+ None => false,
+ Some(s) => {
+ let parts = s.split('=').collect::<Vec<_>>();
+ if parts.len() != 2 { return false; }
+ let crate_name = parts[0].to_string();
+ let fuel = parts[1].parse::<u64>();
+ if fuel.is_err() { return false; }
+ *slot = Some((crate_name, fuel.unwrap()));
+ true
+ }
+ }
+ }
}
) }
"pass `-install_name @rpath/...` to the macOS linker"),
sanitizer: Option<Sanitizer> = (None, parse_sanitizer, [TRACKED],
"Use a sanitizer"),
+ linker_flavor: Option<LinkerFlavor> = (None, parse_linker_flavor, [UNTRACKED],
+ "Linker flavor"),
+ fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED],
+ "Set the optimization fuel quota for a crate."),
+ print_fuel: Option<String> = (None, parse_opt_string, [TRACKED],
+ "Make Rustc print the total optimization fuel used by a crate."),
}
pub fn default_lib_output() -> CrateType {
impl_dep_tracking_hash_via_hash!(bool);
impl_dep_tracking_hash_via_hash!(usize);
+ impl_dep_tracking_hash_via_hash!(u64);
impl_dep_tracking_hash_via_hash!(String);
impl_dep_tracking_hash_via_hash!(lint::Level);
impl_dep_tracking_hash_via_hash!(Option<bool>);
impl_dep_tracking_hash_via_hash!(Option<usize>);
impl_dep_tracking_hash_via_hash!(Option<String>);
+ impl_dep_tracking_hash_via_hash!(Option<(String, u64)>);
impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
impl_dep_tracking_hash_via_hash!(Option<PathBuf>);
impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level));
impl_dep_tracking_hash_for_sortable_vec_of!((String, Option<String>,
Option<cstore::NativeLibraryKind>));
+ impl_dep_tracking_hash_for_sortable_vec_of!((String, u64));
impl DepTrackingHash for SearchPaths {
fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) {
let mut elems: Vec<_> = self
use syntax::feature_gate::AttributeType;
use syntax_pos::{Span, MultiSpan};
-use rustc_back::PanicStrategy;
+use rustc_back::{LinkerFlavor, PanicStrategy};
use rustc_back::target::Target;
use rustc_data_structures::flock;
use llvm;
pub code_stats: RefCell<CodeStats>,
next_node_id: Cell<ast::NodeId>,
+
+ /// If -zfuel=crate=n is specified, Some(crate).
+ optimization_fuel_crate: Option<String>,
+ /// If -zfuel=crate=n is specified, initially set to n. Otherwise 0.
+ optimization_fuel_limit: Cell<u64>,
+ /// We're rejecting all further optimizations.
+ out_of_fuel: Cell<bool>,
+
+ // The next two are public because the driver needs to read them.
+
+ /// If -zprint-fuel=crate, Some(crate).
+ pub print_fuel_crate: Option<String>,
+ /// Always set to zero and incremented so that we can print fuel expended by a crate.
+ pub print_fuel: Cell<u64>,
}
pub struct PerfStats {
pub fn panic_strategy(&self) -> PanicStrategy {
self.opts.cg.panic.unwrap_or(self.target.target.options.panic_strategy)
}
+ pub fn linker_flavor(&self) -> LinkerFlavor {
+ self.opts.debugging_opts.linker_flavor.unwrap_or(self.target.target.linker_flavor)
+ }
pub fn no_landing_pads(&self) -> bool {
self.opts.debugging_opts.no_landing_pads || self.panic_strategy() == PanicStrategy::Abort
}
println!("Total time spent decoding DefPath tables: {}",
duration_to_secs_str(self.perf_stats.decode_def_path_tables_time.get()));
}
+
+ /// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n.
+ /// This expends fuel if applicable, and records fuel if applicable.
+ pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
+ let mut ret = true;
+ match self.optimization_fuel_crate {
+ Some(ref c) if c == crate_name => {
+ let fuel = self.optimization_fuel_limit.get();
+ ret = fuel != 0;
+ if fuel == 0 && !self.out_of_fuel.get() {
+ println!("optimization-fuel-exhausted: {}", msg());
+ self.out_of_fuel.set(true);
+ } else if fuel > 0 {
+ self.optimization_fuel_limit.set(fuel-1);
+ }
+ }
+ _ => {}
+ }
+ match self.print_fuel_crate {
+ Some(ref c) if c == crate_name=> {
+ self.print_fuel.set(self.print_fuel.get()+1);
+ },
+ _ => {}
+ }
+ ret
+ }
}
pub fn build_session(sopts: config::Options,
}
);
+ let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone());
+ let optimization_fuel_limit = Cell::new(sopts.debugging_opts.fuel.as_ref()
+ .map(|i| i.1).unwrap_or(0));
+ let print_fuel_crate = sopts.debugging_opts.print_fuel.clone();
+ let print_fuel = Cell::new(0);
+
let sess = Session {
dep_graph: dep_graph.clone(),
target: target_cfg,
decode_def_path_tables_time: Cell::new(Duration::from_secs(0)),
},
code_stats: RefCell::new(CodeStats::new()),
+ optimization_fuel_crate: optimization_fuel_crate,
+ optimization_fuel_limit: optimization_fuel_limit,
+ print_fuel_crate: print_fuel_crate,
+ print_fuel: print_fuel,
+ out_of_fuel: Cell::new(false),
};
init_llvm(&sess);
"the trait bound `{}` is not satisfied{}",
trait_ref.to_predicate(),
post_message);
- err.span_label(span,
- &format!("{}the trait `{}` is not \
- implemented for `{}`",
- pre_message,
- trait_ref,
- trait_ref.self_ty()));
// Try to report a help message
-
if !trait_ref.has_infer_types() &&
self.predicate_can_apply(trait_ref) {
// If a where-clause may be useful, remind the
// which is somewhat confusing.
err.help(&format!("consider adding a `where {}` bound",
trait_ref.to_predicate()));
- } else if let Some(s) = self.on_unimplemented_note(trait_ref,
- obligation) {
+ } else if let Some(s) = self.on_unimplemented_note(trait_ref, obligation) {
// If it has a custom "#[rustc_on_unimplemented]"
// error message, let's display it!
err.note(&s);
} else {
- // If we can't show anything useful, try to find
- // similar impls.
+ // Can't show anything else useful, try to find similar impls.
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
self.report_similar_impl_candidates(impl_candidates, &mut err);
}
+
+ err.span_label(span,
+ &format!("{}the trait `{}` is not implemented for `{}`",
+ pre_message,
+ trait_ref,
+ trait_ref.self_ty()));
err
}
suggested_limit));
}
}
+
ast_ty_to_ty_cache: RefCell::new(NodeMap()),
}, f)
}
+
+ pub fn consider_optimizing<T: Fn() -> String>(&self, msg: T) -> bool {
+ let cname = self.crate_name(LOCAL_CRATE).as_str();
+ self.sess.consider_optimizing(&cname, msg)
+ }
}
impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> {
}
impl<'a, 'gcx, 'tcx> Struct {
- // FIXME(camlorn): reprs need a better representation to deal with multiple reprs on one type.
fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>,
repr: &ReprOptions, kind: StructKind,
scapegoat: Ty<'gcx>) -> Result<Struct, LayoutError<'gcx>> {
// Neither do 1-member and 2-member structs.
// In addition, code in trans assume that 2-element structs can become pairs.
// It's easier to just short-circuit here.
- let mut can_optimize = (fields.len() > 2 || StructKind::EnumVariant == kind)
- && ! (repr.c || repr.packed);
-
- // Disable field reordering until we can decide what to do.
- // The odd pattern here avoids a warning about the value never being read.
- if can_optimize { can_optimize = false; }
+ let can_optimize = (fields.len() > 2 || StructKind::EnumVariant == kind)
+ && !(repr.c || repr.packed || repr.linear || repr.simd);
let (optimize, sort_ascending) = match kind {
StructKind::AlwaysSizedUnivariant => (can_optimize, false),
pub packed: bool,
pub simd: bool,
pub int: Option<attr::IntType>,
+ // Internal only for now. If true, don't reorder fields.
+ pub linear: bool,
}
impl_stable_hash_for!(struct ReprOptions {
c,
packed,
simd,
- int
+ int,
+ linear
});
impl ReprOptions {
ret.simd = true;
}
+ // This is here instead of layout because the choice must make it into metadata.
+ ret.linear = !tcx.consider_optimizing(|| format!("Reorder fields of {:?}",
+ tcx.item_path_str(did)));
ret
}
use serialize::json::{Json, ToJson};
+macro_rules! linker_flavor {
+ ($(($variant:ident, $string:expr),)+) => {
+ #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
+ RustcEncodable, RustcDecodable)]
+ pub enum LinkerFlavor {
+ $($variant,)+
+ }
+
+ impl LinkerFlavor {
+ pub const fn one_of() -> &'static str {
+ concat!("one of: ", $($string, " ",)+)
+ }
+
+ pub fn from_str(s: &str) -> Option<Self> {
+ Some(match s {
+ $($string => LinkerFlavor::$variant,)+
+ _ => return None,
+ })
+ }
+
+ pub fn desc(&self) -> &str {
+ match *self {
+ $(LinkerFlavor::$variant => $string,)+
+ }
+ }
+ }
+
+ impl ToJson for LinkerFlavor {
+ fn to_json(&self) -> Json {
+ self.desc().to_json()
+ }
+ }
+ }
+}
+
+linker_flavor! {
+ (Em, "em"),
+ (Gcc, "gcc"),
+ (Ld, "ld"),
+ (Msvc, "msvc"),
+}
+
#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
pub enum PanicStrategy {
Unwind,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
use super::apple_ios_base::{opts, Arch};
target_os: "ios".to_string(),
target_env: "".to_string(),
target_vendor: "apple".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
features: "+neon,+fp-armv8,+cyclone".to_string(),
eliminate_frame_pointer: false,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
// See https://developer.android.com/ndk/guides/abis.html#arm64-v8a
target_os: "android".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
abi_blacklist: super::arm_base::abi_blacklist(),
.. base
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "freebsd".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
abi_blacklist: super::arm_base::abi_blacklist(),
.. base
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "fuchsia".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
abi_blacklist: super::arm_base::abi_blacklist(),
.. base
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
arch: "aarch64".to_string(),
target_os: "linux".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
abi_blacklist: super::arm_base::abi_blacklist(),
.. base
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::TargetOptions;
pub fn opts() -> TargetOptions {
let mut base = super::linux_base::opts();
// Many of the symbols defined in compiler-rt are also defined in libgcc.
// Android's linker doesn't like that by default.
- base.pre_link_args.push("-Wl,--allow-multiple-definition".to_string());
+ base.pre_link_args
+ .get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,--allow-multiple-definition".to_string());
base.is_like_android = true;
base.position_independent_executables = true;
base.has_elf_tls = false;
use std::env;
-use target::TargetOptions;
+use target::{LinkArgs, TargetOptions};
pub fn opts() -> TargetOptions {
// ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6
dll_prefix: "lib".to_string(),
dll_suffix: ".dylib".to_string(),
archive_format: "bsd".to_string(),
- pre_link_args: Vec::new(),
+ pre_link_args: LinkArgs::new(),
exe_allocation_crate: super::maybe_jemalloc(),
has_elf_tls: version >= (10, 7),
.. Default::default()
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use std::io;
use std::process::Command;
-use target::TargetOptions;
+use target::{LinkArgs, TargetOptions};
use self::Arch::*;
}
}
-fn build_pre_link_args(arch: Arch) -> Result<Vec<String>, String> {
+fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {
let sdk_name = match arch {
Armv7 | Armv7s | Arm64 => "iphoneos",
I386 | X86_64 => "iphonesimulator"
let sdk_root = get_sdk_root(sdk_name)?;
- Ok(vec!["-arch".to_string(), arch_name.to_string(),
- "-Wl,-syslibroot".to_string(), sdk_root])
+ let mut args = LinkArgs::new();
+ args.insert(LinkerFlavor::Gcc,
+ vec!["-arch".to_string(),
+ arch_name.to_string(),
+ "-Wl,-syslibroot".to_string(),
+ sdk_root]);
+
+ Ok(args)
}
fn target_cpu(arch: Arch) -> String {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "android".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
abi_blacklist: super::arm_base::abi_blacklist(),
.. base
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
features: "+v6".to_string(),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
features: "+v6,+vfp2".to_string(),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "linux".to_string(),
target_env: "musl".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
abi_blacklist: super::arm_base::abi_blacklist(),
.. base
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "linux".to_string(),
target_env: "musl".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
abi_blacklist: super::arm_base::abi_blacklist(),
.. base
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
features: "+soft-float".to_string(),
}
})
}
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
use super::apple_ios_base::{opts, Arch};
target_os: "ios".to_string(),
target_env: "".to_string(),
target_vendor: "apple".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
features: "+v7,+vfp3,+neon".to_string(),
max_atomic_width: Some(64),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
// See https://developer.android.com/ndk/guides/abis.html#v7a
target_os: "android".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
abi_blacklist: super::arm_base::abi_blacklist(),
.. base
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
// Info about features at https://wiki.debian.org/ArmHardFloatPort
}
})
}
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "linux".to_string(),
target_env: "musl".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
abi_blacklist: super::arm_base::abi_blacklist(),
.. base
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
use super::apple_ios_base::{opts, Arch};
target_os: "ios".to_string(),
target_env: "".to_string(),
target_vendor: "apple".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
features: "+v7,+vfp4,+neon".to_string(),
max_atomic_width: Some(64),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use super::{Target, TargetOptions};
+use LinkerFlavor;
+use super::{LinkArgs, Target, TargetOptions};
use super::emscripten_base::{cmd};
pub fn target() -> Result<Target, String> {
+ let mut args = LinkArgs::new();
+ args.insert(LinkerFlavor::Em,
+ vec!["-s".to_string(),
+ "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]);
+
let opts = TargetOptions {
linker: cmd("emcc"),
ar: cmd("emar"),
obj_is_bitcode: true,
is_like_emscripten: true,
max_atomic_width: Some(32),
- post_link_args: vec!["-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()],
+ post_link_args: args,
target_family: Some("unix".to_string()),
.. Default::default()
};
target_vendor: "unknown".to_string(),
data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(),
arch: "asmjs".to_string(),
+ linker_flavor: LinkerFlavor::Em,
options: opts,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use target::TargetOptions;
+use LinkerFlavor;
+use target::{LinkArgs, TargetOptions};
use std::default::Default;
pub fn opts() -> TargetOptions {
+ let mut args = LinkArgs::new();
+ args.insert(LinkerFlavor::Gcc, vec![
+ // GNU-style linkers will use this to omit linking to libraries
+ // which don't actually fulfill any relocations, but only for
+ // libraries which follow this flag. Thus, use it before
+ // specifying libraries to link to.
+ "-Wl,--as-needed".to_string(),
+
+ // Always enable NX protection when it is available
+ "-Wl,-z,noexecstack".to_string(),
+ ]);
+
TargetOptions {
dynamic_linking: true,
executables: true,
target_family: Some("unix".to_string()),
linker_is_gnu: true,
has_rpath: true,
- pre_link_args: vec![
- // GNU-style linkers will use this to omit linking to libraries
- // which don't actually fulfill any relocations, but only for
- // libraries which follow this flag. Thus, use it before
- // specifying libraries to link to.
- "-Wl,--as-needed".to_string(),
-
- // Always enable NX protection when it is available
- "-Wl,-z,noexecstack".to_string(),
- ],
+ pre_link_args: args,
position_independent_executables: true,
exe_allocation_crate: super::maybe_jemalloc(),
.. Default::default()
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use target::TargetOptions;
+use LinkerFlavor;
+use target::{LinkArgs, TargetOptions};
use std::default::Default;
pub fn opts() -> TargetOptions {
+ let mut args = LinkArgs::new();
+ args.insert(LinkerFlavor::Gcc, vec![
+ // GNU-style linkers will use this to omit linking to libraries
+ // which don't actually fulfill any relocations, but only for
+ // libraries which follow this flag. Thus, use it before
+ // specifying libraries to link to.
+ "-Wl,--as-needed".to_string(),
+
+ // Always enable NX protection when it is available
+ "-Wl,-z,noexecstack".to_string(),
+ ]);
+
TargetOptions {
dynamic_linking: true,
executables: true,
target_family: Some("unix".to_string()),
linker_is_gnu: true,
has_rpath: true,
- pre_link_args: vec![
- // GNU-style linkers will use this to omit linking to libraries
- // which don't actually fulfill any relocations, but only for
- // libraries which follow this flag. Thus, use it before
- // specifying libraries to link to.
- "-Wl,--as-needed".to_string(),
-
- // Always enable NX protection when it is available
- "-Wl,-z,noexecstack".to_string(),
- ],
+ pre_link_args: args,
position_independent_executables: true,
exe_allocation_crate: super::maybe_jemalloc(),
.. Default::default()
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use target::TargetOptions;
+use LinkerFlavor;
+use target::{LinkArgs, TargetOptions};
use std::default::Default;
pub fn opts() -> TargetOptions {
+ let mut args = LinkArgs::new();
+ args.insert(LinkerFlavor::Gcc, vec![
+ // We want to be able to strip as much executable code as possible
+ // from the linker command line, and this flag indicates to the
+ // linker that it can avoid linking in dynamic libraries that don't
+ // actually satisfy any symbols up to that point (as with many other
+ // resolutions the linker does). This option only applies to all
+ // following libraries so we're sure to pass it as one of the first
+ // arguments.
+ // FIXME: figure out whether these linker args are desirable
+ //"-Wl,--as-needed".to_string(),
+
+ // Always enable NX protection when it is available
+ //"-Wl,-z,noexecstack".to_string(),
+ ]);
+
TargetOptions {
dynamic_linking: true,
executables: true,
target_family: Some("unix".to_string()),
linker_is_gnu: true,
has_rpath: true,
- pre_link_args: vec![
- // We want to be able to strip as much executable code as possible
- // from the linker command line, and this flag indicates to the
- // linker that it can avoid linking in dynamic libraries that don't
- // actually satisfy any symbols up to that point (as with many other
- // resolutions the linker does). This option only applies to all
- // following libraries so we're sure to pass it as one of the first
- // arguments.
- // FIXME: figure out whether these linker args are desirable
- //"-Wl,--as-needed".to_string(),
-
- // Always enable NX protection when it is available
- //"-Wl,-z,noexecstack".to_string(),
- ],
+ pre_link_args: args,
position_independent_executables: true,
exe_allocation_crate: "alloc_system".to_string(),
has_elf_tls: true,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
use super::apple_ios_base::{opts, Arch};
target_os: "ios".to_string(),
target_env: "".to_string(),
target_vendor: "apple".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
max_atomic_width: Some(64),
.. base
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::apple_base::opts();
base.cpu = "yonah".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m32".to_string());
+ base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]);
Ok(Target {
llvm_target: "i686-apple-darwin".to_string(),
target_os: "macos".to_string(),
target_env: "".to_string(),
target_vendor: "apple".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
// See https://developer.android.com/ndk/guides/abis.html#x86
target_os: "android".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
// Mark all dynamic libraries and executables as compatible with the larger 4GiB address
// space available to x86 Windows binaries on x86_64.
- base.pre_link_args.push("-Wl,--large-address-aware".to_string());
+ base.pre_link_args
+ .get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,--large-address-aware".to_string());
Ok(Target {
llvm_target: "i686-pc-windows-gnu".to_string(),
target_os: "windows".to_string(),
target_env: "gnu".to_string(),
target_vendor: "pc".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
// Mark all dynamic libraries and executables as compatible with the larger 4GiB address
// space available to x86 Windows binaries on x86_64.
- base.pre_link_args.push("/LARGEADDRESSAWARE".to_string());
+ base.pre_link_args
+ .get_mut(&LinkerFlavor::Msvc).unwrap().push("/LARGEADDRESSAWARE".to_string());
// Ensure the linker will only produce an image if it can also produce a table of
// the image's safe exception handlers.
// https://msdn.microsoft.com/en-us/library/9a89h429.aspx
- base.pre_link_args.push("/SAFESEH".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().push("/SAFESEH".to_string());
Ok(Target {
llvm_target: "i686-pc-windows-msvc".to_string(),
target_os: "windows".to_string(),
target_env: "msvc".to_string(),
target_vendor: "pc".to_string(),
+ linker_flavor: LinkerFlavor::Msvc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::dragonfly_base::opts();
base.cpu = "pentium4".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m32".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
Ok(Target {
llvm_target: "i686-unknown-dragonfly".to_string(),
target_os: "dragonfly".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::freebsd_base::opts();
base.cpu = "pentium4".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m32".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
Ok(Target {
llvm_target: "i686-unknown-freebsd".to_string(),
target_os: "freebsd".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::haiku_base::opts();
base.cpu = "pentium4".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m32".to_string());
+ base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]);
Ok(Target {
llvm_target: "i686-unknown-haiku".to_string(),
target_os: "haiku".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::linux_base::opts();
base.cpu = "pentium4".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m32".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
Ok(Target {
llvm_target: "i686-unknown-linux-gnu".to_string(),
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::linux_musl_base::opts();
base.cpu = "pentium4".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m32".to_string());
- base.pre_link_args.push("-Wl,-melf_i386".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,-melf_i386".to_string());
// The unwinder used by i686-unknown-linux-musl, the LLVM libunwind
// implementation, apparently relies on frame pointers existing... somehow.
target_os: "linux".to_string(),
target_env: "musl".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::netbsd_base::opts();
base.cpu = "pentium4".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m32".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
Ok(Target {
llvm_target: "i686-unknown-netbsdelf".to_string(),
target_os: "netbsd".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::openbsd_base::opts();
base.cpu = "pentium4".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m32".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
Ok(Target {
llvm_target: "i686-unknown-openbsd".to_string(),
target_os: "openbsd".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use super::{Target, TargetOptions, TargetResult};
+use LinkerFlavor;
+use super::{LinkArgs, Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
+ let mut pre_link_args = LinkArgs::new();
+ pre_link_args.insert(LinkerFlavor::Gcc,
+ vec!["--pnacl-exceptions=sjlj".to_string(),
+ "--target=le32-unknown-nacl".to_string(),
+ "-Wl,--start-group".to_string()]);
+ let mut post_link_args = LinkArgs::new();
+ post_link_args.insert(LinkerFlavor::Gcc,
+ vec!["-Wl,--end-group".to_string()]);
+
let opts = TargetOptions {
linker: "pnacl-clang".to_string(),
ar: "pnacl-ar".to_string(),
- pre_link_args: vec!["--pnacl-exceptions=sjlj".to_string(),
- "--target=le32-unknown-nacl".to_string(),
- "-Wl,--start-group".to_string()],
- post_link_args: vec!["-Wl,--end-group".to_string()],
+ pre_link_args: pre_link_args,
+ post_link_args: post_link_args,
dynamic_linking: false,
executables: true,
exe_suffix: ".pexe".to_string(),
target_vendor: "unknown".to_string(),
data_layout: "e-i64:64:64-p:32:32:32-v128:32:32".to_string(),
arch: "le32".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: opts,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use target::TargetOptions;
+use LinkerFlavor;
+use target::{LinkArgs, TargetOptions};
use std::default::Default;
pub fn opts() -> TargetOptions {
+ let mut args = LinkArgs::new();
+ args.insert(LinkerFlavor::Gcc, vec![
+ // We want to be able to strip as much executable code as possible
+ // from the linker command line, and this flag indicates to the
+ // linker that it can avoid linking in dynamic libraries that don't
+ // actually satisfy any symbols up to that point (as with many other
+ // resolutions the linker does). This option only applies to all
+ // following libraries so we're sure to pass it as one of the first
+ // arguments.
+ "-Wl,--as-needed".to_string(),
+
+ // Always enable NX protection when it is available
+ "-Wl,-z,noexecstack".to_string(),
+ ]);
+
TargetOptions {
dynamic_linking: true,
executables: true,
target_family: Some("unix".to_string()),
linker_is_gnu: true,
has_rpath: true,
- pre_link_args: vec![
- // We want to be able to strip as much executable code as possible
- // from the linker command line, and this flag indicates to the
- // linker that it can avoid linking in dynamic libraries that don't
- // actually satisfy any symbols up to that point (as with many other
- // resolutions the linker does). This option only applies to all
- // following libraries so we're sure to pass it as one of the first
- // arguments.
- "-Wl,--as-needed".to_string(),
-
- // Always enable NX protection when it is available
- "-Wl,-z,noexecstack".to_string(),
- ],
+ pre_link_args: args,
position_independent_executables: true,
exe_allocation_crate: super::maybe_jemalloc(),
has_elf_tls: true,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::TargetOptions;
pub fn opts() -> TargetOptions {
// Make sure that the linker/gcc really don't pull in anything, including
// default objects, libs, etc.
- base.pre_link_args.push("-nostdlib".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-nostdlib".to_string());
// At least when this was tested, the linker would not add the
// `GNU_EH_FRAME` program header to executables generated, which is required
// when unwinding to locate the unwinding information. I'm not sure why this
// argument is *not* necessary for normal builds, but it can't hurt!
- base.pre_link_args.push("-Wl,--eh-frame-hdr".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,--eh-frame-hdr".to_string());
// There's a whole bunch of circular dependencies when dealing with MUSL
// unfortunately. To put this in perspective libc is statically linked to
// link everything as a group, not stripping anything out until everything
// is processed. The linker will still perform a pass to strip out object
// files but it won't do so until all objects/archives have been processed.
- base.pre_link_args.push("-Wl,-(".to_string());
- base.post_link_args.push("-Wl,-)".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,-(".to_string());
+ base.post_link_args.insert(LinkerFlavor::Gcc, vec!["-Wl,-)".to_string()]);
// When generating a statically linked executable there's generally some
// small setup needed which is listed in these files. These are provided by
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
// NOTE(mips64r2) matches C toolchain
cpu: "mips64r2".to_string(),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
// NOTE(mips64r2) matches C toolchain
cpu: "mips64r2".to_string(),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
cpu: "mips32r2".to_string(),
features: "+mips32r2".to_string(),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "linux".to_string(),
target_env: "musl".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
cpu: "mips32r2".to_string(),
features: "+mips32r2,+soft-float".to_string(),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "linux".to_string(),
target_env: "uclibc".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
cpu: "mips32r2".to_string(),
features: "+mips32r2,+soft-float".to_string(),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
cpu: "mips32".to_string(),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "linux".to_string(),
target_env: "musl".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
cpu: "mips32".to_string(),
features: "+mips32,+soft-float".to_string(),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "linux".to_string(),
target_env: "uclibc".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
cpu: "mips32".to_string(),
use std::io::prelude::*;
use syntax::abi::{Abi, lookup as lookup_abi};
-use PanicStrategy;
+use {LinkerFlavor, PanicStrategy};
mod android_base;
mod apple_base;
mod fuchsia_base;
mod redox_base;
+pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<String>>;
pub type TargetResult = Result<Target, String>;
macro_rules! supported_targets {
pub arch: String,
/// [Data layout](http://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM.
pub data_layout: String,
+ /// Linker flavor
+ pub linker_flavor: LinkerFlavor,
/// Optional settings with defaults.
pub options: TargetOptions,
}
/// Linker arguments that are unconditionally passed *before* any
/// user-defined libraries.
- pub pre_link_args: Vec<String>,
+ pub pre_link_args: LinkArgs,
/// Objects to link before all others, always found within the
/// sysroot folder.
pub pre_link_objects_exe: Vec<String>, // ... when linking an executable
/// Linker arguments that are unconditionally passed after any
/// user-defined but before post_link_objects. Standard platform
/// libraries that should be always be linked to, usually go here.
- pub late_link_args: Vec<String>,
+ pub late_link_args: LinkArgs,
/// Objects to link after all others, always found within the
/// sysroot folder.
pub post_link_objects: Vec<String>,
/// Linker arguments that are unconditionally passed *after* any
/// user-defined libraries.
- pub post_link_args: Vec<String>,
+ pub post_link_args: LinkArgs,
/// Extra arguments to pass to the external assembler (when used)
pub asm_args: Vec<String>,
is_builtin: false,
linker: option_env!("CFG_DEFAULT_LINKER").unwrap_or("cc").to_string(),
ar: option_env!("CFG_DEFAULT_AR").unwrap_or("ar").to_string(),
- pre_link_args: Vec::new(),
- post_link_args: Vec::new(),
+ pre_link_args: LinkArgs::new(),
+ post_link_args: LinkArgs::new(),
asm_args: Vec::new(),
cpu: "generic".to_string(),
features: "".to_string(),
pre_link_objects_exe: Vec::new(),
pre_link_objects_dll: Vec::new(),
post_link_objects: Vec::new(),
- late_link_args: Vec::new(),
+ late_link_args: LinkArgs::new(),
archive_format: "gnu".to_string(),
custom_unwind_resume: false,
lib_allocation_crate: "alloc_system".to_string(),
target_os: get_req_field("os")?,
target_env: get_opt_field("env", ""),
target_vendor: get_opt_field("vendor", "unknown"),
+ linker_flavor: LinkerFlavor::from_str(&*get_req_field("linker-flavor")?)
+ .ok_or_else(|| {
+ format!("linker flavor must be {}", LinkerFlavor::one_of())
+ })?,
options: Default::default(),
};
.map(|s| s.to_string() );
}
} );
+ ($key_name:ident, LinkerFlavor) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ obj.find(&name[..]).and_then(|o| o.as_string().map(|s| {
+ LinkerFlavor::from_str(&s).ok_or_else(|| {
+ Err(format!("'{}' is not a valid value for linker-flavor. \
+ Use 'em', 'gcc', 'ld' or 'msvc.", s))
+ })
+ })).unwrap_or(Ok(()))
+ } );
+ ($key_name:ident, link_args) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ if let Some(obj) = obj.find(&name[..]).and_then(|o| o.as_object()) {
+ let mut args = LinkArgs::new();
+ for (k, v) in obj {
+ let k = LinkerFlavor::from_str(&k).ok_or_else(|| {
+ format!("{}: '{}' is not a valid value for linker-flavor. \
+ Use 'em', 'gcc', 'ld' or 'msvc'", name, k)
+ })?;
+
+ let v = v.as_array().map(|a| {
+ a
+ .iter()
+ .filter_map(|o| o.as_string())
+ .map(|s| s.to_owned())
+ .collect::<Vec<_>>()
+ }).unwrap_or(vec![]);
+
+ args.insert(k, v);
+ }
+ base.options.$key_name = args;
+ }
+ } );
}
key!(is_builtin, bool);
key!(linker);
key!(ar);
- key!(pre_link_args, list);
+ key!(pre_link_args, link_args);
key!(pre_link_objects_exe, list);
key!(pre_link_objects_dll, list);
- key!(late_link_args, list);
+ key!(late_link_args, link_args);
key!(post_link_objects, list);
- key!(post_link_args, list);
+ key!(post_link_args, link_args);
key!(asm_args, list);
key!(cpu);
key!(features);
d.insert(name.to_string(), self.options.$attr.to_json());
}
} );
+ (link_args - $attr:ident) => ( {
+ let name = (stringify!($attr)).replace("_", "-");
+ if default.$attr != self.options.$attr {
+ let obj = self.options.$attr
+ .iter()
+ .map(|(k, v)| (k.desc().to_owned(), v.clone()))
+ .collect::<BTreeMap<_, _>>();
+ d.insert(name.to_string(), obj.to_json());
+ }
+ } );
}
target_val!(llvm_target);
target_val!(target_os, "os");
target_val!(target_env, "env");
target_val!(target_vendor, "vendor");
- target_val!(arch);
target_val!(data_layout);
+ target_val!(linker_flavor);
target_option_val!(is_builtin);
target_option_val!(linker);
target_option_val!(ar);
- target_option_val!(pre_link_args);
+ target_option_val!(link_args - pre_link_args);
target_option_val!(pre_link_objects_exe);
target_option_val!(pre_link_objects_dll);
- target_option_val!(late_link_args);
+ target_option_val!(link_args - late_link_args);
target_option_val!(post_link_objects);
- target_option_val!(post_link_args);
+ target_option_val!(link_args - post_link_args);
target_option_val!(asm_args);
target_option_val!(cpu);
target_option_val!(features);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use target::TargetOptions;
+use LinkerFlavor;
+use target::{LinkArgs, TargetOptions};
use std::default::Default;
pub fn opts() -> TargetOptions {
+ let mut args = LinkArgs::new();
+ args.insert(LinkerFlavor::Gcc, vec![
+ // GNU-style linkers will use this to omit linking to libraries
+ // which don't actually fulfill any relocations, but only for
+ // libraries which follow this flag. Thus, use it before
+ // specifying libraries to link to.
+ "-Wl,--as-needed".to_string(),
+
+ // Always enable NX protection when it is available
+ "-Wl,-z,noexecstack".to_string(),
+ ]);
+
TargetOptions {
dynamic_linking: true,
executables: true,
target_family: Some("unix".to_string()),
linker_is_gnu: true,
has_rpath: true,
- pre_link_args: vec![
- // GNU-style linkers will use this to omit linking to libraries
- // which don't actually fulfill any relocations, but only for
- // libraries which follow this flag. Thus, use it before
- // specifying libraries to link to.
- "-Wl,--as-needed".to_string(),
-
- // Always enable NX protection when it is available
- "-Wl,-z,noexecstack".to_string(),
- ],
+ pre_link_args: args,
position_independent_executables: true,
.. Default::default()
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use target::TargetOptions;
+use LinkerFlavor;
+use target::{LinkArgs, TargetOptions};
use std::default::Default;
pub fn opts() -> TargetOptions {
+ let mut args = LinkArgs::new();
+ args.insert(LinkerFlavor::Gcc, vec![
+ // GNU-style linkers will use this to omit linking to libraries
+ // which don't actually fulfill any relocations, but only for
+ // libraries which follow this flag. Thus, use it before
+ // specifying libraries to link to.
+ "-Wl,--as-needed".to_string(),
+
+ // Always enable NX protection when it is available
+ "-Wl,-z,noexecstack".to_string(),
+ ]);
+
TargetOptions {
dynamic_linking: true,
executables: true,
linker_is_gnu: true,
has_rpath: true,
is_like_openbsd: true,
- pre_link_args: vec![
- // GNU-style linkers will use this to omit linking to libraries
- // which don't actually fulfill any relocations, but only for
- // libraries which follow this flag. Thus, use it before
- // specifying libraries to link to.
- "-Wl,--as-needed".to_string(),
-
- // Always enable NX protection when it is available
- "-Wl,-z,noexecstack".to_string(),
- ],
+ pre_link_args: args,
position_independent_executables: true,
exe_allocation_crate: "alloc_system".to_string(),
.. Default::default()
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::linux_base::opts();
base.cpu = "ppc64".to_string();
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
base.max_atomic_width = Some(64);
// see #36994
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::linux_base::opts();
base.cpu = "ppc64le".to_string();
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
base.max_atomic_width = Some(64);
// see #36994
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::linux_base::opts();
- base.pre_link_args.push("-m32".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
base.max_atomic_width = Some(32);
// see #36994
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use PanicStrategy;
-use target::TargetOptions;
+use {LinkerFlavor, PanicStrategy};
+use target::{LinkArgs, TargetOptions};
use std::default::Default;
pub fn opts() -> TargetOptions {
- TargetOptions {
- pre_link_args: vec![
- // We want to be able to strip as much executable code as possible
- // from the linker command line, and this flag indicates to the
- // linker that it can avoid linking in dynamic libraries that don't
- // actually satisfy any symbols up to that point (as with many other
- // resolutions the linker does). This option only applies to all
- // following libraries so we're sure to pass it as one of the first
- // arguments.
- "-Wl,--as-needed".to_string(),
+ let mut args = LinkArgs::new();
+ args.insert(LinkerFlavor::Gcc, vec![
+ // We want to be able to strip as much executable code as possible
+ // from the linker command line, and this flag indicates to the
+ // linker that it can avoid linking in dynamic libraries that don't
+ // actually satisfy any symbols up to that point (as with many other
+ // resolutions the linker does). This option only applies to all
+ // following libraries so we're sure to pass it as one of the first
+ // arguments.
+ "-Wl,--as-needed".to_string(),
+
+ // Always enable NX protection when it is available
+ "-Wl,-z,noexecstack".to_string()
+ ]);
- // Always enable NX protection when it is available
- "-Wl,-z,noexecstack".to_string()
- ],
+ TargetOptions {
+ pre_link_args: args,
executables: true,
relocation_model: "static".to_string(),
disable_redzone: true,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::netbsd_base::opts();
base.cpu = "v9".to_string();
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
base.max_atomic_width = Some(64);
Ok(Target {
target_os: "netbsd".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::solaris_base::opts();
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
// llvm calls this "v9"
base.cpu = "v9".to_string();
base.max_atomic_width = Some(64);
target_os: "solaris".to_string(),
target_env: "".to_string(),
target_vendor: "sun".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// Targets the Cortex-M0, Cortex-M0+ and Cortex-M1 processors (ARMv6-M architecture)
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "none".to_string(),
target_env: "".to_string(),
target_vendor: "".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
// The ARMv6-M architecture doesn't support unaligned loads/stores so we disable them
// To opt-in to hardware accelerated floating point operations, you can use, for example,
// `-C target-feature=+vfp4` or `-C target-cpu=cortex-m4`.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "none".to_string(),
target_env: "".to_string(),
target_vendor: "".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
max_atomic_width: Some(32),
//
// To opt into double precision hardware support, use the `-C target-feature=-fp-only-sp` flag.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "none".to_string(),
target_env: "".to_string(),
target_vendor: "".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
// `+vfp4` is the lowest common denominator between the Cortex-M4 (vfp4-16) and the
// Targets the Cortex-M3 processor (ARMv7-M)
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
target_os: "none".to_string(),
target_env: "".to_string(),
target_vendor: "".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
max_atomic_width: Some(32),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use super::{Target, TargetOptions};
+use LinkerFlavor;
+use super::{LinkArgs, Target, TargetOptions};
use super::emscripten_base::{cmd};
pub fn target() -> Result<Target, String> {
+ let mut post_link_args = LinkArgs::new();
+ post_link_args.insert(LinkerFlavor::Gcc,
+ vec!["-s".to_string(),
+ "BINARYEN=1".to_string(),
+ "-s".to_string(),
+ "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]);
+
let opts = TargetOptions {
linker: cmd("emcc"),
ar: cmd("emar"),
obj_is_bitcode: true,
is_like_emscripten: true,
max_atomic_width: Some(32),
- post_link_args: vec!["-s".to_string(), "BINARYEN=1".to_string(),
- "-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()],
+ post_link_args: post_link_args,
target_family: Some("unix".to_string()),
.. Default::default()
};
target_vendor: "unknown".to_string(),
data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(),
arch: "wasm32".to_string(),
+ linker_flavor: LinkerFlavor::Em,
options: opts,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use target::TargetOptions;
+use LinkerFlavor;
+use target::{LinkArgs, TargetOptions};
use std::default::Default;
pub fn opts() -> TargetOptions {
- TargetOptions {
- // FIXME(#13846) this should be enabled for windows
- function_sections: false,
- linker: "gcc".to_string(),
- dynamic_linking: true,
- executables: true,
- dll_prefix: "".to_string(),
- dll_suffix: ".dll".to_string(),
- exe_suffix: ".exe".to_string(),
- staticlib_prefix: "".to_string(),
- staticlib_suffix: ".lib".to_string(),
- no_default_libraries: true,
- target_family: Some("windows".to_string()),
- is_like_windows: true,
- allows_weak_linkage: false,
- pre_link_args: vec![
+ let mut pre_link_args = LinkArgs::new();
+ pre_link_args.insert(LinkerFlavor::Gcc, vec![
// And here, we see obscure linker flags #45. On windows, it has been
// found to be necessary to have this flag to compile liblibc.
//
// Do not use the standard system startup files or libraries when linking
"-nostdlib".to_string(),
- ],
+ ]);
+
+ let mut late_link_args = LinkArgs::new();
+ late_link_args.insert(LinkerFlavor::Gcc, vec![
+ "-lmingwex".to_string(),
+ "-lmingw32".to_string(),
+ "-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc
+ "-lmsvcrt".to_string(),
+ "-luser32".to_string(),
+ "-lkernel32".to_string(),
+ ]);
+
+ TargetOptions {
+ // FIXME(#13846) this should be enabled for windows
+ function_sections: false,
+ linker: "gcc".to_string(),
+ dynamic_linking: true,
+ executables: true,
+ dll_prefix: "".to_string(),
+ dll_suffix: ".dll".to_string(),
+ exe_suffix: ".exe".to_string(),
+ staticlib_prefix: "".to_string(),
+ staticlib_suffix: ".lib".to_string(),
+ no_default_libraries: true,
+ target_family: Some("windows".to_string()),
+ is_like_windows: true,
+ allows_weak_linkage: false,
+ pre_link_args: pre_link_args,
pre_link_objects_exe: vec![
"crt2.o".to_string(), // mingw C runtime initialization for executables
"rsbegin.o".to_string(), // Rust compiler runtime initialization, see rsbegin.rs
"dllcrt2.o".to_string(), // mingw C runtime initialization for dlls
"rsbegin.o".to_string(),
],
- late_link_args: vec![
- "-lmingwex".to_string(),
- "-lmingw32".to_string(),
- "-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc
- "-lmsvcrt".to_string(),
- "-luser32".to_string(),
- "-lkernel32".to_string(),
- ],
+ late_link_args: late_link_args,
post_link_objects: vec![
"rsend.o".to_string()
],
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use target::TargetOptions;
+use LinkerFlavor;
+use target::{LinkArgs, TargetOptions};
use std::default::Default;
pub fn opts() -> TargetOptions {
+ let mut args = LinkArgs::new();
+ args.insert(LinkerFlavor::Msvc,
+ vec!["/NOLOGO".to_string(),
+ "/NXCOMPAT".to_string()]);
+
TargetOptions {
function_sections: true,
linker: "link.exe".to_string(),
target_family: Some("windows".to_string()),
is_like_windows: true,
is_like_msvc: true,
- pre_link_args: vec![
- "/NOLOGO".to_string(),
- "/NXCOMPAT".to_string(),
- ],
+ pre_link_args: args,
exe_allocation_crate: "alloc_system".to_string(),
.. Default::default()
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
base.cpu = "core2".to_string();
base.max_atomic_width = Some(128); // core2 support cmpxchg16b
base.eliminate_frame_pointer = false;
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
Ok(Target {
llvm_target: "x86_64-apple-darwin".to_string(),
target_os: "macos".to_string(),
target_env: "".to_string(),
target_vendor: "apple".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetOptions, TargetResult};
use super::apple_ios_base::{opts, Arch};
target_os: "ios".to_string(),
target_env: "".to_string(),
target_vendor: "apple".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
max_atomic_width: Some(64),
.. base
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::windows_base::opts();
base.cpu = "x86-64".to_string();
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
base.max_atomic_width = Some(64);
Ok(Target {
target_os: "windows".to_string(),
target_env: "gnu".to_string(),
target_vendor: "pc".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
target_os: "windows".to_string(),
target_env: "msvc".to_string(),
target_vendor: "pc".to_string(),
+ linker_flavor: LinkerFlavor::Msvc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::netbsd_base::opts();
base.cpu = "x86-64".to_string();
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
base.linker = "x86_64-rumprun-netbsd-gcc".to_string();
base.ar = "x86_64-rumprun-netbsd-ar".to_string();
base.max_atomic_width = Some(64);
target_os: "netbsd".to_string(),
target_env: "".to_string(),
target_vendor: "rumprun".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::solaris_base::opts();
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
base.cpu = "x86-64".to_string();
base.max_atomic_width = Some(64);
target_os: "solaris".to_string(),
target_env: "".to_string(),
target_vendor: "sun".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::bitrig_base::opts();
base.cpu = "x86-64".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
Ok(Target {
llvm_target: "x86_64-unknown-bitrig".to_string(),
target_os: "bitrig".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::dragonfly_base::opts();
base.cpu = "x86-64".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
Ok(Target {
llvm_target: "x86_64-unknown-dragonfly".to_string(),
target_os: "dragonfly".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::freebsd_base::opts();
base.cpu = "x86-64".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
Ok(Target {
llvm_target: "x86_64-unknown-freebsd".to_string(),
target_os: "freebsd".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::fuchsia_base::opts();
base.cpu = "x86-64".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
Ok(Target {
llvm_target: "x86_64-unknown-fuchsia".to_string(),
target_os: "fuchsia".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::haiku_base::opts();
base.cpu = "x86-64".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
Ok(Target {
llvm_target: "x86_64-unknown-haiku".to_string(),
target_os: "haiku".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::linux_base::opts();
base.cpu = "x86-64".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
Ok(Target {
llvm_target: "x86_64-unknown-linux-gnu".to_string(),
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::linux_musl_base::opts();
base.cpu = "x86-64".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
Ok(Target {
llvm_target: "x86_64-unknown-linux-musl".to_string(),
target_os: "linux".to_string(),
target_env: "musl".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::netbsd_base::opts();
base.cpu = "x86-64".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
Ok(Target {
llvm_target: "x86_64-unknown-netbsd".to_string(),
target_os: "netbsd".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::openbsd_base::opts();
base.cpu = "x86-64".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
Ok(Target {
llvm_target: "x86_64-unknown-openbsd".to_string(),
target_os: "openbsd".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use LinkerFlavor;
use target::{Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::redox_base::opts();
base.cpu = "x86-64".to_string();
base.max_atomic_width = Some(64);
- base.pre_link_args.push("-m64".to_string());
+ base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
Ok(Target {
llvm_target: "x86_64-unknown-redox".to_string(),
target_os: "redox".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
use std::mem;
use std::collections::range::RangeArgument;
use std::collections::Bound::{Excluded, Included, Unbounded};
+use std::mem::ManuallyDrop;
pub unsafe trait Array {
type Element;
- type PartialStorage: Default + Unsize<[ManuallyDrop<Self::Element>]>;
+ type PartialStorage: Unsize<[ManuallyDrop<Self::Element>]>;
const LEN: usize;
}
pub fn new() -> Self {
ArrayVec {
count: 0,
- values: Default::default(),
+ values: unsafe { ::std::mem::uninitialized() },
}
}
/// Panics when the stack vector is full.
pub fn push(&mut self, el: A::Element) {
let arr = &mut self.values as &mut [ManuallyDrop<_>];
- arr[self.count] = ManuallyDrop { value: el };
+ arr[self.count] = ManuallyDrop::new(el);
self.count += 1;
}
let arr = &mut self.values as &mut [ManuallyDrop<_>];
self.count -= 1;
unsafe {
- let value = ptr::read(&arr[self.count]);
- Some(value.value)
+ let value = ptr::read(&*arr[self.count]);
+ Some(value)
}
} else {
None
fn next(&mut self) -> Option<A::Element> {
let arr = &self.store as &[ManuallyDrop<_>];
unsafe {
- self.indices.next().map(|i| ptr::read(&arr[i]).value)
+ self.indices.next().map(|i| ptr::read(&*arr[i]))
}
}
#[inline]
fn next(&mut self) -> Option<A::Element> {
- self.iter.next().map(|elt| unsafe { ptr::read(elt as *const ManuallyDrop<_>).value })
+ self.iter.next().map(|elt| unsafe { ptr::read(&**elt) })
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter_mut()
}
}
-
-// FIXME: This should use repr(transparent) from rust-lang/rfcs#1758.
-#[allow(unions_with_drop_fields)]
-pub union ManuallyDrop<T> {
- value: T,
- #[allow(dead_code)]
- empty: (),
-}
-
-impl<T> ManuallyDrop<T> {
- fn new() -> ManuallyDrop<T> {
- ManuallyDrop {
- empty: ()
- }
- }
-}
-
-impl<T> Default for ManuallyDrop<T> {
- fn default() -> Self {
- ManuallyDrop::new()
- }
-}
#![feature(conservative_impl_trait)]
#![feature(discriminant_value)]
#![feature(specialization)]
+#![feature(manually_drop)]
#![cfg_attr(unix, feature(libc))]
#![cfg_attr(test, feature(test))]
control.make_glob_map = resolve::MakeGlobMap::Yes;
}
+ if sess.print_fuel_crate.is_some() {
+ let old_callback = control.compilation_done.callback;
+ control.compilation_done.callback = box move |state| {
+ old_callback(state);
+ let sess = state.session;
+ println!("Fuel used by {}: {}",
+ sess.print_fuel_crate.as_ref().unwrap(),
+ sess.print_fuel.get());
+ }
+ }
control
}
}
outputs: &OutputFilenames,
tmpdir: &Path) {
info!("preparing {:?} from {:?} to {:?}", crate_type, objects, out_filename);
+ let flavor = sess.linker_flavor();
// The invocations of cc share some flags across platforms
let (pname, mut cmd, extra) = get_linker(sess);
cmd.env("PATH", command_path(sess, extra));
let root = sess.target_filesearch(PathKind::Native).get_lib_path();
- cmd.args(&sess.target.target.options.pre_link_args);
+ if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) {
+ cmd.args(args);
+ }
let pre_link_objects = if crate_type == config::CrateTypeExecutable {
&sess.target.target.options.pre_link_objects_exe
objects, out_filename, outputs, trans);
cmd = linker.finalize();
}
- cmd.args(&sess.target.target.options.late_link_args);
+ if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) {
+ cmd.args(args);
+ }
for obj in &sess.target.target.options.post_link_objects {
cmd.arg(root.join(obj));
}
- cmd.args(&sess.target.target.options.post_link_args);
+ if let Some(args) = sess.target.target.options.post_link_args.get(&flavor) {
+ cmd.args(args);
+ }
if sess.opts.debugging_opts.print_link_args {
println!("{:?}", &cmd);
// except according to those terms.
use std::collections::HashMap;
-use std::ffi::OsString;
+use std::ffi::{OsStr, OsString};
use std::fs::{self, File};
use std::io::prelude::*;
use std::io::{self, BufWriter};
use back::symbol_export::{self, ExportedSymbols};
use middle::dependency_format::Linkage;
use rustc::hir::def_id::{LOCAL_CRATE, CrateNum};
+use rustc_back::LinkerFlavor;
use session::Session;
use session::config::{self, CrateType, OptLevel, DebugInfoLevel};
use serialize::{json, Encoder};
pub fn to_linker(&'a self,
cmd: Command,
sess: &'a Session) -> Box<Linker+'a> {
- if sess.target.target.options.is_like_msvc {
- Box::new(MsvcLinker {
- cmd: cmd,
- sess: sess,
- info: self
- }) as Box<Linker>
- } else if sess.target.target.options.is_like_emscripten {
- Box::new(EmLinker {
- cmd: cmd,
- sess: sess,
- info: self
- }) as Box<Linker>
- } else {
- Box::new(GnuLinker {
- cmd: cmd,
- sess: sess,
- info: self,
- hinted_static: false,
- }) as Box<Linker>
+ match sess.linker_flavor() {
+ LinkerFlavor::Msvc => {
+ Box::new(MsvcLinker {
+ cmd: cmd,
+ sess: sess,
+ info: self
+ }) as Box<Linker>
+ }
+ LinkerFlavor::Em => {
+ Box::new(EmLinker {
+ cmd: cmd,
+ sess: sess,
+ info: self
+ }) as Box<Linker>
+ }
+ LinkerFlavor::Gcc => {
+ Box::new(GccLinker {
+ cmd: cmd,
+ sess: sess,
+ info: self,
+ hinted_static: false,
+ is_ld: false,
+ }) as Box<Linker>
+ }
+ LinkerFlavor::Ld => {
+ Box::new(GccLinker {
+ cmd: cmd,
+ sess: sess,
+ info: self,
+ hinted_static: false,
+ is_ld: true,
+ }) as Box<Linker>
+ }
}
}
}
fn finalize(&mut self) -> Command;
}
-pub struct GnuLinker<'a> {
+pub struct GccLinker<'a> {
cmd: Command,
sess: &'a Session,
info: &'a LinkerInfo,
hinted_static: bool, // Keeps track of the current hinting mode.
+ // Link as ld
+ is_ld: bool,
}
-impl<'a> GnuLinker<'a> {
+impl<'a> GccLinker<'a> {
+ /// Argument that must be passed *directly* to the linker
+ ///
+ /// These arguments need to be prepended with '-Wl,' when a gcc-style linker is used
+ fn linker_arg<S>(&mut self, arg: S) -> &mut Self
+ where S: AsRef<OsStr>
+ {
+ if !self.is_ld {
+ let mut os = OsString::from("-Wl,");
+ os.push(arg.as_ref());
+ self.cmd.arg(os);
+ } else {
+ self.cmd.arg(arg);
+ }
+ self
+ }
+
fn takes_hints(&self) -> bool {
!self.sess.target.target.options.is_like_osx
}
fn hint_static(&mut self) {
if !self.takes_hints() { return }
if !self.hinted_static {
- self.cmd.arg("-Wl,-Bstatic");
+ self.linker_arg("-Bstatic");
self.hinted_static = true;
}
}
fn hint_dynamic(&mut self) {
if !self.takes_hints() { return }
if self.hinted_static {
- self.cmd.arg("-Wl,-Bdynamic");
+ self.linker_arg("-Bdynamic");
self.hinted_static = false;
}
}
}
-impl<'a> Linker for GnuLinker<'a> {
+impl<'a> Linker for GccLinker<'a> {
fn link_dylib(&mut self, lib: &str) { self.hint_dynamic(); self.cmd.arg("-l").arg(lib); }
fn link_staticlib(&mut self, lib: &str) { self.hint_static(); self.cmd.arg("-l").arg(lib); }
fn link_rlib(&mut self, lib: &Path) { self.hint_static(); self.cmd.arg(lib); }
self.hint_static();
let target = &self.sess.target.target;
if !target.options.is_like_osx {
- self.cmd.arg("-Wl,--whole-archive")
- .arg("-l").arg(lib)
- .arg("-Wl,--no-whole-archive");
+ self.linker_arg("--whole-archive").cmd.arg("-l").arg(lib);
+ self.linker_arg("--no-whole-archive");
} else {
// -force_load is the macOS equivalent of --whole-archive, but it
// involves passing the full path to the library to link.
- let mut v = OsString::from("-Wl,-force_load,");
+ let mut v = OsString::from("-force_load,");
v.push(&archive::find_library(lib, search_path, &self.sess));
- self.cmd.arg(&v);
+ self.linker_arg(&v);
}
}
fn link_whole_rlib(&mut self, lib: &Path) {
self.hint_static();
if self.sess.target.target.options.is_like_osx {
- let mut v = OsString::from("-Wl,-force_load,");
+ let mut v = OsString::from("-force_load,");
v.push(lib);
- self.cmd.arg(&v);
+ self.linker_arg(&v);
} else {
- self.cmd.arg("-Wl,--whole-archive").arg(lib)
- .arg("-Wl,--no-whole-archive");
+ self.linker_arg("--whole-archive").cmd.arg(lib);
+ self.linker_arg("--no-whole-archive");
}
}
// for partial linking when using multiple codegen units (-r). So we
// insert it here.
if self.sess.target.target.options.is_like_osx {
- self.cmd.arg("-Wl,-dead_strip");
+ self.linker_arg("-dead_strip");
} else if self.sess.target.target.options.is_like_solaris {
- self.cmd.arg("-Wl,-z");
- self.cmd.arg("-Wl,ignore");
+ self.linker_arg("-z");
+ self.linker_arg("ignore");
// If we're building a dylib, we don't use --gc-sections because LLVM
// has already done the best it can do, and we also don't want to
// --gc-sections drops the size of hello world from 1.8MB to 597K, a 67%
// reduction.
} else if !keep_metadata {
- self.cmd.arg("-Wl,--gc-sections");
+ self.linker_arg("--gc-sections");
}
}
// need a numeric argument, but other linkers do.
if self.sess.opts.optimize == config::OptLevel::Default ||
self.sess.opts.optimize == config::OptLevel::Aggressive {
- self.cmd.arg("-Wl,-O1");
+ self.linker_arg("-O1");
}
}
}
fn no_default_libraries(&mut self) {
- self.cmd.arg("-nodefaultlibs");
+ if !self.is_ld {
+ self.cmd.arg("-nodefaultlibs");
+ }
}
fn build_dylib(&mut self, out_filename: &Path) {
// On mac we need to tell the linker to let this library be rpathed
if self.sess.target.target.options.is_like_osx {
- self.cmd.args(&["-dynamiclib", "-Wl,-dylib"]);
+ self.cmd.arg("-dynamiclib");
+ self.linker_arg("-dylib");
// Note that the `osx_rpath_install_name` option here is a hack
// purely to support rustbuild right now, we should get a more
// the right `-Wl,-install_name` with an `@rpath` in it.
if self.sess.opts.cg.rpath ||
self.sess.opts.debugging_opts.osx_rpath_install_name {
- let mut v = OsString::from("-Wl,-install_name,@rpath/");
+ let mut v = OsString::from("-install_name,@rpath/");
v.push(out_filename.file_name().unwrap());
- self.cmd.arg(&v);
+ self.linker_arg(&v);
}
} else {
self.cmd.arg("-shared");
}
if self.sess.target.target.options.is_like_osx {
- arg.push("-Wl,-exported_symbols_list,");
+ if !self.is_ld {
+ arg.push("-Wl,")
+ }
+ arg.push("-exported_symbols_list,");
} else if self.sess.target.target.options.is_like_solaris {
- arg.push("-Wl,-M,");
+ if !self.is_ld {
+ arg.push("-Wl,")
+ }
+ arg.push("-M,");
} else {
- arg.push("-Wl,--version-script=");
+ if !self.is_ld {
+ arg.push("-Wl,")
+ }
+ arg.push("--version-script=");
}
arg.push(&path);
}
fn subsystem(&mut self, subsystem: &str) {
- self.cmd.arg(&format!("-Wl,--subsystem,{}", subsystem));
+ self.linker_arg(&format!("--subsystem,{}", subsystem));
}
fn finalize(&mut self) -> Command {
use llvm::{ValueRef};
use abi::{Abi, FnType};
use adt;
-use mir::lvalue::LvalueRef;
+use mir::lvalue::{LvalueRef, Alignment};
use base::*;
use common::*;
use declare;
use std::cmp::Ordering;
use std::iter;
-use mir::lvalue::Alignment;
-
fn get_simple_intrinsic(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
let llvm_name = match name {
"sqrtf32" => "llvm.sqrt.f32",
C_nil(ccx)
}
// Effectively no-ops
- "uninit" | "forget" => {
+ "uninit" => {
C_nil(ccx)
}
"needs_drop" => {
for i in 0..elems.len() {
let val = bcx.extract_value(val, i);
- bcx.store(val, bcx.struct_gep(llresult, i), None);
+ let lval = LvalueRef::new_sized_ty(llresult, ret_ty,
+ Alignment::AbiAligned);
+ let (dest, align) = lval.trans_field_ptr(bcx, i);
+ bcx.store(val, dest, align.to_align());
}
C_nil(ccx)
}
let lvalue = LvalueRef::alloca(bcx, arg_ty, &format!("arg{}", arg_index));
for (i, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() {
- let dst = bcx.struct_gep(lvalue.llval, i);
+ let (dst, _) = lvalue.trans_field_ptr(bcx, i);
let arg = &mircx.fn_ty.args[idx];
idx += 1;
if common::type_is_fat_ptr(bcx.ccx, tupled_arg_ty) {
"rustc_peek" => (1, vec![param(0)], param(0)),
"init" => (1, Vec::new(), param(0)),
"uninit" => (1, Vec::new(), param(0)),
- "forget" => (1, vec![ param(0) ], tcx.mk_nil()),
"transmute" => (2, vec![ param(0) ], param(1)),
"move_val_init" => {
(1,
);
for token in tokens {
- match token {
+ match token.trim() {
"" => {},
- "should_panic" => { data.should_panic = true; seen_rust_tags = true; },
- "no_run" => { data.no_run = true; seen_rust_tags = true; },
- "ignore" => { data.ignore = true; seen_rust_tags = true; },
- "rust" => { data.rust = true; seen_rust_tags = true; },
- "test_harness" => { data.test_harness = true; seen_rust_tags = true; },
+ "should_panic" => {
+ data.should_panic = true;
+ seen_rust_tags = seen_other_tags == false;
+ }
+ "no_run" => { data.no_run = true; seen_rust_tags = !seen_other_tags; }
+ "ignore" => { data.ignore = true; seen_rust_tags = !seen_other_tags; }
+ "rust" => { data.rust = true; seen_rust_tags = true; }
+ "test_harness" => {
+ data.test_harness = true;
+ seen_rust_tags = !seen_other_tags || seen_rust_tags;
+ }
"compile_fail" if allow_compile_fail => {
data.compile_fail = true;
- seen_rust_tags = true;
+ seen_rust_tags = !seen_other_tags || seen_rust_tags;
data.no_run = true;
}
x if allow_error_code_check && x.starts_with("E") && x.len() == 5 => {
if let Ok(_) = x[1..].parse::<u32>() {
data.error_codes.push(x.to_owned());
- seen_rust_tags = true;
+ seen_rust_tags = !seen_other_tags || seen_rust_tags;
} else {
seen_other_tags = true;
}
t("test_harness", false, false, false, true, true, false, Vec::new());
t("compile_fail", false, true, false, true, false, true, Vec::new());
t("{.no_run .example}", false, true, false, true, false, false, Vec::new());
- t("{.sh .should_panic}", true, false, false, true, false, false, Vec::new());
+ t("{.sh .should_panic}", true, false, false, false, false, false, Vec::new());
t("{.example .rust}", false, false, false, true, false, false, Vec::new());
t("{.test_harness .rust}", false, false, false, true, true, false, Vec::new());
+ t("text, no_run", false, true, false, false, false, false, Vec::new());
+ t("text,no_run", false, true, false, false, false, false, Vec::new());
}
#[test]
#![stable(feature = "rust1", since = "1.0.0")]
use fmt;
-use mem;
use ops::Range;
use iter::FusedIterator;
}
fn make_ascii_uppercase(&mut self) {
- let me: &mut [u8] = unsafe { mem::transmute(self) };
+ let me = unsafe { self.as_bytes_mut() };
me.make_ascii_uppercase()
}
fn make_ascii_lowercase(&mut self) {
- let me: &mut [u8] = unsafe { mem::transmute(self) };
+ let me = unsafe { self.as_bytes_mut() };
me.make_ascii_lowercase()
}
#![feature(stmt_expr_attributes)]
#![feature(str_char)]
#![feature(str_internals)]
+#![feature(str_mut_extras)]
#![feature(str_utf16)]
#![feature(test, rustc_private)]
#![feature(thread_local)]
/// Arrays of sizes from 0 to 32 (inclusive) implement the following traits if
/// the element type allows it:
///
-/// - [`Clone`][clone] (only if `T: [Copy][copy]`)
+/// - [`Clone`][clone] (only if `T: `[`Copy`][copy])
/// - [`Debug`][debug]
/// - [`IntoIterator`][intoiterator] (implemented for `&[T; N]` and `&mut [T; N]`)
/// - [`PartialEq`][partialeq], [`PartialOrd`][partialord], [`Eq`][eq], [`Ord`][ord]
// Used to preserve symbols (see llvm.used)
(active, used, "1.18.0", Some(40289)),
+
+ // Hack to document `-Z linker-flavor` in The Unstable Book
+ (active, linker_flavor, "1.18.0", Some(41142)),
);
declare_features! (
} else {
label_sp
};
- err.span_label(sp, &label_exp);
- if !sp.source_equal(&self.span) {
+ if self.span.contains(sp) {
+ err.span_label(self.span, &label_exp);
+ } else {
+ err.span_label(sp, &label_exp);
err.span_label(self.span, &"unexpected token");
}
Err(err)
/// Returns a new span representing the next character after the end-point of this span
pub fn next_point(self) -> Span {
let lo = cmp::max(self.hi.0, self.lo.0 + 1);
- Span { lo: BytePos(lo), hi: BytePos(lo + 1), ..self }
+ Span { lo: BytePos(lo), hi: BytePos(lo), ..self }
}
/// Returns `self` if `self` is not the dummy span, and `other` otherwise.
--- /dev/null
+// Copyright 2017 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.
+
+// This is a fake compile fail test as there's no way to generate a
+// `#![feature(linker_flavor)]` error. The only reason we have a `linker_flavor`
+// feature gate is to be able to document `-Z linker-flavor` in the unstable
+// book
+
+#[used]
+fn foo() {}
+//~^^ ERROR the `#[used]` attribute is an experimental feature
+
+fn main() {}
#![feature(core_intrinsics)]
-use std::intrinsics::{init, forget};
+use std::intrinsics::{init};
// Test that the `forget` and `init` intrinsics are really unsafe
pub fn main() {
let stuff = init::<isize>(); //~ ERROR call to unsafe function requires unsafe
- forget(stuff); //~ ERROR call to unsafe function requires unsafe
}
+++ /dev/null
-// Copyright 2016 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(conservative_impl_trait, specialization)]
-
-trait Foo: Copy + ToString {}
-
-impl<T: Copy + ToString> Foo for T {}
-
-fn hide<T: Foo>(x: T) -> impl Foo {
- x
-}
-
-fn two(x: bool) -> impl Foo {
- if x {
- return 1_i32;
- }
- 0_u32
- //~^ ERROR mismatched types
- //~| expected i32, found u32
-}
-
-fn sum_to(n: u32) -> impl Foo {
- if n == 0 {
- 0
- } else {
- n + sum_to(n - 1)
- //~^ ERROR the trait bound `u32: std::ops::Add<impl Foo>` is not satisfied
- }
-}
-
-trait Leak: Sized {
- type T;
- fn leak(self) -> Self::T;
-}
-impl<T> Leak for T {
- default type T = ();
- default fn leak(self) -> Self::T { panic!() }
-}
-impl Leak for i32 {
- type T = i32;
- fn leak(self) -> i32 { self }
-}
-
-fn main() {
- let _: u32 = hide(0_u32);
- //~^ ERROR mismatched types
- //~| expected type `u32`
- //~| found type `impl Foo`
- //~| expected u32, found anonymized type
-
- let _: i32 = Leak::leak(hide(0_i32));
- //~^ ERROR mismatched types
- //~| expected type `i32`
- //~| found type `<impl Foo as Leak>::T`
- //~| expected i32, found associated type
-
- let mut x = (hide(0_u32), hide(0_i32));
- x = (x.1,
- //~^ ERROR mismatched types
- //~| expected u32, found i32
- x.0);
- //~^ ERROR mismatched types
- //~| expected i32, found u32
-}
{
"data-layout": "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128",
+ "linker-flavor": "gcc",
"llvm-target": "i686-unknown-linux-gnu",
"target-endian": "little",
"target-pointer-width": "32",
{
"data-layout": "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32",
+ "linker-flavor": "gcc",
"target-endian": "little",
"target-pointer-width": "32",
"arch": "x86",
{
"pre-link-args": ["-m64"],
"data-layout": "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128",
+ "linker-flavor": "gcc",
"llvm-target": "x86_64-unknown-linux-gnu",
"target-endian": "little",
"target-pointer-width": "64",
--- /dev/null
+// Copyright 2012 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.
+
+#![crate_name="foo"]
+
+use std::mem::size_of;
+
+// compile-flags: -Z fuel=foo=0
+
+struct S1(u8, u16, u8);
+struct S2(u8, u16, u8);
+
+fn main() {
+ assert_eq!(size_of::<S1>(), 6);
+ assert_eq!(size_of::<S2>(), 6);
+}
+
--- /dev/null
+// Copyright 2012 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.
+
+#![crate_name="foo"]
+
+use std::mem::size_of;
+
+// compile-flags: -Z fuel=foo=1
+
+struct S1(u8, u16, u8);
+struct S2(u8, u16, u8);
+
+fn main() {
+ let optimized = (size_of::<S1>() == 4) as usize
+ +(size_of::<S2>() == 4) as usize;
+ assert_eq!(optimized, 1);
+}
+
+
a([u16; 0], u8), b
}
+struct ReorderedStruct {
+ a: u8,
+ b: u16,
+ c: u8
+}
+
+enum ReorderedEnum {
+ A(u8, u16, u8),
+ B(u8, u16, u8),
+}
+
pub fn main() {
assert_eq!(size_of::<u8>(), 1 as usize);
assert_eq!(size_of::<u32>(), 4 as usize);
assert_eq!(size_of::<e1>(), 8 as usize);
assert_eq!(size_of::<e2>(), 8 as usize);
assert_eq!(size_of::<e3>(), 4 as usize);
+ assert_eq!(size_of::<ReorderedStruct>(), 4);
+ assert_eq!(size_of::<ReorderedEnum>(), 6);
}
--- /dev/null
+// Copyright 2016 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(conservative_impl_trait, specialization)]
+
+trait Foo: Copy + ToString {}
+
+impl<T: Copy + ToString> Foo for T {}
+
+fn hide<T: Foo>(x: T) -> impl Foo {
+ x
+}
+
+fn two(x: bool) -> impl Foo {
+ if x {
+ return 1_i32;
+ }
+ 0_u32
+ //~^ ERROR mismatched types
+ //~| expected i32, found u32
+}
+
+fn sum_to(n: u32) -> impl Foo {
+ if n == 0 {
+ 0
+ } else {
+ n + sum_to(n - 1)
+ //~^ ERROR no implementation for `u32 + impl Foo`
+ }
+}
+
+trait Leak: Sized {
+ type T;
+ fn leak(self) -> Self::T;
+}
+impl<T> Leak for T {
+ default type T = ();
+ default fn leak(self) -> Self::T { panic!() }
+}
+impl Leak for i32 {
+ type T = i32;
+ fn leak(self) -> i32 { self }
+}
+
+fn main() {
+ let _: u32 = hide(0_u32);
+ //~^ ERROR mismatched types
+ //~| expected type `u32`
+ //~| found type `impl Foo`
+ //~| expected u32, found anonymized type
+
+ let _: i32 = Leak::leak(hide(0_i32));
+ //~^ ERROR mismatched types
+ //~| expected type `i32`
+ //~| found type `<impl Foo as Leak>::T`
+ //~| expected i32, found associated type
+
+ let mut x = (hide(0_u32), hide(0_i32));
+ x = (x.1,
+ //~^ ERROR mismatched types
+ //~| expected u32, found i32
+ x.0);
+ //~^ ERROR mismatched types
+ //~| expected i32, found u32
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/equality.rs:25:5
+ |
+25 | 0_u32
+ | ^^^^^ expected i32, found u32
+ |
+ = note: expected type `i32`
+ found type `u32`
+
+error[E0277]: the trait bound `u32: std::ops::Add<impl Foo>` is not satisfied
+ --> $DIR/equality.rs:34:9
+ |
+34 | n + sum_to(n - 1)
+ | ^^^^^^^^^^^^^^^^^ the trait `std::ops::Add<impl Foo>` is not implemented for `u32`
+ |
+ = note: no implementation for `u32 + impl Foo`
+
+error[E0308]: mismatched types
+ --> $DIR/equality.rs:53:18
+ |
+53 | let _: u32 = hide(0_u32);
+ | ^^^^^^^^^^^ expected u32, found anonymized type
+ |
+ = note: expected type `u32`
+ found type `impl Foo`
+
+error[E0308]: mismatched types
+ --> $DIR/equality.rs:59:18
+ |
+59 | let _: i32 = Leak::leak(hide(0_i32));
+ | ^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found associated type
+ |
+ = note: expected type `i32`
+ found type `<impl Foo as Leak>::T`
+
+error[E0308]: mismatched types
+ --> $DIR/equality.rs:66:10
+ |
+66 | x = (x.1,
+ | ^^^ expected u32, found i32
+ |
+ = note: expected type `impl Foo` (u32)
+ found type `impl Foo` (i32)
+
+error[E0308]: mismatched types
+ --> $DIR/equality.rs:69:10
+ |
+69 | x.0);
+ | ^^^ expected i32, found u32
+ |
+ = note: expected type `impl Foo` (i32)
+ found type `impl Foo` (u32)
+
+error: aborting due to 6 previous errors
+
--- /dev/null
+// Copyright 2017 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.
+
+fn main() {
+ 1 + Some(1);
+ 2 as usize - Some(1);
+ 3 * ();
+ 4 / "";
+ 5 < String::new();
+ 6 == Ok(1);
+}
--- /dev/null
+error[E0277]: the trait bound `{integer}: std::ops::Add<std::option::Option<{integer}>>` is not satisfied
+ --> $DIR/binops.rs:12:5
+ |
+12 | 1 + Some(1);
+ | ^^^^^^^^^^^ the trait `std::ops::Add<std::option::Option<{integer}>>` is not implemented for `{integer}`
+ |
+ = note: no implementation for `{integer} + std::option::Option<{integer}>`
+
+error[E0277]: the trait bound `usize: std::ops::Sub<std::option::Option<{integer}>>` is not satisfied
+ --> $DIR/binops.rs:13:5
+ |
+13 | 2 as usize - Some(1);
+ | ^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Sub<std::option::Option<{integer}>>` is not implemented for `usize`
+ |
+ = note: no implementation for `usize - std::option::Option<{integer}>`
+
+error[E0277]: the trait bound `{integer}: std::ops::Mul<()>` is not satisfied
+ --> $DIR/binops.rs:14:5
+ |
+14 | 3 * ();
+ | ^^^^^^ the trait `std::ops::Mul<()>` is not implemented for `{integer}`
+ |
+ = note: no implementation for `{integer} * ()`
+
+error[E0277]: the trait bound `{integer}: std::ops::Div<&str>` is not satisfied
+ --> $DIR/binops.rs:15:5
+ |
+15 | 4 / "";
+ | ^^^^^^ the trait `std::ops::Div<&str>` is not implemented for `{integer}`
+ |
+ = note: no implementation for `{integer} / &str`
+
+error[E0277]: the trait bound `{integer}: std::cmp::PartialEq<std::string::String>` is not satisfied
+ --> $DIR/binops.rs:16:5
+ |
+16 | 5 < String::new();
+ | ^^^^^^^^^^^^^^^^^ the trait `std::cmp::PartialEq<std::string::String>` is not implemented for `{integer}`
+ |
+ = note: can't compare `{integer}` with `std::string::String`
+
+error[E0277]: the trait bound `{integer}: std::cmp::PartialOrd<std::string::String>` is not satisfied
+ --> $DIR/binops.rs:16:5
+ |
+16 | 5 < String::new();
+ | ^^^^^^^^^^^^^^^^^ the trait `std::cmp::PartialOrd<std::string::String>` is not implemented for `{integer}`
+ |
+ = note: can't compare `{integer}` with `std::string::String`
+
+error[E0277]: the trait bound `{integer}: std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not satisfied
+ --> $DIR/binops.rs:17:5
+ |
+17 | 6 == Ok(1);
+ | ^^^^^^^^^^ the trait `std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not implemented for `{integer}`
+ |
+ = note: can't compare `{integer}` with `std::result::Result<{integer}, _>`
+
+error: aborting due to 7 previous errors
+
--- /dev/null
+// Copyright 2016 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.
+
+#![crate_name="foo"]
+#![allow(dead_code)]
+
+// compile-flags: -Z print-fuel=foo
+
+struct S1(u8, u16, u8);
+struct S2(u8, u16, u8);
+struct S3(u8, u16, u8);
+
+fn main() {
+}
--- /dev/null
+Fuel used by foo: 3
-print-type-size type: `IndirectNonZero<u32>`: 20 bytes, alignment: 4 bytes
-print-type-size field `.pre`: 1 bytes
-print-type-size padding: 3 bytes
-print-type-size field `.nested`: 12 bytes, alignment: 4 bytes
+print-type-size type: `IndirectNonZero<u32>`: 12 bytes, alignment: 4 bytes
+print-type-size field `.nested`: 8 bytes
print-type-size field `.post`: 2 bytes
-print-type-size end padding: 2 bytes
-print-type-size type: `MyOption<IndirectNonZero<u32>>`: 20 bytes, alignment: 4 bytes
-print-type-size variant `Some`: 20 bytes
-print-type-size field `.0`: 20 bytes
-print-type-size type: `EmbeddedDiscr`: 12 bytes, alignment: 4 bytes
-print-type-size variant `Record`: 10 bytes
-print-type-size field `.pre`: 1 bytes
-print-type-size padding: 3 bytes
-print-type-size field `.val`: 4 bytes, alignment: 4 bytes
-print-type-size field `.post`: 2 bytes
-print-type-size end padding: 2 bytes
-print-type-size type: `NestedNonZero<u32>`: 12 bytes, alignment: 4 bytes
print-type-size field `.pre`: 1 bytes
-print-type-size padding: 3 bytes
-print-type-size field `.val`: 4 bytes, alignment: 4 bytes
+print-type-size end padding: 1 bytes
+print-type-size type: `MyOption<IndirectNonZero<u32>>`: 12 bytes, alignment: 4 bytes
+print-type-size variant `Some`: 12 bytes
+print-type-size field `.0`: 12 bytes
+print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes
+print-type-size variant `Record`: 7 bytes
+print-type-size field `.val`: 4 bytes
+print-type-size field `.post`: 2 bytes
+print-type-size field `.pre`: 1 bytes
+print-type-size end padding: 1 bytes
+print-type-size type: `NestedNonZero<u32>`: 8 bytes, alignment: 4 bytes
+print-type-size field `.val`: 4 bytes
print-type-size field `.post`: 2 bytes
-print-type-size end padding: 2 bytes
+print-type-size field `.pre`: 1 bytes
+print-type-size end padding: 1 bytes
print-type-size type: `MyOption<core::nonzero::NonZero<u32>>`: 4 bytes, alignment: 4 bytes
print-type-size variant `Some`: 4 bytes
print-type-size field `.0`: 4 bytes
-print-type-size type: `Padded`: 16 bytes, alignment: 4 bytes
+print-type-size type: `Padded`: 12 bytes, alignment: 4 bytes
+print-type-size field `.g`: 4 bytes
+print-type-size field `.h`: 2 bytes
print-type-size field `.a`: 1 bytes
print-type-size field `.b`: 1 bytes
-print-type-size padding: 2 bytes
-print-type-size field `.g`: 4 bytes, alignment: 4 bytes
print-type-size field `.c`: 1 bytes
-print-type-size padding: 1 bytes
-print-type-size field `.h`: 2 bytes, alignment: 2 bytes
print-type-size field `.d`: 1 bytes
-print-type-size end padding: 3 bytes
+print-type-size end padding: 2 bytes
print-type-size type: `Packed`: 10 bytes, alignment: 1 bytes
print-type-size field `.a`: 1 bytes
print-type-size field `.b`: 1 bytes
print-type-size type: `E1`: 12 bytes, alignment: 4 bytes
-print-type-size discriminant: 4 bytes
-print-type-size variant `A`: 5 bytes
-print-type-size field `.0`: 4 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `A`: 7 bytes
print-type-size field `.1`: 1 bytes
-print-type-size variant `B`: 8 bytes
-print-type-size field `.0`: 8 bytes
+print-type-size padding: 2 bytes
+print-type-size field `.0`: 4 bytes, alignment: 4 bytes
+print-type-size variant `B`: 11 bytes
+print-type-size padding: 3 bytes
+print-type-size field `.0`: 8 bytes, alignment: 4 bytes
print-type-size type: `E2`: 12 bytes, alignment: 4 bytes
print-type-size discriminant: 1 bytes
print-type-size variant `A`: 7 bytes
print-type-size padding: 3 bytes
print-type-size field `.0`: 8 bytes, alignment: 4 bytes
print-type-size type: `S`: 8 bytes, alignment: 4 bytes
+print-type-size field `.g`: 4 bytes
print-type-size field `.a`: 1 bytes
print-type-size field `.b`: 1 bytes
-print-type-size padding: 2 bytes
-print-type-size field `.g`: 4 bytes, alignment: 4 bytes
+print-type-size end padding: 2 bytes
27 | | y),
| |______________^ ...ending here: the trait `std::ops::Add<()>` is not implemented for `u32`
|
- = help: the following implementations were found:
- <u32 as std::ops::Add>
- <&'a u32 as std::ops::Add<u32>>
- <u32 as std::ops::Add<&'a u32>>
- <&'b u32 as std::ops::Add<&'a u32>>
+ = note: no implementation for `u32 + ()`
error: aborting due to previous error
--- /dev/null
+// Copyright 2017 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.
+
+impl S {
+ pub
+}
--- /dev/null
+error: expected one of `(`, `const`, `default`, `extern`, `fn`, `type`, or `unsafe`, found `}`
+ --> $DIR/issue-41155.rs:13:1
+ |
+12 | pub
+ | - expected one of 7 possible tokens here
+13 | }
+ | ^ unexpected token
+
+error: aborting due to previous error
+
extern crate toml;
extern crate rustc_serialize;
-use std::collections::{BTreeMap, HashMap};
+use std::collections::BTreeMap;
use std::env;
use std::fs::File;
use std::io::{self, Read, Write};
struct Manifest {
manifest_version: String,
date: String,
- pkg: HashMap<String, Package>,
+ pkg: BTreeMap<String, Package>,
}
#[derive(RustcEncodable)]
struct Package {
version: String,
- target: HashMap<String, Target>,
+ target: BTreeMap<String, Target>,
}
#[derive(RustcEncodable)]
input: PathBuf,
output: PathBuf,
gpg_passphrase: String,
- digests: HashMap<String, String>,
+ digests: BTreeMap<String, String>,
s3_address: String,
date: String,
rust_version: String,
input: input,
output: output,
gpg_passphrase: passphrase,
- digests: HashMap::new(),
+ digests: BTreeMap::new(),
s3_address: s3_address,
date: date,
rust_version: String::new(),
let mut manifest = Manifest {
manifest_version: "2".to_string(),
date: self.date.to_string(),
- pkg: HashMap::new(),
+ pkg: BTreeMap::new(),
};
self.package("rustc", &mut manifest.pkg, HOSTS);
let mut pkg = Package {
version: self.cached_version("rust").to_string(),
- target: HashMap::new(),
+ target: BTreeMap::new(),
};
for host in HOSTS {
let filename = self.filename("rust", host);
fn package(&mut self,
pkgname: &str,
- dst: &mut HashMap<String, Package>,
+ dst: &mut BTreeMap<String, Package>,
targets: &[&str]) {
let targets = targets.iter().map(|name| {
let filename = self.filename(pkgname, name);