Auto merge of #121728 - tgross35:f16-f128-step1-ty-updates, r=compiler-errors

Add stubs in IR and ABI for `f16` and `f128`

This is the very first step toward the changes in https://github.com/rust-lang/rust/pull/114607 and the [`f16` and `f128` RFC](https://rust-lang.github.io/rfcs/3453-f16-and-f128.html). It adds the types to `rustc_type_ir::FloatTy` and `rustc_abi::Primitive`, and just propagates those out as `unimplemented!` stubs where necessary.

These types do not parse yet so there is no feature gate, and it should be okay to use `unimplemented!`.

The next steps will probably be AST support with parsing and the feature gate.

r? `@compiler-errors`
cc `@Nilstrieb` suggested breaking the PR up in https://github.com/rust-lang/rust/pull/120645#issuecomment-1925900572
This commit is contained in:
bors 2024-03-01 03:36:11 +00:00
commit 6cbf0926d5
37 changed files with 233 additions and 14 deletions

View file

@ -171,8 +171,10 @@ pub struct TargetDataLayout {
pub i32_align: AbiAndPrefAlign, pub i32_align: AbiAndPrefAlign,
pub i64_align: AbiAndPrefAlign, pub i64_align: AbiAndPrefAlign,
pub i128_align: AbiAndPrefAlign, pub i128_align: AbiAndPrefAlign,
pub f16_align: AbiAndPrefAlign,
pub f32_align: AbiAndPrefAlign, pub f32_align: AbiAndPrefAlign,
pub f64_align: AbiAndPrefAlign, pub f64_align: AbiAndPrefAlign,
pub f128_align: AbiAndPrefAlign,
pub pointer_size: Size, pub pointer_size: Size,
pub pointer_align: AbiAndPrefAlign, pub pointer_align: AbiAndPrefAlign,
pub aggregate_align: AbiAndPrefAlign, pub aggregate_align: AbiAndPrefAlign,
@ -200,8 +202,10 @@ impl Default for TargetDataLayout {
i32_align: AbiAndPrefAlign::new(align(32)), i32_align: AbiAndPrefAlign::new(align(32)),
i64_align: AbiAndPrefAlign { abi: align(32), pref: align(64) }, i64_align: AbiAndPrefAlign { abi: align(32), pref: align(64) },
i128_align: AbiAndPrefAlign { abi: align(32), pref: align(64) }, i128_align: AbiAndPrefAlign { abi: align(32), pref: align(64) },
f16_align: AbiAndPrefAlign::new(align(16)),
f32_align: AbiAndPrefAlign::new(align(32)), f32_align: AbiAndPrefAlign::new(align(32)),
f64_align: AbiAndPrefAlign::new(align(64)), f64_align: AbiAndPrefAlign::new(align(64)),
f128_align: AbiAndPrefAlign::new(align(128)),
pointer_size: Size::from_bits(64), pointer_size: Size::from_bits(64),
pointer_align: AbiAndPrefAlign::new(align(64)), pointer_align: AbiAndPrefAlign::new(align(64)),
aggregate_align: AbiAndPrefAlign { abi: align(0), pref: align(64) }, aggregate_align: AbiAndPrefAlign { abi: align(0), pref: align(64) },
@ -281,8 +285,10 @@ impl TargetDataLayout {
dl.instruction_address_space = parse_address_space(&p[1..], "P")? dl.instruction_address_space = parse_address_space(&p[1..], "P")?
} }
["a", ref a @ ..] => dl.aggregate_align = parse_align(a, "a")?, ["a", ref a @ ..] => dl.aggregate_align = parse_align(a, "a")?,
["f16", ref a @ ..] => dl.f16_align = parse_align(a, "f16")?,
["f32", ref a @ ..] => dl.f32_align = parse_align(a, "f32")?, ["f32", ref a @ ..] => dl.f32_align = parse_align(a, "f32")?,
["f64", ref a @ ..] => dl.f64_align = parse_align(a, "f64")?, ["f64", ref a @ ..] => dl.f64_align = parse_align(a, "f64")?,
["f128", ref a @ ..] => dl.f128_align = parse_align(a, "f128")?,
// FIXME(erikdesjardins): we should be parsing nonzero address spaces // FIXME(erikdesjardins): we should be parsing nonzero address spaces
// this will require replacing TargetDataLayout::{pointer_size,pointer_align} // this will require replacing TargetDataLayout::{pointer_size,pointer_align}
// with e.g. `fn pointer_size_in(AddressSpace)` // with e.g. `fn pointer_size_in(AddressSpace)`
@ -919,8 +925,10 @@ pub enum Primitive {
/// a negative integer passed by zero-extension will appear positive in /// a negative integer passed by zero-extension will appear positive in
/// the callee, and most operations on it will produce the wrong values. /// the callee, and most operations on it will produce the wrong values.
Int(Integer, bool), Int(Integer, bool),
F16,
F32, F32,
F64, F64,
F128,
Pointer(AddressSpace), Pointer(AddressSpace),
} }
@ -931,8 +939,10 @@ impl Primitive {
match self { match self {
Int(i, _) => i.size(), Int(i, _) => i.size(),
F16 => Size::from_bits(16),
F32 => Size::from_bits(32), F32 => Size::from_bits(32),
F64 => Size::from_bits(64), F64 => Size::from_bits(64),
F128 => Size::from_bits(128),
// FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in // FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in
// different address spaces can have different sizes // different address spaces can have different sizes
// (but TargetDataLayout doesn't currently parse that part of the DL string) // (but TargetDataLayout doesn't currently parse that part of the DL string)
@ -946,8 +956,10 @@ impl Primitive {
match self { match self {
Int(i, _) => i.align(dl), Int(i, _) => i.align(dl),
F16 => dl.f16_align,
F32 => dl.f32_align, F32 => dl.f32_align,
F64 => dl.f64_align, F64 => dl.f64_align,
F128 => dl.f128_align,
// FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in // FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in
// different address spaces can have different alignments // different address spaces can have different alignments
// (but TargetDataLayout doesn't currently parse that part of the DL string) // (but TargetDataLayout doesn't currently parse that part of the DL string)

View file

@ -33,8 +33,10 @@ pub(crate) fn scalar_to_clif_type(tcx: TyCtxt<'_>, scalar: Scalar) -> Type {
Integer::I64 => types::I64, Integer::I64 => types::I64,
Integer::I128 => types::I128, Integer::I128 => types::I128,
}, },
Primitive::F16 => unimplemented!("f16_f128"),
Primitive::F32 => types::F32, Primitive::F32 => types::F32,
Primitive::F64 => types::F64, Primitive::F64 => types::F64,
Primitive::F128 => unimplemented!("f16_f128"),
// FIXME(erikdesjardins): handle non-default addrspace ptr sizes // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
Primitive::Pointer(_) => pointer_ty(tcx), Primitive::Pointer(_) => pointer_ty(tcx),
} }
@ -61,8 +63,10 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<types::Typ
}, },
ty::Char => types::I32, ty::Char => types::I32,
ty::Float(size) => match size { ty::Float(size) => match size {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => types::F32, FloatTy::F32 => types::F32,
FloatTy::F64 => types::F64, FloatTy::F64 => types::F64,
FloatTy::F128 => unimplemented!("f16_f128"),
}, },
ty::FnPtr(_) => pointer_ty(tcx), ty::FnPtr(_) => pointer_ty(tcx),
ty::RawPtr(TypeAndMut { ty: pointee_ty, mutbl: _ }) | ty::Ref(_, pointee_ty, _) => { ty::RawPtr(TypeAndMut { ty: pointee_ty, mutbl: _ }) | ty::Ref(_, pointee_ty, _) => {

View file

@ -83,8 +83,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
pub fn type_float_from_ty(&self, t: ty::FloatTy) -> Type<'gcc> { pub fn type_float_from_ty(&self, t: ty::FloatTy) -> Type<'gcc> {
match t { match t {
ty::FloatTy::F16 => self.type_f16(),
ty::FloatTy::F32 => self.type_f32(), ty::FloatTy::F32 => self.type_f32(),
ty::FloatTy::F64 => self.type_f64(), ty::FloatTy::F64 => self.type_f64(),
ty::FloatTy::F128 => self.type_f128(),
} }
} }
} }
@ -118,6 +120,10 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
self.isize_type self.isize_type
} }
fn type_f16(&self) -> Type<'gcc> {
unimplemented!("f16_f128")
}
fn type_f32(&self) -> Type<'gcc> { fn type_f32(&self) -> Type<'gcc> {
self.float_type self.float_type
} }
@ -125,6 +131,10 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
fn type_f64(&self) -> Type<'gcc> { fn type_f64(&self) -> Type<'gcc> {
self.double_type self.double_type
} }
fn type_f128(&self) -> Type<'gcc> {
unimplemented!("f16_f128")
}
fn type_func(&self, params: &[Type<'gcc>], return_type: Type<'gcc>) -> Type<'gcc> { fn type_func(&self, params: &[Type<'gcc>], return_type: Type<'gcc>) -> Type<'gcc> {
self.context.new_function_pointer_type(None, return_type, params, false) self.context.new_function_pointer_type(None, return_type, params, false)

View file

@ -6,7 +6,7 @@ use rustc_middle::bug;
use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_middle::ty::{self, Ty, TypeVisitableExt};
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_target::abi::{self, Abi, Align, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants}; use rustc_target::abi::{self, Abi, Align, F16, F128, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants};
use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType}; use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType};
@ -257,8 +257,10 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
match scalar.primitive() { match scalar.primitive() {
Int(i, true) => cx.type_from_integer(i), Int(i, true) => cx.type_from_integer(i),
Int(i, false) => cx.type_from_unsigned_integer(i), Int(i, false) => cx.type_from_unsigned_integer(i),
F16 => cx.type_f16(),
F32 => cx.type_f32(), F32 => cx.type_f32(),
F64 => cx.type_f64(), F64 => cx.type_f64(),
F128 => cx.type_f128(),
Pointer(address_space) => { Pointer(address_space) => {
// If we know the alignment, pick something better than i8. // If we know the alignment, pick something better than i8.
let pointee = let pointee =

View file

@ -568,7 +568,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
} }
} }
abi::F32 | abi::F64 => {} abi::F16 | abi::F32 | abi::F64 | abi::F128 => {}
} }
} }

View file

@ -695,9 +695,13 @@ impl MsvcBasicName for ty::UintTy {
impl MsvcBasicName for ty::FloatTy { impl MsvcBasicName for ty::FloatTy {
fn msvc_basic_name(self) -> &'static str { fn msvc_basic_name(self) -> &'static str {
// FIXME: f16 and f128 have no MSVE representation. We could improve the debuginfo.
// See: <https://github.com/rust-lang/rust/pull/114607/files#r1454683264>
match self { match self {
ty::FloatTy::F16 => "half",
ty::FloatTy::F32 => "float", ty::FloatTy::F32 => "float",
ty::FloatTy::F64 => "double", ty::FloatTy::F64 => "double",
ty::FloatTy::F128 => "fp128",
} }
} }
} }

View file

@ -122,8 +122,10 @@ fn tag_base_type<'ll, 'tcx>(
// Niche tags are always normalized to unsized integers of the correct size. // Niche tags are always normalized to unsized integers of the correct size.
match tag.primitive() { match tag.primitive() {
Primitive::Int(t, _) => t, Primitive::Int(t, _) => t,
Primitive::F16 => Integer::I16,
Primitive::F32 => Integer::I32, Primitive::F32 => Integer::I32,
Primitive::F64 => Integer::I64, Primitive::F64 => Integer::I64,
Primitive::F128 => Integer::I128,
// FIXME(erikdesjardins): handle non-default addrspace ptr sizes // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
Primitive::Pointer(_) => { Primitive::Pointer(_) => {
// If the niche is the NULL value of a reference, then `discr_enum_ty` will be // If the niche is the NULL value of a reference, then `discr_enum_ty` will be

View file

@ -163,11 +163,15 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
emit_va_arg(self, args[0], ret_ty) emit_va_arg(self, args[0], ret_ty)
} }
} }
Primitive::F16 => bug!("the va_arg intrinsic does not work with `f16`"),
Primitive::F64 | Primitive::Pointer(_) => { Primitive::F64 | Primitive::Pointer(_) => {
emit_va_arg(self, args[0], ret_ty) emit_va_arg(self, args[0], ret_ty)
} }
// `va_arg` should never be used with the return type f32. // `va_arg` should never be used with the return type f32.
Primitive::F32 => bug!("the va_arg intrinsic does not work with `f32`"), Primitive::F32 => bug!("the va_arg intrinsic does not work with `f32`"),
Primitive::F128 => {
bug!("the va_arg intrinsic does not work with `f128`")
}
} }
} }
_ => bug!("the va_arg intrinsic does not work with non-scalar types"), _ => bug!("the va_arg intrinsic does not work with non-scalar types"),

View file

@ -858,8 +858,10 @@ extern "C" {
pub fn LLVMGetIntTypeWidth(IntegerTy: &Type) -> c_uint; pub fn LLVMGetIntTypeWidth(IntegerTy: &Type) -> c_uint;
// Operations on real types // Operations on real types
pub fn LLVMHalfTypeInContext(C: &Context) -> &Type;
pub fn LLVMFloatTypeInContext(C: &Context) -> &Type; pub fn LLVMFloatTypeInContext(C: &Context) -> &Type;
pub fn LLVMDoubleTypeInContext(C: &Context) -> &Type; pub fn LLVMDoubleTypeInContext(C: &Context) -> &Type;
pub fn LLVMFP128TypeInContext(C: &Context) -> &Type;
// Operations on function types // Operations on function types
pub fn LLVMFunctionType<'a>( pub fn LLVMFunctionType<'a>(

View file

@ -107,8 +107,10 @@ impl<'ll> CodegenCx<'ll, '_> {
pub(crate) fn type_float_from_ty(&self, t: ty::FloatTy) -> &'ll Type { pub(crate) fn type_float_from_ty(&self, t: ty::FloatTy) -> &'ll Type {
match t { match t {
ty::FloatTy::F16 => self.type_f16(),
ty::FloatTy::F32 => self.type_f32(), ty::FloatTy::F32 => self.type_f32(),
ty::FloatTy::F64 => self.type_f64(), ty::FloatTy::F64 => self.type_f64(),
ty::FloatTy::F128 => self.type_f128(),
} }
} }
@ -156,6 +158,10 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
self.isize_ty self.isize_ty
} }
fn type_f16(&self) -> &'ll Type {
unsafe { llvm::LLVMHalfTypeInContext(self.llcx) }
}
fn type_f32(&self) -> &'ll Type { fn type_f32(&self) -> &'ll Type {
unsafe { llvm::LLVMFloatTypeInContext(self.llcx) } unsafe { llvm::LLVMFloatTypeInContext(self.llcx) }
} }
@ -164,6 +170,10 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
unsafe { llvm::LLVMDoubleTypeInContext(self.llcx) } unsafe { llvm::LLVMDoubleTypeInContext(self.llcx) }
} }
fn type_f128(&self) -> &'ll Type {
unsafe { llvm::LLVMFP128TypeInContext(self.llcx) }
}
fn type_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type { fn type_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, False) } unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, False) }
} }
@ -195,7 +205,7 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
match self.type_kind(ty) { match self.type_kind(ty) {
TypeKind::Array | TypeKind::Vector => unsafe { llvm::LLVMGetElementType(ty) }, TypeKind::Array | TypeKind::Vector => unsafe { llvm::LLVMGetElementType(ty) },
TypeKind::Pointer => bug!("element_type is not supported for opaque pointers"), TypeKind::Pointer => bug!("element_type is not supported for opaque pointers"),
other => bug!("element_type called on unsupported type {:?}", other), other => bug!("element_type called on unsupported type {other:?}"),
} }
} }
@ -205,11 +215,12 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
fn float_width(&self, ty: &'ll Type) -> usize { fn float_width(&self, ty: &'ll Type) -> usize {
match self.type_kind(ty) { match self.type_kind(ty) {
TypeKind::Half => 16,
TypeKind::Float => 32, TypeKind::Float => 32,
TypeKind::Double => 64, TypeKind::Double => 64,
TypeKind::X86_FP80 => 80, TypeKind::X86_FP80 => 80,
TypeKind::FP128 | TypeKind::PPC_FP128 => 128, TypeKind::FP128 | TypeKind::PPC_FP128 => 128,
_ => bug!("llvm_float_width called on a non-float type"), other => bug!("llvm_float_width called on a non-float type {other:?}"),
} }
} }

View file

@ -8,7 +8,7 @@ use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_middle::ty::{self, Ty, TypeVisitableExt};
use rustc_target::abi::HasDataLayout; use rustc_target::abi::HasDataLayout;
use rustc_target::abi::{Abi, Align, FieldsShape}; use rustc_target::abi::{Abi, Align, FieldsShape};
use rustc_target::abi::{Int, Pointer, F32, F64}; use rustc_target::abi::{Int, Pointer, F128, F16, F32, F64};
use rustc_target::abi::{Scalar, Size, Variants}; use rustc_target::abi::{Scalar, Size, Variants};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
@ -291,8 +291,10 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, scalar: Scalar) -> &'a Type { fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, scalar: Scalar) -> &'a Type {
match scalar.primitive() { match scalar.primitive() {
Int(i, _) => cx.type_from_integer(i), Int(i, _) => cx.type_from_integer(i),
F16 => cx.type_f16(),
F32 => cx.type_f32(), F32 => cx.type_f32(),
F64 => cx.type_f64(), F64 => cx.type_f64(),
F128 => cx.type_f128(),
Pointer(address_space) => cx.type_ptr_ext(address_space), Pointer(address_space) => cx.type_ptr_ext(address_space),
} }
} }

View file

@ -303,15 +303,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty); self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty);
imm = match (from_scalar.primitive(), to_scalar.primitive()) { imm = match (from_scalar.primitive(), to_scalar.primitive()) {
(Int(..) | F32 | F64, Int(..) | F32 | F64) => bx.bitcast(imm, to_backend_ty), (Int(..) | F16 | F32 | F64 | F128, Int(..) | F16 | F32 | F64 | F128) => {
bx.bitcast(imm, to_backend_ty)
}
(Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty), (Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty),
(Int(..), Pointer(..)) => bx.inttoptr(imm, to_backend_ty), (Int(..), Pointer(..)) => bx.inttoptr(imm, to_backend_ty),
(Pointer(..), Int(..)) => bx.ptrtoint(imm, to_backend_ty), (Pointer(..), Int(..)) => bx.ptrtoint(imm, to_backend_ty),
(F32 | F64, Pointer(..)) => { (F16 | F32 | F64 | F128, Pointer(..)) => {
let int_imm = bx.bitcast(imm, bx.cx().type_isize()); let int_imm = bx.bitcast(imm, bx.cx().type_isize());
bx.inttoptr(int_imm, to_backend_ty) bx.inttoptr(int_imm, to_backend_ty)
} }
(Pointer(..), F32 | F64) => { (Pointer(..), F16 | F32 | F64 | F128) => {
let int_imm = bx.ptrtoint(imm, bx.cx().type_isize()); let int_imm = bx.ptrtoint(imm, bx.cx().type_isize());
bx.bitcast(int_imm, to_backend_ty) bx.bitcast(int_imm, to_backend_ty)
} }

View file

@ -19,8 +19,10 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
fn type_i128(&self) -> Self::Type; fn type_i128(&self) -> Self::Type;
fn type_isize(&self) -> Self::Type; fn type_isize(&self) -> Self::Type;
fn type_f16(&self) -> Self::Type;
fn type_f32(&self) -> Self::Type; fn type_f32(&self) -> Self::Type;
fn type_f64(&self) -> Self::Type; fn type_f64(&self) -> Self::Type;
fn type_f128(&self) -> Self::Type;
fn type_array(&self, ty: Self::Type, len: u64) -> Self::Type; fn type_array(&self, ty: Self::Type, len: u64) -> Self::Type;
fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type; fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;

View file

@ -389,12 +389,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let left = left.to_scalar(); let left = left.to_scalar();
let right = right.to_scalar(); let right = right.to_scalar();
Ok(match fty { Ok(match fty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => { FloatTy::F32 => {
self.binary_float_op(bin_op, layout, left.to_f32()?, right.to_f32()?) self.binary_float_op(bin_op, layout, left.to_f32()?, right.to_f32()?)
} }
FloatTy::F64 => { FloatTy::F64 => {
self.binary_float_op(bin_op, layout, left.to_f64()?, right.to_f64()?) self.binary_float_op(bin_op, layout, left.to_f64()?, right.to_f64()?)
} }
FloatTy::F128 => unimplemented!("f16_f128"),
}) })
} }
_ if left.layout.ty.is_integral() => { _ if left.layout.ty.is_integral() => {

View file

@ -561,8 +561,10 @@ fn lint_literal<'tcx>(
ty::Float(t) => { ty::Float(t) => {
let is_infinite = match lit.node { let is_infinite = match lit.node {
ast::LitKind::Float(v, _) => match t { ast::LitKind::Float(v, _) => match t {
ty::FloatTy::F16 => unimplemented!("f16_f128"),
ty::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite), ty::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite),
ty::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite), ty::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite),
ty::FloatTy::F128 => unimplemented!("f16_f128"),
}, },
_ => bug!(), _ => bug!(),
}; };

View file

@ -335,8 +335,10 @@ pub struct CommonTypes<'tcx> {
pub u32: Ty<'tcx>, pub u32: Ty<'tcx>,
pub u64: Ty<'tcx>, pub u64: Ty<'tcx>,
pub u128: Ty<'tcx>, pub u128: Ty<'tcx>,
pub f16: Ty<'tcx>,
pub f32: Ty<'tcx>, pub f32: Ty<'tcx>,
pub f64: Ty<'tcx>, pub f64: Ty<'tcx>,
pub f128: Ty<'tcx>,
pub str_: Ty<'tcx>, pub str_: Ty<'tcx>,
pub never: Ty<'tcx>, pub never: Ty<'tcx>,
pub self_param: Ty<'tcx>, pub self_param: Ty<'tcx>,
@ -416,8 +418,10 @@ impl<'tcx> CommonTypes<'tcx> {
u32: mk(Uint(ty::UintTy::U32)), u32: mk(Uint(ty::UintTy::U32)),
u64: mk(Uint(ty::UintTy::U64)), u64: mk(Uint(ty::UintTy::U64)),
u128: mk(Uint(ty::UintTy::U128)), u128: mk(Uint(ty::UintTy::U128)),
f16: mk(Float(ty::FloatTy::F16)),
f32: mk(Float(ty::FloatTy::F32)), f32: mk(Float(ty::FloatTy::F32)),
f64: mk(Float(ty::FloatTy::F64)), f64: mk(Float(ty::FloatTy::F64)),
f128: mk(Float(ty::FloatTy::F128)),
str_: mk(Str), str_: mk(Str),
self_param: mk(ty::Param(ty::ParamTy { index: 0, name: kw::SelfUpper })), self_param: mk(ty::Param(ty::ParamTy { index: 0, name: kw::SelfUpper })),

View file

@ -116,8 +116,10 @@ impl Primitive {
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match *self { match *self {
Int(i, signed) => i.to_ty(tcx, signed), Int(i, signed) => i.to_ty(tcx, signed),
F16 => tcx.types.f16,
F32 => tcx.types.f32, F32 => tcx.types.f32,
F64 => tcx.types.f64, F64 => tcx.types.f64,
F128 => tcx.types.f128,
// FIXME(erikdesjardins): handle non-default addrspace ptr sizes // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
Pointer(_) => Ty::new_mut_ptr(tcx, Ty::new_unit(tcx)), Pointer(_) => Ty::new_mut_ptr(tcx, Ty::new_unit(tcx)),
} }
@ -134,7 +136,7 @@ impl Primitive {
let signed = false; let signed = false;
tcx.data_layout().ptr_sized_integer().to_ty(tcx, signed) tcx.data_layout().ptr_sized_integer().to_ty(tcx, signed)
} }
F32 | F64 => bug!("floats do not have an int type"), F16 | F32 | F64 | F128 => bug!("floats do not have an int type"),
} }
} }
} }

View file

@ -1580,8 +1580,10 @@ impl<'tcx> Ty<'tcx> {
pub fn new_float(tcx: TyCtxt<'tcx>, f: ty::FloatTy) -> Ty<'tcx> { pub fn new_float(tcx: TyCtxt<'tcx>, f: ty::FloatTy) -> Ty<'tcx> {
use ty::FloatTy::*; use ty::FloatTy::*;
match f { match f {
F16 => tcx.types.f16,
F32 => tcx.types.f32, F32 => tcx.types.f32,
F64 => tcx.types.f64, F64 => tcx.types.f64,
F128 => tcx.types.f128,
} }
} }
@ -2539,8 +2541,10 @@ impl<'tcx> Ty<'tcx> {
ty::Bool => Some(sym::bool), ty::Bool => Some(sym::bool),
ty::Char => Some(sym::char), ty::Char => Some(sym::char),
ty::Float(f) => match f { ty::Float(f) => match f {
ty::FloatTy::F16 => Some(sym::f16),
ty::FloatTy::F32 => Some(sym::f32), ty::FloatTy::F32 => Some(sym::f32),
ty::FloatTy::F64 => Some(sym::f64), ty::FloatTy::F64 => Some(sym::f64),
ty::FloatTy::F128 => Some(sym::f128),
}, },
ty::Int(f) => match f { ty::Int(f) => match f {
ty::IntTy::Isize => Some(sym::isize), ty::IntTy::Isize => Some(sym::isize),

View file

@ -1053,6 +1053,7 @@ pub(crate) fn parse_float_into_scalar(
) -> Option<Scalar> { ) -> Option<Scalar> {
let num = num.as_str(); let num = num.as_str();
match float_ty { match float_ty {
ty::FloatTy::F16 => unimplemented!("f16_f128"),
ty::FloatTy::F32 => { ty::FloatTy::F32 => {
let Ok(rust_f) = num.parse::<f32>() else { return None }; let Ok(rust_f) = num.parse::<f32>() else { return None };
let mut f = num let mut f = num
@ -1099,6 +1100,7 @@ pub(crate) fn parse_float_into_scalar(
Some(Scalar::from_f64(f)) Some(Scalar::from_f64(f))
} }
ty::FloatTy::F128 => unimplemented!("f16_f128"),
} }
} }

View file

@ -442,8 +442,10 @@ impl<'tcx> ConstToPat<'tcx> {
ty::Float(flt) => { ty::Float(flt) => {
let v = cv.unwrap_leaf(); let v = cv.unwrap_leaf();
let is_nan = match flt { let is_nan = match flt {
ty::FloatTy::F16 => unimplemented!("f16_f128"),
ty::FloatTy::F32 => v.try_to_f32().unwrap().is_nan(), ty::FloatTy::F32 => v.try_to_f32().unwrap().is_nan(),
ty::FloatTy::F64 => v.try_to_f64().unwrap().is_nan(), ty::FloatTy::F64 => v.try_to_f64().unwrap().is_nan(),
ty::FloatTy::F128 => unimplemented!("f16_f128"),
}; };
if is_nan { if is_nan {
// NaNs are not ever equal to anything so they make no sense as patterns. // NaNs are not ever equal to anything so they make no sense as patterns.

View file

@ -604,6 +604,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
let lo = lo.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env)); let lo = lo.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env));
let hi = hi.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env)); let hi = hi.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env));
match fty { match fty {
ty::FloatTy::F16 => unimplemented!("f16_f128"),
ty::FloatTy::F32 => { ty::FloatTy::F32 => {
use rustc_apfloat::ieee::Single; use rustc_apfloat::ieee::Single;
let lo = lo.map(Single::from_bits).unwrap_or(-Single::INFINITY); let lo = lo.map(Single::from_bits).unwrap_or(-Single::INFINITY);
@ -616,6 +617,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
let hi = hi.map(Double::from_bits).unwrap_or(Double::INFINITY); let hi = hi.map(Double::from_bits).unwrap_or(Double::INFINITY);
F64Range(lo, hi, end) F64Range(lo, hi, end)
} }
ty::FloatTy::F128 => unimplemented!("f16_f128"),
} }
} }
_ => bug!("invalid type for range pattern: {}", ty.inner()), _ => bug!("invalid type for range pattern: {}", ty.inner()),

View file

@ -297,8 +297,10 @@ impl<'tcx> Stable<'tcx> for ty::FloatTy {
fn stable(&self, _: &mut Tables<'_>) -> Self::T { fn stable(&self, _: &mut Tables<'_>) -> Self::T {
match self { match self {
ty::FloatTy::F16 => unimplemented!("f16_f128"),
ty::FloatTy::F32 => FloatTy::F32, ty::FloatTy::F32 => FloatTy::F32,
ty::FloatTy::F64 => FloatTy::F64, ty::FloatTy::F64 => FloatTy::F64,
ty::FloatTy::F128 => unimplemented!("f16_f128"),
} }
} }
} }

View file

@ -758,6 +758,8 @@ symbols! {
external, external,
external_doc, external_doc,
f, f,
f128,
f16,
f16c_target_feature, f16c_target_feature,
f32, f32,
f32_legacy_const_digits, f32_legacy_const_digits,

View file

@ -470,8 +470,10 @@ fn encode_ty<'tcx>(
// (See https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#fixed-width-floating-point-types.) // (See https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#fixed-width-floating-point-types.)
ty::Float(float_ty) => { ty::Float(float_ty) => {
typeid.push(match float_ty { typeid.push(match float_ty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => 'f', FloatTy::F32 => 'f',
FloatTy::F64 => 'd', FloatTy::F64 => 'd',
FloatTy::F128 => unimplemented!("f16_f128"),
}); });
} }

View file

@ -59,7 +59,7 @@ where
_ => return Err(CannotUseFpConv), _ => return Err(CannotUseFpConv),
} }
} }
abi::F32 | abi::F64 => { abi::F16 | abi::F32 | abi::F64 | abi::F128 => {
if arg_layout.size.bits() > flen { if arg_layout.size.bits() > flen {
return Err(CannotUseFpConv); return Err(CannotUseFpConv);
} }

View file

@ -412,7 +412,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
Abi::Scalar(scalar) => { Abi::Scalar(scalar) => {
let kind = match scalar.primitive() { let kind = match scalar.primitive() {
abi::Int(..) | abi::Pointer(_) => RegKind::Integer, abi::Int(..) | abi::Pointer(_) => RegKind::Integer,
abi::F32 | abi::F64 => RegKind::Float, abi::F16 | abi::F32 | abi::F64 | abi::F128 => RegKind::Float,
}; };
Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size })) Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size }))
} }

View file

@ -65,7 +65,7 @@ where
_ => return Err(CannotUseFpConv), _ => return Err(CannotUseFpConv),
} }
} }
abi::F32 | abi::F64 => { abi::F16 | abi::F32 | abi::F64 | abi::F128 => {
if arg_layout.size.bits() > flen { if arg_layout.size.bits() > flen {
return Err(CannotUseFpConv); return Err(CannotUseFpConv);
} }

View file

@ -51,7 +51,7 @@ where
Abi::Scalar(scalar) => match scalar.primitive() { Abi::Scalar(scalar) => match scalar.primitive() {
abi::Int(..) | abi::Pointer(_) => Class::Int, abi::Int(..) | abi::Pointer(_) => Class::Int,
abi::F32 | abi::F64 => Class::Sse, abi::F16 | abi::F32 | abi::F64 | abi::F128 => Class::Sse,
}, },
Abi::Vector { .. } => Class::Sse, Abi::Vector { .. } => Class::Sse,

View file

@ -394,10 +394,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
ty::Infer(ty::FloatVar(_)) => { ty::Infer(ty::FloatVar(_)) => {
// This causes a compiler error if any new float kinds are added. // This causes a compiler error if any new float kinds are added.
let (ty::FloatTy::F32 | ty::FloatTy::F64); let (ty::FloatTy::F16 | ty::FloatTy::F32 | ty::FloatTy::F64 | ty::FloatTy::F128);
let possible_floats = [ let possible_floats = [
SimplifiedType::Float(ty::FloatTy::F16),
SimplifiedType::Float(ty::FloatTy::F32), SimplifiedType::Float(ty::FloatTy::F32),
SimplifiedType::Float(ty::FloatTy::F64), SimplifiedType::Float(ty::FloatTy::F64),
SimplifiedType::Float(ty::FloatTy::F128),
]; ];
for simp in possible_floats { for simp in possible_floats {

View file

@ -141,8 +141,10 @@ fn layout_of_uncached<'tcx>(
ty::Int(ity) => scalar(Int(Integer::from_int_ty(dl, ity), true)), ty::Int(ity) => scalar(Int(Integer::from_int_ty(dl, ity), true)),
ty::Uint(ity) => scalar(Int(Integer::from_uint_ty(dl, ity), false)), ty::Uint(ity) => scalar(Int(Integer::from_uint_ty(dl, ity), false)),
ty::Float(fty) => scalar(match fty { ty::Float(fty) => scalar(match fty {
ty::FloatTy::F16 => F16,
ty::FloatTy::F32 => F32, ty::FloatTy::F32 => F32,
ty::FloatTy::F64 => F64, ty::FloatTy::F64 => F64,
ty::FloatTy::F128 => F128,
}), }),
ty::FnPtr(_) => { ty::FnPtr(_) => {
let mut ptr = scalar_unit(Pointer(dl.instruction_address_space)); let mut ptr = scalar_unit(Pointer(dl.instruction_address_space));

View file

@ -550,22 +550,28 @@ impl UintTy {
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
pub enum FloatTy { pub enum FloatTy {
F16,
F32, F32,
F64, F64,
F128,
} }
impl FloatTy { impl FloatTy {
pub fn name_str(self) -> &'static str { pub fn name_str(self) -> &'static str {
match self { match self {
FloatTy::F16 => "f16",
FloatTy::F32 => "f32", FloatTy::F32 => "f32",
FloatTy::F64 => "f64", FloatTy::F64 => "f64",
FloatTy::F128 => "f128",
} }
} }
pub fn bit_width(self) -> u64 { pub fn bit_width(self) -> u64 {
match self { match self {
FloatTy::F16 => 16,
FloatTy::F32 => 32, FloatTy::F32 => 32,
FloatTy::F64 => 64, FloatTy::F64 => 64,
FloatTy::F128 => 128,
} }
} }
} }

View file

@ -1743,8 +1743,10 @@ pub(crate) enum PrimitiveType {
U32, U32,
U64, U64,
U128, U128,
F16,
F32, F32,
F64, F64,
F128,
Char, Char,
Bool, Bool,
Str, Str,
@ -1890,8 +1892,10 @@ impl PrimitiveType {
U32 => sym::u32, U32 => sym::u32,
U64 => sym::u64, U64 => sym::u64,
U128 => sym::u128, U128 => sym::u128,
F16 => sym::f16,
F32 => sym::f32, F32 => sym::f32,
F64 => sym::f64, F64 => sym::f64,
F128 => sym::f128,
Str => sym::str, Str => sym::str,
Bool => sym::bool, Bool => sym::bool,
Char => sym::char, Char => sym::char,
@ -2008,8 +2012,10 @@ impl From<ty::UintTy> for PrimitiveType {
impl From<ty::FloatTy> for PrimitiveType { impl From<ty::FloatTy> for PrimitiveType {
fn from(float_ty: ty::FloatTy) -> PrimitiveType { fn from(float_ty: ty::FloatTy) -> PrimitiveType {
match float_ty { match float_ty {
ty::FloatTy::F16 => PrimitiveType::F16,
ty::FloatTy::F32 => PrimitiveType::F32, ty::FloatTy::F32 => PrimitiveType::F32,
ty::FloatTy::F64 => PrimitiveType::F64, ty::FloatTy::F64 => PrimitiveType::F64,
ty::FloatTy::F128 => PrimitiveType::F128,
} }
} }
} }

View file

@ -81,6 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
LitFloatType::Unsuffixed => None, LitFloatType::Unsuffixed => None,
}; };
let (is_whole, is_inf, mut float_str) = match fty { let (is_whole, is_inf, mut float_str) = match fty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => { FloatTy::F32 => {
let value = sym_str.parse::<f32>().unwrap(); let value = sym_str.parse::<f32>().unwrap();
@ -91,6 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
(value.fract() == 0.0, value.is_infinite(), formatter.format(value)) (value.fract() == 0.0, value.is_infinite(), formatter.format(value))
}, },
FloatTy::F128 => unimplemented!("f16_f128"),
}; };
if is_inf { if is_inf {
@ -135,8 +137,10 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
#[must_use] #[must_use]
fn max_digits(fty: FloatTy) -> u32 { fn max_digits(fty: FloatTy) -> u32 {
match fty { match fty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => f32::DIGITS, FloatTy::F32 => f32::DIGITS,
FloatTy::F64 => f64::DIGITS, FloatTy::F64 => f64::DIGITS,
FloatTy::F128 => unimplemented!("f16_f128"),
} }
} }

View file

@ -778,8 +778,10 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) ->
let range = alloc_range(offset + size * idx, size); let range = alloc_range(offset + size * idx, size);
let val = alloc.read_scalar(&lcx.tcx, range, /* read_provenance */ false).ok()?; let val = alloc.read_scalar(&lcx.tcx, range, /* read_provenance */ false).ok()?;
res.push(match flt { res.push(match flt {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => Constant::F32(f32::from_bits(val.to_u32().ok()?)), FloatTy::F32 => Constant::F32(f32::from_bits(val.to_u32().ok()?)),
FloatTy::F64 => Constant::F64(f64::from_bits(val.to_u64().ok()?)), FloatTy::F64 => Constant::F64(f64::from_bits(val.to_u64().ok()?)),
FloatTy::F128 => unimplemented!("f16_f128"),
}); });
} }
Some(Constant::Vec(res)) Some(Constant::Vec(res))

View file

@ -83,8 +83,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let op = op.to_scalar(); let op = op.to_scalar();
// "Bitwise" operation, no NaN adjustments // "Bitwise" operation, no NaN adjustments
match float_ty { match float_ty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => Scalar::from_f32(op.to_f32()?.abs()), FloatTy::F32 => Scalar::from_f32(op.to_f32()?.abs()),
FloatTy::F64 => Scalar::from_f64(op.to_f64()?.abs()), FloatTy::F64 => Scalar::from_f64(op.to_f64()?.abs()),
FloatTy::F128 => unimplemented!("f16_f128"),
} }
} }
Op::Sqrt => { Op::Sqrt => {
@ -93,6 +95,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
}; };
// FIXME using host floats // FIXME using host floats
match float_ty { match float_ty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => { FloatTy::F32 => {
let f = op.to_scalar().to_f32()?; let f = op.to_scalar().to_f32()?;
let res = f.to_host().sqrt().to_soft(); let res = f.to_host().sqrt().to_soft();
@ -105,6 +108,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let res = this.adjust_nan(res, &[f]); let res = this.adjust_nan(res, &[f]);
Scalar::from(res) Scalar::from(res)
} }
FloatTy::F128 => unimplemented!("f16_f128"),
} }
} }
Op::Round(rounding) => { Op::Round(rounding) => {
@ -112,6 +116,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name) span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name)
}; };
match float_ty { match float_ty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => { FloatTy::F32 => {
let f = op.to_scalar().to_f32()?; let f = op.to_scalar().to_f32()?;
let res = f.round_to_integral(rounding).value; let res = f.round_to_integral(rounding).value;
@ -124,6 +129,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let res = this.adjust_nan(res, &[f]); let res = this.adjust_nan(res, &[f]);
Scalar::from_f64(res) Scalar::from_f64(res)
} }
FloatTy::F128 => unimplemented!("f16_f128"),
} }
} }
Op::Numeric(name) => { Op::Numeric(name) => {
@ -267,6 +273,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name) span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name)
}; };
let val = match float_ty { let val = match float_ty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => { FloatTy::F32 => {
let a = a.to_f32()?; let a = a.to_f32()?;
let b = b.to_f32()?; let b = b.to_f32()?;
@ -283,6 +290,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let res = this.adjust_nan(res, &[a, b, c]); let res = this.adjust_nan(res, &[a, b, c]);
Scalar::from(res) Scalar::from(res)
} }
FloatTy::F128 => unimplemented!("f16_f128"),
}; };
this.write_scalar(val, &dest)?; this.write_scalar(val, &dest)?;
} }
@ -724,6 +732,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let left = left.to_scalar(); let left = left.to_scalar();
let right = right.to_scalar(); let right = right.to_scalar();
Ok(match float_ty { Ok(match float_ty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => { FloatTy::F32 => {
let left = left.to_f32()?; let left = left.to_f32()?;
let right = right.to_f32()?; let right = right.to_f32()?;
@ -744,6 +753,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let res = this.adjust_nan(res, &[left, right]); let res = this.adjust_nan(res, &[left, right]);
Scalar::from_f64(res) Scalar::from_f64(res)
} }
FloatTy::F128 => unimplemented!("f16_f128"),
}) })
} }
} }

View file

@ -0,0 +1,37 @@
// Make sure we don't ICE while incrementally adding f16 and f128 support
mod f16_checks {
const A: f16 = 10.0; //~ ERROR cannot find type `f16` in this scope
pub fn main() {
let a: f16 = 100.0; //~ ERROR cannot find type `f16` in this scope
let b = 0.0f16; //~ ERROR invalid width `16` for float literal
foo(1.23);
}
fn foo(a: f16) {} //~ ERROR cannot find type `f16` in this scope
struct Bar {
a: f16, //~ ERROR cannot find type `f16` in this scope
}
}
mod f128_checks {
const A: f128 = 10.0; //~ ERROR cannot find type `f128` in this scope
pub fn main() {
let a: f128 = 100.0; //~ ERROR cannot find type `f128` in this scope
let b = 0.0f128; //~ ERROR invalid width `128` for float literal
foo(1.23);
}
fn foo(a: f128) {} //~ ERROR cannot find type `f128` in this scope
struct Bar {
a: f128, //~ ERROR cannot find type `f128` in this scope
}
}
fn main() {}

View file

@ -0,0 +1,67 @@
error[E0412]: cannot find type `f16` in this scope
--> $DIR/f16-f128.rs:4:14
|
LL | const A: f16 = 10.0;
| ^^^ help: a builtin type with a similar name exists: `i16`
error[E0412]: cannot find type `f16` in this scope
--> $DIR/f16-f128.rs:7:16
|
LL | let a: f16 = 100.0;
| ^^^ help: a builtin type with a similar name exists: `i16`
error[E0412]: cannot find type `f16` in this scope
--> $DIR/f16-f128.rs:13:15
|
LL | fn foo(a: f16) {}
| ^^^ help: a builtin type with a similar name exists: `i16`
error[E0412]: cannot find type `f16` in this scope
--> $DIR/f16-f128.rs:16:12
|
LL | a: f16,
| ^^^ help: a builtin type with a similar name exists: `i16`
error[E0412]: cannot find type `f128` in this scope
--> $DIR/f16-f128.rs:21:14
|
LL | const A: f128 = 10.0;
| ^^^^ help: a builtin type with a similar name exists: `i128`
error[E0412]: cannot find type `f128` in this scope
--> $DIR/f16-f128.rs:24:16
|
LL | let a: f128 = 100.0;
| ^^^^ help: a builtin type with a similar name exists: `i128`
error[E0412]: cannot find type `f128` in this scope
--> $DIR/f16-f128.rs:30:15
|
LL | fn foo(a: f128) {}
| ^^^^ help: a builtin type with a similar name exists: `i128`
error[E0412]: cannot find type `f128` in this scope
--> $DIR/f16-f128.rs:33:12
|
LL | a: f128,
| ^^^^ help: a builtin type with a similar name exists: `i128`
error: invalid width `16` for float literal
--> $DIR/f16-f128.rs:8:17
|
LL | let b = 0.0f16;
| ^^^^^^
|
= help: valid widths are 32 and 64
error: invalid width `128` for float literal
--> $DIR/f16-f128.rs:25:17
|
LL | let b = 0.0f128;
| ^^^^^^^
|
= help: valid widths are 32 and 64
error: aborting due to 10 previous errors
For more information about this error, try `rustc --explain E0412`.