diff options
Diffstat (limited to 'src/librustc_target')
36 files changed, 438 insertions, 274 deletions
diff --git a/src/librustc_target/README.md b/src/librustc_target/README.md index a22000ea9d2..ac1e03385d1 100644 --- a/src/librustc_target/README.md +++ b/src/librustc_target/README.md @@ -1,6 +1,6 @@ `librustc_target` contains some very low-level details that are specific to different compilation targets and so forth. -For more information about how rustc works, see the [rustc guide]. +For more information about how rustc works, see the [rustc dev guide]. -[rustc guide]: https://rust-lang.github.io/rustc-guide/ +[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/ diff --git a/src/librustc_target/abi/call/aarch64.rs b/src/librustc_target/abi/call/aarch64.rs index c8bac5aebc6..1ab7722edab 100644 --- a/src/librustc_target/abi/call/aarch64.rs +++ b/src/librustc_target/abi/call/aarch64.rs @@ -1,10 +1,10 @@ use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform}; -use crate::abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; +use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods}; fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform> where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| { let size = arg.layout.size; @@ -26,8 +26,8 @@ where fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !ret.layout.is_aggregate() { ret.extend_integer_width_to(32); @@ -58,8 +58,8 @@ where fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !arg.layout.is_aggregate() { arg.extend_integer_width_to(32); @@ -90,8 +90,8 @@ where pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !fn_abi.ret.is_ignore() { classify_ret(cx, &mut fn_abi.ret); diff --git a/src/librustc_target/abi/call/amdgpu.rs b/src/librustc_target/abi/call/amdgpu.rs index 704e8b8ffa8..0b4f279fece 100644 --- a/src/librustc_target/abi/call/amdgpu.rs +++ b/src/librustc_target/abi/call/amdgpu.rs @@ -1,26 +1,26 @@ use crate::abi::call::{ArgAbi, FnAbi}; -use crate::abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; +use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods}; fn classify_ret<'a, Ty, C>(_cx: &C, ret: &mut ArgAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { ret.extend_integer_width_to(32); } fn classify_arg<'a, Ty, C>(_cx: &C, arg: &mut ArgAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { arg.extend_integer_width_to(32); } pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !fn_abi.ret.is_ignore() { classify_ret(cx, &mut fn_abi.ret); diff --git a/src/librustc_target/abi/call/arm.rs b/src/librustc_target/abi/call/arm.rs index 59ec87e3c9e..26fed3bae4e 100644 --- a/src/librustc_target/abi/call/arm.rs +++ b/src/librustc_target/abi/call/arm.rs @@ -1,11 +1,11 @@ use crate::abi::call::{ArgAbi, Conv, FnAbi, Reg, RegKind, Uniform}; -use crate::abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; +use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods}; use crate::spec::HasTargetSpec; fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform> where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| { let size = arg.layout.size; @@ -27,8 +27,8 @@ where fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, vfp: bool) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !ret.layout.is_aggregate() { ret.extend_integer_width_to(32); @@ -60,8 +60,8 @@ where fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, vfp: bool) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !arg.layout.is_aggregate() { arg.extend_integer_width_to(32); @@ -82,8 +82,8 @@ where pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout + HasTargetSpec, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec, { // If this is a target with a hard-float ABI, and the function is not explicitly // `extern "aapcs"`, then we must use the VFP registers for homogeneous aggregates. diff --git a/src/librustc_target/abi/call/mips.rs b/src/librustc_target/abi/call/mips.rs index b332b9afe7f..733a7328bd3 100644 --- a/src/librustc_target/abi/call/mips.rs +++ b/src/librustc_target/abi/call/mips.rs @@ -1,9 +1,9 @@ use crate::abi::call::{ArgAbi, FnAbi, Reg, Uniform}; -use crate::abi::{HasDataLayout, LayoutOf, Size, TyLayoutMethods}; +use crate::abi::{HasDataLayout, LayoutOf, Size, TyAndLayoutMethods}; fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size) where - Ty: TyLayoutMethods<'a, C>, + Ty: TyAndLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout, { if !ret.layout.is_aggregate() { @@ -16,7 +16,7 @@ where fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size) where - Ty: TyLayoutMethods<'a, C>, + Ty: TyAndLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout, { let dl = cx.data_layout(); @@ -37,7 +37,7 @@ where pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'_, Ty>) where - Ty: TyLayoutMethods<'a, C>, + Ty: TyAndLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout, { let mut offset = Size::ZERO; diff --git a/src/librustc_target/abi/call/mips64.rs b/src/librustc_target/abi/call/mips64.rs index 6f8910a011a..81de6306788 100644 --- a/src/librustc_target/abi/call/mips64.rs +++ b/src/librustc_target/abi/call/mips64.rs @@ -1,5 +1,5 @@ use crate::abi::call::{ArgAbi, ArgAttribute, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; -use crate::abi::{self, HasDataLayout, LayoutOf, Size, TyLayout, TyLayoutMethods}; +use crate::abi::{self, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods}; fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) { // Always sign extend u32 values on 64-bit mips @@ -19,8 +19,8 @@ fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) { fn float_reg<'a, Ty, C>(cx: &C, ret: &ArgAbi<'a, Ty>, i: usize) -> Option<Reg> where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { match ret.layout.field(cx, i).abi { abi::Abi::Scalar(ref scalar) => match scalar.value { @@ -34,8 +34,8 @@ where fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !ret.layout.is_aggregate() { extend_integer_width_mips(ret, 64); @@ -49,7 +49,7 @@ where // use of float registers to structures (not unions) containing exactly one or two // float fields. - if let abi::FieldPlacement::Arbitrary { .. } = ret.layout.fields { + if let abi::FieldsShape::Arbitrary { .. } = ret.layout.fields { if ret.layout.fields.count() == 1 { if let Some(reg) = float_reg(cx, ret, 0) { ret.cast_to(reg); @@ -74,8 +74,8 @@ where fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !arg.layout.is_aggregate() { extend_integer_width_mips(arg, 64); @@ -88,15 +88,15 @@ where let mut prefix_index = 0; match arg.layout.fields { - abi::FieldPlacement::Array { .. } => { + abi::FieldsShape::Array { .. } => { // Arrays are passed indirectly arg.make_indirect(); return; } - abi::FieldPlacement::Union(_) => { + abi::FieldsShape::Union(_) => { // Unions and are always treated as a series of 64-bit integer chunks } - abi::FieldPlacement::Arbitrary { .. } => { + abi::FieldsShape::Arbitrary { .. } => { // Structures are split up into a series of 64-bit integer chunks, but any aligned // doubles not part of another aggregate are passed as floats. let mut last_offset = Size::ZERO; @@ -143,8 +143,8 @@ where pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !fn_abi.ret.is_ignore() { classify_ret(cx, &mut fn_abi.ret); diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs index 8c7108229bd..b6bfa70005b 100644 --- a/src/librustc_target/abi/call/mod.rs +++ b/src/librustc_target/abi/call/mod.rs @@ -1,5 +1,5 @@ -use crate::abi::{self, Abi, Align, FieldPlacement, Size}; -use crate::abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; +use crate::abi::{self, Abi, Align, FieldsShape, Size}; +use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods}; use crate::spec::{self, HasTargetSpec}; mod aarch64; @@ -264,7 +264,7 @@ impl HomogeneousAggregate { } } -impl<'a, Ty> TyLayout<'a, Ty> { +impl<'a, Ty> TyAndLayout<'a, Ty> { fn is_aggregate(&self) -> bool { match self.abi { Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } => false, @@ -284,8 +284,8 @@ impl<'a, Ty> TyLayout<'a, Ty> { /// specific targets. pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, Heterogeneous> where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = Self>, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = Self>, { match self.abi { Abi::Uninhabited => Err(Heterogeneous), @@ -315,7 +315,7 @@ impl<'a, Ty> TyLayout<'a, Ty> { start: Size| -> Result<(HomogeneousAggregate, Size), Heterogeneous> { let is_union = match layout.fields { - FieldPlacement::Array { count, .. } => { + FieldsShape::Array { count, .. } => { assert_eq!(start, Size::ZERO); let result = if count > 0 { @@ -325,8 +325,8 @@ impl<'a, Ty> TyLayout<'a, Ty> { }; return Ok((result, layout.size)); } - FieldPlacement::Union(_) => true, - FieldPlacement::Arbitrary { .. } => false, + FieldsShape::Union(_) => true, + FieldsShape::Arbitrary { .. } => false, }; let mut result = HomogeneousAggregate::NoData; @@ -365,11 +365,11 @@ impl<'a, Ty> TyLayout<'a, Ty> { // // NB: for all tagged `enum`s (which include all non-C-like // `enum`s with defined FFI representation), this will - // match the homogenous computation on the equivalent + // match the homogeneous computation on the equivalent // `struct { tag; union { variant1; ... } }` and/or // `union { struct { tag; variant1; } ... }` // (the offsets of variant fields should be identical - // between the two for either to be a homogenous aggregate). + // between the two for either to be a homogeneous aggregate). let variant_start = total; for variant_idx in variants.indices() { let (variant_result, variant_total) = @@ -404,7 +404,7 @@ impl<'a, Ty> TyLayout<'a, Ty> { /// or return a value from, a function, under some ABI. #[derive(Debug)] pub struct ArgAbi<'a, Ty> { - pub layout: TyLayout<'a, Ty>, + pub layout: TyAndLayout<'a, Ty>, /// Dummy argument, which is emitted before the real argument. pub pad: Option<Reg>, @@ -413,7 +413,7 @@ pub struct ArgAbi<'a, Ty> { } impl<'a, Ty> ArgAbi<'a, Ty> { - pub fn new(layout: TyLayout<'a, Ty>) -> Self { + pub fn new(layout: TyAndLayout<'a, Ty>) -> Self { ArgAbi { layout, pad: None, mode: PassMode::Direct(ArgAttributes::new()) } } @@ -542,17 +542,19 @@ pub struct FnAbi<'a, Ty> { /// The count of non-variadic arguments. /// /// Should only be different from args.len() when c_variadic is true. - /// This can be used to know wether an argument is variadic or not. + /// This can be used to know whether an argument is variadic or not. pub fixed_count: usize, pub conv: Conv, + + pub can_unwind: bool, } impl<'a, Ty> FnAbi<'a, Ty> { pub fn adjust_for_cabi<C>(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), String> where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout + HasTargetSpec, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec, { match &cx.target_spec().arch[..] { "x86" => { diff --git a/src/librustc_target/abi/call/powerpc64.rs b/src/librustc_target/abi/call/powerpc64.rs index 93c4e97de10..b740707320f 100644 --- a/src/librustc_target/abi/call/powerpc64.rs +++ b/src/librustc_target/abi/call/powerpc64.rs @@ -3,7 +3,7 @@ // need to be fixed when PowerPC vector support is added. use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform}; -use crate::abi::{Endian, HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; +use crate::abi::{Endian, HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods}; use crate::spec::HasTargetSpec; #[derive(Debug, Clone, Copy, PartialEq)] @@ -19,8 +19,8 @@ fn is_homogeneous_aggregate<'a, Ty, C>( abi: ABI, ) -> Option<Uniform> where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| { // ELFv1 only passes one-member aggregates transparently. @@ -43,8 +43,8 @@ where fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, abi: ABI) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !ret.layout.is_aggregate() { ret.extend_integer_width_to(64); @@ -86,8 +86,8 @@ where fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, abi: ABI) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !arg.layout.is_aggregate() { arg.extend_integer_width_to(64); @@ -116,8 +116,8 @@ where pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout + HasTargetSpec, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec, { let abi = if cx.target_spec().target_env == "musl" { ELFv2 diff --git a/src/librustc_target/abi/call/riscv.rs b/src/librustc_target/abi/call/riscv.rs index 11d6c4d8191..0eb8816e434 100644 --- a/src/librustc_target/abi/call/riscv.rs +++ b/src/librustc_target/abi/call/riscv.rs @@ -6,7 +6,7 @@ use crate::abi::call::{ArgAbi, ArgAttribute, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; use crate::abi::{ - self, Abi, FieldPlacement, HasDataLayout, LayoutOf, Size, TyLayout, TyLayoutMethods, + self, Abi, FieldsShape, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods, }; use crate::spec::HasTargetSpec; @@ -36,15 +36,15 @@ fn is_riscv_aggregate<'a, Ty>(arg: &ArgAbi<'a, Ty>) -> bool { fn should_use_fp_conv_helper<'a, Ty, C>( cx: &C, - arg_layout: &TyLayout<'a, Ty>, + arg_layout: &TyAndLayout<'a, Ty>, xlen: u64, flen: u64, field1_kind: &mut RegPassKind, field2_kind: &mut RegPassKind, ) -> Result<(), CannotUseFpConv> where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>>, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>>, { match arg_layout.abi { Abi::Scalar(ref scalar) => match scalar.value { @@ -87,12 +87,12 @@ where }, Abi::Vector { .. } | Abi::Uninhabited => return Err(CannotUseFpConv), Abi::ScalarPair(..) | Abi::Aggregate { .. } => match arg_layout.fields { - FieldPlacement::Union(_) => { + FieldsShape::Union(_) => { if !arg_layout.is_zst() { return Err(CannotUseFpConv); } } - FieldPlacement::Array { count, .. } => { + FieldsShape::Array { count, .. } => { for _ in 0..count { let elem_layout = arg_layout.field(cx, 0); should_use_fp_conv_helper( @@ -105,7 +105,7 @@ where )?; } } - FieldPlacement::Arbitrary { .. } => { + FieldsShape::Arbitrary { .. } => { match arg_layout.variants { abi::Variants::Multiple { .. } => return Err(CannotUseFpConv), abi::Variants::Single { .. } => (), @@ -122,13 +122,13 @@ where fn should_use_fp_conv<'a, Ty, C>( cx: &C, - arg: &TyLayout<'a, Ty>, + arg: &TyAndLayout<'a, Ty>, xlen: u64, flen: u64, ) -> Option<FloatConv> where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>>, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>>, { let mut field1_kind = RegPassKind::Unknown; let mut field2_kind = RegPassKind::Unknown; @@ -146,8 +146,8 @@ where fn classify_ret<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, xlen: u64, flen: u64) -> bool where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>>, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>>, { if let Some(conv) = should_use_fp_conv(cx, &arg.layout, xlen, flen) { match conv { @@ -209,8 +209,8 @@ fn classify_arg<'a, Ty, C>( avail_gprs: &mut u64, avail_fprs: &mut u64, ) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>>, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>>, { if !is_vararg { match should_use_fp_conv(cx, &arg.layout, xlen, flen) { @@ -300,30 +300,25 @@ fn classify_arg<'a, Ty, C>( } fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) { - match arg.layout.abi { - Abi::Scalar(ref scalar) => { - match scalar.value { - abi::Int(i, _) => { - // 32-bit integers are always sign-extended - if i.size().bits() == 32 && xlen > 32 { - if let PassMode::Direct(ref mut attrs) = arg.mode { - attrs.set(ArgAttribute::SExt); - return; - } - } + if let Abi::Scalar(ref scalar) = arg.layout.abi { + if let abi::Int(i, _) = scalar.value { + // 32-bit integers are always sign-extended + if i.size().bits() == 32 && xlen > 32 { + if let PassMode::Direct(ref mut attrs) = arg.mode { + attrs.set(ArgAttribute::SExt); + return; } - _ => (), } } - _ => (), } + arg.extend_integer_width_to(xlen); } pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout + HasTargetSpec, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec, { let flen = match &cx.target_spec().options.llvm_abiname[..] { "ilp32f" | "lp64f" => 32, diff --git a/src/librustc_target/abi/call/s390x.rs b/src/librustc_target/abi/call/s390x.rs index d4e9511d087..005dcc62dfd 100644 --- a/src/librustc_target/abi/call/s390x.rs +++ b/src/librustc_target/abi/call/s390x.rs @@ -2,11 +2,11 @@ // for a pre-z13 machine or using -mno-vx. use crate::abi::call::{ArgAbi, FnAbi, Reg}; -use crate::abi::{self, HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; +use crate::abi::{self, HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods}; fn classify_ret<'a, Ty, C>(ret: &mut ArgAbi<'_, Ty>) where - Ty: TyLayoutMethods<'a, C>, + Ty: TyAndLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout, { if !ret.layout.is_aggregate() && ret.layout.size.bits() <= 64 { @@ -16,10 +16,10 @@ where } } -fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyLayout<'a, Ty>) -> bool +fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool where - Ty: TyLayoutMethods<'a, C>, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C>, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { match layout.abi { abi::Abi::Scalar(ref scalar) => scalar.value.is_float(), @@ -36,8 +36,8 @@ where fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 { arg.extend_integer_width_to(64); @@ -63,8 +63,8 @@ where pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !fn_abi.ret.is_ignore() { classify_ret(&mut fn_abi.ret); diff --git a/src/librustc_target/abi/call/sparc.rs b/src/librustc_target/abi/call/sparc.rs index b332b9afe7f..733a7328bd3 100644 --- a/src/librustc_target/abi/call/sparc.rs +++ b/src/librustc_target/abi/call/sparc.rs @@ -1,9 +1,9 @@ use crate::abi::call::{ArgAbi, FnAbi, Reg, Uniform}; -use crate::abi::{HasDataLayout, LayoutOf, Size, TyLayoutMethods}; +use crate::abi::{HasDataLayout, LayoutOf, Size, TyAndLayoutMethods}; fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size) where - Ty: TyLayoutMethods<'a, C>, + Ty: TyAndLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout, { if !ret.layout.is_aggregate() { @@ -16,7 +16,7 @@ where fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size) where - Ty: TyLayoutMethods<'a, C>, + Ty: TyAndLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout, { let dl = cx.data_layout(); @@ -37,7 +37,7 @@ where pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'_, Ty>) where - Ty: TyLayoutMethods<'a, C>, + Ty: TyAndLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout, { let mut offset = Size::ZERO; diff --git a/src/librustc_target/abi/call/sparc64.rs b/src/librustc_target/abi/call/sparc64.rs index c80f8316feb..a647675e073 100644 --- a/src/librustc_target/abi/call/sparc64.rs +++ b/src/librustc_target/abi/call/sparc64.rs @@ -1,12 +1,12 @@ // FIXME: This needs an audit for correctness and completeness. use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform}; -use crate::abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; +use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods}; fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform> where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| { // Ensure we have at most eight uniquely addressable members. @@ -26,8 +26,8 @@ where fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !ret.layout.is_aggregate() { ret.extend_integer_width_to(64); @@ -52,8 +52,8 @@ where fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !arg.layout.is_aggregate() { arg.extend_integer_width_to(64); @@ -76,8 +76,8 @@ where pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !fn_abi.ret.is_ignore() { classify_ret(cx, &mut fn_abi.ret); diff --git a/src/librustc_target/abi/call/wasm32.rs b/src/librustc_target/abi/call/wasm32.rs index 9aab64ef272..510f671a501 100644 --- a/src/librustc_target/abi/call/wasm32.rs +++ b/src/librustc_target/abi/call/wasm32.rs @@ -1,10 +1,10 @@ use crate::abi::call::{ArgAbi, FnAbi, Uniform}; -use crate::abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; +use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods}; fn unwrap_trivial_aggregate<'a, Ty, C>(cx: &C, val: &mut ArgAbi<'a, Ty>) -> bool where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if val.layout.is_aggregate() { if let Some(unit) = val.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()) { @@ -20,8 +20,8 @@ where fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { ret.extend_integer_width_to(32); if ret.layout.is_aggregate() { @@ -33,8 +33,8 @@ where fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { arg.extend_integer_width_to(32); if arg.layout.is_aggregate() { @@ -46,8 +46,8 @@ where pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !fn_abi.ret.is_ignore() { classify_ret(cx, &mut fn_abi.ret); diff --git a/src/librustc_target/abi/call/x86.rs b/src/librustc_target/abi/call/x86.rs index e776a8b3fe4..df3dd5d9208 100644 --- a/src/librustc_target/abi/call/x86.rs +++ b/src/librustc_target/abi/call/x86.rs @@ -1,5 +1,5 @@ use crate::abi::call::{ArgAttribute, FnAbi, PassMode, Reg, RegKind}; -use crate::abi::{self, HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; +use crate::abi::{self, HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods}; use crate::spec::HasTargetSpec; #[derive(PartialEq)] @@ -8,10 +8,10 @@ pub enum Flavor { Fastcall, } -fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyLayout<'a, Ty>) -> bool +fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { match layout.abi { abi::Abi::Scalar(ref scalar) => scalar.value.is_float(), @@ -28,8 +28,8 @@ where pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, flavor: Flavor) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout + HasTargetSpec, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec, { if !fn_abi.ret.is_ignore() { if fn_abi.ret.layout.is_aggregate() { diff --git a/src/librustc_target/abi/call/x86_64.rs b/src/librustc_target/abi/call/x86_64.rs index 4c192c46786..5f154dc1bc9 100644 --- a/src/librustc_target/abi/call/x86_64.rs +++ b/src/librustc_target/abi/call/x86_64.rs @@ -2,7 +2,7 @@ // https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp use crate::abi::call::{ArgAbi, CastTarget, FnAbi, Reg, RegKind}; -use crate::abi::{self, Abi, HasDataLayout, LayoutOf, Size, TyLayout, TyLayoutMethods}; +use crate::abi::{self, Abi, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods}; /// Classification of "eightbyte" components. // N.B., the order of the variants is from general to specific, @@ -26,18 +26,18 @@ fn classify_arg<'a, Ty, C>( arg: &ArgAbi<'a, Ty>, ) -> Result<[Option<Class>; MAX_EIGHTBYTES], Memory> where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { fn classify<'a, Ty, C>( cx: &C, - layout: TyLayout<'a, Ty>, + layout: TyAndLayout<'a, Ty>, cls: &mut [Option<Class>], off: Size, ) -> Result<(), Memory> where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { if !off.is_aligned(layout.align.abi) { if !layout.is_zst() { @@ -172,8 +172,8 @@ const MAX_SSE_REGS: usize = 8; // XMM0-7 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where - Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout, + Ty: TyAndLayoutMethods<'a, C> + Copy, + C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, { let mut int_regs = MAX_INT_REGS; let mut sse_regs = MAX_SSE_REGS; diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index ffef38cedfc..4c25363a657 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -3,6 +3,7 @@ pub use Primitive::*; use crate::spec::Target; +use std::convert::{TryFrom, TryInto}; use std::ops::{Add, AddAssign, Deref, Mul, Range, RangeInclusive, Sub}; use rustc_index::vec::{Idx, IndexVec}; @@ -240,17 +241,18 @@ pub struct Size { } impl Size { - pub const ZERO: Size = Self::from_bytes(0); + pub const ZERO: Size = Size { raw: 0 }; #[inline] - pub fn from_bits(bits: u64) -> Size { + pub fn from_bits(bits: impl TryInto<u64>) -> Size { + let bits = bits.try_into().ok().unwrap(); // Avoid potential overflow from `bits + 7`. Size::from_bytes(bits / 8 + ((bits % 8) + 7) / 8) } #[inline] - pub const fn from_bytes(bytes: u64) -> Size { - Size { raw: bytes } + pub fn from_bytes(bytes: impl TryInto<u64>) -> Size { + Size { raw: bytes.try_into().ok().unwrap() } } #[inline] @@ -259,6 +261,11 @@ impl Size { } #[inline] + pub fn bytes_usize(self) -> usize { + self.bytes().try_into().unwrap() + } + + #[inline] pub fn bits(self) -> u64 { self.bytes().checked_mul(8).unwrap_or_else(|| { panic!("Size::bits: {} bytes in bits doesn't fit in u64", self.bytes()) @@ -266,6 +273,11 @@ impl Size { } #[inline] + pub fn bits_usize(self) -> usize { + self.bits().try_into().unwrap() + } + + #[inline] pub fn align_to(self, align: Align) -> Size { let mask = align.bytes() - 1; Size::from_bytes((self.bytes() + mask) & !mask) @@ -401,7 +413,7 @@ impl Align { } } -/// A pair of aligments, ABI-mandated and preferred. +/// A pair of alignments, ABI-mandated and preferred. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] #[derive(HashStable_Generic)] pub struct AbiAndPrefAlign { @@ -565,7 +577,7 @@ pub struct Scalar { pub value: Primitive, /// Inclusive wrap-around range of valid values, that is, if - /// start > end, it represents `start..=max_value()`, + /// start > end, it represents `start..=MAX`, /// followed by `0..=end`. /// /// That is, for an i8 primitive, a range of `254..=2` means following @@ -606,7 +618,7 @@ impl Scalar { /// Describes how the fields of a type are located in memory. #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] -pub enum FieldPlacement { +pub enum FieldsShape { /// All fields start at no offset. The `usize` is the field count. /// /// In the case of primitives the number of fields is `0`. @@ -645,35 +657,38 @@ pub enum FieldPlacement { }, } -impl FieldPlacement { +impl FieldsShape { pub fn count(&self) -> usize { match *self { - FieldPlacement::Union(count) => count, - FieldPlacement::Array { count, .. } => { + FieldsShape::Union(count) => count, + FieldsShape::Array { count, .. } => { let usize_count = count as usize; assert_eq!(usize_count as u64, count); usize_count } - FieldPlacement::Arbitrary { ref offsets, .. } => offsets.len(), + FieldsShape::Arbitrary { ref offsets, .. } => offsets.len(), } } pub fn offset(&self, i: usize) -> Size { match *self { - FieldPlacement::Union(_) => Size::ZERO, - FieldPlacement::Array { stride, count } => { - let i = i as u64; + FieldsShape::Union(count) => { + assert!(i < count, "tried to access field {} of union with {} fields", i, count); + Size::ZERO + } + FieldsShape::Array { stride, count } => { + let i = u64::try_from(i).unwrap(); assert!(i < count); stride * i } - FieldPlacement::Arbitrary { ref offsets, .. } => offsets[i], + FieldsShape::Arbitrary { ref offsets, .. } => offsets[i], } } pub fn memory_index(&self, i: usize) -> usize { match *self { - FieldPlacement::Union(_) | FieldPlacement::Array { .. } => i, - FieldPlacement::Arbitrary { ref memory_index, .. } => { + FieldsShape::Union(_) | FieldsShape::Array { .. } => i, + FieldsShape::Arbitrary { ref memory_index, .. } => { let r = memory_index[i]; assert_eq!(r as usize as u32, r); r as usize @@ -689,7 +704,7 @@ impl FieldPlacement { let use_small = self.count() <= inverse_small.len(); // We have to write this logic twice in order to keep the array small. - if let FieldPlacement::Arbitrary { ref memory_index, .. } = *self { + if let FieldsShape::Arbitrary { ref memory_index, .. } = *self { if use_small { for i in 0..self.count() { inverse_small[memory_index[i] as usize] = i as u8; @@ -703,8 +718,8 @@ impl FieldPlacement { } (0..self.count()).map(move |i| match *self { - FieldPlacement::Union(_) | FieldPlacement::Array { .. } => i, - FieldPlacement::Arbitrary { .. } => { + FieldsShape::Union(_) | FieldsShape::Array { .. } => i, + FieldsShape::Arbitrary { .. } => { if use_small { inverse_small[i] as usize } else { @@ -748,7 +763,7 @@ impl Abi { Primitive::Int(_, signed) => signed, _ => false, }, - _ => false, + _ => panic!("`is_signed` on non-scalar ABI {:?}", self), } } @@ -787,7 +802,7 @@ pub enum Variants { discr: Scalar, discr_kind: DiscriminantKind, discr_index: usize, - variants: IndexVec<VariantIdx, LayoutDetails>, + variants: IndexVec<VariantIdx, Layout>, }, } @@ -870,10 +885,10 @@ impl Niche { } #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] -pub struct LayoutDetails { +pub struct Layout { /// Says where the fields are located within the layout. - /// Primitives and fieldless enums appear as unions without fields. - pub fields: FieldPlacement, + /// Primitives and uninhabited enums appear as unions without fields. + pub fields: FieldsShape, /// Encodes information about multi-variant layouts. /// Even with `Multiple` variants, a layout still has its own fields! Those are then @@ -901,14 +916,14 @@ pub struct LayoutDetails { pub size: Size, } -impl LayoutDetails { +impl Layout { pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self { let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar.clone()); let size = scalar.value.size(cx); let align = scalar.value.align(cx); - LayoutDetails { + Layout { variants: Variants::Single { index: VariantIdx::new(0) }, - fields: FieldPlacement::Union(0), + fields: FieldsShape::Union(0), abi: Abi::Scalar(scalar), largest_niche, size, @@ -917,36 +932,69 @@ impl LayoutDetails { } } -/// The details of the layout of a type, alongside the type itself. +/// The layout of a type, alongside the type itself. /// Provides various type traversal APIs (e.g., recursing into fields). /// -/// Note that the details are NOT guaranteed to always be identical -/// to those obtained from `layout_of(ty)`, as we need to produce +/// Note that the layout is NOT guaranteed to always be identical +/// to that obtained from `layout_of(ty)`, as we need to produce /// layouts for which Rust types do not exist, such as enum variants /// or synthetic fields of enums (i.e., discriminants) and fat pointers. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub struct TyLayout<'a, Ty> { +pub struct TyAndLayout<'a, Ty> { pub ty: Ty, - pub details: &'a LayoutDetails, + pub layout: &'a Layout, } -impl<'a, Ty> Deref for TyLayout<'a, Ty> { - type Target = &'a LayoutDetails; - fn deref(&self) -> &&'a LayoutDetails { - &self.details +impl<'a, Ty> Deref for TyAndLayout<'a, Ty> { + type Target = &'a Layout; + fn deref(&self) -> &&'a Layout { + &self.layout } } +/// Trait for context types that can compute layouts of things. pub trait LayoutOf { type Ty; - type TyLayout; + type TyAndLayout; - fn layout_of(&self, ty: Self::Ty) -> Self::TyLayout; - fn spanned_layout_of(&self, ty: Self::Ty, _span: Span) -> Self::TyLayout { + fn layout_of(&self, ty: Self::Ty) -> Self::TyAndLayout; + fn spanned_layout_of(&self, ty: Self::Ty, _span: Span) -> Self::TyAndLayout { self.layout_of(ty) } } +/// The `TyAndLayout` above will always be a `MaybeResult<TyAndLayout<'_, Self>>`. +/// We can't add the bound due to the lifetime, but this trait is still useful when +/// writing code that's generic over the `LayoutOf` impl. +pub trait MaybeResult<T> { + type Error; + + fn from(x: Result<T, Self::Error>) -> Self; + fn to_result(self) -> Result<T, Self::Error>; +} + +impl<T> MaybeResult<T> for T { + type Error = !; + + fn from(Ok(x): Result<T, Self::Error>) -> Self { + x + } + fn to_result(self) -> Result<T, Self::Error> { + Ok(self) + } +} + +impl<T, E> MaybeResult<T> for Result<T, E> { + type Error = E; + + fn from(x: Result<T, Self::Error>) -> Self { + x + } + fn to_result(self) -> Result<T, Self::Error> { + self + } +} + #[derive(Copy, Clone, PartialEq, Eq)] pub enum PointerKind { /// Most general case, we know no restrictions to tell LLVM. @@ -969,41 +1017,45 @@ pub struct PointeeInfo { pub safe: Option<PointerKind>, } -pub trait TyLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized { +pub trait TyAndLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized { fn for_variant( - this: TyLayout<'a, Self>, + this: TyAndLayout<'a, Self>, cx: &C, variant_index: VariantIdx, - ) -> TyLayout<'a, Self>; - fn field(this: TyLayout<'a, Self>, cx: &C, i: usize) -> C::TyLayout; - fn pointee_info_at(this: TyLayout<'a, Self>, cx: &C, offset: Size) -> Option<PointeeInfo>; + ) -> TyAndLayout<'a, Self>; + fn field(this: TyAndLayout<'a, Self>, cx: &C, i: usize) -> C::TyAndLayout; + fn pointee_info_at(this: TyAndLayout<'a, Self>, cx: &C, offset: Size) -> Option<PointeeInfo>; } -impl<'a, Ty> TyLayout<'a, Ty> { +impl<'a, Ty> TyAndLayout<'a, Ty> { pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self where - Ty: TyLayoutMethods<'a, C>, + Ty: TyAndLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty>, { Ty::for_variant(self, cx, variant_index) } - pub fn field<C>(self, cx: &C, i: usize) -> C::TyLayout + + /// Callers might want to use `C: LayoutOf<Ty=Ty, TyAndLayout: MaybeResult<Self>>` + /// to allow recursion (see `might_permit_zero_init` below for an example). + pub fn field<C>(self, cx: &C, i: usize) -> C::TyAndLayout where - Ty: TyLayoutMethods<'a, C>, + Ty: TyAndLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty>, { Ty::field(self, cx, i) } + pub fn pointee_info_at<C>(self, cx: &C, offset: Size) -> Option<PointeeInfo> where - Ty: TyLayoutMethods<'a, C>, + Ty: TyAndLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty>, { Ty::pointee_info_at(self, cx, offset) } } -impl<'a, Ty> TyLayout<'a, Ty> { +impl<'a, Ty> TyAndLayout<'a, Ty> { /// Returns `true` if the layout corresponds to an unsized type. pub fn is_unsized(&self) -> bool { self.abi.is_unsized() @@ -1017,4 +1069,52 @@ impl<'a, Ty> TyLayout<'a, Ty> { Abi::Aggregate { sized } => sized && self.size.bytes() == 0, } } + + /// Determines if this type permits "raw" initialization by just transmuting some + /// memory into an instance of `T`. + /// `zero` indicates if the memory is zero-initialized, or alternatively + /// left entirely uninitialized. + /// This is conservative: in doubt, it will answer `true`. + /// + /// FIXME: Once we removed all the conservatism, we could alternatively + /// create an all-0/all-undef constant and run the const value validator to see if + /// this is a valid value for the given type. + pub fn might_permit_raw_init<C, E>(self, cx: &C, zero: bool) -> Result<bool, E> + where + Self: Copy, + Ty: TyAndLayoutMethods<'a, C>, + C: LayoutOf<Ty = Ty, TyAndLayout: MaybeResult<Self, Error = E>> + HasDataLayout, + { + let scalar_allows_raw_init = move |s: &Scalar| -> bool { + if zero { + let range = &s.valid_range; + // The range must contain 0. + range.contains(&0) || (*range.start() > *range.end()) // wrap-around allows 0 + } else { + // The range must include all values. `valid_range_exclusive` handles + // the wrap-around using target arithmetic; with wrap-around then the full + // range is one where `start == end`. + let range = s.valid_range_exclusive(cx); + range.start == range.end + } + }; + + // Check the ABI. + let valid = match &self.abi { + Abi::Uninhabited => false, // definitely UB + Abi::Scalar(s) => scalar_allows_raw_init(s), + Abi::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2), + Abi::Vector { element: s, count } => *count == 0 || scalar_allows_raw_init(s), + Abi::Aggregate { .. } => true, // Cannot be excluded *right now*. + }; + if !valid { + // This is definitely not okay. + trace!("might_permit_raw_init({:?}, zero={}): not valid", self.layout, zero); + return Ok(false); + } + + // If we have not found an error yet, we need to recursively descend. + // FIXME(#66151): For now, we are conservative and do not do this. + Ok(true) + } } diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index 71150e74f70..b2965fb8806 100644 --- a/src/librustc_target/lib.rs +++ b/src/librustc_target/lib.rs @@ -9,7 +9,13 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(bool_to_option)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(nll)] +#![feature(never_type)] +#![feature(associated_type_bounds)] +#![feature(exhaustive_patterns)] #[macro_use] extern crate log; @@ -19,5 +25,5 @@ pub mod spec; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro -/// instead of implementing everything in librustc. +/// instead of implementing everything in librustc_middle. pub trait HashStableContext {} diff --git a/src/librustc_target/spec/aarch64_apple_ios.rs b/src/librustc_target/spec/aarch64_apple_ios.rs index 6549be41ea9..e896b46da9a 100644 --- a/src/librustc_target/spec/aarch64_apple_ios.rs +++ b/src/librustc_target/spec/aarch64_apple_ios.rs @@ -1,8 +1,8 @@ -use super::apple_ios_base::{opts, Arch}; +use super::apple_sdk_base::{opts, AppleOS, Arch}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { - let base = opts(Arch::Arm64)?; + let base = opts(Arch::Arm64, AppleOS::iOS)?; Ok(Target { llvm_target: "arm64-apple-ios".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/aarch64_apple_tvos.rs b/src/librustc_target/spec/aarch64_apple_tvos.rs new file mode 100644 index 00000000000..794bc7900e7 --- /dev/null +++ b/src/librustc_target/spec/aarch64_apple_tvos.rs @@ -0,0 +1,25 @@ +use super::apple_sdk_base::{opts, AppleOS, Arch}; +use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + let base = opts(Arch::Arm64, AppleOS::tvOS)?; + Ok(Target { + llvm_target: "arm64-apple-tvos".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(), + arch: "aarch64".to_string(), + target_os: "tvos".to_string(), + target_env: String::new(), + target_vendor: "apple".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: TargetOptions { + features: "+neon,+fp-armv8,+cyclone".to_string(), + eliminate_frame_pointer: false, + max_atomic_width: Some(128), + abi_blacklist: super::arm_base::abi_blacklist(), + ..base + }, + }) +} diff --git a/src/librustc_target/spec/abi.rs b/src/librustc_target/spec/abi.rs index ac4c561402b..1736063cc5f 100644 --- a/src/librustc_target/spec/abi.rs +++ b/src/librustc_target/spec/abi.rs @@ -5,19 +5,8 @@ use rustc_macros::HashStable_Generic; #[cfg(test)] mod tests; -#[derive( - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - RustcEncodable, - RustcDecodable, - Clone, - Copy, - Debug, - HashStable_Generic -)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Clone, Copy, Debug)] +#[derive(HashStable_Generic)] pub enum Abi { // N.B., this ordering MUST match the AbiDatas array below. // (This is ensured by the test indices_are_correct().) diff --git a/src/librustc_target/spec/apple_base.rs b/src/librustc_target/spec/apple_base.rs index d116ddf952a..4ad65569e6a 100644 --- a/src/librustc_target/spec/apple_base.rs +++ b/src/librustc_target/spec/apple_base.rs @@ -57,7 +57,7 @@ pub fn macos_link_env_remove() -> Vec<String> { let mut env_remove = Vec::with_capacity(2); // Remove the `SDKROOT` environment variable if it's clearly set for the wrong platform, which // may occur when we're linking a custom build script while targeting iOS for example. - if let Some(sdkroot) = env::var("SDKROOT").ok() { + if let Ok(sdkroot) = env::var("SDKROOT") { if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform") { env_remove.push("SDKROOT".to_string()) } diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_sdk_base.rs index 2673748321d..c7cff17b154 100644 --- a/src/librustc_target/spec/apple_ios_base.rs +++ b/src/librustc_target/spec/apple_sdk_base.rs @@ -5,7 +5,6 @@ use std::path::Path; use std::process::Command; use Arch::*; - #[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub enum Arch { @@ -17,6 +16,13 @@ pub enum Arch { X86_64_macabi, } +#[allow(non_camel_case_types)] +#[derive(Copy, Clone)] +pub enum AppleOS { + tvOS, + iOS, +} + impl Arch { pub fn to_string(self) -> &'static str { match self { @@ -37,29 +43,26 @@ pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> { // to allow the SDK path to be set. (For clang, xcrun sets // SDKROOT; for rustc, the user or build system can set it, or we // can fall back to checking for xcrun on PATH.) - if let Some(sdkroot) = env::var("SDKROOT").ok() { + if let Ok(sdkroot) = env::var("SDKROOT") { let p = Path::new(&sdkroot); match sdk_name { // Ignore `SDKROOT` if it's clearly set for the wrong platform. + "appletvos" + if sdkroot.contains("TVSimulator.platform") + || sdkroot.contains("MacOSX.platform") => {} + "appletvsimulator" + if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") => {} "iphoneos" if sdkroot.contains("iPhoneSimulator.platform") - || sdkroot.contains("MacOSX.platform") => - { - () - } + || sdkroot.contains("MacOSX.platform") => {} "iphonesimulator" - if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("MacOSX.platform") => - { - () + if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("MacOSX.platform") => { } "macosx10.15" if sdkroot.contains("iPhoneOS.platform") - || sdkroot.contains("iPhoneSimulator.platform") => - { - () - } + || sdkroot.contains("iPhoneSimulator.platform") => {} // Ignore `SDKROOT` if it's not a valid path. - _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => (), + _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {} _ => return Ok(sdkroot), } } @@ -82,11 +85,17 @@ pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> { } } -fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> { - let sdk_name = match arch { - Armv7 | Armv7s | Arm64 => "iphoneos", - I386 | X86_64 => "iphonesimulator", - X86_64_macabi => "macosx10.15", +fn build_pre_link_args(arch: Arch, os: AppleOS) -> Result<LinkArgs, String> { + let sdk_name = match (arch, os) { + (Arm64, AppleOS::tvOS) => "appletvos", + (X86_64, AppleOS::tvOS) => "appletvsimulator", + (Armv7, AppleOS::iOS) => "iphoneos", + (Armv7s, AppleOS::iOS) => "iphoneos", + (Arm64, AppleOS::iOS) => "iphoneos", + (I386, AppleOS::iOS) => "iphonesimulator", + (X86_64, AppleOS::iOS) => "iphonesimulator", + (X86_64_macabi, AppleOS::iOS) => "macosx10.15", + _ => unreachable!(), }; let arch_name = arch.to_string(); @@ -128,8 +137,8 @@ fn link_env_remove(arch: Arch) -> Vec<String> { } } -pub fn opts(arch: Arch) -> Result<TargetOptions, String> { - let pre_link_args = build_pre_link_args(arch)?; +pub fn opts(arch: Arch, os: AppleOS) -> Result<TargetOptions, String> { + let pre_link_args = build_pre_link_args(arch, os)?; Ok(TargetOptions { cpu: target_cpu(arch), dynamic_linking: false, diff --git a/src/librustc_target/spec/armv7_apple_ios.rs b/src/librustc_target/spec/armv7_apple_ios.rs index aa2d32e2d79..c0c2ae909f8 100644 --- a/src/librustc_target/spec/armv7_apple_ios.rs +++ b/src/librustc_target/spec/armv7_apple_ios.rs @@ -1,8 +1,8 @@ -use super::apple_ios_base::{opts, Arch}; +use super::apple_sdk_base::{opts, AppleOS, Arch}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { - let base = opts(Arch::Armv7)?; + let base = opts(Arch::Armv7, AppleOS::iOS)?; Ok(Target { llvm_target: "armv7-apple-ios".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/armv7s_apple_ios.rs b/src/librustc_target/spec/armv7s_apple_ios.rs index 6514643a64d..6a5654f10d4 100644 --- a/src/librustc_target/spec/armv7s_apple_ios.rs +++ b/src/librustc_target/spec/armv7s_apple_ios.rs @@ -1,8 +1,8 @@ -use super::apple_ios_base::{opts, Arch}; +use super::apple_sdk_base::{opts, AppleOS, Arch}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { - let base = opts(Arch::Armv7s)?; + let base = opts(Arch::Armv7s, AppleOS::iOS)?; Ok(Target { llvm_target: "armv7s-apple-ios".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/i386_apple_ios.rs b/src/librustc_target/spec/i386_apple_ios.rs index a6c1d24fa62..a121d49769d 100644 --- a/src/librustc_target/spec/i386_apple_ios.rs +++ b/src/librustc_target/spec/i386_apple_ios.rs @@ -1,8 +1,8 @@ -use super::apple_ios_base::{opts, Arch}; +use super::apple_sdk_base::{opts, AppleOS, Arch}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { - let base = opts(Arch::I386)?; + let base = opts(Arch::I386, AppleOS::iOS)?; Ok(Target { llvm_target: "i386-apple-ios".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/i686_apple_darwin.rs b/src/librustc_target/spec/i686_apple_darwin.rs index 033b87b110e..b7a34f9740a 100644 --- a/src/librustc_target/spec/i686_apple_darwin.rs +++ b/src/librustc_target/spec/i686_apple_darwin.rs @@ -16,7 +16,7 @@ pub fn target() -> TargetResult { let llvm_target = super::apple_base::macos_llvm_target(&arch); Ok(Target { - llvm_target: llvm_target, + llvm_target, target_endian: "little".to_string(), target_pointer_width: "32".to_string(), target_c_int_width: "32".to_string(), diff --git a/src/librustc_target/spec/i686_unknown_uefi.rs b/src/librustc_target/spec/i686_unknown_uefi.rs index 345590a00be..e299f92fdeb 100644 --- a/src/librustc_target/spec/i686_unknown_uefi.rs +++ b/src/librustc_target/spec/i686_unknown_uefi.rs @@ -29,7 +29,7 @@ pub fn target() -> TargetResult { base.abi_return_struct_as_int = true; // Use -GNU here, because of the reason below: - // Backgound and Problem: + // Background and Problem: // If we use i686-unknown-windows, the LLVM IA32 MSVC generates compiler intrinsic // _alldiv, _aulldiv, _allrem, _aullrem, _allmul, which will cause undefined symbol. // A real issue is __aulldiv() is referred by __udivdi3() - udivmod_inner!(), from @@ -64,7 +64,7 @@ pub fn target() -> TargetResult { // i386/umoddi3.S // Possible solution: // 1. Eliminate Intrinsics generation. - // 1.1 Choose differnt target to bypass isTargetKnownWindowsMSVC(). + // 1.1 Choose different target to bypass isTargetKnownWindowsMSVC(). // 1.2 Remove the "Setup Windows compiler runtime calls" in LLVM // 2. Implement Intrinsics. // We evaluated all options. diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 67f45d3d230..1bc2bf12fad 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -47,7 +47,7 @@ use rustc_macros::HashStable_Generic; pub mod abi; mod android_base; mod apple_base; -mod apple_ios_base; +mod apple_sdk_base; mod arm_base; mod cloudabi_base; mod dragonfly_base; @@ -434,6 +434,8 @@ supported_targets! { ("armv7-apple-ios", armv7_apple_ios), ("armv7s-apple-ios", armv7s_apple_ios), ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi), + ("aarch64-apple-tvos", aarch64_apple_tvos), + ("x86_64-apple-tvos", x86_64_apple_tvos), ("armebv7r-none-eabi", armebv7r_none_eabi), ("armebv7r-none-eabihf", armebv7r_none_eabihf), @@ -579,6 +581,12 @@ pub struct TargetOptions { /// user-defined but before post_link_objects. Standard platform /// libraries that should be always be linked to, usually go here. pub late_link_args: LinkArgs, + /// Linker arguments used in addition to `late_link_args` if at least one + /// Rust dependency is dynamically linked. + pub late_link_args_dynamic: LinkArgs, + /// Linker arguments used in addition to `late_link_args` if aall Rust + /// dependencies are statically linked. + pub late_link_args_static: LinkArgs, /// Objects to link after all others, always found within the /// sysroot folder. pub post_link_objects: Vec<String>, // ... unconditionally @@ -692,11 +700,6 @@ pub struct TargetOptions { pub archive_format: String, /// Is asm!() allowed? Defaults to true. pub allow_asm: bool, - /// Whether the target uses a custom unwind resumption routine. - /// By default LLVM lowers `resume` instructions into calls to `_Unwind_Resume` - /// defined in libgcc. If this option is enabled, the target must provide - /// `eh_unwind_resume` lang item. - pub custom_unwind_resume: bool, /// Whether the runtime startup code requires the `main` function be passed /// `argc` and `argv` values. pub main_needs_argc_argv: bool, @@ -709,11 +712,6 @@ pub struct TargetOptions { // will 'just work'. pub obj_is_bitcode: bool, - // LLVM can't produce object files for this target. Instead, we'll make LLVM - // emit assembly and then use `gcc` to turn that assembly into an object - // file - pub no_integrated_as: bool, - /// Don't use this field; instead use the `.min_atomic_width()` method. pub min_atomic_width: Option<u64>, @@ -768,9 +766,6 @@ pub struct TargetOptions { /// rather than "default" pub default_hidden_visibility: bool, - /// Whether or not bitcode is embedded in object files - pub embed_bitcode: bool, - /// Whether a .debug_gdb_scripts section will be added to the output object file pub emit_debug_gdb_scripts: bool, @@ -863,15 +858,15 @@ impl Default for TargetOptions { post_link_objects: Vec::new(), post_link_objects_crt: Vec::new(), late_link_args: LinkArgs::new(), + late_link_args_dynamic: LinkArgs::new(), + late_link_args_static: LinkArgs::new(), link_env: Vec::new(), link_env_remove: Vec::new(), archive_format: "gnu".to_string(), - custom_unwind_resume: false, main_needs_argc_argv: true, allow_asm: true, has_elf_tls: false, obj_is_bitcode: false, - no_integrated_as: false, min_atomic_width: None, max_atomic_width: None, atomic_cas: true, @@ -889,7 +884,6 @@ impl Default for TargetOptions { no_builtins: false, codegen_backend: "llvm".to_string(), default_hidden_visibility: false, - embed_bitcode: false, emit_debug_gdb_scripts: true, requires_uwtable: false, simd_types_indirect: true, @@ -1142,6 +1136,8 @@ impl Target { key!(pre_link_objects_exe_crt, list); key!(pre_link_objects_dll, list); key!(late_link_args, link_args); + key!(late_link_args_dynamic, link_args); + key!(late_link_args_static, link_args); key!(post_link_objects, list); key!(post_link_objects_crt, list); key!(post_link_args, link_args); @@ -1182,11 +1178,9 @@ impl Target { key!(relro_level, RelroLevel)?; key!(archive_format); key!(allow_asm, bool); - key!(custom_unwind_resume, bool); key!(main_needs_argc_argv, bool); key!(has_elf_tls, bool); key!(obj_is_bitcode, bool); - key!(no_integrated_as, bool); key!(max_atomic_width, Option<u64>); key!(min_atomic_width, Option<u64>); key!(atomic_cas, bool); @@ -1203,7 +1197,6 @@ impl Target { key!(no_builtins, bool); key!(codegen_backend); key!(default_hidden_visibility, bool); - key!(embed_bitcode, bool); key!(emit_debug_gdb_scripts, bool); key!(requires_uwtable, bool); key!(simd_types_indirect, bool); @@ -1370,6 +1363,8 @@ impl ToJson for Target { target_option_val!(pre_link_objects_exe_crt); target_option_val!(pre_link_objects_dll); target_option_val!(link_args - late_link_args); + target_option_val!(link_args - late_link_args_dynamic); + target_option_val!(link_args - late_link_args_static); target_option_val!(post_link_objects); target_option_val!(post_link_objects_crt); target_option_val!(link_args - post_link_args); @@ -1410,11 +1405,9 @@ impl ToJson for Target { target_option_val!(relro_level); target_option_val!(archive_format); target_option_val!(allow_asm); - target_option_val!(custom_unwind_resume); target_option_val!(main_needs_argc_argv); target_option_val!(has_elf_tls); target_option_val!(obj_is_bitcode); - target_option_val!(no_integrated_as); target_option_val!(min_atomic_width); target_option_val!(max_atomic_width); target_option_val!(atomic_cas); @@ -1431,7 +1424,6 @@ impl ToJson for Target { target_option_val!(no_builtins); target_option_val!(codegen_backend); target_option_val!(default_hidden_visibility); - target_option_val!(embed_bitcode); target_option_val!(emit_debug_gdb_scripts); target_option_val!(requires_uwtable); target_option_val!(simd_types_indirect); diff --git a/src/librustc_target/spec/msp430_none_elf.rs b/src/librustc_target/spec/msp430_none_elf.rs index e05a18e76d2..9a90ac7ccec 100644 --- a/src/librustc_target/spec/msp430_none_elf.rs +++ b/src/librustc_target/spec/msp430_none_elf.rs @@ -22,7 +22,6 @@ pub fn target() -> TargetResult { // dependency on this specific gcc. asm_args: vec!["-mcpu=msp430".to_string()], linker: Some("msp430-elf-gcc".to_string()), - no_integrated_as: true, // There are no atomic CAS instructions available in the MSP430 // instruction set, and the LLVM backend doesn't currently support diff --git a/src/librustc_target/spec/nvptx64_nvidia_cuda.rs b/src/librustc_target/spec/nvptx64_nvidia_cuda.rs index f070a3e5da4..e0a402533e7 100644 --- a/src/librustc_target/spec/nvptx64_nvidia_cuda.rs +++ b/src/librustc_target/spec/nvptx64_nvidia_cuda.rs @@ -23,7 +23,7 @@ pub fn target() -> TargetResult { // The linker can be installed from `crates.io`. linker: Some("rust-ptx-linker".to_string()), - // With `ptx-linker` approach, it can be later overriden via link flags. + // With `ptx-linker` approach, it can be later overridden via link flags. cpu: "sm_30".to_string(), // FIXME: create tests for the atomics. @@ -43,7 +43,7 @@ pub fn target() -> TargetResult { // Let the `ptx-linker` to handle LLVM lowering into MC / assembly. obj_is_bitcode: true, - // Convinient and predicable naming scheme. + // Convenient and predicable naming scheme. dll_prefix: "".to_string(), dll_suffix: ".ptx".to_string(), exe_suffix: ".ptx".to_string(), diff --git a/src/librustc_target/spec/windows_base.rs b/src/librustc_target/spec/windows_base.rs index 693a343d5a5..5f59ca8a5a3 100644 --- a/src/librustc_target/spec/windows_base.rs +++ b/src/librustc_target/spec/windows_base.rs @@ -17,12 +17,13 @@ pub fn opts() -> TargetOptions { ); let mut late_link_args = LinkArgs::new(); + let mut late_link_args_dynamic = LinkArgs::new(); + let mut late_link_args_static = LinkArgs::new(); late_link_args.insert( LinkerFlavor::Gcc, vec![ "-lmingwex".to_string(), "-lmingw32".to_string(), - "-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc "-lmsvcrt".to_string(), // mingw's msvcrt is a weird hybrid import library and static library. // And it seems that the linker fails to use import symbols from msvcrt @@ -37,6 +38,33 @@ pub fn opts() -> TargetOptions { "-lkernel32".to_string(), ], ); + late_link_args_dynamic.insert( + LinkerFlavor::Gcc, + vec![ + // If any of our crates are dynamically linked then we need to use + // the shared libgcc_s-dw2-1.dll. This is required to support + // unwinding across DLL boundaries. + "-lgcc_s".to_string(), + "-lgcc".to_string(), + "-lkernel32".to_string(), + ], + ); + late_link_args_static.insert( + LinkerFlavor::Gcc, + vec![ + // If all of our crates are statically linked then we can get away + // with statically linking the libgcc unwinding code. This allows + // binaries to be redistributed without the libgcc_s-dw2-1.dll + // dependency, but unfortunately break unwinding across DLL + // boundaries when unwinding across FFI boundaries. + "-lgcc".to_string(), + "-lgcc_eh".to_string(), + "-lpthread".to_string(), + // libpthread depends on libmsvcrt, so we need to link it *again*. + "-lmsvcrt".to_string(), + "-lkernel32".to_string(), + ], + ); TargetOptions { // FIXME(#13846) this should be enabled for windows @@ -63,8 +91,9 @@ pub fn opts() -> TargetOptions { "rsbegin.o".to_string(), ], late_link_args, + late_link_args_dynamic, + late_link_args_static, post_link_objects: vec!["rsend.o".to_string()], - custom_unwind_resume: true, abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, requires_uwtable: true, diff --git a/src/librustc_target/spec/windows_uwp_base.rs b/src/librustc_target/spec/windows_uwp_base.rs index b19c4dd7eb1..3f7eb442bbc 100644 --- a/src/librustc_target/spec/windows_uwp_base.rs +++ b/src/librustc_target/spec/windows_uwp_base.rs @@ -54,7 +54,6 @@ pub fn opts() -> TargetOptions { pre_link_objects_dll: vec!["rsbegin.o".to_string()], late_link_args, post_link_objects: vec!["rsend.o".to_string()], - custom_unwind_resume: true, abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, requires_uwtable: true, diff --git a/src/librustc_target/spec/x86_64_apple_darwin.rs b/src/librustc_target/spec/x86_64_apple_darwin.rs index e846f42f8f8..31011e84749 100644 --- a/src/librustc_target/spec/x86_64_apple_darwin.rs +++ b/src/librustc_target/spec/x86_64_apple_darwin.rs @@ -16,7 +16,7 @@ pub fn target() -> TargetResult { let llvm_target = super::apple_base::macos_llvm_target(&arch); Ok(Target { - llvm_target: llvm_target, + llvm_target, target_endian: "little".to_string(), target_pointer_width: "64".to_string(), target_c_int_width: "32".to_string(), diff --git a/src/librustc_target/spec/x86_64_apple_ios.rs b/src/librustc_target/spec/x86_64_apple_ios.rs index ca02e2deabc..cfcf856836b 100644 --- a/src/librustc_target/spec/x86_64_apple_ios.rs +++ b/src/librustc_target/spec/x86_64_apple_ios.rs @@ -1,8 +1,8 @@ -use super::apple_ios_base::{opts, Arch}; +use super::apple_sdk_base::{opts, AppleOS, Arch}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { - let base = opts(Arch::X86_64)?; + let base = opts(Arch::X86_64, AppleOS::iOS)?; Ok(Target { llvm_target: "x86_64-apple-ios".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/x86_64_apple_ios_macabi.rs b/src/librustc_target/spec/x86_64_apple_ios_macabi.rs index 5f4f6ade682..c42d0911725 100644 --- a/src/librustc_target/spec/x86_64_apple_ios_macabi.rs +++ b/src/librustc_target/spec/x86_64_apple_ios_macabi.rs @@ -1,8 +1,8 @@ -use super::apple_ios_base::{opts, Arch}; +use super::apple_sdk_base::{opts, AppleOS, Arch}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { - let base = opts(Arch::X86_64_macabi)?; + let base = opts(Arch::X86_64_macabi, AppleOS::iOS)?; Ok(Target { llvm_target: "x86_64-apple-ios13.0-macabi".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/x86_64_apple_tvos.rs b/src/librustc_target/spec/x86_64_apple_tvos.rs new file mode 100644 index 00000000000..a56062c0b2b --- /dev/null +++ b/src/librustc_target/spec/x86_64_apple_tvos.rs @@ -0,0 +1,19 @@ +use super::apple_sdk_base::{opts, AppleOS, Arch}; +use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + let base = opts(Arch::X86_64, AppleOS::iOS)?; + Ok(Target { + llvm_target: "x86_64-apple-tvos".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(), + arch: "x86_64".to_string(), + target_os: "tvos".to_string(), + target_env: String::new(), + target_vendor: "apple".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: TargetOptions { max_atomic_width: Some(64), stack_probes: true, ..base }, + }) +} |
