diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins index 4cfd7101eb5..86bf357a14c 160000 --- a/src/libcompiler_builtins +++ b/src/libcompiler_builtins @@ -1 +1 @@ -Subproject commit 4cfd7101eb549169cdaeda5313f7c39415b9d736 +Subproject commit 86bf357a14cacb4a4169455e729d409b5ecc1da0 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, pub target_features: Vec, pub linkage: Option, + pub wasm_custom_section: Option, } 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> 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> 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>, [] fn wasm_import_module_map: WasmImportModuleMap(CrateNum) -> Lrc>, } 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, -} - -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 } } @@ -919,11 +920,12 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec { 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>) { - 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>) { /// /// 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) { 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) { +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")); - 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"); + info!("loading wasm section {:?}", def_id); - let instance = ty::Instance::mono(tcx, id); + let section = cx.tcx.codegen_fn_attrs(def_id).wasm_custom_section.unwrap(); + + 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>, used_crates_static: Vec<(CrateNum, LibSource)>, used_crates_dynamic: Vec<(CrateNum, LibSource)>, - wasm_custom_sections: BTreeMap>, wasm_imports: FxHashMap, lang_item_to_crate: FxHashMap, missing_lang_items: FxHashMap>, 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 { - let sections = self.root - .wasm_custom_sections - .decode(self) - .map(|def_index| self.local_def_id(def_index)) - .collect::>(); - 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 { - info!("encoding custom wasm section constants {:?}", statics); - self.lazy_seq(statics.iter().map(|id| id.index)) - } - fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq> { 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, pub impls: LazySeq, pub exported_symbols: EncodedExportedSymbols, - pub wasm_custom_sections: LazySeq, pub interpret_alloc_index: LazySeq, pub index: LazySeq, 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 { .. 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 index 509f29ac178..03684905101 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 509f29ac17874394acf4d49d6bae3cd93c652aa1 +Subproject commit 03684905101f0b7e49dfe530e54dc1aeac6ef0fb 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 { #[no_mangle] pub fn low_align_const() -> E { // 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 { #[no_mangle] pub fn high_align_const() -> E { // 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 { -// 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(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 index b87873eaceb..8214ccf861d 160000 --- a/src/tools/lld +++ b/src/tools/lld @@ -1 +1 @@ -Subproject commit b87873eaceb75cf9342d5273f01ba2c020f61ca8 +Subproject commit 8214ccf861d538671b0a1436dbf4538dc4a64d09