Rollup merge of #124797 - beetrees:primitive-float, r=davidtwco
Refactor float `Primitive`s to a separate `Float` type Now there are 4 of them, it makes sense to refactor `F16`, `F32`, `F64` and `F128` out of `Primitive` and into a separate `Float` type (like integers already are). This allows patterns like `F16 | F32 | F64 | F128` to be simplified into `Float(_)`, and is consistent with `ty::FloatTy`. As a side effect, this PR also makes the `Ty::primitive_size` method work with `f16` and `f128`. Tracking issue: #116909 `@rustbot` label +F-f16_and_f128
This commit is contained in:
commit
1ae0d90b72
@ -926,6 +926,41 @@ pub fn from_size(size: Size) -> Result<Self, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Floating-point types.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
|
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
|
||||||
|
pub enum Float {
|
||||||
|
F16,
|
||||||
|
F32,
|
||||||
|
F64,
|
||||||
|
F128,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Float {
|
||||||
|
pub fn size(self) -> Size {
|
||||||
|
use Float::*;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
F16 => Size::from_bits(16),
|
||||||
|
F32 => Size::from_bits(32),
|
||||||
|
F64 => Size::from_bits(64),
|
||||||
|
F128 => Size::from_bits(128),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
|
||||||
|
use Float::*;
|
||||||
|
let dl = cx.data_layout();
|
||||||
|
|
||||||
|
match self {
|
||||||
|
F16 => dl.f16_align,
|
||||||
|
F32 => dl.f32_align,
|
||||||
|
F64 => dl.f64_align,
|
||||||
|
F128 => dl.f128_align,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Fundamental unit of memory access and layout.
|
/// Fundamental unit of memory access and layout.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
|
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
|
||||||
@ -938,10 +973,7 @@ 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,
|
Float(Float),
|
||||||
F32,
|
|
||||||
F64,
|
|
||||||
F128,
|
|
||||||
Pointer(AddressSpace),
|
Pointer(AddressSpace),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -952,10 +984,7 @@ pub fn size<C: HasDataLayout>(self, cx: &C) -> Size {
|
|||||||
|
|
||||||
match self {
|
match self {
|
||||||
Int(i, _) => i.size(),
|
Int(i, _) => i.size(),
|
||||||
F16 => Size::from_bits(16),
|
Float(f) => f.size(),
|
||||||
F32 => Size::from_bits(32),
|
|
||||||
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)
|
||||||
@ -969,10 +998,7 @@ pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
|
|||||||
|
|
||||||
match self {
|
match self {
|
||||||
Int(i, _) => i.align(dl),
|
Int(i, _) => i.align(dl),
|
||||||
F16 => dl.f16_align,
|
Float(f) => f.align(dl),
|
||||||
F32 => dl.f32_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)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
use rustc_middle::ty::TypeFoldable;
|
use rustc_middle::ty::TypeFoldable;
|
||||||
use rustc_span::source_map::Spanned;
|
use rustc_span::source_map::Spanned;
|
||||||
use rustc_target::abi::call::FnAbi;
|
use rustc_target::abi::call::FnAbi;
|
||||||
use rustc_target::abi::{Integer, Primitive};
|
use rustc_target::abi::{Float, Integer, Primitive};
|
||||||
use rustc_target::spec::{HasTargetSpec, Target};
|
use rustc_target::spec::{HasTargetSpec, Target};
|
||||||
|
|
||||||
use crate::constant::ConstantCx;
|
use crate::constant::ConstantCx;
|
||||||
@ -32,10 +32,12 @@ 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::Float(float) => match float {
|
||||||
Primitive::F32 => types::F32,
|
Float::F16 => unimplemented!("f16_f128"),
|
||||||
Primitive::F64 => types::F64,
|
Float::F32 => types::F32,
|
||||||
Primitive::F128 => unimplemented!("f16_f128"),
|
Float::F64 => types::F64,
|
||||||
|
Float::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),
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||||
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
|
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
|
||||||
use rustc_target::abi::{
|
use rustc_target::abi::{
|
||||||
self, Abi, Align, FieldsShape, Int, Integer, PointeeInfo, Pointer, Size, TyAbiInterface,
|
self, Abi, Align, FieldsShape, Float, Int, Integer, PointeeInfo, Pointer, Size, TyAbiInterface,
|
||||||
Variants, F128, F16, F32, F64,
|
Variants,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType};
|
use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType};
|
||||||
@ -283,10 +283,7 @@ fn scalar_gcc_type_at<'gcc>(
|
|||||||
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(),
|
Float(f) => cx.type_from_float(f),
|
||||||
F32 => cx.type_f32(),
|
|
||||||
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 = if let Some(pointee) = self.pointee_info_at(cx, offset) {
|
let pointee = if let Some(pointee) = self.pointee_info_at(cx, offset) {
|
||||||
|
@ -904,8 +904,8 @@ fn llvm_asm_scalar_type<'ll>(cx: &CodegenCx<'ll, '_>, scalar: Scalar) -> &'ll Ty
|
|||||||
Primitive::Int(Integer::I16, _) => cx.type_i16(),
|
Primitive::Int(Integer::I16, _) => cx.type_i16(),
|
||||||
Primitive::Int(Integer::I32, _) => cx.type_i32(),
|
Primitive::Int(Integer::I32, _) => cx.type_i32(),
|
||||||
Primitive::Int(Integer::I64, _) => cx.type_i64(),
|
Primitive::Int(Integer::I64, _) => cx.type_i64(),
|
||||||
Primitive::F32 => cx.type_f32(),
|
Primitive::Float(Float::F32) => cx.type_f32(),
|
||||||
Primitive::F64 => cx.type_f64(),
|
Primitive::Float(Float::F64) => cx.type_f64(),
|
||||||
// FIXME(erikdesjardins): handle non-default addrspace ptr sizes
|
// FIXME(erikdesjardins): handle non-default addrspace ptr sizes
|
||||||
Primitive::Pointer(_) => cx.type_from_integer(dl.ptr_sized_integer()),
|
Primitive::Pointer(_) => cx.type_from_integer(dl.ptr_sized_integer()),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -950,7 +950,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
|
|||||||
bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
|
bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
|
||||||
}
|
}
|
||||||
(InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
|
(InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
|
||||||
if s.primitive() == Primitive::F64 =>
|
if s.primitive() == Primitive::Float(Float::F64) =>
|
||||||
{
|
{
|
||||||
bx.bitcast(value, bx.cx.type_i64())
|
bx.bitcast(value, bx.cx.type_i64())
|
||||||
}
|
}
|
||||||
@ -986,8 +986,8 @@ fn llvm_fixup_input<'ll, 'tcx>(
|
|||||||
match s.primitive() {
|
match s.primitive() {
|
||||||
// MIPS only supports register-length arithmetics.
|
// MIPS only supports register-length arithmetics.
|
||||||
Primitive::Int(Integer::I8 | Integer::I16, _) => bx.zext(value, bx.cx.type_i32()),
|
Primitive::Int(Integer::I8 | Integer::I16, _) => bx.zext(value, bx.cx.type_i32()),
|
||||||
Primitive::F32 => bx.bitcast(value, bx.cx.type_i32()),
|
Primitive::Float(Float::F32) => bx.bitcast(value, bx.cx.type_i32()),
|
||||||
Primitive::F64 => bx.bitcast(value, bx.cx.type_i64()),
|
Primitive::Float(Float::F64) => bx.bitcast(value, bx.cx.type_i64()),
|
||||||
_ => value,
|
_ => value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1027,7 +1027,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
|
|||||||
bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
|
bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
|
||||||
}
|
}
|
||||||
(InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
|
(InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
|
||||||
if s.primitive() == Primitive::F64 =>
|
if s.primitive() == Primitive::Float(Float::F64) =>
|
||||||
{
|
{
|
||||||
bx.bitcast(value, bx.cx.type_f64())
|
bx.bitcast(value, bx.cx.type_f64())
|
||||||
}
|
}
|
||||||
@ -1064,8 +1064,8 @@ fn llvm_fixup_output<'ll, 'tcx>(
|
|||||||
// MIPS only supports register-length arithmetics.
|
// MIPS only supports register-length arithmetics.
|
||||||
Primitive::Int(Integer::I8, _) => bx.trunc(value, bx.cx.type_i8()),
|
Primitive::Int(Integer::I8, _) => bx.trunc(value, bx.cx.type_i8()),
|
||||||
Primitive::Int(Integer::I16, _) => bx.trunc(value, bx.cx.type_i16()),
|
Primitive::Int(Integer::I16, _) => bx.trunc(value, bx.cx.type_i16()),
|
||||||
Primitive::F32 => bx.bitcast(value, bx.cx.type_f32()),
|
Primitive::Float(Float::F32) => bx.bitcast(value, bx.cx.type_f32()),
|
||||||
Primitive::F64 => bx.bitcast(value, bx.cx.type_f64()),
|
Primitive::Float(Float::F64) => bx.bitcast(value, bx.cx.type_f64()),
|
||||||
_ => value,
|
_ => value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1100,7 +1100,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
|
|||||||
cx.type_vector(elem_ty, count * 2)
|
cx.type_vector(elem_ty, count * 2)
|
||||||
}
|
}
|
||||||
(InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
|
(InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
|
||||||
if s.primitive() == Primitive::F64 =>
|
if s.primitive() == Primitive::Float(Float::F64) =>
|
||||||
{
|
{
|
||||||
cx.type_i64()
|
cx.type_i64()
|
||||||
}
|
}
|
||||||
@ -1136,8 +1136,8 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
|
|||||||
match s.primitive() {
|
match s.primitive() {
|
||||||
// MIPS only supports register-length arithmetics.
|
// MIPS only supports register-length arithmetics.
|
||||||
Primitive::Int(Integer::I8 | Integer::I16, _) => cx.type_i32(),
|
Primitive::Int(Integer::I8 | Integer::I16, _) => cx.type_i32(),
|
||||||
Primitive::F32 => cx.type_i32(),
|
Primitive::Float(Float::F32) => cx.type_i32(),
|
||||||
Primitive::F64 => cx.type_i64(),
|
Primitive::Float(Float::F64) => cx.type_i64(),
|
||||||
_ => layout.llvm_type(cx),
|
_ => layout.llvm_type(cx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -576,7 +576,7 @@ fn scalar_load_metadata<'a, 'll, 'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
abi::F16 | abi::F32 | abi::F64 | abi::F128 => {}
|
abi::Float(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,10 +122,7 @@ 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::Float(f) => Integer::from_size(f.size()).unwrap(),
|
||||||
Primitive::F32 => Integer::I32,
|
|
||||||
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
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
use rustc_middle::ty::{self, GenericArgsRef, Ty};
|
use rustc_middle::ty::{self, GenericArgsRef, Ty};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_span::{sym, Span, Symbol};
|
use rustc_span::{sym, Span, Symbol};
|
||||||
use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size};
|
use rustc_target::abi::{self, Align, Float, HasDataLayout, Primitive, Size};
|
||||||
use rustc_target::spec::{HasTargetSpec, PanicStrategy};
|
use rustc_target::spec::{HasTargetSpec, PanicStrategy};
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
@ -231,13 +231,17 @@ fn codegen_intrinsic_call(
|
|||||||
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::Float(Float::F16) => {
|
||||||
Primitive::F64 | Primitive::Pointer(_) => {
|
bug!("the va_arg intrinsic does not work with `f16`")
|
||||||
|
}
|
||||||
|
Primitive::Float(Float::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::Float(Float::F32) => {
|
||||||
Primitive::F128 => {
|
bug!("the va_arg intrinsic does not work with `f32`")
|
||||||
|
}
|
||||||
|
Primitive::Float(Float::F128) => {
|
||||||
bug!("the va_arg intrinsic does not work with `f128`")
|
bug!("the va_arg intrinsic does not work with `f128`")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
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::{Abi, Align, FieldsShape};
|
use rustc_target::abi::{Abi, Align, FieldsShape};
|
||||||
use rustc_target::abi::{Int, Pointer, F128, F16, F32, F64};
|
use rustc_target::abi::{Float, Int, Pointer};
|
||||||
use rustc_target::abi::{Scalar, Size, Variants};
|
use rustc_target::abi::{Scalar, Size, Variants};
|
||||||
|
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
@ -272,10 +272,7 @@ fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
|
|||||||
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(),
|
Float(f) => cx.type_from_float(f),
|
||||||
F32 => cx.type_f32(),
|
|
||||||
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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,17 +306,15 @@ fn transmute_immediate(
|
|||||||
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(..) | F16 | F32 | F64 | F128, Int(..) | F16 | F32 | F64 | F128) => {
|
(Int(..) | Float(_), Int(..) | Float(_)) => bx.bitcast(imm, to_backend_ty),
|
||||||
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.ptradd(bx.const_null(bx.type_ptr()), imm),
|
(Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm),
|
||||||
(Pointer(..), Int(..)) => bx.ptrtoint(imm, to_backend_ty),
|
(Pointer(..), Int(..)) => bx.ptrtoint(imm, to_backend_ty),
|
||||||
(F16 | F32 | F64 | F128, Pointer(..)) => {
|
(Float(_), Pointer(..)) => {
|
||||||
let int_imm = bx.bitcast(imm, bx.cx().type_isize());
|
let int_imm = bx.bitcast(imm, bx.cx().type_isize());
|
||||||
bx.ptradd(bx.const_null(bx.type_ptr()), int_imm)
|
bx.ptradd(bx.const_null(bx.type_ptr()), int_imm)
|
||||||
}
|
}
|
||||||
(Pointer(..), F16 | F32 | F64 | F128) => {
|
(Pointer(..), Float(_)) => {
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
use rustc_middle::ty::layout::TyAndLayout;
|
use rustc_middle::ty::layout::TyAndLayout;
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg};
|
use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg};
|
||||||
use rustc_target::abi::{AddressSpace, Integer};
|
use rustc_target::abi::{AddressSpace, Float, Integer};
|
||||||
|
|
||||||
// This depends on `Backend` and not `BackendTypes`, because consumers will probably want to use
|
// This depends on `Backend` and not `BackendTypes`, because consumers will probably want to use
|
||||||
// `LayoutOf` or `HasTyCtxt`. This way, they don't have to add a constraint on it themselves.
|
// `LayoutOf` or `HasTyCtxt`. This way, they don't have to add a constraint on it themselves.
|
||||||
@ -65,6 +65,16 @@ fn type_from_integer(&self, i: Integer) -> Self::Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn type_from_float(&self, f: Float) -> Self::Type {
|
||||||
|
use Float::*;
|
||||||
|
match f {
|
||||||
|
F16 => self.type_f16(),
|
||||||
|
F32 => self.type_f32(),
|
||||||
|
F64 => self.type_f64(),
|
||||||
|
F128 => self.type_f128(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
|
fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
|
||||||
ty.needs_drop(self.tcx(), ty::ParamEnv::reveal_all())
|
ty.needs_drop(self.tcx(), ty::ParamEnv::reveal_all())
|
||||||
}
|
}
|
||||||
|
@ -114,16 +114,35 @@ fn repr_discr<'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[extension(pub trait FloatExt)]
|
||||||
|
impl Float {
|
||||||
|
#[inline]
|
||||||
|
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
||||||
|
match *self {
|
||||||
|
F16 => tcx.types.f16,
|
||||||
|
F32 => tcx.types.f32,
|
||||||
|
F64 => tcx.types.f64,
|
||||||
|
F128 => tcx.types.f128,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_float_ty(fty: ty::FloatTy) -> Self {
|
||||||
|
match fty {
|
||||||
|
ty::FloatTy::F16 => F16,
|
||||||
|
ty::FloatTy::F32 => F32,
|
||||||
|
ty::FloatTy::F64 => F64,
|
||||||
|
ty::FloatTy::F128 => F128,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[extension(pub trait PrimitiveExt)]
|
#[extension(pub trait PrimitiveExt)]
|
||||||
impl Primitive {
|
impl Primitive {
|
||||||
#[inline]
|
#[inline]
|
||||||
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,
|
Float(f) => f.to_ty(tcx),
|
||||||
F32 => tcx.types.f32,
|
|
||||||
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, tcx.types.unit),
|
Pointer(_) => Ty::new_mut_ptr(tcx, tcx.types.unit),
|
||||||
}
|
}
|
||||||
@ -140,7 +159,7 @@ fn to_int_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
|||||||
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)
|
||||||
}
|
}
|
||||||
F16 | F32 | F64 | F128 => bug!("floats do not have an int type"),
|
Float(_) => bug!("floats do not have an int type"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||||
use crate::query::{IntoQueryParam, Providers};
|
use crate::query::{IntoQueryParam, Providers};
|
||||||
use crate::ty::layout::IntegerExt;
|
use crate::ty::layout::{FloatExt, IntegerExt};
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||||
TypeVisitableExt,
|
TypeVisitableExt,
|
||||||
@ -20,7 +20,7 @@
|
|||||||
use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable};
|
use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable};
|
||||||
use rustc_session::Limit;
|
use rustc_session::Limit;
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
use rustc_target::abi::{Integer, IntegerType, Primitive, Size};
|
use rustc_target::abi::{Float, Integer, IntegerType, Size};
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use std::{fmt, iter};
|
use std::{fmt, iter};
|
||||||
@ -1145,8 +1145,7 @@ pub fn primitive_size(self, tcx: TyCtxt<'tcx>) -> Size {
|
|||||||
ty::Char => Size::from_bytes(4),
|
ty::Char => Size::from_bytes(4),
|
||||||
ty::Int(ity) => Integer::from_int_ty(&tcx, ity).size(),
|
ty::Int(ity) => Integer::from_int_ty(&tcx, ity).size(),
|
||||||
ty::Uint(uty) => Integer::from_uint_ty(&tcx, uty).size(),
|
ty::Uint(uty) => Integer::from_uint_ty(&tcx, uty).size(),
|
||||||
ty::Float(ty::FloatTy::F32) => Primitive::F32.size(&tcx),
|
ty::Float(fty) => Float::from_float_ty(fty).size(),
|
||||||
ty::Float(ty::FloatTy::F64) => Primitive::F64.size(&tcx),
|
|
||||||
_ => bug!("non primitive type"),
|
_ => bug!("non primitive type"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,10 +256,9 @@ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
|||||||
rustc_abi::Primitive::Int(length, signed) => {
|
rustc_abi::Primitive::Int(length, signed) => {
|
||||||
Primitive::Int { length: length.stable(tables), signed: *signed }
|
Primitive::Int { length: length.stable(tables), signed: *signed }
|
||||||
}
|
}
|
||||||
rustc_abi::Primitive::F16 => Primitive::Float { length: FloatLength::F16 },
|
rustc_abi::Primitive::Float(length) => {
|
||||||
rustc_abi::Primitive::F32 => Primitive::Float { length: FloatLength::F32 },
|
Primitive::Float { length: length.stable(tables) }
|
||||||
rustc_abi::Primitive::F64 => Primitive::Float { length: FloatLength::F64 },
|
}
|
||||||
rustc_abi::Primitive::F128 => Primitive::Float { length: FloatLength::F128 },
|
|
||||||
rustc_abi::Primitive::Pointer(space) => Primitive::Pointer(space.stable(tables)),
|
rustc_abi::Primitive::Pointer(space) => Primitive::Pointer(space.stable(tables)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -287,6 +286,19 @@ fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for rustc_abi::Float {
|
||||||
|
type T = FloatLength;
|
||||||
|
|
||||||
|
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||||
|
match self {
|
||||||
|
rustc_abi::Float::F16 => FloatLength::F16,
|
||||||
|
rustc_abi::Float::F32 => FloatLength::F32,
|
||||||
|
rustc_abi::Float::F64 => FloatLength::F64,
|
||||||
|
rustc_abi::Float::F128 => FloatLength::F128,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> Stable<'tcx> for rustc_abi::WrappingRange {
|
impl<'tcx> Stable<'tcx> for rustc_abi::WrappingRange {
|
||||||
type T = WrappingRange;
|
type T = WrappingRange;
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>(
|
|||||||
_ => return Err(CannotUseFpConv),
|
_ => return Err(CannotUseFpConv),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
abi::F16 | abi::F32 | abi::F64 | abi::F128 => {
|
abi::Float(_) => {
|
||||||
if arg_layout.size.bits() > flen {
|
if arg_layout.size.bits() > flen {
|
||||||
return Err(CannotUseFpConv);
|
return Err(CannotUseFpConv);
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,8 @@ fn float_reg<'a, Ty, C>(cx: &C, ret: &ArgAbi<'a, Ty>, i: usize) -> Option<Reg>
|
|||||||
{
|
{
|
||||||
match ret.layout.field(cx, i).abi {
|
match ret.layout.field(cx, i).abi {
|
||||||
abi::Abi::Scalar(scalar) => match scalar.primitive() {
|
abi::Abi::Scalar(scalar) => match scalar.primitive() {
|
||||||
abi::F32 => Some(Reg::f32()),
|
abi::Float(abi::F32) => Some(Reg::f32()),
|
||||||
abi::F64 => Some(Reg::f64()),
|
abi::Float(abi::F64) => Some(Reg::f64()),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -110,7 +110,7 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
|
|||||||
|
|
||||||
// We only care about aligned doubles
|
// We only care about aligned doubles
|
||||||
if let abi::Abi::Scalar(scalar) = field.abi {
|
if let abi::Abi::Scalar(scalar) = field.abi {
|
||||||
if let abi::F64 = scalar.primitive() {
|
if scalar.primitive() == abi::Float(abi::F64) {
|
||||||
if offset.is_aligned(dl.f64_align.abi) {
|
if offset.is_aligned(dl.f64_align.abi) {
|
||||||
// Insert enough integers to cover [last_offset, offset)
|
// Insert enough integers to cover [last_offset, offset)
|
||||||
assert!(last_offset.is_aligned(dl.f64_align.abi));
|
assert!(last_offset.is_aligned(dl.f64_align.abi));
|
||||||
|
@ -443,7 +443,7 @@ pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, H
|
|||||||
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::F16 | abi::F32 | abi::F64 | abi::F128 => RegKind::Float,
|
abi::Float(_) => RegKind::Float,
|
||||||
};
|
};
|
||||||
Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size }))
|
Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size }))
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>(
|
|||||||
_ => return Err(CannotUseFpConv),
|
_ => return Err(CannotUseFpConv),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
abi::F16 | abi::F32 | abi::F64 | abi::F128 => {
|
abi::Float(_) => {
|
||||||
if arg_layout.size.bits() > flen {
|
if arg_layout.size.bits() > flen {
|
||||||
return Err(CannotUseFpConv);
|
return Err(CannotUseFpConv);
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ fn arg_scalar<C>(cx: &C, scalar: &Scalar, offset: Size, mut data: Sdata) -> Sdat
|
|||||||
{
|
{
|
||||||
let dl = cx.data_layout();
|
let dl = cx.data_layout();
|
||||||
|
|
||||||
if !matches!(scalar.primitive(), abi::F32 | abi::F64) {
|
if !matches!(scalar.primitive(), abi::Float(abi::F32 | abi::F64)) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ fn arg_scalar<C>(cx: &C, scalar: &Scalar, offset: Size, mut data: Sdata) -> Sdat
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if scalar.primitive() == abi::F32 {
|
if scalar.primitive() == abi::Float(abi::F32) {
|
||||||
data.arg_attribute = ArgAttribute::InReg;
|
data.arg_attribute = ArgAttribute::InReg;
|
||||||
data.prefix[data.prefix_index] = Some(Reg::f32());
|
data.prefix[data.prefix_index] = Some(Reg::f32());
|
||||||
data.last_offset = offset + Reg::f32().size;
|
data.last_offset = offset + Reg::f32().size;
|
||||||
@ -80,14 +80,14 @@ fn arg_scalar_pair<C>(
|
|||||||
{
|
{
|
||||||
data = arg_scalar(cx, scalar1, offset, data);
|
data = arg_scalar(cx, scalar1, offset, data);
|
||||||
match (scalar1.primitive(), scalar2.primitive()) {
|
match (scalar1.primitive(), scalar2.primitive()) {
|
||||||
(abi::F32, _) => offset += Reg::f32().size,
|
(abi::Float(abi::F32), _) => offset += Reg::f32().size,
|
||||||
(_, abi::F64) => offset += Reg::f64().size,
|
(_, abi::Float(abi::F64)) => offset += Reg::f64().size,
|
||||||
(abi::Int(i, _signed), _) => offset += i.size(),
|
(abi::Int(i, _signed), _) => offset += i.size(),
|
||||||
(abi::Pointer(_), _) => offset += Reg::i64().size,
|
(abi::Pointer(_), _) => offset += Reg::i64().size,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset.bytes() % 4) != 0 && matches!(scalar2.primitive(), abi::F32 | abi::F64) {
|
if (offset.bytes() % 4) != 0 && matches!(scalar2.primitive(), abi::Float(abi::F32 | abi::F64)) {
|
||||||
offset += Size::from_bytes(4 - (offset.bytes() % 4));
|
offset += Size::from_bytes(4 - (offset.bytes() % 4));
|
||||||
}
|
}
|
||||||
data = arg_scalar(cx, scalar2, offset, data);
|
data = arg_scalar(cx, scalar2, offset, data);
|
||||||
|
@ -51,7 +51,7 @@ fn classify<'a, Ty, C>(
|
|||||||
|
|
||||||
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::F16 | abi::F32 | abi::F64 | abi::F128 => Class::Sse,
|
abi::Float(_) => Class::Sse,
|
||||||
},
|
},
|
||||||
|
|
||||||
Abi::Vector { .. } => Class::Sse,
|
Abi::Vector { .. } => Class::Sse,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use rustc_data_structures::intern::Interned;
|
use rustc_data_structures::intern::Interned;
|
||||||
|
pub use Float::*;
|
||||||
pub use Integer::*;
|
pub use Integer::*;
|
||||||
pub use Primitive::*;
|
pub use Primitive::*;
|
||||||
|
|
||||||
@ -11,7 +12,8 @@
|
|||||||
|
|
||||||
pub mod call;
|
pub mod call;
|
||||||
|
|
||||||
pub use rustc_abi::*;
|
// Explicitly import `Float` to avoid ambiguity with `Primitive::Float`.
|
||||||
|
pub use rustc_abi::{Float, *};
|
||||||
|
|
||||||
impl ToJson for Endian {
|
impl ToJson for Endian {
|
||||||
fn to_json(&self) -> Json {
|
fn to_json(&self) -> Json {
|
||||||
@ -207,7 +209,7 @@ pub fn is_single_fp_element<C>(self, cx: &C) -> bool
|
|||||||
C: HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
match self.abi {
|
match self.abi {
|
||||||
Abi::Scalar(scalar) => matches!(scalar.primitive(), F32 | F64),
|
Abi::Scalar(scalar) => matches!(scalar.primitive(), Float(F32 | F64)),
|
||||||
Abi::Aggregate { .. } => {
|
Abi::Aggregate { .. } => {
|
||||||
if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 {
|
if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 {
|
||||||
self.field(cx, 0).is_single_fp_element(cx)
|
self.field(cx, 0).is_single_fp_element(cx)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
use rustc_middle::mir::{CoroutineLayout, CoroutineSavedLocal};
|
use rustc_middle::mir::{CoroutineLayout, CoroutineSavedLocal};
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::layout::{
|
use rustc_middle::ty::layout::{
|
||||||
IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
|
FloatExt, IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
@ -180,12 +180,7 @@ 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(Float(Float::from_float_ty(fty))),
|
||||||
ty::FloatTy::F16 => F16,
|
|
||||||
ty::FloatTy::F32 => F32,
|
|
||||||
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));
|
||||||
ptr.valid_range_mut().start = 1;
|
ptr.valid_range_mut().start = 1;
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
|
use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
layout::{
|
layout::{
|
||||||
Abi, FieldsShape, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions, Scalar, Size,
|
Abi, FieldsShape, Float, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions,
|
||||||
StructKind, TargetDataLayout, WrappingRange,
|
Scalar, Size, StructKind, TargetDataLayout, WrappingRange,
|
||||||
},
|
},
|
||||||
LocalFieldId, StructId,
|
LocalFieldId, StructId,
|
||||||
};
|
};
|
||||||
@ -264,10 +264,10 @@ pub fn layout_of_ty_query(
|
|||||||
),
|
),
|
||||||
chalk_ir::Scalar::Float(f) => scalar(
|
chalk_ir::Scalar::Float(f) => scalar(
|
||||||
dl,
|
dl,
|
||||||
match f {
|
Primitive::Float(match f {
|
||||||
FloatTy::F32 => Primitive::F32,
|
FloatTy::F32 => Float::F32,
|
||||||
FloatTy::F64 => Primitive::F64,
|
FloatTy::F64 => Float::F64,
|
||||||
},
|
}),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
TyKind::Tuple(len, tys) => {
|
TyKind::Tuple(len, tys) => {
|
||||||
|
@ -576,7 +576,9 @@ error: ABIs are not compatible
|
|||||||
},
|
},
|
||||||
abi: Scalar(
|
abi: Scalar(
|
||||||
Initialized {
|
Initialized {
|
||||||
value: F32,
|
value: Float(
|
||||||
|
F32,
|
||||||
|
),
|
||||||
valid_range: $FULL,
|
valid_range: $FULL,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
Loading…
Reference in New Issue
Block a user