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
This commit is contained in:
parent
09bfb92fdc
commit
dc7d7d2698
21 changed files with 81 additions and 10 deletions
|
@ -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() {
|
Some(Ident{ident, span}) => match token::get_ident(ident).get() {
|
||||||
"f32" => Some(ast::TyF32),
|
"f32" => Some(ast::TyF32),
|
||||||
"f64" => Some(ast::TyF64),
|
"f64" => Some(ast::TyF64),
|
||||||
|
"f128" => Some(ast::TyF128),
|
||||||
_ => {
|
_ => {
|
||||||
cx.span_err(span, "invalid floating point type in hexfloat!");
|
cx.span_err(span, "invalid floating point type in hexfloat!");
|
||||||
None
|
None
|
||||||
|
|
|
@ -57,6 +57,8 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
|
||||||
("linkage", Active),
|
("linkage", Active),
|
||||||
("struct_inherit", Active),
|
("struct_inherit", Active),
|
||||||
|
|
||||||
|
("quad_precision_float", Active),
|
||||||
|
|
||||||
// These are used to test this portion of the compiler, they don't actually
|
// These are used to test this portion of the compiler, they don't actually
|
||||||
// mean anything
|
// mean anything
|
||||||
("test_accepted_feature", Accepted),
|
("test_accepted_feature", Accepted),
|
||||||
|
@ -77,13 +79,15 @@ enum Status {
|
||||||
|
|
||||||
/// A set of features to be used by later passes.
|
/// A set of features to be used by later passes.
|
||||||
pub struct Features {
|
pub struct Features {
|
||||||
pub default_type_params: Cell<bool>
|
pub default_type_params: Cell<bool>,
|
||||||
|
pub quad_precision_float: Cell<bool>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Features {
|
impl Features {
|
||||||
pub fn new() -> Features {
|
pub fn new() -> Features {
|
||||||
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.abort_if_errors();
|
||||||
|
|
||||||
sess.features.default_type_params.set(cx.has_feature("default_type_params"));
|
sess.features.default_type_params.set(cx.has_feature("default_type_params"));
|
||||||
|
sess.features.quad_precision_float.set(cx.has_feature("quad_precision_float"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -317,6 +317,7 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
|
||||||
'D' => return ty::mk_mach_int(ast::TyI64),
|
'D' => return ty::mk_mach_int(ast::TyI64),
|
||||||
'f' => return ty::mk_mach_float(ast::TyF32),
|
'f' => return ty::mk_mach_float(ast::TyF32),
|
||||||
'F' => return ty::mk_mach_float(ast::TyF64),
|
'F' => return ty::mk_mach_float(ast::TyF64),
|
||||||
|
'Q' => return ty::mk_mach_float(ast::TyF128),
|
||||||
_ => fail!("parse_ty: bad numeric type")
|
_ => fail!("parse_ty: bad numeric type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,6 +236,7 @@ fn enc_sty(w: &mut MemWriter, cx: &ctxt, st: &ty::sty) {
|
||||||
match t {
|
match t {
|
||||||
TyF32 => mywrite!(w, "Mf"),
|
TyF32 => mywrite!(w, "Mf"),
|
||||||
TyF64 => mywrite!(w, "MF"),
|
TyF64 => mywrite!(w, "MF"),
|
||||||
|
TyF128 => mywrite!(w, "MQ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::ty_enum(def, ref substs) => {
|
ty::ty_enum(def, ref substs) => {
|
||||||
|
|
|
@ -772,6 +772,7 @@ fn PrimitiveTypeTable() -> PrimitiveTypeTable {
|
||||||
table.intern("char", TyChar);
|
table.intern("char", TyChar);
|
||||||
table.intern("f32", TyFloat(TyF32));
|
table.intern("f32", TyFloat(TyF32));
|
||||||
table.intern("f64", TyFloat(TyF64));
|
table.intern("f64", TyFloat(TyF64));
|
||||||
|
table.intern("f128", TyFloat(TyF128));
|
||||||
table.intern("int", TyInt(TyI));
|
table.intern("int", TyInt(TyI));
|
||||||
table.intern("i8", TyInt(TyI8));
|
table.intern("i8", TyInt(TyI8));
|
||||||
table.intern("i16", TyInt(TyI16));
|
table.intern("i16", TyInt(TyI16));
|
||||||
|
|
|
@ -1170,7 +1170,8 @@ fn basic_type_metadata(cx: &CrateContext, t: ty::t) -> DIType {
|
||||||
},
|
},
|
||||||
ty::ty_float(float_ty) => match float_ty {
|
ty::ty_float(float_ty) => match float_ty {
|
||||||
ast::TyF32 => ("f32".to_owned(), DW_ATE_float),
|
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")
|
_ => cx.sess().bug("debuginfo::basic_type_metadata - t is invalid type")
|
||||||
};
|
};
|
||||||
|
|
|
@ -163,6 +163,7 @@ impl<'a, 'b> Reflector<'a, 'b> {
|
||||||
ty::ty_uint(ast::TyU64) => self.leaf("u64"),
|
ty::ty_uint(ast::TyU64) => self.leaf("u64"),
|
||||||
ty::ty_float(ast::TyF32) => self.leaf("f32"),
|
ty::ty_float(ast::TyF32) => self.leaf("f32"),
|
||||||
ty::ty_float(ast::TyF64) => self.leaf("f64"),
|
ty::ty_float(ast::TyF64) => self.leaf("f64"),
|
||||||
|
ty::ty_float(ast::TyF128) => self.leaf("f128"),
|
||||||
|
|
||||||
// Should rename to str_*/vec_*.
|
// Should rename to str_*/vec_*.
|
||||||
ty::ty_str(vst) => {
|
ty::ty_str(vst) => {
|
||||||
|
|
|
@ -88,6 +88,10 @@ impl Type {
|
||||||
ty!(llvm::LLVMDoubleTypeInContext(ccx.llcx))
|
ty!(llvm::LLVMDoubleTypeInContext(ccx.llcx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn f128(ccx: &CrateContext) -> Type {
|
||||||
|
ty!(llvm::LLVMFP128TypeInContext(ccx.llcx))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bool(ccx: &CrateContext) -> Type {
|
pub fn bool(ccx: &CrateContext) -> Type {
|
||||||
Type::i8(ccx)
|
Type::i8(ccx)
|
||||||
}
|
}
|
||||||
|
@ -130,7 +134,8 @@ impl Type {
|
||||||
pub fn float_from_ty(ccx: &CrateContext, t: ast::FloatTy) -> Type {
|
pub fn float_from_ty(ccx: &CrateContext, t: ast::FloatTy) -> Type {
|
||||||
match t {
|
match t {
|
||||||
ast::TyF32 => Type::f32(ccx),
|
ast::TyF32 => Type::f32(ccx),
|
||||||
ast::TyF64 => Type::f64(ccx)
|
ast::TyF64 => Type::f64(ccx),
|
||||||
|
ast::TyF128 => Type::f128(ccx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -706,6 +706,7 @@ mod primitives {
|
||||||
def_prim_ty!(TY_U64, super::ty_uint(ast::TyU64), 12)
|
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_F32, super::ty_float(ast::TyF32), 14)
|
||||||
def_prim_ty!(TY_F64, super::ty_float(ast::TyF64), 15)
|
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_ {
|
pub static TY_BOT: t_box_ = t_box_ {
|
||||||
sty: super::ty_bot,
|
sty: super::ty_bot,
|
||||||
|
@ -1305,6 +1306,9 @@ pub fn mk_f32() -> t { mk_prim_t(&primitives::TY_F32) }
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mk_f64() -> t { mk_prim_t(&primitives::TY_F64) }
|
pub fn mk_f64() -> t { mk_prim_t(&primitives::TY_F64) }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn mk_f128() -> t { mk_prim_t(&primitives::TY_F128) }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mk_uint() -> t { mk_prim_t(&primitives::TY_UINT) }
|
pub fn mk_uint() -> t { mk_prim_t(&primitives::TY_UINT) }
|
||||||
|
|
||||||
|
@ -1344,6 +1348,7 @@ pub fn mk_mach_float(tm: ast::FloatTy) -> t {
|
||||||
match tm {
|
match tm {
|
||||||
ast::TyF32 => mk_f32(),
|
ast::TyF32 => mk_f32(),
|
||||||
ast::TyF64 => mk_f64(),
|
ast::TyF64 => mk_f64(),
|
||||||
|
ast::TyF128 => mk_f128()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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))
|
Some(ty::mk_mach_uint(uit))
|
||||||
}
|
}
|
||||||
ast::TyFloat(ft) => {
|
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);
|
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
|
||||||
Some(ty::mk_mach_float(ft))
|
Some(ty::mk_mach_float(ft))
|
||||||
}
|
}
|
||||||
|
|
|
@ -332,6 +332,7 @@ impl fmt::Show for clean::Type {
|
||||||
ast::TyUint(ast::TyU64) => "u64",
|
ast::TyUint(ast::TyU64) => "u64",
|
||||||
ast::TyFloat(ast::TyF32) => "f32",
|
ast::TyFloat(ast::TyF32) => "f32",
|
||||||
ast::TyFloat(ast::TyF64) => "f64",
|
ast::TyFloat(ast::TyF64) => "f64",
|
||||||
|
ast::TyFloat(ast::TyF128) => "f128",
|
||||||
ast::TyStr => "str",
|
ast::TyStr => "str",
|
||||||
ast::TyBool => "bool",
|
ast::TyBool => "bool",
|
||||||
ast::TyChar => "char",
|
ast::TyChar => "char",
|
||||||
|
|
|
@ -95,6 +95,8 @@ pub trait TyVisitor {
|
||||||
|
|
||||||
fn visit_f32(&mut self) -> bool;
|
fn visit_f32(&mut self) -> bool;
|
||||||
fn visit_f64(&mut self) -> bool;
|
fn visit_f64(&mut self) -> bool;
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
fn visit_f128(&mut self) -> bool;
|
||||||
|
|
||||||
fn visit_char(&mut self) -> bool;
|
fn visit_char(&mut self) -> bool;
|
||||||
|
|
||||||
|
|
|
@ -52,11 +52,13 @@
|
||||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||||
html_root_url = "http://static.rust-lang.org/doc/master")]
|
html_root_url = "http://static.rust-lang.org/doc/master")]
|
||||||
#![feature(macro_rules, globs, asm, managed_boxes, thread_local, link_args,
|
#![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.
|
// Don't link to std. We are std.
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
// NOTE: remove after snapshot
|
||||||
|
#![allow(unknown_features)]
|
||||||
#![deny(missing_doc)]
|
#![deny(missing_doc)]
|
||||||
|
|
||||||
// When testing libstd, bring in libuv as the I/O backend so tests can print
|
// When testing libstd, bring in libuv as the I/O backend so tests can print
|
||||||
|
|
|
@ -176,6 +176,14 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
|
||||||
true
|
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 {
|
fn visit_char(&mut self) -> bool {
|
||||||
self.align_to::<char>();
|
self.align_to::<char>();
|
||||||
if ! self.inner.visit_char() { return false; }
|
if ! self.inner.visit_char() { return false; }
|
||||||
|
|
|
@ -280,6 +280,8 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
|
||||||
|
|
||||||
fn visit_f32(&mut self) -> bool { self.write::<f32>() }
|
fn visit_f32(&mut self) -> bool { self.write::<f32>() }
|
||||||
fn visit_f64(&mut self) -> bool { self.write::<f64>() }
|
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 {
|
fn visit_char(&mut self) -> bool {
|
||||||
self.get::<char>(|this, &ch| {
|
self.get::<char>(|this, &ch| {
|
||||||
|
|
|
@ -730,6 +730,7 @@ impl fmt::Show for UintTy {
|
||||||
pub enum FloatTy {
|
pub enum FloatTy {
|
||||||
TyF32,
|
TyF32,
|
||||||
TyF64,
|
TyF64,
|
||||||
|
TyF128
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Show for FloatTy {
|
impl fmt::Show for FloatTy {
|
||||||
|
|
|
@ -187,7 +187,7 @@ pub fn uint_ty_max(t: UintTy) -> u64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn float_ty_to_str(t: FloatTy) -> ~str {
|
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 {
|
pub fn is_call_expr(e: @Expr) -> bool {
|
||||||
|
|
|
@ -436,7 +436,8 @@ fn mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> @ast::Expr {
|
||||||
LIT_FLOAT(fident, fty) => {
|
LIT_FLOAT(fident, fty) => {
|
||||||
let s_fty = match fty {
|
let s_fty = match fty {
|
||||||
ast::TyF32 => "TyF32".to_owned(),
|
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));
|
let e_fty = cx.expr_ident(sp, id_ext(s_fty));
|
||||||
|
|
||||||
|
|
|
@ -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
|
/* FIXME (#2252): if this is out of range for either a
|
||||||
32-bit or 64-bit float, it won't be noticed till the
|
32-bit or 64-bit float, it won't be noticed till the
|
||||||
back-end. */
|
back-end. */
|
||||||
} else {
|
} else if c == '1' && n == '2' && nextnextch(rdr).unwrap_or('\x00') == '8' {
|
||||||
fatal_span(rdr, start_bpos, rdr.last_pos,
|
bump(rdr);
|
||||||
"expected `f32` or `f64` suffix".to_owned());
|
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 {
|
if is_float {
|
||||||
check_float_base(rdr, start_bpos, rdr.last_pos, base);
|
check_float_base(rdr, start_bpos, rdr.last_pos, base);
|
||||||
|
|
20
src/test/run-pass/quad-precision-float.rs
Normal file
20
src/test/run-pass/quad-precision-float.rs
Normal file
|
@ -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);
|
||||||
|
}
|
|
@ -58,6 +58,7 @@ impl TyVisitor for MyVisitor {
|
||||||
|
|
||||||
fn visit_f32(&mut self) -> bool { true }
|
fn visit_f32(&mut self) -> bool { true }
|
||||||
fn visit_f64(&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 }
|
fn visit_char(&mut self) -> bool { true }
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue