]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #39724 - malbarbo:android, r=alexcrichton
authorCorey Farwell <coreyf@rwell.org>
Sat, 11 Feb 2017 04:41:39 +0000 (23:41 -0500)
committerGitHub <noreply@github.com>
Sat, 11 Feb 2017 04:41:39 +0000 (23:41 -0500)
Allow rustc data structures compile to android

flock structure is defined in asm*/fcntl.h. This file on android is
generated from the linux kernel source, so they are the same.

15 files changed:
RELEASES.md
src/Cargo.lock
src/liballoc/boxed.rs
src/liballoc/boxed_test.rs
src/libcollections/vec.rs
src/libcore/iter/iterator.rs
src/librustc_trans/Cargo.toml
src/librustc_trans/back/link.rs
src/librustc_trans/back/linker.rs
src/librustc_trans/lib.rs
src/libstd/lib.rs
src/libstd/panicking.rs
src/test/run-pass/catch-unwind-bang.rs [new file with mode: 0644]
src/test/run-pass/dst-field-align.rs
src/tools/build-manifest/src/main.rs

index 2df1a83db81ffb3a5fa806a3ffd44863e582ae3b..1de44ef7e6d0546dd024f5a7e0eaf1e6bc232528 100644 (file)
@@ -1,9 +1,11 @@
-Version 1.15.1 (2017-02-08)
+Version 1.15.1 (2017-02-09)
 ===========================
 
 * [Fix IntoIter::as_mut_slice's signature][39466]
+* [Compile compiler builtins with `-fPIC` on 32-bit platforms][39523]
 
 [39466]: https://github.com/rust-lang/rust/pull/39466
+[39523]: https://github.com/rust-lang/rust/pull/39523
 
 
 Version 1.15.0 (2017-02-02)
index 09aefd45e94c88964ce6bdcd1515c6f9dc5b2460..219ed5d6bc281ba86d120e3c415b705bf5cc7639 100644 (file)
@@ -551,6 +551,7 @@ dependencies = [
  "rustc_incremental 0.0.0",
  "rustc_llvm 0.0.0",
  "rustc_platform_intrinsics 0.0.0",
+ "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
index 82d361fb0e853064ffa317b66e582f36f87b6660..ac9439974a491c9d634c9ff461355b8b4218c6e7 100644 (file)
@@ -419,6 +419,23 @@ fn from(t: T) -> Self {
     }
 }
 
+#[stable(feature = "box_from_slice", since = "1.17.0")]
+impl<'a, T: Copy> From<&'a [T]> for Box<[T]> {
+    fn from(slice: &'a [T]) -> Box<[T]> {
+        let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() };
+        boxed.copy_from_slice(slice);
+        boxed
+    }
+}
+
+#[stable(feature = "box_from_slice", since = "1.17.0")]
+impl<'a> From<&'a str> for Box<str> {
+    fn from(s: &'a str) -> Box<str> {
+        let boxed: Box<[u8]> = Box::from(s.as_bytes());
+        unsafe { mem::transmute(boxed) }
+    }
+}
+
 impl Box<Any> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
index 8d68ce3c1f6e2ebfa406c81a15cb50c478df4139..837f8dfaca13a52ecddab5f7dd9b6114a8a75ae5 100644 (file)
@@ -14,6 +14,8 @@
 use core::ops::Deref;
 use core::result::Result::{Err, Ok};
 use core::clone::Clone;
+use core::f64;
+use core::i64;
 
 use std::boxed::Box;
 
@@ -117,3 +119,24 @@ fn set(&mut self, value: u32) {
         assert_eq!(19, y.get());
     }
 }
+
+#[test]
+fn f64_slice() {
+    let slice: &[f64] = &[-1.0, 0.0, 1.0, f64::INFINITY];
+    let boxed: Box<[f64]> = Box::from(slice);
+    assert_eq!(&*boxed, slice)
+}
+
+#[test]
+fn i64_slice() {
+    let slice: &[i64] = &[i64::MIN, -2, -1, 0, 1, 2, i64::MAX];
+    let boxed: Box<[i64]> = Box::from(slice);
+    assert_eq!(&*boxed, slice)
+}
+
+#[test]
+fn str_slice() {
+    let s = "Hello, world!";
+    let boxed: Box<str> = Box::from(s);
+    assert_eq!(&*boxed, s)
+}
index dc0f33d9bc3e00d82e0ca9a5d92d835050bc218a..3873b3535a07b5bacc8d61e3091ea2faf5ff4bef 100644 (file)
@@ -437,7 +437,9 @@ pub fn capacity(&self) -> usize {
 
     /// Reserves capacity for at least `additional` more elements to be inserted
     /// in the given `Vec<T>`. The collection may reserve more space to avoid
-    /// frequent reallocations.
+    /// frequent reallocations. After calling `reserve`, capacity will be
+    /// greater than or equal to `self.len() + additional`. Does nothing if
+    /// capacity is already sufficient.
     ///
     /// # Panics
     ///
@@ -456,8 +458,9 @@ pub fn reserve(&mut self, additional: usize) {
     }
 
     /// Reserves the minimum capacity for exactly `additional` more elements to
-    /// be inserted in the given `Vec<T>`. Does nothing if the capacity is already
-    /// sufficient.
+    /// be inserted in the given `Vec<T>`. After calling `reserve_exact`,
+    /// capacity will be greater than or equal to `self.len() + additional`.
+    /// Does nothing if the capacity is already sufficient.
     ///
     /// Note that the allocator may give the collection more space than it
     /// requests. Therefore capacity can not be relied upon to be precisely
index 3b406873d4b191b63fc2d5a71cc416fd884d4606..d41767cce18fe9ef2710217bc3e9650484fa9eb9 100644 (file)
@@ -209,11 +209,14 @@ fn last(self) -> Option<Self::Item> where Self: Sized {
 
     /// Returns the `n`th element of the iterator.
     ///
-    /// Note that all preceding elements will be consumed (i.e. discarded).
-    ///
     /// Like most indexing operations, the count starts from zero, so `nth(0)`
     /// returns the first value, `nth(1)` the second, and so on.
     ///
+    /// Note that all preceding elements, as well as the returned element, will be
+    /// consumed from the iterator. That means that the preceding elements will be
+    /// discarded, and also that calling `nth(0)` multiple times on the same iterator
+    /// will return different elements.
+    ///
     /// `nth()` will return [`None`] if `n` is greater than or equal to the length of the
     /// iterator.
     ///
index fa48a63b6b8f5865350fd879a18523de28c22fc4..b5c67ad998b69e4ea448eebe5cca0e99078b42f8 100644 (file)
@@ -22,5 +22,6 @@ rustc_errors = { path = "../librustc_errors" }
 rustc_incremental = { path = "../librustc_incremental" }
 rustc_llvm = { path = "../librustc_llvm" }
 rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
+serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
index 9d48dc523d3a7f4c2321a9ce09521aa2937fa06b..1da9fcb0e95e437cd4dd614b149ebae102a790b9 100644 (file)
@@ -722,9 +722,13 @@ fn link_natively(sess: &Session,
         cmd.arg(root.join(obj));
     }
 
-    if sess.target.target.options.is_like_emscripten &&
-       sess.panic_strategy() == PanicStrategy::Abort {
-        cmd.args(&["-s", "DISABLE_EXCEPTION_CATCHING=1"]);
+    if sess.target.target.options.is_like_emscripten {
+        cmd.arg("-s");
+        cmd.arg(if sess.panic_strategy() == PanicStrategy::Abort {
+            "DISABLE_EXCEPTION_CATCHING=1"
+        } else {
+            "DISABLE_EXCEPTION_CATCHING=0"
+        });
     }
 
     {
@@ -830,7 +834,8 @@ fn link_args(cmd: &mut Linker,
 
     // If we're building a dynamic library then some platforms need to make sure
     // that all symbols are exported correctly from the dynamic library.
-    if crate_type != config::CrateTypeExecutable {
+    if crate_type != config::CrateTypeExecutable ||
+       sess.target.target.options.is_like_emscripten {
         cmd.export_symbols(tmpdir, crate_type);
     }
 
index 7f352f1da517d215215c740b0d82286a05f0724d..830d1d0d3a5586fddba895d70551857381dd17eb 100644 (file)
@@ -23,8 +23,8 @@
 use middle::dependency_format::Linkage;
 use rustc::hir::def_id::{LOCAL_CRATE, CrateNum};
 use session::Session;
-use session::config::CrateType;
-use session::config;
+use session::config::{self, CrateType, OptLevel, DebugInfoLevel};
+use serialize::{json, Encoder};
 
 /// For all the linkers we support, and information they might
 /// need out of the shared crate context before we get rid of it.
@@ -51,6 +51,12 @@ pub fn to_linker(&'a self,
                 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,
@@ -488,6 +494,154 @@ fn subsystem(&mut self, subsystem: &str) {
     }
 }
 
+pub struct EmLinker<'a> {
+    cmd: &'a mut Command,
+    sess: &'a Session,
+    info: &'a LinkerInfo
+}
+
+impl<'a> Linker for EmLinker<'a> {
+    fn include_path(&mut self, path: &Path) {
+        self.cmd.arg("-L").arg(path);
+    }
+
+    fn link_staticlib(&mut self, lib: &str) {
+        self.cmd.arg("-l").arg(lib);
+    }
+
+    fn output_filename(&mut self, path: &Path) {
+        self.cmd.arg("-o").arg(path);
+    }
+
+    fn add_object(&mut self, path: &Path) {
+        self.cmd.arg(path);
+    }
+
+    fn link_dylib(&mut self, lib: &str) {
+        // Emscripten always links statically
+        self.link_staticlib(lib);
+    }
+
+    fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) {
+        // not supported?
+        self.link_staticlib(lib);
+    }
+
+    fn link_whole_rlib(&mut self, lib: &Path) {
+        // not supported?
+        self.link_rlib(lib);
+    }
+
+    fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
+        self.link_dylib(lib);
+    }
+
+    fn link_rlib(&mut self, lib: &Path) {
+        self.add_object(lib);
+    }
+
+    fn position_independent_executable(&mut self) {
+        // noop
+    }
+
+    fn args(&mut self, args: &[String]) {
+        self.cmd.args(args);
+    }
+
+    fn framework_path(&mut self, _path: &Path) {
+        bug!("frameworks are not supported on Emscripten")
+    }
+
+    fn link_framework(&mut self, _framework: &str) {
+        bug!("frameworks are not supported on Emscripten")
+    }
+
+    fn gc_sections(&mut self, _keep_metadata: bool) {
+        // noop
+    }
+
+    fn optimize(&mut self) {
+        // Emscripten performs own optimizations
+        self.cmd.arg(match self.sess.opts.optimize {
+            OptLevel::No => "-O0",
+            OptLevel::Less => "-O1",
+            OptLevel::Default => "-O2",
+            OptLevel::Aggressive => "-O3",
+            OptLevel::Size => "-Os",
+            OptLevel::SizeMin => "-Oz"
+        });
+        // Unusable until https://github.com/rust-lang/rust/issues/38454 is resolved
+        self.cmd.args(&["--memory-init-file", "0"]);
+    }
+
+    fn debuginfo(&mut self) {
+        // Preserve names or generate source maps depending on debug info
+        self.cmd.arg(match self.sess.opts.debuginfo {
+            DebugInfoLevel::NoDebugInfo => "-g0",
+            DebugInfoLevel::LimitedDebugInfo => "-g3",
+            DebugInfoLevel::FullDebugInfo => "-g4"
+        });
+    }
+
+    fn no_default_libraries(&mut self) {
+        self.cmd.args(&["-s", "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]"]);
+    }
+
+    fn build_dylib(&mut self, _out_filename: &Path) {
+        bug!("building dynamic library is unsupported on Emscripten")
+    }
+
+    fn whole_archives(&mut self) {
+        // noop
+    }
+
+    fn no_whole_archives(&mut self) {
+        // noop
+    }
+
+    fn hint_static(&mut self) {
+        // noop
+    }
+
+    fn hint_dynamic(&mut self) {
+        // noop
+    }
+
+    fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
+        let symbols = &self.info.exports[&crate_type];
+
+        debug!("EXPORTED SYMBOLS:");
+
+        self.cmd.arg("-s");
+
+        let mut arg = OsString::from("EXPORTED_FUNCTIONS=");
+        let mut encoded = String::new();
+
+        {
+            let mut encoder = json::Encoder::new(&mut encoded);
+            let res = encoder.emit_seq(symbols.len(), |encoder| {
+                for (i, sym) in symbols.iter().enumerate() {
+                    encoder.emit_seq_elt(i, |encoder| {
+                        encoder.emit_str(&("_".to_string() + sym))
+                    })?;
+                }
+                Ok(())
+            });
+            if let Err(e) = res {
+                self.sess.fatal(&format!("failed to encode exported symbols: {}", e));
+            }
+        }
+        debug!("{}", encoded);
+        arg.push(encoded);
+
+        self.cmd.arg(arg);
+    }
+
+    fn subsystem(&mut self, _subsystem: &str) {
+        // noop
+    }
+}
+
 fn exported_symbols(scx: &SharedCrateContext,
                     exported_symbols: &ExportedSymbols,
                     crate_type: CrateType)
index 21c92cb4a4ad2329b5f06f558012a9db69fa1a05..1530fcda3d3ea19c5415d17983fd47220de6928a 100644 (file)
@@ -59,6 +59,7 @@
 #[macro_use] extern crate syntax;
 extern crate syntax_pos;
 extern crate rustc_errors as errors;
+extern crate serialize;
 
 pub use rustc::session;
 pub use rustc::middle;
index 3a552c060a9b9066d0031e1007213b15561184e4..070690773b6c4792a05dc525ce790c9d1cdc72ce 100644 (file)
 #![feature(unboxed_closures)]
 #![feature(unicode)]
 #![feature(unique)]
+#![feature(untagged_unions)]
 #![feature(unwind_attributes)]
 #![feature(vec_push_all)]
 #![feature(zero_one)]
index d76e8816ca45f3932b37baf92a35fcdf8fca5028..3fba49345e63d1e5ee34cf8f63cc483f44492353 100644 (file)
@@ -389,28 +389,23 @@ pub fn update_panic_count(amt: isize) -> usize {
 
 /// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
 pub unsafe fn try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<Any + Send>> {
-    struct Data<F, R> {
+    #[allow(unions_with_drop_fields)]
+    union Data<F, R> {
         f: F,
         r: R,
     }
 
     // We do some sketchy operations with ownership here for the sake of
-    // performance. The `Data` structure is never actually fully valid, but
-    // instead it always contains at least one uninitialized field. We can only
-    // pass pointers down to `__rust_maybe_catch_panic` (can't pass objects by
-    // value), so we do all the ownership tracking here manully.
+    // performance. We can only  pass pointers down to
+    // `__rust_maybe_catch_panic` (can't pass objects by value), so we do all
+    // the ownership tracking here manually using a union.
     //
-    // Note that this is all invalid if any of these functions unwind, but the
-    // whole point of this function is to prevent that! As a result we go
-    // through a transition where:
+    // We go through a transition where:
     //
-    // * First, only the closure we're going to call is initialized. The return
-    //   value is uninitialized.
+    // * First, we set the data to be the closure that we're going to call.
     // * When we make the function call, the `do_call` function below, we take
-    //   ownership of the function pointer, replacing it with uninitialized
-    //   data. At this point the `Data` structure is entirely uninitialized, but
-    //   it won't drop due to an unwind because it's owned on the other side of
-    //   the catch panic.
+    //   ownership of the function pointer. At this point the `Data` union is
+    //   entirely uninitialized.
     // * If the closure successfully returns, we write the return value into the
     //   data's return slot. Note that `ptr::write` is used as it's overwriting
     //   uninitialized data.
@@ -418,11 +413,10 @@ struct Data<F, R> {
     //   in one of two states:
     //
     //      1. The closure didn't panic, in which case the return value was
-    //         filled in. We have to be careful to `forget` the closure,
-    //         however, as ownership was passed to the `do_call` function.
+    //         filled in. We move it out of `data` and return it.
     //      2. The closure panicked, in which case the return value wasn't
-    //         filled in. In this case the entire `data` structure is invalid,
-    //         so we forget the entire thing.
+    //         filled in. In this case the entire `data` union is invalid, so
+    //         there is no need to drop anything.
     //
     // Once we stack all that together we should have the "most efficient'
     // method of calling a catch panic whilst juggling ownership.
@@ -430,7 +424,6 @@ struct Data<F, R> {
     let mut any_vtable = 0;
     let mut data = Data {
         f: f,
-        r: mem::uninitialized(),
     };
 
     let r = __rust_maybe_catch_panic(do_call::<F, R>,
@@ -439,12 +432,9 @@ struct Data<F, R> {
                                      &mut any_vtable);
 
     return if r == 0 {
-        let Data { f, r } = data;
-        mem::forget(f);
         debug_assert!(update_panic_count(0) == 0);
-        Ok(r)
+        Ok(data.r)
     } else {
-        mem::forget(data);
         update_panic_count(-1);
         debug_assert!(update_panic_count(0) == 0);
         Err(mem::transmute(raw::TraitObject {
diff --git a/src/test/run-pass/catch-unwind-bang.rs b/src/test/run-pass/catch-unwind-bang.rs
new file mode 100644 (file)
index 0000000..df54ec9
--- /dev/null
@@ -0,0 +1,17 @@
+// 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 worker() -> ! {
+    panic!()
+}
+
+fn main() {
+    std::panic::catch_unwind(worker).unwrap_err();
+}
index cf2acfe986c2155b4276613b65882ece9bf5770d..c36833f2fb6271862f25fade4e7988edd6779265 100644 (file)
@@ -25,12 +25,6 @@ struct Baz<T: ?Sized> {
     a: T
 }
 
-#[repr(packed)]
-struct Packed<T: ?Sized> {
-    a: u8,
-    b: T
-}
-
 struct HasDrop<T: ?Sized> {
     ptr: Box<usize>,
     data: T
@@ -55,12 +49,6 @@ fn main() {
     // The pointers should be the same
     assert_eq!(ptr1, ptr2);
 
-    // Test that packed structs are handled correctly
-    let p : Packed<usize> = Packed { a: 0, b: 13 };
-    assert_eq!(p.b.get(), 13);
-    let p : &Packed<Bar> = &p;
-    assert_eq!(p.b.get(), 13);
-
     // Test that nested DSTs work properly
     let f : Foo<Foo<usize>> = Foo { a: 0, b: Foo { a: 1, b: 17 }};
     assert_eq!(f.b.b.get(), 17);
index 2a24edd4e3f330633b05a87d2ac32091c3a340ff..991cd02d215dcdfd782c6216e2c88a61bc28edc5 100644 (file)
@@ -179,8 +179,8 @@ fn build(&mut self) {
         // and wrap it up in a `Value::Table`.
         let mut manifest = BTreeMap::new();
         manifest.insert("manifest-version".to_string(),
-                        toml::encode(&manifest_version));
-        manifest.insert("date".to_string(), toml::encode(&date));
+                        toml::Value::String(manifest_version));
+        manifest.insert("date".to_string(), toml::Value::String(date));
         manifest.insert("pkg".to_string(), toml::encode(&pkg));
         let manifest = toml::Value::Table(manifest).to_string();
 
@@ -362,7 +362,8 @@ fn version(&self, component: &str, target: &str) -> String {
     fn hash(&self, path: &Path) -> String {
         let sha = t!(Command::new("shasum")
                         .arg("-a").arg("256")
-                        .arg(path)
+                        .arg(path.file_name().unwrap())
+                        .current_dir(path.parent().unwrap())
                         .output());
         assert!(sha.status.success());