about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDaniel Micay <danielmicay@gmail.com>2014-04-08 18:08:08 -0400
committerDaniel Micay <danielmicay@gmail.com>2014-04-22 20:47:28 -0400
commitdc7d7d2698139d9d9b0887481c4f50773daa392b (patch)
treecd48dd32d932cb90c80c536783c4955f5883b068
parent09bfb92fdc3ccff42dfcf91b0af368f88dc3e446 (diff)
downloadrust-dc7d7d2698139d9d9b0887481c4f50773daa392b.tar.gz
rust-dc7d7d2698139d9d9b0887481c4f50773daa392b.zip
add support for quadruple precision floating point
This currently requires linking against a library like libquadmath (or
libgcc), because compiler-rt barely has any support for this and most
hardware does not yet have 128-bit precision floating point. For this
reason, it's currently hidden behind a feature gate.

When compiler-rt is updated to trunk, some tests can be added for
constant evaluation since there will be support for the comparison
operators.

Closes #13381
-rw-r--r--src/libhexfloat/lib.rs1
-rw-r--r--src/librustc/front/feature_gate.rs9
-rw-r--r--src/librustc/metadata/tydecode.rs1
-rw-r--r--src/librustc/metadata/tyencode.rs1
-rw-r--r--src/librustc/middle/resolve.rs1
-rw-r--r--src/librustc/middle/trans/debuginfo.rs3
-rw-r--r--src/librustc/middle/trans/reflect.rs1
-rw-r--r--src/librustc/middle/trans/type_.rs7
-rw-r--r--src/librustc/middle/ty.rs5
-rw-r--r--src/librustc/middle/typeck/astconv.rs7
-rw-r--r--src/librustdoc/html/format.rs1
-rw-r--r--src/libstd/intrinsics.rs2
-rw-r--r--src/libstd/lib.rs4
-rw-r--r--src/libstd/reflect.rs8
-rw-r--r--src/libstd/repr.rs2
-rw-r--r--src/libsyntax/ast.rs1
-rw-r--r--src/libsyntax/ast_util.rs2
-rw-r--r--src/libsyntax/ext/quote.rs3
-rw-r--r--src/libsyntax/parse/lexer.rs11
-rw-r--r--src/test/run-pass/quad-precision-float.rs20
-rw-r--r--src/test/run-pass/reflect-visit-type.rs1
21 files changed, 81 insertions, 10 deletions
diff --git a/src/libhexfloat/lib.rs b/src/libhexfloat/lib.rs
index 4897924c55b..72528e96917 100644
--- a/src/libhexfloat/lib.rs
+++ b/src/libhexfloat/lib.rs
@@ -105,6 +105,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ->
         Some(Ident{ident, span}) => match token::get_ident(ident).get() {
             "f32" => Some(ast::TyF32),
             "f64" => Some(ast::TyF64),
+            "f128" => Some(ast::TyF128),
             _ => {
                 cx.span_err(span, "invalid floating point type in hexfloat!");
                 None
diff --git a/src/librustc/front/feature_gate.rs b/src/librustc/front/feature_gate.rs
index 5bca018c3ee..50018feff2d 100644
--- a/src/librustc/front/feature_gate.rs
+++ b/src/librustc/front/feature_gate.rs
@@ -57,6 +57,8 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
     ("linkage", Active),
     ("struct_inherit", Active),
 
+    ("quad_precision_float", Active),
+
     // These are used to test this portion of the compiler, they don't actually
     // mean anything
     ("test_accepted_feature", Accepted),
@@ -77,13 +79,15 @@ enum Status {
 
 /// A set of features to be used by later passes.
 pub struct Features {
-    pub default_type_params: Cell<bool>
+    pub default_type_params: Cell<bool>,
+    pub quad_precision_float: Cell<bool>
 }
 
 impl Features {
     pub fn new() -> Features {
         Features {
-            default_type_params: Cell::new(false)
+            default_type_params: Cell::new(false),
+            quad_precision_float: Cell::new(false)
         }
     }
 }
@@ -364,4 +368,5 @@ pub fn check_crate(sess: &Session, krate: &ast::Crate) {
     sess.abort_if_errors();
 
     sess.features.default_type_params.set(cx.has_feature("default_type_params"));
+    sess.features.quad_precision_float.set(cx.has_feature("quad_precision_float"));
 }
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 3ba8dd3b30f..3fdf3053451 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -317,6 +317,7 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
           'D' => return ty::mk_mach_int(ast::TyI64),
           'f' => return ty::mk_mach_float(ast::TyF32),
           'F' => return ty::mk_mach_float(ast::TyF64),
+          'Q' => return ty::mk_mach_float(ast::TyF128),
           _ => fail!("parse_ty: bad numeric type")
         }
       }
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index 13d24e7a1d0..192a9591658 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -236,6 +236,7 @@ fn enc_sty(w: &mut MemWriter, cx: &ctxt, st: &ty::sty) {
             match t {
                 TyF32 => mywrite!(w, "Mf"),
                 TyF64 => mywrite!(w, "MF"),
+                TyF128 => mywrite!(w, "MQ")
             }
         }
         ty::ty_enum(def, ref substs) => {
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index d645b628aff..b20c434729a 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -772,6 +772,7 @@ fn PrimitiveTypeTable() -> PrimitiveTypeTable {
     table.intern("char",    TyChar);
     table.intern("f32",     TyFloat(TyF32));
     table.intern("f64",     TyFloat(TyF64));
+    table.intern("f128",    TyFloat(TyF128));
     table.intern("int",     TyInt(TyI));
     table.intern("i8",      TyInt(TyI8));
     table.intern("i16",     TyInt(TyI16));
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index 4dd929e16f7..27a97af6108 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -1170,7 +1170,8 @@ fn basic_type_metadata(cx: &CrateContext, t: ty::t) -> DIType {
         },
         ty::ty_float(float_ty) => match float_ty {
             ast::TyF32 => ("f32".to_owned(), DW_ATE_float),
-            ast::TyF64 => ("f64".to_owned(), DW_ATE_float)
+            ast::TyF64 => ("f64".to_owned(), DW_ATE_float),
+            ast::TyF128 => ("f128".to_owned(), DW_ATE_float)
         },
         _ => cx.sess().bug("debuginfo::basic_type_metadata - t is invalid type")
     };
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index a1752862715..fffc13fe36b 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -163,6 +163,7 @@ impl<'a, 'b> Reflector<'a, 'b> {
           ty::ty_uint(ast::TyU64) => self.leaf("u64"),
           ty::ty_float(ast::TyF32) => self.leaf("f32"),
           ty::ty_float(ast::TyF64) => self.leaf("f64"),
+          ty::ty_float(ast::TyF128) => self.leaf("f128"),
 
           // Should rename to str_*/vec_*.
           ty::ty_str(vst) => {
diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs
index 6f91ec53419..e49e9539980 100644
--- a/src/librustc/middle/trans/type_.rs
+++ b/src/librustc/middle/trans/type_.rs
@@ -88,6 +88,10 @@ impl Type {
         ty!(llvm::LLVMDoubleTypeInContext(ccx.llcx))
     }
 
+    pub fn f128(ccx: &CrateContext) -> Type {
+        ty!(llvm::LLVMFP128TypeInContext(ccx.llcx))
+    }
+
     pub fn bool(ccx: &CrateContext) -> Type {
         Type::i8(ccx)
     }
@@ -130,7 +134,8 @@ impl Type {
     pub fn float_from_ty(ccx: &CrateContext, t: ast::FloatTy) -> Type {
         match t {
             ast::TyF32 => Type::f32(ccx),
-            ast::TyF64 => Type::f64(ccx)
+            ast::TyF64 => Type::f64(ccx),
+            ast::TyF128 => Type::f128(ccx)
         }
     }
 
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 9a3bdcc1e15..cc4f3d9dd93 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -706,6 +706,7 @@ mod primitives {
     def_prim_ty!(TY_U64,    super::ty_uint(ast::TyU64),     12)
     def_prim_ty!(TY_F32,    super::ty_float(ast::TyF32),    14)
     def_prim_ty!(TY_F64,    super::ty_float(ast::TyF64),    15)
+    def_prim_ty!(TY_F128,   super::ty_float(ast::TyF128),   16)
 
     pub static TY_BOT: t_box_ = t_box_ {
         sty: super::ty_bot,
@@ -1306,6 +1307,9 @@ pub fn mk_f32() -> t { mk_prim_t(&primitives::TY_F32) }
 pub fn mk_f64() -> t { mk_prim_t(&primitives::TY_F64) }
 
 #[inline]
+pub fn mk_f128() -> t { mk_prim_t(&primitives::TY_F128) }
+
+#[inline]
 pub fn mk_uint() -> t { mk_prim_t(&primitives::TY_UINT) }
 
 #[inline]
@@ -1344,6 +1348,7 @@ pub fn mk_mach_float(tm: ast::FloatTy) -> t {
     match tm {
         ast::TyF32  => mk_f32(),
         ast::TyF64  => mk_f64(),
+        ast::TyF128 => mk_f128()
     }
 }
 
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index 6ae68bdbad1..33f833a2594 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -341,6 +341,13 @@ pub fn ast_ty_to_prim_ty(tcx: &ty::ctxt, ast_ty: &ast::Ty) -> Option<ty::t> {
                             Some(ty::mk_mach_uint(uit))
                         }
                         ast::TyFloat(ft) => {
+                            if ft == ast::TyF128 && !tcx.sess.features.quad_precision_float.get() {
+                                tcx.sess.span_err(path.span, "quadruple precision floats are \
+                                                              missing complete runtime support");
+                                tcx.sess.span_note(path.span, "add \
+                                                               #[feature(quad_precision_float)] \
+                                                               to the crate attributes to enable");
+                            }
                             check_path_args(tcx, path, NO_TPS | NO_REGIONS);
                             Some(ty::mk_mach_float(ft))
                         }
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 2819a70de92..1e2f89659cd 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -332,6 +332,7 @@ impl fmt::Show for clean::Type {
                     ast::TyUint(ast::TyU64) => "u64",
                     ast::TyFloat(ast::TyF32) => "f32",
                     ast::TyFloat(ast::TyF64) => "f64",
+                    ast::TyFloat(ast::TyF128) => "f128",
                     ast::TyStr => "str",
                     ast::TyBool => "bool",
                     ast::TyChar => "char",
diff --git a/src/libstd/intrinsics.rs b/src/libstd/intrinsics.rs
index 7f02ab28342..43b5f42163e 100644
--- a/src/libstd/intrinsics.rs
+++ b/src/libstd/intrinsics.rs
@@ -95,6 +95,8 @@ pub trait TyVisitor {
 
     fn visit_f32(&mut self) -> bool;
     fn visit_f64(&mut self) -> bool;
+    #[cfg(not(stage0))]
+    fn visit_f128(&mut self) -> bool;
 
     fn visit_char(&mut self) -> bool;
 
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 9325a0ad112..7cb07e8e551 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -52,11 +52,13 @@
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
        html_root_url = "http://static.rust-lang.org/doc/master")]
 #![feature(macro_rules, globs, asm, managed_boxes, thread_local, link_args,
-           simd, linkage, default_type_params, phase, concat_idents)]
+           simd, linkage, default_type_params, phase, concat_idents, quad_precision_float)]
 
 // Don't link to std. We are std.
 #![no_std]
 
+// NOTE: remove after snapshot
+#![allow(unknown_features)]
 #![deny(missing_doc)]
 
 // When testing libstd, bring in libuv as the I/O backend so tests can print
diff --git a/src/libstd/reflect.rs b/src/libstd/reflect.rs
index e64a6b86d02..45f214e26fb 100644
--- a/src/libstd/reflect.rs
+++ b/src/libstd/reflect.rs
@@ -176,6 +176,14 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
         true
     }
 
+    #[cfg(not(stage0))]
+    fn visit_f128(&mut self) -> bool {
+        self.align_to::<f128>();
+        if ! self.inner.visit_f128() { return false; }
+        self.bump_past::<f128>();
+        true
+    }
+
     fn visit_char(&mut self) -> bool {
         self.align_to::<char>();
         if ! self.inner.visit_char() { return false; }
diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs
index 668edbcc42f..61154502445 100644
--- a/src/libstd/repr.rs
+++ b/src/libstd/repr.rs
@@ -280,6 +280,8 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
 
     fn visit_f32(&mut self) -> bool { self.write::<f32>() }
     fn visit_f64(&mut self) -> bool { self.write::<f64>() }
+    #[cfg(not(stage0))]
+    fn visit_f128(&mut self) -> bool { fail!("not implemented") }
 
     fn visit_char(&mut self) -> bool {
         self.get::<char>(|this, &ch| {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 2b6f94e6bf5..a6146e0eaea 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -730,6 +730,7 @@ impl fmt::Show for UintTy {
 pub enum FloatTy {
     TyF32,
     TyF64,
+    TyF128
 }
 
 impl fmt::Show for FloatTy {
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 437f865b449..adb97af7490 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -187,7 +187,7 @@ pub fn uint_ty_max(t: UintTy) -> u64 {
 }
 
 pub fn float_ty_to_str(t: FloatTy) -> ~str {
-    match t { TyF32 => "f32".to_owned(), TyF64 => "f64".to_owned() }
+    match t { TyF32 => "f32".to_owned(), TyF64 => "f64".to_owned(), TyF128 => "f128".to_owned() }
 }
 
 pub fn is_call_expr(e: @Expr) -> bool {
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index 7d86b988077..68b0ef40b16 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -436,7 +436,8 @@ fn mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> @ast::Expr {
         LIT_FLOAT(fident, fty) => {
             let s_fty = match fty {
                 ast::TyF32 => "TyF32".to_owned(),
-                ast::TyF64 => "TyF64".to_owned()
+                ast::TyF64 => "TyF64".to_owned(),
+                ast::TyF128 => "TyF128".to_owned()
             };
             let e_fty = cx.expr_ident(sp, id_ext(s_fty));
 
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index ff087d95e50..992d289b4e9 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -593,10 +593,15 @@ fn scan_number(c: char, rdr: &mut StringReader) -> token::Token {
             /* FIXME (#2252): if this is out of range for either a
             32-bit or 64-bit float, it won't be noticed till the
             back-end.  */
-        } else {
-            fatal_span(rdr, start_bpos, rdr.last_pos,
-                       "expected `f32` or `f64` suffix".to_owned());
+        } else if c == '1' && n == '2' && nextnextch(rdr).unwrap_or('\x00') == '8' {
+            bump(rdr);
+            bump(rdr);
+            bump(rdr);
+            check_float_base(rdr, start_bpos, rdr.last_pos, base);
+            return token::LIT_FLOAT(str_to_ident(num_str.as_slice()), ast::TyF128);
         }
+        fatal_span(rdr, start_bpos, rdr.last_pos,
+                   "expected `f32`, `f64` or `f128` suffix".to_owned());
     }
     if is_float {
         check_float_base(rdr, start_bpos, rdr.last_pos, base);
diff --git a/src/test/run-pass/quad-precision-float.rs b/src/test/run-pass/quad-precision-float.rs
new file mode 100644
index 00000000000..d6827666eeb
--- /dev/null
+++ b/src/test/run-pass/quad-precision-float.rs
@@ -0,0 +1,20 @@
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(quad_precision_float)]
+
+static x: f128 = 1.0 + 2.0;
+
+fn foo(a: f128) -> f128 { a }
+
+pub fn main() {
+    let y = x;
+    foo(y);
+}
diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs
index 5c28307ea49..e3ad5f1e40f 100644
--- a/src/test/run-pass/reflect-visit-type.rs
+++ b/src/test/run-pass/reflect-visit-type.rs
@@ -58,6 +58,7 @@ impl TyVisitor for MyVisitor {
 
     fn visit_f32(&mut self) -> bool { true }
     fn visit_f64(&mut self) -> bool { true }
+    fn visit_f128(&mut self) -> bool { true }
 
     fn visit_char(&mut self) -> bool { true }