about summary refs log tree commit diff
diff options
context:
space:
mode:
m---------src/libcompiler_builtins0
-rw-r--r--src/librustc/dep_graph/dep_node.rs2
-rw-r--r--src/librustc/hir/check_attr.rs7
-rw-r--r--src/librustc/hir/mod.rs2
-rw-r--r--src/librustc/ich/impls_hir.rs1
-rw-r--r--src/librustc/mir/mono.rs8
-rw-r--r--src/librustc/ty/query/config.rs6
-rw-r--r--src/librustc/ty/query/mod.rs1
-rw-r--r--src/librustc/ty/query/plumbing.rs1
-rw-r--r--src/librustc_codegen_llvm/attributes.rs31
-rw-r--r--src/librustc_codegen_llvm/back/link.rs6
-rw-r--r--src/librustc_codegen_llvm/back/linker.rs37
-rw-r--r--src/librustc_codegen_llvm/back/wasm.rs42
-rw-r--r--src/librustc_codegen_llvm/base.rs59
-rw-r--r--src/librustc_codegen_llvm/lib.rs4
-rw-r--r--src/librustc_codegen_llvm/mono_item.rs7
-rw-r--r--src/librustc_codegen_utils/codegen_backend.rs1
-rw-r--r--src/librustc_metadata/cstore_impl.rs2
-rw-r--r--src/librustc_metadata/decoder.rs10
-rw-r--r--src/librustc_metadata/encoder.rs12
-rw-r--r--src/librustc_metadata/schema.rs1
-rw-r--r--src/librustc_mir/monomorphize/collector.rs10
-rw-r--r--src/librustc_mir/monomorphize/item.rs18
-rw-r--r--src/librustc_mir/monomorphize/partitioning.rs7
-rw-r--r--src/librustc_target/spec/wasm32_unknown_unknown.rs2
-rw-r--r--src/librustc_typeck/collect.rs8
-rw-r--r--src/librustdoc/fold.rs9
m---------src/llvm0
-rw-r--r--src/rustllvm/PassWrapper.cpp4
-rw-r--r--src/test/codegen/align-struct.rs3
-rw-r--r--src/test/codegen/consts.rs5
-rw-r--r--src/test/codegen/packed.rs14
-rw-r--r--src/test/codegen/repeat-trusted-len.rs3
-rw-r--r--src/test/codegen/simd-intrinsic-float-minmax.rs15
-rw-r--r--src/test/codegen/stores.rs6
-rw-r--r--src/test/run-make-fulldeps/pgo-gen-lto/Makefile2
-rw-r--r--src/test/run-make-fulldeps/pgo-gen/Makefile2
-rw-r--r--src/test/run-pass/simd-intrinsic-float-math.rs46
m---------src/tools/lld0
39 files changed, 199 insertions, 195 deletions
diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins
-Subproject 4cfd7101eb549169cdaeda5313f7c39415b9d73
+Subproject 86bf357a14cacb4a4169455e729d409b5ecc1da
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 3c4472aef6b..ef564ac89f9 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -665,8 +665,6 @@ define_dep_nodes!( <'tcx>
 
     [] InstanceDefSizeEstimate { instance_def: InstanceDef<'tcx> },
 
-    [] WasmCustomSections(CrateNum),
-
     [input] Features,
 
     [] ProgramClausesFor(DefId),
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index c71b47fa4e1..2d83c158fe0 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -57,7 +57,7 @@ struct CheckAttrVisitor<'a, 'tcx: 'a> {
 impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
     /// Check any attribute.
     fn check_attributes(&self, item: &hir::Item, target: Target) {
-        if target == Target::Fn {
+        if target == Target::Fn || target == Target::Const {
             self.tcx.codegen_fn_attrs(self.tcx.hir.local_def_id(item.id));
         } else if let Some(a) = item.attrs.iter().find(|a| a.check_name("target_feature")) {
             self.tcx.sess.struct_span_err(a.span, "attribute should be applied to a function")
@@ -85,11 +85,6 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
                 if target != Target::Const {
                     self.tcx.sess.span_err(attr.span, "only allowed on consts");
                 }
-
-                if attr.value_str().is_none() {
-                    self.tcx.sess.span_err(attr.span, "must be of the form \
-                        #[wasm_custom_section = \"foo\"]");
-                }
             }
         }
 
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index f18846b8574..bae443bfc58 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -2268,6 +2268,7 @@ pub struct CodegenFnAttrs {
     pub export_name: Option<Symbol>,
     pub target_features: Vec<Symbol>,
     pub linkage: Option<Linkage>,
+    pub wasm_custom_section: Option<Symbol>,
 }
 
 bitflags! {
@@ -2292,6 +2293,7 @@ impl CodegenFnAttrs {
             export_name: None,
             target_features: vec![],
             linkage: None,
+            wasm_custom_section: None,
         }
     }
 
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 8b62ba119eb..b6add3e6f12 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -1120,6 +1120,7 @@ impl_stable_hash_for!(struct hir::CodegenFnAttrs {
     export_name,
     target_features,
     linkage,
+    wasm_custom_section,
 });
 
 impl<'hir> HashStable<StableHashingContext<'hir>> for hir::CodegenFnAttrFlags
diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs
index 9de9347d0ce..79566fbbc11 100644
--- a/src/librustc/mir/mono.rs
+++ b/src/librustc/mir/mono.rs
@@ -24,6 +24,7 @@ pub enum MonoItem<'tcx> {
     Fn(Instance<'tcx>),
     Static(DefId),
     GlobalAsm(NodeId),
+    CustomSection(DefId),
 }
 
 impl<'tcx> MonoItem<'tcx> {
@@ -36,7 +37,9 @@ impl<'tcx> MonoItem<'tcx> {
             },
             // Conservatively estimate the size of a static declaration
             // or assembly to be 1.
-            MonoItem::Static(_) | MonoItem::GlobalAsm(_) => 1,
+            MonoItem::Static(_) |
+            MonoItem::GlobalAsm(_) |
+            MonoItem::CustomSection(_) => 1,
         }
     }
 }
@@ -51,7 +54,8 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for MonoItem<'tcx> {
             MonoItem::Fn(ref instance) => {
                 instance.hash_stable(hcx, hasher);
             }
-            MonoItem::Static(def_id) => {
+            MonoItem::Static(def_id) |
+            MonoItem::CustomSection(def_id) => {
                 def_id.hash_stable(hcx, hasher);
             }
             MonoItem::GlobalAsm(node_id) => {
diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs
index 229caeb95d6..bd6217e28c7 100644
--- a/src/librustc/ty/query/config.rs
+++ b/src/librustc/ty/query/config.rs
@@ -776,12 +776,6 @@ impl<'tcx> QueryDescription<'tcx> for queries::instance_def_size_estimate<'tcx>
     }
 }
 
-impl<'tcx> QueryDescription<'tcx> for queries::wasm_custom_sections<'tcx> {
-    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
-        format!("custom wasm sections for a crate")
-    }
-}
-
 impl<'tcx> QueryDescription<'tcx> for queries::generics_of<'tcx> {
     #[inline]
     fn cache_on_disk(def_id: Self::Key) -> bool {
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index 9ad93b4d5e2..3581dd87f6f 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -546,7 +546,6 @@ define_queries! { <'tcx>
         ty::ParamEnv<'tcx>
     ) -> Clauses<'tcx>,
 
-    [] fn wasm_custom_sections: WasmCustomSections(CrateNum) -> Lrc<Vec<DefId>>,
     [] fn wasm_import_module_map: WasmImportModuleMap(CrateNum)
         -> Lrc<FxHashMap<DefId, String>>,
 }
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index 9f802f7fdcd..9dc8321f825 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -1208,7 +1208,6 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
         DepKind::Features => { force!(features_query, LOCAL_CRATE); }
 
         DepKind::ProgramClausesFor => { force!(program_clauses_for, def_id!()); }
-        DepKind::WasmCustomSections => { force!(wasm_custom_sections, krate!()); }
         DepKind::WasmImportModuleMap => { force!(wasm_import_module_map, krate!()); }
         DepKind::ForeignModules => { force!(foreign_modules, krate!()); }
 
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index 429acbbe0c2..8246bb24366 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -11,9 +11,8 @@
 
 use std::ffi::{CStr, CString};
 
-use rustc::hir::{self, CodegenFnAttrFlags};
+use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::session::Session;
 use rustc::session::config::Sanitizer;
 use rustc::ty::TyCtxt;
@@ -222,37 +221,9 @@ pub fn provide(providers: &mut Providers) {
         }
     };
 
-    providers.wasm_custom_sections = |tcx, cnum| {
-        assert_eq!(cnum, LOCAL_CRATE);
-        let mut finder = WasmSectionFinder { tcx, list: Vec::new() };
-        tcx.hir.krate().visit_all_item_likes(&mut finder);
-        Lrc::new(finder.list)
-    };
-
     provide_extern(providers);
 }
 
-struct WasmSectionFinder<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    list: Vec<DefId>,
-}
-
-impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for WasmSectionFinder<'a, 'tcx> {
-    fn visit_item(&mut self, i: &'tcx hir::Item) {
-        match i.node {
-            hir::ItemConst(..) => {}
-            _ => return,
-        }
-        if i.attrs.iter().any(|i| i.check_name("wasm_custom_section")) {
-            self.list.push(self.tcx.hir.local_def_id(i.id));
-        }
-    }
-
-    fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) {}
-
-    fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) {}
-}
-
 pub fn provide_extern(providers: &mut Providers) {
     providers.wasm_import_module_map = |tcx, cnum| {
         let mut ret = FxHashMap();
diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs
index 70053cb7e9d..e8636b1c999 100644
--- a/src/librustc_codegen_llvm/back/link.rs
+++ b/src/librustc_codegen_llvm/back/link.rs
@@ -29,7 +29,7 @@ use rustc::util::common::time;
 use rustc::util::fs::fix_windows_verbatim_for_gcc;
 use rustc::hir::def_id::CrateNum;
 use tempfile::{Builder as TempFileBuilder, TempDir};
-use rustc_target::spec::{PanicStrategy, RelroLevel, LinkerFlavor, TargetTriple};
+use rustc_target::spec::{PanicStrategy, RelroLevel, LinkerFlavor};
 use rustc_data_structures::fx::FxHashSet;
 use context::get_reloc_model;
 use llvm;
@@ -837,10 +837,8 @@ fn link_natively(sess: &Session,
         }
     }
 
-    if sess.opts.target_triple == TargetTriple::from_triple("wasm32-unknown-unknown") {
+    if sess.opts.target_triple.triple() == "wasm32-unknown-unknown" {
         wasm::rewrite_imports(&out_filename, &codegen_results.crate_info.wasm_imports);
-        wasm::add_custom_sections(&out_filename,
-                                  &codegen_results.crate_info.wasm_custom_sections);
     }
 }
 
diff --git a/src/librustc_codegen_llvm/back/linker.rs b/src/librustc_codegen_llvm/back/linker.rs
index 99249255d27..f07c758807e 100644
--- a/src/librustc_codegen_llvm/back/linker.rs
+++ b/src/librustc_codegen_llvm/back/linker.rs
@@ -86,6 +86,7 @@ impl LinkerInfo {
             LinkerFlavor::Lld(LldFlavor::Wasm) => {
                 Box::new(WasmLd {
                     cmd,
+                    sess,
                 }) as Box<Linker>
             }
         }
@@ -919,11 +920,12 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
     symbols
 }
 
-pub struct WasmLd {
+pub struct WasmLd<'a> {
     cmd: Command,
+    sess: &'a Session,
 }
 
-impl Linker for WasmLd {
+impl<'a> Linker for WasmLd<'a> {
     fn link_dylib(&mut self, lib: &str) {
         self.cmd.arg("-l").arg(lib);
     }
@@ -988,9 +990,20 @@ impl Linker for WasmLd {
     }
 
     fn gc_sections(&mut self, _keep_metadata: bool) {
+        self.cmd.arg("--gc-sections");
     }
 
     fn optimize(&mut self) {
+        self.cmd.arg(match self.sess.opts.optimize {
+            OptLevel::No => "-O0",
+            OptLevel::Less => "-O1",
+            OptLevel::Default => "-O2",
+            OptLevel::Aggressive => "-O3",
+            // Currently LLD doesn't support `Os` and `Oz`, so pass through `O2`
+            // instead.
+            OptLevel::Size => "-O2",
+            OptLevel::SizeMin => "-O2"
+        });
     }
 
     fn pgo_gen(&mut self) {
@@ -1020,8 +1033,28 @@ impl Linker for WasmLd {
         // this isn't yet the bottleneck of compilation at all anyway.
         self.cmd.arg("--no-threads");
 
+        // By default LLD only gives us one page of stack (64k) which is a
+        // little small. Default to a larger stack closer to other PC platforms
+        // (1MB) and users can always inject their own link-args to override this.
         self.cmd.arg("-z").arg("stack-size=1048576");
 
+        // By default LLD's memory layout is:
+        //
+        // 1. First, a blank page
+        // 2. Next, all static data
+        // 3. Finally, the main stack (which grows down)
+        //
+        // This has the unfortunate consequence that on stack overflows you
+        // corrupt static data and can cause some exceedingly weird bugs. To
+        // help detect this a little sooner we instead request that the stack is
+        // placed before static data.
+        //
+        // This means that we'll generate slightly larger binaries as references
+        // to static data will take more bytes in the ULEB128 encoding, but
+        // stack overflow will be guaranteed to trap as it underflows instead of
+        // corrupting static data.
+        self.cmd.arg("--stack-first");
+
         // FIXME we probably shouldn't pass this but instead pass an explicit
         // whitelist of symbols we'll allow to be undefined. Unfortunately
         // though we can't handle symbols like `log10` that LLVM injects at a
diff --git a/src/librustc_codegen_llvm/back/wasm.rs b/src/librustc_codegen_llvm/back/wasm.rs
index c553eca08e6..d378d5af1c0 100644
--- a/src/librustc_codegen_llvm/back/wasm.rs
+++ b/src/librustc_codegen_llvm/back/wasm.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::collections::BTreeMap;
 use std::fs;
 use std::path::Path;
 use std::str;
@@ -24,45 +23,6 @@ const WASM_EXTERNAL_KIND_TABLE: u8 = 1;
 const WASM_EXTERNAL_KIND_MEMORY: u8 = 2;
 const WASM_EXTERNAL_KIND_GLOBAL: u8 = 3;
 
-/// Append all the custom sections listed in `sections` to the wasm binary
-/// specified at `path`.
-///
-/// LLVM 6 which we're using right now doesn't have the ability to create custom
-/// sections in wasm files nor does LLD have the ability to merge these sections
-/// into one larger section when linking. It's expected that this will
-/// eventually get implemented, however!
-///
-/// Until that time though this is a custom implementation in rustc to append
-/// all sections to a wasm file to the finished product that LLD produces.
-///
-/// Support for this is landing in LLVM in https://reviews.llvm.org/D43097,
-/// although after that support will need to be in LLD as well.
-pub fn add_custom_sections(path: &Path, sections: &BTreeMap<String, Vec<u8>>) {
-    if sections.len() == 0 {
-        return
-    }
-
-    let wasm = fs::read(path).expect("failed to read wasm output");
-
-    // see https://webassembly.github.io/spec/core/binary/modules.html#custom-section
-    let mut wasm = WasmEncoder { data: wasm };
-    for (section, bytes) in sections {
-        // write the `id` identifier, 0 for a custom section
-        wasm.byte(0);
-
-        // figure out how long our name descriptor will be
-        let mut name = WasmEncoder::new();
-        name.str(section);
-
-        // write the length of the payload followed by all its contents
-        wasm.u32((bytes.len() + name.data.len()) as u32);
-        wasm.data.extend_from_slice(&name.data);
-        wasm.data.extend_from_slice(bytes);
-    }
-
-    fs::write(path, &wasm.data).expect("failed to write wasm output");
-}
-
 /// Rewrite the module imports are listed from in a wasm module given the field
 /// name to module name mapping in `import_map`.
 ///
@@ -80,7 +40,7 @@ pub fn add_custom_sections(path: &Path, sections: &BTreeMap<String, Vec<u8>>) {
 ///
 /// Support for this was added to LLVM in
 /// https://github.com/llvm-mirror/llvm/commit/0f32e1365, although support still
-/// needs to be added (AFAIK at the time of this writing) to LLD
+/// needs to be added, tracked at https://bugs.llvm.org/show_bug.cgi?id=37168
 pub fn rewrite_imports(path: &Path, import_map: &FxHashMap<String, String>) {
     if import_map.len() == 0 {
         return
diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs
index 2598e7c86f9..179fffc4e7f 100644
--- a/src/librustc_codegen_llvm/base.rs
+++ b/src/librustc_codegen_llvm/base.rs
@@ -33,6 +33,7 @@ use back::link;
 use back::write::{self, OngoingCodegen, create_target_machine};
 use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param};
 use llvm;
+use libc::c_uint;
 use metadata;
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::middle::lang_items::StartFnLangItem;
@@ -74,10 +75,8 @@ use type_of::LayoutLlvmExt;
 use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet};
 use CrateInfo;
 use rustc_data_structures::sync::Lrc;
-use rustc_target::spec::TargetTriple;
 
 use std::any::Any;
-use std::collections::BTreeMap;
 use std::ffi::CString;
 use std::str;
 use std::sync::Arc;
@@ -1100,7 +1099,6 @@ impl CrateInfo {
             used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic),
             used_crates_static: cstore::used_crates(tcx, LinkagePreference::RequireStatic),
             used_crate_source: FxHashMap(),
-            wasm_custom_sections: BTreeMap::new(),
             wasm_imports: FxHashMap(),
             lang_item_to_crate: FxHashMap(),
             missing_lang_items: FxHashMap(),
@@ -1110,16 +1108,9 @@ impl CrateInfo {
         let load_wasm_items = tcx.sess.crate_types.borrow()
             .iter()
             .any(|c| *c != config::CrateTypeRlib) &&
-            tcx.sess.opts.target_triple == TargetTriple::from_triple("wasm32-unknown-unknown");
+            tcx.sess.opts.target_triple.triple() == "wasm32-unknown-unknown";
 
         if load_wasm_items {
-            info!("attempting to load all wasm sections");
-            for &id in tcx.wasm_custom_sections(LOCAL_CRATE).iter() {
-                let (name, contents) = fetch_wasm_section(tcx, id);
-                info.wasm_custom_sections.entry(name)
-                    .or_insert(Vec::new())
-                    .extend(contents);
-            }
             info.load_wasm_imports(tcx, LOCAL_CRATE);
         }
 
@@ -1143,12 +1134,6 @@ impl CrateInfo {
                 info.is_no_builtins.insert(cnum);
             }
             if load_wasm_items {
-                for &id in tcx.wasm_custom_sections(cnum).iter() {
-                    let (name, contents) = fetch_wasm_section(tcx, id);
-                    info.wasm_custom_sections.entry(name)
-                        .or_insert(Vec::new())
-                        .extend(contents);
-                }
                 info.load_wasm_imports(tcx, cnum);
             }
             let missing = tcx.missing_lang_items(cnum);
@@ -1385,25 +1370,41 @@ mod temp_stable_hash_impls {
     }
 }
 
-fn fetch_wasm_section(tcx: TyCtxt, id: DefId) -> (String, Vec<u8>) {
+pub fn define_custom_section(cx: &CodegenCx, def_id: DefId) {
     use rustc::mir::interpret::GlobalId;
 
-    info!("loading wasm section {:?}", id);
+    assert!(cx.tcx.sess.opts.target_triple.triple().starts_with("wasm32"));
+
+    info!("loading wasm section {:?}", def_id);
 
-    let section = tcx.get_attrs(id)
-        .iter()
-        .find(|a| a.check_name("wasm_custom_section"))
-        .expect("missing #[wasm_custom_section] attribute")
-        .value_str()
-        .expect("malformed #[wasm_custom_section] attribute");
+    let section = cx.tcx.codegen_fn_attrs(def_id).wasm_custom_section.unwrap();
 
-    let instance = ty::Instance::mono(tcx, id);
+    let instance = ty::Instance::mono(cx.tcx, def_id);
     let cid = GlobalId {
         instance,
         promoted: None
     };
     let param_env = ty::ParamEnv::reveal_all();
-    let val = tcx.const_eval(param_env.and(cid)).unwrap();
-    let alloc = tcx.const_value_to_allocation(val);
-    (section.to_string(), alloc.bytes.clone())
+    let val = cx.tcx.const_eval(param_env.and(cid)).unwrap();
+    let alloc = cx.tcx.const_value_to_allocation(val);
+
+    unsafe {
+        let section = llvm::LLVMMDStringInContext(
+            cx.llcx,
+            section.as_str().as_ptr() as *const _,
+            section.as_str().len() as c_uint,
+        );
+        let alloc = llvm::LLVMMDStringInContext(
+            cx.llcx,
+            alloc.bytes.as_ptr() as *const _,
+            alloc.bytes.len() as c_uint,
+        );
+        let data = [section, alloc];
+        let meta = llvm::LLVMMDNodeInContext(cx.llcx, data.as_ptr(), 2);
+        llvm::LLVMAddNamedMetadataOperand(
+            cx.llmod,
+            "wasm.custom_sections\0".as_ptr() as *const _,
+            meta,
+        );
+    }
 }
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 93d9ce1e98a..a2f28417520 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -65,7 +65,6 @@ pub use llvm_util::target_features;
 use std::any::Any;
 use std::path::PathBuf;
 use std::sync::mpsc;
-use std::collections::BTreeMap;
 use rustc_data_structures::sync::Lrc;
 
 use rustc::dep_graph::DepGraph;
@@ -94,7 +93,7 @@ mod back {
     pub mod symbol_export;
     pub mod write;
     mod rpath;
-    mod wasm;
+    pub mod wasm;
 }
 
 mod abi;
@@ -382,7 +381,6 @@ struct CrateInfo {
     used_crate_source: FxHashMap<CrateNum, Lrc<CrateSource>>,
     used_crates_static: Vec<(CrateNum, LibSource)>,
     used_crates_dynamic: Vec<(CrateNum, LibSource)>,
-    wasm_custom_sections: BTreeMap<String, Vec<u8>>,
     wasm_imports: FxHashMap<String, String>,
     lang_item_to_crate: FxHashMap<LangItem, CrateNum>,
     missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs
index 2f7b27b85af..e142a7d9c1c 100644
--- a/src/librustc_codegen_llvm/mono_item.rs
+++ b/src/librustc_codegen_llvm/mono_item.rs
@@ -66,6 +66,9 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
                     span_bug!(item.span, "Mismatch between hir::Item type and MonoItem type")
                 }
             }
+            MonoItem::CustomSection(def_id) => {
+                base::define_custom_section(cx, def_id);
+            }
             MonoItem::Fn(instance) => {
                 base::codegen_instance(&cx, instance);
             }
@@ -97,6 +100,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
             MonoItem::Fn(instance) => {
                 predefine_fn(cx, instance, linkage, visibility, &symbol_name);
             }
+            MonoItem::CustomSection(..) => {}
             MonoItem::GlobalAsm(..) => {}
         }
 
@@ -116,6 +120,9 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
             MonoItem::Static(id) => {
                 format!("Static({:?})", id)
             }
+            MonoItem::CustomSection(id) => {
+                format!("CustomSection({:?})", id)
+            }
             MonoItem::GlobalAsm(id) => {
                 format!("GlobalAsm({:?})", id)
             }
diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs
index 3cbf176d98b..57e6c0d7b85 100644
--- a/src/librustc_codegen_utils/codegen_backend.rs
+++ b/src/librustc_codegen_utils/codegen_backend.rs
@@ -137,7 +137,6 @@ impl CodegenBackend for MetadataOnlyCodegenBackend {
         };
         providers.is_reachable_non_generic = |_tcx, _defid| true;
         providers.exported_symbols = |_tcx, _crate| Arc::new(Vec::new());
-        providers.wasm_custom_sections = |_tcx, _crate| Lrc::new(Vec::new());
     }
     fn provide_extern(&self, providers: &mut Providers) {
         providers.is_reachable_non_generic = |_tcx, _defid| true;
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 20d9121668b..cded812b5f0 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -266,8 +266,6 @@ provide! { <'tcx> tcx, def_id, other, cdata,
 
         Arc::new(cdata.exported_symbols(tcx))
     }
-
-    wasm_custom_sections => { Lrc::new(cdata.wasm_custom_sections()) }
 }
 
 pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index d604ac819b8..38149d1ca50 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -1011,16 +1011,6 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn wasm_custom_sections(&self) -> Vec<DefId> {
-        let sections = self.root
-            .wasm_custom_sections
-            .decode(self)
-            .map(|def_index| self.local_def_id(def_index))
-            .collect::<Vec<_>>();
-        info!("loaded wasm sections {:?}", sections);
-        return sections
-    }
-
     pub fn get_macro(&self, id: DefIndex) -> (InternedString, MacroDef) {
         let entry = self.entry(id);
         match entry.kind {
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 36f053e5aa9..72f91dcea60 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -436,12 +436,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             &exported_symbols);
         let exported_symbols_bytes = self.position() - i;
 
-        // encode wasm custom sections
-        let wasm_custom_sections = self.tcx.wasm_custom_sections(LOCAL_CRATE);
-        let wasm_custom_sections = self.tracked(
-            IsolatedEncoder::encode_wasm_custom_sections,
-            &wasm_custom_sections);
-
         let tcx = self.tcx;
 
         // Encode the items.
@@ -527,7 +521,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             def_path_table,
             impls,
             exported_symbols,
-            wasm_custom_sections,
             interpret_alloc_index,
             index,
         });
@@ -1543,11 +1536,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
         }
     }
 
-    fn encode_wasm_custom_sections(&mut self, statics: &[DefId]) -> LazySeq<DefIndex> {
-        info!("encoding custom wasm section constants {:?}", statics);
-        self.lazy_seq(statics.iter().map(|id| id.index))
-    }
-
     fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq<Option<LinkagePreference>> {
         match self.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) {
             Some(arr) => {
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index a0b21e63ac5..430cbf9b529 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -206,7 +206,6 @@ pub struct CrateRoot {
     pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
     pub impls: LazySeq<TraitImpls>,
     pub exported_symbols: EncodedExportedSymbols,
-    pub wasm_custom_sections: LazySeq<DefIndex>,
     pub interpret_alloc_index: LazySeq<u32>,
 
     pub index: LazySeq<index::Index>,
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 09c5df00052..ce917b8ca55 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -414,6 +414,9 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         MonoItem::GlobalAsm(..) => {
             recursion_depth_reset = None;
         }
+        MonoItem::CustomSection(..) => {
+            recursion_depth_reset = None;
+        }
     }
 
     record_accesses(tcx, starting_point, &neighbors[..], inlining_map);
@@ -990,6 +993,13 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
             hir::ItemConst(..) => {
                 // const items only generate mono items if they are
                 // actually used somewhere. Just declaring them is insufficient.
+
+                let def_id = self.tcx.hir.local_def_id(item.id);
+                if self.tcx.sess.opts.target_triple.triple().starts_with("wasm32") &&
+                    self.tcx.codegen_fn_attrs(def_id).wasm_custom_section.is_some()
+                {
+                    self.output.push(MonoItem::CustomSection(def_id));
+                }
             }
             hir::ItemFn(..) => {
                 let def_id = self.tcx.hir.local_def_id(item.id);
diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index 0428489fd8d..1389ad63c3a 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -63,6 +63,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
                 instance.substs.types().next().is_some()
             }
             MonoItem::Static(..) |
+            MonoItem::CustomSection(..) |
             MonoItem::GlobalAsm(..) => false,
         }
     }
@@ -73,6 +74,9 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
             MonoItem::Static(def_id) => {
                 tcx.symbol_name(Instance::mono(tcx, def_id))
             }
+            MonoItem::CustomSection(def_id) => {
+                tcx.symbol_name(Instance::mono(tcx, def_id))
+            }
             MonoItem::GlobalAsm(node_id) => {
                 let def_id = tcx.hir.local_def_id(node_id);
                 ty::SymbolName {
@@ -121,9 +125,8 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
                     }
                 }
             }
-            MonoItem::Static(..) => {
-                InstantiationMode::GloballyShared { may_conflict: false }
-            }
+            MonoItem::Static(..) |
+            MonoItem::CustomSection(..) |
             MonoItem::GlobalAsm(..) => {
                 InstantiationMode::GloballyShared { may_conflict: false }
             }
@@ -134,6 +137,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
         let def_id = match *self.as_mono_item() {
             MonoItem::Fn(ref instance) => instance.def_id(),
             MonoItem::Static(def_id) => def_id,
+            MonoItem::CustomSection(..) => return None,
             MonoItem::GlobalAsm(..) => return None,
         };
 
@@ -171,6 +175,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
         let (def_id, substs) = match *self.as_mono_item() {
             MonoItem::Fn(ref instance) => (instance.def_id(), instance.substs),
             MonoItem::Static(def_id) => (def_id, Substs::empty()),
+            MonoItem::CustomSection(..) => return true,
             // global asm never has predicates
             MonoItem::GlobalAsm(..) => return true
         };
@@ -187,6 +192,10 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
                 let instance = Instance::new(def_id, tcx.intern_substs(&[]));
                 to_string_internal(tcx, "static ", instance)
             },
+            MonoItem::CustomSection(def_id) => {
+                let instance = Instance::new(def_id, tcx.intern_substs(&[]));
+                to_string_internal(tcx, "custom-section ", instance)
+            },
             MonoItem::GlobalAsm(..) => {
                 "global_asm".to_string()
             }
@@ -212,6 +221,9 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
             MonoItem::Static(def_id) => {
                 tcx.hir.as_local_node_id(def_id)
             }
+            MonoItem::CustomSection(def_id) => {
+                tcx.hir.as_local_node_id(def_id)
+            }
             MonoItem::GlobalAsm(node_id) => {
                 Some(node_id)
             }
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index f83ea6fa13b..5f15870d6fb 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -180,7 +180,8 @@ pub trait CodegenUnitExt<'tcx> {
                         }
                     }
                 }
-                MonoItem::Static(def_id) => {
+                MonoItem::Static(def_id) |
+                MonoItem::CustomSection(def_id) => {
                     tcx.hir.as_local_node_id(def_id)
                 }
                 MonoItem::GlobalAsm(node_id) => {
@@ -449,6 +450,9 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         };
                         (Linkage::External, visibility)
                     }
+                    MonoItem::CustomSection(..) => {
+                        (Linkage::External, Visibility::Hidden)
+                    }
                     MonoItem::GlobalAsm(node_id) => {
                         let def_id = tcx.hir.local_def_id(node_id);
                         let visibility = if tcx.is_reachable_non_generic(def_id) {
@@ -714,6 +718,7 @@ fn characteristic_def_id_of_mono_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             Some(def_id)
         }
         MonoItem::Static(def_id) => Some(def_id),
+        MonoItem::CustomSection(def_id) => Some(def_id),
         MonoItem::GlobalAsm(node_id) => Some(tcx.hir.local_def_id(node_id)),
     }
 }
diff --git a/src/librustc_target/spec/wasm32_unknown_unknown.rs b/src/librustc_target/spec/wasm32_unknown_unknown.rs
index 6f51495bae9..51d402e197d 100644
--- a/src/librustc_target/spec/wasm32_unknown_unknown.rs
+++ b/src/librustc_target/spec/wasm32_unknown_unknown.rs
@@ -57,7 +57,7 @@ pub fn target() -> Result<Target, String> {
         .. Default::default()
     };
     Ok(Target {
-        llvm_target: "wasm32-unknown-unknown-wasm".to_string(),
+        llvm_target: "wasm32-unknown-unknown".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 94b17532cb7..fa2f9885964 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1925,6 +1925,14 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen
             if let Some(val) = attr.value_str() {
                 codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str()));
             }
+        } else if attr.check_name("wasm_custom_section") {
+            match attr.value_str() {
+                Some(name) => codegen_fn_attrs.wasm_custom_section = Some(name),
+                None => {
+                    tcx.sess.span_err(attr.span, "must be of the form \
+                        #[wasm_custom_section = \"foo\"]");
+                }
+            }
         }
     }
 
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index 54c57c9ac6e..8e8566cbbde 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::mem;
+
 use clean::*;
 
 pub enum FoldItem {
@@ -109,12 +111,13 @@ pub trait DocFolder : Sized {
     }
 
     fn fold_crate(&mut self, mut c: Crate) -> Crate {
-        c.module = c.module.and_then(|module| self.fold_item(module));
+        c.module = c.module.take().and_then(|module| self.fold_item(module));
 
-        c.external_traits = c.external_traits.into_iter().map(|(k, mut v)| {
+        let traits = mem::replace(&mut c.external_traits, Default::default());
+        c.external_traits.extend(traits.into_iter().map(|(k, mut v)| {
             v.items = v.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
             (k, v)
-        }).collect();
+        }));
         c
     }
 }
diff --git a/src/llvm b/src/llvm
-Subproject 509f29ac17874394acf4d49d6bae3cd93c652aa
+Subproject 03684905101f0b7e49dfe530e54dc1aeac6ef0f
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index d5410feb254..a00ff3b345d 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -545,7 +545,11 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
     return LLVMRustResult::Failure;
   }
 
+#if LLVM_VERSION_GE(7, 0)
+  unwrap(Target)->addPassesToEmitFile(*PM, OS, nullptr, FileType, false);
+#else
   unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
+#endif
   PM->run(*unwrap(M));
 
   // Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output
diff --git a/src/test/codegen/align-struct.rs b/src/test/codegen/align-struct.rs
index f306608f432..bf119da2e82 100644
--- a/src/test/codegen/align-struct.rs
+++ b/src/test/codegen/align-struct.rs
@@ -10,6 +10,7 @@
 
 // compile-flags: -C no-prepopulate-passes
 // ignore-tidy-linelength
+// min-llvm-version 7.0
 
 #![crate_type = "lib"]
 
@@ -42,7 +43,7 @@ pub enum Enum64 {
 #[no_mangle]
 pub fn align64(i : i32) -> Align64 {
 // CHECK: %a64 = alloca %Align64, align 64
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 64, i32 64, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 64 %{{.*}}, i8* align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
     let a64 = Align64(i);
     a64
 }
diff --git a/src/test/codegen/consts.rs b/src/test/codegen/consts.rs
index 007fb7f4596..30fffbb769b 100644
--- a/src/test/codegen/consts.rs
+++ b/src/test/codegen/consts.rs
@@ -10,6 +10,7 @@
 
 // compile-flags: -C no-prepopulate-passes
 // ignore-tidy-linelength
+// min-llvm-version 7.0
 
 #![crate_type = "lib"]
 
@@ -54,7 +55,7 @@ pub fn inline_enum_const() -> E<i8, i16> {
 #[no_mangle]
 pub fn low_align_const() -> E<i16, [i16; 3]> {
 // Check that low_align_const and high_align_const use the same constant
-// CHECK: i8* getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0),
+// CHECK: i8* align 2 getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0),
     *&E::A(0)
 }
 
@@ -62,6 +63,6 @@ pub fn low_align_const() -> E<i16, [i16; 3]> {
 #[no_mangle]
 pub fn high_align_const() -> E<i16, i32> {
 // Check that low_align_const and high_align_const use the same constant
-// CHECK: i8* getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0),
+// CHECK: i8* align 4 getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0),
     *&E::A(0)
 }
diff --git a/src/test/codegen/packed.rs b/src/test/codegen/packed.rs
index 0693eae7d78..10dd12909b6 100644
--- a/src/test/codegen/packed.rs
+++ b/src/test/codegen/packed.rs
@@ -8,7 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
 // compile-flags: -C no-prepopulate-passes
+// min-llvm-version 7.0
 
 #![crate_type = "lib"]
 #![feature(repr_packed)]
@@ -63,7 +65,7 @@ pub struct BigPacked2 {
 pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
 // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
 // CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]])
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 32, i32 1, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 %{{.*}}, i8* align 1 %{{.*}}, i{{[0-9]+}} 32, i1 false)
     // check that calls whose destination is a field of a packed struct
     // go through an alloca rather than calling the function with an
     // unaligned destination.
@@ -75,7 +77,7 @@ pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
 pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 {
 // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
 // CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]])
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 32, i32 2, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 2 %{{.*}}, i8* align 2 %{{.*}}, i{{[0-9]+}} 32, i1 false)
     // check that calls whose destination is a field of a packed struct
     // go through an alloca rather than calling the function with an
     // unaligned destination.
@@ -93,14 +95,14 @@ pub struct Packed2Pair(u8, u32);
 // CHECK-LABEL: @pkd1_pair
 #[no_mangle]
 pub fn pkd1_pair(pair1: &mut Packed1Pair, pair2: &mut Packed1Pair) {
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 5, i32 1, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 %{{.*}}, i8* align 1 %{{.*}}, i{{[0-9]+}} 5, i1 false)
     *pair2 = *pair1;
 }
 
 // CHECK-LABEL: @pkd2_pair
 #[no_mangle]
 pub fn pkd2_pair(pair1: &mut Packed2Pair, pair2: &mut Packed2Pair) {
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 6, i32 2, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 2 %{{.*}}, i8* align 2 %{{.*}}, i{{[0-9]+}} 6, i1 false)
     *pair2 = *pair1;
 }
 
@@ -115,14 +117,14 @@ pub struct Packed2NestedPair((u32, u32));
 // CHECK-LABEL: @pkd1_nested_pair
 #[no_mangle]
 pub fn pkd1_nested_pair(pair1: &mut Packed1NestedPair, pair2: &mut Packed1NestedPair) {
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 8, i32 1, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 %{{.*}}, i8* align 1 %{{.*}}, i{{[0-9]+}} 8, i1 false)
     *pair2 = *pair1;
 }
 
 // CHECK-LABEL: @pkd2_nested_pair
 #[no_mangle]
 pub fn pkd2_nested_pair(pair1: &mut Packed2NestedPair, pair2: &mut Packed2NestedPair) {
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 8, i32 2, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 2 %{{.*}}, i8* align 2 %{{.*}}, i{{[0-9]+}} 8, i1 false)
     *pair2 = *pair1;
 }
 
diff --git a/src/test/codegen/repeat-trusted-len.rs b/src/test/codegen/repeat-trusted-len.rs
index 8b3294281e9..8565335bd75 100644
--- a/src/test/codegen/repeat-trusted-len.rs
+++ b/src/test/codegen/repeat-trusted-len.rs
@@ -10,6 +10,7 @@
 
 // compile-flags: -O
 // ignore-tidy-linelength
+// min-llvm-version 7.0
 
 #![crate_type = "lib"]
 
@@ -23,6 +24,6 @@ pub fn helper(_: usize) {
 // CHECK-LABEL: @repeat_take_collect
 #[no_mangle]
 pub fn repeat_take_collect() -> Vec<u8> {
-// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}%{{[0-9]+}}, i8 42, [[USIZE]] 100000, i32 1, i1 false)
+// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1 %{{[0-9]+}}, i8 42, [[USIZE]] 100000, i1 false)
     iter::repeat(42).take(100000).collect()
 }
diff --git a/src/test/codegen/simd-intrinsic-float-minmax.rs b/src/test/codegen/simd-intrinsic-float-minmax.rs
index d963c7e8ddf..16f86735c2e 100644
--- a/src/test/codegen/simd-intrinsic-float-minmax.rs
+++ b/src/test/codegen/simd-intrinsic-float-minmax.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // ignore-emscripten
-// min-llvm-version 6.0
+// min-llvm-version 7.0
 
 // compile-flags: -C no-prepopulate-passes
 
@@ -34,10 +34,9 @@ pub unsafe fn fmin(a: f32x4, b: f32x4) -> f32x4 {
     simd_fmin(a, b)
 }
 
-// FIXME(49261)
-// // C_HECK-LABEL: @fmax
-// #[no_mangle]
-// pub unsafe fn fmax(a: f32x4, b: f32x4) -> f32x4 {
-// // C_HECK: call <4 x float> @llvm.maxnum.v4f32
-//     simd_fmax(a, b)
-// }
+// CHECK-LABEL: @fmax
+#[no_mangle]
+pub unsafe fn fmax(a: f32x4, b: f32x4) -> f32x4 {
+    // CHECK: call <4 x float> @llvm.maxnum.v4f32
+    simd_fmax(a, b)
+}
diff --git a/src/test/codegen/stores.rs b/src/test/codegen/stores.rs
index 08f5038fb18..0aaf00bfdbe 100644
--- a/src/test/codegen/stores.rs
+++ b/src/test/codegen/stores.rs
@@ -9,6 +9,8 @@
 // except according to those terms.
 
 // compile-flags: -C no-prepopulate-passes
+// ignore-tidy-linelength
+// min-llvm-version 7.0
 
 #![crate_type = "lib"]
 
@@ -29,7 +31,7 @@ pub fn small_array_alignment(x: &mut [i8; 4], y: [i8; 4]) {
 // CHECK: store i32 %0, i32* [[TMP]]
 // CHECK: [[Y8:%[0-9]+]] = bitcast [4 x i8]* %y to i8*
 // CHECK: [[TMP8:%[0-9]+]] = bitcast i32* [[TMP]] to i8*
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* [[Y8]], i8* [[TMP8]], i{{[0-9]+}} 4, i32 1, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 [[Y8]], i8* align 1 [[TMP8]], i{{[0-9]+}} 4, i1 false)
     *x = y;
 }
 
@@ -43,6 +45,6 @@ pub fn small_struct_alignment(x: &mut Bytes, y: Bytes) {
 // CHECK: store i32 %0, i32* [[TMP]]
 // CHECK: [[Y8:%[0-9]+]] = bitcast %Bytes* %y to i8*
 // CHECK: [[TMP8:%[0-9]+]] = bitcast i32* [[TMP]] to i8*
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* [[Y8]], i8* [[TMP8]], i{{[0-9]+}} 4, i32 1, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 [[Y8]], i8* align 1 [[TMP8]], i{{[0-9]+}} 4, i1 false)
     *x = y;
 }
diff --git a/src/test/run-make-fulldeps/pgo-gen-lto/Makefile b/src/test/run-make-fulldeps/pgo-gen-lto/Makefile
index e8c695f52be..6ec2978058d 100644
--- a/src/test/run-make-fulldeps/pgo-gen-lto/Makefile
+++ b/src/test/run-make-fulldeps/pgo-gen-lto/Makefile
@@ -2,7 +2,9 @@
 
 all:
 ifeq ($(PROFILER_SUPPORT),1)
+ifndef IS_WINDOWS
 	$(RUSTC) -Copt-level=3 -Clto=fat -Z pgo-gen="$(TMPDIR)/test.profraw" test.rs
 	$(call RUN,test) || exit 1
 	[ -e "$(TMPDIR)/test.profraw" ] || (echo "No .profraw file"; exit 1)
 endif
+endif
diff --git a/src/test/run-make-fulldeps/pgo-gen/Makefile b/src/test/run-make-fulldeps/pgo-gen/Makefile
index 7dc227b5a14..96126ab7a79 100644
--- a/src/test/run-make-fulldeps/pgo-gen/Makefile
+++ b/src/test/run-make-fulldeps/pgo-gen/Makefile
@@ -2,7 +2,9 @@
 
 all:
 ifeq ($(PROFILER_SUPPORT),1)
+ifndef IS_WINDOWS
 	$(RUSTC) -g -Z pgo-gen="$(TMPDIR)/test.profraw" test.rs
 	$(call RUN,test) || exit 1
 	[ -e "$(TMPDIR)/test.profraw" ] || (echo "No .profraw file"; exit 1)
 endif
+endif
diff --git a/src/test/run-pass/simd-intrinsic-float-math.rs b/src/test/run-pass/simd-intrinsic-float-math.rs
index 4597674b3f1..3c7ca21459f 100644
--- a/src/test/run-pass/simd-intrinsic-float-math.rs
+++ b/src/test/run-pass/simd-intrinsic-float-math.rs
@@ -41,6 +41,24 @@ extern "platform-intrinsic" {
     fn simd_fpowi<T>(x: T, y: i32) -> T;
 }
 
+macro_rules! assert_approx_eq_f32 {
+    ($a:expr, $b:expr) => ({
+        let (a, b) = (&$a, &$b);
+        assert!((*a - *b).abs() < 1.0e-6,
+                "{} is not approximately equal to {}", *a, *b);
+    })
+}
+macro_rules! assert_approx_eq {
+    ($a:expr, $b:expr) => ({
+        let a = $a;
+        let b = $b;
+        assert_approx_eq_f32!(a.0, b.0);
+        assert_approx_eq_f32!(a.1, b.1);
+        assert_approx_eq_f32!(a.2, b.2);
+        assert_approx_eq_f32!(a.3, b.3);
+    })
+}
+
 fn main() {
     let x = f32x4(1.0, 1.0, 1.0, 1.0);
     let y = f32x4(-1.0, -1.0, -1.0, -1.0);
@@ -50,45 +68,45 @@ fn main() {
 
     unsafe {
         let r = simd_fabs(y);
-        assert_eq!(x, r);
+        assert_approx_eq!(x, r);
 
         let r = simd_fcos(z);
-        assert_eq!(x, r);
+        assert_approx_eq!(x, r);
 
         let r = simd_ceil(h);
-        assert_eq!(x, r);
+        assert_approx_eq!(x, r);
 
         let r = simd_fexp(z);
-        assert_eq!(x, r);
+        assert_approx_eq!(x, r);
 
         let r = simd_fexp2(z);
-        assert_eq!(x, r);
+        assert_approx_eq!(x, r);
 
         let r = simd_floor(h);
-        assert_eq!(z, r);
+        assert_approx_eq!(z, r);
 
         let r = simd_fma(x, h, h);
-        assert_eq!(x, r);
+        assert_approx_eq!(x, r);
 
         let r = simd_fsqrt(x);
-        assert_eq!(x, r);
+        assert_approx_eq!(x, r);
 
         let r = simd_flog(x);
-        assert_eq!(z, r);
+        assert_approx_eq!(z, r);
 
         let r = simd_flog2(x);
-        assert_eq!(z, r);
+        assert_approx_eq!(z, r);
 
         let r = simd_flog10(x);
-        assert_eq!(z, r);
+        assert_approx_eq!(z, r);
 
         let r = simd_fpow(h, x);
-        assert_eq!(h, r);
+        assert_approx_eq!(h, r);
 
         let r = simd_fpowi(h, 1);
-        assert_eq!(h, r);
+        assert_approx_eq!(h, r);
 
         let r = simd_fsin(z);
-        assert_eq!(z, r);
+        assert_approx_eq!(z, r);
     }
 }
diff --git a/src/tools/lld b/src/tools/lld
-Subproject b87873eaceb75cf9342d5273f01ba2c020f61ca
+Subproject 8214ccf861d538671b0a1436dbf4538dc4a64d0