diff --git a/src/doc/reference.md b/src/doc/reference.md index fcf9aefaba847..88d00447f9118 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2087,6 +2087,7 @@ The following configurations must be defined by the implementation: 64-bit pointers. * `target_vendor = "..."` - Vendor of the target, for example `apple`, `pc`, or simply `"unknown"`. +* `target_has_floating_point` - Enabled if the target supports floating point operations. * `test` - Enabled when compiling the test harness (using the `--test` flag). * `unix` - See `target_family`. * `windows` - See `target_family`. @@ -2287,6 +2288,9 @@ The currently implemented features of the reference compiler are: * `cfg_target_vendor` - Allows conditional compilation using the `target_vendor` matcher which is subject to change. +* `cfg_target_has_floating_point` - Allows conditional compilation using the + `target_has_floating_point` matcher which is subject to change. + * `concat_idents` - Allows use of the `concat_idents` macro, which is in many ways insufficient for concatenating identifiers, and may be removed entirely for something more wholesome. diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index a793502e58d37..5660defbe46e6 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -105,7 +105,9 @@ clone_impl! { u16 } clone_impl! { u32 } clone_impl! { u64 } +#[cfg(any(stage0, target_has_floating_point))] clone_impl! { f32 } +#[cfg(any(stage0, target_has_floating_point))] clone_impl! { f64 } clone_impl! { () } diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 12c4a5ca200ad..26339d6460cb4 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -160,5 +160,7 @@ default_impl! { i16, 0 } default_impl! { i32, 0 } default_impl! { i64, 0 } +#[cfg(any(stage0, target_has_floating_point))] default_impl! { f32, 0.0f32 } +#[cfg(any(stage0, target_has_floating_point))] default_impl! { f64, 0.0f64 } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 2f02f5c21f51b..ab431bf2f7126 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -17,6 +17,7 @@ use prelude::v1::*; use cell::{UnsafeCell, Cell, RefCell, Ref, RefMut, BorrowState}; use marker::PhantomData; use mem; +#[cfg(any(stage0, target_has_floating_point))] use num::flt2dec; use ops::Deref; use result; @@ -1023,6 +1024,7 @@ impl<'a> Formatter<'a> { /// Takes the formatted parts and applies the padding. /// Assumes that the caller already has rendered the parts with required precision, /// so that `self.precision` can be ignored. + #[cfg(any(stage0, target_has_floating_point))] fn pad_formatted_parts(&mut self, formatted: &flt2dec::Formatted) -> Result { if let Some(mut width) = self.width { // for the sign-aware zero padding, we render the sign first and @@ -1059,6 +1061,7 @@ impl<'a> Formatter<'a> { } } + #[cfg(any(stage0, target_has_floating_point))] fn write_formatted_parts(&mut self, formatted: &flt2dec::Formatted) -> Result { fn write_bytes(buf: &mut Write, s: &[u8]) -> Result { buf.write_str(unsafe { str::from_utf8_unchecked(s) }) @@ -1448,6 +1451,7 @@ impl<'a, T: ?Sized> Pointer for &'a mut T { } // Common code of floating point Debug and Display. +#[cfg(any(stage0, target_has_floating_point))] fn float_to_decimal_common(fmt: &mut Formatter, num: &T, negative_zero: bool) -> Result where T: flt2dec::DecodableFloat { @@ -1472,6 +1476,7 @@ fn float_to_decimal_common(fmt: &mut Formatter, num: &T, negative_zero: bool) } // Common code of floating point LowerExp and UpperExp. +#[cfg(any(stage0, target_has_floating_point))] fn float_to_exponential_common(fmt: &mut Formatter, num: &T, upper: bool) -> Result where T: flt2dec::DecodableFloat { @@ -1524,7 +1529,9 @@ macro_rules! floating { ($ty:ident) => { } } } } +#[cfg(any(stage0, target_has_floating_point))] floating! { f32 } +#[cfg(any(stage0, target_has_floating_point))] floating! { f64 } // Implementation of Display/Debug for various core types diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 03bcf9caeea0c..1f6ad860787e7 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -448,7 +448,10 @@ extern "rust-intrinsic" { pub fn volatile_load(src: *const T) -> T; /// Perform a volatile store to the `dst` pointer. pub fn volatile_store(dst: *mut T, val: T); +} +#[cfg(any(stage0, target_has_floating_point))] +extern "rust-intrinsic" { /// Returns the square root of an `f32` pub fn sqrtf32(x: f32) -> f32; /// Returns the square root of an `f64` @@ -570,8 +573,9 @@ extern "rust-intrinsic" { /// May assume inputs are finite. #[cfg(not(stage0))] pub fn frem_fast(a: T, b: T) -> T; +} - +extern "rust-intrinsic" { /// Returns the number of bits set in an integer type `T` pub fn ctpop(x: T) -> T; diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 648b652772aec..aa3be7e31f6eb 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -78,6 +78,7 @@ #![feature(staged_api)] #![feature(unboxed_closures)] #![feature(question_mark)] +#![cfg_attr(not(stage0), feature(cfg_target_has_floating_point))] #[macro_use] mod macros; @@ -106,7 +107,9 @@ mod uint_macros; #[path = "num/u32.rs"] pub mod u32; #[path = "num/u64.rs"] pub mod u64; +#[cfg(any(stage0, target_has_floating_point))] #[path = "num/f32.rs"] pub mod f32; +#[cfg(any(stage0, target_has_floating_point))] #[path = "num/f64.rs"] pub mod f64; #[macro_use] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 229a864d712c5..27d711815b517 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -44,7 +44,9 @@ pub struct Wrapping(#[stable(feature = "rust1", since = "1.0.0")] pub T); mod wrapping; // All these modules are technically private and only exposed for libcoretest: +#[cfg(any(stage0, target_has_floating_point))] pub mod flt2dec; +#[cfg(any(stage0, target_has_floating_point))] pub mod dec2flt; pub mod bignum; pub mod diy_float; @@ -111,6 +113,7 @@ macro_rules! zero_one_impl_float { } )*) } +#[cfg(any(stage0, target_has_floating_point))] zero_one_impl_float! { f32 f64 } macro_rules! checked_op { @@ -2213,6 +2216,7 @@ pub enum FpCategory { #[unstable(feature = "core_float", reason = "stable interface is via `impl f{32,64}` in later crates", issue = "32110")] +#[cfg(any(stage0, target_has_floating_point))] pub trait Float: Sized { /// Returns the NaN value. #[unstable(feature = "float_extras", reason = "needs removal", @@ -2451,6 +2455,7 @@ impl fmt::Display for ParseIntError { } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(any(stage0, target_has_floating_point))] pub use num::dec2flt::ParseFloatError; // Conversion traits for primitive integer and float types @@ -2498,19 +2503,24 @@ impl_from! { u32, i64 } // they fit in the significand, which is 24 bits in f32 and 53 bits in f64. // Lossy float conversions are not implemented at this time. -// Signed -> Float -impl_from! { i8, f32 } -impl_from! { i8, f64 } -impl_from! { i16, f32 } -impl_from! { i16, f64 } -impl_from! { i32, f64 } - -// Unsigned -> Float -impl_from! { u8, f32 } -impl_from! { u8, f64 } -impl_from! { u16, f32 } -impl_from! { u16, f64 } -impl_from! { u32, f64 } - -// Float -> Float -impl_from! { f32, f64 } +#[cfg(any(stage0, target_has_floating_point))] +mod _int_float_conv { + use convert::From; + + // Signed -> Float + impl_from! { i8, f32 } + impl_from! { i8, f64 } + impl_from! { i16, f32 } + impl_from! { i16, f64 } + impl_from! { i32, f64 } + + // Unsigned -> Float + impl_from! { u8, f32 } + impl_from! { u8, f64 } + impl_from! { u16, f32 } + impl_from! { u16, f64 } + impl_from! { u32, f64 } + + // Float -> Float + impl_from! { f32, f64 } +} diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 44c498ef6d4e0..9a146508ff386 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -215,7 +215,9 @@ macro_rules! add_impl { )*) } -add_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } +add_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(any(stage0, target_has_floating_point))] +add_impl! { f32 f64 } /// The `Sub` trait is used to specify the functionality of `-`. /// @@ -268,7 +270,9 @@ macro_rules! sub_impl { )*) } -sub_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } +sub_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(any(stage0, target_has_floating_point))] +sub_impl! { f32 f64 } /// The `Mul` trait is used to specify the functionality of `*`. /// @@ -321,7 +325,9 @@ macro_rules! mul_impl { )*) } -mul_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } +mul_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(any(stage0, target_has_floating_point))] +mul_impl! { f32 f64 } /// The `Div` trait is used to specify the functionality of `/`. /// @@ -392,6 +398,7 @@ macro_rules! div_impl_float { )*) } +#[cfg(any(stage0, target_has_floating_point))] div_impl_float! { f32 f64 } /// The `Rem` trait is used to specify the functionality of `%`. @@ -463,6 +470,7 @@ macro_rules! rem_impl_float { )*) } +#[cfg(any(stage0, target_has_floating_point))] rem_impl_float! { f32 f64 } /// The `Neg` trait is used to specify the functionality of unary `-`. @@ -530,7 +538,9 @@ macro_rules! neg_impl_unsigned { } // neg_impl_unsigned! { usize u8 u16 u32 u64 } -neg_impl_numeric! { isize i8 i16 i32 i64 f32 f64 } +neg_impl_numeric! { isize i8 i16 i32 i64 } +#[cfg(any(stage0, target_has_floating_point))] +neg_impl_numeric! { f32 f64 } /// The `Not` trait is used to specify the functionality of unary `!`. /// @@ -928,7 +938,9 @@ macro_rules! add_assign_impl { )+) } -add_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } +add_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(any(stage0, target_has_floating_point))] +add_assign_impl! { f32 f64 } /// The `SubAssign` trait is used to specify the functionality of `-=`. /// @@ -972,7 +984,9 @@ macro_rules! sub_assign_impl { )+) } -sub_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } +sub_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(any(stage0, target_has_floating_point))] +sub_assign_impl! { f32 f64 } /// The `MulAssign` trait is used to specify the functionality of `*=`. /// @@ -1016,7 +1030,9 @@ macro_rules! mul_assign_impl { )+) } -mul_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } +mul_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(any(stage0, target_has_floating_point))] +mul_assign_impl! { f32 f64 } /// The `DivAssign` trait is used to specify the functionality of `/=`. /// @@ -1060,7 +1076,9 @@ macro_rules! div_assign_impl { )+) } -div_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } +div_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(any(stage0, target_has_floating_point))] +div_assign_impl! { f32 f64 } /// The `RemAssign` trait is used to specify the functionality of `%=`. /// @@ -1104,7 +1122,9 @@ macro_rules! rem_assign_impl { )+) } -rem_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } +rem_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(any(stage0, target_has_floating_point))] +rem_assign_impl! { f32 f64 } /// The `BitAndAssign` trait is used to specify the functionality of `&=`. /// diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index eba3332c8f713..a245389db8c3c 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -710,6 +710,9 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { if sess.target.target.options.has_elf_tls { ret.push(attr::mk_word_item(InternedString::new("target_thread_local"))); } + if sess.target.target.options.has_floating_point { + ret.push(attr::mk_word_item(InternedString::new("target_has_floating_point"))); + } if sess.opts.debug_assertions { ret.push(attr::mk_word_item(InternedString::new("debug_assertions"))); } diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index a8eac524971ba..771eb414ef0f7 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -287,6 +287,9 @@ pub struct TargetOptions { // If we give emcc .o files that are actually .bc files it // will 'just work'. pub obj_is_bitcode: bool, + + /// Flag indicating whether the target supports floating point instructions. Defaults to true. + pub has_floating_point: bool, } impl Default for TargetOptions { @@ -335,6 +338,7 @@ impl Default for TargetOptions { allow_asm: true, has_elf_tls: false, obj_is_bitcode: false, + has_floating_point: true, } } } @@ -445,6 +449,7 @@ impl Target { key!(archive_format); key!(allow_asm, bool); key!(custom_unwind_resume, bool); + key!(has_floating_point, bool); base } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 5ade636a3271d..c6e96bd39dad0 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -256,6 +256,9 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option, Status // impl specialization (RFC 1210) ("specialization", "1.7.0", Some(31844), Active), + + // Allows cfg(target_has_floating_point) + ("cfg_target_has_floating_point", "1.9.0", None, Active), ]; // (changing above list without updating src/doc/reference.md makes @cmr sad) @@ -460,6 +463,8 @@ const GATED_CFGS: &'static [(&'static str, &'static str, fn(&Features) -> bool)] ("target_vendor", "cfg_target_vendor", cfg_fn!(|x| x.cfg_target_vendor)), ("target_thread_local", "cfg_target_thread_local", cfg_fn!(|x| x.cfg_target_thread_local)), + ("target_has_floating_point", "cfg_target_has_floating_point", + cfg_fn!(|x| x.cfg_target_has_floating_point)), ]; #[derive(Debug, Eq, PartialEq)] @@ -595,6 +600,7 @@ pub struct Features { pub cfg_target_feature: bool, pub cfg_target_vendor: bool, pub cfg_target_thread_local: bool, + pub cfg_target_has_floating_point: bool, pub staged_api: bool, pub stmt_expr_attributes: bool, pub deprecated: bool, @@ -631,6 +637,7 @@ impl Features { cfg_target_feature: false, cfg_target_vendor: false, cfg_target_thread_local: false, + cfg_target_has_floating_point: true, staged_api: false, stmt_expr_attributes: false, deprecated: false, @@ -1243,6 +1250,7 @@ fn check_crate_inner(cm: &CodeMap, span_handler: &Handler, cfg_target_feature: cx.has_feature("cfg_target_feature"), cfg_target_vendor: cx.has_feature("cfg_target_vendor"), cfg_target_thread_local: cx.has_feature("cfg_target_thread_local"), + cfg_target_has_floating_point: cx.has_feature("cfg_target_has_floating_point"), staged_api: cx.has_feature("staged_api"), stmt_expr_attributes: cx.has_feature("stmt_expr_attributes"), deprecated: cx.has_feature("deprecated"), diff --git a/src/test/compile-fail/feature-gate-cfg-target-has-floating-point.rs b/src/test/compile-fail/feature-gate-cfg-target-has-floating-point.rs new file mode 100644 index 0000000000000..7bf42532799b5 --- /dev/null +++ b/src/test/compile-fail/feature-gate-cfg-target-has-floating-point.rs @@ -0,0 +1,23 @@ +// 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. + +#[cfg(target_has_floating_point)] //~ ERROR `cfg(target_has_floating_point)` is experimental +#[cfg_attr(target_has_floating_point, repr(C))] +//~^ ERROR `cfg(target_has_floating_point)` is experimental +struct Foo(u64, u64); + +#[cfg(not(any(all(target_has_floating_point))))] +//~^ ERROR `cfg(target_has_floating_point)` is experimental +fn foo() {} + +fn main() { + cfg!(target_has_floating_point); + //~^ ERROR `cfg(target_has_floating_point)` is experimental and subject to change +} diff --git a/src/test/run-pass/cfg-target-has-floating-point.rs b/src/test/run-pass/cfg-target-has-floating-point.rs new file mode 100644 index 0000000000000..8e7c9d4684477 --- /dev/null +++ b/src/test/run-pass/cfg-target-has-floating-point.rs @@ -0,0 +1,19 @@ +// 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. + +#![feature(cfg_target_has_floating_point)] + +#[cfg(target_has_floating_point)] +pub fn main() { +} + +#[cfg(not(target_has_floating_point))] +pub fn main() { +}