diff --git a/src/Cargo.lock b/src/Cargo.lock index ce9fc63230d7c..f1088708c4e87 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -195,13 +195,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cargo" -version = "0.28.0" +version = "0.29.0" dependencies = [ "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crates-io 0.16.0", + "crates-io 0.17.0", "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -462,7 +462,7 @@ dependencies = [ [[package]] name = "crates-io" -version = "0.16.0" +version = "0.17.0" dependencies = [ "curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1652,7 +1652,7 @@ dependencies = [ name = "rls" version = "0.127.0" dependencies = [ - "cargo 0.28.0", + "cargo 0.29.0", "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "clippy_lints 0.0.197 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 220af6bd6e4af..4b6e266f1e55c 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -556,15 +556,6 @@ tool_extended!((self, builder), }; Miri, miri, "src/tools/miri", "miri", {}; Rls, rls, "src/tools/rls", "rls", { - let clippy = builder.ensure(Clippy { - compiler: self.compiler, - target: self.target, - extra_features: Vec::new(), - }); - let channel = &builder.config.channel; - if clippy.is_some() && channel != "stable" && channel != "beta" { - self.extra_features.push("clippy".to_owned()); - } builder.ensure(native::Openssl { target: self.target, }); diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index b8437e39ddca4..acd5c44c1a4d8 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -19,10 +19,10 @@ use super::{CombinedSnapshot, use super::combine::CombineFields; use super::region_constraints::{TaintDirections}; -use rustc_data_structures::lazy_btree_map::LazyBTreeMap; use ty::{self, TyCtxt, Binder, TypeFoldable}; use ty::error::TypeError; use ty::relate::{Relate, RelateResult, TypeRelation}; +use std::collections::BTreeMap; use syntax_pos::Span; use util::nodemap::{FxHashMap, FxHashSet}; @@ -247,8 +247,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { snapshot: &CombinedSnapshot<'a, 'tcx>, debruijn: ty::DebruijnIndex, new_vars: &[ty::RegionVid], - a_map: &LazyBTreeMap>, + a_map: &BTreeMap>, r0: ty::Region<'tcx>) -> ty::Region<'tcx> { // Regions that pre-dated the LUB computation stay as they are. @@ -344,8 +343,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { snapshot: &CombinedSnapshot<'a, 'tcx>, debruijn: ty::DebruijnIndex, new_vars: &[ty::RegionVid], - a_map: &LazyBTreeMap>, + a_map: &BTreeMap>, a_vars: &[ty::RegionVid], b_vars: &[ty::RegionVid], r0: ty::Region<'tcx>) @@ -414,7 +412,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { fn rev_lookup<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, span: Span, - a_map: &LazyBTreeMap>, + a_map: &BTreeMap>, r: ty::Region<'tcx>) -> ty::Region<'tcx> { for (a_br, a_r) in a_map { @@ -437,7 +435,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { } fn var_ids<'a, 'gcx, 'tcx>(fields: &CombineFields<'a, 'gcx, 'tcx>, - map: &LazyBTreeMap>) + map: &BTreeMap>) -> Vec { map.iter() .map(|(_, &r)| match *r { diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index c62e7f8d9b635..b72a25dec273b 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -28,9 +28,9 @@ use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; use ty::fold::TypeFoldable; use ty::relate::RelateResult; use traits::{self, ObligationCause, PredicateObligations}; -use rustc_data_structures::lazy_btree_map::LazyBTreeMap; use rustc_data_structures::unify as ut; use std::cell::{Cell, RefCell, Ref, RefMut}; +use std::collections::BTreeMap; use std::fmt; use syntax::ast; use errors::DiagnosticBuilder; @@ -198,7 +198,7 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// A map returned by `skolemize_late_bound_regions()` indicating the skolemized /// region that each late-bound region was replaced with. -pub type SkolemizationMap<'tcx> = LazyBTreeMap>; +pub type SkolemizationMap<'tcx> = BTreeMap>; /// See `error_reporting` module for more details #[derive(Clone, Debug)] @@ -1236,7 +1236,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { span: Span, lbrct: LateBoundRegionConversionTime, value: &ty::Binder) - -> (T, LazyBTreeMap>) + -> (T, BTreeMap>) where T : TypeFoldable<'tcx> { self.tcx.replace_late_bound_regions( diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 1793b5e1edba8..42adc82f48e5d 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -43,7 +43,7 @@ use middle::const_val::ConstVal; use hir::def_id::DefId; use ty::{self, Binder, Ty, TyCtxt, TypeFlags}; -use rustc_data_structures::lazy_btree_map::LazyBTreeMap; +use std::collections::BTreeMap; use std::fmt; use util::nodemap::FxHashSet; @@ -328,7 +328,7 @@ struct RegionReplacer<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, current_depth: u32, fld_r: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a), - map: LazyBTreeMap> + map: BTreeMap> } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { @@ -343,7 +343,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn replace_late_bound_regions(self, value: &Binder, mut f: F) - -> (T, LazyBTreeMap>) + -> (T, BTreeMap>) where F : FnMut(ty::BoundRegion) -> ty::Region<'tcx>, T : TypeFoldable<'tcx>, { @@ -456,7 +456,7 @@ impl<'a, 'gcx, 'tcx> RegionReplacer<'a, 'gcx, 'tcx> { tcx, current_depth: 1, fld_r, - map: LazyBTreeMap::default() + map: BTreeMap::default() } } } diff --git a/src/librustc_data_structures/lazy_btree_map.rs b/src/librustc_data_structures/lazy_btree_map.rs deleted file mode 100644 index 74f91af10fe63..0000000000000 --- a/src/librustc_data_structures/lazy_btree_map.rs +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::collections::btree_map; -use std::collections::BTreeMap; - -/// A thin wrapper around BTreeMap that avoids allocating upon creation. -/// -/// Vec, HashSet and HashMap all have the nice feature that they don't do any -/// heap allocation when creating a new structure of the default size. In -/// contrast, BTreeMap *does* allocate in that situation. The compiler uses -/// B-Tree maps in some places such that many maps are created but few are -/// inserted into, so having a BTreeMap alternative that avoids allocating on -/// creation is a performance win. -/// -/// Only a fraction of BTreeMap's functionality is currently supported. -/// Additional functionality should be added on demand. -#[derive(Debug)] -pub struct LazyBTreeMap(Option>); - -impl LazyBTreeMap { - pub fn new() -> LazyBTreeMap { - LazyBTreeMap(None) - } - - pub fn iter(&self) -> Iter { - Iter(self.0.as_ref().map(|btm| btm.iter())) - } - - pub fn is_empty(&self) -> bool { - self.0.as_ref().map_or(true, |btm| btm.is_empty()) - } -} - -impl LazyBTreeMap { - fn instantiate(&mut self) -> &mut BTreeMap { - if let Some(ref mut btm) = self.0 { - btm - } else { - let btm = BTreeMap::new(); - self.0 = Some(btm); - self.0.as_mut().unwrap() - } - } - - pub fn insert(&mut self, key: K, value: V) -> Option { - self.instantiate().insert(key, value) - } - - pub fn entry(&mut self, key: K) -> btree_map::Entry { - self.instantiate().entry(key) - } - - pub fn values<'a>(&'a self) -> Values<'a, K, V> { - Values(self.0.as_ref().map(|btm| btm.values())) - } -} - -impl Default for LazyBTreeMap { - fn default() -> LazyBTreeMap { - LazyBTreeMap::new() - } -} - -impl<'a, K: 'a, V: 'a> IntoIterator for &'a LazyBTreeMap { - type Item = (&'a K, &'a V); - type IntoIter = Iter<'a, K, V>; - - fn into_iter(self) -> Iter<'a, K, V> { - self.iter() - } -} - -pub struct Iter<'a, K: 'a, V: 'a>(Option>); - -impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> { - type Item = (&'a K, &'a V); - - fn next(&mut self) -> Option<(&'a K, &'a V)> { - self.0.as_mut().and_then(|iter| iter.next()) - } - - fn size_hint(&self) -> (usize, Option) { - self.0.as_ref().map_or_else(|| (0, Some(0)), |iter| iter.size_hint()) - } -} - -pub struct Values<'a, K: 'a, V: 'a>(Option>); - -impl<'a, K, V> Iterator for Values<'a, K, V> { - type Item = &'a V; - - fn next(&mut self) -> Option<&'a V> { - self.0.as_mut().and_then(|values| values.next()) - } - - fn size_hint(&self) -> (usize, Option) { - self.0.as_ref().map_or_else(|| (0, Some(0)), |values| values.size_hint()) - } -} - diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index b2e7450e76cdf..5bac1bd9a7b08 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -61,7 +61,6 @@ pub mod bitvec; pub mod graph; pub mod indexed_set; pub mod indexed_vec; -pub mod lazy_btree_map; pub mod obligation_forest; pub mod sip128; pub mod snapshot_map; diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 90b2fb4b59a70..335330d372c65 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -522,6 +522,15 @@ fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option { let t_f32 = Type::f32(cx); let t_f64 = Type::f64(cx); + let t_v2f32 = Type::vector(&t_f32, 2); + let t_v4f32 = Type::vector(&t_f32, 4); + let t_v8f32 = Type::vector(&t_f32, 8); + let t_v16f32 = Type::vector(&t_f32, 16); + + let t_v2f64 = Type::vector(&t_f64, 2); + let t_v4f64 = Type::vector(&t_f64, 4); + let t_v8f64 = Type::vector(&t_f64, 8); + ifn!("llvm.memcpy.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void); ifn!("llvm.memcpy.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void); ifn!("llvm.memcpy.p0i8.p0i8.i64", fn(i8p, i8p, t_i64, t_i32, i1) -> void); @@ -537,37 +546,145 @@ fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option { ifn!("llvm.frameaddress", fn(t_i32) -> i8p); ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32); + ifn!("llvm.powi.v2f32", fn(t_v2f32, t_i32) -> t_v2f32); + ifn!("llvm.powi.v4f32", fn(t_v4f32, t_i32) -> t_v4f32); + ifn!("llvm.powi.v8f32", fn(t_v8f32, t_i32) -> t_v8f32); + ifn!("llvm.powi.v16f32", fn(t_v16f32, t_i32) -> t_v16f32); ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64); + ifn!("llvm.powi.v2f64", fn(t_v2f64, t_i32) -> t_v2f64); + ifn!("llvm.powi.v4f64", fn(t_v4f64, t_i32) -> t_v4f64); + ifn!("llvm.powi.v8f64", fn(t_v8f64, t_i32) -> t_v8f64); + ifn!("llvm.pow.f32", fn(t_f32, t_f32) -> t_f32); + ifn!("llvm.pow.v2f32", fn(t_v2f32, t_v2f32) -> t_v2f32); + ifn!("llvm.pow.v4f32", fn(t_v4f32, t_v4f32) -> t_v4f32); + ifn!("llvm.pow.v8f32", fn(t_v8f32, t_v8f32) -> t_v8f32); + ifn!("llvm.pow.v16f32", fn(t_v16f32, t_v16f32) -> t_v16f32); ifn!("llvm.pow.f64", fn(t_f64, t_f64) -> t_f64); + ifn!("llvm.pow.v2f64", fn(t_v2f64, t_v2f64) -> t_v2f64); + ifn!("llvm.pow.v4f64", fn(t_v4f64, t_v4f64) -> t_v4f64); + ifn!("llvm.pow.v8f64", fn(t_v8f64, t_v8f64) -> t_v8f64); ifn!("llvm.sqrt.f32", fn(t_f32) -> t_f32); + ifn!("llvm.sqrt.v2f32", fn(t_v2f32) -> t_v2f32); + ifn!("llvm.sqrt.v4f32", fn(t_v4f32) -> t_v4f32); + ifn!("llvm.sqrt.v8f32", fn(t_v8f32) -> t_v8f32); + ifn!("llvm.sqrt.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.sqrt.f64", fn(t_f64) -> t_f64); + ifn!("llvm.sqrt.v2f64", fn(t_v2f64) -> t_v2f64); + ifn!("llvm.sqrt.v4f64", fn(t_v4f64) -> t_v4f64); + ifn!("llvm.sqrt.v8f64", fn(t_v8f64) -> t_v8f64); + ifn!("llvm.sin.f32", fn(t_f32) -> t_f32); + ifn!("llvm.sin.v2f32", fn(t_v2f32) -> t_v2f32); + ifn!("llvm.sin.v4f32", fn(t_v4f32) -> t_v4f32); + ifn!("llvm.sin.v8f32", fn(t_v8f32) -> t_v8f32); + ifn!("llvm.sin.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.sin.f64", fn(t_f64) -> t_f64); + ifn!("llvm.sin.v2f64", fn(t_v2f64) -> t_v2f64); + ifn!("llvm.sin.v4f64", fn(t_v4f64) -> t_v4f64); + ifn!("llvm.sin.v8f64", fn(t_v8f64) -> t_v8f64); + ifn!("llvm.cos.f32", fn(t_f32) -> t_f32); + ifn!("llvm.cos.v2f32", fn(t_v2f32) -> t_v2f32); + ifn!("llvm.cos.v4f32", fn(t_v4f32) -> t_v4f32); + ifn!("llvm.cos.v8f32", fn(t_v8f32) -> t_v8f32); + ifn!("llvm.cos.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.cos.f64", fn(t_f64) -> t_f64); + ifn!("llvm.cos.v2f64", fn(t_v2f64) -> t_v2f64); + ifn!("llvm.cos.v4f64", fn(t_v4f64) -> t_v4f64); + ifn!("llvm.cos.v8f64", fn(t_v8f64) -> t_v8f64); + ifn!("llvm.exp.f32", fn(t_f32) -> t_f32); + ifn!("llvm.exp.v2f32", fn(t_v2f32) -> t_v2f32); + ifn!("llvm.exp.v4f32", fn(t_v4f32) -> t_v4f32); + ifn!("llvm.exp.v8f32", fn(t_v8f32) -> t_v8f32); + ifn!("llvm.exp.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.exp.f64", fn(t_f64) -> t_f64); + ifn!("llvm.exp.v2f64", fn(t_v2f64) -> t_v2f64); + ifn!("llvm.exp.v4f64", fn(t_v4f64) -> t_v4f64); + ifn!("llvm.exp.v8f64", fn(t_v8f64) -> t_v8f64); + ifn!("llvm.exp2.f32", fn(t_f32) -> t_f32); + ifn!("llvm.exp2.v2f32", fn(t_v2f32) -> t_v2f32); + ifn!("llvm.exp2.v4f32", fn(t_v4f32) -> t_v4f32); + ifn!("llvm.exp2.v8f32", fn(t_v8f32) -> t_v8f32); + ifn!("llvm.exp2.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.exp2.f64", fn(t_f64) -> t_f64); + ifn!("llvm.exp2.v2f64", fn(t_v2f64) -> t_v2f64); + ifn!("llvm.exp2.v4f64", fn(t_v4f64) -> t_v4f64); + ifn!("llvm.exp2.v8f64", fn(t_v8f64) -> t_v8f64); + ifn!("llvm.log.f32", fn(t_f32) -> t_f32); + ifn!("llvm.log.v2f32", fn(t_v2f32) -> t_v2f32); + ifn!("llvm.log.v4f32", fn(t_v4f32) -> t_v4f32); + ifn!("llvm.log.v8f32", fn(t_v8f32) -> t_v8f32); + ifn!("llvm.log.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.log.f64", fn(t_f64) -> t_f64); + ifn!("llvm.log.v2f64", fn(t_v2f64) -> t_v2f64); + ifn!("llvm.log.v4f64", fn(t_v4f64) -> t_v4f64); + ifn!("llvm.log.v8f64", fn(t_v8f64) -> t_v8f64); + ifn!("llvm.log10.f32", fn(t_f32) -> t_f32); + ifn!("llvm.log10.v2f32", fn(t_v2f32) -> t_v2f32); + ifn!("llvm.log10.v4f32", fn(t_v4f32) -> t_v4f32); + ifn!("llvm.log10.v8f32", fn(t_v8f32) -> t_v8f32); + ifn!("llvm.log10.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.log10.f64", fn(t_f64) -> t_f64); + ifn!("llvm.log10.v2f64", fn(t_v2f64) -> t_v2f64); + ifn!("llvm.log10.v4f64", fn(t_v4f64) -> t_v4f64); + ifn!("llvm.log10.v8f64", fn(t_v8f64) -> t_v8f64); + ifn!("llvm.log2.f32", fn(t_f32) -> t_f32); + ifn!("llvm.log2.v2f32", fn(t_v2f32) -> t_v2f32); + ifn!("llvm.log2.v4f32", fn(t_v4f32) -> t_v4f32); + ifn!("llvm.log2.v8f32", fn(t_v8f32) -> t_v8f32); + ifn!("llvm.log2.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.log2.f64", fn(t_f64) -> t_f64); + ifn!("llvm.log2.v2f64", fn(t_v2f64) -> t_v2f64); + ifn!("llvm.log2.v4f64", fn(t_v4f64) -> t_v4f64); + ifn!("llvm.log2.v8f64", fn(t_v8f64) -> t_v8f64); ifn!("llvm.fma.f32", fn(t_f32, t_f32, t_f32) -> t_f32); + ifn!("llvm.fma.v2f32", fn(t_v2f32, t_v2f32, t_v2f32) -> t_v2f32); + ifn!("llvm.fma.v4f32", fn(t_v4f32, t_v4f32, t_v4f32) -> t_v4f32); + ifn!("llvm.fma.v8f32", fn(t_v8f32, t_v8f32, t_v8f32) -> t_v8f32); + ifn!("llvm.fma.v16f32", fn(t_v16f32, t_v16f32, t_v16f32) -> t_v16f32); ifn!("llvm.fma.f64", fn(t_f64, t_f64, t_f64) -> t_f64); + ifn!("llvm.fma.v2f64", fn(t_v2f64, t_v2f64, t_v2f64) -> t_v2f64); + ifn!("llvm.fma.v4f64", fn(t_v4f64, t_v4f64, t_v4f64) -> t_v4f64); + ifn!("llvm.fma.v8f64", fn(t_v8f64, t_v8f64, t_v8f64) -> t_v8f64); ifn!("llvm.fabs.f32", fn(t_f32) -> t_f32); + ifn!("llvm.fabs.v2f32", fn(t_v2f32) -> t_v2f32); + ifn!("llvm.fabs.v4f32", fn(t_v4f32) -> t_v4f32); + ifn!("llvm.fabs.v8f32", fn(t_v8f32) -> t_v8f32); + ifn!("llvm.fabs.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.fabs.f64", fn(t_f64) -> t_f64); + ifn!("llvm.fabs.v2f64", fn(t_v2f64) -> t_v2f64); + ifn!("llvm.fabs.v4f64", fn(t_v4f64) -> t_v4f64); + ifn!("llvm.fabs.v8f64", fn(t_v8f64) -> t_v8f64); ifn!("llvm.floor.f32", fn(t_f32) -> t_f32); + ifn!("llvm.floor.v2f32", fn(t_v2f32) -> t_v2f32); + ifn!("llvm.floor.v4f32", fn(t_v4f32) -> t_v4f32); + ifn!("llvm.floor.v8f32", fn(t_v8f32) -> t_v8f32); + ifn!("llvm.floor.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.floor.f64", fn(t_f64) -> t_f64); + ifn!("llvm.floor.v2f64", fn(t_v2f64) -> t_v2f64); + ifn!("llvm.floor.v4f64", fn(t_v4f64) -> t_v4f64); + ifn!("llvm.floor.v8f64", fn(t_v8f64) -> t_v8f64); + ifn!("llvm.ceil.f32", fn(t_f32) -> t_f32); + ifn!("llvm.ceil.v2f32", fn(t_v2f32) -> t_v2f32); + ifn!("llvm.ceil.v4f32", fn(t_v4f32) -> t_v4f32); + ifn!("llvm.ceil.v8f32", fn(t_v8f32) -> t_v8f32); + ifn!("llvm.ceil.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.ceil.f64", fn(t_f64) -> t_f64); + ifn!("llvm.ceil.v2f64", fn(t_v2f64) -> t_v2f64); + ifn!("llvm.ceil.v4f64", fn(t_v4f64) -> t_v4f64); + ifn!("llvm.ceil.v8f64", fn(t_v8f64) -> t_v8f64); + ifn!("llvm.trunc.f32", fn(t_f32) -> t_f32); ifn!("llvm.trunc.f64", fn(t_f64) -> t_f64); diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 86aa48b6a9e48..00cdcf4dca1a8 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -1152,6 +1152,389 @@ fn generic_simd_intrinsic<'a, 'tcx>( return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate())); } + fn simd_simple_float_intrinsic<'a, 'tcx>(name: &str, + in_elem: &::rustc::ty::TyS, + in_ty: &::rustc::ty::TyS, + in_len: usize, + bx: &Builder<'a, 'tcx>, + span: Span, + args: &[OperandRef<'tcx>]) + -> Result { + macro_rules! emit_error { + ($msg: tt) => { + emit_error!($msg, ) + }; + ($msg: tt, $($fmt: tt)*) => { + span_invalid_monomorphization_error( + bx.sess(), span, + &format!(concat!("invalid monomorphization of `{}` intrinsic: ", + $msg), + name, $($fmt)*)); + } + } + macro_rules! return_error { + ($($fmt: tt)*) => { + { + emit_error!($($fmt)*); + return Err(()); + } + } + } + let ety = match in_elem.sty { + ty::TyFloat(f) if f.bit_width() == 32 => { + if in_len < 2 || in_len > 16 { + return_error!( + "unsupported floating-point vector `{}` with length `{}` \ + out-of-range [2, 16]", + in_ty, in_len); + } + "f32" + }, + ty::TyFloat(f) if f.bit_width() == 64 => { + if in_len < 2 || in_len > 8 { + return_error!("unsupported floating-point vector `{}` with length `{}` \ + out-of-range [2, 8]", + in_ty, in_len); + } + "f64" + }, + ty::TyFloat(f) => { + return_error!("unsupported element type `{}` of floating-point vector `{}`", + f, in_ty); + }, + _ => { + return_error!("`{}` is not a floating-point type", in_ty); + } + }; + + let llvm_name = &format!("llvm.{0}.v{1}{2}", name, in_len, ety); + let intrinsic = bx.cx.get_intrinsic(&llvm_name); + let c = bx.call(intrinsic, + &args.iter().map(|arg| arg.immediate()).collect::>(), + None); + unsafe { llvm::LLVMRustSetHasUnsafeAlgebra(c) }; + return Ok(c); + } + + if name == "simd_fsqrt" { + return simd_simple_float_intrinsic("sqrt", in_elem, in_ty, in_len, bx, span, args); + } + + if name == "simd_fsin" { + return simd_simple_float_intrinsic("sin", in_elem, in_ty, in_len, bx, span, args); + } + + if name == "simd_fcos" { + return simd_simple_float_intrinsic("cos", in_elem, in_ty, in_len, bx, span, args); + } + + if name == "simd_fabs" { + return simd_simple_float_intrinsic("fabs", in_elem, in_ty, in_len, bx, span, args); + } + + if name == "simd_floor" { + return simd_simple_float_intrinsic("floor", in_elem, in_ty, in_len, bx, span, args); + } + + if name == "simd_ceil" { + return simd_simple_float_intrinsic("ceil", in_elem, in_ty, in_len, bx, span, args); + } + + if name == "simd_fexp" { + return simd_simple_float_intrinsic("exp", in_elem, in_ty, in_len, bx, span, args); + } + + if name == "simd_fexp2" { + return simd_simple_float_intrinsic("exp2", in_elem, in_ty, in_len, bx, span, args); + } + + if name == "simd_flog10" { + return simd_simple_float_intrinsic("log10", in_elem, in_ty, in_len, bx, span, args); + } + + if name == "simd_flog2" { + return simd_simple_float_intrinsic("log2", in_elem, in_ty, in_len, bx, span, args); + } + + if name == "simd_flog" { + return simd_simple_float_intrinsic("log", in_elem, in_ty, in_len, bx, span, args); + } + + if name == "simd_fpowi" { + return simd_simple_float_intrinsic("powi", in_elem, in_ty, in_len, bx, span, args); + } + + if name == "simd_fpow" { + return simd_simple_float_intrinsic("pow", in_elem, in_ty, in_len, bx, span, args); + } + + if name == "simd_fma" { + return simd_simple_float_intrinsic("fma", in_elem, in_ty, in_len, bx, span, args); + } + + if name == "simd_gather" { + // simd_gather(values: , pointers: , + // mask: ) -> + // * N: number of elements in the input vectors + // * T: type of the element to load + // * M: any integer width is supported, will be truncated to i1 + + // All types must be simd vector types + require_simd!(in_ty, "first"); + require_simd!(arg_tys[1], "second"); + require_simd!(arg_tys[2], "third"); + require_simd!(ret_ty, "return"); + + // Of the same length: + require!(in_len == arg_tys[1].simd_size(tcx), + "expected {} argument with length {} (same as input type `{}`), \ + found `{}` with length {}", "second", in_len, in_ty, arg_tys[1], + arg_tys[1].simd_size(tcx)); + require!(in_len == arg_tys[2].simd_size(tcx), + "expected {} argument with length {} (same as input type `{}`), \ + found `{}` with length {}", "third", in_len, in_ty, arg_tys[2], + arg_tys[2].simd_size(tcx)); + + // The return type must match the first argument type + require!(ret_ty == in_ty, + "expected return type `{}`, found `{}`", + in_ty, ret_ty); + + // This counts how many pointers + fn ptr_count(t: ty::Ty) -> usize { + match t.sty { + ty::TyRawPtr(p) => 1 + ptr_count(p.ty), + _ => 0, + } + } + + // Non-ptr type + fn non_ptr(t: ty::Ty) -> ty::Ty { + match t.sty { + ty::TyRawPtr(p) => non_ptr(p.ty), + _ => t, + } + } + + // The second argument must be a simd vector with an element type that's a pointer + // to the element type of the first argument + let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).sty { + ty::TyRawPtr(p) if p.ty == in_elem => (ptr_count(arg_tys[1].simd_type(tcx)), + non_ptr(arg_tys[1].simd_type(tcx))), + _ => { + require!(false, "expected element type `{}` of second argument `{}` \ + to be a pointer to the element type `{}` of the first \ + argument `{}`, found `{}` != `*_ {}`", + arg_tys[1].simd_type(tcx).sty, arg_tys[1], in_elem, in_ty, + arg_tys[1].simd_type(tcx).sty, in_elem); + unreachable!(); + } + }; + assert!(pointer_count > 0); + assert!(pointer_count - 1 == ptr_count(arg_tys[0].simd_type(tcx))); + assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx))); + + // The element type of the third argument must be a signed integer type of any width: + match arg_tys[2].simd_type(tcx).sty { + ty::TyInt(_) => (), + _ => { + require!(false, "expected element type `{}` of third argument `{}` \ + to be a signed integer type", + arg_tys[2].simd_type(tcx).sty, arg_tys[2]); + } + } + + // Alignment of T, must be a constant integer value: + let alignment_ty = Type::i32(bx.cx); + let alignment = C_i32(bx.cx, bx.cx.align_of(in_elem).abi() as i32); + + // Truncate the mask vector to a vector of i1s: + let (mask, mask_ty) = { + let i1 = Type::i1(bx.cx); + let i1xn = Type::vector(&i1, in_len as u64); + (bx.trunc(args[2].immediate(), i1xn), i1xn) + }; + + // FIXME: use: + // https://github.com/llvm-mirror/llvm/blob/master/include/llvm/IR/Function.h#L182 + // https://github.com/llvm-mirror/llvm/blob/master/include/llvm/IR/Intrinsics.h#L81 + fn llvm_vector_str(elem_ty: ty::Ty, vec_len: usize, no_pointers: usize) -> String { + let p0s: String = "p0".repeat(no_pointers); + match elem_ty.sty { + ty::TyInt(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()), + ty::TyUint(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()), + ty::TyFloat(v) => format!("v{}{}f{}", vec_len, p0s, v.bit_width()), + _ => unreachable!(), + } + } + + fn llvm_vector_ty(cx: &CodegenCx, elem_ty: ty::Ty, vec_len: usize, + mut no_pointers: usize) -> Type { + // FIXME: use cx.layout_of(ty).llvm_type() ? + let mut elem_ty = match elem_ty.sty { + ty::TyInt(v) => Type::int_from_ty(cx, v), + ty::TyUint(v) => Type::uint_from_ty(cx, v), + ty::TyFloat(v) => Type::float_from_ty(cx, v), + _ => unreachable!(), + }; + while no_pointers > 0 { + elem_ty = elem_ty.ptr_to(); + no_pointers -= 1; + } + Type::vector(&elem_ty, vec_len as u64) + } + + + // Type of the vector of pointers: + let llvm_pointer_vec_ty = llvm_vector_ty(bx.cx, underlying_ty, in_len, pointer_count); + let llvm_pointer_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count); + + // Type of the vector of elements: + let llvm_elem_vec_ty = llvm_vector_ty(bx.cx, underlying_ty, in_len, pointer_count - 1); + let llvm_elem_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count - 1); + + let llvm_intrinsic = format!("llvm.masked.gather.{}.{}", + llvm_elem_vec_str, llvm_pointer_vec_str); + let f = declare::declare_cfn(bx.cx, &llvm_intrinsic, + Type::func(&[llvm_pointer_vec_ty, alignment_ty, mask_ty, + llvm_elem_vec_ty], &llvm_elem_vec_ty)); + llvm::SetUnnamedAddr(f, false); + let v = bx.call(f, &[args[1].immediate(), alignment, mask, args[0].immediate()], + None); + return Ok(v); + } + + if name == "simd_scatter" { + // simd_scatter(values: , pointers: , + // mask: ) -> () + // * N: number of elements in the input vectors + // * T: type of the element to load + // * M: any integer width is supported, will be truncated to i1 + + // All types must be simd vector types + require_simd!(in_ty, "first"); + require_simd!(arg_tys[1], "second"); + require_simd!(arg_tys[2], "third"); + + // Of the same length: + require!(in_len == arg_tys[1].simd_size(tcx), + "expected {} argument with length {} (same as input type `{}`), \ + found `{}` with length {}", "second", in_len, in_ty, arg_tys[1], + arg_tys[1].simd_size(tcx)); + require!(in_len == arg_tys[2].simd_size(tcx), + "expected {} argument with length {} (same as input type `{}`), \ + found `{}` with length {}", "third", in_len, in_ty, arg_tys[2], + arg_tys[2].simd_size(tcx)); + + // This counts how many pointers + fn ptr_count(t: ty::Ty) -> usize { + match t.sty { + ty::TyRawPtr(p) => 1 + ptr_count(p.ty), + _ => 0, + } + } + + // Non-ptr type + fn non_ptr(t: ty::Ty) -> ty::Ty { + match t.sty { + ty::TyRawPtr(p) => non_ptr(p.ty), + _ => t, + } + } + + // The second argument must be a simd vector with an element type that's a pointer + // to the element type of the first argument + let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).sty { + ty::TyRawPtr(p) if p.ty == in_elem && p.mutbl == hir::MutMutable + => (ptr_count(arg_tys[1].simd_type(tcx)), + non_ptr(arg_tys[1].simd_type(tcx))), + _ => { + require!(false, "expected element type `{}` of second argument `{}` \ + to be a pointer to the element type `{}` of the first \ + argument `{}`, found `{}` != `*mut {}`", + arg_tys[1].simd_type(tcx).sty, arg_tys[1], in_elem, in_ty, + arg_tys[1].simd_type(tcx).sty, in_elem); + unreachable!(); + } + }; + assert!(pointer_count > 0); + assert!(pointer_count - 1 == ptr_count(arg_tys[0].simd_type(tcx))); + assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx))); + + // The element type of the third argument must be a signed integer type of any width: + match arg_tys[2].simd_type(tcx).sty { + ty::TyInt(_) => (), + _ => { + require!(false, "expected element type `{}` of third argument `{}` \ + to be a signed integer type", + arg_tys[2].simd_type(tcx).sty, arg_tys[2]); + } + } + + // Alignment of T, must be a constant integer value: + let alignment_ty = Type::i32(bx.cx); + let alignment = C_i32(bx.cx, bx.cx.align_of(in_elem).abi() as i32); + + // Truncate the mask vector to a vector of i1s: + let (mask, mask_ty) = { + let i1 = Type::i1(bx.cx); + let i1xn = Type::vector(&i1, in_len as u64); + (bx.trunc(args[2].immediate(), i1xn), i1xn) + }; + + let ret_t = Type::void(bx.cx); + + // FIXME: use: + // https://github.com/llvm-mirror/llvm/blob/master/include/llvm/IR/Function.h#L182 + // https://github.com/llvm-mirror/llvm/blob/master/include/llvm/IR/Intrinsics.h#L81 + fn llvm_vector_str(elem_ty: ty::Ty, vec_len: usize, no_pointers: usize) -> String { + let p0s: String = "p0".repeat(no_pointers); + match elem_ty.sty { + ty::TyInt(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()), + ty::TyUint(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()), + ty::TyFloat(v) => format!("v{}{}f{}", vec_len, p0s, v.bit_width()), + _ => unreachable!(), + } + } + + fn llvm_vector_ty(cx: &CodegenCx, elem_ty: ty::Ty, vec_len: usize, + mut no_pointers: usize) -> Type { + // FIXME: use cx.layout_of(ty).llvm_type() ? + let mut elem_ty = match elem_ty.sty { + ty::TyInt(v) => Type::int_from_ty(cx, v), + ty::TyUint(v) => Type::uint_from_ty(cx, v), + ty::TyFloat(v) => Type::float_from_ty(cx, v), + _ => unreachable!(), + }; + while no_pointers > 0 { + elem_ty = elem_ty.ptr_to(); + no_pointers -= 1; + } + Type::vector(&elem_ty, vec_len as u64) + } + + + // Type of the vector of pointers: + let llvm_pointer_vec_ty = llvm_vector_ty(bx.cx, underlying_ty, in_len, pointer_count); + let llvm_pointer_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count); + + // Type of the vector of elements: + let llvm_elem_vec_ty = llvm_vector_ty(bx.cx, underlying_ty, in_len, pointer_count - 1); + let llvm_elem_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count - 1); + + let llvm_intrinsic = format!("llvm.masked.scatter.{}.{}", + llvm_elem_vec_str, llvm_pointer_vec_str); + let f = declare::declare_cfn(bx.cx, &llvm_intrinsic, + Type::func(&[llvm_elem_vec_ty, + llvm_pointer_vec_ty, + alignment_ty, + mask_ty], &ret_t)); + llvm::SetUnnamedAddr(f, false); + let v = bx.call(f, &[args[0].immediate(), args[1].immediate(), alignment, mask], + None); + return Ok(v); + } + macro_rules! arith_red { ($name:tt : $integer_reduce:ident, $float_reduce:ident, $ordered:expr) => { if name == $name { diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index fcf7541a159b0..eefd6799d3d88 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -356,9 +356,26 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "simd_add" | "simd_sub" | "simd_mul" | "simd_rem" | "simd_div" | "simd_shl" | "simd_shr" | "simd_and" | "simd_or" | "simd_xor" | - "simd_fmin" | "simd_fmax" => { + "simd_fmin" | "simd_fmax" | "simd_fpow" => { (1, vec![param(0), param(0)], param(0)) } + "simd_fsqrt" | "simd_fsin" | "simd_fcos" | "simd_fexp" | "simd_fexp2" | + "simd_flog2" | "simd_flog10" | "simd_flog" | + "simd_fabs" | "simd_floor" | "simd_ceil" => { + (1, vec![param(0)], param(0)) + } + "simd_fpowi" => { + (1, vec![param(0), tcx.types.i32], param(0)) + } + "simd_fma" => { + (1, vec![param(0), param(0), param(0)], param(0)) + } + "simd_gather" => { + (3, vec![param(0), param(1), param(2)], param(0)) + } + "simd_scatter" => { + (3, vec![param(0), param(1), param(2)], tcx.mk_nil()) + } "simd_insert" => (2, vec![param(0), tcx.types.u32, param(1)], param(0)), "simd_extract" => (2, vec![param(0), tcx.types.u32], param(1)), "simd_cast" => (2, vec![param(0)], param(1)), diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 6222edd5450f0..c9a80d4779177 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -117,6 +117,57 @@ impl DocAccessLevels for AccessLevels { } } +/// Creates a new diagnostic `Handler` that can be used to emit warnings and errors. +/// +/// If the given `error_format` is `ErrorOutputType::Json` and no `CodeMap` is given, a new one +/// will be created for the handler. +pub fn new_handler(error_format: ErrorOutputType, codemap: Option>) + -> errors::Handler +{ + // rustdoc doesn't override (or allow to override) anything from this that is relevant here, so + // stick to the defaults + let sessopts = config::basic_options(); + let emitter: Box = match error_format { + ErrorOutputType::HumanReadable(color_config) => Box::new( + EmitterWriter::stderr( + color_config, + codemap.map(|cm| cm as _), + false, + sessopts.debugging_opts.teach, + ).ui_testing(sessopts.debugging_opts.ui_testing) + ), + ErrorOutputType::Json(pretty) => { + let codemap = codemap.unwrap_or_else( + || Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping()))); + Box::new( + JsonEmitter::stderr( + None, + codemap, + pretty, + sessopts.debugging_opts.suggestion_applicability, + ).ui_testing(sessopts.debugging_opts.ui_testing) + ) + }, + ErrorOutputType::Short(color_config) => Box::new( + EmitterWriter::stderr( + color_config, + codemap.map(|cm| cm as _), + true, + false) + ), + }; + + errors::Handler::with_emitter_and_flags( + emitter, + errors::HandlerFlags { + can_emit_warnings: true, + treat_err_as_bug: false, + external_macro_backtrace: false, + ..Default::default() + }, + ) +} + pub fn run_core(search_paths: SearchPaths, cfgs: Vec, externs: config::Externs, @@ -159,41 +210,11 @@ pub fn run_core(search_paths: SearchPaths, }, error_format, edition, - ..config::basic_options().clone() + ..config::basic_options() }; driver::spawn_thread_pool(sessopts, move |sessopts| { let codemap = Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping())); - let emitter: Box = match error_format { - ErrorOutputType::HumanReadable(color_config) => Box::new( - EmitterWriter::stderr( - color_config, - Some(codemap.clone()), - false, - sessopts.debugging_opts.teach, - ).ui_testing(sessopts.debugging_opts.ui_testing) - ), - ErrorOutputType::Json(pretty) => Box::new( - JsonEmitter::stderr( - None, - codemap.clone(), - pretty, - sessopts.debugging_opts.suggestion_applicability, - ).ui_testing(sessopts.debugging_opts.ui_testing) - ), - ErrorOutputType::Short(color_config) => Box::new( - EmitterWriter::stderr(color_config, Some(codemap.clone()), true, false) - ), - }; - - let diagnostic_handler = errors::Handler::with_emitter_and_flags( - emitter, - errors::HandlerFlags { - can_emit_warnings: true, - treat_err_as_bug: false, - external_macro_backtrace: false, - ..Default::default() - }, - ); + let diagnostic_handler = new_handler(error_format, Some(codemap.clone())); let mut sess = session::build_session_( sessopts, cpath, diagnostic_handler, codemap, diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 6c328a87208aa..10b6c9850ae77 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -11,6 +11,7 @@ use std::fs; use std::path::Path; use std::str; +use errors; use html::markdown::Markdown; #[derive(Clone)] @@ -28,23 +29,23 @@ pub struct ExternalHtml { impl ExternalHtml { pub fn load(in_header: &[String], before_content: &[String], after_content: &[String], - md_before_content: &[String], md_after_content: &[String]) + md_before_content: &[String], md_after_content: &[String], diag: &errors::Handler) -> Option { - load_external_files(in_header) + load_external_files(in_header, diag) .and_then(|ih| - load_external_files(before_content) + load_external_files(before_content, diag) .map(|bc| (ih, bc)) ) .and_then(|(ih, bc)| - load_external_files(md_before_content) + load_external_files(md_before_content, diag) .map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, &[])))) ) .and_then(|(ih, bc)| - load_external_files(after_content) + load_external_files(after_content, diag) .map(|ac| (ih, bc, ac)) ) .and_then(|(ih, bc, ac)| - load_external_files(md_after_content) + load_external_files(md_after_content, diag) .map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, &[])))) ) .map(|(ih, bc, ac)| @@ -62,28 +63,30 @@ pub enum LoadStringError { BadUtf8, } -pub fn load_string>(file_path: P) -> Result { +pub fn load_string>(file_path: P, diag: &errors::Handler) + -> Result +{ let file_path = file_path.as_ref(); let contents = match fs::read(file_path) { Ok(bytes) => bytes, Err(e) => { - eprintln!("error reading `{}`: {}", file_path.display(), e); + diag.struct_err(&format!("error reading `{}`: {}", file_path.display(), e)).emit(); return Err(LoadStringError::ReadFail); } }; match str::from_utf8(&contents) { Ok(s) => Ok(s.to_string()), Err(_) => { - eprintln!("error reading `{}`: not UTF-8", file_path.display()); + diag.struct_err(&format!("error reading `{}`: not UTF-8", file_path.display())).emit(); Err(LoadStringError::BadUtf8) } } } -fn load_external_files(names: &[String]) -> Option { +fn load_external_files(names: &[String], diag: &errors::Handler) -> Option { let mut out = String::new(); for name in names { - let s = match load_string(name) { + let s = match load_string(name, diag) { Ok(s) => s, Err(_) => return None, }; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index d4244bfdba075..7d98feaf53947 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -57,15 +57,13 @@ use errors::ColorConfig; use std::collections::{BTreeMap, BTreeSet}; use std::default::Default; use std::env; -use std::fmt::Display; -use std::io; -use std::io::Write; use std::path::{Path, PathBuf}; use std::process; use std::sync::mpsc::channel; use syntax::edition::Edition; use externalfiles::ExternalHtml; +use rustc::session::{early_warn, early_error}; use rustc::session::search_paths::SearchPaths; use rustc::session::config::{ErrorOutputType, RustcOptGroup, Externs, CodegenOptions}; use rustc::session::config::{nightly_options, build_codegen_options}; @@ -119,7 +117,8 @@ pub fn main() { fn get_args() -> Option> { env::args_os().enumerate() .map(|(i, arg)| arg.into_string().map_err(|arg| { - print_error(format!("Argument {} is not valid Unicode: {:?}", i, arg)); + early_warn(ErrorOutputType::default(), + &format!("Argument {} is not valid Unicode: {:?}", i, arg)); }).ok()) .collect() } @@ -324,16 +323,12 @@ pub fn main_args(args: &[String]) -> isize { let matches = match options.parse(&args[1..]) { Ok(m) => m, Err(err) => { - print_error(err); - return 1; + early_error(ErrorOutputType::default(), &err.to_string()); } }; // Check for unstable options. nightly_options::check_nightly_options(&matches, &opts()); - // check for deprecated options - check_deprecated_options(&matches); - if matches.opt_present("h") || matches.opt_present("help") { usage("rustdoc"); return 0; @@ -354,6 +349,35 @@ pub fn main_args(args: &[String]) -> isize { return 0; } + let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) { + Some("auto") => ColorConfig::Auto, + Some("always") => ColorConfig::Always, + Some("never") => ColorConfig::Never, + None => ColorConfig::Auto, + Some(arg) => { + early_error(ErrorOutputType::default(), + &format!("argument for --color must be `auto`, `always` or `never` \ + (instead was `{}`)", arg)); + } + }; + let error_format = match matches.opt_str("error-format").as_ref().map(|s| &s[..]) { + Some("human") => ErrorOutputType::HumanReadable(color), + Some("json") => ErrorOutputType::Json(false), + Some("pretty-json") => ErrorOutputType::Json(true), + Some("short") => ErrorOutputType::Short(color), + None => ErrorOutputType::HumanReadable(color), + Some(arg) => { + early_error(ErrorOutputType::default(), + &format!("argument for --error-format must be `human`, `json` or \ + `short` (instead was `{}`)", arg)); + } + }; + + let diag = core::new_handler(error_format, None); + + // check for deprecated options + check_deprecated_options(&matches, &diag); + let to_check = matches.opt_strs("theme-checker"); if !to_check.is_empty() { let paths = theme::load_css_paths(include_bytes!("html/static/themes/light.css")); @@ -362,7 +386,7 @@ pub fn main_args(args: &[String]) -> isize { println!("rustdoc: [theme-checker] Starting tests!"); for theme_file in to_check.iter() { print!(" - Checking \"{}\"...", theme_file); - let (success, differences) = theme::test_theme_against(theme_file, &paths); + let (success, differences) = theme::test_theme_against(theme_file, &paths, &diag); if !differences.is_empty() || !success { println!(" FAILED"); errors += 1; @@ -380,39 +404,15 @@ pub fn main_args(args: &[String]) -> isize { } if matches.free.is_empty() { - print_error("missing file operand"); + diag.struct_err("missing file operand").emit(); return 1; } if matches.free.len() > 1 { - print_error("too many file operands"); + diag.struct_err("too many file operands").emit(); return 1; } let input = &matches.free[0]; - let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) { - Some("auto") => ColorConfig::Auto, - Some("always") => ColorConfig::Always, - Some("never") => ColorConfig::Never, - None => ColorConfig::Auto, - Some(arg) => { - print_error(&format!("argument for --color must be `auto`, `always` or `never` \ - (instead was `{}`)", arg)); - return 1; - } - }; - let error_format = match matches.opt_str("error-format").as_ref().map(|s| &s[..]) { - Some("human") => ErrorOutputType::HumanReadable(color), - Some("json") => ErrorOutputType::Json(false), - Some("pretty-json") => ErrorOutputType::Json(true), - Some("short") => ErrorOutputType::Short(color), - None => ErrorOutputType::HumanReadable(color), - Some(arg) => { - print_error(&format!("argument for --error-format must be `human`, `json` or \ - `short` (instead was `{}`)", arg)); - return 1; - } - }; - let mut libs = SearchPaths::new(); for s in &matches.opt_strs("L") { libs.add_path(s, error_format); @@ -420,7 +420,7 @@ pub fn main_args(args: &[String]) -> isize { let externs = match parse_externs(&matches) { Ok(ex) => ex, Err(err) => { - print_error(err); + diag.struct_err(&err.to_string()).emit(); return 1; } }; @@ -441,10 +441,7 @@ pub fn main_args(args: &[String]) -> isize { if let Some(ref p) = css_file_extension { if !p.is_file() { - writeln!( - &mut io::stderr(), - "rustdoc: option --extend-css argument must be a file." - ).unwrap(); + diag.struct_err("option --extend-css argument must be a file").emit(); return 1; } } @@ -457,13 +454,14 @@ pub fn main_args(args: &[String]) -> isize { .iter() .map(|s| (PathBuf::from(&s), s.to_owned())) { if !theme_file.is_file() { - println!("rustdoc: option --themes arguments must all be files"); + diag.struct_err("option --themes arguments must all be files").emit(); return 1; } - let (success, ret) = theme::test_theme_against(&theme_file, &paths); + let (success, ret) = theme::test_theme_against(&theme_file, &paths, &diag); if !success || !ret.is_empty() { - println!("rustdoc: invalid theme: \"{}\"", theme_s); - println!(" Check what's wrong with the \"theme-checker\" option"); + diag.struct_err(&format!("invalid theme: \"{}\"", theme_s)) + .help("check what's wrong with the --theme-checker option") + .emit(); return 1; } themes.push(theme_file); @@ -475,7 +473,7 @@ pub fn main_args(args: &[String]) -> isize { &matches.opt_strs("html-before-content"), &matches.opt_strs("html-after-content"), &matches.opt_strs("markdown-before-content"), - &matches.opt_strs("markdown-after-content")) { + &matches.opt_strs("markdown-after-content"), &diag) { Some(eh) => eh, None => return 3, }; @@ -492,7 +490,7 @@ pub fn main_args(args: &[String]) -> isize { let edition = match edition.parse() { Ok(e) => e, Err(_) => { - print_error("could not parse edition"); + diag.struct_err("could not parse edition").emit(); return 1; } }; @@ -502,7 +500,7 @@ pub fn main_args(args: &[String]) -> isize { match (should_test, markdown_input) { (true, true) => { return markdown::test(input, cfgs, libs, externs, test_args, maybe_sysroot, - display_warnings, linker, edition, cg) + display_warnings, linker, edition, cg, &diag) } (true, false) => { return test::run(Path::new(input), cfgs, libs, externs, test_args, crate_name, @@ -511,7 +509,7 @@ pub fn main_args(args: &[String]) -> isize { (false, true) => return markdown::render(Path::new(input), output.unwrap_or(PathBuf::from("doc")), &matches, &external_html, - !matches.opt_present("markdown-no-toc")), + !matches.opt_present("markdown-no-toc"), &diag), (false, false) => {} } @@ -520,6 +518,7 @@ pub fn main_args(args: &[String]) -> isize { let res = acquire_input(PathBuf::from(input), externs, edition, cg, &matches, error_format, move |out| { let Output { krate, passes, renderinfo } = out; + let diag = core::new_handler(error_format, None); info!("going to format"); match output_format.as_ref().map(|s| &**s) { Some("html") | None => { @@ -536,26 +535,17 @@ pub fn main_args(args: &[String]) -> isize { 0 } Some(s) => { - print_error(format!("unknown output format: {}", s)); + diag.struct_err(&format!("unknown output format: {}", s)).emit(); 1 } } }); res.unwrap_or_else(|s| { - print_error(format!("input error: {}", s)); + diag.struct_err(&format!("input error: {}", s)).emit(); 1 }) } -/// Prints an uniformized error message on the standard error output -fn print_error(error_message: T) where T: Display { - writeln!( - &mut io::stderr(), - "rustdoc: {}\nTry 'rustdoc --help' for more information.", - error_message - ).unwrap(); -} - /// Looks inside the command line arguments to extract the relevant input format /// and files and then generates the necessary rustdoc output for formatting. fn acquire_input(input: PathBuf, @@ -722,7 +712,7 @@ where R: 'static + Send, } /// Prints deprecation warnings for deprecated options -fn check_deprecated_options(matches: &getopts::Matches) { +fn check_deprecated_options(matches: &getopts::Matches, diag: &errors::Handler) { let deprecated_flags = [ "input-format", "output-format", @@ -734,12 +724,15 @@ fn check_deprecated_options(matches: &getopts::Matches) { for flag in deprecated_flags.into_iter() { if matches.opt_present(flag) { - eprintln!("WARNING: the '{}' flag is considered deprecated", flag); - eprintln!("WARNING: please see https://github.com/rust-lang/rust/issues/44136"); - } - } + let mut err = diag.struct_warn(&format!("the '{}' flag is considered deprecated", + flag)); + err.warn("please see https://github.com/rust-lang/rust/issues/44136"); - if matches.opt_present("no-defaults") { - eprintln!("WARNING: (you may want to use --document-private-items)"); + if *flag == "no-defaults" { + err.help("you may want to use --document-private-items"); + } + + err.emit(); + } } } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 8ada5ce1a4df9..bf7b025884d5a 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -13,6 +13,7 @@ use std::fs::File; use std::io::prelude::*; use std::path::{PathBuf, Path}; +use errors; use getopts; use testing; use rustc::session::search_paths::SearchPaths; @@ -50,7 +51,7 @@ fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) { /// Render `input` (e.g. "foo.md") into an HTML file in `output` /// (e.g. output = "bar" => "bar/foo.html"). pub fn render(input: &Path, mut output: PathBuf, matches: &getopts::Matches, - external_html: &ExternalHtml, include_toc: bool) -> isize { + external_html: &ExternalHtml, include_toc: bool, diag: &errors::Handler) -> isize { output.push(input.file_stem().unwrap()); output.set_extension("html"); @@ -60,7 +61,7 @@ pub fn render(input: &Path, mut output: PathBuf, matches: &getopts::Matches, css.push_str(&s) } - let input_str = match load_string(input) { + let input_str = match load_string(input, diag) { Ok(s) => s, Err(LoadStringError::ReadFail) => return 1, Err(LoadStringError::BadUtf8) => return 2, @@ -72,7 +73,7 @@ pub fn render(input: &Path, mut output: PathBuf, matches: &getopts::Matches, let mut out = match File::create(&output) { Err(e) => { - eprintln!("rustdoc: {}: {}", output.display(), e); + diag.struct_err(&format!("{}: {}", output.display(), e)).emit(); return 4; } Ok(f) => f @@ -80,7 +81,7 @@ pub fn render(input: &Path, mut output: PathBuf, matches: &getopts::Matches, let (metadata, text) = extract_leading_metadata(&input_str); if metadata.is_empty() { - eprintln!("rustdoc: invalid markdown file: no initial lines starting with `# ` or `%`"); + diag.struct_err("invalid markdown file: no initial lines starting with `# ` or `%`").emit(); return 5; } let title = metadata[0]; @@ -130,7 +131,7 @@ pub fn render(input: &Path, mut output: PathBuf, matches: &getopts::Matches, match err { Err(e) => { - eprintln!("rustdoc: cannot write to `{}`: {}", output.display(), e); + diag.struct_err(&format!("cannot write to `{}`: {}", output.display(), e)).emit(); 6 } Ok(_) => 0, @@ -141,8 +142,8 @@ pub fn render(input: &Path, mut output: PathBuf, matches: &getopts::Matches, pub fn test(input: &str, cfgs: Vec, libs: SearchPaths, externs: Externs, mut test_args: Vec, maybe_sysroot: Option, display_warnings: bool, linker: Option, edition: Edition, - cg: CodegenOptions) -> isize { - let input_str = match load_string(input) { + cg: CodegenOptions, diag: &errors::Handler) -> isize { + let input_str = match load_string(input, diag) { Ok(s) => s, Err(LoadStringError::ReadFail) => return 1, Err(LoadStringError::BadUtf8) => return 2, diff --git a/src/librustdoc/theme.rs b/src/librustdoc/theme.rs index 1e4f64f5c52c9..96a67e0788758 100644 --- a/src/librustdoc/theme.rs +++ b/src/librustdoc/theme.rs @@ -14,12 +14,14 @@ use std::hash::{Hash, Hasher}; use std::io::Read; use std::path::Path; +use errors::Handler; + macro_rules! try_something { - ($e:expr, $out:expr) => ({ + ($e:expr, $diag:expr, $out:expr) => ({ match $e { Ok(c) => c, Err(e) => { - eprintln!("rustdoc: got an error: {}", e); + $diag.struct_err(&e.to_string()).emit(); return $out; } } @@ -273,11 +275,13 @@ pub fn get_differences(against: &CssPath, other: &CssPath, v: &mut Vec) } } -pub fn test_theme_against>(f: &P, against: &CssPath) -> (bool, Vec) { - let mut file = try_something!(File::open(f), (false, Vec::new())); +pub fn test_theme_against>(f: &P, against: &CssPath, diag: &Handler) + -> (bool, Vec) +{ + let mut file = try_something!(File::open(f), diag, (false, Vec::new())); let mut data = Vec::with_capacity(1000); - try_something!(file.read_to_end(&mut data), (false, Vec::new())); + try_something!(file.read_to_end(&mut data), diag, (false, Vec::new())); let paths = load_css_paths(&data); let mut ret = Vec::new(); get_differences(against, &paths, &mut ret); diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index 67546d06b4e55..4830e38d6a92f 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -154,6 +154,13 @@ impl FileDesc { } } + #[cfg(target_os = "linux")] + pub fn get_cloexec(&self) -> io::Result { + unsafe { + Ok((cvt(libc::fcntl(self.fd, libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) + } + } + #[cfg(not(any(target_env = "newlib", target_os = "solaris", target_os = "emscripten", diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index a1ca839dc1872..77968ffdedf37 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -441,15 +441,48 @@ impl File { // Currently the standard library supports Linux 2.6.18 which did not // have the O_CLOEXEC flag (passed above). If we're running on an older - // Linux kernel then the flag is just ignored by the OS, so we continue - // to explicitly ask for a CLOEXEC fd here. + // Linux kernel then the flag is just ignored by the OS. After we open + // the first file, we check whether it has CLOEXEC set. If it doesn't, + // we will explicitly ask for a CLOEXEC fd for every further file we + // open, if it does, we will skip that step. // // The CLOEXEC flag, however, is supported on versions of macOS/BSD/etc // that we support, so we only do this on Linux currently. - if cfg!(target_os = "linux") { - fd.set_cloexec()?; + #[cfg(target_os = "linux")] + fn ensure_cloexec(fd: &FileDesc) -> io::Result<()> { + use sync::atomic::{AtomicUsize, Ordering}; + + const OPEN_CLOEXEC_UNKNOWN: usize = 0; + const OPEN_CLOEXEC_SUPPORTED: usize = 1; + const OPEN_CLOEXEC_NOTSUPPORTED: usize = 2; + static OPEN_CLOEXEC: AtomicUsize = AtomicUsize::new(OPEN_CLOEXEC_UNKNOWN); + + let need_to_set; + match OPEN_CLOEXEC.load(Ordering::Relaxed) { + OPEN_CLOEXEC_UNKNOWN => { + need_to_set = !fd.get_cloexec()?; + OPEN_CLOEXEC.store(if need_to_set { + OPEN_CLOEXEC_NOTSUPPORTED + } else { + OPEN_CLOEXEC_SUPPORTED + }, Ordering::Relaxed); + }, + OPEN_CLOEXEC_SUPPORTED => need_to_set = false, + OPEN_CLOEXEC_NOTSUPPORTED => need_to_set = true, + _ => unreachable!(), + } + if need_to_set { + fd.set_cloexec()?; + } + Ok(()) + } + + #[cfg(not(target_os = "linux"))] + fn ensure_cloexec(_: &FileDesc) -> io::Result<()> { + Ok(()) } + ensure_cloexec(&fd)?; Ok(File(fd)) } diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index ec9b6f17dca1c..0a5dccddddae2 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -100,24 +100,6 @@ pub fn read2(p1: AnonPipe, // wait for either pipe to become readable using `poll` cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?; - // Read as much as we can from each pipe, ignoring EWOULDBLOCK or - // EAGAIN. If we hit EOF, then this will happen because the underlying - // reader will return Ok(0), in which case we'll see `Ok` ourselves. In - // this case we flip the other fd back into blocking mode and read - // whatever's leftover on that file descriptor. - let read = |fd: &FileDesc, dst: &mut Vec| { - match fd.read_to_end(dst) { - Ok(_) => Ok(true), - Err(e) => { - if e.raw_os_error() == Some(libc::EWOULDBLOCK) || - e.raw_os_error() == Some(libc::EAGAIN) { - Ok(false) - } else { - Err(e) - } - } - } - }; if fds[0].revents != 0 && read(&p1, v1)? { p2.set_nonblocking(false)?; return p2.read_to_end(v2).map(|_| ()); @@ -127,4 +109,23 @@ pub fn read2(p1: AnonPipe, return p1.read_to_end(v1).map(|_| ()); } } + + // Read as much as we can from each pipe, ignoring EWOULDBLOCK or + // EAGAIN. If we hit EOF, then this will happen because the underlying + // reader will return Ok(0), in which case we'll see `Ok` ourselves. In + // this case we flip the other fd back into blocking mode and read + // whatever's leftover on that file descriptor. + fn read(fd: &FileDesc, dst: &mut Vec) -> Result { + match fd.read_to_end(dst) { + Ok(_) => Ok(true), + Err(e) => { + if e.raw_os_error() == Some(libc::EWOULDBLOCK) || + e.raw_os_error() == Some(libc::EAGAIN) { + Ok(false) + } else { + Err(e) + } + } + } + } } diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index e1eabc5cb0145..369c5b1ff60db 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -179,9 +179,11 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, let (constraint, _str_style) = panictry!(p.parse_str()); if constraint.as_str().starts_with("=") { - cx.span_err(p.prev_span, "input operand constraint contains '='"); + span_err_if_not_stage0!(cx, p.prev_span, E0662, + "input operand constraint contains '='"); } else if constraint.as_str().starts_with("+") { - cx.span_err(p.prev_span, "input operand constraint contains '+'"); + span_err_if_not_stage0!(cx, p.prev_span, E0663, + "input operand constraint contains '+'"); } panictry!(p.expect(&token::OpenDelim(token::Paren))); @@ -203,7 +205,8 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, if OPTIONS.iter().any(|&opt| s == opt) { cx.span_warn(p.prev_span, "expected a clobber, found an option"); } else if s.as_str().starts_with("{") || s.as_str().ends_with("}") { - cx.span_err(p.prev_span, "clobber should not be surrounded by braces"); + span_err_if_not_stage0!(cx, p.prev_span, E0664, + "clobber should not be surrounded by braces"); } clobs.push(s); diff --git a/src/libsyntax_ext/diagnostics.rs b/src/libsyntax_ext/diagnostics.rs index a840c0392e9fe..33ae24c37e53f 100644 --- a/src/libsyntax_ext/diagnostics.rs +++ b/src/libsyntax_ext/diagnostics.rs @@ -38,6 +38,58 @@ let a; asm!("nop" : "r"(a)); ``` +Considering that this would be a long explanation, we instead recommend you to +take a look at the unstable book: +https://doc.rust-lang.org/unstable-book/language-features/asm.html +"##, + +E0662: r##" +An invalid input operand constraint was passed to the `asm` macro (third line). + +Erroneous code example: + +```compile_fail,E0662 +asm!("xor %eax, %eax" + : + : "=test"("a") + ); +``` + +Considering that this would be a long explanation, we instead recommend you to +take a look at the unstable book: +https://doc.rust-lang.org/unstable-book/language-features/asm.html +"##, + +E0663: r##" +An invalid input operand constraint was passed to the `asm` macro (third line). + +Erroneous code example: + +```compile_fail,E0663 +asm!("xor %eax, %eax" + : + : "+test"("a") + ); +``` + +Considering that this would be a long explanation, we instead recommend you to +take a look at the unstable book: +https://doc.rust-lang.org/unstable-book/language-features/asm.html +"##, + +E0664: r##" +A clobber was surrounded by braces in the `asm` macro. + +Erroneous code example: + +```compile_fail,E0663 +asm!("mov $$0x200, %eax" + : + : + : "{eax}" + ); +``` + Considering that this would be a long explanation, we instead recommend you to take a look at the unstable book: https://doc.rust-lang.org/unstable-book/language-features/asm.html diff --git a/src/test/codegen/simd-intrinsic-float-abs.rs b/src/test/codegen/simd-intrinsic-float-abs.rs new file mode 100644 index 0000000000000..49f1f3e8565c6 --- /dev/null +++ b/src/test/codegen/simd-intrinsic-float-abs.rs @@ -0,0 +1,104 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x2(pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x8(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x16(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_fabs(x: T) -> T; +} + +// CHECK-LABEL: @fabs_32x2 +#[no_mangle] +pub unsafe fn fabs_32x2(a: f32x2) -> f32x2 { + // CHECK: call fast <2 x float> @llvm.fabs.v2f32 + simd_fabs(a) +} + +// CHECK-LABEL: @fabs_32x4 +#[no_mangle] +pub unsafe fn fabs_32x4(a: f32x4) -> f32x4 { + // CHECK: call fast <4 x float> @llvm.fabs.v4f32 + simd_fabs(a) +} + +// CHECK-LABEL: @fabs_32x8 +#[no_mangle] +pub unsafe fn fabs_32x8(a: f32x8) -> f32x8 { + // CHECK: call fast <8 x float> @llvm.fabs.v8f32 + simd_fabs(a) +} + +// CHECK-LABEL: @fabs_32x16 +#[no_mangle] +pub unsafe fn fabs_32x16(a: f32x16) -> f32x16 { + // CHECK: call fast <16 x float> @llvm.fabs.v16f32 + simd_fabs(a) +} + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x2(pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x4(pub f64, pub f64, pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x8(pub f64, pub f64, pub f64, pub f64, + pub f64, pub f64, pub f64, pub f64); + +// CHECK-LABEL: @fabs_64x4 +#[no_mangle] +pub unsafe fn fabs_64x4(a: f64x4) -> f64x4 { + // CHECK: call fast <4 x double> @llvm.fabs.v4f64 + simd_fabs(a) +} + +// CHECK-LABEL: @fabs_64x2 +#[no_mangle] +pub unsafe fn fabs_64x2(a: f64x2) -> f64x2 { + // CHECK: call fast <2 x double> @llvm.fabs.v2f64 + simd_fabs(a) +} + +// CHECK-LABEL: @fabs_64x8 +#[no_mangle] +pub unsafe fn fabs_64x8(a: f64x8) -> f64x8 { + // CHECK: call fast <8 x double> @llvm.fabs.v8f64 + simd_fabs(a) +} diff --git a/src/test/codegen/simd-intrinsic-float-ceil.rs b/src/test/codegen/simd-intrinsic-float-ceil.rs new file mode 100644 index 0000000000000..4a6f162e16b1b --- /dev/null +++ b/src/test/codegen/simd-intrinsic-float-ceil.rs @@ -0,0 +1,104 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x2(pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x8(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x16(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_ceil(x: T) -> T; +} + +// CHECK-LABEL: @ceil_32x2 +#[no_mangle] +pub unsafe fn ceil_32x2(a: f32x2) -> f32x2 { + // CHECK: call fast <2 x float> @llvm.ceil.v2f32 + simd_ceil(a) +} + +// CHECK-LABEL: @ceil_32x4 +#[no_mangle] +pub unsafe fn ceil_32x4(a: f32x4) -> f32x4 { + // CHECK: call fast <4 x float> @llvm.ceil.v4f32 + simd_ceil(a) +} + +// CHECK-LABEL: @ceil_32x8 +#[no_mangle] +pub unsafe fn ceil_32x8(a: f32x8) -> f32x8 { + // CHECK: call fast <8 x float> @llvm.ceil.v8f32 + simd_ceil(a) +} + +// CHECK-LABEL: @ceil_32x16 +#[no_mangle] +pub unsafe fn ceil_32x16(a: f32x16) -> f32x16 { + // CHECK: call fast <16 x float> @llvm.ceil.v16f32 + simd_ceil(a) +} + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x2(pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x4(pub f64, pub f64, pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x8(pub f64, pub f64, pub f64, pub f64, + pub f64, pub f64, pub f64, pub f64); + +// CHECK-LABEL: @ceil_64x4 +#[no_mangle] +pub unsafe fn ceil_64x4(a: f64x4) -> f64x4 { + // CHECK: call fast <4 x double> @llvm.ceil.v4f64 + simd_ceil(a) +} + +// CHECK-LABEL: @ceil_64x2 +#[no_mangle] +pub unsafe fn ceil_64x2(a: f64x2) -> f64x2 { + // CHECK: call fast <2 x double> @llvm.ceil.v2f64 + simd_ceil(a) +} + +// CHECK-LABEL: @ceil_64x8 +#[no_mangle] +pub unsafe fn ceil_64x8(a: f64x8) -> f64x8 { + // CHECK: call fast <8 x double> @llvm.ceil.v8f64 + simd_ceil(a) +} diff --git a/src/test/codegen/simd-intrinsic-float-cos.rs b/src/test/codegen/simd-intrinsic-float-cos.rs new file mode 100644 index 0000000000000..6304c6c644f42 --- /dev/null +++ b/src/test/codegen/simd-intrinsic-float-cos.rs @@ -0,0 +1,104 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x2(pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x8(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x16(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_fcos(x: T) -> T; +} + +// CHECK-LABEL: @fcos_32x2 +#[no_mangle] +pub unsafe fn fcos_32x2(a: f32x2) -> f32x2 { + // CHECK: call fast <2 x float> @llvm.cos.v2f32 + simd_fcos(a) +} + +// CHECK-LABEL: @fcos_32x4 +#[no_mangle] +pub unsafe fn fcos_32x4(a: f32x4) -> f32x4 { + // CHECK: call fast <4 x float> @llvm.cos.v4f32 + simd_fcos(a) +} + +// CHECK-LABEL: @fcos_32x8 +#[no_mangle] +pub unsafe fn fcos_32x8(a: f32x8) -> f32x8 { + // CHECK: call fast <8 x float> @llvm.cos.v8f32 + simd_fcos(a) +} + +// CHECK-LABEL: @fcos_32x16 +#[no_mangle] +pub unsafe fn fcos_32x16(a: f32x16) -> f32x16 { + // CHECK: call fast <16 x float> @llvm.cos.v16f32 + simd_fcos(a) +} + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x2(pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x4(pub f64, pub f64, pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x8(pub f64, pub f64, pub f64, pub f64, + pub f64, pub f64, pub f64, pub f64); + +// CHECK-LABEL: @fcos_64x4 +#[no_mangle] +pub unsafe fn fcos_64x4(a: f64x4) -> f64x4 { + // CHECK: call fast <4 x double> @llvm.cos.v4f64 + simd_fcos(a) +} + +// CHECK-LABEL: @fcos_64x2 +#[no_mangle] +pub unsafe fn fcos_64x2(a: f64x2) -> f64x2 { + // CHECK: call fast <2 x double> @llvm.cos.v2f64 + simd_fcos(a) +} + +// CHECK-LABEL: @fcos_64x8 +#[no_mangle] +pub unsafe fn fcos_64x8(a: f64x8) -> f64x8 { + // CHECK: call fast <8 x double> @llvm.cos.v8f64 + simd_fcos(a) +} diff --git a/src/test/codegen/simd-intrinsic-float-exp.rs b/src/test/codegen/simd-intrinsic-float-exp.rs new file mode 100644 index 0000000000000..110031c645143 --- /dev/null +++ b/src/test/codegen/simd-intrinsic-float-exp.rs @@ -0,0 +1,104 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x2(pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x8(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x16(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_fexp(x: T) -> T; +} + +// CHECK-LABEL: @exp_32x2 +#[no_mangle] +pub unsafe fn exp_32x2(a: f32x2) -> f32x2 { + // CHECK: call fast <2 x float> @llvm.exp.v2f32 + simd_fexp(a) +} + +// CHECK-LABEL: @exp_32x4 +#[no_mangle] +pub unsafe fn exp_32x4(a: f32x4) -> f32x4 { + // CHECK: call fast <4 x float> @llvm.exp.v4f32 + simd_fexp(a) +} + +// CHECK-LABEL: @exp_32x8 +#[no_mangle] +pub unsafe fn exp_32x8(a: f32x8) -> f32x8 { + // CHECK: call fast <8 x float> @llvm.exp.v8f32 + simd_fexp(a) +} + +// CHECK-LABEL: @exp_32x16 +#[no_mangle] +pub unsafe fn exp_32x16(a: f32x16) -> f32x16 { + // CHECK: call fast <16 x float> @llvm.exp.v16f32 + simd_fexp(a) +} + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x2(pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x4(pub f64, pub f64, pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x8(pub f64, pub f64, pub f64, pub f64, + pub f64, pub f64, pub f64, pub f64); + +// CHECK-LABEL: @exp_64x4 +#[no_mangle] +pub unsafe fn exp_64x4(a: f64x4) -> f64x4 { + // CHECK: call fast <4 x double> @llvm.exp.v4f64 + simd_fexp(a) +} + +// CHECK-LABEL: @exp_64x2 +#[no_mangle] +pub unsafe fn exp_64x2(a: f64x2) -> f64x2 { + // CHECK: call fast <2 x double> @llvm.exp.v2f64 + simd_fexp(a) +} + +// CHECK-LABEL: @exp_64x8 +#[no_mangle] +pub unsafe fn exp_64x8(a: f64x8) -> f64x8 { + // CHECK: call fast <8 x double> @llvm.exp.v8f64 + simd_fexp(a) +} diff --git a/src/test/codegen/simd-intrinsic-float-exp2.rs b/src/test/codegen/simd-intrinsic-float-exp2.rs new file mode 100644 index 0000000000000..dc62c90822f0c --- /dev/null +++ b/src/test/codegen/simd-intrinsic-float-exp2.rs @@ -0,0 +1,104 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x2(pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x8(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x16(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_fexp2(x: T) -> T; +} + +// CHECK-LABEL: @exp2_32x2 +#[no_mangle] +pub unsafe fn exp2_32x2(a: f32x2) -> f32x2 { + // CHECK: call fast <2 x float> @llvm.exp2.v2f32 + simd_fexp2(a) +} + +// CHECK-LABEL: @exp2_32x4 +#[no_mangle] +pub unsafe fn exp2_32x4(a: f32x4) -> f32x4 { + // CHECK: call fast <4 x float> @llvm.exp2.v4f32 + simd_fexp2(a) +} + +// CHECK-LABEL: @exp2_32x8 +#[no_mangle] +pub unsafe fn exp2_32x8(a: f32x8) -> f32x8 { + // CHECK: call fast <8 x float> @llvm.exp2.v8f32 + simd_fexp2(a) +} + +// CHECK-LABEL: @exp2_32x16 +#[no_mangle] +pub unsafe fn exp2_32x16(a: f32x16) -> f32x16 { + // CHECK: call fast <16 x float> @llvm.exp2.v16f32 + simd_fexp2(a) +} + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x2(pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x4(pub f64, pub f64, pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x8(pub f64, pub f64, pub f64, pub f64, + pub f64, pub f64, pub f64, pub f64); + +// CHECK-LABEL: @exp2_64x4 +#[no_mangle] +pub unsafe fn exp2_64x4(a: f64x4) -> f64x4 { + // CHECK: call fast <4 x double> @llvm.exp2.v4f64 + simd_fexp2(a) +} + +// CHECK-LABEL: @exp2_64x2 +#[no_mangle] +pub unsafe fn exp2_64x2(a: f64x2) -> f64x2 { + // CHECK: call fast <2 x double> @llvm.exp2.v2f64 + simd_fexp2(a) +} + +// CHECK-LABEL: @exp2_64x8 +#[no_mangle] +pub unsafe fn exp2_64x8(a: f64x8) -> f64x8 { + // CHECK: call fast <8 x double> @llvm.exp2.v8f64 + simd_fexp2(a) +} diff --git a/src/test/codegen/simd-intrinsic-float-floor.rs b/src/test/codegen/simd-intrinsic-float-floor.rs new file mode 100644 index 0000000000000..9bc8ca0d1527f --- /dev/null +++ b/src/test/codegen/simd-intrinsic-float-floor.rs @@ -0,0 +1,104 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x2(pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x8(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x16(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_floor(x: T) -> T; +} + +// CHECK-LABEL: @floor_32x2 +#[no_mangle] +pub unsafe fn floor_32x2(a: f32x2) -> f32x2 { + // CHECK: call fast <2 x float> @llvm.floor.v2f32 + simd_floor(a) +} + +// CHECK-LABEL: @floor_32x4 +#[no_mangle] +pub unsafe fn floor_32x4(a: f32x4) -> f32x4 { + // CHECK: call fast <4 x float> @llvm.floor.v4f32 + simd_floor(a) +} + +// CHECK-LABEL: @floor_32x8 +#[no_mangle] +pub unsafe fn floor_32x8(a: f32x8) -> f32x8 { + // CHECK: call fast <8 x float> @llvm.floor.v8f32 + simd_floor(a) +} + +// CHECK-LABEL: @floor_32x16 +#[no_mangle] +pub unsafe fn floor_32x16(a: f32x16) -> f32x16 { + // CHECK: call fast <16 x float> @llvm.floor.v16f32 + simd_floor(a) +} + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x2(pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x4(pub f64, pub f64, pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x8(pub f64, pub f64, pub f64, pub f64, + pub f64, pub f64, pub f64, pub f64); + +// CHECK-LABEL: @floor_64x4 +#[no_mangle] +pub unsafe fn floor_64x4(a: f64x4) -> f64x4 { + // CHECK: call fast <4 x double> @llvm.floor.v4f64 + simd_floor(a) +} + +// CHECK-LABEL: @floor_64x2 +#[no_mangle] +pub unsafe fn floor_64x2(a: f64x2) -> f64x2 { + // CHECK: call fast <2 x double> @llvm.floor.v2f64 + simd_floor(a) +} + +// CHECK-LABEL: @floor_64x8 +#[no_mangle] +pub unsafe fn floor_64x8(a: f64x8) -> f64x8 { + // CHECK: call fast <8 x double> @llvm.floor.v8f64 + simd_floor(a) +} diff --git a/src/test/codegen/simd-intrinsic-float-fma.rs b/src/test/codegen/simd-intrinsic-float-fma.rs new file mode 100644 index 0000000000000..acd7f717214f1 --- /dev/null +++ b/src/test/codegen/simd-intrinsic-float-fma.rs @@ -0,0 +1,104 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x2(pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x8(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x16(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_fma(x: T, b: T, c: T) -> T; +} + +// CHECK-LABEL: @fma_32x2 +#[no_mangle] +pub unsafe fn fma_32x2(a: f32x2, b: f32x2, c: f32x2) -> f32x2 { + // CHECK: call fast <2 x float> @llvm.fma.v2f32 + simd_fma(a, b, c) +} + +// CHECK-LABEL: @fma_32x4 +#[no_mangle] +pub unsafe fn fma_32x4(a: f32x4, b: f32x4, c: f32x4) -> f32x4 { + // CHECK: call fast <4 x float> @llvm.fma.v4f32 + simd_fma(a, b, c) +} + +// CHECK-LABEL: @fma_32x8 +#[no_mangle] +pub unsafe fn fma_32x8(a: f32x8, b: f32x8, c: f32x8) -> f32x8 { + // CHECK: call fast <8 x float> @llvm.fma.v8f32 + simd_fma(a, b, c) +} + +// CHECK-LABEL: @fma_32x16 +#[no_mangle] +pub unsafe fn fma_32x16(a: f32x16, b: f32x16, c: f32x16) -> f32x16 { + // CHECK: call fast <16 x float> @llvm.fma.v16f32 + simd_fma(a, b, c) +} + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x2(pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x4(pub f64, pub f64, pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x8(pub f64, pub f64, pub f64, pub f64, + pub f64, pub f64, pub f64, pub f64); + +// CHECK-LABEL: @fma_64x4 +#[no_mangle] +pub unsafe fn fma_64x4(a: f64x4, b: f64x4, c: f64x4) -> f64x4 { + // CHECK: call fast <4 x double> @llvm.fma.v4f64 + simd_fma(a, b, c) +} + +// CHECK-LABEL: @fma_64x2 +#[no_mangle] +pub unsafe fn fma_64x2(a: f64x2, b: f64x2, c: f64x2) -> f64x2 { + // CHECK: call fast <2 x double> @llvm.fma.v2f64 + simd_fma(a, b, c) +} + +// CHECK-LABEL: @fma_64x8 +#[no_mangle] +pub unsafe fn fma_64x8(a: f64x8, b: f64x8, c: f64x8) -> f64x8 { + // CHECK: call fast <8 x double> @llvm.fma.v8f64 + simd_fma(a, b, c) +} diff --git a/src/test/codegen/simd-intrinsic-float-fsqrt.rs b/src/test/codegen/simd-intrinsic-float-fsqrt.rs new file mode 100644 index 0000000000000..2bad0bba48a78 --- /dev/null +++ b/src/test/codegen/simd-intrinsic-float-fsqrt.rs @@ -0,0 +1,104 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x2(pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x8(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x16(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_fsqrt(x: T) -> T; +} + +// CHECK-LABEL: @fsqrt_32x2 +#[no_mangle] +pub unsafe fn fsqrt_32x2(a: f32x2) -> f32x2 { + // CHECK: call fast <2 x float> @llvm.sqrt.v2f32 + simd_fsqrt(a) +} + +// CHECK-LABEL: @fsqrt_32x4 +#[no_mangle] +pub unsafe fn fsqrt_32x4(a: f32x4) -> f32x4 { + // CHECK: call fast <4 x float> @llvm.sqrt.v4f32 + simd_fsqrt(a) +} + +// CHECK-LABEL: @fsqrt_32x8 +#[no_mangle] +pub unsafe fn fsqrt_32x8(a: f32x8) -> f32x8 { + // CHECK: call fast <8 x float> @llvm.sqrt.v8f32 + simd_fsqrt(a) +} + +// CHECK-LABEL: @fsqrt_32x16 +#[no_mangle] +pub unsafe fn fsqrt_32x16(a: f32x16) -> f32x16 { + // CHECK: call fast <16 x float> @llvm.sqrt.v16f32 + simd_fsqrt(a) +} + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x2(pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x4(pub f64, pub f64, pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x8(pub f64, pub f64, pub f64, pub f64, + pub f64, pub f64, pub f64, pub f64); + +// CHECK-LABEL: @fsqrt_64x4 +#[no_mangle] +pub unsafe fn fsqrt_64x4(a: f64x4) -> f64x4 { + // CHECK: call fast <4 x double> @llvm.sqrt.v4f64 + simd_fsqrt(a) +} + +// CHECK-LABEL: @fsqrt_64x2 +#[no_mangle] +pub unsafe fn fsqrt_64x2(a: f64x2) -> f64x2 { + // CHECK: call fast <2 x double> @llvm.sqrt.v2f64 + simd_fsqrt(a) +} + +// CHECK-LABEL: @fsqrt_64x8 +#[no_mangle] +pub unsafe fn fsqrt_64x8(a: f64x8) -> f64x8 { + // CHECK: call fast <8 x double> @llvm.sqrt.v8f64 + simd_fsqrt(a) +} diff --git a/src/test/codegen/simd-intrinsic-float-log.rs b/src/test/codegen/simd-intrinsic-float-log.rs new file mode 100644 index 0000000000000..d3829efe09b0e --- /dev/null +++ b/src/test/codegen/simd-intrinsic-float-log.rs @@ -0,0 +1,104 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x2(pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x8(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x16(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_flog(x: T) -> T; +} + +// CHECK-LABEL: @log_32x2 +#[no_mangle] +pub unsafe fn log_32x2(a: f32x2) -> f32x2 { + // CHECK: call fast <2 x float> @llvm.log.v2f32 + simd_flog(a) +} + +// CHECK-LABEL: @log_32x4 +#[no_mangle] +pub unsafe fn log_32x4(a: f32x4) -> f32x4 { + // CHECK: call fast <4 x float> @llvm.log.v4f32 + simd_flog(a) +} + +// CHECK-LABEL: @log_32x8 +#[no_mangle] +pub unsafe fn log_32x8(a: f32x8) -> f32x8 { + // CHECK: call fast <8 x float> @llvm.log.v8f32 + simd_flog(a) +} + +// CHECK-LABEL: @log_32x16 +#[no_mangle] +pub unsafe fn log_32x16(a: f32x16) -> f32x16 { + // CHECK: call fast <16 x float> @llvm.log.v16f32 + simd_flog(a) +} + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x2(pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x4(pub f64, pub f64, pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x8(pub f64, pub f64, pub f64, pub f64, + pub f64, pub f64, pub f64, pub f64); + +// CHECK-LABEL: @log_64x4 +#[no_mangle] +pub unsafe fn log_64x4(a: f64x4) -> f64x4 { + // CHECK: call fast <4 x double> @llvm.log.v4f64 + simd_flog(a) +} + +// CHECK-LABEL: @log_64x2 +#[no_mangle] +pub unsafe fn log_64x2(a: f64x2) -> f64x2 { + // CHECK: call fast <2 x double> @llvm.log.v2f64 + simd_flog(a) +} + +// CHECK-LABEL: @log_64x8 +#[no_mangle] +pub unsafe fn log_64x8(a: f64x8) -> f64x8 { + // CHECK: call fast <8 x double> @llvm.log.v8f64 + simd_flog(a) +} diff --git a/src/test/codegen/simd-intrinsic-float-log10.rs b/src/test/codegen/simd-intrinsic-float-log10.rs new file mode 100644 index 0000000000000..47f19e499fa7d --- /dev/null +++ b/src/test/codegen/simd-intrinsic-float-log10.rs @@ -0,0 +1,104 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x2(pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x8(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x16(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_flog10(x: T) -> T; +} + +// CHECK-LABEL: @log10_32x2 +#[no_mangle] +pub unsafe fn log10_32x2(a: f32x2) -> f32x2 { + // CHECK: call fast <2 x float> @llvm.log10.v2f32 + simd_flog10(a) +} + +// CHECK-LABEL: @log10_32x4 +#[no_mangle] +pub unsafe fn log10_32x4(a: f32x4) -> f32x4 { + // CHECK: call fast <4 x float> @llvm.log10.v4f32 + simd_flog10(a) +} + +// CHECK-LABEL: @log10_32x8 +#[no_mangle] +pub unsafe fn log10_32x8(a: f32x8) -> f32x8 { + // CHECK: call fast <8 x float> @llvm.log10.v8f32 + simd_flog10(a) +} + +// CHECK-LABEL: @log10_32x16 +#[no_mangle] +pub unsafe fn log10_32x16(a: f32x16) -> f32x16 { + // CHECK: call fast <16 x float> @llvm.log10.v16f32 + simd_flog10(a) +} + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x2(pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x4(pub f64, pub f64, pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x8(pub f64, pub f64, pub f64, pub f64, + pub f64, pub f64, pub f64, pub f64); + +// CHECK-LABEL: @log10_64x4 +#[no_mangle] +pub unsafe fn log10_64x4(a: f64x4) -> f64x4 { + // CHECK: call fast <4 x double> @llvm.log10.v4f64 + simd_flog10(a) +} + +// CHECK-LABEL: @log10_64x2 +#[no_mangle] +pub unsafe fn log10_64x2(a: f64x2) -> f64x2 { + // CHECK: call fast <2 x double> @llvm.log10.v2f64 + simd_flog10(a) +} + +// CHECK-LABEL: @log10_64x8 +#[no_mangle] +pub unsafe fn log10_64x8(a: f64x8) -> f64x8 { + // CHECK: call fast <8 x double> @llvm.log10.v8f64 + simd_flog10(a) +} diff --git a/src/test/codegen/simd-intrinsic-float-log2.rs b/src/test/codegen/simd-intrinsic-float-log2.rs new file mode 100644 index 0000000000000..e36a5887b6196 --- /dev/null +++ b/src/test/codegen/simd-intrinsic-float-log2.rs @@ -0,0 +1,104 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x2(pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x8(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x16(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_flog2(x: T) -> T; +} + +// CHECK-LABEL: @log2_32x2 +#[no_mangle] +pub unsafe fn log2_32x2(a: f32x2) -> f32x2 { + // CHECK: call fast <2 x float> @llvm.log2.v2f32 + simd_flog2(a) +} + +// CHECK-LABEL: @log2_32x4 +#[no_mangle] +pub unsafe fn log2_32x4(a: f32x4) -> f32x4 { + // CHECK: call fast <4 x float> @llvm.log2.v4f32 + simd_flog2(a) +} + +// CHECK-LABEL: @log2_32x8 +#[no_mangle] +pub unsafe fn log2_32x8(a: f32x8) -> f32x8 { + // CHECK: call fast <8 x float> @llvm.log2.v8f32 + simd_flog2(a) +} + +// CHECK-LABEL: @log2_32x16 +#[no_mangle] +pub unsafe fn log2_32x16(a: f32x16) -> f32x16 { + // CHECK: call fast <16 x float> @llvm.log2.v16f32 + simd_flog2(a) +} + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x2(pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x4(pub f64, pub f64, pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x8(pub f64, pub f64, pub f64, pub f64, + pub f64, pub f64, pub f64, pub f64); + +// CHECK-LABEL: @log2_64x4 +#[no_mangle] +pub unsafe fn log2_64x4(a: f64x4) -> f64x4 { + // CHECK: call fast <4 x double> @llvm.log2.v4f64 + simd_flog2(a) +} + +// CHECK-LABEL: @log2_64x2 +#[no_mangle] +pub unsafe fn log2_64x2(a: f64x2) -> f64x2 { + // CHECK: call fast <2 x double> @llvm.log2.v2f64 + simd_flog2(a) +} + +// CHECK-LABEL: @log2_64x8 +#[no_mangle] +pub unsafe fn log2_64x8(a: f64x8) -> f64x8 { + // CHECK: call fast <8 x double> @llvm.log2.v8f64 + simd_flog2(a) +} diff --git a/src/test/codegen/simd-intrinsic-float-minmax.rs b/src/test/codegen/simd-intrinsic-float-minmax.rs index 6663b841808f1..d963c7e8ddf1b 100644 --- a/src/test/codegen/simd-intrinsic-float-minmax.rs +++ b/src/test/codegen/simd-intrinsic-float-minmax.rs @@ -16,7 +16,7 @@ #![crate_type = "lib"] #![feature(repr_simd, platform_intrinsics)] -#[allow(non_camel_case_types)] +#![allow(non_camel_case_types)] #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] diff --git a/src/test/codegen/simd-intrinsic-float-pow.rs b/src/test/codegen/simd-intrinsic-float-pow.rs new file mode 100644 index 0000000000000..bb2ac36220302 --- /dev/null +++ b/src/test/codegen/simd-intrinsic-float-pow.rs @@ -0,0 +1,104 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x2(pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x8(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x16(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_fpow(x: T, b: T) -> T; +} + +// CHECK-LABEL: @fpow_32x2 +#[no_mangle] +pub unsafe fn fpow_32x2(a: f32x2, b: f32x2) -> f32x2 { + // CHECK: call fast <2 x float> @llvm.pow.v2f32 + simd_fpow(a, b) +} + +// CHECK-LABEL: @fpow_32x4 +#[no_mangle] +pub unsafe fn fpow_32x4(a: f32x4, b: f32x4) -> f32x4 { + // CHECK: call fast <4 x float> @llvm.pow.v4f32 + simd_fpow(a, b) +} + +// CHECK-LABEL: @fpow_32x8 +#[no_mangle] +pub unsafe fn fpow_32x8(a: f32x8, b: f32x8) -> f32x8 { + // CHECK: call fast <8 x float> @llvm.pow.v8f32 + simd_fpow(a, b) +} + +// CHECK-LABEL: @fpow_32x16 +#[no_mangle] +pub unsafe fn fpow_32x16(a: f32x16, b: f32x16) -> f32x16 { + // CHECK: call fast <16 x float> @llvm.pow.v16f32 + simd_fpow(a, b) +} + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x2(pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x4(pub f64, pub f64, pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x8(pub f64, pub f64, pub f64, pub f64, + pub f64, pub f64, pub f64, pub f64); + +// CHECK-LABEL: @fpow_64x4 +#[no_mangle] +pub unsafe fn fpow_64x4(a: f64x4, b: f64x4) -> f64x4 { + // CHECK: call fast <4 x double> @llvm.pow.v4f64 + simd_fpow(a, b) +} + +// CHECK-LABEL: @fpow_64x2 +#[no_mangle] +pub unsafe fn fpow_64x2(a: f64x2, b: f64x2) -> f64x2 { + // CHECK: call fast <2 x double> @llvm.pow.v2f64 + simd_fpow(a, b) +} + +// CHECK-LABEL: @fpow_64x8 +#[no_mangle] +pub unsafe fn fpow_64x8(a: f64x8, b: f64x8) -> f64x8 { + // CHECK: call fast <8 x double> @llvm.pow.v8f64 + simd_fpow(a, b) +} diff --git a/src/test/codegen/simd-intrinsic-float-powi.rs b/src/test/codegen/simd-intrinsic-float-powi.rs new file mode 100644 index 0000000000000..6e28af262ace6 --- /dev/null +++ b/src/test/codegen/simd-intrinsic-float-powi.rs @@ -0,0 +1,104 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x2(pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x8(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x16(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_fpowi(x: T, b: i32) -> T; +} + +// CHECK-LABEL: @fpowi_32x2 +#[no_mangle] +pub unsafe fn fpowi_32x2(a: f32x2, b: i32) -> f32x2 { + // CHECK: call fast <2 x float> @llvm.powi.v2f32 + simd_fpowi(a, b) +} + +// CHECK-LABEL: @fpowi_32x4 +#[no_mangle] +pub unsafe fn fpowi_32x4(a: f32x4, b: i32) -> f32x4 { + // CHECK: call fast <4 x float> @llvm.powi.v4f32 + simd_fpowi(a, b) +} + +// CHECK-LABEL: @fpowi_32x8 +#[no_mangle] +pub unsafe fn fpowi_32x8(a: f32x8, b: i32) -> f32x8 { + // CHECK: call fast <8 x float> @llvm.powi.v8f32 + simd_fpowi(a, b) +} + +// CHECK-LABEL: @fpowi_32x16 +#[no_mangle] +pub unsafe fn fpowi_32x16(a: f32x16, b: i32) -> f32x16 { + // CHECK: call fast <16 x float> @llvm.powi.v16f32 + simd_fpowi(a, b) +} + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x2(pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x4(pub f64, pub f64, pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x8(pub f64, pub f64, pub f64, pub f64, + pub f64, pub f64, pub f64, pub f64); + +// CHECK-LABEL: @fpowi_64x4 +#[no_mangle] +pub unsafe fn fpowi_64x4(a: f64x4, b: i32) -> f64x4 { + // CHECK: call fast <4 x double> @llvm.powi.v4f64 + simd_fpowi(a, b) +} + +// CHECK-LABEL: @fpowi_64x2 +#[no_mangle] +pub unsafe fn fpowi_64x2(a: f64x2, b: i32) -> f64x2 { + // CHECK: call fast <2 x double> @llvm.powi.v2f64 + simd_fpowi(a, b) +} + +// CHECK-LABEL: @fpowi_64x8 +#[no_mangle] +pub unsafe fn fpowi_64x8(a: f64x8, b: i32) -> f64x8 { + // CHECK: call fast <8 x double> @llvm.powi.v8f64 + simd_fpowi(a, b) +} diff --git a/src/test/codegen/simd-intrinsic-float-sin.rs b/src/test/codegen/simd-intrinsic-float-sin.rs new file mode 100644 index 0000000000000..26100ed5c3f03 --- /dev/null +++ b/src/test/codegen/simd-intrinsic-float-sin.rs @@ -0,0 +1,104 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x2(pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x8(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x16(pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32, + pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_fsin(x: T) -> T; +} + +// CHECK-LABEL: @fsin_32x2 +#[no_mangle] +pub unsafe fn fsin_32x2(a: f32x2) -> f32x2 { + // CHECK: call fast <2 x float> @llvm.sin.v2f32 + simd_fsin(a) +} + +// CHECK-LABEL: @fsin_32x4 +#[no_mangle] +pub unsafe fn fsin_32x4(a: f32x4) -> f32x4 { + // CHECK: call fast <4 x float> @llvm.sin.v4f32 + simd_fsin(a) +} + +// CHECK-LABEL: @fsin_32x8 +#[no_mangle] +pub unsafe fn fsin_32x8(a: f32x8) -> f32x8 { + // CHECK: call fast <8 x float> @llvm.sin.v8f32 + simd_fsin(a) +} + +// CHECK-LABEL: @fsin_32x16 +#[no_mangle] +pub unsafe fn fsin_32x16(a: f32x16) -> f32x16 { + // CHECK: call fast <16 x float> @llvm.sin.v16f32 + simd_fsin(a) +} + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x2(pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x4(pub f64, pub f64, pub f64, pub f64); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f64x8(pub f64, pub f64, pub f64, pub f64, + pub f64, pub f64, pub f64, pub f64); + +// CHECK-LABEL: @fsin_64x4 +#[no_mangle] +pub unsafe fn fsin_64x4(a: f64x4) -> f64x4 { + // CHECK: call fast <4 x double> @llvm.sin.v4f64 + simd_fsin(a) +} + +// CHECK-LABEL: @fsin_64x2 +#[no_mangle] +pub unsafe fn fsin_64x2(a: f64x2) -> f64x2 { + // CHECK: call fast <2 x double> @llvm.sin.v2f64 + simd_fsin(a) +} + +// CHECK-LABEL: @fsin_64x8 +#[no_mangle] +pub unsafe fn fsin_64x8(a: f64x8) -> f64x8 { + // CHECK: call fast <8 x double> @llvm.sin.v8f64 + simd_fsin(a) +} diff --git a/src/test/codegen/simd-intrinsic-generic-gather.rs b/src/test/codegen/simd-intrinsic-generic-gather.rs new file mode 100644 index 0000000000000..6c47bf3e321fb --- /dev/null +++ b/src/test/codegen/simd-intrinsic-generic-gather.rs @@ -0,0 +1,48 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten +// ignore-tidy-linelength +// min-llvm-version 6.0 + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct Vec2(pub T, pub T); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct Vec4(pub T, pub T, pub T, pub T); + +extern "platform-intrinsic" { + fn simd_gather(value: T, pointers: P, mask: M) -> T; +} + +// CHECK-LABEL: @gather_f32x2 +#[no_mangle] +pub unsafe fn gather_f32x2(pointers: Vec2<*const f32>, mask: Vec2, + values: Vec2) -> Vec2 { + // CHECK: call <2 x float> @llvm.masked.gather.v2f32.v2p0f32(<2 x float*> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}, <2 x float> {{.*}}) + simd_gather(values, pointers, mask) +} + +// CHECK-LABEL: @gather_pf32x2 +#[no_mangle] +pub unsafe fn gather_pf32x2(pointers: Vec2<*const *const f32>, mask: Vec2, + values: Vec2<*const f32>) -> Vec2<*const f32> { + // CHECK: call <2 x float*> @llvm.masked.gather.v2p0f32.v2p0p0f32(<2 x float**> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}, <2 x float*> {{.*}}) + simd_gather(values, pointers, mask) +} diff --git a/src/test/codegen/simd-intrinsic-generic-scatter.rs b/src/test/codegen/simd-intrinsic-generic-scatter.rs new file mode 100644 index 0000000000000..7b5b2e55e2949 --- /dev/null +++ b/src/test/codegen/simd-intrinsic-generic-scatter.rs @@ -0,0 +1,49 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten +// ignore-tidy-linelength +// min-llvm-version 6.0 + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct Vec2(pub T, pub T); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct Vec4(pub T, pub T, pub T, pub T); + +extern "platform-intrinsic" { + fn simd_scatter(value: T, pointers: P, mask: M); +} + +// CHECK-LABEL: @scatter_f32x2 +#[no_mangle] +pub unsafe fn scatter_f32x2(pointers: Vec2<*mut f32>, mask: Vec2, + values: Vec2) { + // CHECK: call void @llvm.masked.scatter.v2f32.v2p0f32(<2 x float> {{.*}}, <2 x float*> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}) + simd_scatter(values, pointers, mask) +} + + +// CHECK-LABEL: @scatter_pf32x2 +#[no_mangle] +pub unsafe fn scatter_pf32x2(pointers: Vec2<*mut *const f32>, mask: Vec2, + values: Vec2<*const f32>) { + // CHECK: call void @llvm.masked.scatter.v2p0f32.v2p0p0f32(<2 x float*> {{.*}}, <2 x float**> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}) + simd_scatter(values, pointers, mask) +} diff --git a/src/test/run-pass/simd-intrinsic-float-math.rs b/src/test/run-pass/simd-intrinsic-float-math.rs new file mode 100644 index 0000000000000..e2bf310641c87 --- /dev/null +++ b/src/test/run-pass/simd-intrinsic-float-math.rs @@ -0,0 +1,90 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten +// error-pattern: panicked + +// Test that the simd floating-point math intrinsics produce correct results. + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct f32x4(pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_fsqrt(x: T) -> T; + fn simd_fabs(x: T) -> T; + fn simd_fsin(x: T) -> T; + fn simd_fcos(x: T) -> T; + fn simd_ceil(x: T) -> T; + fn simd_fexp(x: T) -> T; + fn simd_fexp2(x: T) -> T; + fn simd_floor(x: T) -> T; + fn simd_fma(x: T, y: T, z: T) -> T; + fn simd_flog(x: T) -> T; + fn simd_flog10(x: T) -> T; + fn simd_flog2(x: T) -> T; + fn simd_fpow(x: T, y: T) -> T; + fn simd_fpowi(x: T, y: i32) -> T; +} + +fn main() { + let x = f32x4(1.0, 1.0, 1.0, 1.0); + let y = f32x4(-1.0, -1.0, -1.0, -1.0); + let z = f32x4(0.0, 0.0, 0.0, 0.0); + + let h = f32x4(0.5, 0.5, 0.5, 0.5); + + unsafe { + let r = simd_fabs(y); + assert_eq!(x, r); + + let r = simd_fcos(z); + assert_eq!(x, r); + + let r = simd_ceil(h); + assert_eq!(x, r); + + let r = simd_fexp(z); + assert_eq!(x, r); + + let r = simd_fexp2(z); + assert_eq!(x, r); + + let r = simd_floor(h); + assert_eq!(z, r); + + let r = simd_fma(x, h, h); + assert_eq!(x, r); + + let r = simd_fsqrt(x); + assert_eq!(x, r); + + let r = simd_flog(x); + assert_eq!(z, r); + + let r = simd_flog2(x); + assert_eq!(z, r); + + let r = simd_flog10(x); + assert_eq!(z, r); + + let r = simd_fpow(h, x); + assert_eq!(h, r); + + let r = simd_fpowi(h, 1); + assert_eq!(h, r); + + let r = simd_fsin(z); + assert_eq!(z, r); + } +} diff --git a/src/test/run-fail/simd-intrinsic-float-minmax.rs b/src/test/run-pass/simd-intrinsic-float-minmax.rs similarity index 95% rename from src/test/run-fail/simd-intrinsic-float-minmax.rs rename to src/test/run-pass/simd-intrinsic-float-minmax.rs index f4fb8e12250b5..71c0139bb03bb 100644 --- a/src/test/run-fail/simd-intrinsic-float-minmax.rs +++ b/src/test/run-pass/simd-intrinsic-float-minmax.rs @@ -9,13 +9,13 @@ // except according to those terms. // ignore-emscripten -// min-llvm-version 6.0 +// min-llvm-version 7.0 // error-pattern: panicked // Test that the simd_f{min,max} intrinsics produce the correct results. #![feature(repr_simd, platform_intrinsics)] -#[allow(non_camel_case_types)] +#![allow(non_camel_case_types)] #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] @@ -43,7 +43,6 @@ fn main() { let minn = simd_fmin(y, n); assert_eq!(minn, y); - // FIXME(49261) let max0 = simd_fmax(x, y); let max1 = simd_fmax(y, x); assert_eq!(max0, max1); diff --git a/src/test/run-pass/simd-intrinsic-generic-gather.rs b/src/test/run-pass/simd-intrinsic-generic-gather.rs new file mode 100644 index 0000000000000..54143739a88f9 --- /dev/null +++ b/src/test/run-pass/simd-intrinsic-generic-gather.rs @@ -0,0 +1,151 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten +// min-llvm-version 6.0 + +// Test that the simd_{gather,scatter} intrinsics produce the correct results. + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct x4(pub T, pub T, pub T, pub T); + +extern "platform-intrinsic" { + fn simd_gather(x: T, y: U, z: V) -> T; + fn simd_scatter(x: T, y: U, z: V) -> (); +} + +fn main() { + let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.]; + + let default = x4(-3_f32, -3., -3., -3.); + let s_strided = x4(0_f32, 2., -3., 6.); + let mask = x4(-1_i32, -1, 0, -1); + + // reading from *const + unsafe { + let pointer = &x[0] as *const f32; + let pointers = x4( + pointer.offset(0) as *const f32, + pointer.offset(2), + pointer.offset(4), + pointer.offset(6) + ); + + let r_strided = simd_gather(default, pointers, mask); + + assert_eq!(r_strided, s_strided); + } + + // reading from *mut + unsafe { + let pointer = &mut x[0] as *mut f32; + let pointers = x4( + pointer.offset(0) as *mut f32, + pointer.offset(2), + pointer.offset(4), + pointer.offset(6) + ); + + let r_strided = simd_gather(default, pointers, mask); + + assert_eq!(r_strided, s_strided); + } + + // writing to *mut + unsafe { + let pointer = &mut x[0] as *mut f32; + let pointers = x4( + pointer.offset(0) as *mut f32, + pointer.offset(2), + pointer.offset(4), + pointer.offset(6) + ); + + let values = x4(42_f32, 43_f32, 44_f32, 45_f32); + simd_scatter(values, pointers, mask); + + assert_eq!(x, [42., 1., 43., 3., 4., 5., 45., 7.]); + } + + // test modifying array of *const f32 + let mut y = [ + &x[0] as *const f32, + &x[1] as *const f32, + &x[2] as *const f32, + &x[3] as *const f32, + &x[4] as *const f32, + &x[5] as *const f32, + &x[6] as *const f32, + &x[7] as *const f32 + ]; + + let default = x4(y[0], y[0], y[0], y[0]); + let s_strided = x4(y[0], y[2], y[0], y[6]); + + // reading from *const + unsafe { + let pointer = &y[0] as *const *const f32; + let pointers = x4( + pointer.offset(0) as *const *const f32, + pointer.offset(2), + pointer.offset(4), + pointer.offset(6) + ); + + let r_strided = simd_gather(default, pointers, mask); + + assert_eq!(r_strided, s_strided); + } + + // reading from *mut + unsafe { + let pointer = &mut y[0] as *mut *const f32; + let pointers = x4( + pointer.offset(0) as *mut *const f32, + pointer.offset(2), + pointer.offset(4), + pointer.offset(6) + ); + + let r_strided = simd_gather(default, pointers, mask); + + assert_eq!(r_strided, s_strided); + } + + // writing to *mut + unsafe { + let pointer = &mut y[0] as *mut *const f32; + let pointers = x4( + pointer.offset(0) as *mut *const f32, + pointer.offset(2), + pointer.offset(4), + pointer.offset(6) + ); + + let values = x4(y[7], y[6], y[5], y[1]); + simd_scatter(values, pointers, mask); + + let s = [ + &x[7] as *const f32, + &x[1] as *const f32, + &x[6] as *const f32, + &x[3] as *const f32, + &x[4] as *const f32, + &x[5] as *const f32, + &x[1] as *const f32, + &x[7] as *const f32 + ]; + assert_eq!(y, s); + } +} diff --git a/src/test/ui/E0662.rs b/src/test/ui/E0662.rs new file mode 100644 index 0000000000000..6adb11c56169c --- /dev/null +++ b/src/test/ui/E0662.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-stage1 + +#![feature(asm)] + +fn main() { + asm!("xor %eax, %eax" + : + : "=test"("a") //~ ERROR E0662 + ); +} diff --git a/src/test/ui/E0662.stderr b/src/test/ui/E0662.stderr new file mode 100644 index 0000000000000..215e3a6d2f023 --- /dev/null +++ b/src/test/ui/E0662.stderr @@ -0,0 +1,9 @@ +error[E0662]: input operand constraint contains '=' + --> $DIR/E0662.rs:18:12 + | +LL | : "=test"("a") //~ ERROR E0662 + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0662`. diff --git a/src/test/ui/E0663.rs b/src/test/ui/E0663.rs new file mode 100644 index 0000000000000..9eb05ada4a82a --- /dev/null +++ b/src/test/ui/E0663.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-stage1 + +#![feature(asm)] + +fn main() { + asm!("xor %eax, %eax" + : + : "+test"("a") //~ ERROR E0663 + ); +} diff --git a/src/test/ui/E0663.stderr b/src/test/ui/E0663.stderr new file mode 100644 index 0000000000000..123aa73eccc5e --- /dev/null +++ b/src/test/ui/E0663.stderr @@ -0,0 +1,9 @@ +error[E0663]: input operand constraint contains '+' + --> $DIR/E0663.rs:18:12 + | +LL | : "+test"("a") //~ ERROR E0663 + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0663`. diff --git a/src/test/ui/E0664.rs b/src/test/ui/E0664.rs new file mode 100644 index 0000000000000..738ffc18e3827 --- /dev/null +++ b/src/test/ui/E0664.rs @@ -0,0 +1,21 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-stage1 + +#![feature(asm)] + +fn main() { + asm!("mov $$0x200, %eax" + : + : + : "{eax}" //~ ERROR E0664 + ); +} diff --git a/src/test/ui/E0664.stderr b/src/test/ui/E0664.stderr new file mode 100644 index 0000000000000..570811729be85 --- /dev/null +++ b/src/test/ui/E0664.stderr @@ -0,0 +1,9 @@ +error[E0664]: clobber should not be surrounded by braces + --> $DIR/E0664.rs:19:12 + | +LL | : "{eax}" //~ ERROR E0664 + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0664`. diff --git a/src/tools/cargo b/src/tools/cargo index 9e53ac6e6525d..f352115d534eb 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 9e53ac6e6525da914cb05a85e5e8eff7b5dca81f +Subproject commit f352115d534ebdc8ec331209107f91a4f62da2e7