From d1cace17af31ddb21aeb8a3d94cb3eda934047d9 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Thu, 22 Oct 2015 22:07:19 -0700
Subject: [PATCH] trans: Upgrade LLVM

This brings some routine upgrades to the bundled LLVM that we're using, the most
notable of which is a bug fix to the way we handle range asserts when loading
the discriminant of an enum. This fix ended up being very similar to f9d4149c
where we basically can't have a range assert when loading a discriminant due to
filling drop, and appropriate flags were added to communicate this to
`trans::adt`.
---
 src/librustc_llvm/archive_ro.rs               |  8 ++---
 src/librustc_llvm/lib.rs                      | 16 ++++++++-
 src/librustc_metadata/loader.rs               |  2 +-
 src/librustc_trans/back/archive.rs            | 35 ++++++++++++++++---
 src/librustc_trans/back/lto.rs                |  2 +-
 src/librustc_trans/back/write.rs              | 16 +++------
 src/librustc_trans/trans/_match.rs            |  3 +-
 src/librustc_trans/trans/adt.rs               | 28 ++++++++++-----
 src/librustc_trans/trans/base.rs              |  2 +-
 src/librustc_trans/trans/expr.rs              |  3 +-
 src/librustc_trans/trans/intrinsic.rs         |  3 +-
 src/librustc_trans/trans/mir/block.rs         |  3 +-
 src/llvm                                      |  2 +-
 src/rustllvm/ArchiveWrapper.cpp               | 22 ++++++++++--
 src/rustllvm/RustWrapper.cpp                  | 18 +++++++++-
 src/rustllvm/llvm-auto-clean-trigger          |  2 +-
 .../target-specs/my-awesome-platform.json     |  1 -
 17 files changed, 123 insertions(+), 43 deletions(-)

diff --git a/src/librustc_llvm/archive_ro.rs b/src/librustc_llvm/archive_ro.rs
index 85c0c721114..be7f0ed6a02 100644
--- a/src/librustc_llvm/archive_ro.rs
+++ b/src/librustc_llvm/archive_ro.rs
@@ -79,14 +79,14 @@ impl Drop for ArchiveRO {
 }
 
 impl<'a> Iterator for Iter<'a> {
-    type Item = Child<'a>;
+    type Item = Result<Child<'a>, String>;
 
-    fn next(&mut self) -> Option<Child<'a>> {
+    fn next(&mut self) -> Option<Result<Child<'a>, String>> {
         let ptr = unsafe { ::LLVMRustArchiveIteratorNext(self.ptr) };
         if ptr.is_null() {
-            None
+            ::last_error().map(Err)
         } else {
-            Some(Child { ptr: ptr, _data: marker::PhantomData })
+            Some(Ok(Child { ptr: ptr, _data: marker::PhantomData }))
         }
     }
 }
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 0bb3ddc9ad1..32009b0f29d 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -56,7 +56,7 @@ pub use self::DiagnosticSeverity::*;
 pub use self::Linkage::*;
 pub use self::DLLStorageClassTypes::*;
 
-use std::ffi::CString;
+use std::ffi::{CString, CStr};
 use std::cell::RefCell;
 use std::slice;
 use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char};
@@ -2404,6 +2404,20 @@ pub fn initialize_available_targets() {
     init_pnacl();
 }
 
+pub fn last_error() -> Option<String> {
+    unsafe {
+        let cstr = LLVMRustGetLastError();
+        if cstr.is_null() {
+            None
+        } else {
+            let err = CStr::from_ptr(cstr).to_bytes();
+            let err = String::from_utf8_lossy(err).to_string();
+            libc::free(cstr as *mut _);
+            Some(err)
+        }
+    }
+}
+
 // The module containing the native LLVM dependencies, generated by the build system
 // Note that this must come after the rustllvm extern declaration so that
 // parts of LLVM that rustllvm depends on aren't thrown away by the linker.
diff --git a/src/librustc_metadata/loader.rs b/src/librustc_metadata/loader.rs
index b0fb12b26b2..07a736d9959 100644
--- a/src/librustc_metadata/loader.rs
+++ b/src/librustc_metadata/loader.rs
@@ -729,7 +729,7 @@ pub fn note_crate_name(err: &mut DiagnosticBuilder, name: &str) {
 impl ArchiveMetadata {
     fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
         let data = {
-            let section = ar.iter().find(|sect| {
+            let section = ar.iter().filter_map(|s| s.ok()).find(|sect| {
                 sect.name() == Some(METADATA_FILENAME)
             });
             match section {
diff --git a/src/librustc_trans/back/archive.rs b/src/librustc_trans/back/archive.rs
index 85060858823..df902fbaff4 100644
--- a/src/librustc_trans/back/archive.rs
+++ b/src/librustc_trans/back/archive.rs
@@ -124,6 +124,7 @@ impl<'a> ArchiveBuilder<'a> {
         }
         let archive = self.src_archive.as_ref().unwrap().as_ref().unwrap();
         let ret = archive.iter()
+                         .filter_map(|child| child.ok())
                          .filter(is_relevant_child)
                          .filter_map(|child| child.name())
                          .filter(|name| !self.removals.iter().any(|x| x == name))
@@ -332,9 +333,15 @@ impl<'a> ArchiveBuilder<'a> {
         // We skip any files explicitly desired for skipping, and we also skip
         // all SYMDEF files as these are just magical placeholders which get
         // re-created when we make a new archive anyway.
-        for file in archive.iter().filter(is_relevant_child) {
+        for file in archive.iter() {
+            let file = try!(file.map_err(string2io));
+            if !is_relevant_child(&file) {
+                continue
+            }
             let filename = file.name().unwrap();
-            if skip(filename) { continue }
+            if skip(filename) {
+                continue
+            }
             let filename = Path::new(filename).file_name().unwrap()
                                               .to_str().unwrap();
 
@@ -448,6 +455,7 @@ impl<'a> ArchiveBuilder<'a> {
         unsafe {
             if let Some(archive) = self.src_archive() {
                 for child in archive.iter() {
+                    let child = try!(child.map_err(string2io));
                     let child_name = match child.name() {
                         Some(s) => s,
                         None => continue,
@@ -475,10 +483,25 @@ impl<'a> ArchiveBuilder<'a> {
                         strings.push(name);
                     }
                     Addition::Archive { archive, archive_name: _, mut skip } => {
-                        for child in archive.iter().filter(is_relevant_child) {
+                        for child in archive.iter() {
+                            let child = try!(child.map_err(string2io));
+                            if !is_relevant_child(&child) {
+                                continue
+                            }
                             let child_name = child.name().unwrap();
-                            if skip(child_name) { continue }
+                            if skip(child_name) {
+                                continue
+                            }
 
+                            // It appears that LLVM's archive writer is a little
+                            // buggy if the name we pass down isn't just the
+                            // filename component, so chop that off here and
+                            // pass it in.
+                            //
+                            // See LLVM bug 25877 for more info.
+                            let child_name = Path::new(child_name)
+                                                  .file_name().unwrap()
+                                                  .to_str().unwrap();
                             let name = try!(CString::new(child_name));
                             let m = llvm::LLVMRustArchiveMemberNew(ptr::null(),
                                                                    name.as_ptr(),
@@ -517,3 +540,7 @@ impl<'a> ArchiveBuilder<'a> {
         }
     }
 }
+
+fn string2io(s: String) -> io::Error {
+    io::Error::new(io::ErrorKind::Other, format!("bad archive: {}", s))
+}
diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs
index 06d32b8f601..649d37e802d 100644
--- a/src/librustc_trans/back/lto.rs
+++ b/src/librustc_trans/back/lto.rs
@@ -52,7 +52,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
     link::each_linked_rlib(sess, &mut |_, path| {
         let archive = ArchiveRO::open(&path).expect("wanted an rlib");
         let bytecodes = archive.iter().filter_map(|child| {
-            child.name().map(|name| (name, child))
+            child.ok().and_then(|c| c.name().map(|name| (name, c)))
         }).filter(|&(name, _)| name.ends_with("bytecode.deflate"));
         for (name, data) in bytecodes {
             let bc_encoded = data.data();
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 1068bca55d6..1bbc0a5b04d 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -27,24 +27,16 @@ use std::collections::HashMap;
 use std::ffi::{CStr, CString};
 use std::fs;
 use std::path::{Path, PathBuf};
-use std::ptr;
 use std::str;
 use std::sync::{Arc, Mutex};
 use std::sync::mpsc::channel;
 use std::thread;
-use libc::{self, c_uint, c_int, c_void};
+use libc::{c_uint, c_int, c_void};
 
 pub fn llvm_err(handler: &errors::Handler, msg: String) -> ! {
-    unsafe {
-        let cstr = llvm::LLVMRustGetLastError();
-        if cstr == ptr::null() {
-            panic!(handler.fatal(&msg[..]));
-        } else {
-            let err = CStr::from_ptr(cstr).to_bytes();
-            let err = String::from_utf8_lossy(err).to_string();
-            libc::free(cstr as *mut _);
-            panic!(handler.fatal(&format!("{}: {}", &msg[..], &err[..])));
-        }
+    match llvm::last_error() {
+        Some(err) => panic!(handler.fatal(&format!("{}: {}", msg, err))),
+        None => panic!(handler.fatal(&msg)),
     }
 }
 
diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs
index 9a05135b76e..851ff33cf93 100644
--- a/src/librustc_trans/trans/_match.rs
+++ b/src/librustc_trans/trans/_match.rs
@@ -1271,7 +1271,8 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                 };
             }
             Variant(_, ref repr, _, _) => {
-                let (the_kind, val_opt) = adt::trans_switch(bcx, &**repr, val.val);
+                let (the_kind, val_opt) = adt::trans_switch(bcx, &repr,
+                                                            val.val, true);
                 kind = the_kind;
                 if let Some(tval) = val_opt { test_val = tval; }
             }
diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs
index 2c11aad8940..ae42134813e 100644
--- a/src/librustc_trans/trans/adt.rs
+++ b/src/librustc_trans/trans/adt.rs
@@ -890,12 +890,15 @@ fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>,
 ///
 /// This should ideally be less tightly tied to `_match`.
 pub fn trans_switch<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                r: &Repr<'tcx>, scrutinee: ValueRef)
+                                r: &Repr<'tcx>,
+                                scrutinee: ValueRef,
+                                range_assert: bool)
                                 -> (_match::BranchKind, Option<ValueRef>) {
     match *r {
         CEnum(..) | General(..) |
         RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => {
-            (_match::Switch, Some(trans_get_discr(bcx, r, scrutinee, None)))
+            (_match::Switch, Some(trans_get_discr(bcx, r, scrutinee, None,
+                                                  range_assert)))
         }
         Univariant(..) => {
             // N.B.: Univariant means <= 1 enum variants (*not* == 1 variants).
@@ -916,14 +919,18 @@ pub fn is_discr_signed<'tcx>(r: &Repr<'tcx>) -> bool {
 
 /// Obtain the actual discriminant of a value.
 pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
-                                   scrutinee: ValueRef, cast_to: Option<Type>)
+                                   scrutinee: ValueRef, cast_to: Option<Type>,
+                                   range_assert: bool)
     -> ValueRef {
     debug!("trans_get_discr r: {:?}", r);
     let val = match *r {
-        CEnum(ity, min, max) => load_discr(bcx, ity, scrutinee, min, max),
+        CEnum(ity, min, max) => {
+            load_discr(bcx, ity, scrutinee, min, max, range_assert)
+        }
         General(ity, ref cases, _) => {
             let ptr = StructGEP(bcx, scrutinee, 0);
-            load_discr(bcx, ity, ptr, Disr(0), Disr(cases.len() as u64 - 1))
+            load_discr(bcx, ity, ptr, Disr(0), Disr(cases.len() as u64 - 1),
+                       range_assert)
         }
         Univariant(..) => C_u8(bcx.ccx(), 0),
         RawNullablePointer { nndiscr, nnty, .. } =>  {
@@ -950,7 +957,8 @@ fn struct_wrapped_nullable_bitdiscr(bcx: Block, nndiscr: Disr, discrfield: &Disc
 }
 
 /// Helper for cases where the discriminant is simply loaded.
-fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
+fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr,
+              range_assert: bool)
     -> ValueRef {
     let llty = ll_inttype(bcx.ccx(), ity);
     assert_eq!(val_ty(ptr), llty.ptr_to());
@@ -960,7 +968,7 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
     let mask = Disr(!0u64 >> (64 - bits));
     // For a (max) discr of -1, max will be `-1 as usize`, which overflows.
     // However, that is fine here (it would still represent the full range),
-    if max.wrapping_add(Disr(1)) & mask == min & mask {
+    if max.wrapping_add(Disr(1)) & mask == min & mask || !range_assert {
         // i.e., if the range is everything.  The lo==hi case would be
         // rejected by the LLVM verifier (it would mean either an
         // empty set, which is impossible, or the entire range of the
@@ -1239,10 +1247,14 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
             // runtime, so the basic block isn't actually unreachable, so we
             // need to make it do something with defined behavior. In this case
             // we just return early from the function.
+            //
+            // Note that this is also why the `trans_get_discr` below has
+            // `false` to indicate that loading the discriminant should
+            // not have a range assert.
             let ret_void_cx = fcx.new_temp_block("enum-variant-iter-ret-void");
             RetVoid(ret_void_cx, DebugLoc::None);
 
-            let discr_val = trans_get_discr(bcx, r, value, None);
+            let discr_val = trans_get_discr(bcx, r, value, None, false);
             let llswitch = Switch(bcx, discr_val, ret_void_cx.llbb, cases.len());
             let bcx_next = fcx.new_temp_block("enum-variant-iter-next");
 
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 7460ef82ebe..9c25284eb60 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -556,7 +556,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
             // NB: we must hit the discriminant first so that structural
             // comparison know not to proceed when the discriminants differ.
 
-            match adt::trans_switch(cx, &*repr, av) {
+            match adt::trans_switch(cx, &*repr, av, false) {
                 (_match::Single, None) => {
                     if n_variants != 0 {
                         assert!(n_variants == 1);
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs
index ada37c5d8df..30cbe6eeee4 100644
--- a/src/librustc_trans/trans/expr.rs
+++ b/src/librustc_trans/trans/expr.rs
@@ -2116,7 +2116,8 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         let datum = unpack_datum!(
             bcx, datum.to_lvalue_datum(bcx, "trans_imm_cast", expr.id));
         let llexpr_ptr = datum.to_llref();
-        let discr = adt::trans_get_discr(bcx, &*repr, llexpr_ptr, Some(Type::i64(ccx)));
+        let discr = adt::trans_get_discr(bcx, &*repr, llexpr_ptr,
+                                         Some(Type::i64(ccx)), true);
         ll_t_in = val_ty(discr);
         (discr, adt::is_discr_signed(&*repr))
     } else {
diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs
index 0c9b076cb65..629ea6f1c2f 100644
--- a/src/librustc_trans/trans/intrinsic.rs
+++ b/src/librustc_trans/trans/intrinsic.rs
@@ -655,7 +655,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
             match val_ty.sty {
                 ty::TyEnum(..) => {
                     let repr = adt::represent_type(ccx, *val_ty);
-                    adt::trans_get_discr(bcx, &*repr, llargs[0], Some(llret_ty))
+                    adt::trans_get_discr(bcx, &*repr, llargs[0],
+                                         Some(llret_ty), true)
                 }
                 _ => C_null(llret_ty)
             }
diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs
index 852f08a0d34..0dadcf54bf3 100644
--- a/src/librustc_trans/trans/mir/block.rs
+++ b/src/librustc_trans/trans/mir/block.rs
@@ -55,7 +55,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 let discr_lvalue = self.trans_lvalue(bcx, discr);
                 let ty = discr_lvalue.ty.to_ty(bcx.tcx());
                 let repr = adt::represent_type(bcx.ccx(), ty);
-                let discr = adt::trans_get_discr(bcx, &repr, discr_lvalue.llval, None);
+                let discr = adt::trans_get_discr(bcx, &repr, discr_lvalue.llval,
+                                                 None, true);
 
                 // The else branch of the Switch can't be hit, so branch to an unreachable
                 // instruction so LLVM knows that
diff --git a/src/llvm b/src/llvm
index 35644395159..de5c31045dc 160000
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit 3564439515985dc1cc0d77057ed00901635a80ad
+Subproject commit de5c31045dc0f6da1f65d02ee640ccf99ba90e7c
diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp
index 2cf6277e057..d3f2907bfc3 100644
--- a/src/rustllvm/ArchiveWrapper.cpp
+++ b/src/rustllvm/ArchiveWrapper.cpp
@@ -24,7 +24,13 @@ struct LLVMRustArchiveMember {
   const char *name;
   Archive::Child child;
 
-  LLVMRustArchiveMember(): filename(NULL), name(NULL), child(NULL, NULL) {}
+  LLVMRustArchiveMember(): filename(NULL), name(NULL),
+#if LLVM_VERSION_MINOR >= 8
+    child(NULL, NULL, NULL)
+#else
+    child(NULL, NULL)
+#endif
+  {}
   ~LLVMRustArchiveMember() {}
 };
 
@@ -92,8 +98,18 @@ extern "C" const Archive::Child*
 LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
     if (rai->cur == rai->end)
         return NULL;
-    const Archive::Child *cur = rai->cur.operator->();
-    Archive::Child *ret = new Archive::Child(*cur);
+#if LLVM_VERSION_MINOR >= 8
+    const ErrorOr<Archive::Child>* cur = rai->cur.operator->();
+    if (!*cur) {
+        LLVMRustSetLastError(cur->getError().message().c_str());
+        return NULL;
+    }
+    const Archive::Child &child = cur->get();
+#else
+    const Archive::Child &child = *rai->cur.operator->();
+#endif
+    Archive::Child *ret = new Archive::Child(child);
+
     ++rai->cur;
     return ret;
 }
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 5a9c096e5f5..a625a75933d 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -348,6 +348,19 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction(
     LLVMValueRef Fn,
     LLVMMetadataRef TParam,
     LLVMMetadataRef Decl) {
+#if LLVM_VERSION_MINOR >= 8
+    DITemplateParameterArray TParams =
+        DITemplateParameterArray(unwrap<MDTuple>(TParam));
+    DISubprogram *Sub = Builder->createFunction(
+        unwrapDI<DIScope>(Scope), Name, LinkageName,
+        unwrapDI<DIFile>(File), LineNo,
+        unwrapDI<DISubroutineType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
+        Flags, isOptimized,
+        TParams,
+        unwrapDIptr<DISubprogram>(Decl));
+    unwrap<Function>(Fn)->setSubprogram(Sub);
+    return wrap(Sub);
+#else
     return wrap(Builder->createFunction(
         unwrapDI<DIScope>(Scope), Name, LinkageName,
         unwrapDI<DIFile>(File), LineNo,
@@ -356,6 +369,7 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction(
         unwrap<Function>(Fn),
         unwrapDIptr<MDNode>(TParam),
         unwrapDIptr<MDNode>(Decl)));
+#endif
 }
 
 extern "C" LLVMMetadataRef LLVMDIBuilderCreateBasicType(
@@ -830,7 +844,9 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
 #if LLVM_VERSION_MINOR >= 6
     raw_string_ostream Stream(Err);
     DiagnosticPrinterRawOStream DP(Stream);
-#if LLVM_VERSION_MINOR >= 7
+#if LLVM_VERSION_MINOR >= 8
+    if (Linker::linkModules(*Dst, std::move(Src.get()))) {
+#elif LLVM_VERSION_MINOR >= 7
     if (Linker::LinkModules(Dst, Src->get(), [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
 #else
     if (Linker::LinkModules(Dst, *Src, [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger
index 4ef1fbb506b..7df7df505cd 100644
--- a/src/rustllvm/llvm-auto-clean-trigger
+++ b/src/rustllvm/llvm-auto-clean-trigger
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2015-12-02
+2015-01-25
diff --git a/src/test/run-make/target-specs/my-awesome-platform.json b/src/test/run-make/target-specs/my-awesome-platform.json
index d7cf7131d73..e3080d29ec3 100644
--- a/src/test/run-make/target-specs/my-awesome-platform.json
+++ b/src/test/run-make/target-specs/my-awesome-platform.json
@@ -1,5 +1,4 @@
 {
-    "data-layout": "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32",
     "llvm-target": "i686-unknown-linux-gnu",
     "target-endian": "little",
     "target-pointer-width": "32",